From 9d200f2d88600c685e4d2945308b5116c29849e7 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Tue, 2 Apr 2024 10:54:29 -0500 Subject: [PATCH] Address review comments --- compiler/rustc_feature/src/unstable.rs | 4 ++-- compiler/rustc_hir_typeck/src/pat.rs | 6 +++--- compiler/rustc_hir_typeck/src/writeback.rs | 10 ++++----- .../rustc_middle/src/ty/typeck_results.rs | 12 +++++------ .../rustc_mir_build/src/thir/pattern/mod.rs | 14 ++++++------- compiler/rustc_span/src/symbol.rs | 2 +- .../feature-gate-ref_pat_everywhere.rs} | 0 .../feature-gate-ref_pat_everywhere.stderr} | 8 +++---- ...ref_pat_everywhere-mutability-mismatch.rs} | 6 +++++- ...pat_everywhere-mutability-mismatch.stderr} | 21 ++++++++++++++++--- ...at_everywhere.rs => ref_pat_everywhere.rs} | 5 ++++- 11 files changed, 55 insertions(+), 33 deletions(-) rename tests/ui/{match/feature-gate-and_pat_everywhere.rs => feature-gates/feature-gate-ref_pat_everywhere.rs} (100%) rename tests/ui/{match/feature-gate-and_pat_everywhere.stderr => feature-gates/feature-gate-ref_pat_everywhere.stderr} (88%) rename tests/ui/match/{and_pat_everywhere-mutability-mismatch.rs => ref_pat_everywhere-mutability-mismatch.rs} (65%) rename tests/ui/match/{and_pat_everywhere-mutability-mismatch.stderr => ref_pat_everywhere-mutability-mismatch.stderr} (55%) rename tests/ui/match/{and_pat_everywhere.rs => ref_pat_everywhere.rs} (72%) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index d1a67f4f96ec9..36db377f7e0a8 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -339,8 +339,6 @@ declare_features! ( (incomplete, adt_const_params, "1.56.0", Some(95174)), /// Allows defining an `#[alloc_error_handler]`. (unstable, alloc_error_handler, "1.29.0", Some(51540)), - /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references. - (incomplete, and_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)), /// Allows trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows using `const` operands in inline assembly. @@ -569,6 +567,8 @@ declare_features! ( (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. (unstable, raw_ref_op, "1.41.0", Some(64490)), + /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references. + (incomplete, ref_pat_everywhere, "CURRENT_RUSTC_VERSION", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f428c536da038..298047427cc0b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2058,7 +2058,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mutbl: Mutability, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, - already_consumed: bool, + consumed_inherited_ref: bool, ) -> Ty<'tcx> { let tcx = self.tcx; let expected = self.shallow_resolve(expected); @@ -2074,13 +2074,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *expected.kind() { ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty), _ => { - if already_consumed && self.tcx.features().and_pat_everywhere { + if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere { // We already matched against a match-ergonmics inserted reference, // so we don't need to match against a reference from the original type. // Save this infor for use in lowering later self.typeck_results .borrow_mut() - .ref_pats_that_dont_deref_mut() + .skipped_ref_pats_mut() .insert(pat.hir_id); (expected, expected) } else { diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 142a13f88767c..6604bf094c14a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -345,7 +345,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { _ => {} }; - self.visit_ref_pats_that_dont_deref(p.hir_id); + self.visit_skipped_ref_pats(p.hir_id); self.visit_pat_adjustments(p.span, p.hir_id); self.visit_node_id(p.span, p.hir_id); @@ -676,10 +676,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn visit_ref_pats_that_dont_deref(&mut self, hir_id: hir::HirId) { - if self.fcx.typeck_results.borrow_mut().ref_pats_that_dont_deref_mut().remove(hir_id) { - debug!("node is a ref pat that doesn't deref"); - self.typeck_results.ref_pats_that_dont_deref_mut().insert(hir_id); + fn visit_skipped_ref_pats(&mut self, hir_id: hir::HirId) { + if self.fcx.typeck_results.borrow_mut().skipped_ref_pats_mut().remove(hir_id) { + debug!("node is a skipped ref pat"); + self.typeck_results.skipped_ref_pats_mut().insert(hir_id); } } diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 6abcab0699a61..175b53686a176 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -98,7 +98,7 @@ pub struct TypeckResults<'tcx> { /// Set of reference patterns that match against a match-ergonomics inserted reference /// (as opposed to against a reference in the scrutinee type). - ref_pats_that_dont_deref: ItemLocalSet, + skipped_ref_pats: ItemLocalSet, /// Records the reasons that we picked the kind of each closure; /// not all closures are present in the map. @@ -232,7 +232,7 @@ impl<'tcx> TypeckResults<'tcx> { adjustments: Default::default(), pat_binding_modes: Default::default(), pat_adjustments: Default::default(), - ref_pats_that_dont_deref: Default::default(), + skipped_ref_pats: Default::default(), closure_kind_origins: Default::default(), liberated_fn_sigs: Default::default(), fru_field_types: Default::default(), @@ -440,12 +440,12 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } - pub fn ref_pats_that_dont_deref(&self) -> LocalSetInContext<'_> { - LocalSetInContext { hir_owner: self.hir_owner, data: &self.ref_pats_that_dont_deref } + pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> { + LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats } } - pub fn ref_pats_that_dont_deref_mut(&mut self) -> LocalSetInContextMut<'_> { - LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.ref_pats_that_dont_deref } + pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> { + LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats } } /// Does the pattern recursively contain a `ref mut` binding in it? diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4b4a54a85c0b0..133cf8e334929 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -65,16 +65,16 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // we wrap the unadjusted pattern in `PatKind::Deref` repeatedly, consuming the // adjustments in *reverse order* (last-in-first-out, so that the last `Deref` inserted // gets the least-dereferenced type). - let unadjusted = if self.typeck_results.ref_pats_that_dont_deref().contains(pat.hir_id) { - match pat.kind { - hir::PatKind::Ref(inner, _) => self.lower_pattern_unadjusted(inner), - _ => span_bug!(pat.span, "non ref pattern marked as non-deref ref pattern"), + let unadjusted_pat = match pat.kind { + hir::PatKind::Ref(inner, _) + if self.typeck_results.skipped_ref_pats().contains(pat.hir_id) => + { + self.lower_pattern_unadjusted(inner) } - } else { - self.lower_pattern_unadjusted(pat) + _ => self.lower_pattern_unadjusted(pat), }; self.typeck_results.pat_adjustments().get(pat.hir_id).unwrap_or(&vec![]).iter().rev().fold( - unadjusted, + unadjusted_pat, |pat: Box<_>, ref_ty| { debug!("{:?}: wrapping pattern with type {:?}", pat, ref_ty); Box::new(Pat { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1a20ed1caa3ed..1b407539d3c1e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -380,7 +380,6 @@ symbols! { alu32, always, and, - and_pat_everywhere, and_then, anon, anon_adt, @@ -1457,6 +1456,7 @@ symbols! { receiver, recursion_limit, reexport_test_harness_main, + ref_pat_everywhere, ref_unwind_safe_trait, reference, reflect, diff --git a/tests/ui/match/feature-gate-and_pat_everywhere.rs b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs similarity index 100% rename from tests/ui/match/feature-gate-and_pat_everywhere.rs rename to tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs diff --git a/tests/ui/match/feature-gate-and_pat_everywhere.stderr b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr similarity index 88% rename from tests/ui/match/feature-gate-and_pat_everywhere.stderr rename to tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr index 3c6b7752a0aca..0f0051325cdf0 100644 --- a/tests/ui/match/feature-gate-and_pat_everywhere.stderr +++ b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-and_pat_everywhere.rs:2:22 + --> $DIR/feature-gate-ref_pat_everywhere.rs:2:22 | LL | if let Some(Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -14,7 +14,7 @@ LL | if let Some(Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/feature-gate-and_pat_everywhere.rs:6:17 + --> $DIR/feature-gate-ref_pat_everywhere.rs:6:17 | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ^^^^^^^^ -------------- this expression has type `&Option>` @@ -25,7 +25,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/feature-gate-and_pat_everywhere.rs:10:22 + --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` @@ -35,7 +35,7 @@ LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { = note: expected type `{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/feature-gate-and_pat_everywhere.rs:10:22 + --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ diff --git a/tests/ui/match/and_pat_everywhere-mutability-mismatch.rs b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs similarity index 65% rename from tests/ui/match/and_pat_everywhere-mutability-mismatch.rs rename to tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs index 2135f0e2e5057..9dd7a7893ec71 100644 --- a/tests/ui/match/and_pat_everywhere-mutability-mismatch.rs +++ b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.rs @@ -1,5 +1,5 @@ #![allow(incomplete_features)] -#![feature(and_pat_everywhere)] +#![feature(ref_pat_everywhere)] pub fn main() { if let Some(&x) = Some(0) { //~^ ERROR: mismatched types [E0308] @@ -9,4 +9,8 @@ pub fn main() { //~^ ERROR: mismatched types [E0308] let _: u32 = x; } + if let Some(&x) = &mut Some(0) { + //~^ ERROR: mismatched types [E0308] + let _: u32 = x; + } } diff --git a/tests/ui/match/and_pat_everywhere-mutability-mismatch.stderr b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr similarity index 55% rename from tests/ui/match/and_pat_everywhere-mutability-mismatch.stderr rename to tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr index 6d1317a9dfdbc..d512ea5f957da 100644 --- a/tests/ui/match/and_pat_everywhere-mutability-mismatch.stderr +++ b/tests/ui/match/ref_pat_everywhere-mutability-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/and_pat_everywhere-mutability-mismatch.rs:4:17 + --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:4:17 | LL | if let Some(&x) = Some(0) { | ^^ ------- this expression has type `Option<{integer}>` @@ -14,7 +14,7 @@ LL | if let Some(x) = Some(0) { | ~ error[E0308]: mismatched types - --> $DIR/and_pat_everywhere-mutability-mismatch.rs:8:12 + --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:8:12 | LL | if let &Some(x) = &mut Some(0) { | ^^^^^^^^ ------------ this expression has type `&mut Option<{integer}>` @@ -24,6 +24,21 @@ LL | if let &Some(x) = &mut Some(0) { = note: expected mutable reference `&mut Option<{integer}>` found reference `&_` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/ref_pat_everywhere-mutability-mismatch.rs:12:17 + | +LL | if let Some(&x) = &mut Some(0) { + | ^^ ------------ this expression has type `&mut Option<{integer}>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(x) = &mut Some(0) { + | ~ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/and_pat_everywhere.rs b/tests/ui/match/ref_pat_everywhere.rs similarity index 72% rename from tests/ui/match/and_pat_everywhere.rs rename to tests/ui/match/ref_pat_everywhere.rs index 00938a212ab3b..b3daca484092b 100644 --- a/tests/ui/match/and_pat_everywhere.rs +++ b/tests/ui/match/ref_pat_everywhere.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(incomplete_features)] -#![feature(and_pat_everywhere)] +#![feature(ref_pat_everywhere)] pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { @@ -12,4 +12,7 @@ pub fn main() { if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { let _: u32 = x; } + if let Some(Some(&x)) = &Some(&mut Some(0)) { + let _: u32 = x; + } }