From f57b970de8103f1d7cd6307ad18e9f07d21e0e84 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 4 May 2024 16:04:08 -0400 Subject: [PATCH] Comments and fixes --- compiler/rustc_hir_typeck/src/pat.rs | 37 ++++++++++------ .../ref_pat_eat_one_layer_2024_fail.rs | 12 ------ .../ref_pat_eat_one_layer_2024_fail.stderr | 35 +++------------ ...at_one_layer_2024_ref_mut_inside_and.fixed | 30 +++++++++++++ ...t_eat_one_layer_2024_ref_mut_inside_and.rs | 30 +++++++++++++ ...t_one_layer_2024_ref_mut_inside_and.stderr | 43 +++++++++++++++++++ 6 files changed, 132 insertions(+), 55 deletions(-) create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs create mode 100644 tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index d8e21574cf4..170057d4adf 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -137,8 +137,8 @@ enum AdjustMode { /// with mutability matching the pattern, /// mark the pattern as having consumed this reference. /// - /// `Span` is that of the `&` or `&mut` itself - ResetAndConsumeRef(Mutability, Span), + /// `Span` is that of the `&` or `&mut` itself. + ResetAndConsumeRef(Mutability, Option), /// Pass on the input binding mode and expected type. Pass, } @@ -154,15 +154,23 @@ enum AdjustMode { /// this last case, so we need to throw an error ourselves. #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum MutblCap { - /// Mutability restricted to immutable; - /// contained span, if present, should be shown in diagnostics as the reason. - Not(Option), + /// Mutability restricted to immutable. + /// + /// The contained span, if present, points to an `&` pattern + /// that is the reason for the restriction, + /// and which will be reported in a diagnostic. + /// (Said diagnostic is shown only if + /// replacing the `&` pattern with `&mut` would allow the code to compile.) + /// + /// (Outer [`Option`] is for whether to show the diagnostic, + /// inner [`Option`] is for whether we have a span we can report) + Not(Option>), /// No restriction on mutability Mut, } impl MutblCap { - fn cap_mutbl_to_not(self, span: Option) -> Self { + fn cap_mutbl_to_not(self, span: Option>) -> Self { if let Some(s) = span && self != MutblCap::Not(None) { @@ -434,7 +442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // ``` // // See issue #46688. - PatKind::Ref(inner, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl, pat.span.until(inner.span.find_ancestor_inside(pat.span).unwrap())), + PatKind::Ref(inner, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl, inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end))), // A `_` pattern works with any expected type, so there's no need to do anything. PatKind::Wild // A malformed pattern doesn't have an expected type, so let's just accept any type. @@ -752,12 +760,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0596, "cannot borrow as mutable inside an `&` pattern" ); - err.span_suggestion( - and_pat_span, - "replace this `&` with `&mut`", - "&mut ", - Applicability::MachineApplicable, - ); + + if let Some(span) = and_pat_span { + err.span_suggestion( + span, + "replace this `&` with `&mut`", + "&mut ", + Applicability::MachineApplicable, + ); + } err.emit(); } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs index 376855406a6..96b4ff77ddb 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs @@ -23,12 +23,6 @@ pub fn main() { if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types } - if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - } - if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern - } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types } @@ -38,10 +32,4 @@ pub fn main() { let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; //~^ ERROR: mismatched types - - macro_rules! pat { - ($var:ident) => { ref mut $var }; - } - let &pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr index d51b92230e8..e06a645fc0d 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr @@ -64,24 +64,8 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) { = note: expected enum `Option<{integer}>` found mutable reference `&mut _` -error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:31 - | -LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { - | - ^ - | | - | help: replace this `&` with `&mut`: `&mut` - -error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:31 - | -LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { - | - ^ - | | - | help: replace this `&` with `&mut`: `&mut` - error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:17 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` @@ -92,7 +76,7 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) { found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9 | LL | let &mut _ = &&0; | ^^^^^^ --- this expression has type `&&{integer}` @@ -103,7 +87,7 @@ LL | let &mut _ = &&0; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:39:9 + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:33:9 | LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` @@ -113,15 +97,6 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; = note: expected type `{integer}` found mutable reference `&mut _` -error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:45:15 - | -LL | let &pat!(x) = &mut 0; - | - ^ - | | - | help: replace this `&` with `&mut`: `&mut` +error: aborting due to 9 previous errors -error: aborting due to 12 previous errors - -Some errors have detailed explanations: E0308, E0596. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed new file mode 100644 index 00000000000..bc7a58a382d --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.fixed @@ -0,0 +1,30 @@ +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +//@ run-rustfix +#![allow(incomplete_features)] +#![feature(ref_pat_eat_one_layer_2024)] + +pub fn main() { + if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) { + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + macro_rules! pat { + ($var:ident) => { ref mut $var }; + } + let &mut pat!(x) = &mut 0; + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + + let &mut (ref mut a, ref mut b) = &mut (true, false); + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //~| ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut bool = a; + let _: &mut bool = b; +} diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs new file mode 100644 index 00000000000..c6d72b0a9d7 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs @@ -0,0 +1,30 @@ +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +//@ run-rustfix +#![allow(incomplete_features)] +#![feature(ref_pat_eat_one_layer_2024)] + +pub fn main() { + if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + } + + macro_rules! pat { + ($var:ident) => { ref mut $var }; + } + let &pat!(x) = &mut 0; + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut u8 = x; + + let &(ref mut a, ref mut b) = &mut (true, false); + //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //~| ERROR: cannot borrow as mutable inside an `&` pattern + let _: &mut bool = a; + let _: &mut bool = b; +} diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr new file mode 100644 index 00000000000..964e9f36596 --- /dev/null +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_ref_mut_inside_and.stderr @@ -0,0 +1,43 @@ +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:8:31 + | +LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:13:31 + | +LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:21:15 + | +LL | let &pat!(x) = &mut 0; + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:19 + | +LL | let &(ref mut a, ref mut b) = &mut (true, false); + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:30 + | +LL | let &(ref mut a, ref mut b) = &mut (true, false); + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0596`.