From a56f9ad574773c06c511b0caee89382494ee24db Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 2 Jan 2025 21:47:54 -0800 Subject: [PATCH 01/23] remove Rule 3 from `ref_pat_eat_one_layer_2024` The debug assertion ensuring that the pattern mutability cap holds assumes the presence of Rule 3, so it now checks for that. I considered going back to only tracking the mutability cap when Rule 3 is present, but since the mutability cap is used in Rule 5's implementation too, the debug assertion would still need to check which typing rules are present. This also required some changes to tests: - `ref_pat_eat_one_layer_2021.rs` had a test for Rule 3; I'll be handling tests for earlier editions in a later commit, so as a stopgap I've #[cfg]ed it out. - One test case had to be moved from `well-typed-edition-2024.rs` to `borrowck-errors.rs` in order to get borrowck to run on it and emit an error. --- compiler/rustc_hir_typeck/src/pat.rs | 8 +++--- .../borrowck-errors.classic.stderr | 8 +++++- .../experimental/borrowck-errors.rs | 5 ++++ .../pattern-errors.classic.stderr | 26 +------------------ .../experimental/pattern-errors.rs | 4 +-- .../ref_pat_eat_one_layer_2021.rs | 2 ++ .../experimental/well-typed-edition-2024.rs | 3 --- 7 files changed, 22 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index cbd1db2ca2558..cf9921312d522 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -243,8 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn downgrade_mut_inside_shared(&self) -> bool { // NB: RFC 3627 proposes stabilizing Rule 3 in all editions. If we adopt the same behavior // across all editions, this may be removed. - self.tcx.features().ref_pat_eat_one_layer_2024() - || self.tcx.features().ref_pat_eat_one_layer_2024_structural() + self.tcx.features().ref_pat_eat_one_layer_2024_structural() } /// Experimental pattern feature: when do reference patterns match against inherited references? @@ -425,7 +424,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { #[cfg(debug_assertions)] - if def_br == ByRef::Yes(Mutability::Mut) && max_ref_mutbl != MutblCap::Mut { + if def_br == ByRef::Yes(Mutability::Mut) + && max_ref_mutbl != MutblCap::Mut + && self.downgrade_mut_inside_shared() + { span_bug!(pat.span, "Pattern mutability cap violated!"); } match adjust_mode { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr index c62461140750b..f26151fe4f704 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr @@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | let &ref mut x = &0; | ^^^^^^^^^ cannot borrow as mutable -error: aborting due to 2 previous errors +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:17:23 + | +LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { + | ^ cannot borrow as mutable + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0507, E0596. For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index a01e9ca265760..79581936418af 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -13,4 +13,9 @@ pub fn main() { let &ref mut x = &0; //~^ cannot borrow data in a `&` reference as mutable [E0596] + + if let &Some(Some(x)) = &Some(&mut Some(0)) { + //[classic]~^ ERROR: cannot borrow data in a `&` reference as mutable + let _: &u32 = x; + } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr index 2bc3ecb7636d0..9b8a1e0ff39b0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr @@ -46,18 +46,6 @@ help: replace this `&mut` pattern with `&` LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:31:23 - | -LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - | ^^^^^ - | - = note: cannot match inherited `&` with `&mut` pattern -help: replace this `&mut` pattern with `&` - | -LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { - | ~ - error[E0308]: mismatched types --> $DIR/pattern-errors.rs:34:23 | @@ -70,18 +58,6 @@ help: replace this `&mut` pattern with `&` LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:37:29 - | -LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^ - | - = note: cannot match inherited `&` with `&mut` pattern -help: replace this `&mut` pattern with `&` - | -LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { - | ~ - error[E0308]: mismatched types --> $DIR/pattern-errors.rs:40:17 | @@ -106,6 +82,6 @@ help: replace this `&mut` pattern with `&` LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 3535ba9c7019a..f9cc8504d5547 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -29,13 +29,13 @@ pub fn main() { //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //~^ ERROR: mismatched types + //[structural]~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types } if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //~^ ERROR: mismatched types + //[structural]~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs index 9372049a2b283..ab3264704acc0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs @@ -6,9 +6,11 @@ #![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { + #[cfg(structural)] if let &Some(Some(x)) = &Some(&mut Some(0)) { let _: &u32 = x; } + if let Some(&x) = Some(&mut 0) { let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 077b52d8f274e..28e008a779b11 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -35,9 +35,6 @@ pub fn main() { if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { let _: &u32 = x; } - if let &Some(Some(x)) = &Some(&mut Some(0)) { - let _: &u32 = x; - } if let Some(&Some(&x)) = &Some(&mut Some(0)) { let _: u32 = x; } From c57708a58dbb7fbf3605dcc33d03d4e1d33747e3 Mon Sep 17 00:00:00 2001 From: dianne Date: Sat, 4 Jan 2025 01:38:17 -0800 Subject: [PATCH 02/23] add more tests where the rulesets disagree These come directly from the "Compare" tab of Typing Rust Patterns, though they had to be split across multiple files. They're not comprehensive, but they do provide some previously-missing coverage and are easier to check against the spec. Possibly they should be split up some more, since `pattern-errors.rs` is getting a bit unwieldy, but I'm not sure how best to go about that. --- .../borrowck-errors.classic.stderr | 52 ++- .../experimental/borrowck-errors.rs | 16 + .../pattern-errors.classic.stderr | 50 ++- .../experimental/pattern-errors.rs | 92 +++++ .../pattern-errors.structural.stderr | 319 +++++++++++++++++- .../ref-binding-on-inh-ref-errors.rs | 40 +++ ...inding-on-inh-ref-errors.structural.stderr | 74 ++++ ...ef-mut-inside-shared-ref-pat.classic.fixed | 4 + ...f-mut-inside-shared-ref-pat.classic.stderr | 10 +- .../ref-mut-inside-shared-ref-pat.rs | 4 + ...mut-inside-shared-ref-pat.structural.fixed | 4 + 11 files changed, 659 insertions(+), 6 deletions(-) create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr index f26151fe4f704..65b03f7a61096 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr @@ -25,7 +25,55 @@ error[E0596]: cannot borrow data in a `&` reference as mutable LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | ^ cannot borrow as mutable -error: aborting due to 3 previous errors +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:22:11 + | +LL | let &[x] = &&mut [0]; + | ^ cannot borrow as mutable + +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:26:16 + | +LL | let [&x] = &[&mut 0]; + | - ^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &[&mut 0]; + | +++ + +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:31:16 + | +LL | let [&x] = &mut [&mut 0]; + | - ^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &mut [&mut 0]; + | +++ + +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:34:20 + | +LL | let [&mut x] = &mut [&mut 0]; + | - ^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&mut ref x] = &mut [&mut 0]; + | +++ + +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0507, E0596. +Some errors have detailed explanations: E0507, E0508, E0596. For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 79581936418af..7645c145b6529 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -18,4 +18,20 @@ pub fn main() { //[classic]~^ ERROR: cannot borrow data in a `&` reference as mutable let _: &u32 = x; } + + let &[x] = &&mut [0]; + //[classic]~^ ERROR: cannot borrow data in a `&` reference as mutable + let _: &u32 = x; + + let [&x] = &[&mut 0]; + //[classic]~^ ERROR: cannot move out of type + let _: &u32 = x; + + #[cfg(classic)] // TODO: this should pass on `structural` but doesn't + let [&x] = &mut [&mut 0]; //[classic]~ ERROR: cannot move out of type + let _: &u32 = x; + + let [&mut x] = &mut [&mut 0]; + //[classic]~^ ERROR: cannot move out of type + let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr index 9b8a1e0ff39b0..fbb9a35443a2f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr @@ -82,6 +82,54 @@ help: replace this `&mut` pattern with `&` LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ -error: aborting due to 7 previous errors +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:119:10 + | +LL | let [&mut x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:124:10 + | +LL | let [&mut &x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:129:10 + | +LL | let [&mut &ref x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&ref x] = &[&mut 0]; + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:134:10 + | +LL | let [&mut &(mut x)] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&&(mut x)] = &[&mut 0]; + | ~ + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index f9cc8504d5547..b5e8bd112aa84 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -44,3 +44,95 @@ pub fn main() { //~^ ERROR: mismatched types } } + +// TODO: these should be mutability mismatches on `structural` +fn structural_errors_0() { + let &[&mut x] = &&mut [0]; + //[structural]~^ ERROR: mismatched types + let _: u32 = x; + //[structural]~^ ERROR: mismatched types + + let &[&mut x] = &mut &mut [0]; + //[structural]~^ ERROR: mismatched types + let _: u32 = x; + //[structural]~^ ERROR: mismatched types + + let &[&mut ref x] = &&mut [0]; + //[structural]~^ ERROR: mismatched types + let _: &u32 = x; + + let &[&mut ref x] = &mut &mut [0]; + //[structural]~^ ERROR: mismatched types + let _: &u32 = x; + + let &[&mut mut x] = &&mut [0]; + //[structural]~^ ERROR: mismatched types + //[structural]~| ERROR: binding cannot be both mutable and by-reference + let _: u32 = x; + //[structural]~^ ERROR: mismatched types + + let &[&mut mut x] = &mut &mut [0]; + //[structural]~^ ERROR: mismatched types + //[structural]~| ERROR: binding cannot be both mutable and by-reference + let _: u32 = x; + //[structural]~^ ERROR: mismatched types +} + +fn structural_errors_1() { + let [&(mut x)] = &[&0]; + //[structural]~^ ERROR: binding cannot be both mutable and by-reference + let _: &u32 = x; + + let [&(mut x)] = &mut [&0]; + //[structural]~^ ERROR: binding cannot be both mutable and by-reference + let _: &u32 = x; +} + +// TODO: these should be mutability mismatches on `structural` +fn structural_errors_2() { + let [&&mut x] = &[&mut 0]; + //[structural]~^ ERROR: mismatched types + let _: u32 = x; + //[structural]~^ ERROR: mismatched types + + let [&&mut x] = &mut [&mut 0]; + let _: u32 = x; + + let [&&mut ref x] = &[&mut 0]; + //[structural]~^ ERROR: mismatched types + let _: &u32 = x; + + let [&&mut ref x] = &mut [&mut 0]; + let _: &u32 = x; + + let [&&mut mut x] = &[&mut 0]; + //[structural]~^ ERROR: binding cannot be both mutable and by-reference + //[structural]~| ERROR: mismatched types + let _: u32 = x; + //[structural]~^ ERROR: mismatched types + + let [&&mut mut x] = &mut [&mut 0]; + let _: u32 = x; +} + +fn classic_errors_0() { + let [&mut x] = &[&mut 0]; + //[classic]~^ ERROR: mismatched types + //[classic]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let [&mut &x] = &[&mut 0]; + //[classic]~^ ERROR: mismatched types + //[classic]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; + + let [&mut &ref x] = &[&mut 0]; + //[classic]~^ ERROR: mismatched types + //[classic]~| cannot match inherited `&` with `&mut` pattern + let _: &u32 = x; + + let [&mut &(mut x)] = &[&mut 0]; + //[classic]~^ ERROR: mismatched types + //[classic]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr index 59d65553fae8f..4eabb8b1b0a39 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr @@ -84,6 +84,321 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) { = note: expected enum `Option<{integer}>` found mutable reference `&mut _` -error: aborting due to 7 previous errors +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:50:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:50:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut x] = &&mut [0]; +LL + let &[x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:52:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:55:11 + | +LL | let &[&mut x] = &mut &mut [0]; + | ^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:55:11 + | +LL | let &[&mut x] = &mut &mut [0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut x] = &mut &mut [0]; +LL + let &[x] = &mut &mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:57:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:60:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:60:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut ref x] = &&mut [0]; +LL + let &[ref x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:64:11 + | +LL | let &[&mut ref x] = &mut &mut [0]; + | ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:64:11 + | +LL | let &[&mut ref x] = &mut &mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut ref x] = &mut &mut [0]; +LL + let &[ref x] = &mut &mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:68:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:68:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut mut x] = &&mut [0]; +LL + let &[mut x] = &&mut [0]; + | + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:68:16 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:71:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:74:11 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:74:11 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut mut x] = &mut &mut [0]; +LL + let &[mut x] = &mut &mut [0]; + | + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:74:16 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:77:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:82:12 + | +LL | let [&(mut x)] = &[&0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:86:12 + | +LL | let [&(mut x)] = &mut [&0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:93:11 + | +LL | let [&&mut x] = &[&mut 0]; + | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut x] = &[&mut 0]; +LL + let [&x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:95:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:101:11 + | +LL | let [&&mut ref x] = &[&mut 0]; + | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut ref x] = &[&mut 0]; +LL + let [&ref x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:108:11 + | +LL | let [&&mut mut x] = &[&mut 0]; + | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut mut x] = &[&mut 0]; +LL + let [&mut x] = &[&mut 0]; + | + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:108:16 + | +LL | let [&&mut mut x] = &[&mut 0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:111:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error: aborting due to 27 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs new file mode 100644 index 0000000000000..3b27aa0f6ac45 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -0,0 +1,40 @@ +//@ edition: 2024 +//@ revisions: classic structural +//@[classic] run-pass +//! Tests for errors from binding with `ref x` under a by-ref default binding mode. These can't be +//! in the same body as tests for other errors, since they're emitted during THIR construction. +#![allow(incomplete_features)] +#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] + +pub fn main() { + let [&ref x] = &[&0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &&u32 = x; + + let [&ref x] = &[&mut 0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &&mut u32 = x; + + let [&ref x] = &mut [&0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &&u32 = x; + + let [&ref x] = &mut [&mut 0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &&mut u32 = x; + + let [&mut ref x] = &mut [&mut 0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &&mut u32 = x; + + let [&mut ref mut x] = &mut [&mut 0]; + //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic)] let _: &mut &mut u32 = x; +} diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr new file mode 100644 index 0000000000000..a952f72f08e9f --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr @@ -0,0 +1,74 @@ +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:11:11 + | +LL | let [&ref x] = &[&0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&ref x] = &[&0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:16:11 + | +LL | let [&ref x] = &[&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&ref x] = &[&mut 0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11 + | +LL | let [&ref x] = &mut [&0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&ref x] = &mut [&0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:26:11 + | +LL | let [&ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&ref x] = &mut [&mut 0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:31:15 + | +LL | let [&mut ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&mut ref x] = &mut [&mut 0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:36:15 + | +LL | let [&mut ref mut x] = &mut [&mut 0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [&mut ref mut x] = &mut [&mut 0]; + | ++++ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed index 4f4941975d804..c7216d06bb715 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed @@ -30,4 +30,8 @@ pub fn main() { //~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; + + let &mut [x] = &mut &mut [0]; + //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr index 6c384a51fac14..42a4a8597f7a0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr @@ -38,6 +38,14 @@ LL | let &(ref mut a, ref mut b) = &mut (true, false); | | | help: replace this `&` with `&mut`: `&mut` -error: aborting due to 5 previous errors +error[E0596]: cannot borrow as mutable inside an `&` pattern + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:11 + | +LL | let &[x] = &mut &mut [0]; + | - ^ + | | + | help: replace this `&` with `&mut`: `&mut` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs index b29bff7603f7a..138de4f8eac82 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs @@ -30,4 +30,8 @@ pub fn main() { //~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; + + let &[x] = &mut &mut [0]; + //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed index 4f4941975d804..24fb99ae0299f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed @@ -30,4 +30,8 @@ pub fn main() { //~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; + + let &[x] = &mut &mut [0]; + //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + let _: &u32 = x; } From c03769524bc52b0761385cab4b0a5c5e8fd96bd7 Mon Sep 17 00:00:00 2001 From: dianne Date: Sat, 4 Jan 2025 22:01:01 -0800 Subject: [PATCH 03/23] "structural" ruleset: account for dbm mutability cap in Deref(EatInner) rules --- compiler/rustc_hir_typeck/src/pat.rs | 7 +- .../borrowck-errors.classic.stderr | 2 +- .../experimental/borrowck-errors.rs | 4 +- .../pattern-errors.classic.stderr | 8 +- .../experimental/pattern-errors.rs | 6 ++ .../pattern-errors.structural.stderr | 98 ++++++++++++++++++- 6 files changed, 112 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index cf9921312d522..1cbeb6d1fd00f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2344,7 +2344,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { InheritedRefMatchRule::EatInner => { if let ty::Ref(_, _, r_mutbl) = *expected.kind() { // Match against the reference type; don't consume the inherited ref. - pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl); + // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref + // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing + // ruleset with Rule 4 but not Rule 3, we'll need to check that here. + debug_assert!(self.downgrade_mut_inside_shared()); + let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl()); + pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap); } else { // The expected type isn't a reference, so match against the inherited ref. if pat_mutbl > inh_mut { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr index 65b03f7a61096..d72539eeeb2fc 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr @@ -46,7 +46,7 @@ LL | let [&ref x] = &[&mut 0]; | +++ error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:31:16 + --> $DIR/borrowck-errors.rs:30:16 | LL | let [&x] = &mut [&mut 0]; | - ^^^^^^^^^^^^^ cannot move out of here diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 7645c145b6529..60f3a1dc18c47 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -27,8 +27,8 @@ pub fn main() { //[classic]~^ ERROR: cannot move out of type let _: &u32 = x; - #[cfg(classic)] // TODO: this should pass on `structural` but doesn't - let [&x] = &mut [&mut 0]; //[classic]~ ERROR: cannot move out of type + let [&x] = &mut [&mut 0]; + //[classic]~^ ERROR: cannot move out of type let _: &u32 = x; let [&mut x] = &mut [&mut 0]; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr index fbb9a35443a2f..939eb4ea430e4 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr @@ -83,7 +83,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:119:10 + --> $DIR/pattern-errors.rs:125:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:124:10 + --> $DIR/pattern-errors.rs:130:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:129:10 + --> $DIR/pattern-errors.rs:135:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -119,7 +119,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:134:10 + --> $DIR/pattern-errors.rs:140:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index b5e8bd112aa84..90f77df871dd9 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -96,13 +96,16 @@ fn structural_errors_2() { //[structural]~^ ERROR: mismatched types let [&&mut x] = &mut [&mut 0]; + //[structural]~^ ERROR: mismatched types let _: u32 = x; + //[structural]~^ ERROR: mismatched types let [&&mut ref x] = &[&mut 0]; //[structural]~^ ERROR: mismatched types let _: &u32 = x; let [&&mut ref x] = &mut [&mut 0]; + //[structural]~^ ERROR: mismatched types let _: &u32 = x; let [&&mut mut x] = &[&mut 0]; @@ -112,7 +115,10 @@ fn structural_errors_2() { //[structural]~^ ERROR: mismatched types let [&&mut mut x] = &mut [&mut 0]; + //[structural]~^ ERROR: binding cannot be both mutable and by-reference + //[structural]~| ERROR: mismatched types let _: u32 = x; + //[structural]~^ ERROR: mismatched types } fn classic_errors_0() { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr index 4eabb8b1b0a39..ed7e09c937a62 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr @@ -342,7 +342,38 @@ LL | let _: u32 = *x; | + error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:101:11 + --> $DIR/pattern-errors.rs:98:11 + | +LL | let [&&mut x] = &mut [&mut 0]; + | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut x] = &mut [&mut 0]; +LL + let [&x] = &mut [&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:100:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:103:11 | LL | let [&&mut ref x] = &[&mut 0]; | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` @@ -358,7 +389,23 @@ LL + let [&ref x] = &[&mut 0]; | error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:108:11 + --> $DIR/pattern-errors.rs:107:11 + | +LL | let [&&mut ref x] = &mut [&mut 0]; + | ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut ref x] = &mut [&mut 0]; +LL + let [&ref x] = &mut [&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:111:11 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` @@ -374,7 +421,7 @@ LL + let [&mut x] = &[&mut 0]; | error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:108:16 + --> $DIR/pattern-errors.rs:111:16 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^ @@ -384,7 +431,48 @@ LL | let [&&mut mut x] = &[&mut 0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:111:18 + --> $DIR/pattern-errors.rs:114:18 + | +LL | let _: u32 = x; + | --- ^ expected `u32`, found `&_` + | | + | expected due to this + | + = note: expected type `u32` + found reference `&_` +help: consider dereferencing the borrow + | +LL | let _: u32 = *x; + | + + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:117:11 + | +LL | let [&&mut mut x] = &mut [&mut 0]; + | ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +help: consider removing `&mut` from the pattern + | +LL - let [&&mut mut x] = &mut [&mut 0]; +LL + let [&mut x] = &mut [&mut 0]; + | + +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/pattern-errors.rs:117:16 + | +LL | let [&&mut mut x] = &mut [&mut 0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:120:18 | LL | let _: u32 = x; | --- ^ expected `u32`, found `&_` @@ -398,7 +486,7 @@ help: consider dereferencing the borrow LL | let _: u32 = *x; | + -error: aborting due to 27 previous errors +error: aborting due to 33 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. From f8315ae3b586fcd476e3dafd85b5891ddc70cc33 Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 5 Jan 2025 19:42:26 -0800 Subject: [PATCH 04/23] "structural" ruleset: use the "classic" ruleset's diagnostic and fallback for inherited ref mutability mismatches I think the diagnostic could use some work, but it's more helpful than the alternative. The previous error was misleading, since it ignored the inherited reference altogether. --- compiler/rustc_hir_typeck/src/pat.rs | 58 +-- .../pattern-errors.classic.stderr | 8 +- .../experimental/pattern-errors.rs | 30 +- .../pattern-errors.structural.stderr | 437 ++++-------------- 4 files changed, 151 insertions(+), 382 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 1cbeb6d1fd00f..ba5ba7a745271 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2318,22 +2318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // (RFC 3627, Rule 5). If we implement a pattern typing ruleset with Rule 4E // but not Rule 5, we'll need to check that here. debug_assert!(ref_pat_matches_mut_ref); - let err_msg = "mismatched types"; - let err = if let Some(span) = pat_prefix_span { - let mut err = self.dcx().struct_span_err(span, err_msg); - err.code(E0308); - err.note("cannot match inherited `&` with `&mut` pattern"); - err.span_suggestion_verbose( - span, - "replace this `&mut` pattern with `&`", - "&", - Applicability::MachineApplicable, - ); - err - } else { - self.dcx().struct_span_err(pat.span, err_msg) - }; - err.emit(); + self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span); } pat_info.binding_mode = ByRef::No; @@ -2353,22 +2338,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { // The expected type isn't a reference, so match against the inherited ref. if pat_mutbl > inh_mut { - // We can't match an inherited shared reference with `&mut`. This will - // be a type error later, since we're matching a reference pattern - // against a non-reference type. + // We can't match an inherited shared reference with `&mut`. // NB: This assumes that `&` patterns can match against mutable // references (RFC 3627, Rule 5). If we implement a pattern typing // ruleset with Rule 4 but not Rule 5, we'll need to check that here. debug_assert!(ref_pat_matches_mut_ref); - } else { - pat_info.binding_mode = ByRef::No; - self.typeck_results - .borrow_mut() - .skipped_ref_pats_mut() - .insert(pat.hir_id); - self.check_pat(inner, expected, pat_info); - return expected; + self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span); } + + pat_info.binding_mode = ByRef::No; + self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; } } InheritedRefMatchRule::EatBoth => { @@ -2442,6 +2423,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ty::new_ref(self.tcx, region, ty, mutbl) } + fn error_inherited_ref_mutability_mismatch( + &self, + pat: &'tcx Pat<'tcx>, + pat_prefix_span: Option, + ) -> ErrorGuaranteed { + let err_msg = "mismatched types"; + let err = if let Some(span) = pat_prefix_span { + let mut err = self.dcx().struct_span_err(span, err_msg); + err.code(E0308); + err.note("cannot match inherited `&` with `&mut` pattern"); + err.span_suggestion_verbose( + span, + "replace this `&mut` pattern with `&`", + "&", + Applicability::MachineApplicable, + ); + err + } else { + self.dcx().struct_span_err(pat.span, err_msg) + }; + err.emit() + } + fn try_resolve_slice_ty_to_array_ty( &self, before: &'tcx [Pat<'tcx>], diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr index 939eb4ea430e4..6993e724be2c4 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr @@ -83,7 +83,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:125:10 + --> $DIR/pattern-errors.rs:123:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:130:10 + --> $DIR/pattern-errors.rs:128:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:135:10 + --> $DIR/pattern-errors.rs:133:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -119,7 +119,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:140:10 + --> $DIR/pattern-errors.rs:138:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 90f77df871dd9..bbaa717e8bddf 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -45,37 +45,36 @@ pub fn main() { } } -// TODO: these should be mutability mismatches on `structural` fn structural_errors_0() { let &[&mut x] = &&mut [0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types let &[&mut x] = &mut &mut [0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types let &[&mut ref x] = &&mut [0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut ref x] = &mut &mut [0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut mut x] = &&mut [0]; //[structural]~^ ERROR: mismatched types - //[structural]~| ERROR: binding cannot be both mutable and by-reference + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types let &[&mut mut x] = &mut &mut [0]; //[structural]~^ ERROR: mismatched types - //[structural]~| ERROR: binding cannot be both mutable and by-reference + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types } fn structural_errors_1() { @@ -88,37 +87,36 @@ fn structural_errors_1() { let _: &u32 = x; } -// TODO: these should be mutability mismatches on `structural` fn structural_errors_2() { let [&&mut x] = &[&mut 0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types let [&&mut x] = &mut [&mut 0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; - //[structural]~^ ERROR: mismatched types let [&&mut ref x] = &[&mut 0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut ref x] = &mut [&mut 0]; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut mut x] = &[&mut 0]; - //[structural]~^ ERROR: binding cannot be both mutable and by-reference - //[structural]~| ERROR: mismatched types - let _: u32 = x; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; let [&&mut mut x] = &mut [&mut 0]; - //[structural]~^ ERROR: binding cannot be both mutable and by-reference - //[structural]~| ERROR: mismatched types - let _: u32 = x; //[structural]~^ ERROR: mismatched types + //[structural]~| cannot match inherited `&` with `&mut` pattern + let _: u32 = x; } fn classic_errors_0() { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr index ed7e09c937a62..d835a3abe3745 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr @@ -33,265 +33,136 @@ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:31:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:34:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:37:29 | LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^^ ------------------------- this expression has type `&Option>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:40:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` + | ^^^^^ | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:43:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` - | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:50:11 + | ^^^^^ | -LL | let &[&mut x] = &&mut [0]; - | ^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:50:11 - | -LL | let &[&mut x] = &&mut [0]; - | ^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let &[&mut x] = &&mut [0]; -LL + let &[x] = &&mut [0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:52:18 + --> $DIR/pattern-errors.rs:49:11 | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this +LL | let &[&mut x] = &&mut [0]; + | ^^^^^ | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | -LL | let _: u32 = *x; - | + +LL | let &[&x] = &&mut [0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:55:11 - | -LL | let &[&mut x] = &mut &mut [0]; - | ^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:55:11 + --> $DIR/pattern-errors.rs:54:11 | LL | let &[&mut x] = &mut &mut [0]; - | ^^^^^^ -help: consider removing `&mut` from the pattern + | ^^^^^ | -LL - let &[&mut x] = &mut &mut [0]; -LL + let &[x] = &mut &mut [0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let &[&x] = &mut &mut [0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:57:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this - | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:60:11 + --> $DIR/pattern-errors.rs:59:11 | LL | let &[&mut ref x] = &&mut [0]; - | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:60:11 - | -LL | let &[&mut ref x] = &&mut [0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let &[&mut ref x] = &&mut [0]; -LL + let &[ref x] = &&mut [0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let &[&ref x] = &&mut [0]; + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:64:11 | LL | let &[&mut ref x] = &mut &mut [0]; - | ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:64:11 - | -LL | let &[&mut ref x] = &mut &mut [0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern + | ^^^^^ | -LL - let &[&mut ref x] = &mut &mut [0]; -LL + let &[ref x] = &mut &mut [0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let &[&ref x] = &mut &mut [0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:68:11 - | -LL | let &[&mut mut x] = &&mut [0]; - | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:68:11 - | -LL | let &[&mut mut x] = &&mut [0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let &[&mut mut x] = &&mut [0]; -LL + let &[mut x] = &&mut [0]; - | - -error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:68:16 + --> $DIR/pattern-errors.rs:69:11 | LL | let &[&mut mut x] = &&mut [0]; - | ^^^^ - | - = note: see issue #123076 for more information - = help: add `#![feature(mut_ref)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:71:18 + | ^^^^^ | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + +LL | let &[&mut x] = &&mut [0]; + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:74:11 | LL | let &[&mut mut x] = &mut &mut [0]; - | ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:74:11 - | -LL | let &[&mut mut x] = &mut &mut [0]; - | ^^^^^^^^^^ -help: consider removing `&mut` from the pattern - | -LL - let &[&mut mut x] = &mut &mut [0]; -LL + let &[mut x] = &mut &mut [0]; - | - -error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:74:16 + | ^^^^^ | -LL | let &[&mut mut x] = &mut &mut [0]; - | ^^^^ + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | - = note: see issue #123076 for more information - = help: add `#![feature(mut_ref)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:77:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this - | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + +LL | let &[&mut x] = &mut &mut [0]; + | ~ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:82:12 + --> $DIR/pattern-errors.rs:81:12 | LL | let [&(mut x)] = &[&0]; | ^^^^ @@ -301,7 +172,7 @@ LL | let [&(mut x)] = &[&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:86:12 + --> $DIR/pattern-errors.rs:85:12 | LL | let [&(mut x)] = &mut [&0]; | ^^^^ @@ -311,182 +182,78 @@ LL | let [&(mut x)] = &mut [&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:93:11 + --> $DIR/pattern-errors.rs:91:11 | LL | let [&&mut x] = &[&mut 0]; - | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern - | -LL - let [&&mut x] = &[&mut 0]; -LL + let [&x] = &[&mut 0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let [&&x] = &[&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:95:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this - | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:98:11 + --> $DIR/pattern-errors.rs:96:11 | LL | let [&&mut x] = &mut [&mut 0]; - | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern + | ^^^^^ | -LL - let [&&mut x] = &mut [&mut 0]; -LL + let [&x] = &mut [&mut 0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let [&&x] = &mut [&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:100:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this - | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:103:11 + --> $DIR/pattern-errors.rs:101:11 | LL | let [&&mut ref x] = &[&mut 0]; - | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern - | -LL - let [&&mut ref x] = &[&mut 0]; -LL + let [&ref x] = &[&mut 0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let [&&ref x] = &[&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:107:11 + --> $DIR/pattern-errors.rs:106:11 | LL | let [&&mut ref x] = &mut [&mut 0]; - | ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern - | -LL - let [&&mut ref x] = &mut [&mut 0]; -LL + let [&ref x] = &mut [&mut 0]; + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | +LL | let [&&ref x] = &mut [&mut 0]; + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:111:11 | LL | let [&&mut mut x] = &[&mut 0]; - | ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern - | -LL - let [&&mut mut x] = &[&mut 0]; -LL + let [&mut x] = &[&mut 0]; - | - -error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:111:16 - | -LL | let [&&mut mut x] = &[&mut 0]; - | ^^^^ - | - = note: see issue #123076 for more information - = help: add `#![feature(mut_ref)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:114:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this + | ^^^^^ | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | -LL | let _: u32 = *x; - | + +LL | let [&&mut x] = &[&mut 0]; + | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:117:11 - | -LL | let [&&mut mut x] = &mut [&mut 0]; - | ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -help: consider removing `&mut` from the pattern - | -LL - let [&&mut mut x] = &mut [&mut 0]; -LL + let [&mut x] = &mut [&mut 0]; - | - -error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:117:16 + --> $DIR/pattern-errors.rs:116:11 | LL | let [&&mut mut x] = &mut [&mut 0]; - | ^^^^ + | ^^^^^ | - = note: see issue #123076 for more information - = help: add `#![feature(mut_ref)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:120:18 - | -LL | let _: u32 = x; - | --- ^ expected `u32`, found `&_` - | | - | expected due to this + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | - = note: expected type `u32` - found reference `&_` -help: consider dereferencing the borrow - | -LL | let _: u32 = *x; - | + +LL | let [&&mut x] = &mut [&mut 0]; + | ~ -error: aborting due to 33 previous errors +error: aborting due to 21 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. From 586ff158a25f421983be7b9f41437a73e56ef3cc Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 13 Jan 2025 00:07:16 -0800 Subject: [PATCH 05/23] "structural" ruleset: match against the inherited ref when a reference pattern doesn't match the mutability of an inner reference This is the `Deref(EatInner, FallbackToOuter)` rule in Typing Rust Patterns. --- compiler/rustc_hir_typeck/src/pat.rs | 13 +++- .../pattern-errors.classic.stderr | 22 +++--- .../experimental/pattern-errors.rs | 5 -- .../pattern-errors.structural.stderr | 71 +++++++------------ .../experimental/well-typed-edition-2024.rs | 25 ++++++- 5 files changed, 72 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ba5ba7a745271..992ab8cefc0fc 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2327,8 +2327,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return expected; } InheritedRefMatchRule::EatInner => { - if let ty::Ref(_, _, r_mutbl) = *expected.kind() { + if let ty::Ref(_, _, r_mutbl) = *expected.kind() + && pat_mutbl <= r_mutbl + { // Match against the reference type; don't consume the inherited ref. + // NB: The check for compatible pattern and ref type mutability assumes that + // `&` patterns can match against mutable references (RFC 3627, Rule 5). If + // we implement a pattern typing ruleset with Rule 4 (including the fallback + // to matching the inherited ref when the inner ref can't match) but not + // Rule 5, we'll need to check that here. + debug_assert!(ref_pat_matches_mut_ref); // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing // ruleset with Rule 4 but not Rule 3, we'll need to check that here. @@ -2336,7 +2344,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl()); pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap); } else { - // The expected type isn't a reference, so match against the inherited ref. + // The reference pattern can't match against the expected type, so try + // matching against the inherited ref instead. if pat_mutbl > inh_mut { // We can't match an inherited shared reference with `&mut`. // NB: This assumes that `&` patterns can match against mutable diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr index 6993e724be2c4..45ee489c52065 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:15:17 + --> $DIR/pattern-errors.rs:10:17 | LL | if let Some(&mut x) = &Some(&mut 0) { | ^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(&x) = &Some(&mut 0) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:19:17 + --> $DIR/pattern-errors.rs:14:17 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:23:22 + --> $DIR/pattern-errors.rs:18:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:28:17 + --> $DIR/pattern-errors.rs:23:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -47,7 +47,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 + --> $DIR/pattern-errors.rs:29:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -59,7 +59,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:40:17 + --> $DIR/pattern-errors.rs:35:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -71,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:43:17 + --> $DIR/pattern-errors.rs:38:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -83,7 +83,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:123:10 + --> $DIR/pattern-errors.rs:118:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:128:10 + --> $DIR/pattern-errors.rs:123:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:133:10 + --> $DIR/pattern-errors.rs:128:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -119,7 +119,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:138:10 + --> $DIR/pattern-errors.rs:133:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index bbaa717e8bddf..1e170b7d3f8e7 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -7,11 +7,6 @@ #![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { - if let Some(&mut x) = &mut Some(&0) { - //[structural]~^ ERROR: mismatched types - let _: &u32 = x; - } - if let Some(&mut x) = &Some(&mut 0) { //[classic]~^ ERROR: mismatched types let _: &u32 = x; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr index d835a3abe3745..3396d41481973 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr @@ -1,36 +1,17 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:10:17 + --> $DIR/pattern-errors.rs:23:17 | -LL | if let Some(&mut x) = &mut Some(&0) { - | ^^^^^^ ------------- this expression has type `&mut Option<&{integer}>` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/pattern-errors.rs:10:17 +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^ | -LL | if let Some(&mut x) = &mut Some(&0) { - | ^^^^^^ -help: consider removing `&mut` from the pattern + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` | -LL | if let Some(x) = &mut Some(&0) { +LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:28:17 - | -LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { - | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` - | | - | types differ in mutability - | - = note: expected reference `&Option<{integer}>` - found mutable reference `&mut _` - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:31:23 + --> $DIR/pattern-errors.rs:26:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { | ^^^^^ @@ -42,7 +23,7 @@ LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 + --> $DIR/pattern-errors.rs:29:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -54,7 +35,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:37:29 + --> $DIR/pattern-errors.rs:32:29 | LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { | ^^^^^ @@ -66,7 +47,7 @@ LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:40:17 + --> $DIR/pattern-errors.rs:35:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -78,7 +59,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:43:17 + --> $DIR/pattern-errors.rs:38:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -90,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:49:11 + --> $DIR/pattern-errors.rs:44:11 | LL | let &[&mut x] = &&mut [0]; | ^^^^^ @@ -102,7 +83,7 @@ LL | let &[&x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:54:11 + --> $DIR/pattern-errors.rs:49:11 | LL | let &[&mut x] = &mut &mut [0]; | ^^^^^ @@ -114,7 +95,7 @@ LL | let &[&x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:59:11 + --> $DIR/pattern-errors.rs:54:11 | LL | let &[&mut ref x] = &&mut [0]; | ^^^^^ @@ -126,7 +107,7 @@ LL | let &[&ref x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:64:11 + --> $DIR/pattern-errors.rs:59:11 | LL | let &[&mut ref x] = &mut &mut [0]; | ^^^^^ @@ -138,7 +119,7 @@ LL | let &[&ref x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:69:11 + --> $DIR/pattern-errors.rs:64:11 | LL | let &[&mut mut x] = &&mut [0]; | ^^^^^ @@ -150,7 +131,7 @@ LL | let &[&mut x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:74:11 + --> $DIR/pattern-errors.rs:69:11 | LL | let &[&mut mut x] = &mut &mut [0]; | ^^^^^ @@ -162,7 +143,7 @@ LL | let &[&mut x] = &mut &mut [0]; | ~ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:81:12 + --> $DIR/pattern-errors.rs:76:12 | LL | let [&(mut x)] = &[&0]; | ^^^^ @@ -172,7 +153,7 @@ LL | let [&(mut x)] = &[&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:85:12 + --> $DIR/pattern-errors.rs:80:12 | LL | let [&(mut x)] = &mut [&0]; | ^^^^ @@ -182,7 +163,7 @@ LL | let [&(mut x)] = &mut [&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:91:11 + --> $DIR/pattern-errors.rs:86:11 | LL | let [&&mut x] = &[&mut 0]; | ^^^^^ @@ -194,7 +175,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:96:11 + --> $DIR/pattern-errors.rs:91:11 | LL | let [&&mut x] = &mut [&mut 0]; | ^^^^^ @@ -206,7 +187,7 @@ LL | let [&&x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:101:11 + --> $DIR/pattern-errors.rs:96:11 | LL | let [&&mut ref x] = &[&mut 0]; | ^^^^^ @@ -218,7 +199,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:106:11 + --> $DIR/pattern-errors.rs:101:11 | LL | let [&&mut ref x] = &mut [&mut 0]; | ^^^^^ @@ -230,7 +211,7 @@ LL | let [&&ref x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:111:11 + --> $DIR/pattern-errors.rs:106:11 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^^ @@ -242,7 +223,7 @@ LL | let [&&mut x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:116:11 + --> $DIR/pattern-errors.rs:111:11 | LL | let [&&mut mut x] = &mut [&mut 0]; | ^^^^^ @@ -253,7 +234,7 @@ help: replace this `&mut` pattern with `&` LL | let [&&mut x] = &mut [&mut 0]; | ~ -error: aborting due to 21 previous errors +error: aborting due to 20 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 28e008a779b11..1db7abc473e7d 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -3,7 +3,7 @@ //@ run-pass //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests. -#![allow(incomplete_features)] +#![allow(incomplete_features, unused_mut)] #![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] #![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] @@ -53,4 +53,27 @@ pub fn main() { if let Some(&Some(x)) = &mut Some(Some(0)) { let _: u32 = x; } + + // Tests for eat-inner rulesets matching on the outer reference if matching on the inner + // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`: + let [&mut x] = &mut [&0]; + let _: &u32 = x; + + let [&mut ref x] = &mut [&0]; + let _: &&u32 = x; + + let [&mut ref mut x] = &mut [&0]; + let _: &mut &u32 = x; + + let [&mut mut x] = &mut [&0]; + let _: &u32 = x; + + let [&mut &x] = &mut [&0]; + let _: u32 = x; + + let [&mut &ref x] = &mut [&0]; + let _: &u32 = x; + + let [&mut &(mut x)] = &mut [&0]; + let _: u32 = x; } From 3f9b198dcbb09f189d6d2781401c526077f19fbe Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 15 Jan 2025 01:21:35 -0800 Subject: [PATCH 06/23] rename tests' revisions to allow testing multiple editions --- ...err => borrowck-errors.classic2024.stderr} | 0 .../experimental/borrowck-errors.rs | 16 ++-- ... => borrowck-errors.structural2024.stderr} | 0 ...tably-deref-shared-ref.classic2024.stderr} | 0 .../cannot-mutably-deref-shared-ref.rs | 6 +- ...ly-deref-shared-ref.structural2024.stderr} | 0 ....stderr => mut-ref-mut.classic2024.stderr} | 0 .../experimental/mut-ref-mut.rs | 6 +- ...derr => mut-ref-mut.structural2024.stderr} | 0 ...derr => pattern-errors.classic2024.stderr} | 0 .../experimental/pattern-errors.rs | 84 +++++++++---------- ...r => pattern-errors.structural2024.stderr} | 0 .../ref-binding-on-inh-ref-errors.rs | 44 +++++----- ...g-on-inh-ref-errors.structural2024.stderr} | 0 ...t-inside-shared-ref-pat.classic2024.fixed} | 8 +- ...-inside-shared-ref-pat.classic2024.stderr} | 0 .../ref-mut-inside-shared-ref-pat.rs | 8 +- ...nside-shared-ref-pat.structural2024.fixed} | 8 +- ...side-shared-ref-pat.structural2024.stderr} | 0 .../experimental/well-typed-edition-2024.rs | 6 +- 20 files changed, 93 insertions(+), 93 deletions(-) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{borrowck-errors.classic.stderr => borrowck-errors.classic2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{borrowck-errors.structural.stderr => borrowck-errors.structural2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{cannot-mutably-deref-shared-ref.classic.stderr => cannot-mutably-deref-shared-ref.classic2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{cannot-mutably-deref-shared-ref.structural.stderr => cannot-mutably-deref-shared-ref.structural2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{mut-ref-mut.classic.stderr => mut-ref-mut.classic2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{mut-ref-mut.structural.stderr => mut-ref-mut.structural2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{pattern-errors.classic.stderr => pattern-errors.classic2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{pattern-errors.structural.stderr => pattern-errors.structural2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{ref-binding-on-inh-ref-errors.structural.stderr => ref-binding-on-inh-ref-errors.structural2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{ref-mut-inside-shared-ref-pat.classic.fixed => ref-mut-inside-shared-ref-pat.classic2024.fixed} (79%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{ref-mut-inside-shared-ref-pat.classic.stderr => ref-mut-inside-shared-ref-pat.classic2024.stderr} (100%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{ref-mut-inside-shared-ref-pat.structural.fixed => ref-mut-inside-shared-ref-pat.structural2024.fixed} (79%) rename tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/{ref-mut-inside-shared-ref-pat.structural.stderr => ref-mut-inside-shared-ref-pat.structural2024.stderr} (100%) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 60f3a1dc18c47..9107d3ebf6ac3 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -1,9 +1,9 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Tests for pattern errors not handled by the pattern typing rules, but by borrowck. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&Some(x)) = Some(&Some(&mut 0)) { @@ -15,23 +15,23 @@ pub fn main() { //~^ cannot borrow data in a `&` reference as mutable [E0596] if let &Some(Some(x)) = &Some(&mut Some(0)) { - //[classic]~^ ERROR: cannot borrow data in a `&` reference as mutable + //[classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable let _: &u32 = x; } let &[x] = &&mut [0]; - //[classic]~^ ERROR: cannot borrow data in a `&` reference as mutable + //[classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable let _: &u32 = x; let [&x] = &[&mut 0]; - //[classic]~^ ERROR: cannot move out of type + //[classic2024]~^ ERROR: cannot move out of type let _: &u32 = x; let [&x] = &mut [&mut 0]; - //[classic]~^ ERROR: cannot move out of type + //[classic2024]~^ ERROR: cannot move out of type let _: &u32 = x; let [&mut x] = &mut [&mut 0]; - //[classic]~^ ERROR: cannot move out of type + //[classic2024]~^ ERROR: cannot move out of type let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs index e22bd1f8f6c99..a493b672c929f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.rs @@ -1,9 +1,9 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Test that `&mut` patterns don't match shared reference types under new typing rules in Rust 2024 #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { let &mut _ = &&0; diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/cannot-mutably-deref-shared-ref.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs index 786587984ba41..c2fb3f2870929 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs @@ -1,9 +1,9 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Test diagnostics for binding with `mut` when the default binding mode is by-ref. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { struct Foo(u8); diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 1e170b7d3f8e7..22ff0708d93a0 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -1,22 +1,22 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must //! be separate from cases caught by MIR borrowck or the latter errors may not be emitted. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&mut x) = &Some(&mut 0) { - //[classic]~^ ERROR: mismatched types + //[classic2024]~^ ERROR: mismatched types let _: &u32 = x; } if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { - //[classic]~^ ERROR: mismatched types + //[classic2024]~^ ERROR: mismatched types let _: u32 = x; } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { - //[classic]~^ ERROR: mismatched types + //[classic2024]~^ ERROR: mismatched types let _: &u32 = x; } @@ -24,13 +24,13 @@ pub fn main() { //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //[structural]~^ ERROR: mismatched types + //[structural2024]~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types } if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //[structural]~^ ERROR: mismatched types + //[structural2024]~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types @@ -42,96 +42,96 @@ pub fn main() { fn structural_errors_0() { let &[&mut x] = &&mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut x] = &mut &mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut ref x] = &&mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut ref x] = &mut &mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut mut x] = &&mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut mut x] = &mut &mut [0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } fn structural_errors_1() { let [&(mut x)] = &[&0]; - //[structural]~^ ERROR: binding cannot be both mutable and by-reference + //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference let _: &u32 = x; let [&(mut x)] = &mut [&0]; - //[structural]~^ ERROR: binding cannot be both mutable and by-reference + //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference let _: &u32 = x; } fn structural_errors_2() { let [&&mut x] = &[&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut x] = &mut [&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut ref x] = &[&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut ref x] = &mut [&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut mut x] = &[&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut mut x] = &mut [&mut 0]; - //[structural]~^ ERROR: mismatched types - //[structural]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } fn classic_errors_0() { let [&mut x] = &[&mut 0]; - //[classic]~^ ERROR: mismatched types - //[classic]~| cannot match inherited `&` with `&mut` pattern + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&mut &x] = &[&mut 0]; - //[classic]~^ ERROR: mismatched types - //[classic]~| cannot match inherited `&` with `&mut` pattern + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&mut &ref x] = &[&mut 0]; - //[classic]~^ ERROR: mismatched types - //[classic]~| cannot match inherited `&` with `&mut` pattern + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&mut &(mut x)] = &[&mut 0]; - //[classic]~^ ERROR: mismatched types - //[classic]~| cannot match inherited `&` with `&mut` pattern + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs index 3b27aa0f6ac45..de06489b9f810 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -1,40 +1,40 @@ //@ edition: 2024 -//@ revisions: classic structural -//@[classic] run-pass +//@ revisions: classic2024 structural2024 +//@[classic2024] run-pass //! Tests for errors from binding with `ref x` under a by-ref default binding mode. These can't be //! in the same body as tests for other errors, since they're emitted during THIR construction. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { let [&ref x] = &[&0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &&u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&u32 = x; let [&ref x] = &[&mut 0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &&mut u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; let [&ref x] = &mut [&0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &&u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&u32 = x; let [&ref x] = &mut [&mut 0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &&mut u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; let [&mut ref x] = &mut [&mut 0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &&mut u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; let [&mut ref mut x] = &mut [&mut 0]; - //[structural]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic)] let _: &mut &mut u32 = x; + //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &mut &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed similarity index 79% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed index c7216d06bb715..82c40878f493c 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed @@ -1,11 +1,11 @@ //@ edition: 2024 //@ run-rustfix -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { @@ -32,6 +32,6 @@ pub fn main() { let _: &mut bool = b; let &mut [x] = &mut &mut [0]; - //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs index 138de4f8eac82..62b9037fac4ca 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs @@ -1,11 +1,11 @@ //@ edition: 2024 //@ run-rustfix -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { @@ -32,6 +32,6 @@ pub fn main() { let _: &mut bool = b; let &[x] = &mut &mut [0]; - //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed similarity index 79% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed index 24fb99ae0299f..32e955db12ce6 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed @@ -1,11 +1,11 @@ //@ edition: 2024 //@ run-rustfix -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { @@ -32,6 +32,6 @@ pub fn main() { let _: &mut bool = b; let &[x] = &mut &mut [0]; - //[classic]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr similarity index 100% rename from tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural.stderr rename to tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 1db7abc473e7d..8a2593d0e3abe 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -1,11 +1,11 @@ //@ edition: 2024 -//@ revisions: classic structural +//@ revisions: classic2024 structural2024 //@ run-pass //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests. #![allow(incomplete_features, unused_mut)] -#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))] -#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))] +#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] +#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { From fdcbd7111b227193d4355b8072ff075d1e1df6d0 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 01:09:55 -0800 Subject: [PATCH 07/23] minor test cleanup - Removes some excess parens - Removes 3 duplicated tests --- .../pattern-errors.classic2024.stderr | 22 ++------ .../experimental/pattern-errors.rs | 5 +- .../pattern-errors.structural2024.stderr | 52 +++++++------------ .../experimental/well-typed-edition-2024.rs | 6 --- 4 files changed, 26 insertions(+), 59 deletions(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr index 45ee489c52065..cc39e9b8ab745 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr @@ -71,19 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:38:17 - | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^ - | - = note: cannot match inherited `&` with `&mut` pattern -help: replace this `&mut` pattern with `&` - | -LL | if let Some(&Some(x)) = &Some(Some(0)) { - | ~ - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:118:10 + --> $DIR/pattern-errors.rs:115:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -95,7 +83,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:123:10 + --> $DIR/pattern-errors.rs:120:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -107,7 +95,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:128:10 + --> $DIR/pattern-errors.rs:125:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -119,7 +107,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:133:10 + --> $DIR/pattern-errors.rs:130:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ @@ -130,6 +118,6 @@ help: replace this `&mut` pattern with `&` LL | let [&&(mut x)] = &[&mut 0]; | ~ -error: aborting due to 11 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 22ff0708d93a0..d1f404a634b8c 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -29,15 +29,12 @@ pub fn main() { if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types } - if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { + if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { //[structural2024]~^ ERROR: mismatched types } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types } - if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: mismatched types - } } fn structural_errors_0() { diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr index 3396d41481973..b996af4c13460 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr @@ -35,16 +35,16 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:32:29 + --> $DIR/pattern-errors.rs:32:28 | -LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^ +LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { + | ^^^^^ | = note: cannot match inherited `&` with `&mut` pattern help: replace this `&mut` pattern with `&` | -LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { - | ~ +LL | if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) { + | ~ error[E0308]: mismatched types --> $DIR/pattern-errors.rs:35:17 @@ -59,19 +59,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:38:17 - | -LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^ - | - = note: cannot match inherited `&` with `&mut` pattern -help: replace this `&mut` pattern with `&` - | -LL | if let Some(&Some(x)) = &Some(Some(0)) { - | ~ - -error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:44:11 + --> $DIR/pattern-errors.rs:41:11 | LL | let &[&mut x] = &&mut [0]; | ^^^^^ @@ -83,7 +71,7 @@ LL | let &[&x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:49:11 + --> $DIR/pattern-errors.rs:46:11 | LL | let &[&mut x] = &mut &mut [0]; | ^^^^^ @@ -95,7 +83,7 @@ LL | let &[&x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:54:11 + --> $DIR/pattern-errors.rs:51:11 | LL | let &[&mut ref x] = &&mut [0]; | ^^^^^ @@ -107,7 +95,7 @@ LL | let &[&ref x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:59:11 + --> $DIR/pattern-errors.rs:56:11 | LL | let &[&mut ref x] = &mut &mut [0]; | ^^^^^ @@ -119,7 +107,7 @@ LL | let &[&ref x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:64:11 + --> $DIR/pattern-errors.rs:61:11 | LL | let &[&mut mut x] = &&mut [0]; | ^^^^^ @@ -131,7 +119,7 @@ LL | let &[&mut x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:69:11 + --> $DIR/pattern-errors.rs:66:11 | LL | let &[&mut mut x] = &mut &mut [0]; | ^^^^^ @@ -143,7 +131,7 @@ LL | let &[&mut x] = &mut &mut [0]; | ~ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:76:12 + --> $DIR/pattern-errors.rs:73:12 | LL | let [&(mut x)] = &[&0]; | ^^^^ @@ -153,7 +141,7 @@ LL | let [&(mut x)] = &[&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:80:12 + --> $DIR/pattern-errors.rs:77:12 | LL | let [&(mut x)] = &mut [&0]; | ^^^^ @@ -163,7 +151,7 @@ LL | let [&(mut x)] = &mut [&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:86:11 + --> $DIR/pattern-errors.rs:83:11 | LL | let [&&mut x] = &[&mut 0]; | ^^^^^ @@ -175,7 +163,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:91:11 + --> $DIR/pattern-errors.rs:88:11 | LL | let [&&mut x] = &mut [&mut 0]; | ^^^^^ @@ -187,7 +175,7 @@ LL | let [&&x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:96:11 + --> $DIR/pattern-errors.rs:93:11 | LL | let [&&mut ref x] = &[&mut 0]; | ^^^^^ @@ -199,7 +187,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:101:11 + --> $DIR/pattern-errors.rs:98:11 | LL | let [&&mut ref x] = &mut [&mut 0]; | ^^^^^ @@ -211,7 +199,7 @@ LL | let [&&ref x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:106:11 + --> $DIR/pattern-errors.rs:103:11 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^^ @@ -223,7 +211,7 @@ LL | let [&&mut x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:111:11 + --> $DIR/pattern-errors.rs:108:11 | LL | let [&&mut mut x] = &mut [&mut 0]; | ^^^^^ @@ -234,7 +222,7 @@ help: replace this `&mut` pattern with `&` LL | let [&&mut x] = &mut [&mut 0]; | ~ -error: aborting due to 20 previous errors +error: aborting due to 19 previous errors Some errors have detailed explanations: E0308, E0658. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 8a2593d0e3abe..906110d1dce81 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -23,9 +23,6 @@ pub fn main() { if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { let _: u32 = x; } - if let Some(Some(&x)) = &Some(&Some(0)) { - let _: u32 = x; - } if let Some(&Some(&x)) = &mut Some(&Some(0)) { let _: u32 = x; } @@ -41,9 +38,6 @@ pub fn main() { if let Some(&Some(&x)) = &Some(&Some(0)) { let _: u32 = x; } - if let Some(&Some(&x)) = &Some(&mut Some(0)) { - let _: u32 = x; - } if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { let _: u32 = x; } From afd976b2b0382a91fba18f946a6272512895456a Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 00:50:44 -0800 Subject: [PATCH 08/23] add more information to old tests --- .../pattern-errors.classic2024.stderr | 18 ++++----- .../experimental/pattern-errors.rs | 8 ++++ .../pattern-errors.structural2024.stderr | 38 +++++++++---------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr index cc39e9b8ab745..7b1abb6eaac36 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr @@ -11,7 +11,7 @@ LL | if let Some(&x) = &Some(&mut 0) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:14:17 + --> $DIR/pattern-errors.rs:15:17 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:18:22 + --> $DIR/pattern-errors.rs:20:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:23:17 + --> $DIR/pattern-errors.rs:26:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -47,7 +47,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:29:23 + --> $DIR/pattern-errors.rs:34:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -59,7 +59,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:35:17 + --> $DIR/pattern-errors.rs:42:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -71,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:115:10 + --> $DIR/pattern-errors.rs:123:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -83,7 +83,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:120:10 + --> $DIR/pattern-errors.rs:128:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:125:10 + --> $DIR/pattern-errors.rs:133:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:130:10 + --> $DIR/pattern-errors.rs:138:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index d1f404a634b8c..14c32a053e319 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -9,31 +9,39 @@ pub fn main() { if let Some(&mut x) = &Some(&mut 0) { //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; } if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; } if let Some(&mut Some(&_)) = &Some(&Some(0)) { //~^ ERROR: mismatched types + //~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types + //~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { //[structural2024]~^ ERROR: mismatched types + //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types + //~| cannot match inherited `&` with `&mut` pattern } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr index b996af4c13460..05ff254ab9806 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:23:17 + --> $DIR/pattern-errors.rs:26:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:26:23 + --> $DIR/pattern-errors.rs:30:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:29:23 + --> $DIR/pattern-errors.rs:34:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:32:28 + --> $DIR/pattern-errors.rs:38:28 | LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { | ^^^^^ @@ -47,7 +47,7 @@ LL | if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:35:17 + --> $DIR/pattern-errors.rs:42:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -59,7 +59,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:41:11 + --> $DIR/pattern-errors.rs:49:11 | LL | let &[&mut x] = &&mut [0]; | ^^^^^ @@ -71,7 +71,7 @@ LL | let &[&x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:46:11 + --> $DIR/pattern-errors.rs:54:11 | LL | let &[&mut x] = &mut &mut [0]; | ^^^^^ @@ -83,7 +83,7 @@ LL | let &[&x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:51:11 + --> $DIR/pattern-errors.rs:59:11 | LL | let &[&mut ref x] = &&mut [0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let &[&ref x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:56:11 + --> $DIR/pattern-errors.rs:64:11 | LL | let &[&mut ref x] = &mut &mut [0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let &[&ref x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:61:11 + --> $DIR/pattern-errors.rs:69:11 | LL | let &[&mut mut x] = &&mut [0]; | ^^^^^ @@ -119,7 +119,7 @@ LL | let &[&mut x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:66:11 + --> $DIR/pattern-errors.rs:74:11 | LL | let &[&mut mut x] = &mut &mut [0]; | ^^^^^ @@ -131,7 +131,7 @@ LL | let &[&mut x] = &mut &mut [0]; | ~ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:73:12 + --> $DIR/pattern-errors.rs:81:12 | LL | let [&(mut x)] = &[&0]; | ^^^^ @@ -141,7 +141,7 @@ LL | let [&(mut x)] = &[&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:77:12 + --> $DIR/pattern-errors.rs:85:12 | LL | let [&(mut x)] = &mut [&0]; | ^^^^ @@ -151,7 +151,7 @@ LL | let [&(mut x)] = &mut [&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:83:11 + --> $DIR/pattern-errors.rs:91:11 | LL | let [&&mut x] = &[&mut 0]; | ^^^^^ @@ -163,7 +163,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:88:11 + --> $DIR/pattern-errors.rs:96:11 | LL | let [&&mut x] = &mut [&mut 0]; | ^^^^^ @@ -175,7 +175,7 @@ LL | let [&&x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:93:11 + --> $DIR/pattern-errors.rs:101:11 | LL | let [&&mut ref x] = &[&mut 0]; | ^^^^^ @@ -187,7 +187,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:98:11 + --> $DIR/pattern-errors.rs:106:11 | LL | let [&&mut ref x] = &mut [&mut 0]; | ^^^^^ @@ -199,7 +199,7 @@ LL | let [&&ref x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:103:11 + --> $DIR/pattern-errors.rs:111:11 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^^ @@ -211,7 +211,7 @@ LL | let [&&mut x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:108:11 + --> $DIR/pattern-errors.rs:116:11 | LL | let [&&mut mut x] = &mut [&mut 0]; | ^^^^^ From 4ed44c9bd6608bb945bedf69b91dbaa6bdf0c6b7 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 02:07:32 -0800 Subject: [PATCH 09/23] add a stable edition 2021 revision to pattern typing tests This serves two purposes. First, they're additional tests that stable Rust behavior hasn't been messed with. There's plenty of other pattern tests, so this is less important, but these at least are targeted at what's being changed. Second, this helps document exactly where the new rulesets agree and disagree with stable pattern typing. This will be especially important after the new rules for old editions are updated, since they need to be strictly more permissive; any patterns well-typed on stable should also be well-typed with the same resultant bindings on the (upcoming) new new old-edition rules. The unusual test ordering on `borrowck-errors.rs` and `ref-binding-on-inh-ref-errors.rs` are to hopefully reduce how much adding new tests will mess with line numbers in their stderr. --- .../borrowck-errors.classic2024.stderr | 70 ++--- .../experimental/borrowck-errors.rs | 37 ++- .../borrowck-errors.stable2021.stderr | 69 +++++ .../borrowck-errors.structural2024.stderr | 4 +- .../mut-ref-mut.classic2024.stderr | 4 +- .../experimental/mut-ref-mut.rs | 19 +- .../mut-ref-mut.structural2024.stderr | 4 +- .../pattern-errors.classic2024.stderr | 20 +- .../experimental/pattern-errors.rs | 84 ++++-- .../pattern-errors.stable2021.stderr | 283 ++++++++++++++++++ .../pattern-errors.structural2024.stderr | 38 +-- ...nding-on-inh-ref-errors.classic2024.stderr | 70 +++++ .../ref-binding-on-inh-ref-errors.rs | 53 +++- ...inding-on-inh-ref-errors.stable2021.stderr | 35 +++ ...ng-on-inh-ref-errors.structural2024.stderr | 44 +-- ...ut-inside-shared-ref-pat.classic2024.fixed | 26 +- ...t-inside-shared-ref-pat.classic2024.stderr | 12 +- .../ref-mut-inside-shared-ref-pat.rs | 26 +- ...ut-inside-shared-ref-pat.stable2021.stderr | 58 ++++ ...inside-shared-ref-pat.structural2024.fixed | 26 +- ...nside-shared-ref-pat.structural2024.stderr | 10 +- .../experimental/well-typed-edition-2024.rs | 49 ++- .../well-typed-edition-2024.stable2021.stderr | 260 ++++++++++++++++ 23 files changed, 1103 insertions(+), 198 deletions(-) create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr create mode 100644 tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr index d72539eeeb2fc..331b86736a0ba 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr @@ -1,5 +1,33 @@ +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:13:16 + | +LL | let [&x] = &[&mut 0]; + | - ^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &[&mut 0]; + | +++ + +error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:19:16 + | +LL | let [&x] = &mut [&mut 0]; + | - ^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let [&ref x] = &mut [&mut 0]; + | +++ + error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:9:29 + --> $DIR/borrowck-errors.rs:27:29 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ @@ -14,59 +42,31 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { | error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:14:10 + --> $DIR/borrowck-errors.rs:32:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:17:23 + --> $DIR/borrowck-errors.rs:35:23 | LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | ^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:22:11 + --> $DIR/borrowck-errors.rs:40:11 | LL | let &[x] = &&mut [0]; | ^ cannot borrow as mutable -error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:26:16 - | -LL | let [&x] = &[&mut 0]; - | - ^^^^^^^^^ cannot move out of here - | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding - | -LL | let [&ref x] = &[&mut 0]; - | +++ - -error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:30:16 - | -LL | let [&x] = &mut [&mut 0]; - | - ^^^^^^^^^^^^^ cannot move out of here - | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding - | -LL | let [&ref x] = &mut [&mut 0]; - | +++ - -error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:34:20 +error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array + --> $DIR/borrowck-errors.rs:44:20 | LL | let [&mut x] = &mut [&mut 0]; | - ^^^^^^^^^^^^^ cannot move out of here | | | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 9107d3ebf6ac3..3f5d9c8db5d87 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -1,10 +1,28 @@ -//@ edition: 2024 -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 //! Tests for pattern errors not handled by the pattern typing rules, but by borrowck. #![allow(incomplete_features)] #![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] #![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] +/// These patterns additionally use `&` to match a `&mut` reference type, which causes compilation +/// to fail in HIR typeck on stable. As such, they need to be separate from the other tests. +fn errors_caught_in_hir_typeck_on_stable() { + let [&x] = &[&mut 0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + //[classic2024]~^^^ ERROR: cannot move out of type + let _: &u32 = x; + + let [&x] = &mut [&mut 0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability + //[classic2024]~^^^ ERROR: cannot move out of type + let _: &u32 = x; +} + pub fn main() { if let Some(&Some(x)) = Some(&Some(&mut 0)) { //~^ ERROR: cannot move out of a shared reference [E0507] @@ -15,23 +33,16 @@ pub fn main() { //~^ cannot borrow data in a `&` reference as mutable [E0596] if let &Some(Some(x)) = &Some(&mut Some(0)) { - //[classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable + //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable let _: &u32 = x; } let &[x] = &&mut [0]; - //[classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable - let _: &u32 = x; - - let [&x] = &[&mut 0]; - //[classic2024]~^ ERROR: cannot move out of type - let _: &u32 = x; - - let [&x] = &mut [&mut 0]; - //[classic2024]~^ ERROR: cannot move out of type + //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable let _: &u32 = x; let [&mut x] = &mut [&mut 0]; //[classic2024]~^ ERROR: cannot move out of type - let _: &mut u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr new file mode 100644 index 0000000000000..65c98e2da9c38 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr @@ -0,0 +1,69 @@ +error[E0308]: mismatched types + --> $DIR/borrowck-errors.rs:13:10 + | +LL | let [&x] = &[&mut 0]; + | ^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&x] = &[&mut 0]; +LL + let [x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/borrowck-errors.rs:19:10 + | +LL | let [&x] = &mut [&mut 0]; + | ^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&x] = &mut [&mut 0]; +LL + let [x] = &mut [&mut 0]; + | + +error[E0507]: cannot move out of a shared reference + --> $DIR/borrowck-errors.rs:27:29 + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | - ^^^^^^^^^^^^^^^^^^^ + | | + | data moved here + | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { +LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { + | + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:10 + | +LL | let &ref mut x = &0; + | ^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:35:23 + | +LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:40:11 + | +LL | let &[x] = &&mut [0]; + | ^ cannot borrow as mutable + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0507, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr index c62461140750b..30d2f9f3d702f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:9:29 + --> $DIR/borrowck-errors.rs:27:29 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { | error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:14:10 + --> $DIR/borrowck-errors.rs:32:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ cannot borrow as mutable diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr index 43560a1803026..3849b4ed98948 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr @@ -1,5 +1,5 @@ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:11:13 + --> $DIR/mut-ref-mut.rs:14:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -9,7 +9,7 @@ LL | let Foo(mut a) = &Foo(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:15:13 + --> $DIR/mut-ref-mut.rs:19:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs index c2fb3f2870929..68d6871eabfa3 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs @@ -1,7 +1,10 @@ -//@ edition: 2024 -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[stable2021] run-pass //! Test diagnostics for binding with `mut` when the default binding mode is by-ref. -#![allow(incomplete_features)] +#![allow(incomplete_features, unused_assignments, unused_variables)] #![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] #![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] @@ -9,10 +12,12 @@ pub fn main() { struct Foo(u8); let Foo(mut a) = &Foo(0); - //~^ ERROR: binding cannot be both mutable and by-reference - a = &42; + //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] { a = 42 } + #[cfg(any(classic2024, structural2024))] { a = &42 } let Foo(mut a) = &mut Foo(0); - //~^ ERROR: binding cannot be both mutable and by-reference - a = &mut 42; + //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference + #[cfg(stable2021)] { a = 42 } + #[cfg(any(classic2024, structural2024))] { a = &mut 42 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr index 43560a1803026..3849b4ed98948 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr @@ -1,5 +1,5 @@ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:11:13 + --> $DIR/mut-ref-mut.rs:14:13 | LL | let Foo(mut a) = &Foo(0); | ^^^^ @@ -9,7 +9,7 @@ LL | let Foo(mut a) = &Foo(0); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/mut-ref-mut.rs:15:13 + --> $DIR/mut-ref-mut.rs:19:13 | LL | let Foo(mut a) = &mut Foo(0); | ^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr index 7b1abb6eaac36..3a124dcead52a 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:10:17 + --> $DIR/pattern-errors.rs:12:17 | LL | if let Some(&mut x) = &Some(&mut 0) { | ^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(&x) = &Some(&mut 0) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:15:17 + --> $DIR/pattern-errors.rs:18:17 | LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:20:22 + --> $DIR/pattern-errors.rs:24:22 | LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:26:17 + --> $DIR/pattern-errors.rs:31:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -47,7 +47,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 + --> $DIR/pattern-errors.rs:41:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -59,7 +59,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:42:17 + --> $DIR/pattern-errors.rs:51:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -71,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:123:10 + --> $DIR/pattern-errors.rs:147:10 | LL | let [&mut x] = &[&mut 0]; | ^^^^^ @@ -83,7 +83,7 @@ LL | let [&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:128:10 + --> $DIR/pattern-errors.rs:153:10 | LL | let [&mut &x] = &[&mut 0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:133:10 + --> $DIR/pattern-errors.rs:159:10 | LL | let [&mut &ref x] = &[&mut 0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:138:10 + --> $DIR/pattern-errors.rs:165:10 | LL | let [&mut &(mut x)] = &[&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs index 14c32a053e319..c07c2972cd055 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs @@ -1,5 +1,7 @@ -//@ edition: 2024 -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 //! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must //! be separate from cases caught by MIR borrowck or the latter errors may not be emitted. #![allow(incomplete_features)] @@ -10,69 +12,83 @@ pub fn main() { if let Some(&mut x) = &Some(&mut 0) { //[classic2024]~^ ERROR: mismatched types //[classic2024]~| cannot match inherited `&` with `&mut` pattern - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; } if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { - //[classic2024]~^ ERROR: mismatched types + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { //[classic2024]~^ ERROR: mismatched types //[classic2024]~| cannot match inherited `&` with `&mut` pattern - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; } if let Some(&mut Some(&_)) = &Some(&Some(0)) { //~^ ERROR: mismatched types - //~| cannot match inherited `&` with `&mut` pattern + //[stable2021]~| types differ in mutability + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { //~^ ERROR: mismatched types - //~| cannot match inherited `&` with `&mut` pattern + //[stable2021]~| expected integer, found `&mut _` + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` //[structural2024]~| cannot match inherited `&` with `&mut` pattern } if let Some(&mut Some(x)) = &Some(Some(0)) { //~^ ERROR: mismatched types - //~| cannot match inherited `&` with `&mut` pattern + //[stable2021]~| expected `Option<{integer}>`, found `&mut _` + //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern } } fn structural_errors_0() { let &[&mut x] = &&mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut x] = &mut &mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut ref x] = &&mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut ref x] = &mut &mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let &[&mut mut x] = &&mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&mut _` //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let &[&mut mut x] = &mut &mut [0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } @@ -80,41 +96,49 @@ fn structural_errors_0() { fn structural_errors_1() { let [&(mut x)] = &[&0]; //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(classic2024)] let _: &u32 = x; let [&(mut x)] = &mut [&0]; //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(classic2024)] let _: &u32 = x; } fn structural_errors_2() { let [&&mut x] = &[&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut ref x] = &[&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut ref x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&&mut mut x] = &[&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&&mut mut x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: mismatched types + //[stable2021,structural2024]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability //[structural2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } @@ -123,20 +147,24 @@ fn classic_errors_0() { let [&mut x] = &[&mut 0]; //[classic2024]~^ ERROR: mismatched types //[classic2024]~| cannot match inherited `&` with `&mut` pattern - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(structural2024)] let _: &u32 = x; let [&mut &x] = &[&mut 0]; - //[classic2024]~^ ERROR: mismatched types + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; let [&mut &ref x] = &[&mut 0]; - //[classic2024]~^ ERROR: mismatched types + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: &u32 = x; let [&mut &(mut x)] = &[&mut 0]; - //[classic2024]~^ ERROR: mismatched types + //[stable2021,classic2024]~^ ERROR: mismatched types + //[stable2021]~| expected integer, found `&_` //[classic2024]~| cannot match inherited `&` with `&mut` pattern let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr new file mode 100644 index 0000000000000..e7eb1813846e6 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr @@ -0,0 +1,283 @@ +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:18:27 + | +LL | if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { + | ^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&mut Some(x)) = &Some(&mut Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:31:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { + | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected reference `&Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:36:17 + | +LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { + | ^^^^^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:41:23 + | +LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { + | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:46:17 + | +LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { + | ^^^^^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected `Option<&mut Option<{integer}>>`, found `&_` + | + = note: expected enum `Option<&mut Option<{integer}>>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:51:17 + | +LL | if let Some(&mut Some(x)) = &Some(Some(0)) { + | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&mut _` + | + = note: expected enum `Option<{integer}>` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:59:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:59:11 + | +LL | let &[&mut x] = &&mut [0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut x] = &&mut [0]; +LL + let &[x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:65:9 + | +LL | let &[&mut x] = &mut &mut [0]; + | ^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:71:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:71:11 + | +LL | let &[&mut ref x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut ref x] = &&mut [0]; +LL + let &[ref x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:77:9 + | +LL | let &[&mut ref x] = &mut &mut [0]; + | ^^^^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:83:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/pattern-errors.rs:83:11 + | +LL | let &[&mut mut x] = &&mut [0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let &[&mut mut x] = &&mut [0]; +LL + let &[mut x] = &&mut [0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:89:9 + | +LL | let &[&mut mut x] = &mut &mut [0]; + | ^^^^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:109:10 + | +LL | let [&&mut x] = &[&mut 0]; + | ^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:115:10 + | +LL | let [&&mut x] = &mut [&mut 0]; + | ^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:121:10 + | +LL | let [&&mut ref x] = &[&mut 0]; + | ^^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:127:10 + | +LL | let [&&mut ref x] = &mut [&mut 0]; + | ^^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:133:10 + | +LL | let [&&mut mut x] = &[&mut 0]; + | ^^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:139:10 + | +LL | let [&&mut mut x] = &mut [&mut 0]; + | ^^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:153:15 + | +LL | let [&mut &x] = &[&mut 0]; + | ^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &x] = &[&mut 0]; +LL + let [&mut x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:159:15 + | +LL | let [&mut &ref x] = &[&mut 0]; + | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &ref x] = &[&mut 0]; +LL + let [&mut ref x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/pattern-errors.rs:165:15 + | +LL | let [&mut &(mut x)] = &[&mut 0]; + | ^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&mut &(mut x)] = &[&mut 0]; +LL + let [&mut mut x)] = &[&mut 0]; + | + +error: aborting due to 21 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr index 05ff254ab9806..861ed2216cd9b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:26:17 + --> $DIR/pattern-errors.rs:31:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { | ^^^^^ @@ -11,7 +11,7 @@ LL | if let Some(&Some(&_)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:30:23 + --> $DIR/pattern-errors.rs:36:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { | ^^^^^ @@ -23,7 +23,7 @@ LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:34:23 + --> $DIR/pattern-errors.rs:41:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { | ^^^^^ @@ -35,7 +35,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:38:28 + --> $DIR/pattern-errors.rs:46:28 | LL | if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) { | ^^^^^ @@ -47,7 +47,7 @@ LL | if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:42:17 + --> $DIR/pattern-errors.rs:51:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { | ^^^^^ @@ -59,7 +59,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:49:11 + --> $DIR/pattern-errors.rs:59:11 | LL | let &[&mut x] = &&mut [0]; | ^^^^^ @@ -71,7 +71,7 @@ LL | let &[&x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:54:11 + --> $DIR/pattern-errors.rs:65:11 | LL | let &[&mut x] = &mut &mut [0]; | ^^^^^ @@ -83,7 +83,7 @@ LL | let &[&x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:59:11 + --> $DIR/pattern-errors.rs:71:11 | LL | let &[&mut ref x] = &&mut [0]; | ^^^^^ @@ -95,7 +95,7 @@ LL | let &[&ref x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:64:11 + --> $DIR/pattern-errors.rs:77:11 | LL | let &[&mut ref x] = &mut &mut [0]; | ^^^^^ @@ -107,7 +107,7 @@ LL | let &[&ref x] = &mut &mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:69:11 + --> $DIR/pattern-errors.rs:83:11 | LL | let &[&mut mut x] = &&mut [0]; | ^^^^^ @@ -119,7 +119,7 @@ LL | let &[&mut x] = &&mut [0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:74:11 + --> $DIR/pattern-errors.rs:89:11 | LL | let &[&mut mut x] = &mut &mut [0]; | ^^^^^ @@ -131,7 +131,7 @@ LL | let &[&mut x] = &mut &mut [0]; | ~ error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:81:12 + --> $DIR/pattern-errors.rs:97:12 | LL | let [&(mut x)] = &[&0]; | ^^^^ @@ -141,7 +141,7 @@ LL | let [&(mut x)] = &[&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: binding cannot be both mutable and by-reference - --> $DIR/pattern-errors.rs:85:12 + --> $DIR/pattern-errors.rs:102:12 | LL | let [&(mut x)] = &mut [&0]; | ^^^^ @@ -151,7 +151,7 @@ LL | let [&(mut x)] = &mut [&0]; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:91:11 + --> $DIR/pattern-errors.rs:109:11 | LL | let [&&mut x] = &[&mut 0]; | ^^^^^ @@ -163,7 +163,7 @@ LL | let [&&x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:96:11 + --> $DIR/pattern-errors.rs:115:11 | LL | let [&&mut x] = &mut [&mut 0]; | ^^^^^ @@ -175,7 +175,7 @@ LL | let [&&x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:101:11 + --> $DIR/pattern-errors.rs:121:11 | LL | let [&&mut ref x] = &[&mut 0]; | ^^^^^ @@ -187,7 +187,7 @@ LL | let [&&ref x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:106:11 + --> $DIR/pattern-errors.rs:127:11 | LL | let [&&mut ref x] = &mut [&mut 0]; | ^^^^^ @@ -199,7 +199,7 @@ LL | let [&&ref x] = &mut [&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:111:11 + --> $DIR/pattern-errors.rs:133:11 | LL | let [&&mut mut x] = &[&mut 0]; | ^^^^^ @@ -211,7 +211,7 @@ LL | let [&&mut x] = &[&mut 0]; | ~ error[E0308]: mismatched types - --> $DIR/pattern-errors.rs:116:11 + --> $DIR/pattern-errors.rs:139:11 | LL | let [&&mut mut x] = &mut [&mut 0]; | ^^^^^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr new file mode 100644 index 0000000000000..70cdcbd62eb07 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr @@ -0,0 +1,70 @@ +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:60:10 + | +LL | let [&mut ref x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&ref x] = &[&mut 0]; + | ~ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref mut x] = &[0]; + | + + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 + | +LL | let [ref x] = &[0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref x] = &[0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 + | +LL | let [ref x] = &mut [0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref x] = &mut [0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref mut x] = &mut [0]; + | ++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs index de06489b9f810..a151c84739c17 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -1,40 +1,63 @@ -//@ edition: 2024 -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 //@[classic2024] run-pass -//! Tests for errors from binding with `ref x` under a by-ref default binding mode. These can't be -//! in the same body as tests for other errors, since they're emitted during THIR construction. +//! Tests for errors from binding with `ref x` under a by-ref default binding mode in edition 2024. +//! These can't be in the same body as tests for other errors, since they're emitted during THIR +//! construction. The errors on stable edition 2021 Rust are unrelated. #![allow(incomplete_features)] #![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))] #![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] -pub fn main() { +/// These only fail on the eat-inner variant of the new edition 2024 pattern typing rules. +/// The eat-outer variant eats the inherited reference, so binding with `ref` isn't a problem. +fn errors_from_eating_the_real_reference() { let [&ref x] = &[&0]; //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&u32 = x; - let [&ref x] = &[&mut 0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic2024)] let _: &&mut u32 = x; - let [&ref x] = &mut [&0]; //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&u32 = x; - let [&ref x] = &mut [&mut 0]; - //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 - //[structural2024]~| cannot override to bind by-reference when that is the implicit default - #[cfg(classic2024)] let _: &&mut u32 = x; - let [&mut ref x] = &mut [&mut 0]; //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; #[cfg(classic2024)] let _: &&mut u32 = x; let [&mut ref mut x] = &mut [&mut 0]; //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &mut u32 = x; #[cfg(classic2024)] let _: &mut &mut u32 = x; + + errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable(); +} + +/// To make absolutely sure binding with `ref` ignores inherited references on stable, let's +/// quarantine these typeck errors (from using a `&` pattern to match a `&mut` reference type). +fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() { + let [&ref x] = &[&mut 0]; + //[stable2021]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; + + let [&ref x] = &mut [&mut 0]; + //[stable2021]~^ ERROR: mismatched types + //[stable2021]~| types differ in mutability + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(classic2024)] let _: &&mut u32 = x; +} + +pub fn main() { + errors_from_eating_the_real_reference(); } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr new file mode 100644 index 0000000000000..c0518130368d7 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:46:10 + | +LL | let [&ref x] = &[&mut 0]; + | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&ref x] = &[&mut 0]; +LL + let [ref x] = &[&mut 0]; + | + +error[E0308]: mismatched types + --> $DIR/ref-binding-on-inh-ref-errors.rs:53:10 + | +LL | let [&ref x] = &mut [&mut 0]; + | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - let [&ref x] = &mut [&mut 0]; +LL + let [ref x] = &mut [&mut 0]; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index a952f72f08e9f..92aa8f1ea6853 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -1,5 +1,5 @@ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:11:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:16:11 | LL | let [&ref x] = &[&0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -11,63 +11,63 @@ LL | let &[&ref x] = &[&0]; | + error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:16:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:22:11 | -LL | let [&ref x] = &[&mut 0]; +LL | let [&ref x] = &mut [&0]; | ^^^ cannot override to bind by-reference when that is the implicit default | = note: for more information, see help: make the implied reference pattern explicit | -LL | let &[&ref x] = &[&mut 0]; - | + +LL | let &mut [&ref x] = &mut [&0]; + | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:28:15 | -LL | let [&ref x] = &mut [&0]; - | ^^^ cannot override to bind by-reference when that is the implicit default +LL | let [&mut ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default | = note: for more information, see help: make the implied reference pattern explicit | -LL | let &mut [&ref x] = &mut [&0]; +LL | let &mut [&mut ref x] = &mut [&mut 0]; | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:26:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:34:15 | -LL | let [&ref x] = &mut [&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default +LL | let [&mut ref mut x] = &mut [&mut 0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default | = note: for more information, see help: make the implied reference pattern explicit | -LL | let &mut [&ref x] = &mut [&mut 0]; +LL | let &mut [&mut ref mut x] = &mut [&mut 0]; | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:31:15 + --> $DIR/ref-binding-on-inh-ref-errors.rs:46:11 | -LL | let [&mut ref x] = &mut [&mut 0]; - | ^^^ cannot override to bind by-reference when that is the implicit default +LL | let [&ref x] = &[&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default | = note: for more information, see help: make the implied reference pattern explicit | -LL | let &mut [&mut ref x] = &mut [&mut 0]; - | ++++ +LL | let &[&ref x] = &[&mut 0]; + | + error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:36:15 + --> $DIR/ref-binding-on-inh-ref-errors.rs:53:11 | -LL | let [&mut ref mut x] = &mut [&mut 0]; - | ^^^^^^^ cannot override to bind by-reference when that is the implicit default +LL | let [&ref x] = &mut [&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default | = note: for more information, see help: make the implied reference pattern explicit | -LL | let &mut [&mut ref mut x] = &mut [&mut 0]; +LL | let &mut [&ref x] = &mut [&mut 0]; | ++++ error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed index 82c40878f493c..c01784d5076b7 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed @@ -1,6 +1,9 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] @@ -9,12 +12,14 @@ pub fn main() { if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; } @@ -22,16 +27,19 @@ pub fn main() { ($var:ident) => { ref mut $var }; } let &mut pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; let &mut [x] = &mut &mut [0]; - //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr index 42a4a8597f7a0..5e98b77be40cd 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31 | LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -7,7 +7,7 @@ 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-mut-inside-shared-ref-pat.rs:16:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31 | LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -15,7 +15,7 @@ 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-mut-inside-shared-ref-pat.rs:24:15 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15 | LL | let &pat!(x) = &mut 0; | - ^ @@ -23,7 +23,7 @@ LL | let &pat!(x) = &mut 0; | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ @@ -31,7 +31,7 @@ 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-mut-inside-shared-ref-pat.rs:28:30 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ @@ -39,7 +39,7 @@ 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-mut-inside-shared-ref-pat.rs:34:11 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:11 | LL | let &[x] = &mut &mut [0]; | - ^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs index 62b9037fac4ca..fe40dabb55394 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs @@ -1,6 +1,9 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] @@ -9,12 +12,14 @@ pub fn main() { if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; } @@ -22,16 +27,19 @@ pub fn main() { ($var:ident) => { ref mut $var }; } let &pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; let &[x] = &mut &mut [0]; - //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr new file mode 100644 index 0000000000000..72c6c05e18443 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr @@ -0,0 +1,58 @@ +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:17 + | +LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { + | ^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:12 + | +LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { + | ^^^^^^^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:9 + | +LL | let &pat!(x) = &mut 0; + | ^^^^^^^^ ------ this expression has type `&mut {integer}` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:9 + | +LL | let &(ref mut a, ref mut b) = &mut (true, false); + | ^^^^^^^^^^^^^^^^^^^^^^^ ------------------ this expression has type `&mut (bool, bool)` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut (bool, bool)` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:9 + | +LL | let &[x] = &mut &mut [0]; + | ^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut &mut [{integer}; 1]` + found reference `&_` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed index 32e955db12ce6..4ee849b38c53b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed @@ -1,6 +1,9 @@ -//@ edition: 2024 -//@ run-rustfix -//@ revisions: classic2024 structural2024 +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-rustfix +//@[structural2024] run-rustfix //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts //! to bind by mutable reference. #![allow(incomplete_features)] @@ -9,12 +12,14 @@ pub fn main() { if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) { - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut u8 = x; } @@ -22,16 +27,19 @@ pub fn main() { ($var:ident) => { ref mut $var }; } let &mut pat!(x) = &mut 0; - //~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ 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 + //[stable2021]~^ ERROR: mismatched types + //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern + //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern let _: &mut bool = a; let _: &mut bool = b; let &[x] = &mut &mut [0]; - //[classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern + //[stable2021]~^ ERROR: mismatched types + //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern let _: &u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr index 6c384a51fac14..69cb6c438b6ed 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:11:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31 | LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -7,7 +7,7 @@ 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-mut-inside-shared-ref-pat.rs:16:31 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31 | LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ @@ -15,7 +15,7 @@ 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-mut-inside-shared-ref-pat.rs:24:15 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15 | LL | let &pat!(x) = &mut 0; | - ^ @@ -23,7 +23,7 @@ LL | let &pat!(x) = &mut 0; | help: replace this `&` with `&mut`: `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern - --> $DIR/ref-mut-inside-shared-ref-pat.rs:28:19 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ @@ -31,7 +31,7 @@ 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-mut-inside-shared-ref-pat.rs:28:30 + --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30 | LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 906110d1dce81..a8ad014fc5d37 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -1,6 +1,9 @@ -//@ edition: 2024 -//@ revisions: classic2024 structural2024 -//@ run-pass +//@ revisions: stable2021 classic2024 structural2024 +//@[stable2021] edition: 2021 +//@[classic2024] edition: 2024 +//@[structural2024] edition: 2024 +//@[classic2024] run-pass +//@[structural2024] run-pass //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests. #![allow(incomplete_features, unused_mut)] @@ -9,65 +12,101 @@ pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } if let Some(Some(&x)) = &Some(Some(&0)) { - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } if let Some(Some(&&x)) = &Some(Some(&0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } if let Some(&Some(x)) = &Some(Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&_` let _: u32 = x; } if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&mut _` let _: u32 = x; } if let Some(&Some(&x)) = &mut Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } if let Some(&Some(x)) = &mut Some(&Some(0)) { - let _: &u32 = x; + #[cfg(stable2021)] let _: u32 = x; + #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { let _: &u32 = x; } if let Some(&Some(&x)) = &Some(&mut Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; } if let Some(&Some(&x)) = &Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` let _: u32 = x; } if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; } if let Some(&Some(x)) = &mut Some(Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&_` let _: u32 = x; } // Tests for eat-inner rulesets matching on the outer reference if matching on the inner // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`: let [&mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: &u32 = x; let [&mut ref x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: &&u32 = x; let [&mut ref mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: &mut &u32 = x; let [&mut mut x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: &u32 = x; let [&mut &x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; let [&mut &ref x] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: &u32 = x; let [&mut &(mut x)] = &mut [&0]; + //[stable2021]~^ mismatched types + //[stable2021]~| types differ in mutability let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr new file mode 100644 index 0000000000000..c78459bb21cf9 --- /dev/null +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr @@ -0,0 +1,260 @@ +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:14:22 + | +LL | if let Some(Some(&x)) = &Some(&Some(0)) { + | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(Some(x)) = &Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:23:23 + | +LL | if let Some(Some(&&x)) = &Some(Some(&0)) { + | ^^ --------------- this expression has type `&Option>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL - if let Some(Some(&&x)) = &Some(Some(&0)) { +LL + if let Some(Some(&x)) = &Some(Some(&0)) { + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:28:17 + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ^^^^^^^^ -------------- this expression has type `&Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:33:22 + | +LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` + | | + | expected integer, found `&mut _` + | + = note: expected type `{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:33:22 + | +LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:38:23 + | +LL | if let Some(&Some(&x)) = &mut Some(&Some(0)) { + | ^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = &mut Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:50:17 + | +LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { + | ^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:55:23 + | +LL | if let Some(&Some(&x)) = &Some(&Some(0)) { + | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = &Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:60:17 + | +LL | if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { + | ^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option>>` + | | + | expected `Option<&mut Option<{integer}>>`, found `&_` + | + = note: expected enum `Option<&mut Option<{integer}>>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:65:23 + | +LL | if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + | ^^ ------------------- this expression has type `Option<&Option<&mut {integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut {integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:70:17 + | +LL | if let Some(&Some(x)) = &mut Some(Some(0)) { + | ^^^^^^^^ ------------------ this expression has type `&mut Option>` + | | + | expected `Option<{integer}>`, found `&_` + | + = note: expected enum `Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:78:10 + | +LL | let [&mut x] = &mut [&0]; + | ^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:78:10 + | +LL | let [&mut x] = &mut [&0]; + | ^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut x] = &mut [&0]; +LL + let [x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:83:10 + | +LL | let [&mut ref x] = &mut [&0]; + | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:83:10 + | +LL | let [&mut ref x] = &mut [&0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref x] = &mut [&0]; +LL + let [ref x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:88:10 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:88:10 + | +LL | let [&mut ref mut x] = &mut [&0]; + | ^^^^^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut ref mut x] = &mut [&0]; +LL + let [ref mut x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:93:10 + | +LL | let [&mut mut x] = &mut [&0]; + | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` +note: to declare a mutable binding use: `mut x` + --> $DIR/well-typed-edition-2024.rs:93:10 + | +LL | let [&mut mut x] = &mut [&0]; + | ^^^^^^^^^^ +help: consider removing `&mut` from the pattern + | +LL - let [&mut mut x] = &mut [&0]; +LL + let [mut x] = &mut [&0]; + | + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:98:10 + | +LL | let [&mut &x] = &mut [&0]; + | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:103:10 + | +LL | let [&mut &ref x] = &mut [&0]; + | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:108:10 + | +LL | let [&mut &(mut x)] = &mut [&0]; + | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` + | | + | types differ in mutability + | + = note: expected reference `&{integer}` + found mutable reference `&mut _` + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0308`. From f5567e1132c1dce184f34313715e3f22dc6a8e04 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 02:19:27 -0800 Subject: [PATCH 10/23] organize old well-typed-edition-2024 tests This doesn't (or at least shouldn't!) add, remove, or change any test cases. I've grouped them by which rule variants they test. --- .../experimental/well-typed-edition-2024.rs | 55 +++++--- .../well-typed-edition-2024.stable2021.stderr | 130 +++++++++--------- 2 files changed, 100 insertions(+), 85 deletions(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index a8ad014fc5d37..3114b9d3bf8cb 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -11,20 +11,34 @@ #![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))] pub fn main() { - if let Some(Some(&x)) = &Some(&Some(0)) { - //[stable2021]~^ mismatched types - //[stable2021]~| expected integer, found `&_` - let _: u32 = x; + // Tests not using match ergonomics. These should always succeed with the same bindings. + if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { + let _: &u32 = x; } + + // Tests for differences in how many layers of reference are eaten by reference patterns if let Some(Some(&x)) = &Some(Some(&0)) { #[cfg(stable2021)] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } + if let Some(&Some(x)) = &mut Some(&Some(0)) { + // This additionally tests that `&` patterns can eat inherited `&mut` refs. + // This is possible on stable when the real reference being eaten is of a `&` type. + #[cfg(stable2021)] let _: u32 = x; + #[cfg(any(classic2024, structural2024))] let _: &u32 = x; + } if let Some(Some(&&x)) = &Some(Some(&0)) { //[stable2021]~^ mismatched types //[stable2021]~| expected integer, found `&_` let _: u32 = x; } + + // Tests for eating a lone inherited reference + if let Some(Some(&x)) = &Some(&Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected integer, found `&_` + let _: u32 = x; + } if let Some(&Some(x)) = &Some(Some(0)) { //[stable2021]~^ mismatched types //[stable2021]~| expected `Option<{integer}>`, found `&_` @@ -35,41 +49,42 @@ pub fn main() { //[stable2021]~| expected integer, found `&mut _` let _: u32 = x; } - if let Some(&Some(&x)) = &mut Some(&Some(0)) { - //[stable2021]~^ mismatched types - //[stable2021]~| expected integer, found `&_` - let _: u32 = x; - } - if let Some(&Some(x)) = &mut Some(&Some(0)) { - #[cfg(stable2021)] let _: u32 = x; - #[cfg(any(classic2024, structural2024))] let _: &u32 = x; - } - if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { - let _: &u32 = x; - } - if let Some(&Some(&x)) = &Some(&mut Some(0)) { + + // Tests for `&` patterns matching real `&mut` reference types + if let Some(&Some(&x)) = Some(&Some(&mut 0)) { //[stable2021]~^ mismatched types //[stable2021]~| types differ in mutability let _: u32 = x; } + + // Tests for eating only one layer and also eating a lone inherited reference if let Some(&Some(&x)) = &Some(&Some(0)) { //[stable2021]~^ mismatched types //[stable2021]~| expected integer, found `&_` let _: u32 = x; } + + // Tests for `&` matching a lone inherited possibly-`&mut` reference if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { //[stable2021]~^ mismatched types //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` let _: u32 = x; } - if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + if let Some(&Some(x)) = &mut Some(Some(0)) { + //[stable2021]~^ mismatched types + //[stable2021]~| expected `Option<{integer}>`, found `&_` + let _: u32 = x; + } + + // Tests eating one layer, eating a lone inherited ref, and `&` eating `&mut` (realness varies) + if let Some(&Some(&x)) = &Some(&mut Some(0)) { //[stable2021]~^ mismatched types //[stable2021]~| types differ in mutability let _: u32 = x; } - if let Some(&Some(x)) = &mut Some(Some(0)) { + if let Some(&Some(&x)) = &mut Some(&Some(0)) { //[stable2021]~^ mismatched types - //[stable2021]~| expected `Option<{integer}>`, found `&_` + //[stable2021]~| expected integer, found `&_` let _: u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr index c78459bb21cf9..e9c338de24312 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr @@ -1,36 +1,36 @@ error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:14:22 + --> $DIR/well-typed-edition-2024.rs:30:23 | -LL | if let Some(Some(&x)) = &Some(&Some(0)) { - | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` - | | - | expected integer, found `&_` +LL | if let Some(Some(&&x)) = &Some(Some(&0)) { + | ^^ --------------- this expression has type `&Option>` + | | + | expected integer, found `&_` | = note: expected type `{integer}` found reference `&_` help: consider removing `&` from the pattern | -LL | if let Some(Some(x)) = &Some(&Some(0)) { - | ~ +LL - if let Some(Some(&&x)) = &Some(Some(&0)) { +LL + if let Some(Some(&x)) = &Some(Some(&0)) { + | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:23:23 + --> $DIR/well-typed-edition-2024.rs:37:22 | -LL | if let Some(Some(&&x)) = &Some(Some(&0)) { - | ^^ --------------- this expression has type `&Option>` - | | - | expected integer, found `&_` +LL | if let Some(Some(&x)) = &Some(&Some(0)) { + | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` + | | + | expected integer, found `&_` | = note: expected type `{integer}` found reference `&_` help: consider removing `&` from the pattern | -LL - if let Some(Some(&&x)) = &Some(Some(&0)) { -LL + if let Some(Some(&x)) = &Some(Some(&0)) { - | +LL | if let Some(Some(x)) = &Some(&Some(0)) { + | ~ error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:28:17 + --> $DIR/well-typed-edition-2024.rs:42:17 | LL | if let Some(&Some(x)) = &Some(Some(0)) { | ^^^^^^^^ -------------- this expression has type `&Option>` @@ -41,7 +41,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:33:22 + --> $DIR/well-typed-edition-2024.rs:47:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` @@ -51,7 +51,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/well-typed-edition-2024.rs:33:22 + --> $DIR/well-typed-edition-2024.rs:47:22 | LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { | ^^^^^^ @@ -61,33 +61,22 @@ LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:38:23 + --> $DIR/well-typed-edition-2024.rs:54:23 | -LL | if let Some(&Some(&x)) = &mut Some(&Some(0)) { - | ^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` +LL | if let Some(&Some(&x)) = Some(&Some(&mut 0)) { + | ^^ ------------------- this expression has type `Option<&Option<&mut {integer}>>` | | - | expected integer, found `&_` + | types differ in mutability | - = note: expected type `{integer}` - found reference `&_` + = note: expected mutable reference `&mut {integer}` + found reference `&_` help: consider removing `&` from the pattern | -LL | if let Some(&Some(x)) = &mut Some(&Some(0)) { +LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | ~ error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:50:17 - | -LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { - | ^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` - | | - | types differ in mutability - | - = note: expected mutable reference `&mut Option<{integer}>` - found reference `&_` - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:55:23 + --> $DIR/well-typed-edition-2024.rs:61:23 | LL | if let Some(&Some(&x)) = &Some(&Some(0)) { | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` @@ -102,7 +91,7 @@ LL | if let Some(&Some(x)) = &Some(&Some(0)) { | ~ error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:60:17 + --> $DIR/well-typed-edition-2024.rs:68:17 | LL | if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { | ^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option>>` @@ -113,22 +102,7 @@ LL | if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { found reference `&_` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:65:23 - | -LL | if let Some(&Some(&x)) = Some(&Some(&mut 0)) { - | ^^ ------------------- this expression has type `Option<&Option<&mut {integer}>>` - | | - | types differ in mutability - | - = note: expected mutable reference `&mut {integer}` - found reference `&_` -help: consider removing `&` from the pattern - | -LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | ~ - -error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:70:17 + --> $DIR/well-typed-edition-2024.rs:73:17 | LL | if let Some(&Some(x)) = &mut Some(Some(0)) { | ^^^^^^^^ ------------------ this expression has type `&mut Option>` @@ -139,7 +113,33 @@ LL | if let Some(&Some(x)) = &mut Some(Some(0)) { found reference `&_` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:78:10 + --> $DIR/well-typed-edition-2024.rs:80:17 + | +LL | if let Some(&Some(&x)) = &Some(&mut Some(0)) { + | ^^^^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` + | | + | types differ in mutability + | + = note: expected mutable reference `&mut Option<{integer}>` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:85:23 + | +LL | if let Some(&Some(&x)) = &mut Some(&Some(0)) { + | ^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` + | | + | expected integer, found `&_` + | + = note: expected type `{integer}` + found reference `&_` +help: consider removing `&` from the pattern + | +LL | if let Some(&Some(x)) = &mut Some(&Some(0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/well-typed-edition-2024.rs:93:10 | LL | let [&mut x] = &mut [&0]; | ^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -149,7 +149,7 @@ LL | let [&mut x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:78:10 + --> $DIR/well-typed-edition-2024.rs:93:10 | LL | let [&mut x] = &mut [&0]; | ^^^^^^ @@ -160,7 +160,7 @@ LL + let [x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:83:10 + --> $DIR/well-typed-edition-2024.rs:98:10 | LL | let [&mut ref x] = &mut [&0]; | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -170,7 +170,7 @@ LL | let [&mut ref x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:83:10 + --> $DIR/well-typed-edition-2024.rs:98:10 | LL | let [&mut ref x] = &mut [&0]; | ^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + let [ref x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:88:10 + --> $DIR/well-typed-edition-2024.rs:103:10 | LL | let [&mut ref mut x] = &mut [&0]; | ^^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -191,7 +191,7 @@ LL | let [&mut ref mut x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:88:10 + --> $DIR/well-typed-edition-2024.rs:103:10 | LL | let [&mut ref mut x] = &mut [&0]; | ^^^^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL + let [ref mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:93:10 + --> $DIR/well-typed-edition-2024.rs:108:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -212,7 +212,7 @@ LL | let [&mut mut x] = &mut [&0]; = note: expected reference `&{integer}` found mutable reference `&mut _` note: to declare a mutable binding use: `mut x` - --> $DIR/well-typed-edition-2024.rs:93:10 + --> $DIR/well-typed-edition-2024.rs:108:10 | LL | let [&mut mut x] = &mut [&0]; | ^^^^^^^^^^ @@ -223,7 +223,7 @@ LL + let [mut x] = &mut [&0]; | error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:98:10 + --> $DIR/well-typed-edition-2024.rs:113:10 | LL | let [&mut &x] = &mut [&0]; | ^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -234,7 +234,7 @@ LL | let [&mut &x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:103:10 + --> $DIR/well-typed-edition-2024.rs:118:10 | LL | let [&mut &ref x] = &mut [&0]; | ^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` @@ -245,7 +245,7 @@ LL | let [&mut &ref x] = &mut [&0]; found mutable reference `&mut _` error[E0308]: mismatched types - --> $DIR/well-typed-edition-2024.rs:108:10 + --> $DIR/well-typed-edition-2024.rs:123:10 | LL | let [&mut &(mut x)] = &mut [&0]; | ^^^^^^^^^^^^^ --------- this expression has type `&mut [&{integer}; 1]` From e288cff5cf38c66a5fad52d010e97f9dd3c5b991 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 06:27:11 -0800 Subject: [PATCH 11/23] add tests differing between stable and new rules (with errors on new rules) Since there are so many ways to write these, I've opted to only include two sorts of test: simple tests that directly target the rules differing between rulesets and nuanced tests that produce different errors under different rulesets. I've also tried not to add any duplicate tests. `well-typed-edition-2024.rs` already has tests disagreeing with stable, so I've opted not to include any in this commit that are well-typed under the new rules. --- .../mut-ref-mut.classic2024.stderr | 17 +++- .../experimental/mut-ref-mut.rs | 6 ++ .../mut-ref-mut.structural2024.stderr | 12 ++- .../ref-binding-on-inh-ref-errors.rs | 42 +++++++++- ...inding-on-inh-ref-errors.stable2021.stderr | 15 +++- ...ng-on-inh-ref-errors.structural2024.stderr | 81 +++++++++++++++++-- 6 files changed, 155 insertions(+), 18 deletions(-) diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr index 3849b4ed98948..afaa925a75779 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr @@ -18,6 +18,19 @@ LL | let Foo(mut a) = &mut Foo(0); = help: add `#![feature(mut_ref)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/mut-ref-mut.rs:24:10 + | +LL | let [&mut mut x] = &[&mut 0]; + | ^^^^^ + | + = note: cannot match inherited `&` with `&mut` pattern +help: replace this `&mut` pattern with `&` + | +LL | let [&mut x] = &[&mut 0]; + | ~ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs index 68d6871eabfa3..fbd6514df73d6 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs @@ -20,4 +20,10 @@ pub fn main() { //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference #[cfg(stable2021)] { a = 42 } #[cfg(any(classic2024, structural2024))] { a = &mut 42 } + + let [&mut mut x] = &[&mut 0]; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^^^ binding cannot be both mutable and by-reference + #[cfg(stable2021)] { x = 0 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr index 3849b4ed98948..fd82da70a18de 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr @@ -18,6 +18,16 @@ LL | let Foo(mut a) = &mut Foo(0); = help: add `#![feature(mut_ref)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/mut-ref-mut.rs:24:15 + | +LL | let [&mut mut x] = &[&mut 0]; + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs index a151c84739c17..4c88c0c63ae54 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs @@ -2,7 +2,6 @@ //@[stable2021] edition: 2021 //@[classic2024] edition: 2024 //@[structural2024] edition: 2024 -//@[classic2024] run-pass //! Tests for errors from binding with `ref x` under a by-ref default binding mode in edition 2024. //! These can't be in the same body as tests for other errors, since they're emitted during THIR //! construction. The errors on stable edition 2021 Rust are unrelated. @@ -36,8 +35,6 @@ fn errors_from_eating_the_real_reference() { //[structural2024]~| cannot override to bind by-reference when that is the implicit default #[cfg(stable2021)] let _: &mut u32 = x; #[cfg(classic2024)] let _: &mut &mut u32 = x; - - errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable(); } /// To make absolutely sure binding with `ref` ignores inherited references on stable, let's @@ -58,6 +55,43 @@ fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() { #[cfg(classic2024)] let _: &&mut u32 = x; } +/// This one also needs to be quarantined for a typeck error on `classic2024` (eat-outer). +fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() { + let [&mut ref x] = &[&mut 0]; + //[classic2024]~^ ERROR: mismatched types + //[classic2024]~| cannot match inherited `&` with `&mut` pattern + //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; +} + +/// These should be errors in all editions. In edition 2024, they should be caught by the pattern +/// typing rules disallowing `ref` when there's an inherited reference. In old editions where that +/// resets the binding mode, they're borrowck errors due to binding with `ref mut`. +/// As a quirk of how the edition 2024 error is emitted during THIR construction, it ends up going +/// through borrowck as well, using the old `ref` behavior as a fallback, so we get that error too. +fn borrowck_errors_in_old_editions() { + let [ref mut x] = &[0]; + //~^ ERROR: cannot borrow data in a `&` reference as mutable + //[classic2024,structural2024]~| ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default +} + +/// The remaining tests are purely for testing `ref` bindings in the presence of an inherited +/// reference. These should always fail on edition 2024 and succeed on edition 2021. pub fn main() { - errors_from_eating_the_real_reference(); + let [ref x] = &[0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + + let [ref x] = &mut [0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &u32 = x; + + let [ref mut x] = &mut [0]; + //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024 + //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default + #[cfg(stable2021)] let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr index c0518130368d7..a21e4bb5b8f8f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/ref-binding-on-inh-ref-errors.rs:46:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:43:10 | LL | let [&ref x] = &[&mut 0]; | ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]` @@ -15,7 +15,7 @@ LL + let [ref x] = &[&mut 0]; | error[E0308]: mismatched types - --> $DIR/ref-binding-on-inh-ref-errors.rs:53:10 + --> $DIR/ref-binding-on-inh-ref-errors.rs:50:10 | LL | let [&ref x] = &mut [&mut 0]; | ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]` @@ -30,6 +30,13 @@ LL - let [&ref x] = &mut [&mut 0]; LL + let [ref x] = &mut [&mut 0]; | -error: aborting due to 2 previous errors +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0596. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr index 92aa8f1ea6853..ee2c831bfcc80 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr @@ -1,5 +1,5 @@ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:16:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11 | LL | let [&ref x] = &[&0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -11,7 +11,7 @@ LL | let &[&ref x] = &[&0]; | + error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:22:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11 | LL | let [&ref x] = &mut [&0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -23,7 +23,7 @@ LL | let &mut [&ref x] = &mut [&0]; | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:28:15 + --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15 | LL | let [&mut ref x] = &mut [&mut 0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -35,7 +35,7 @@ LL | let &mut [&mut ref x] = &mut [&mut 0]; | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:34:15 + --> $DIR/ref-binding-on-inh-ref-errors.rs:33:15 | LL | let [&mut ref mut x] = &mut [&mut 0]; | ^^^^^^^ cannot override to bind by-reference when that is the implicit default @@ -47,7 +47,7 @@ LL | let &mut [&mut ref mut x] = &mut [&mut 0]; | ++++ error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:46:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:43:11 | LL | let [&ref x] = &[&mut 0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -59,7 +59,7 @@ LL | let &[&ref x] = &[&mut 0]; | + error: this pattern relies on behavior which may change in edition 2024 - --> $DIR/ref-binding-on-inh-ref-errors.rs:53:11 + --> $DIR/ref-binding-on-inh-ref-errors.rs:50:11 | LL | let [&ref x] = &mut [&mut 0]; | ^^^ cannot override to bind by-reference when that is the implicit default @@ -70,5 +70,72 @@ help: make the implied reference pattern explicit LL | let &mut [&ref x] = &mut [&mut 0]; | ++++ -error: aborting due to 6 previous errors +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:60:15 + | +LL | let [&mut ref x] = &[&mut 0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[&mut ref x] = &[&mut 0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref mut x] = &[0]; + | + + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10 + | +LL | let [ref mut x] = &[0]; + | ^^^^^^^^^ cannot borrow as mutable + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10 + | +LL | let [ref x] = &[0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &[ref x] = &[0]; + | + + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10 + | +LL | let [ref x] = &mut [0]; + | ^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref x] = &mut [0]; + | ++++ + +error: this pattern relies on behavior which may change in edition 2024 + --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10 + | +LL | let [ref mut x] = &mut [0]; + | ^^^^^^^ cannot override to bind by-reference when that is the implicit default + | + = note: for more information, see +help: make the implied reference pattern explicit + | +LL | let &mut [ref mut x] = &mut [0]; + | ++++ + +error: aborting due to 12 previous errors +For more information about this error, try `rustc --explain E0596`. From ccb967438de778b7f4ee3cf94f3e8163f6f5c53f Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Wed, 22 Jan 2025 16:01:10 +0100 Subject: [PATCH 12/23] simplify similar_tokens from Option> to Vec<_> --- compiler/rustc_ast/src/token.rs | 14 +++++++------- compiler/rustc_builtin_macros/src/format.rs | 15 +++++++-------- compiler/rustc_parse/src/parser/expr.rs | 3 +-- compiler/rustc_parse/src/parser/mod.rs | 6 ++---- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 3b7367d1ee209..5b6e65c804f52 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -527,13 +527,13 @@ impl TokenKind { /// Returns tokens that are likely to be typed accidentally instead of the current token. /// Enables better error recovery when the wrong token is found. - pub fn similar_tokens(&self) -> Option> { - match *self { - Comma => Some(vec![Dot, Lt, Semi]), - Semi => Some(vec![Colon, Comma]), - Colon => Some(vec![Semi]), - FatArrow => Some(vec![Eq, RArrow, Ge, Gt]), - _ => None, + pub fn similar_tokens(&self) -> Vec { + match self { + Comma => vec![Dot, Lt, Semi], + Semi => vec![Colon, Comma], + Colon => vec![Semi], + FatArrow => vec![Eq, RArrow, Ge, Gt], + _ => vec![], } } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 5202fe26c401e..d9cfbaf63e621 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -101,15 +101,14 @@ fn parse_args<'a>(ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, match p.expect(exp!(Comma)) { Err(err) => { - match token::TokenKind::Comma.similar_tokens() { - Some(tks) if tks.contains(&p.token.kind) => { - // If a similar token is found, then it may be a typo. We - // consider it as a comma, and continue parsing. - err.emit(); - p.bump(); - } + if token::TokenKind::Comma.similar_tokens().contains(&p.token.kind) { + // If a similar token is found, then it may be a typo. We + // consider it as a comma, and continue parsing. + err.emit(); + p.bump(); + } else { // Otherwise stop the parsing and return the error. - _ => return Err(err), + return Err(err); } } Ok(Recovered::Yes(_)) => (), diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5cd02128287e2..cf87c8c94954f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3115,8 +3115,7 @@ impl<'a> Parser<'a> { let arm_body; let is_fat_arrow = this.check(exp!(FatArrow)); let is_almost_fat_arrow = TokenKind::FatArrow - .similar_tokens() - .is_some_and(|similar_tokens| similar_tokens.contains(&this.token.kind)); + .similar_tokens().contains(&this.token.kind); // this avoids the compiler saying that a `,` or `}` was expected even though // the pattern isn't a never pattern (and thus an arm body is required) diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 10756be6afb8e..aba84d44a448e 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -923,10 +923,8 @@ impl<'a> Parser<'a> { _ => { // Attempt to keep parsing if it was a similar separator. - if let Some(tokens) = exp.tok.similar_tokens() { - if tokens.contains(&self.token.kind) { - self.bump(); - } + if exp.tok.similar_tokens().contains(&self.token.kind) { + self.bump(); } } } From 5f01e12ea8035fdfc23eefaf6b580dbb9a8863ec Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Wed, 22 Jan 2025 16:50:22 +0100 Subject: [PATCH 13/23] simplify similar_tokens from Vec<_> to &[_] --- compiler/rustc_ast/src/token.rs | 12 ++++++------ compiler/rustc_parse/src/parser/expr.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 5b6e65c804f52..100f664a89fd9 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -527,13 +527,13 @@ impl TokenKind { /// Returns tokens that are likely to be typed accidentally instead of the current token. /// Enables better error recovery when the wrong token is found. - pub fn similar_tokens(&self) -> Vec { + pub fn similar_tokens(&self) -> &[TokenKind] { match self { - Comma => vec![Dot, Lt, Semi], - Semi => vec![Colon, Comma], - Colon => vec![Semi], - FatArrow => vec![Eq, RArrow, Ge, Gt], - _ => vec![], + Comma => &[Dot, Lt, Semi], + Semi => &[Colon, Comma], + Colon => &[Semi], + FatArrow => &[Eq, RArrow, Ge, Gt], + _ => &[], } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cf87c8c94954f..0affca1f825c1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3114,8 +3114,8 @@ impl<'a> Parser<'a> { let span_before_body = this.prev_token.span; let arm_body; let is_fat_arrow = this.check(exp!(FatArrow)); - let is_almost_fat_arrow = TokenKind::FatArrow - .similar_tokens().contains(&this.token.kind); + let is_almost_fat_arrow = + TokenKind::FatArrow.similar_tokens().contains(&this.token.kind); // this avoids the compiler saying that a `,` or `}` was expected even though // the pattern isn't a never pattern (and thus an arm body is required) From be7d6e3d5e34641f99f4a77d143beefbf243a934 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 21 Jan 2025 08:17:59 -0800 Subject: [PATCH 14/23] add work-in-progress unstable book chapters These are very bare-bones, only intended to provide some documentation of what these feature gates are and aren't yet implementing. --- .../ref-pat-eat-one-layer-2024-structural.md | 19 +++++++++++++++++++ .../ref-pat-eat-one-layer-2024.md | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md create mode 100644 src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md new file mode 100644 index 0000000000000..bc58768611175 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md @@ -0,0 +1,19 @@ +# `ref_pat_eat_one_layer_2024_structural` + +The tracking issue for this feature is: [#123076] + +[#123076]: https://github.com/rust-lang/rust/issues/123076 + +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust. +For more information, see the corresponding typing rules for [Editions 2024 and later]. +On earlier Editions, the current behavior is unspecified. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md). + +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md new file mode 100644 index 0000000000000..43de1849a5ebb --- /dev/null +++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md @@ -0,0 +1,19 @@ +# `ref_pat_eat_one_layer_2024` + +The tracking issue for this feature is: [#123076] + +[#123076]: https://github.com/rust-lang/rust/issues/123076 + +--- + +This feature is incomplete and not yet intended for general use. + +This implements experimental, Edition-dependent match ergonomics under consideration for inclusion +in Rust. +For more information, see the corresponding typing rules for [Editions 2024 and later]. +On earlier Editions, the current behavior is unspecified. + +For alternative experimental match ergonomics, see the feature +[`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md). + +[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false From 5df51930f926735f2ec48433e95502c3b214cdf8 Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Tue, 28 Jan 2025 19:02:15 +0300 Subject: [PATCH 15/23] Fix tests/codegen/float/f128 --- src/tools/compiletest/src/directive-list.rs | 1 + tests/codegen/float/f128.rs | 31 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index acdb3cbdd4590..71496444660f5 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -177,6 +177,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-bpf", "only-cdb", "only-dist", + "only-emscripten", "only-gnu", "only-i686-pc-windows-gnu", "only-i686-pc-windows-msvc", diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs index 514d35433e12d..562a8e6c9e9ba 100644 --- a/tests/codegen/float/f128.rs +++ b/tests/codegen/float/f128.rs @@ -1,11 +1,15 @@ // 32-bit x86 returns float types differently to avoid the x87 stack. // 32-bit systems will return 128bit values using a return area pointer. -//@ revisions: x86 bit32 bit64 +// Emscripten aligns f128 to 8 bytes, not 16. +//@ revisions: x86 bit32 bit64 emscripten //@[x86] only-x86 //@[bit32] ignore-x86 +//@[bit32] ignore-emscripten //@[bit32] only-32bit //@[bit64] ignore-x86 +//@[bit64] ignore-emscripten //@[bit64] only-64bit +//@[emscripten] only-emscripten // Verify that our intrinsics generate the correct LLVM calls for f128 @@ -59,6 +63,7 @@ pub fn f128_le(a: f128, b: f128) -> bool { // x86-LABEL: void @f128_neg({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_neg({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_neg( +// emscripten-LABEL: void @f128_neg({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_neg(a: f128) -> f128 { // CHECK: fneg fp128 @@ -68,6 +73,7 @@ pub fn f128_neg(a: f128) -> f128 { // x86-LABEL: void @f128_add({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_add({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_add( +// emscripten-LABEL: void @f128_add({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_add(a: f128, b: f128) -> f128 { // CHECK: fadd fp128 %{{.+}}, %{{.+}} @@ -77,6 +83,7 @@ pub fn f128_add(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_sub({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_sub({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_sub( +// emscripten-LABEL: void @f128_sub({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_sub(a: f128, b: f128) -> f128 { // CHECK: fsub fp128 %{{.+}}, %{{.+}} @@ -86,6 +93,7 @@ pub fn f128_sub(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_mul({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_mul({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_mul( +// emscripten-LABEL: void @f128_mul({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_mul(a: f128, b: f128) -> f128 { // CHECK: fmul fp128 %{{.+}}, %{{.+}} @@ -95,6 +103,7 @@ pub fn f128_mul(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_div({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_div({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_div( +// emscripten-LABEL: void @f128_div({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_div(a: f128, b: f128) -> f128 { // CHECK: fdiv fp128 %{{.+}}, %{{.+}} @@ -104,6 +113,7 @@ pub fn f128_div(a: f128, b: f128) -> f128 { // x86-LABEL: void @f128_rem({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_rem({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_rem( +// emscripten-LABEL: void @f128_rem({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_rem(a: f128, b: f128) -> f128 { // CHECK: frem fp128 %{{.+}}, %{{.+}} @@ -164,6 +174,7 @@ pub fn f128_as_f16(a: f128) -> f16 { // x86-LABEL: i32 @f128_as_f32( // bit32-LABEL: float @f128_as_f32( // bit64-LABEL: float @f128_as_f32( +// emscripten-LABEL: float @f128_as_f32( #[no_mangle] pub fn f128_as_f32(a: f128) -> f32 { // CHECK: fptrunc fp128 %{{.+}} to float @@ -173,6 +184,7 @@ pub fn f128_as_f32(a: f128) -> f32 { // x86-LABEL: void @f128_as_f64( // bit32-LABEL: double @f128_as_f64( // bit64-LABEL: double @f128_as_f64( +// emscripten-LABEL: double @f128_as_f64( #[no_mangle] pub fn f128_as_f64(a: f128) -> f64 { // CHECK: fptrunc fp128 %{{.+}} to double @@ -182,17 +194,20 @@ pub fn f128_as_f64(a: f128) -> f64 { // x86-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f128_as_self( +// emscripten-LABEL: void @f128_as_self({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_self(a: f128) -> f128 { // x86: store fp128 %a, ptr %_0, align 16 // bit32: store fp128 %a, ptr %_0, align 16 // bit64: ret fp128 %{{.+}} + // emscripten: store fp128 %a, ptr %_0, align 8 a as f128 } // x86-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f16_as_f128( +// emscripten-LABEL: void @f16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f16_as_f128(a: f16) -> f128 { // CHECK: fpext half %{{.+}} to fp128 @@ -202,6 +217,7 @@ pub fn f16_as_f128(a: f16) -> f128 { // x86-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f32_as_f128( +// emscripten-LABEL: void @f32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f32_as_f128(a: f32) -> f128 { // CHECK: fpext float %{{.+}} to fp128 @@ -211,6 +227,7 @@ pub fn f32_as_f128(a: f32) -> f128 { // x86-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @f64_as_f128( +// emscripten-LABEL: void @f64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f64_as_f128(a: f64) -> f128 { // CHECK: fpext double %{{.+}} to fp128 @@ -249,6 +266,7 @@ pub fn f128_as_u64(a: f128) -> u64 { // x86-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_u128( +// emscripten-LABEL: void @f128_as_u128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_u128(a: f128) -> u128 { // CHECK: call i128 @llvm.fptoui.sat.i128.f128(fp128 %{{.+}}) @@ -285,6 +303,7 @@ pub fn f128_as_i64(a: f128) -> i64 { // x86-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit32-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) // bit64-LABEL: i128 @f128_as_i128( +// emscripten-LABEL: void @f128_as_i128({{.*}}sret([16 x i8]) #[no_mangle] pub fn f128_as_i128(a: f128) -> i128 { // CHECK: call i128 @llvm.fptosi.sat.i128.f128(fp128 %{{.+}}) @@ -296,6 +315,7 @@ pub fn f128_as_i128(a: f128) -> i128 { // x86-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u8_as_f128( +// emscripten-LABEL: void @u8_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u8_as_f128(a: u8) -> f128 { // CHECK: uitofp i8 %{{.+}} to fp128 @@ -305,6 +325,7 @@ pub fn u8_as_f128(a: u8) -> f128 { // x86-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u16_as_f128( +// emscripten-LABEL: void @u16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u16_as_f128(a: u16) -> f128 { // CHECK: uitofp i16 %{{.+}} to fp128 @@ -314,6 +335,7 @@ pub fn u16_as_f128(a: u16) -> f128 { // x86-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u32_as_f128( +// emscripten-LABEL: void @u32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u32_as_f128(a: u32) -> f128 { // CHECK: uitofp i32 %{{.+}} to fp128 @@ -323,6 +345,7 @@ pub fn u32_as_f128(a: u32) -> f128 { // x86-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u64_as_f128( +// emscripten-LABEL: void @u64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u64_as_f128(a: u64) -> f128 { // CHECK: uitofp i64 %{{.+}} to fp128 @@ -332,6 +355,7 @@ pub fn u64_as_f128(a: u64) -> f128 { // x86-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @u128_as_f128( +// emscripten-LABEL: void @u128_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn u128_as_f128(a: u128) -> f128 { // CHECK: uitofp i128 %{{.+}} to fp128 @@ -341,6 +365,7 @@ pub fn u128_as_f128(a: u128) -> f128 { // x86-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i8_as_f128( +// emscripten-LABEL: void @i8_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i8_as_f128(a: i8) -> f128 { // CHECK: sitofp i8 %{{.+}} to fp128 @@ -350,6 +375,7 @@ pub fn i8_as_f128(a: i8) -> f128 { // x86-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i16_as_f128( +// emscripten-LABEL: void @i16_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i16_as_f128(a: i16) -> f128 { // CHECK: sitofp i16 %{{.+}} to fp128 @@ -359,6 +385,7 @@ pub fn i16_as_f128(a: i16) -> f128 { // x86-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i32_as_f128( +// emscripten-LABEL: void @i32_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i32_as_f128(a: i32) -> f128 { // CHECK: sitofp i32 %{{.+}} to fp128 @@ -368,6 +395,7 @@ pub fn i32_as_f128(a: i32) -> f128 { // x86-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i64_as_f128( +// emscripten-LABEL: void @i64_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i64_as_f128(a: i64) -> f128 { // CHECK: sitofp i64 %{{.+}} to fp128 @@ -377,6 +405,7 @@ pub fn i64_as_f128(a: i64) -> f128 { // x86-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit32-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) // bit64-LABEL: fp128 @i128_as_f128( +// emscripten-LABEL: void @i128_as_f128({{.*}}sret([16 x i8]) #[no_mangle] pub fn i128_as_f128(a: i128) -> f128 { // CHECK: sitofp i128 %{{.+}} to fp128 From efaeedef59e4f213806898cdedb2220016d193c0 Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Tue, 28 Jan 2025 19:03:26 +0300 Subject: [PATCH 16/23] Fix tests/codegen/wasm_exceptions --- tests/codegen/wasm_exceptions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs index 719499dd8eade..07b8ae6e9d7e5 100644 --- a/tests/codegen/wasm_exceptions.rs +++ b/tests/codegen/wasm_exceptions.rs @@ -1,5 +1,5 @@ //@ only-wasm32 -//@ compile-flags: -C panic=unwind +//@ compile-flags: -C panic=unwind -Z emscripten-wasm-eh #![crate_type = "lib"] #![feature(core_intrinsics)] From 644e527c17a1b53e60a346cce7b6b32d97b9d10d Mon Sep 17 00:00:00 2001 From: Alisa Sireneva Date: Tue, 28 Jan 2025 19:07:12 +0300 Subject: [PATCH 17/23] Fix tests/ui/privacy/sysroot-private --- tests/ui/privacy/sysroot-private.default.stderr | 8 ++++---- tests/ui/privacy/sysroot-private.rs | 1 + .../privacy/sysroot-private.rustc_private_enabled.stderr | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/ui/privacy/sysroot-private.default.stderr b/tests/ui/privacy/sysroot-private.default.stderr index 845d4558d13a0..fef88d107e635 100644 --- a/tests/ui/privacy/sysroot-private.default.stderr +++ b/tests/ui/privacy/sysroot-private.default.stderr @@ -1,11 +1,11 @@ error[E0405]: cannot find trait `Equivalent` in this scope - --> $DIR/sysroot-private.rs:26:18 + --> $DIR/sysroot-private.rs:27:18 | LL | trait Trait2: Equivalent {} | ^^^^^^^^^^ not found in this scope error[E0412]: cannot find type `K` in this scope - --> $DIR/sysroot-private.rs:31:35 + --> $DIR/sysroot-private.rs:32:35 | LL | fn trait_member(val: &T, key: &K) -> bool { | - ^ @@ -22,13 +22,13 @@ LL | fn trait_member(val: &T, key: &K) -> bool { | +++ error[E0220]: associated type `ExpressionStack` not found for `Trait` - --> $DIR/sysroot-private.rs:21:31 + --> $DIR/sysroot-private.rs:22:31 | LL | type AssociatedTy = dyn Trait; | ^^^^^^^^^^^^^^^ help: `Trait` has the following associated type: `Bar` error[E0425]: cannot find function `memchr2` in this scope - --> $DIR/sysroot-private.rs:39:5 + --> $DIR/sysroot-private.rs:40:5 | LL | memchr2(b'a', b'b', buf) | ^^^^^^^ not found in this scope diff --git a/tests/ui/privacy/sysroot-private.rs b/tests/ui/privacy/sysroot-private.rs index 67ab67c7f5c53..8681857459273 100644 --- a/tests/ui/privacy/sysroot-private.rs +++ b/tests/ui/privacy/sysroot-private.rs @@ -7,6 +7,7 @@ //! of `std`'s dependencies, but may not be robust against dependency upgrades/changes. //@ only-unix Windows sysroots seem to not expose this dependency +//@ ignore-emscripten neither does Emscripten //@ revisions: default rustc_private_enabled // Enabling `rustc_private` should `std`'s dependencies accessible, so they should show up diff --git a/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr index 98e6922428a90..4b54b59714aa6 100644 --- a/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr +++ b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr @@ -1,11 +1,11 @@ error[E0405]: cannot find trait `Equivalent` in this scope - --> $DIR/sysroot-private.rs:26:18 + --> $DIR/sysroot-private.rs:27:18 | LL | trait Trait2: Equivalent {} | ^^^^^^^^^^ not found in this scope error[E0412]: cannot find type `K` in this scope - --> $DIR/sysroot-private.rs:31:35 + --> $DIR/sysroot-private.rs:32:35 | LL | fn trait_member(val: &T, key: &K) -> bool { | - ^ @@ -22,13 +22,13 @@ LL | fn trait_member(val: &T, key: &K) -> bool { | +++ error[E0220]: associated type `ExpressionStack` not found for `Trait` - --> $DIR/sysroot-private.rs:21:31 + --> $DIR/sysroot-private.rs:22:31 | LL | type AssociatedTy = dyn Trait; | ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` error[E0425]: cannot find function `memchr2` in this scope - --> $DIR/sysroot-private.rs:39:5 + --> $DIR/sysroot-private.rs:40:5 | LL | memchr2(b'a', b'b', buf) | ^^^^^^^ not found in this scope From 57cfcd228dd6b5873c96799c64c6186fa8edec66 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 23 Jan 2025 10:16:08 +0100 Subject: [PATCH 18/23] use impl Into --- compiler/rustc_parse_format/src/lib.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 09c88e7f83bb6..d021ea107ed28 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -363,12 +363,7 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err, S2: Into>( - &mut self, - description: S1, - label: S2, - span: InnerSpan, - ) { + fn err(&mut self, description: impl Into, label: impl Into, span: InnerSpan) { self.errors.push(ParseError { description: description.into(), note: None, @@ -382,11 +377,11 @@ impl<'a> Parser<'a> { /// Notifies of an error. The message doesn't actually need to be of type /// String, but I think it does when this eventually uses conditions so it /// might as well start using it now. - fn err_with_note, S2: Into, S3: Into>( + fn err_with_note( &mut self, - description: S1, - label: S2, - note: S3, + description: impl Into, + label: impl Into, + note: impl Into, span: InnerSpan, ) { self.errors.push(ParseError { From 22f074129a27e229b30c69b8e8d600dee3593537 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Jan 2025 11:59:29 +0000 Subject: [PATCH 19/23] Add tests for transmuting pattern types --- tests/ui/type/pattern_types/transmute.rs | 34 +++++++++++++++++ tests/ui/type/pattern_types/transmute.stderr | 39 ++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/ui/type/pattern_types/transmute.rs create mode 100644 tests/ui/type/pattern_types/transmute.stderr diff --git a/tests/ui/type/pattern_types/transmute.rs b/tests/ui/type/pattern_types/transmute.rs new file mode 100644 index 0000000000000..54aab6e3cb248 --- /dev/null +++ b/tests/ui/type/pattern_types/transmute.rs @@ -0,0 +1,34 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +// ok +fn create(x: u32) -> pattern_type!(u32 is S..=E) { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +// ok +fn unwrap(x: pattern_type!(u32 is S..=E)) -> u32 { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +// bad, only when S != u32::MIN or E != u32::MAX will this ok +fn non_base_ty_transmute( + x: Option, +) -> u32 { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +// bad, only when S = u32::MIN and E = u32::MAX will this ok +fn wrapped_transmute( + x: Option, +) -> Option { + unsafe { std::mem::transmute(x) } + //~^ ERROR types of different sizes +} + +fn main() {} diff --git a/tests/ui/type/pattern_types/transmute.stderr b/tests/ui/type/pattern_types/transmute.stderr new file mode 100644 index 0000000000000..f348740b10597 --- /dev/null +++ b/tests/ui/type/pattern_types/transmute.stderr @@ -0,0 +1,39 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:8:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u32` (32 bits) + = note: target type: `(u32) is S..=E` (size can vary because of u32) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:14:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `(u32) is S..=E` (size can vary because of u32) + = note: target type: `u32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:22:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<(u32) is S..=E>` (size can vary because of u32) + = note: target type: `u32` (32 bits) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute.rs:30:14 + | +LL | unsafe { std::mem::transmute(x) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `Option<(u32) is S..=E>` (size can vary because of u32) + = note: target type: `Option` (64 bits) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0512`. From a639e276f3bfb0e0538bad78f3d68ebb7877aeaa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Jan 2025 11:08:22 +0000 Subject: [PATCH 20/23] Allow transmuting generic pattern types to and from their base --- compiler/rustc_middle/src/ty/layout.rs | 3 +++ tests/ui/type/pattern_types/transmute.rs | 2 -- tests/ui/type/pattern_types/transmute.stderr | 24 +++----------------- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0d41a1d7dbfba..b212992bd2dd7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -504,6 +504,9 @@ impl<'tcx> SizeSkeleton<'tcx> { } } + // Pattern types are always the same size as their base. + ty::Pat(base, _) => SizeSkeleton::compute(base, tcx, typing_env), + _ => Err(err), } } diff --git a/tests/ui/type/pattern_types/transmute.rs b/tests/ui/type/pattern_types/transmute.rs index 54aab6e3cb248..cb76b2b938dc6 100644 --- a/tests/ui/type/pattern_types/transmute.rs +++ b/tests/ui/type/pattern_types/transmute.rs @@ -6,13 +6,11 @@ use std::pat::pattern_type; // ok fn create(x: u32) -> pattern_type!(u32 is S..=E) { unsafe { std::mem::transmute(x) } - //~^ ERROR types of different sizes } // ok fn unwrap(x: pattern_type!(u32 is S..=E)) -> u32 { unsafe { std::mem::transmute(x) } - //~^ ERROR types of different sizes } // bad, only when S != u32::MIN or E != u32::MAX will this ok diff --git a/tests/ui/type/pattern_types/transmute.stderr b/tests/ui/type/pattern_types/transmute.stderr index f348740b10597..578549b515c10 100644 --- a/tests/ui/type/pattern_types/transmute.stderr +++ b/tests/ui/type/pattern_types/transmute.stderr @@ -1,23 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute.rs:8:14 - | -LL | unsafe { std::mem::transmute(x) } - | ^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `u32` (32 bits) - = note: target type: `(u32) is S..=E` (size can vary because of u32) - -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute.rs:14:14 - | -LL | unsafe { std::mem::transmute(x) } - | ^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `(u32) is S..=E` (size can vary because of u32) - = note: target type: `u32` (32 bits) - -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute.rs:22:14 + --> $DIR/transmute.rs:20:14 | LL | unsafe { std::mem::transmute(x) } | ^^^^^^^^^^^^^^^^^^^ @@ -26,7 +8,7 @@ LL | unsafe { std::mem::transmute(x) } = note: target type: `u32` (32 bits) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute.rs:30:14 + --> $DIR/transmute.rs:28:14 | LL | unsafe { std::mem::transmute(x) } | ^^^^^^^^^^^^^^^^^^^ @@ -34,6 +16,6 @@ LL | unsafe { std::mem::transmute(x) } = note: source type: `Option<(u32) is S..=E>` (size can vary because of u32) = note: target type: `Option` (64 bits) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0512`. From 89de239fa003a98f640430b74eb0cd6e6220f0ba Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Wed, 29 Jan 2025 12:34:37 +0100 Subject: [PATCH 21/23] ci: refactor how directories are removed in free-disk-space disk --- src/ci/scripts/free-disk-space.sh | 46 +++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh index 4a7dad0090b2e..fe7a3b2dc2fc6 100755 --- a/src/ci/scripts/free-disk-space.sh +++ b/src/ci/scripts/free-disk-space.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -euo pipefail # Free disk space on Linux GitHub action runners # Script inspired by https://github.com/jlumbroso/free-disk-space @@ -14,11 +15,15 @@ printSeparationLine() { # compute available space # REF: https://unix.stackexchange.com/a/42049/60849 # REF: https://stackoverflow.com/a/450821/408734 -getAvailableSpace() { echo $(df -a | awk 'NR > 1 {avail+=$4} END {print avail}'); } +getAvailableSpace() { + df -a | awk 'NR > 1 {avail+=$4} END {print avail}' +} # make Kb human readable (assume the input is Kb) # REF: https://unix.stackexchange.com/a/44087/60849 -formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); } +formatByteCount() { + numfmt --to=iec-i --suffix=B --padding=7 "$1"'000' +} # macro to output saved space printSavedSpace() { @@ -58,11 +63,27 @@ removeDir() { dir=${1} local before - before=$(getAvailableSpace) + if [ ! -d "$dir" ]; then + echo "::warning::Directory $dir does not exist, skipping." + else + before=$(getAvailableSpace) + sudo rm -rf "$dir" + printSavedSpace "$before" "Removed $dir" + fi +} - sudo rm -rf "$dir" || true +removeUnusedDirectories() { + local dirs_to_remove=( + "/usr/local/lib/android" + "/usr/share/dotnet" - printSavedSpace "$before" "$dir" + # Haskell runtime + "/usr/local/.ghcup" + ) + + for dir in "${dirs_to_remove[@]}"; do + removeDir "$dir" + done } execAndMeasureSpaceChange() { @@ -101,9 +122,9 @@ cleanPackages() { # Remove Docker images cleanDocker() { - echo "Removing the following docker images:" + echo "=> Removing the following docker images:" sudo docker image ls - echo "Removing docker images..." + echo "=> Removing docker images..." sudo docker image prune --all --force || true } @@ -121,17 +142,12 @@ AVAILABLE_INITIAL=$(getAvailableSpace) printDF "BEFORE CLEAN-UP:" echo "" -removeDir /usr/local/lib/android -removeDir /usr/share/dotnet - -# Haskell runtime -removeDir /opt/ghc -removeDir /usr/local/.ghcup - -execAndMeasureSpaceChange cleanPackages "Large misc. packages" +execAndMeasureSpaceChange cleanPackages "Unused packages" execAndMeasureSpaceChange cleanDocker "Docker images" execAndMeasureSpaceChange cleanSwap "Swap storage" +removeUnusedDirectories + # Output saved space statistic echo "" printDF "AFTER CLEAN-UP:" From 4cc41a77bd06d481328149848bf3bdff72505486 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Jan 2025 19:50:33 +0000 Subject: [PATCH 22/23] Move fulfillment error derivation into new module --- .../src/solve/fulfill.rs | 496 +---------------- .../src/solve/fulfill/derive_errors.rs | 499 ++++++++++++++++++ .../rustc_trait_selection/src/traits/mod.rs | 7 +- 3 files changed, 506 insertions(+), 496 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 2b7da4bc5ff07..0db44eda8470e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,25 +1,21 @@ use std::marker::PhantomData; use std::mem; -use std::ops::ControlFlow; use rustc_data_structures::thinvec::ExtractIf; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, PredicateObligation, PredicateObligations, SelectionError, TraitEngine, + FromSolverError, PredicateObligation, PredicateObligations, TraitEngine, }; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; -use tracing::{instrument, trace}; +use tracing::instrument; +use self::derive_errors::*; use super::Certainty; use super::delegate::SolverDelegate; -use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError}; +use crate::traits::{FulfillmentError, ScrubbedTraitError}; + +mod derive_errors; /// A trait engine using the new trait solver. /// @@ -244,483 +240,3 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError<' } } } - -fn fulfillment_error_for_no_solution<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - let obligation = find_best_leaf_obligation(infcx, &root_obligation, false); - - let code = match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { - FulfillmentErrorCode::Project( - // FIXME: This could be a `Sorts` if the term is a type - MismatchedProjectionTypes { err: TypeError::Mismatch }, - ) - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { - let ct_ty = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { - infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) - } - ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), - ty::ConstKind::Value(ty, _) => ty, - kind => span_bug!( - obligation.cause.span, - "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}" - ), - }; - FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType { - ct, - ct_ty, - expected_ty, - }) - } - ty::PredicateKind::NormalizesTo(..) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } - ty::PredicateKind::AliasRelate(_, _, _) => { - FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) - } - ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(a, b); - FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) - } - ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.enter_forall_and_leak_universe( - obligation.predicate.kind().rebind((pred.a, pred.b)), - ); - let expected_found = ExpectedFound::new(b, a); - FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) - } - ty::PredicateKind::Clause(_) - | ty::PredicateKind::DynCompatible(_) - | ty::PredicateKind::Ambiguous => { - FulfillmentErrorCode::Select(SelectionError::Unimplemented) - } - ty::PredicateKind::ConstEquate(..) => { - bug!("unexpected goal: {obligation:?}") - } - }; - - FulfillmentError { obligation, code, root_obligation } -} - -fn fulfillment_error_for_stalled<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - let (code, refine_obligation) = infcx.probe(|_| { - match <&SolverDelegate<'tcx>>::from(infcx) - .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No) - .0 - { - Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { - (FulfillmentErrorCode::Ambiguity { overflow: None }, true) - } - Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( - FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, - // Don't look into overflows because we treat overflows weirdly anyways. - // We discard the inference constraints from overflowing goals, so - // recomputing the goal again during `find_best_leaf_obligation` may apply - // inference guidance that makes other goals go from ambig -> pass, for example. - // - // FIXME: We should probably just look into overflows here. - false, - ), - Ok((_, Certainty::Yes)) => { - bug!("did not expect successful goal when collecting ambiguity errors") - } - Err(_) => { - bug!("did not expect selection error when collecting ambiguity errors") - } - } - }); - - FulfillmentError { - obligation: if refine_obligation { - find_best_leaf_obligation(infcx, &root_obligation, true) - } else { - root_obligation.clone() - }, - code, - root_obligation, - } -} - -fn fulfillment_error_for_overflow<'tcx>( - infcx: &InferCtxt<'tcx>, - root_obligation: PredicateObligation<'tcx>, -) -> FulfillmentError<'tcx> { - FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &root_obligation, true), - code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - root_obligation, - } -} - -fn find_best_leaf_obligation<'tcx>( - infcx: &InferCtxt<'tcx>, - obligation: &PredicateObligation<'tcx>, - consider_ambiguities: bool, -) -> PredicateObligation<'tcx> { - let obligation = infcx.resolve_vars_if_possible(obligation.clone()); - // FIXME: we use a probe here as the `BestObligation` visitor does not - // check whether it uses candidates which get shadowed by where-bounds. - // - // We should probably fix the visitor to not do so instead, as this also - // means the leaf obligation may be incorrect. - infcx - .fudge_inference_if_ok(|| { - infcx - .visit_proof_tree(obligation.clone().into(), &mut BestObligation { - obligation: obligation.clone(), - consider_ambiguities, - }) - .break_value() - .ok_or(()) - }) - .unwrap_or(obligation) -} - -struct BestObligation<'tcx> { - obligation: PredicateObligation<'tcx>, - consider_ambiguities: bool, -} - -impl<'tcx> BestObligation<'tcx> { - fn with_derived_obligation( - &mut self, - derived_obligation: PredicateObligation<'tcx>, - and_then: impl FnOnce(&mut Self) -> >::Result, - ) -> >::Result { - let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); - let res = and_then(self); - self.obligation = old_obligation; - res - } - - /// Filter out the candidates that aren't interesting to visit for the - /// purposes of reporting errors. For ambiguities, we only consider - /// candidates that may hold. For errors, we only consider candidates that - /// *don't* hold and which have impl-where clauses that also don't hold. - fn non_trivial_candidates<'a>( - &self, - goal: &'a inspect::InspectGoal<'a, 'tcx>, - ) -> Vec> { - let mut candidates = goal.candidates(); - match self.consider_ambiguities { - true => { - // If we have an ambiguous obligation, we must consider *all* candidates - // that hold, or else we may guide inference causing other goals to go - // from ambig -> pass/fail. - candidates.retain(|candidate| candidate.result().is_ok()); - } - false => { - // If we have >1 candidate, one may still be due to "boring" reasons, like - // an alias-relate that failed to hold when deeply evaluated. We really - // don't care about reasons like this. - if candidates.len() > 1 { - candidates.retain(|candidate| { - goal.infcx().probe(|_| { - candidate.instantiate_nested_goals(self.span()).iter().any( - |nested_goal| { - matches!( - nested_goal.source(), - GoalSource::ImplWhereBound - | GoalSource::AliasBoundConstCondition - | GoalSource::InstantiateHigherRanked - | GoalSource::AliasWellFormed - ) && match self.consider_ambiguities { - true => { - matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) - } - false => matches!(nested_goal.result(), Err(_)), - } - }, - ) - }) - }); - } - - // Prefer a non-rigid candidate if there is one. - if candidates.len() > 1 { - candidates.retain(|candidate| { - !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. }) - }); - } - } - } - - candidates - } -} - -impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { - type Result = ControlFlow>; - - fn span(&self) -> rustc_span::Span { - self.obligation.cause.span - } - - #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))] - fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { - let candidates = self.non_trivial_candidates(goal); - trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::>()); - - let [candidate] = candidates.as_slice() else { - return ControlFlow::Break(self.obligation.clone()); - }; - - // Don't walk into impls that have `do_not_recommend`. - if let inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } = candidate.kind() - && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) - { - return ControlFlow::Break(self.obligation.clone()); - } - - let tcx = goal.infcx().tcx; - // FIXME: Also, what about considering >1 layer up the stack? May be necessary - // for normalizes-to. - let pred_kind = goal.goal().predicate.kind(); - let child_mode = match pred_kind.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - ChildMode::Trait(pred_kind.rebind(pred)) - } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { - ChildMode::Host(pred_kind.rebind(pred)) - } - ty::PredicateKind::NormalizesTo(normalizes_to) - if matches!( - normalizes_to.alias.kind(tcx), - ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst - ) => - { - ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { - trait_ref: normalizes_to.alias.trait_ref(tcx), - polarity: ty::PredicatePolarity::Positive, - })) - } - _ => ChildMode::PassThrough, - }; - - let nested_goals = candidate.instantiate_nested_goals(self.span()); - - // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as - // an actual candidate, instead we should treat them as if the impl was never considered to - // have potentially applied. As if `impl Trait for for<..> fn(..A) -> R` was written - // instead of `impl Trait for T`. - // - // We do this as a separate loop so that we do not choose to tell the user about some nested - // goal before we encounter a `T: FnPtr` nested goal. - for nested_goal in &nested_goals { - if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait() - && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause() - && poly_trait_pred.def_id() == fn_ptr_trait - && let Err(NoSolution) = nested_goal.result() - { - return ControlFlow::Break(self.obligation.clone()); - } - } - - let mut impl_where_bound_count = 0; - for nested_goal in nested_goals { - trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); - - let make_obligation = |cause| Obligation { - cause, - param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, - recursion_depth: self.obligation.recursion_depth + 1, - }; - - let obligation; - match (child_mode, nested_goal.source()) { - (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => { - continue; - } - (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { - obligation = make_obligation(derive_cause( - tcx, - candidate.kind(), - self.obligation.cause.clone(), - impl_where_bound_count, - parent_trait_pred, - )); - impl_where_bound_count += 1; - } - ( - ChildMode::Host(parent_host_pred), - GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, - ) => { - obligation = make_obligation(derive_host_cause( - tcx, - candidate.kind(), - self.obligation.cause.clone(), - impl_where_bound_count, - parent_host_pred, - )); - impl_where_bound_count += 1; - } - // Skip over a higher-ranked predicate. - (_, GoalSource::InstantiateHigherRanked) => { - obligation = self.obligation.clone(); - } - (ChildMode::PassThrough, _) - | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { - obligation = make_obligation(self.obligation.cause.clone()); - } - } - - // Skip nested goals that aren't the *reason* for our goal's failure. - match self.consider_ambiguities { - true if matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) => {} - false if matches!(nested_goal.result(), Err(_)) => {} - _ => continue, - } - - self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; - } - - // alias-relate may fail because the lhs or rhs can't be normalized, - // and therefore is treated as rigid. - if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { - if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } else if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } - } - - ControlFlow::Break(self.obligation.clone()) - } -} - -#[derive(Debug, Copy, Clone)] -enum ChildMode<'tcx> { - // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, - // and skip all `GoalSource::Misc`, which represent useless obligations - // such as alias-eq which may not hold. - Trait(ty::PolyTraitPredicate<'tcx>), - // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, - // and skip all `GoalSource::Misc`, which represent useless obligations - // such as alias-eq which may not hold. - Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>), - // Skip trying to derive an `ObligationCause` from this obligation, and - // report *all* sub-obligations as if they came directly from the parent - // obligation. - PassThrough, -} - -fn derive_cause<'tcx>( - tcx: TyCtxt<'tcx>, - candidate_kind: inspect::ProbeKind>, - mut cause: ObligationCause<'tcx>, - idx: usize, - parent_trait_pred: ty::PolyTraitPredicate<'tcx>, -) -> ObligationCause<'tcx> { - match candidate_kind { - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } => { - if let Some((_, span)) = - tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) - { - cause = cause.derived_cause(parent_trait_pred, |derived| { - ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause { - derived, - impl_or_alias_def_id: impl_def_id, - impl_def_predicate_index: Some(idx), - span, - })) - }) - } - } - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(..), - result: _, - } => { - cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived); - } - _ => {} - }; - cause -} - -fn derive_host_cause<'tcx>( - tcx: TyCtxt<'tcx>, - candidate_kind: inspect::ProbeKind>, - mut cause: ObligationCause<'tcx>, - idx: usize, - parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, -) -> ObligationCause<'tcx> { - match candidate_kind { - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::Impl(impl_def_id), - result: _, - } => { - if let Some((_, span)) = tcx - .predicates_of(impl_def_id) - .instantiate_identity(tcx) - .into_iter() - .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map( - |(trait_ref, span)| { - ( - trait_ref.to_host_effect_clause( - tcx, - parent_host_pred.skip_binder().constness, - ), - span, - ) - }, - )) - .nth(idx) - { - cause = - cause.derived_host_cause(parent_host_pred, |derived| { - ObligationCauseCode::ImplDerivedHost(Box::new( - traits::ImplDerivedHostCause { derived, impl_def_id, span }, - )) - }) - } - } - inspect::ProbeKind::TraitCandidate { - source: CandidateSource::BuiltinImpl(..), - result: _, - } => { - cause = - cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost); - } - _ => {} - }; - cause -} diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs new file mode 100644 index 0000000000000..325808899340f --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -0,0 +1,499 @@ +use std::ops::ControlFlow; + +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; +use rustc_infer::traits::{ + self, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, + PredicateObligation, SelectionError, +}; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{bug, span_bug}; +use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; +use rustc_type_ir::solve::NoSolution; +use tracing::{instrument, trace}; + +use crate::solve::Certainty; +use crate::solve::delegate::SolverDelegate; +use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use crate::traits::{FulfillmentError, FulfillmentErrorCode}; + +pub(super) fn fulfillment_error_for_no_solution<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + let obligation = find_best_leaf_obligation(infcx, &root_obligation, false); + + let code = match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { + FulfillmentErrorCode::Project( + // FIXME: This could be a `Sorts` if the term is a type + MismatchedProjectionTypes { err: TypeError::Mismatch }, + ) + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { + let ct_ty = match ct.kind() { + ty::ConstKind::Unevaluated(uv) => { + infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) + } + ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(obligation.param_env), + ty::ConstKind::Value(ty, _) => ty, + kind => span_bug!( + obligation.cause.span, + "ConstArgHasWrongType failed but we don't know how to compute type for {kind:?}" + ), + }; + FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType { + ct, + ct_ty, + expected_ty, + }) + } + ty::PredicateKind::NormalizesTo(..) => { + FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) + } + ty::PredicateKind::AliasRelate(_, _, _) => { + FulfillmentErrorCode::Project(MismatchedProjectionTypes { err: TypeError::Mismatch }) + } + ty::PredicateKind::Subtype(pred) => { + let (a, b) = infcx.enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(a, b); + FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) + } + ty::PredicateKind::Coerce(pred) => { + let (a, b) = infcx.enter_forall_and_leak_universe( + obligation.predicate.kind().rebind((pred.a, pred.b)), + ); + let expected_found = ExpectedFound::new(b, a); + FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) + } + ty::PredicateKind::Clause(_) + | ty::PredicateKind::DynCompatible(_) + | ty::PredicateKind::Ambiguous => { + FulfillmentErrorCode::Select(SelectionError::Unimplemented) + } + ty::PredicateKind::ConstEquate(..) => { + bug!("unexpected goal: {obligation:?}") + } + }; + + FulfillmentError { obligation, code, root_obligation } +} + +pub(super) fn fulfillment_error_for_stalled<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + let (code, refine_obligation) = infcx.probe(|_| { + match <&SolverDelegate<'tcx>>::from(infcx) + .evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No) + .0 + { + Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { + (FulfillmentErrorCode::Ambiguity { overflow: None }, true) + } + Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( + FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, + // Don't look into overflows because we treat overflows weirdly anyways. + // We discard the inference constraints from overflowing goals, so + // recomputing the goal again during `find_best_leaf_obligation` may apply + // inference guidance that makes other goals go from ambig -> pass, for example. + // + // FIXME: We should probably just look into overflows here. + false, + ), + Ok((_, Certainty::Yes)) => { + bug!("did not expect successful goal when collecting ambiguity errors") + } + Err(_) => { + bug!("did not expect selection error when collecting ambiguity errors") + } + } + }); + + FulfillmentError { + obligation: if refine_obligation { + find_best_leaf_obligation(infcx, &root_obligation, true) + } else { + root_obligation.clone() + }, + code, + root_obligation, + } +} + +pub(super) fn fulfillment_error_for_overflow<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &root_obligation, true), + code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, + root_obligation, + } +} + +fn find_best_leaf_obligation<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, + consider_ambiguities: bool, +) -> PredicateObligation<'tcx> { + let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + // FIXME: we use a probe here as the `BestObligation` visitor does not + // check whether it uses candidates which get shadowed by where-bounds. + // + // We should probably fix the visitor to not do so instead, as this also + // means the leaf obligation may be incorrect. + infcx + .fudge_inference_if_ok(|| { + infcx + .visit_proof_tree(obligation.clone().into(), &mut BestObligation { + obligation: obligation.clone(), + consider_ambiguities, + }) + .break_value() + .ok_or(()) + }) + .unwrap_or(obligation) +} + +struct BestObligation<'tcx> { + obligation: PredicateObligation<'tcx>, + consider_ambiguities: bool, +} + +impl<'tcx> BestObligation<'tcx> { + fn with_derived_obligation( + &mut self, + derived_obligation: PredicateObligation<'tcx>, + and_then: impl FnOnce(&mut Self) -> >::Result, + ) -> >::Result { + let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); + let res = and_then(self); + self.obligation = old_obligation; + res + } + + /// Filter out the candidates that aren't interesting to visit for the + /// purposes of reporting errors. For ambiguities, we only consider + /// candidates that may hold. For errors, we only consider candidates that + /// *don't* hold and which have impl-where clauses that also don't hold. + fn non_trivial_candidates<'a>( + &self, + goal: &'a inspect::InspectGoal<'a, 'tcx>, + ) -> Vec> { + let mut candidates = goal.candidates(); + match self.consider_ambiguities { + true => { + // If we have an ambiguous obligation, we must consider *all* candidates + // that hold, or else we may guide inference causing other goals to go + // from ambig -> pass/fail. + candidates.retain(|candidate| candidate.result().is_ok()); + } + false => { + // If we have >1 candidate, one may still be due to "boring" reasons, like + // an alias-relate that failed to hold when deeply evaluated. We really + // don't care about reasons like this. + if candidates.len() > 1 { + candidates.retain(|candidate| { + goal.infcx().probe(|_| { + candidate.instantiate_nested_goals(self.span()).iter().any( + |nested_goal| { + matches!( + nested_goal.source(), + GoalSource::ImplWhereBound + | GoalSource::AliasBoundConstCondition + | GoalSource::InstantiateHigherRanked + | GoalSource::AliasWellFormed + ) && match self.consider_ambiguities { + true => { + matches!( + nested_goal.result(), + Ok(Certainty::Maybe(MaybeCause::Ambiguity)) + ) + } + false => matches!(nested_goal.result(), Err(_)), + } + }, + ) + }) + }); + } + + // Prefer a non-rigid candidate if there is one. + if candidates.len() > 1 { + candidates.retain(|candidate| { + !matches!(candidate.kind(), inspect::ProbeKind::RigidAlias { .. }) + }); + } + } + } + + candidates + } +} + +impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { + type Result = ControlFlow>; + + fn span(&self) -> rustc_span::Span { + self.obligation.cause.span + } + + #[instrument(level = "trace", skip(self, goal), fields(goal = ?goal.goal()))] + fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + let candidates = self.non_trivial_candidates(goal); + trace!(candidates = ?candidates.iter().map(|c| c.kind()).collect::>()); + + let [candidate] = candidates.as_slice() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + // Don't walk into impls that have `do_not_recommend`. + if let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } = candidate.kind() + && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) + { + return ControlFlow::Break(self.obligation.clone()); + } + + let tcx = goal.infcx().tcx; + // FIXME: Also, what about considering >1 layer up the stack? May be necessary + // for normalizes-to. + let pred_kind = goal.goal().predicate.kind(); + let child_mode = match pred_kind.skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + ChildMode::Trait(pred_kind.rebind(pred)) + } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { + ChildMode::Host(pred_kind.rebind(pred)) + } + ty::PredicateKind::NormalizesTo(normalizes_to) + if matches!( + normalizes_to.alias.kind(tcx), + ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst + ) => + { + ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { + trait_ref: normalizes_to.alias.trait_ref(tcx), + polarity: ty::PredicatePolarity::Positive, + })) + } + _ => ChildMode::PassThrough, + }; + + let nested_goals = candidate.instantiate_nested_goals(self.span()); + + // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as + // an actual candidate, instead we should treat them as if the impl was never considered to + // have potentially applied. As if `impl Trait for for<..> fn(..A) -> R` was written + // instead of `impl Trait for T`. + // + // We do this as a separate loop so that we do not choose to tell the user about some nested + // goal before we encounter a `T: FnPtr` nested goal. + for nested_goal in &nested_goals { + if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait() + && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause() + && poly_trait_pred.def_id() == fn_ptr_trait + && let Err(NoSolution) = nested_goal.result() + { + return ControlFlow::Break(self.obligation.clone()); + } + } + + let mut impl_where_bound_count = 0; + for nested_goal in nested_goals { + trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); + + let make_obligation = |cause| Obligation { + cause, + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + + let obligation; + match (child_mode, nested_goal.source()) { + (ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => { + continue; + } + (ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => { + obligation = make_obligation(derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + )); + impl_where_bound_count += 1; + } + ( + ChildMode::Host(parent_host_pred), + GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition, + ) => { + obligation = make_obligation(derive_host_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_host_pred, + )); + impl_where_bound_count += 1; + } + // Skip over a higher-ranked predicate. + (_, GoalSource::InstantiateHigherRanked) => { + obligation = self.obligation.clone(); + } + (ChildMode::PassThrough, _) + | (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => { + obligation = make_obligation(self.obligation.cause.clone()); + } + } + + // Skip nested goals that aren't the *reason* for our goal's failure. + match self.consider_ambiguities { + true if matches!( + nested_goal.result(), + Ok(Certainty::Maybe(MaybeCause::Ambiguity)) + ) => {} + false if matches!(nested_goal.result(), Err(_)) => {} + _ => continue, + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + // alias-relate may fail because the lhs or rhs can't be normalized, + // and therefore is treated as rigid. + if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { + if let Some(obligation) = goal + .infcx() + .visit_proof_tree_at_depth( + goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())), + goal.depth() + 1, + self, + ) + .break_value() + { + return ControlFlow::Break(obligation); + } else if let Some(obligation) = goal + .infcx() + .visit_proof_tree_at_depth( + goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())), + goal.depth() + 1, + self, + ) + .break_value() + { + return ControlFlow::Break(obligation); + } + } + + ControlFlow::Break(self.obligation.clone()) + } +} + +#[derive(Debug, Copy, Clone)] +enum ChildMode<'tcx> { + // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, + // and skip all `GoalSource::Misc`, which represent useless obligations + // such as alias-eq which may not hold. + Trait(ty::PolyTraitPredicate<'tcx>), + // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, + // and skip all `GoalSource::Misc`, which represent useless obligations + // such as alias-eq which may not hold. + Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>), + // Skip trying to derive an `ObligationCause` from this obligation, and + // report *all* sub-obligations as if they came directly from the parent + // obligation. + PassThrough, +} + +fn derive_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: inspect::ProbeKind>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, +) -> ObligationCause<'tcx> { + match candidate_kind { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } => { + if let Some((_, span)) = + tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) + { + cause = cause.derived_cause(parent_trait_pred, |derived| { + ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause { + derived, + impl_or_alias_def_id: impl_def_id, + impl_def_predicate_index: Some(idx), + span, + })) + }) + } + } + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::BuiltinImpl(..), + result: _, + } => { + cause = cause.derived_cause(parent_trait_pred, ObligationCauseCode::BuiltinDerived); + } + _ => {} + }; + cause +} + +fn derive_host_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: inspect::ProbeKind>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>, +) -> ObligationCause<'tcx> { + match candidate_kind { + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::Impl(impl_def_id), + result: _, + } => { + if let Some((_, span)) = tcx + .predicates_of(impl_def_id) + .instantiate_identity(tcx) + .into_iter() + .chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map( + |(trait_ref, span)| { + ( + trait_ref.to_host_effect_clause( + tcx, + parent_host_pred.skip_binder().constness, + ), + span, + ) + }, + )) + .nth(idx) + { + cause = + cause.derived_host_cause(parent_host_pred, |derived| { + ObligationCauseCode::ImplDerivedHost(Box::new( + traits::ImplDerivedHostCause { derived, impl_def_id, span }, + )) + }) + } + } + inspect::ProbeKind::TraitCandidate { + source: CandidateSource::BuiltinImpl(..), + result: _, + } => { + cause = + cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost); + } + _ => {} + }; + cause +} diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fe5ad003a7e43..b9d03c4265596 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -76,6 +76,7 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::regions::InferCtxtRegionExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +#[derive(Debug)] pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, @@ -107,12 +108,6 @@ impl<'tcx> FulfillmentError<'tcx> { } } -impl<'tcx> Debug for FulfillmentError<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code) - } -} - #[derive(Clone)] pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only From 94ef5cf293a87dd7a8fba4f05d6216ed7921d4b3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Jan 2025 20:13:36 +0000 Subject: [PATCH 23/23] Manually walk into WF obligations in BestObligation proof tree visitor --- .../src/solve/delegate.rs | 9 +- .../src/solve/fulfill/derive_errors.rs | 60 ++++++++++---- .../src/solve/inspect/analyse.rs | 82 +++++++++++-------- .../query/type_op/implied_outlives_bounds.rs | 6 +- .../rustc_trait_selection/src/traits/wf.rs | 10 ++- .../bugs/wf-check-skipped.next.stderr | 2 + .../const-generics/issues/issue-88119.stderr | 34 ++++---- .../as_expression.next.stderr | 12 +-- .../do_not_recommend/as_expression.rs | 4 +- .../in-trait/alias-bounds-when-not-wf.stderr | 5 ++ ...st-region-infer-to-static-in-binder.stderr | 4 +- .../specialization-transmute.stderr | 7 +- tests/ui/union/union-derive-eq.next.stderr | 2 + .../ui/wf/wf-normalization-sized.next.stderr | 6 ++ tests/ui/wf/wf-trait-fn-arg.next.stderr | 5 ++ tests/ui/wf/wf-trait-fn-ret.next.stderr | 5 ++ .../wf/wf-trait-fn-where-clause.next.stderr | 5 ++ 17 files changed, 158 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index acd00d9f74f56..abb794934324e 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::{ Canonical, CanonicalExt as _, CanonicalQueryInput, CanonicalVarInfo, CanonicalVarValues, @@ -98,9 +98,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< param_env: ty::ParamEnv<'tcx>, arg: ty::GenericArg<'tcx>, ) -> Option>>> { - crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg).map(|obligations| { - obligations.into_iter().map(|obligation| obligation.into()).collect() - }) + crate::traits::wf::unnormalized_obligations(&self.0, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .map(|obligations| { + obligations.into_iter().map(|obligation| obligation.into()).collect() + }) } fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 325808899340f..d13e5a1669421 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -10,13 +10,13 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; -use rustc_type_ir::solve::NoSolution; +use rustc_type_ir::solve::{Goal, NoSolution}; use tracing::{instrument, trace}; use crate::solve::Certainty; use crate::solve::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::traits::{FulfillmentError, FulfillmentErrorCode}; +use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; pub(super) fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, @@ -207,14 +207,10 @@ impl<'tcx> BestObligation<'tcx> { | GoalSource::AliasBoundConstCondition | GoalSource::InstantiateHigherRanked | GoalSource::AliasWellFormed - ) && match self.consider_ambiguities { - true => { - matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) - } - false => matches!(nested_goal.result(), Err(_)), + ) && match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) + | (false, Err(_)) => true, + _ => false, } }, ) @@ -233,6 +229,39 @@ impl<'tcx> BestObligation<'tcx> { candidates } + + /// HACK: We walk the nested obligations for a well-formed arg manually, + /// since there's nontrivial logic in `wf.rs` to set up an obligation cause. + /// Ideally we'd be able to track this better. + fn visit_well_formed_goal( + &mut self, + candidate: &inspect::InspectCandidate<'_, 'tcx>, + arg: ty::GenericArg<'tcx>, + ) -> ControlFlow> { + let infcx = candidate.goal().infcx(); + let param_env = candidate.goal().goal().param_env; + let body_id = self.obligation.cause.body_id; + + for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id) + .into_iter() + .flatten() + { + let nested_goal = candidate.instantiate_proof_tree_for_nested_goal( + GoalSource::Misc, + Goal::new(infcx.tcx, obligation.param_env, obligation.predicate), + self.span(), + ); + // Skip nested goals that aren't the *reason* for our goal's failure. + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} + _ => continue, + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + ControlFlow::Break(self.obligation.clone()) + } } impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { @@ -283,6 +312,9 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { polarity: ty::PredicatePolarity::Positive, })) } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + return self.visit_well_formed_goal(candidate, arg); + } _ => ChildMode::PassThrough, }; @@ -355,12 +387,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } // Skip nested goals that aren't the *reason* for our goal's failure. - match self.consider_ambiguities { - true if matches!( - nested_goal.result(), - Ok(Certainty::Maybe(MaybeCause::Ambiguity)) - ) => {} - false if matches!(nested_goal.result(), Err(_)) => {} + match (self.consider_ambiguities, nested_goal.result()) { + (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} _ => continue, } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index e735020a63e66..9ba48cd588fa1 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -194,47 +194,57 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let goals = instantiated_goals .into_iter() - .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { - Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { - let unconstrained_term = match term.unpack() { - ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(_) => infcx.next_const_var(span).into(), - }; - let goal = - goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); - // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the - // expected term. This means that candidates which only fail due to nested goals - // and which normalize to a different term then the final result could ICE: when - // building their proof tree, the expected term was unconstrained, but when - // instantiating the candidate it is already constrained to the result of another - // candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); - InspectGoal::new( - infcx, - self.goal.depth + 1, - proof_tree.unwrap(), - Some(NormalizesToTermHack { term, unconstrained_term }), - source, - ) - } - _ => { - // We're using a probe here as evaluating a goal could constrain - // inference variables by choosing one candidate. If we then recurse - // into another candidate who ends up with different inference - // constraints, we get an ICE if we already applied the constraints - // from the chosen candidate. - let proof_tree = infcx - .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) - .unwrap(); - InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) - } - }) + .map(|(source, goal)| self.instantiate_proof_tree_for_nested_goal(source, goal, span)) .collect(); (goals, opt_impl_args) } + pub fn instantiate_proof_tree_for_nested_goal( + &self, + source: GoalSource, + goal: Goal<'tcx, ty::Predicate<'tcx>>, + span: Span, + ) -> InspectGoal<'a, 'tcx> { + let infcx = self.goal.infcx; + match goal.predicate.kind().no_bound_vars() { + Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { + let unconstrained_term = match term.unpack() { + ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), + ty::TermKind::Const(_) => infcx.next_const_var(span).into(), + }; + let goal = + goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); + // We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the + // expected term. This means that candidates which only fail due to nested goals + // and which normalize to a different term then the final result could ICE: when + // building their proof tree, the expected term was unconstrained, but when + // instantiating the candidate it is already constrained to the result of another + // candidate. + let proof_tree = + infcx.probe(|_| infcx.evaluate_root_goal_raw(goal, GenerateProofTree::Yes).1); + InspectGoal::new( + infcx, + self.goal.depth + 1, + proof_tree.unwrap(), + Some(NormalizesToTermHack { term, unconstrained_term }), + source, + ) + } + _ => { + // We're using a probe here as evaluating a goal could constrain + // inference variables by choosing one candidate. If we then recurse + // into another candidate who ends up with different inference + // constraints, we get an ICE if we already applied the constraints + // from the chosen candidate. + let proof_tree = infcx + .probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1) + .unwrap(); + InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source) + } + } + } + /// Visit all nested goals of this candidate, rolling back /// all inference constraints. pub fn visit_nested_in_probe>(&self, visitor: &mut V) -> V::Result { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 1339739ce7f5e..ec0b790339691 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -5,8 +5,8 @@ use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds; use rustc_middle::infer::canonical::CanonicalQueryResponse; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt}; -use rustc_span::Span; use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::{DUMMY_SP, Span}; use rustc_type_ir::outlives::{Component, push_outlives_components}; use smallvec::{SmallVec, smallvec}; use tracing::debug; @@ -92,7 +92,9 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( // From the full set of obligations, just filter down to the region relationships. for obligation in - wf::unnormalized_obligations(ocx.infcx, param_env, arg).into_iter().flatten() + wf::unnormalized_obligations(ocx.infcx, param_env, arg, DUMMY_SP, CRATE_DEF_ID) + .into_iter() + .flatten() { assert!(!obligation.has_escaping_bound_vars()); let Some(pred) = obligation.predicate.kind().no_bound_vars() else { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 9d32eb0538606..551a25f1ccc69 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -8,8 +8,8 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; +use rustc_span::def_id::{DefId, LocalDefId}; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -89,6 +89,8 @@ pub fn unnormalized_obligations<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, arg: GenericArg<'tcx>, + span: Span, + body_id: LocalDefId, ) -> Option> { debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg)); @@ -106,8 +108,8 @@ pub fn unnormalized_obligations<'tcx>( let mut wf = WfPredicates { infcx, param_env, - body_id: CRATE_DEF_ID, - span: DUMMY_SP, + body_id, + span, out: PredicateObligations::new(), recursion_depth: 0, item: None, diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr index bf53089675d5b..81ace4ebb6daf 100644 --- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr @@ -5,6 +5,8 @@ LL | fn main() -> Foo::Bar::> {} | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u32]` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-88119.stderr b/tests/ui/const-generics/issues/issue-88119.stderr index f219c90849a26..c497f1b6d0bdb 100644 --- a/tests/ui/const-generics/issues/issue-88119.stderr +++ b/tests/ui/const-generics/issues/issue-88119.stderr @@ -6,35 +6,29 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:19:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:21:5 | -LL | impl const ConstName for &T - | ^^ cannot normalize `<&T as ConstName>::{constant#0}` +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` | -note: required for `&T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:19:35 +note: required by a bound in `<&T as ConstName>` + --> $DIR/issue-88119.rs:21:10 | -LL | impl const ConstName for &T - | ^^^^^^^^^ ^^ -LL | where LL | [(); name_len::()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>` -error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}` - --> $DIR/issue-88119.rs:26:49 +error[E0284]: type annotations needed: cannot satisfy `the constant `name_len::()` can be evaluated` + --> $DIR/issue-88119.rs:28:5 | -LL | impl const ConstName for &mut T - | ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}` +LL | [(); name_len::()]:, + | ^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `name_len::()` can be evaluated` | -note: required for `&mut T` to implement `~const ConstName` - --> $DIR/issue-88119.rs:26:35 +note: required by a bound in `<&mut T as ConstName>` + --> $DIR/issue-88119.rs:28:10 | -LL | impl const ConstName for &mut T - | ^^^^^^^^^ ^^^^^^ -LL | where LL | [(); name_len::()]:, - | --------------------- unsatisfied trait bound introduced here + | ^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>` error: aborting due to 3 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 1b76669ccb0d7..4f685c508c721 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -16,23 +16,13 @@ LL | where LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error[E0277]: the trait bound `&str: AsExpression` is not satisfied - --> $DIR/as_expression.rs:55:15 - | -LL | SelectInt.check("bar"); - | ^^^^^ the trait `AsExpression` is not implemented for `&str` - | - = help: the trait `AsExpression` is not implemented for `&str` - but trait `AsExpression` is implemented for it - = help: for that trait implementation, expected `Text`, found `Integer` - error[E0271]: type mismatch resolving `::SqlType == Text` --> $DIR/as_expression.rs:55:5 | LL | SelectInt.check("bar"); | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0277. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 583b3c4675a87..48c1ed2b02d71 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -53,7 +53,7 @@ impl Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //~^ ERROR the trait bound `&str: AsExpression` is not satisfied - //[next]~| the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[current]~^ ERROR the trait bound `&str: AsExpression` is not satisfied + //[next]~^^ the trait bound `&str: AsExpression<::SqlType>` is not satisfied //[next]~| type mismatch } diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index 1cfc2a6d94495..a95670ced8678 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -18,6 +18,11 @@ help: this trait has no implementations, consider adding one | LL | trait Foo {} | ^^^^^^^^^ +note: required by a bound in `A` + --> $DIR/alias-bounds-when-not-wf.rs:8:11 + | +LL | type A = T; + | ^^^ required by this bound in `A` error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:16:10 diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index 377dfc8b52916..425f2d59222e0 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` +error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }` can be evaluated` --> $DIR/const-region-infer-to-static-in-binder.rs:4:10 | LL | struct X; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index b96bfab927d2d..2d0c503bc958d 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -10,11 +10,11 @@ LL | #![feature(specialization)] error: cannot normalize `::Id: '_` -error[E0284]: type annotations needed: cannot normalize `::Id` +error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot normalize `::Id` + | ^^^^^^^^^ cannot infer type for reference `&::Id` error[E0284]: type annotations needed: cannot satisfy `::Id normalizes-to T` --> $DIR/specialization-transmute.rs:17:9 @@ -36,4 +36,5 @@ LL | fn transmute, U: Copy>(t: T) -> U { error: aborting due to 4 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/union/union-derive-eq.next.stderr b/tests/ui/union/union-derive-eq.next.stderr index 3952b1f12840f..151ceebe1ba67 100644 --- a/tests/ui/union/union-derive-eq.next.stderr +++ b/tests/ui/union/union-derive-eq.next.stderr @@ -7,6 +7,8 @@ LL | union U2 { LL | a: PartialEqNotEq, | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` | diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 1e898fb7b78ab..83b56bb6b19ad 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -5,6 +5,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:19:11 @@ -13,6 +14,7 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `str` cannot be known at compilation time @@ -22,6 +24,8 @@ LL | const _: as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:22:11 @@ -30,6 +34,8 @@ LL | const _: as WellUnformed>::RequestNormalize = (); | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/wf/wf-trait-fn-arg.next.stderr b/tests/ui/wf/wf-trait-fn-arg.next.stderr index c55dc5c8a121a..d5dd36fad6dd6 100644 --- a/tests/ui/wf/wf-trait-fn-arg.next.stderr +++ b/tests/ui/wf/wf-trait-fn-arg.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self, x: &Bar); | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-arg.rs:11:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self, x: &Bar) where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-ret.next.stderr b/tests/ui/wf/wf-trait-fn-ret.next.stderr index b3dca17672d31..0ad786c2fd566 100644 --- a/tests/ui/wf/wf-trait-fn-ret.next.stderr +++ b/tests/ui/wf/wf-trait-fn-ret.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | fn bar(&self) -> &Bar; | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-ret.rs:10:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self) -> &Bar where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr index 8c8a5fa3e7041..db5454d0f3c22 100644 --- a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr +++ b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr @@ -4,6 +4,11 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied LL | Bar: Copy; | ^^^^ the trait `Eq` is not implemented for `Self` | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:10:15 + | +LL | struct Bar { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | Bar: Copy, Self: Eq;