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

Fix unused variables lint issue for args in macro #117390

Merged
merged 1 commit into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -778,13 +778,16 @@ passes_unused_var_maybe_capture_ref = unused variable: `{$name}`
passes_unused_var_remove_field = unused variable: `{$name}`
passes_unused_var_remove_field_suggestion = try removing the field

passes_unused_variable_args_in_macro = `{$name}` is captured in macro and introduced a unused variable

passes_unused_variable_try_ignore = unused variable: `{$name}`
.suggestion = try ignoring the field

passes_unused_variable_try_prefix = unused variable: `{$name}`
.label = unused variable
.suggestion = if this is intentional, prefix it with an underscore


passes_used_compiler_linker =
`used(compiler)` and `used(linker)` can't be used together

Expand Down
21 changes: 15 additions & 6 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,15 +1768,24 @@ pub struct UnusedVariableTryPrefix {
#[subdiagnostic]
pub string_interp: Vec<UnusedVariableStringInterp>,
#[subdiagnostic]
pub sugg: UnusedVariableTryPrefixSugg,
pub sugg: UnusedVariableSugg,
pub name: String,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
pub struct UnusedVariableTryPrefixSugg {
#[suggestion_part(code = "_{name}")]
pub spans: Vec<Span>,
pub name: String,
pub enum UnusedVariableSugg {
#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")]
TryPrefixSugg {
#[suggestion_part(code = "_{name}")]
spans: Vec<Span>,
name: String,
},
#[help(passes_unused_variable_args_in_macro)]
NoSugg {
#[primary_span]
span: Span,
name: String,
},
}

pub struct UnusedVariableStringInterp {
Expand Down
25 changes: 20 additions & 5 deletions compiler/rustc_passes/src/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1580,7 +1580,6 @@ impl<'tcx> Liveness<'_, 'tcx> {
opt_body: Option<&hir::Body<'_>>,
) {
let first_hir_id = hir_ids_and_spans[0].0;

if let Some(name) = self.should_warn(var).filter(|name| name != "self") {
// annoying: for parameters in funcs like `fn(x: i32)
// {ret}`, there is only one node, so asking about
Expand Down Expand Up @@ -1652,11 +1651,29 @@ impl<'tcx> Liveness<'_, 'tcx> {
},
);
} else {
// #117284, when `pat_span` and `ident_span` have different contexts
// we can't provide a good suggestion, instead we pointed out the spans from macro
let from_macro = non_shorthands
.iter()
.find(|(_, pat_span, ident_span)| {
pat_span.ctxt() != ident_span.ctxt() && pat_span.from_expansion()
})
.map(|(_, pat_span, _)| *pat_span);
let non_shorthands = non_shorthands
.into_iter()
.map(|(_, _, ident_span)| ident_span)
.collect::<Vec<_>>();

let suggestions = self.string_interp_suggestions(&name, opt_body);
let sugg = if let Some(span) = from_macro {
errors::UnusedVariableSugg::NoSugg { span, name: name.clone() }
} else {
errors::UnusedVariableSugg::TryPrefixSugg {
spans: non_shorthands,
name: name.clone(),
}
};

self.ir.tcx.emit_spanned_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
Expand All @@ -1666,10 +1683,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
.collect::<Vec<_>>(),
errors::UnusedVariableTryPrefix {
label: if !suggestions.is_empty() { Some(pat.span) } else { None },
sugg: errors::UnusedVariableTryPrefixSugg {
spans: non_shorthands,
name,
},
name,
sugg,
string_interp: suggestions,
},
);
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/lint/unused/issue-117284-arg-in-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![deny(unused_variables)]
macro_rules! make_var {
($struct:ident, $var:ident) => {
let $var = $struct.$var;
};
}

#[allow(unused)]
struct MyStruct {
var: i32,
}

fn main() {
let s = MyStruct { var: 42 };
make_var!(s, var); //~ ERROR unused variable: `var`
let a = 1; //~ ERROR unused variable: `a`
}
29 changes: 29 additions & 0 deletions tests/ui/lint/unused/issue-117284-arg-in-macro.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
error: unused variable: `var`
--> $DIR/issue-117284-arg-in-macro.rs:15:18
|
LL | make_var!(s, var);
| ^^^
|
help: `var` is captured in macro and introduced a unused variable
--> $DIR/issue-117284-arg-in-macro.rs:4:13
|
LL | let $var = $struct.$var;
| ^^^^
...
LL | make_var!(s, var);
| ----------------- in this macro invocation
note: the lint level is defined here
--> $DIR/issue-117284-arg-in-macro.rs:1:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^
= note: this error originates in the macro `make_var` (in Nightly builds, run with -Z macro-backtrace for more info)

error: unused variable: `a`
--> $DIR/issue-117284-arg-in-macro.rs:16:9
|
LL | let a = 1;
| ^ help: if this is intentional, prefix it with an underscore: `_a`

error: aborting due to 2 previous errors

Loading