Skip to content

Pattern Migration 2024: fix incorrect messages/suggestions when errors arise in macro expansions #137161

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

Merged
merged 2 commits into from
Feb 19, 2025
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
34 changes: 18 additions & 16 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2806,31 +2806,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
});

let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
info.bad_modifiers = true;
// If the user-provided binding modifier doesn't match the default binding mode, we'll
// need to suggest reference patterns, which can affect other bindings.
// For simplicity, we opt to suggest making the pattern fully explicit.
info.suggest_eliding_modes &=
user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
"binding modifier"
} else {
info.bad_ref_pats = true;
// For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
// suggest adding them instead, which can affect the types assigned to bindings.
// As such, we opt to suggest making the pattern fully explicit.
info.suggest_eliding_modes = false;
"reference pattern"
};
// Only provide a detailed label if the problematic subpattern isn't from an expansion.
// In the case that it's from a macro, we'll add a more detailed note in the emitter.
let from_expansion = subpat.span.from_expansion();
let primary_label = if from_expansion {
// We can't suggest eliding modifiers within expansions.
info.suggest_eliding_modes = false;
// NB: This wording assumes the only expansions that can produce problematic reference
// patterns and bindings are macros. If a desugaring or AST pass is added that can do
// so, we may want to inspect the span's source callee or macro backtrace.
"occurs within macro expansion".to_owned()
} else {
let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
info.bad_modifiers |= true;
// If the user-provided binding modifier doesn't match the default binding mode, we'll
// need to suggest reference patterns, which can affect other bindings.
// For simplicity, we opt to suggest making the pattern fully explicit.
info.suggest_eliding_modes &=
user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
"binding modifier"
} else {
info.bad_ref_pats |= true;
// For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
// suggest adding them instead, which can affect the types assigned to bindings.
// As such, we opt to suggest making the pattern fully explicit.
info.suggest_eliding_modes = false;
"reference pattern"
};
let dbm_str = match def_br_mutbl {
Mutability::Not => "ref",
Mutability::Mut => "ref mut",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ macro_rules! mixed_edition_pat {
Some(mut $foo)
};
}

#[macro_export]
macro_rules! bind_ref {
($foo:ident) => {
ref $foo
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,9 @@ fn main() {
assert_type_eq(b, &0u32);
assert_type_eq(c, &[0u32]);
assert_type_eq(d, 0u32);

// Test that we use the correct message and suggestion style when pointing inside expansions.
let &[migration_lint_macros::bind_ref!(a)] = &[0];
//~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
assert_type_eq(a, &0u32);
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,4 +239,9 @@ fn main() {
assert_type_eq(b, &0u32);
assert_type_eq(c, &[0u32]);
assert_type_eq(d, 0u32);

// Test that we use the correct message and suggestion style when pointing inside expansions.
let [migration_lint_macros::bind_ref!(a)] = &[0];
//~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
assert_type_eq(a, &0u32);
}
Original file line number Diff line number Diff line change
Expand Up @@ -562,5 +562,23 @@ help: make the implied reference patterns explicit
LL | let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
| + +

error: aborting due to 29 previous errors
error: binding modifiers may only be written when the default binding mode is `move`
--> $DIR/migration_lint.rs:244:10
|
LL | let [migration_lint_macros::bind_ref!(a)] = &[0];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: matching on a reference type with a non-reference pattern changes the default binding mode
--> $DIR/migration_lint.rs:244:9
|
LL | let [migration_lint_macros::bind_ref!(a)] = &[0];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
= note: this error originates in the macro `migration_lint_macros::bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
help: make the implied reference pattern explicit
|
LL | let &[migration_lint_macros::bind_ref!(a)] = &[0];
| +

error: aborting due to 30 previous errors

Loading