Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assignment inside format_args! is ignored #45256

Closed
nikolads opened this issue Oct 13, 2017 · 8 comments
Closed

Assignment inside format_args! is ignored #45256

nikolads opened this issue Oct 13, 2017 · 8 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@nikolads
Copy link

Assignments inside format_args! are ignored. Instead only the right-hand side of the expression is used.

I tried this code:

fn main() {
    let mut x = 1;
    println!("first: {}", x = 3);
    println!("second: {}", x);
}

or a similar one, using directly format_args:

use std::io::{self, Write};

fn main() {
    let mut x = 1; 
    io::stdout().write_fmt(format_args!("first: {}\n", x = 3));
    io::stdout().write_fmt(format_args!("second: {}\n", x));
}

I expected to see this:

first: ()
second: 3

Instead the output was:

first: 3
second: 1

It looks like the the assignment x = 3 is ignored and is instead treated as if it was just 3.
I could only replicate this with format_args! and macros that use it. Other macros, like assert_eq!, work as expected.

Meta

rustc --version --verbose:

rustc 1.22.0-nightly (dcbbfb6e8 2017-10-12)
binary: rustc
commit-hash: dcbbfb6e807fdff9c9ba80073bb755f9d9d95e31
commit-date: 2017-10-12
host: x86_64-unknown-linux-gnu
release: 1.22.0-nightly
LLVM version: 4.0

(also tried on rustc 1.20.0-stable and rustc 1.21.0-stable)

@kennytm kennytm added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 13, 2017
@sinkuu
Copy link
Contributor

sinkuu commented Oct 13, 2017

format_args supports named arguments with name = value syntax. Assignments can be written as {x = 3} so that they won't be treated as named argument.

What's odd is that {} formats arguments just in the sequence of arguments, ignoring if they are named or positional. Is this intended behavior?

println!("{x} {} {} {}", 1, x = 2, y= 3);
// => 2 1 2 3

@kennytm
Copy link
Member

kennytm commented Oct 13, 2017

The x = 3 is not parsed as assignment, but named parameters.

The bug here is that println!("first: {}", x = 3); should not compile since parameter 0 is missing.

@nagisa nagisa added I-nominated T-lang Relevant to the language team, which will review and decide on the PR/issue. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 13, 2017
@nagisa
Copy link
Member

nagisa commented Oct 13, 2017

What @kennytm and @sinku said is correct, but I’m not sure it (the behaviour of how named arguments are considered in context of positional arguments) can be considered a bug anymore. At least I can easily see somebody using this, intentionally or not, even if it wasn’t documented to have specifically this behaviour. Therefore nominating it for T-lang (since format_args! is a part of language) to decide what the intended behaviour is.

@ollie27
Copy link
Member

ollie27 commented Oct 13, 2017

From Positional parameters:

Each formatting argument is allowed to specify which value argument it's referencing, and if omitted it is assumed to be "the next argument".

Which suggests this is working as intended.

If anything I'd say there should be a warning if you name a parameter but never reference it by its name.

@sinkuu
Copy link
Contributor

sinkuu commented Oct 13, 2017

@ollie27 Isn't that talking only about positional parameters?

The behavior in question have been introduced in Rust 1.12. I speculate that #33642 (which seems to have added internal translation of named args into positional args) unintentionally did it.

Example:

fn main() {
    println!("{}", x = 1);
}

Rust 1.11.0:

<std macros>:3:11: 3:36 error: invalid reference to argument `0` (no arguments given)
<std macros>:3 print ! ( concat ! ( $ fmt , "\n" ) , $ ( $ arg ) * ) ) ;
                         ^~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:3:11: 3:36 note: in this expansion of concat!
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
test.rs:2:5: 2:27 note: in this expansion of println! (defined in <std macros>)
test.rs:2:24: 2:25 error: named argument never used
test.rs:2     println!("{}", x = 1);
                                 ^
error: aborting due to 2 previous errors

Rust 1.12.0

(compiles fine, and the program prints "1")

@joshtriplett
Copy link
Member

Consensus in the lang team meeting is that we should reintroduce a lint for "named argument never used". And if it's just a lint, we don't need a full crater run.

@Mark-Simulacrum Mark-Simulacrum added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Sep 1, 2019
@estebank estebank added the A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. label Feb 13, 2020
@estebank
Copy link
Contributor

estebank commented Jul 8, 2022

#98580 will lint against this as warn-by-default.

@PrestonFrom
Copy link
Contributor

#98580 has been merged -- should this issue be closed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lint Area: Lints (warnings about flaws in source code) such as unused_mut. C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

10 participants