-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add suggestion for captured and passed arg case in fmt macro #105635
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @oli-obk (or someone else) soon. Please see the contribution instructions for more information. |
let current_arg = symbol.as_str(); | ||
let current_arg_ph = "{".to_owned() + current_arg + "}"; | ||
if current_arg.len() > 0 && fmt_str.contains(current_arg_ph.as_str()) { | ||
err = "argument never used, consider removing it" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the argument is also a duplicate of an existing argument, this should probably mention that the argument is a duplicate of an inline argument, which is the reason it should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"argument is a duplicate of an inline argument" is an intuitive error suggestion I think? or should I include ", consider removing it" afterwards?
r? @estebank |
Replying to your question from the ticket: You should look at all the formatting placeholders that have an Ideally the end result would be something along the lines of
|
Sure will do that soon! Thanks. |
Hello @estebank , So, If I get to know how to reference these spans again after the note, I'll do it. I'm trying to figure it out but if possible please let me know. Though the current suggestion is intuitive but I think your representation is more friendly. |
Hello @estebank can you please review the PR 😅 |
error: argument never used | ||
--> $DIR/issue-105225.rs:3:21 | ||
| | ||
LL | println!("{x}", x); | ||
| ----- ^ argument never used | ||
| | | ||
| formatting specifier missing | ||
| | ||
= note: the formatting string captures that binding directly, it doesn't need to be included in the argument list | ||
help: Consider removing this | ||
--> $DIR/issue-105225.rs:3:21 | ||
| | ||
LL | println!("{x}", x); | ||
| ^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
error: argument never used | |
--> $DIR/issue-105225.rs:3:21 | |
| | |
LL | println!("{x}", x); | |
| ----- ^ argument never used | |
| | | |
| formatting specifier missing | |
| | |
= note: the formatting string captures that binding directly, it doesn't need to be included in the argument list | |
help: Consider removing this | |
--> $DIR/issue-105225.rs:3:21 | |
| | |
LL | println!("{x}", x); | |
| ^ | |
error: argument never used | |
--> $DIR/issue-105225.rs:3:21 | |
| | |
LL | println!("{x}", x); | |
| ----- ^ argument never used | |
| | | |
| formatting specifier missing | |
| | |
note: the formatting string captures that binding directly, it doesn't need to be included in the argument list | |
--> $DIR/issue-105225.rs:3:21 | |
| | |
LL | println!("{x}", x); | |
| ^ - this can be removed | |
| | | |
| this formatting argument captures `x` directly |
In order to add labels in a note you'd have to use a terrible API (details fudged):
let mut span: MultiSpan = vec_primary_spans.into(); // this should be the formatting arg
for arg in args {
span.push_span_label(arg.span, format!("this formatting argument captures `{}` directly", arg.name));
}
for span in duplicate_explicit_arg {
span.push_span_label(span, "this can be removed".to_string());
}
Thanks for the ping! Could you also add a couple of more test cases where multiple arguments are redundantly captured? |
Currently going through university exams, will update soon. |
There was a small problem, The InnerSpan that arg.position_span returns was |
This comment has been minimized.
This comment has been minimized.
if let Some(expr) = args.explicit_args()[i].expr.to_ty() { | ||
if let Some(symbol) = expr.kind.is_simple_path() { | ||
let current_arg = symbol.as_str().to_owned(); | ||
let current_arg_ph = format!("{{{current_arg}}}"); | ||
if current_arg.len() > 0 && fmt_str.contains(current_arg_ph.as_str()) { | ||
duplicate_explicit_arg.push(args.explicit_args()[i].expr.span); | ||
for piece in &pieces { | ||
if let NextArgument(arg) = piece { | ||
if let ArgumentNamed(specifier) = arg.position { | ||
if specifier == symbol.to_string() { | ||
redundant_expl_args.push({ | ||
RedundantArgDiagBuilder { | ||
arg_span: expr.span, | ||
fmt_span: InnerSpan { | ||
start: arg.position_span.start, | ||
end: arg.position_span.end, | ||
}, | ||
fmt_str: specifier, | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can take the chance to leverage let chains and reduce the indentation levels of this code:
if let Some(expr) = args.explicit_args()[i].expr.to_ty()
&& let Some(symbol) = expr.kind.is_simple_path()
{
let current_arg = symbol.as_str().to_owned();
for piece in &pieces {
if let NextArgument(arg) = piece
&& let ArgumentNamed(specifier) = arg.position
{
if specifier == symbol.to_string() {
redundant_expl_args.push(RedundantArgDiagBuilder {
arg_span: expr.span,
fmt_span: InnerSpan {
start: arg.position_span.start,
end: arg.position_span.end,
},
fmt_str: specifier,
});
}
}
}
}
for arg_span in arg_spans { | ||
m_span.push_span_label(arg_span, "this can be removed".to_string()); | ||
} | ||
diag.span_help(m_span, "the formatting string captures that binding directly, it doesn't need to be included in the argument list"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should customize the output depending on the number of bindings:
diag.span_help(m_span, "the formatting string captures that binding directly, it doesn't need to be included in the argument list"); | |
let mut bindings: Vec<_> = arg.iter().collect(); | |
bindings.sort(); | |
bindings.dedup(); | |
diag.span_help( | |
m_span, | |
&format!( | |
"the formatting string captures {} directly, {} need to \ | |
be included in the argument list", | |
match &bindings[..] { | |
[.., last] if bindings.len() < 8 => format!("bindings `{}` and `{last}`"), | |
[binding] => format!("binding {binding}"), | |
_ => "these bindings".to_string(), | |
}, | |
if bindings.len() == 1 { | |
"it doesn't" | |
} else { | |
"they don't" | |
}, | |
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This request is still valid :)
You can choose to simplify it, but at least I'd like to specialize the output for a single binding as opposed to multiple.
You will have to rebase on top of the latest version in the repo. I see that you were working on your checkout's master branch, which will make things slightly less intuitive (but few things with git are). The following should work:
At that point you might have to fix merge conflicts. I find that some kind of interactive UI can help make sense of the situation. But there's potential for things to go awry, so please read https://rustc-dev-guide.rust-lang.org/git.html?highlight=rebase#rebasing and maybe make a backup of your current changes ( BTW this looks awesome! Thank you for working on it! |
Thank you for your kind and detailed review, Will revert ASAP. |
I have found a problem with my code while testing, println!("{x}{x}{x}{x}",x,y,y,x); The suggestion provided is
This is happening because of lines : we are checking Hence I need a way to find which binding is given inside the placeholder. |
@tanveerraza789 what's the update on this? |
Hello @Dylan-DPC Give me a week (7d) if I'm not able to solve this then I'll unclaim this issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me after addressing the nitpicks
Thank you for doing this! It should be very helpful for newcomers that don't know about binding captures yet.
I've made the changes you said, I've also added the skeleton of the logic I was thinking of but could not implement due to some reasons, like getting |
The job Click to see the possible cause of the failure (guessed by this bot)
|
☔ The latest upstream changes (presumably #110092) made this pull request unmergeable. Please resolve the merge conflicts. |
@tanveerraza789 any updates on this? |
Closing this as inactive. Feel free to reöpen this pr or create a new pr if you get the time to work on this. Thanks |
Suggest removing redundant arguments in format!() Closes rust-lang#105225. This is also a follow-up to rust-lang#105635, which seems to have become stale. r? `@estebank`
Suggest removing redundant arguments in format!() Closes rust-lang#105225. This is also a follow-up to rust-lang#105635, which seems to have become stale. r? `@estebank`
Fixes #105225