Skip to content

Commit

Permalink
Fix rust-lang#117284, Fix unused variables lint issue for args in macro
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Oct 30, 2023
1 parent 91bbdd9 commit 82f34fd
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 11 deletions.
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

0 comments on commit 82f34fd

Please sign in to comment.