Skip to content

Commit

Permalink
separate labels for default binding mode spans into their own notes
Browse files Browse the repository at this point in the history
  • Loading branch information
dianne committed Feb 5, 2025
1 parent a064e78 commit 767f820
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 183 deletions.
25 changes: 17 additions & 8 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Determine the binding mode...
let bm = match user_bind_annot {
BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => {
// Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
// using other experimental matching features compatible with it.
if pat.span.at_least_rust_2024()
Expand All @@ -828,18 +828,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_info.top_info.hir_id,
pat,
ident.span,
def_br_mutbl,
);
BindingMode(ByRef::No, Mutability::Mut)
}
}
BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
BindingMode(ByRef::Yes(_), _) => {
if matches!(def_br, ByRef::Yes(_)) {
if let ByRef::Yes(def_br_mutbl) = def_br {
// `ref`/`ref mut` overrides the binding mode on edition <= 2021
self.add_rust_2024_migration_desugared_pat(
pat_info.top_info.hir_id,
pat,
ident.span,
def_br_mutbl,
);
}
user_bind_annot
Expand Down Expand Up @@ -2378,6 +2380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_info.top_info.hir_id,
pat,
inner.span,
inh_mut,
)
}
}
Expand Down Expand Up @@ -2769,6 +2772,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_id: HirId,
subpat: &'tcx Pat<'tcx>,
cutoff_span: Span,
def_br_mutbl: Mutability,
) {
// Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
// If the subpattern's span is is from an expansion, the emitted label will not be trimmed.
Expand All @@ -2791,16 +2795,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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"
"occurs within macro expansion".to_owned()
} else {
if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
let pat_kind = if matches!(subpat.kind, PatKind::Binding(_, _, _, _)) {
info.bad_modifiers |= true;
"this binding modifier"
"binding modifier"
} else {
info.bad_ref_pats |= true;
"this reference pattern"
}
"reference pattern"
};
let dbm_str = match def_br_mutbl {
Mutability::Not => "ref",
Mutability::Mut => "ref mut",
};
format!("{pat_kind} not allowed under `{dbm_str}` default binding mode")
};
info.primary_labels.push((trimmed_span, primary_label.to_owned()));
info.primary_labels.push((trimmed_span, primary_label));
}
}
21 changes: 21 additions & 0 deletions compiler/rustc_mir_build/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,27 @@ impl Subdiagnostic for Rust2024IncompatiblePatSugg {
diag: &mut Diag<'_, G>,
_f: &F,
) {
// Format and emit explanatory notes about default binding modes. Reversing the spans' order
// means if we have nested spans, the innermost ones will be visited first.
for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() {
// Don't point to a macro call site.
if !span.from_expansion() {
let dbm_str = match def_br_mutbl {
ty::Mutability::Not => "ref",
ty::Mutability::Mut => "ref mut",
};
let note_msg = format!(
"the default binding mode changed to `{dbm_str}` because this has type `{}_`",
def_br_mutbl.ref_prefix_str()
);
let label_msg = format!("the default binding mode is `{dbm_str}`, introduced here");
let mut label = MultiSpan::from(span);
label.push_span_label(span, label_msg);
diag.span_note(label, note_msg);
}
}

// Format and emit the suggestion.
let applicability =
if self.suggestion.iter().all(|(span, _)| span.can_be_used_for_suggestions()) {
Applicability::MachineApplicable
Expand Down
10 changes: 0 additions & 10 deletions compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,6 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
for (span, label) in &info.primary_labels {
spans.push_span_label(*span, label.clone());
}
for (span, label_mutbl) in &sugg.default_mode_labels {
// Don't point to a macro call site.
if !span.from_expansion() {
let label = match label_mutbl {
Mutability::Not => "default binding mode is `ref`",
Mutability::Mut => "default binding mode is `ref mut`",
};
spans.push_span_label(*span, label.to_owned())
}
}
// If a relevant span is from at least edition 2024, this is a hard error.
let is_hard_error = spans.primary_spans().iter().any(|span| span.at_least_rust_2024());
if is_hard_error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ error: binding modifiers may only be written when the default binding mode is `m
--> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
|
LL | let [ref mut x] = &[0];
| -^^^^^^^---
| ||
| |this binding modifier
| default binding mode is `ref`
| ^^^^^^^ binding modifier not allowed under `ref` default binding mode
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: the default binding mode changed to `ref` because this has type `&_`
--> $DIR/ref-binding-on-inh-ref-errors.rs:67:9
|
LL | let [ref mut x] = &[0];
| ^^^^^^^^^^^ the default binding mode is `ref`, introduced here
help: make the implied reference pattern explicit
|
LL | let &[ref mut x] = &[0];
Expand All @@ -35,12 +37,14 @@ error: binding modifiers may only be written when the default binding mode is `m
--> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
|
LL | let [ref x] = &[0];
| -^^^---
| ||
| |this binding modifier
| default binding mode is `ref`
| ^^^ binding modifier not allowed under `ref` default binding mode
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: the default binding mode changed to `ref` because this has type `&_`
--> $DIR/ref-binding-on-inh-ref-errors.rs:75:9
|
LL | let [ref x] = &[0];
| ^^^^^^^ the default binding mode is `ref`, introduced here
help: make the implied reference pattern explicit
|
LL | let &[ref x] = &[0];
Expand All @@ -50,12 +54,14 @@ error: binding modifiers may only be written when the default binding mode is `m
--> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
|
LL | let [ref x] = &mut [0];
| -^^^---
| ||
| |this binding modifier
| default binding mode is `ref mut`
| ^^^ binding modifier not allowed under `ref mut` default binding mode
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: the default binding mode changed to `ref mut` because this has type `&mut _`
--> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
|
LL | let [ref x] = &mut [0];
| ^^^^^^^ the default binding mode is `ref mut`, introduced here
help: make the implied reference pattern explicit
|
LL | let &mut [ref x] = &mut [0];
Expand All @@ -65,12 +71,14 @@ error: binding modifiers may only be written when the default binding mode is `m
--> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
|
LL | let [ref mut x] = &mut [0];
| -^^^^^^^---
| ||
| |this binding modifier
| default binding mode is `ref mut`
| ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
note: the default binding mode changed to `ref mut` because this has type `&mut _`
--> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
|
LL | let [ref mut x] = &mut [0];
| ^^^^^^^^^^^ the default binding mode is `ref mut`, introduced here
help: make the implied reference pattern explicit
|
LL | let &mut [ref mut x] = &mut [0];
Expand Down
Loading

0 comments on commit 767f820

Please sign in to comment.