Skip to content

Commit 4161829

Browse files
authored
Unrolled build for rust-lang#131381
Rollup merge of rust-lang#131381 - Nadrieril:min-match-ergonomics, r=pnkfelix Implement edition 2024 match ergonomics restrictions This implements the minimalest version of [match ergonomics for edition 2024](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html). This minimal version makes it an error to ever reset the default binding mode. The implemented proposal is described precisely [here](https://hackmd.io/zUqs2ISNQ0Wrnxsa9nhD0Q#RFC-3627-nano), where it is called "RFC 3627-nano". Rules: - Rule 1C: When the DBM (default binding mode) is not `move` (whether or not behind a reference), writing `mut`, `ref`, or `ref mut` on a binding is an error. - Rule 2C: Reference patterns can only match against references in the scrutinee when the DBM is `move`. This minimal version is forward-compatible with the main proposals for match ergonomics 2024: [RFC3627](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html) itself, the alternative [rule 4-early variant](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html), and [others](https://hackmd.io/zUqs2ISNQ0Wrnxsa9nhD0Q). The idea is to give us more time to iron out a final proposal. This includes a migration lint that desugars any offending pattern into one that doesn't make use of match ergonomics. Such patterns have identical meaning across editions. This PR insta-stabilizes the proposed behavior onto edition 2024. r? `@ghost` Tracking: - rust-lang#123076
2 parents bed75e7 + 2ef0a8f commit 4161829

17 files changed

+757
-242
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -690,16 +690,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
690690

691691
BindingMode(def_br, Mutability::Mut)
692692
} else {
693-
// `mut` resets binding mode on edition <= 2021
694-
self.typeck_results
693+
// `mut` resets the binding mode on edition <= 2021
694+
*self
695+
.typeck_results
695696
.borrow_mut()
696697
.rust_2024_migration_desugared_pats_mut()
697-
.insert(pat_info.top_info.hir_id);
698+
.entry(pat_info.top_info.hir_id)
699+
.or_default() |= pat.span.at_least_rust_2024();
698700
BindingMode(ByRef::No, Mutability::Mut)
699701
}
700702
}
701703
BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
702-
BindingMode(ByRef::Yes(_), _) => user_bind_annot,
704+
BindingMode(ByRef::Yes(_), _) => {
705+
if matches!(def_br, ByRef::Yes(_)) {
706+
// `ref`/`ref mut` overrides the binding mode on edition <= 2021
707+
*self
708+
.typeck_results
709+
.borrow_mut()
710+
.rust_2024_migration_desugared_pats_mut()
711+
.entry(pat_info.top_info.hir_id)
712+
.or_default() |= pat.span.at_least_rust_2024();
713+
}
714+
user_bind_annot
715+
}
703716
};
704717

705718
if bm.0 == ByRef::Yes(Mutability::Mut)
@@ -2204,14 +2217,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22042217
}
22052218
} else {
22062219
// Reset binding mode on old editions
2207-
22082220
if pat_info.binding_mode != ByRef::No {
22092221
pat_info.binding_mode = ByRef::No;
2210-
2211-
self.typeck_results
2222+
*self
2223+
.typeck_results
22122224
.borrow_mut()
22132225
.rust_2024_migration_desugared_pats_mut()
2214-
.insert(pat_info.top_info.hir_id);
2226+
.entry(pat_info.top_info.hir_id)
2227+
.or_default() |= pat.span.at_least_rust_2024();
22152228
}
22162229
}
22172230

@@ -2262,6 +2275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22622275
(err, err)
22632276
}
22642277
};
2278+
22652279
self.check_pat(inner, inner_ty, pat_info);
22662280
ref_ty
22672281
}

compiler/rustc_hir_typeck/src/writeback.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
635635

636636
#[instrument(skip(self), level = "debug")]
637637
fn visit_rust_2024_migration_desugared_pats(&mut self, hir_id: hir::HirId) {
638-
if self
638+
if let Some(is_hard_error) = self
639639
.fcx
640640
.typeck_results
641641
.borrow_mut()
@@ -645,7 +645,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
645645
debug!(
646646
"node is a pat whose match ergonomics are desugared by the Rust 2024 migration lint"
647647
);
648-
self.typeck_results.rust_2024_migration_desugared_pats_mut().insert(hir_id);
648+
self.typeck_results
649+
.rust_2024_migration_desugared_pats_mut()
650+
.insert(hir_id, is_hard_error);
649651
}
650652
}
651653

compiler/rustc_lint_defs/src/builtin.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,6 @@ declare_lint! {
16511651
/// ### Example
16521652
///
16531653
/// ```rust,edition2021
1654-
/// #![feature(ref_pat_eat_one_layer_2024)]
16551654
/// #![warn(rust_2024_incompatible_pat)]
16561655
///
16571656
/// if let Some(&a) = &Some(&0u8) {
@@ -1672,12 +1671,10 @@ declare_lint! {
16721671
pub RUST_2024_INCOMPATIBLE_PAT,
16731672
Allow,
16741673
"detects patterns whose meaning will change in Rust 2024",
1675-
@feature_gate = ref_pat_eat_one_layer_2024;
1676-
// FIXME uncomment below upon stabilization
1677-
/*@future_incompatible = FutureIncompatibleInfo {
1674+
@future_incompatible = FutureIncompatibleInfo {
16781675
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
16791676
reference: "123076",
1680-
};*/
1677+
};
16811678
}
16821679

16831680
declare_lint! {

compiler/rustc_middle/src/ty/typeck_results.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ pub struct TypeckResults<'tcx> {
7373
/// Stores the actual binding mode for all instances of [`BindingMode`].
7474
pat_binding_modes: ItemLocalMap<BindingMode>,
7575

76-
/// Top-level patterns whose match ergonomics need to be desugared
77-
/// by the Rust 2021 -> 2024 migration lint.
78-
rust_2024_migration_desugared_pats: ItemLocalSet,
76+
/// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024
77+
/// migration lint. The boolean indicates whether the emitted diagnostic should be a hard error
78+
/// (if any of the incompatible pattern elements are in edition 2024).
79+
rust_2024_migration_desugared_pats: ItemLocalMap<bool>,
7980

8081
/// Stores the types which were implicitly dereferenced in pattern binding modes
8182
/// for later usage in THIR lowering. For example,
@@ -418,15 +419,15 @@ impl<'tcx> TypeckResults<'tcx> {
418419
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
419420
}
420421

421-
pub fn rust_2024_migration_desugared_pats(&self) -> LocalSetInContext<'_> {
422-
LocalSetInContext {
422+
pub fn rust_2024_migration_desugared_pats(&self) -> LocalTableInContext<'_, bool> {
423+
LocalTableInContext {
423424
hir_owner: self.hir_owner,
424425
data: &self.rust_2024_migration_desugared_pats,
425426
}
426427
}
427428

428-
pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
429-
LocalSetInContextMut {
429+
pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalTableInContextMut<'_, bool> {
430+
LocalTableInContextMut {
430431
hir_owner: self.hir_owner,
431432
data: &mut self.rust_2024_migration_desugared_pats,
432433
}

compiler/rustc_mir_build/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
265265
266266
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
267267
268-
mir_build_rust_2024_incompatible_pat = the semantics of this pattern will change in edition 2024
268+
mir_build_rust_2024_incompatible_pat = patterns are not allowed to reset the default binding mode in edition 2024
269269
270270
mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
271271
.attributes = no other attributes may be applied

compiler/rustc_mir_build/src/errors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,8 @@ pub(crate) struct Rust2024IncompatiblePat {
983983

984984
pub(crate) struct Rust2024IncompatiblePatSugg {
985985
pub(crate) suggestion: Vec<(Span, String)>,
986+
/// Whether the incompatibility is a hard error because a relevant span is in edition 2024.
987+
pub(crate) is_hard_error: bool,
986988
}
987989

988990
impl Subdiagnostic for Rust2024IncompatiblePatSugg {

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use tracing::{debug, instrument};
2525

2626
pub(crate) use self::check_match::check_match;
2727
use crate::errors::*;
28+
use crate::fluent_generated as fluent;
2829
use crate::thir::util::UserAnnotatedTyHelpers;
2930

3031
struct PatCtxt<'a, 'tcx> {
@@ -48,18 +49,28 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
4849
typeck_results,
4950
rust_2024_migration_suggestion: typeck_results
5051
.rust_2024_migration_desugared_pats()
51-
.contains(pat.hir_id)
52-
.then_some(Rust2024IncompatiblePatSugg { suggestion: Vec::new() }),
52+
.get(pat.hir_id)
53+
.map(|&is_hard_error| Rust2024IncompatiblePatSugg {
54+
suggestion: Vec::new(),
55+
is_hard_error,
56+
}),
5357
};
5458
let result = pcx.lower_pattern(pat);
5559
debug!("pat_from_hir({:?}) = {:?}", pat, result);
5660
if let Some(sugg) = pcx.rust_2024_migration_suggestion {
57-
tcx.emit_node_span_lint(
58-
lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
59-
pat.hir_id,
60-
pat.span,
61-
Rust2024IncompatiblePat { sugg },
62-
);
61+
if sugg.is_hard_error {
62+
let mut err =
63+
tcx.dcx().struct_span_err(pat.span, fluent::mir_build_rust_2024_incompatible_pat);
64+
err.subdiagnostic(sugg);
65+
err.emit();
66+
} else {
67+
tcx.emit_node_span_lint(
68+
lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
69+
pat.hir_id,
70+
pat.span,
71+
Rust2024IncompatiblePat { sugg },
72+
);
73+
}
6374
}
6475
result
6576
}

tests/ui/pattern/match_ergonomics_2024.fixed

-57
This file was deleted.

tests/ui/pattern/match_ergonomics_2024.rs

-57
This file was deleted.

0 commit comments

Comments
 (0)