diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 1d7852d964c1d..1bdad508daa2d 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -265,6 +265,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { if def.variants.len() > 1 { needs_to_be_read = true; } + } else { + // If it is not ty::Adt, then it should be read + needs_to_be_read = true; } } PatKind::Lit(_) | PatKind::Range(..) => { diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87988.rs b/src/test/ui/closures/2229_closure_analysis/issue-87988.rs new file mode 100644 index 0000000000000..27e7fabf11ab6 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/issue-87988.rs @@ -0,0 +1,19 @@ +// run-pass +// edition:2021 + +const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: i32 = 0x01; +const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: i32 = 0x02; + +pub fn hotplug_callback(event: i32) { + let _ = || { + match event { + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => (), + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => (), + _ => (), + }; + }; +} + +fn main() { + hotplug_callback(1); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs new file mode 100644 index 0000000000000..914ebbe26a57d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs @@ -0,0 +1,44 @@ +// run-pass +// edition:2021 + +const PATTERN_REF: &str = "Hello World"; +const NUMBER: i32 = 30; +const NUMBER_POINTER: *const i32 = &NUMBER; + +pub fn edge_case_ref(event: &str) { + let _ = || { + match event { + PATTERN_REF => (), + _ => (), + }; + }; +} + +pub fn edge_case_str(event: String) { + let _ = || { + match event.as_str() { + "hello" => (), + _ => (), + }; + }; +} + +pub fn edge_case_raw_ptr(event: *const i32) { + let _ = || { + match event { + NUMBER_POINTER => (), + _ => (), + }; + }; +} + +pub fn edge_case_char(event: char) { + let _ = || { + match event { + 'a' => (), + _ => (), + }; + }; +} + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/match/const_non_normal_zst_ref_pattern.rs b/src/test/ui/closures/2229_closure_analysis/match/const_non_normal_zst_ref_pattern.rs new file mode 100644 index 0000000000000..deba99d98bb42 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/const_non_normal_zst_ref_pattern.rs @@ -0,0 +1,12 @@ +// check-pass +// edition:2021 + +const FOO: isize = 10; +const ZST: &() = unsafe { std::mem::transmute(FOO) }; +fn main() { + || { + match &() { + ZST => 9, + }; + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic-fn.rs b/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic-fn.rs new file mode 100644 index 0000000000000..9b4e48728a735 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic-fn.rs @@ -0,0 +1,22 @@ +// run-fail +// edition:2021 +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn f() -> ! { + panic!() +} + +fn g() -> isize { + let x = || { + match true { + true => f(), + false => 10, + } + }; + return x(); +} + +fn main() { + g(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic.rs b/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic.rs new file mode 100644 index 0000000000000..be34c66c530d6 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/expr-match-panic.rs @@ -0,0 +1,15 @@ +// run-fail +// edition:2021 +// error-pattern:explicit panic +// ignore-emscripten no processes + +fn main() { + let c = || { + let _x = match true { + false => 0, + true => panic!(), + }; + }; + c(); + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.rs new file mode 100644 index 0000000000000..f5b021d04fea8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.rs @@ -0,0 +1,14 @@ +// edition:2021 +const F: &'static dyn Send = &7u32; + +fn main() { + || { + let a: &dyn Send = &7u32; + match a { + F => panic!(), + //~^ ERROR `&dyn Send` cannot be used in patterns + _ => {} + }; + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.stderr new file mode 100644 index 0000000000000..2fe359c553f99 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-70972-dyn-trait.stderr @@ -0,0 +1,8 @@ +error: `&dyn Send` cannot be used in patterns + --> $DIR/issue-70972-dyn-trait.rs:8:13 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-72680.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-72680.rs new file mode 100644 index 0000000000000..589279fd06eb9 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-72680.rs @@ -0,0 +1,76 @@ +// run-pass +// edition:2021 + +fn main() { + assert!(f("", 0)); + assert!(f("a", 1)); + assert!(f("b", 1)); + + assert!(!f("", 1)); + assert!(!f("a", 0)); + assert!(!f("b", 0)); + + assert!(!f("asdf", 32)); + + //// + + assert!(!g(true, true, true)); + assert!(!g(false, true, true)); + assert!(!g(true, false, true)); + assert!(!g(false, false, true)); + assert!(!g(true, true, false)); + + assert!(g(false, true, false)); + assert!(g(true, false, false)); + assert!(g(false, false, false)); + + //// + + assert!(!h(true, true, true)); + assert!(!h(false, true, true)); + assert!(!h(true, false, true)); + assert!(!h(false, false, true)); + assert!(!h(true, true, false)); + + assert!(h(false, true, false)); + assert!(h(true, false, false)); + assert!(h(false, false, false)); +} + +fn f(s: &str, num: usize) -> bool { + let c = || { + match (s, num) { + ("", 0) | ("a" | "b", 1) => true, + + _ => false, + } + }; + c() + +} + +fn g(x: bool, y: bool, z: bool) -> bool { + let c = || { + match (x, y, x, z) { + (true | false, false, true, false) => true, + (false, true | false, true | false, false) => true, + (true | false, true | false, true | false, true) => false, + (true, true | false, true | false, false) => false, + } + }; + c() + +} + +fn h(x: bool, y: bool, z: bool) -> bool { + let c = || { + match (x, (y, (x, (z,)))) { + (true | false, (false, (true, (false,)))) => true, + (false, (true | false, (true | false, (false,)))) => true, + (true | false, (true | false, (true | false, (true,)))) => false, + (true, (true | false, (true | false, (false,)))) => false, + } + }; + c() + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-72896.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-72896.rs new file mode 100644 index 0000000000000..5cdf9fa78882e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-72896.rs @@ -0,0 +1,28 @@ +// run-pass +// edition:2021 + +trait EnumSetType { + type Repr; +} + +enum Enum8 { } +impl EnumSetType for Enum8 { + type Repr = u8; +} + +#[derive(PartialEq, Eq)] +struct EnumSet { + __enumset_underlying: T::Repr, +} + +const CONST_SET: EnumSet = EnumSet { __enumset_underlying: 3 }; + +fn main() { + let _c = || { + match CONST_SET { + CONST_SET => { /* ok */ } + _ => panic!("match fell through?"), + } + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.rs new file mode 100644 index 0000000000000..84bd6361b8cf1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.rs @@ -0,0 +1,17 @@ +// edition:2021 + +fn main() { + || { + let mut args = std::env::args_os(); + let _arg = match args.next() { + Some(arg) => { + match arg.to_str() { + //~^ ERROR `arg` does not live long enough + Some(s) => s, + None => return, + } + } + None => return, + }; + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.stderr new file mode 100644 index 0000000000000..83f1e8bfc87bc --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-74050-end-span.stderr @@ -0,0 +1,15 @@ +error[E0597]: `arg` does not live long enough + --> $DIR/issue-74050-end-span.rs:8:23 + | +LL | let _arg = match args.next() { + | ---- borrow later stored here +LL | Some(arg) => { +LL | match arg.to_str() { + | ^^^ borrowed value does not live long enough +... +LL | } + | - `arg` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-82392.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-82392.rs new file mode 100644 index 0000000000000..08ae5c11f55d0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-82392.rs @@ -0,0 +1,12 @@ +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass +// edition:2021 + +pub fn main() { + || { + if true { + } else if let Some(a) = Some(3) { + } + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-82392.stdout b/src/test/ui/closures/2229_closure_analysis/match/issue-82392.stdout new file mode 100644 index 0000000000000..94ae51a9e7acb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-82392.stdout @@ -0,0 +1,26 @@ +#[prelude_import] +use std::prelude::rust_2021::*; +#[macro_use] +extern crate std; +// https://github.com/rust-lang/rust/issues/82329 +// compile-flags: -Zunpretty=hir,typed +// check-pass +// edition:2021 + +pub fn main() ({ + (|| + ({ + (if (true as bool) + ({ } as + ()) else {match ((Some as + fn(i32) -> Option {Option::::Some})((3 + as + i32)) + as Option) { + Some(a) => { } + _ => { } + }} as ()) + } as + ()) as + [closure@$DIR/issue-82392.rs:7:5: 11:6]); + } as ()) diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-84434.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-84434.rs new file mode 100644 index 0000000000000..a8b1353bfc51d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/issue-84434.rs @@ -0,0 +1,22 @@ +// https://github.com/rust-lang/rust/issues/84434 +// check-pass +// edition:2021 + +use std::path::Path; +struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), +} +const MY_A: A = A { + func: |check, a, b| { + || { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }; + + }, +}; + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.rs b/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.rs new file mode 100644 index 0000000000000..a6a9f96c13a2f --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.rs @@ -0,0 +1,24 @@ +// edition:2021 + +enum E { + A, + B, + C, + D, + E, + F, +} + +fn main() { + let c = || { + match E::F { + E::A => 1, + E::B => 2, + E::C => 3, + E::D => 4, + E::E => unimplemented!(""), + E::F => "", //~ ERROR `match` arms have incompatible types + }; + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.stderr new file mode 100644 index 0000000000000..00f32d71d9c0d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-arm-resolving-to-never.stderr @@ -0,0 +1,34 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-arm-resolving-to-never.rs:20:21 + | +LL | / match E::F { +LL | | E::A => 1, +LL | | E::B => 2, +LL | | E::C => 3, +LL | | E::D => 4, +LL | | E::E => unimplemented!(""), + | | ------------------ this and all prior arms are found to be of type `{integer}` +LL | | E::F => "", + | | ^^ expected integer, found `&str` +LL | | }; + | |_________- `match` arms have incompatible types + | +note: you might have meant to return the `match` expression + --> $DIR/match-arm-resolving-to-never.rs:21:10 + | +LL | let c = || { + | - the `match` arms can conform to this return type +LL | / match E::F { +LL | | E::A => 1, +LL | | E::B => 2, +LL | | E::C => 3, +... | +LL | | E::F => "", +LL | | }; + | | -^ the `match` is a statement because of this semicolon, consider removing it + | |_________| + | this could be implicitly returned but it is a statement, not a tail expression + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-bot-panic.rs b/src/test/ui/closures/2229_closure_analysis/match/match-bot-panic.rs new file mode 100644 index 0000000000000..f168a5b760d27 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-bot-panic.rs @@ -0,0 +1,21 @@ +// run-fail +// edition:2021 +// error-pattern:explicit panic +// ignore-emscripten no processes + +#![allow(unreachable_code)] +#![allow(unused_variables)] + +fn foo(s: String) {} + +fn main() { + let c = || { + let i = match Some::(3) { + None:: => panic!(), + Some::(_) => panic!(), + }; + foo(i); + }; + c(); + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-disc-bot.rs b/src/test/ui/closures/2229_closure_analysis/match/match-disc-bot.rs new file mode 100644 index 0000000000000..a0f0cacb7f490 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-disc-bot.rs @@ -0,0 +1,21 @@ +// run-fail +// edition:2021 +// error-pattern:quux +// ignore-emscripten no processes + +fn f() -> ! { + panic!("quux") +} +fn g() -> isize { + let c = || { + match f() { + true => 1, + false => 0, + } + }; + c() + +} +fn main() { + g(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.rs b/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.rs new file mode 100644 index 0000000000000..26398919f2b16 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.rs @@ -0,0 +1,17 @@ +// edition:2021 + +use std::path::Path; + +fn main() { + || { + let path = Path::new("foo"); + match path { + Path::new("foo") => println!("foo"), + //~^ ERROR expected tuple struct or tuple variant + Path::new("bar") => println!("bar"), + //~^ ERROR expected tuple struct or tuple variant + _ => (), + } + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.stderr new file mode 100644 index 0000000000000..3b81d39e961ce --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-fn-call.stderr @@ -0,0 +1,19 @@ +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:9:13 + | +LL | Path::new("foo") => println!("foo"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error[E0164]: expected tuple struct or tuple variant, found associated function `Path::new` + --> $DIR/match-fn-call.rs:11:13 + | +LL | Path::new("bar") => println!("bar"), + | ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns + | + = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.rs new file mode 100644 index 0000000000000..3a18534da6637 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.rs @@ -0,0 +1,12 @@ +// edition:2021 + +fn main() { + || { + match 1i32 { + 1i32 => 1, + 2u32 => 1, //~ ERROR mismatched types + _ => 2, + }; + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.stderr new file mode 100644 index 0000000000000..dece8a5b74f76 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ill-type2.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/match-ill-type2.rs:7:13 + | +LL | match 1i32 { + | ---- this expression has type `i32` +LL | 1i32 => 1, +LL | 2u32 => 1, + | ^^^^ expected `i32`, found `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.rs b/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.rs new file mode 100644 index 0000000000000..f923b0cd6a7bb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.rs @@ -0,0 +1,57 @@ +// edition:2021 + +// Diagnostic enhancement explained in issue #75418. +// Point at the last statement in the block if there's no tail expression, +// and suggest removing the semicolon if appropriate. + +fn main() { + let _c = || { + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }, + }; + + let _ = if let Some(x) = Some(42) { + x + } else { + 0; + //~^ ERROR incompatible types + //~| HELP consider removing this semicolon + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { + (); + //~^ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => { + x + }, + None => { //~ ERROR incompatible types + }, + }; + + let _ = match Some(42) { + Some(x) => "rust-lang.org" + .chars() + .skip(1) + .chain(Some(x as u8 as char)) + .take(10) + .any(char::is_alphanumeric), + None => {} //~ ERROR incompatible types + }; + + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.stderr new file mode 100644 index 0000000000000..008b1c1e93d6d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-incompat-type-semi.stderr @@ -0,0 +1,88 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:11:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +... | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/match-incompat-type-semi.rs:20:9 + | +LL | let _ = if let Some(x) = Some(42) { + | _____________- +LL | | x + | | - expected because of this +LL | | } else { +LL | | 0; + | | ^- + | | || + | | |help: consider removing this semicolon + | | expected integer, found `()` +LL | | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:30:13 + | +LL | let _ = match Some(42) { + | _____________- +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `{integer}` +LL | | }, +LL | | None => { +LL | | (); + | | ^^^ expected integer, found `()` +LL | | +LL | | }, +LL | | }; + | |_____- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:39:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => { +LL | x + | - this is found to be of type `{integer}` +LL | }, +LL | None => { + | _________________^ +LL | | }, + | |_________^ expected integer, found `()` + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-incompat-type-semi.rs:50:17 + | +LL | let _ = match Some(42) { + | -------------- `match` arms have incompatible types +LL | Some(x) => "rust-lang.org" + | ____________________- +LL | | .chars() +LL | | .skip(1) +LL | | .chain(Some(x as u8 as char)) +LL | | .take(10) +LL | | .any(char::is_alphanumeric), + | |_______________________________________- this is found to be of type `bool` +LL | None => {} + | ^^ expected `bool`, found `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-join.rs b/src/test/ui/closures/2229_closure_analysis/match/match-join.rs new file mode 100644 index 0000000000000..e0f6c41226288 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-join.rs @@ -0,0 +1,16 @@ +// edition:2021 + +// a good test that we merge paths correctly in the presence of a +// variable that's used before it's declared + +fn my_panic() -> ! { panic!(); } + +fn main() { + || { + match true { false => { my_panic(); } true => { } } + + println!("{}", x); //~ ERROR cannot find value `x` in this scope + let x: isize; + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-join.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-join.stderr new file mode 100644 index 0000000000000..301cbc1105bd0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-join.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/match-join.rs:12:24 + | +LL | println!("{}", x); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.rs b/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.rs new file mode 100644 index 0000000000000..bc57edcfa28a2 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.rs @@ -0,0 +1,17 @@ +// edition:2021 + +#![allow(warnings)] +#![deny(unreachable_code)] + +enum Void { } + +fn foo(v: Void) { + let _c = || { + match v { } + let x = 2; //~ ERROR unreachable + }; + +} + +fn main() { +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.stderr new file mode 100644 index 0000000000000..f0927b8f92b16 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-no-arms-unreachable-after.stderr @@ -0,0 +1,16 @@ +error: unreachable statement + --> $DIR/match-no-arms-unreachable-after.rs:11:9 + | +LL | match v { } + | ----------- any code following this expression is unreachable +LL | let x = 2; + | ^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/match-no-arms-unreachable-after.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.rs new file mode 100644 index 0000000000000..f8aebbcef32c3 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.rs @@ -0,0 +1,21 @@ +// edition:2021 + +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + let _c = || { + match c { + Color::Rgb(_, _, _) => { } + Color::Cmyk(_, _, _, _) => { } + Color::NoColor(_) => { } + //~^ ERROR expected tuple struct or tuple variant, found unit variant `Color::NoColor` + } + }; + + } +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.stderr new file mode 100644 index 0000000000000..d1ebe816d0e27 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch-2.stderr @@ -0,0 +1,12 @@ +error[E0532]: expected tuple struct or tuple variant, found unit variant `Color::NoColor` + --> $DIR/match-pattern-field-mismatch-2.rs:15:17 + | +LL | NoColor, + | ------- `Color::NoColor` defined here +... +LL | Color::NoColor(_) => { } + | ^^^^^^^^^^^^^^^^^ help: use this syntax instead: `Color::NoColor` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0532`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.rs b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.rs new file mode 100644 index 0000000000000..d4b98f26444cf --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.rs @@ -0,0 +1,21 @@ +// edition:2021 + +fn main() { + enum Color { + Rgb(usize, usize, usize), + Cmyk(usize, usize, usize, usize), + NoColor, + } + + fn foo(c: Color) { + let _c = || { + match c { + Color::Rgb(_, _) => { } + //~^ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 + Color::Cmyk(_, _, _, _) => { } + Color::NoColor => { } + }; + }; + + } +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.stderr new file mode 100644 index 0000000000000..5180ad6fa0bed --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-pattern-field-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields + --> $DIR/match-pattern-field-mismatch.rs:13:17 + | +LL | Rgb(usize, usize, usize), + | ------------------------ tuple variant defined here +... +LL | Color::Rgb(_, _) => { } + | ^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + | +help: use `_` to explicitly ignore each field + | +LL | Color::Rgb(_, _, _) => { } + | +++ +help: use `..` to ignore all fields + | +LL | Color::Rgb(..) => { } + | ~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.rs new file mode 100644 index 0000000000000..754550312b45a --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.rs @@ -0,0 +1,29 @@ +// edition:2021 + +#![feature(exclusive_range_pattern)] + +fn main() { + || { + match 5 { + 6 ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + + match 5 { + 0 .. 0 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than upper + //~| ERROR lower range bound must be less than upper + + match 5u64 { + 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + _ => { } + }; + //~^^^ ERROR lower range bound must be less than or equal to upper + //~| ERROR lower range bound must be less than or equal to upper + + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.stderr new file mode 100644 index 0000000000000..8cfbb53dbbfa0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail-2.stderr @@ -0,0 +1,40 @@ +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:8:13 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:15:13 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:22:13 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:8:13 + | +LL | 6 ..= 1 => { } + | ^ lower bound larger than upper bound + +error[E0579]: lower range bound must be less than upper + --> $DIR/match-range-fail-2.rs:15:13 + | +LL | 0 .. 0 => { } + | ^ + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/match-range-fail-2.rs:22:13 + | +LL | 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { } + | ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0030, E0579. +For more information about an error, try `rustc --explain E0030`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.rs new file mode 100644 index 0000000000000..d7985901a6061 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.rs @@ -0,0 +1,27 @@ +// edition:2021 + +fn main() { + || { + match "wow" { + "bar" ..= "foo" => { } + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + 10 ..= "what" => () + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match "wow" { + true ..= "what" => {} + }; + //~^^ ERROR only `char` and numeric types are allowed in range + + match 5 { + 'c' ..= 100 => { } + _ => { } + }; + //~^^^ ERROR mismatched types + + }; +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.stderr new file mode 100644 index 0000000000000..9073b8c5bee53 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-range-fail.stderr @@ -0,0 +1,38 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:6:13 + | +LL | "bar" ..= "foo" => { } + | -----^^^^^----- + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `&'static str` but it should be `char` or numeric + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:11:20 + | +LL | 10 ..= "what" => () + | -- ^^^^^^ this is of type `&'static str` but it should be `char` or numeric + | | + | this is of type `{integer}` + +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/match-range-fail.rs:16:13 + | +LL | true ..= "what" => {} + | ----^^^^^------ + | | | + | | this is of type `&'static str` but it should be `char` or numeric + | this is of type `bool` but it should be `char` or numeric + +error[E0308]: mismatched types + --> $DIR/match-range-fail.rs:21:13 + | +LL | 'c' ..= 100 => { } + | ^^^ --- this is of type `{integer}` + | | + | expected integer, found `char` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0029, E0308. +For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.nll.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.nll.stderr new file mode 100644 index 0000000000000..1dc29d2088cea --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.nll.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-invariance.rs:10:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | match self.0 { ref mut x => x } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to &i32 + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.rs b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.rs new file mode 100644 index 0000000000000..2a5605c1240e3 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.rs @@ -0,0 +1,19 @@ +// edition:2021 + +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `match`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let c = || { + match self.0 { ref mut x => x } //~ ERROR mismatched types + }; + c() + } +} + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.stderr new file mode 100644 index 0000000000000..3e9f729dc09f5 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-invariance.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/match-ref-mut-invariance.rs:10:37 + | +LL | match self.0 { ref mut x => x } + | ^ lifetime mismatch + | + = note: expected mutable reference `&'a mut &'a i32` + found mutable reference `&'a mut &'b i32` +note: the lifetime `'a` as defined on the method body at 9:12... + --> $DIR/match-ref-mut-invariance.rs:9:12 + | +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 + --> $DIR/match-ref-mut-invariance.rs:8:6 + | +LL | impl<'b> S<'b> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.nll.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.nll.stderr new file mode 100644 index 0000000000000..8b87c3da28b02 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.nll.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/match-ref-mut-let-invariance.rs:11:9 + | +LL | impl<'b> S<'b> { + | -- lifetime `'b` defined here +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | -- lifetime `'a` defined here +LL | let ref mut x = self.0; +LL | x + | ^ returning this value requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a mutable reference to &i32 + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.rs b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.rs new file mode 100644 index 0000000000000..411e07b80c327 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.rs @@ -0,0 +1,21 @@ +// edition:2021 + +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `let`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let c = || { + let ref mut x = self.0; + x //~ ERROR mismatched types + }; + c() + + } +} + +fn main() {} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.stderr new file mode 100644 index 0000000000000..303aba3422cec --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-let-invariance.stderr @@ -0,0 +1,22 @@ +error[E0308]: mismatched types + --> $DIR/match-ref-mut-let-invariance.rs:11:9 + | +LL | x + | ^ lifetime mismatch + | + = note: expected mutable reference `&'a mut &'a i32` + found mutable reference `&'a mut &'b i32` +note: the lifetime `'a` as defined on the method body at 9:12... + --> $DIR/match-ref-mut-let-invariance.rs:9:12 + | +LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + | ^^ +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 + --> $DIR/match-ref-mut-let-invariance.rs:8:6 + | +LL | impl<'b> S<'b> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-stability.rs b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-stability.rs new file mode 100644 index 0000000000000..e99cc9fbfcc43 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-ref-mut-stability.rs @@ -0,0 +1,47 @@ +// Check that `ref mut` variables don't change address between the match guard +// and the arm expression. + +// run-pass + +// Test that z always point to the same temporary. +fn referent_stability() { + let _c = || { + let p; + match 0 { + ref mut z if { p = z as *const _; true } => assert_eq!(p, z as *const _), + _ => unreachable!(), + }; + }; + +} +// edition:2021 + +// Test that z is always effectively the same variable. +fn variable_stability() { + let _c = || { + let p; + match 0 { + ref mut z if { p = &z as *const _; true } => assert_eq!(p, &z as *const _), + _ => unreachable!(), + }; + }; + +} + +// Test that a borrow of *z can cross from the guard to the arm. +fn persist_borrow() { + let _c = || { + let r; + match 0 { + ref mut z if { r = z as &_; true } => assert_eq!(*r, 0), + _ => unreachable!(), + } + }; + +} + +fn main() { + referent_stability(); + variable_stability(); + persist_borrow(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-struct.rs b/src/test/ui/closures/2229_closure_analysis/match/match-struct.rs new file mode 100644 index 0000000000000..b42c919d8db01 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-struct.rs @@ -0,0 +1,16 @@ +// edition:2021 + +struct S { a: isize } +enum E { C(isize) } + +fn main() { + let _c = || { + match (S { a: 1 }) { + E::C(_) => (), + //~^ ERROR mismatched types + //~| expected struct `S`, found enum `E` + _ => () + } + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-struct.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-struct.stderr new file mode 100644 index 0000000000000..75655a348ec10 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-struct.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-struct.rs:9:13 + | +LL | match (S { a: 1 }) { + | ------------ this expression has type `S` +LL | E::C(_) => (), + | ^^^^^^^ expected struct `S`, found enum `E` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.rs b/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.rs new file mode 100644 index 0000000000000..7164ca268de67 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.rs @@ -0,0 +1,6 @@ +// edition:2021 + +enum A { A } +enum B { B } + +fn main() { || { let x: A = A::A; match x { B::B => { } } }; } //~ ERROR mismatched types diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.stderr new file mode 100644 index 0000000000000..6ac3bb968f2dd --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-tag-nullary.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-nullary.rs:6:45 + | +LL | enum B { B } + | - unit variant defined here +LL | +LL | fn main() { || { let x: A = A::A; match x { B::B => { } } }; } + | - ^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.rs b/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.rs new file mode 100644 index 0000000000000..5cdc2c8573bf1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.rs @@ -0,0 +1,6 @@ +// edition:2021 + +enum A { A(isize) } +enum B { B(isize) } + +fn main() { || { let x: A = A::A(0); match x { B::B(y) => { } } }; } //~ ERROR mismatched types diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.stderr new file mode 100644 index 0000000000000..4ff635a7601ac --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-tag-unary.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/match-tag-unary.rs:6:48 + | +LL | fn main() { || { let x: A = A::A(0); match x { B::B(y) => { } } }; } + | - ^^^^^^^ expected enum `A`, found enum `B` + | | + | this expression has type `A` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.rs b/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.rs new file mode 100644 index 0000000000000..33501d95ff0a5 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.rs @@ -0,0 +1,68 @@ +// edition:2021 + +fn main() { + let _ = test_func1(1); + let _ = test_func2(1); +} + +fn test_func1(n: i32) -> i32 { + let c = || { + match n { + //~^ NOTE `match` arms have incompatible types + 12 => 'b', + //~^ NOTE this is found to be of type `char + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + } + }; + c() + +} + +fn test_func2(n: i32) -> i32 { + let c = || { + let x = match n { //~ NOTE `match` arms have incompatible types + 12 => 'b', //~ NOTE this is found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x + }; + c() +} + +fn test_func3(n: i32) -> i32 { + let c = || { + let x = match n { //~ NOTE `match` arms have incompatible types + 1 => 'b', + 2 => 'b', + 3 => 'b', + 4 => 'b', + 5 => 'b', + 6 => 'b', + //~^ NOTE this and all prior arms are found to be of type `char` + _ => 42, + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `char`, found integer + }; + x + }; + c() + +} + +fn test_func4() { + let _c = || { + match Some(0u32) { //~ NOTE `match` arms have incompatible types + Some(x) => { + x //~ NOTE this is found to be of type `u32` + }, + None => {} + //~^ ERROR `match` arms have incompatible types + //~| NOTE expected `u32`, found `()` + } + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.stderr new file mode 100644 index 0000000000000..c95c81ad5802a --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-type-err-first-arm.stderr @@ -0,0 +1,66 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:14:18 + | +LL | / match n { +LL | | +LL | | 12 => 'b', + | | --- this is found to be of type `char` +LL | | +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | } + | |_________- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:27:18 + | +LL | let x = match n { + | _________________- +LL | | 12 => 'b', + | | --- this is found to be of type `char` +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_________- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:46:18 + | +LL | let x = match n { + | _________________- +LL | | 1 => 'b', +LL | | 2 => 'b', +LL | | 3 => 'b', +... | +LL | | 6 => 'b', + | | --- this and all prior arms are found to be of type `char` +LL | | +LL | | _ => 42, + | | ^^ expected `char`, found integer +LL | | +LL | | +LL | | }; + | |_________- `match` arms have incompatible types + +error[E0308]: `match` arms have incompatible types + --> $DIR/match-type-err-first-arm.rs:62:21 + | +LL | / match Some(0u32) { +LL | | Some(x) => { +LL | | x + | | - this is found to be of type `u32` +LL | | }, +LL | | None => {} + | | ^^ expected `u32`, found `()` +LL | | +LL | | +LL | | } + | |_________- `match` arms have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.rs b/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.rs new file mode 100644 index 0000000000000..63490791d46b7 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.rs @@ -0,0 +1,12 @@ +// edition:2021 + +fn foo() -> T { panic!("Rocks for my pillow") } + +fn main() { + || { + let x = match () { //~ ERROR type annotations needed + () => foo() // T here should be unresolved + }; + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.stderr new file mode 100644 index 0000000000000..d4075c4a193de --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-unresolved-one-arm.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/match-unresolved-one-arm.rs:7:13 + | +LL | let x = match () { + | ^ consider giving `x` a type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.rs new file mode 100644 index 0000000000000..62c7a98e70970 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.rs @@ -0,0 +1,11 @@ +// edition:2021 + +fn main() { + || { + match () { + [()] => { } + //~^ ERROR expected an array or slice, found `()` + } + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.stderr new file mode 100644 index 0000000000000..b465bdf882220 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-vec-mismatch-2.stderr @@ -0,0 +1,9 @@ +error[E0529]: expected an array or slice, found `()` + --> $DIR/match-vec-mismatch-2.rs:6:13 + | +LL | [()] => { } + | ^^^^ pattern cannot match with input type `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-wildcards.rs b/src/test/ui/closures/2229_closure_analysis/match/match-wildcards.rs new file mode 100644 index 0000000000000..0551194ff3b32 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match-wildcards.rs @@ -0,0 +1,26 @@ +// run-fail +// edition:2021 +// error-pattern:squirrelcupcake +// ignore-emscripten no processes + +fn cmp() -> isize { + let c = || { + match (Some('a'), None::) { + (Some(_), _) => { + panic!("squirrelcupcake"); + } + (_, Some(_)) => { + panic!(); + } + _ => { + panic!("wat"); + } + } + }; + c() + +} + +fn main() { + println!("{}", cmp()); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.rs b/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.rs new file mode 100644 index 0000000000000..ac3b1c8c4426e --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.rs @@ -0,0 +1,36 @@ +// edition:2021 +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L { A, B } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2}; + +fn foo() -> L {todo!()} +fn bar() -> (E1, E2) {todo!()} + +fn main() { + || { + let l = foo(); + // No error for enums defined in this crate + match l { L::A => (), L::B => () }; + // (except if the match is already non-exhaustive) + match l { L::A => () }; + //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + + // E1 is not visibly uninhabited from here + let (e1, e2) = bar(); + match e1 {}; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + match e2 { E2::A => (), E2::B => () }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] + }; + +} diff --git a/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.stderr b/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.stderr new file mode 100644 index 0000000000000..5debfe1c566c4 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/match_non_exhaustive.stderr @@ -0,0 +1,36 @@ +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/match_non_exhaustive.rs:23:11 + | +LL | enum L { A, B } + | --------------- + | | | + | | not covered + | `L` defined here +... +LL | match l { L::A => () }; + | ^ pattern `B` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `L` + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/match_non_exhaustive.rs:28:11 + | +LL | match e1 {}; + | ^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E1`, which is marked as non-exhaustive + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match_non_exhaustive.rs:30:11 + | +LL | match e2 { E2::A => (), E2::B => () }; + | ^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E2`, which is marked as non-exhaustive + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-deref-miscompile.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-deref-miscompile.rs new file mode 100644 index 0000000000000..ab33234b40646 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-deref-miscompile.rs @@ -0,0 +1,49 @@ +// run-pass +// edition:2021 + +fn main() { + let _c = || { + match b"." as &[u8] { + b"." if true => {}, + b"." => panic!(), + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b"." as &[u8] { + b"." if false => panic!(), + b"." => {}, + b".." => panic!(), + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if true => panic!(), // the miscompile caused this arm to be reached + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b".." as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => {}, + b"" => panic!(), + _ => panic!(), + } + match b"" as &[u8] { + b"." if true => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } + match b"" as &[u8] { + b"." if false => panic!(), + b"." => panic!(), + b".." => panic!(), + b"" => {}, + _ => panic!(), + } + }; +}