diff options
Diffstat (limited to 'tests/ui/binding')
102 files changed, 2717 insertions, 0 deletions
diff --git a/tests/ui/binding/ambiguity-item.rs b/tests/ui/binding/ambiguity-item.rs new file mode 100644 index 000000000..0f48340c2 --- /dev/null +++ b/tests/ui/binding/ambiguity-item.rs @@ -0,0 +1,19 @@ +// Identifier pattern referring to an ambiguity item is an error (issue #46079). + +mod m { + pub fn f() {} +} +use m::*; + +mod n { + pub fn f() {} +} +use n::*; // OK, no conflict with `use m::*;` + +fn main() { + let v = f; //~ ERROR `f` is ambiguous + match v { + f => {} //~ ERROR `f` is ambiguous + mut f => {} // OK, unambiguously a fresh binding due to `mut` + } +} diff --git a/tests/ui/binding/ambiguity-item.stderr b/tests/ui/binding/ambiguity-item.stderr new file mode 100644 index 000000000..f36201396 --- /dev/null +++ b/tests/ui/binding/ambiguity-item.stderr @@ -0,0 +1,43 @@ +error[E0659]: `f` is ambiguous + --> $DIR/ambiguity-item.rs:14:13 + | +LL | let v = f; + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error[E0659]: `f` is ambiguous + --> $DIR/ambiguity-item.rs:16:9 + | +LL | f => {} + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/binding/bind-field-short-with-modifiers.rs b/tests/ui/binding/bind-field-short-with-modifiers.rs new file mode 100644 index 000000000..b271f84e9 --- /dev/null +++ b/tests/ui/binding/bind-field-short-with-modifiers.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(non_shorthand_field_patterns)] + +pub fn main() { + struct Foo { x: isize, y: isize } + let mut f = Foo { x: 10, y: 0 }; + match f { + Foo { ref mut x, .. } => *x = 11, + } + match f { + Foo { ref x, ref y } => { + assert_eq!(f.x, 11); + assert_eq!(f.y, 0); + } + } + match f { + Foo { mut x, y: ref mut y } => { + x = 12; + *y = 1; + } + } + assert_eq!(f.x, 11); + assert_eq!(f.y, 1); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-2.rs b/tests/ui/binding/borrowed-ptr-pattern-2.rs new file mode 100644 index 000000000..40df85b14 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-2.rs @@ -0,0 +1,13 @@ +// run-pass + +fn foo(s: &String) -> bool { + match &**s { + "kitty" => true, + _ => false + } +} + +pub fn main() { + assert!(foo(&"kitty".to_string())); + assert!(!foo(&"gata".to_string())); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-3.rs b/tests/ui/binding/borrowed-ptr-pattern-3.rs new file mode 100644 index 000000000..f2607eee8 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-3.rs @@ -0,0 +1,13 @@ +// run-pass + +fn foo<'r>(s: &'r usize) -> bool { + match s { + &3 => true, + _ => false + } +} + +pub fn main() { + assert!(foo(&3)); + assert!(!foo(&4)); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-infallible.rs b/tests/ui/binding/borrowed-ptr-pattern-infallible.rs new file mode 100644 index 000000000..1bbc03e19 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-infallible.rs @@ -0,0 +1,8 @@ +// run-pass + + +pub fn main() { + let (&x, &y) = (&3, &'a'); + assert_eq!(x, 3); + assert_eq!(y, 'a'); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern-option.rs b/tests/ui/binding/borrowed-ptr-pattern-option.rs new file mode 100644 index 000000000..319b8631e --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern-option.rs @@ -0,0 +1,15 @@ +// run-pass + +fn select<'r>(x: &'r Option<isize>, y: &'r Option<isize>) -> &'r Option<isize> { + match (x, y) { + (&None, &None) => x, + (&Some(_), _) => x, + (&None, &Some(_)) => y + } +} + +pub fn main() { + let x = None; + let y = Some(3); + assert_eq!(select(&x, &y).unwrap(), 3); +} diff --git a/tests/ui/binding/borrowed-ptr-pattern.rs b/tests/ui/binding/borrowed-ptr-pattern.rs new file mode 100644 index 000000000..d5f94ab54 --- /dev/null +++ b/tests/ui/binding/borrowed-ptr-pattern.rs @@ -0,0 +1,12 @@ +// run-pass + +fn foo<T:Clone>(x: &T) -> T{ + match x { + &ref a => (*a).clone() + } +} + +pub fn main() { + assert_eq!(foo(&3), 3); + assert_eq!(foo(&'a'), 'a'); +} diff --git a/tests/ui/binding/const-param.rs b/tests/ui/binding/const-param.rs new file mode 100644 index 000000000..2d051808f --- /dev/null +++ b/tests/ui/binding/const-param.rs @@ -0,0 +1,10 @@ +// Identifier pattern referring to a const generic parameter is an error (issue #68853). + +fn check<const N: usize>() { + match 1 { + N => {} //~ ERROR const parameters cannot be referenced in patterns + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/binding/const-param.stderr b/tests/ui/binding/const-param.stderr new file mode 100644 index 000000000..adda80810 --- /dev/null +++ b/tests/ui/binding/const-param.stderr @@ -0,0 +1,9 @@ +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:5:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/binding/empty-types-in-patterns.rs b/tests/ui/binding/empty-types-in-patterns.rs new file mode 100644 index 000000000..0d0dbcaf4 --- /dev/null +++ b/tests/ui/binding/empty-types-in-patterns.rs @@ -0,0 +1,59 @@ +// run-pass + +#![feature(never_type, never_type_fallback)] +#![feature(exhaustive_patterns)] + +#![allow(unreachable_patterns)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +#[allow(dead_code)] +fn foo(z: !) { + let x: Result<!, !> = Ok(z); + + let Ok(_y) = x; + let Err(_y) = x; + + let x = [z; 1]; + + match x {}; + match x { + [q] => q, + }; +} + +fn bar(nevers: &[!]) { + match nevers { + &[] => (), + }; + + match nevers { + &[] => (), + &[_] => (), + &[_, _, _, ..] => (), + }; +} + +fn main() { + let x: Result<u32, !> = Ok(123); + let Ok(y) = x; + + assert_eq!(123, y); + + match x { + Ok(y) => y, + }; + + match x { + Ok(y) => y, + Err(e) => match e {}, + }; + + let x: Result<u32, &!> = Ok(123); + match x { + Ok(y) => y, + Err(_) => unimplemented!(), + }; + + bar(&[]); +} diff --git a/tests/ui/binding/exhaustive-bool-match-sanity.rs b/tests/ui/binding/exhaustive-bool-match-sanity.rs new file mode 100644 index 000000000..f83def210 --- /dev/null +++ b/tests/ui/binding/exhaustive-bool-match-sanity.rs @@ -0,0 +1,22 @@ +// run-pass +// Issue #33540 +// We previously used to generate a 3-armed boolean `SwitchInt` in the +// MIR of the function `foo` below. #33583 changed rustc to +// generate an `If` terminator instead. This test is to just ensure +// sanity in that we generate an if-else chain giving the correct +// results. + +fn foo(x: bool, y: bool) -> u32 { + match (x, y) { + (false, _) => 0, + (_, false) => 1, + (true, true) => 2 + } +} + +fn main() { + assert_eq!(foo(false, true), 0); + assert_eq!(foo(false, false), 0); + assert_eq!(foo(true, false), 1); + assert_eq!(foo(true, true), 2); +} diff --git a/tests/ui/binding/expr-match-generic-unique1.rs b/tests/ui/binding/expr-match-generic-unique1.rs new file mode 100644 index 000000000..c5f38d815 --- /dev/null +++ b/tests/ui/binding/expr-match-generic-unique1.rs @@ -0,0 +1,18 @@ +// run-pass + +fn test_generic<T: Clone, F>(expected: Box<T>, eq: F) where F: FnOnce(Box<T>, Box<T>) -> bool { + let actual: Box<T> = match true { + true => { expected.clone() }, + _ => panic!("wat") + }; + assert!(eq(expected, actual)); +} + +fn test_box() { + fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool { + return *b1 == *b2; + } + test_generic::<bool, _>(Box::new(true), compare_box); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/binding/expr-match-generic-unique2.rs b/tests/ui/binding/expr-match-generic-unique2.rs new file mode 100644 index 000000000..8977ca68e --- /dev/null +++ b/tests/ui/binding/expr-match-generic-unique2.rs @@ -0,0 +1,16 @@ +// run-pass + +fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool { + let actual: T = match true { + true => expected.clone(), + _ => panic!("wat") + }; + assert!(eq(expected, actual)); +} + +fn test_vec() { + fn compare_box(v1: Box<isize>, v2: Box<isize>) -> bool { return v1 == v2; } + test_generic::<Box<isize>, _>(Box::new(1), compare_box); +} + +pub fn main() { test_vec(); } diff --git a/tests/ui/binding/expr-match-generic.rs b/tests/ui/binding/expr-match-generic.rs new file mode 100644 index 000000000..530fc676f --- /dev/null +++ b/tests/ui/binding/expr-match-generic.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(non_camel_case_types)] + +type compare<T> = extern "Rust" fn(T, T) -> bool; + +fn test_generic<T:Clone>(expected: T, eq: compare<T>) { + let actual: T = match true { true => { expected.clone() }, _ => panic!("wat") }; + assert!((eq(expected, actual))); +} + +fn test_bool() { + fn compare_bool(b1: bool, b2: bool) -> bool { return b1 == b2; } + test_generic::<bool>(true, compare_bool); +} + +#[derive(Clone)] +struct Pair { + a: isize, + b: isize, +} + +fn test_rec() { + fn compare_rec(t1: Pair, t2: Pair) -> bool { + t1.a == t2.a && t1.b == t2.b + } + test_generic::<Pair>(Pair {a: 1, b: 2}, compare_rec); +} + +pub fn main() { test_bool(); test_rec(); } diff --git a/tests/ui/binding/expr-match-panic-all.rs b/tests/ui/binding/expr-match-panic-all.rs new file mode 100644 index 000000000..ac31b49a1 --- /dev/null +++ b/tests/ui/binding/expr-match-panic-all.rs @@ -0,0 +1,14 @@ +// run-pass + + + +// When all branches of a match expression result in panic, the entire +// match expression results in panic. + +pub fn main() { + let _x = + match true { + true => { 10 } + false => { match true { true => { panic!() } false => { panic!() } } } + }; +} diff --git a/tests/ui/binding/expr-match-panic.rs b/tests/ui/binding/expr-match-panic.rs new file mode 100644 index 000000000..4b6b6e072 --- /dev/null +++ b/tests/ui/binding/expr-match-panic.rs @@ -0,0 +1,14 @@ +// run-pass + + +fn test_simple() { + let r = match true { true => { true } false => { panic!() } }; + assert_eq!(r, true); +} + +fn test_box() { + let r = match true { true => { vec![10] } false => { panic!() } }; + assert_eq!(r[0], 10); +} + +pub fn main() { test_simple(); test_box(); } diff --git a/tests/ui/binding/expr-match-unique.rs b/tests/ui/binding/expr-match-unique.rs new file mode 100644 index 000000000..eec9e1f8b --- /dev/null +++ b/tests/ui/binding/expr-match-unique.rs @@ -0,0 +1,9 @@ +// run-pass + +// Tests for match as expressions resulting in boxed types +fn test_box() { + let res: Box<_> = match true { true => { Box::new(100) }, _ => panic!() }; + assert_eq!(*res, 100); +} + +pub fn main() { test_box(); } diff --git a/tests/ui/binding/expr-match.rs b/tests/ui/binding/expr-match.rs new file mode 100644 index 000000000..575b38fbc --- /dev/null +++ b/tests/ui/binding/expr-match.rs @@ -0,0 +1,45 @@ +// run-pass + + + + +// Tests for using match as an expression + +fn test_basic() { + let mut rs: bool = match true { true => { true } false => { false } }; + assert!((rs)); + rs = match false { true => { false } false => { true } }; + assert!((rs)); +} + +fn test_inferrence() { + let rs = match true { true => { true } false => { false } }; + assert!((rs)); +} + +fn test_alt_as_alt_head() { + // Yeah, this is kind of confusing ... + + let rs = + match match false { true => { true } false => { false } } { + true => { false } + false => { true } + }; + assert!((rs)); +} + +fn test_alt_as_block_result() { + let rs = + match false { + true => { false } + false => { match true { true => { true } false => { false } } } + }; + assert!((rs)); +} + +pub fn main() { + test_basic(); + test_inferrence(); + test_alt_as_alt_head(); + test_alt_as_block_result(); +} diff --git a/tests/ui/binding/fat-arrow-match.rs b/tests/ui/binding/fat-arrow-match.rs new file mode 100644 index 000000000..aaf5be8cf --- /dev/null +++ b/tests/ui/binding/fat-arrow-match.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum color { + red, + green, + blue +} + +pub fn main() { + println!("{}", match color::red { + color::red => { 1 } + color::green => { 2 } + color::blue => { 3 } + }); +} diff --git a/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs new file mode 100644 index 000000000..0450fe8ab --- /dev/null +++ b/tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -0,0 +1,69 @@ +// run-pass +// needs-unwind +// Check that partially moved from function parameters are dropped after the +// named bindings that move from them. + + +use std::{panic, cell::RefCell}; + +struct LogDrop<'a>(i32, Context<'a>); + +#[derive(Copy, Clone)] +struct Context<'a> { + panic_on: i32, + drops: &'a RefCell<Vec<i32>>, +} + +impl<'a> Context<'a> { + fn record_drop(self, index: i32) { + self.drops.borrow_mut().push(index); + if index == self.panic_on { + panic!(); + } + } +} + +impl<'a> Drop for LogDrop<'a> { + fn drop(&mut self) { + self.1.record_drop(self.0); + } +} + +fn bindings_in_params((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {} +fn bindings_with_let(a: (LogDrop, LogDrop), b: (LogDrop, LogDrop)) { + // Drop order in foo is the same as the following bindings. + // _temp2 is declared after _x to avoid a difference between `_: T` and + // `x: T` in function parameters. + let _temp1 = a; + let (_x, _) = _temp1; + + let _temp2 = b; + let (_, _y) = _temp2; +} + +fn test_drop_order(panic_on: i32, fun: fn((LogDrop, LogDrop), (LogDrop, LogDrop))) { + let context = Context { + panic_on, + drops: &RefCell::new(Vec::new()), + }; + let one = LogDrop(1, context); + let two = LogDrop(2, context); + let three = LogDrop(3, context); + let four = LogDrop(4, context); + + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { + fun((three, four), (two, one)); + })); + if panic_on == 0 { + assert!(res.is_ok(), "should not have panicked"); + } else { + assert!(res.is_err(), "should have panicked"); + } + assert_eq!(*context.drops.borrow(), [1, 2, 3, 4], "incorrect drop order"); +} + +fn main() { + (0..=4).for_each(|i| test_drop_order(i, bindings_in_params)); + (0..=4).for_each(|i| test_drop_order(i, bindings_with_let)); + (0..=4).for_each(|i| test_drop_order(i, |(_x, _), (_, _y)| {})); +} diff --git a/tests/ui/binding/fn-pattern-expected-type-2.rs b/tests/ui/binding/fn-pattern-expected-type-2.rs new file mode 100644 index 000000000..130ff3d44 --- /dev/null +++ b/tests/ui/binding/fn-pattern-expected-type-2.rs @@ -0,0 +1,8 @@ +// run-pass +pub fn main() { + let v : &[(isize,isize)] = &[ (1, 2), (3, 4), (5, 6) ]; + for &(x, y) in v { + println!("{}", y); + println!("{}", x); + } +} diff --git a/tests/ui/binding/fn-pattern-expected-type.rs b/tests/ui/binding/fn-pattern-expected-type.rs new file mode 100644 index 000000000..faeb76496 --- /dev/null +++ b/tests/ui/binding/fn-pattern-expected-type.rs @@ -0,0 +1,9 @@ +// run-pass + +pub fn main() { + let f = |(x, y): (isize, isize)| { + assert_eq!(x, 1); + assert_eq!(y, 2); + }; + f((1, 2)); +} diff --git a/tests/ui/binding/func-arg-incomplete-pattern.rs b/tests/ui/binding/func-arg-incomplete-pattern.rs new file mode 100644 index 000000000..eb94ee48f --- /dev/null +++ b/tests/ui/binding/func-arg-incomplete-pattern.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(dead_code)] +// Test that we do not leak when the arg pattern must drop part of the +// argument (in this case, the `y` field). + +struct Foo { + x: Box<usize>, + y: Box<usize>, +} + +fn foo(Foo {x, ..}: Foo) -> *const usize { + let addr: *const usize = &*x; + addr +} + +pub fn main() { + let obj: Box<_> = Box::new(1); + let objptr: *const usize = &*obj; + let f = Foo { x: obj, y: Box::new(2) }; + let xptr = foo(f); + assert_eq!(objptr, xptr); +} diff --git a/tests/ui/binding/func-arg-ref-pattern.rs b/tests/ui/binding/func-arg-ref-pattern.rs new file mode 100644 index 000000000..2d75c1214 --- /dev/null +++ b/tests/ui/binding/func-arg-ref-pattern.rs @@ -0,0 +1,26 @@ +// run-pass + +// Test argument patterns where we create refs to the inside of +// boxes. Make sure that we don't free the box as we match the +// pattern. + +#![feature(box_patterns)] + +fn getaddr(box ref x: Box<usize>) -> *const usize { + let addr: *const usize = &*x; + addr +} + +fn checkval(box ref x: Box<usize>) -> usize { + *x +} + +pub fn main() { + let obj: Box<_> = Box::new(1); + let objptr: *const usize = &*obj; + let xptr = getaddr(obj); + assert_eq!(objptr, xptr); + + let obj = Box::new(22); + assert_eq!(checkval(obj), 22); +} diff --git a/tests/ui/binding/func-arg-wild-pattern.rs b/tests/ui/binding/func-arg-wild-pattern.rs new file mode 100644 index 000000000..bcd82c679 --- /dev/null +++ b/tests/ui/binding/func-arg-wild-pattern.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that we can compile code that uses a `_` in function argument +// patterns. + + +fn foo((x, _): (isize, isize)) -> isize { + x +} + +pub fn main() { + assert_eq!(foo((22, 23)), 22); +} diff --git a/tests/ui/binding/if-let.rs b/tests/ui/binding/if-let.rs new file mode 100644 index 000000000..28d57e92c --- /dev/null +++ b/tests/ui/binding/if-let.rs @@ -0,0 +1,60 @@ +// run-pass +#![allow(dead_code)] + +pub fn main() { + let x = Some(3); + if let Some(y) = x { + assert_eq!(y, 3); + } else { + panic!("`if let` panicked"); + } + let mut worked = false; + if let Some(_) = x { + worked = true; + } + assert!(worked); + let clause: usize; + if let None = Some("test") { + clause = 1; + } else if 4_usize > 5 { + clause = 2; + } else if let Ok(()) = Err::<(),&'static str>("test") { + clause = 3; + } else { + clause = 4; + } + assert_eq!(clause, 4_usize); + + if 3 > 4 { + panic!("bad math"); + } else if let 1 = 2 { + panic!("bad pattern match"); + } + + enum Foo { + One, + Two(usize), + Three(String, isize) + } + + let foo = Foo::Three("three".to_string(), 42); + if let Foo::One = foo { + panic!("bad pattern match"); + } else if let Foo::Two(_x) = foo { + panic!("bad pattern match"); + } else if let Foo::Three(s, _) = foo { + assert_eq!(s, "three"); + } else { + panic!("bad else"); + } + + if false { + panic!("wat"); + } else if let a@Foo::Two(_) = Foo::Two(42_usize) { + if let Foo::Two(b) = a { + assert_eq!(b, 42_usize); + } else { + panic!("panic in nested `if let`"); + } + } +} diff --git a/tests/ui/binding/inconsistent-lifetime-mismatch.rs b/tests/ui/binding/inconsistent-lifetime-mismatch.rs new file mode 100644 index 000000000..87768c28c --- /dev/null +++ b/tests/ui/binding/inconsistent-lifetime-mismatch.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +fn foo(_: &[&str]) {} + +fn bad(a: &str, b: &str) { + foo(&[a, b]); +} + +fn good(a: &str, b: &str) { + foo(&[a, b]); +} + +fn main() {} diff --git a/tests/ui/binding/inferred-suffix-in-pattern-range.rs b/tests/ui/binding/inferred-suffix-in-pattern-range.rs new file mode 100644 index 000000000..079cc0a16 --- /dev/null +++ b/tests/ui/binding/inferred-suffix-in-pattern-range.rs @@ -0,0 +1,24 @@ +// run-pass + +pub fn main() { + let x = 2; + let x_message = match x { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(x_message, "lots".to_string()); + + let y = 2; + let y_message = match y { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(y_message, "lots".to_string()); + + let z = 1u64; + let z_message = match z { + 0 ..= 1 => { "not many".to_string() } + _ => { "lots".to_string() } + }; + assert_eq!(z_message, "not many".to_string()); +} diff --git a/tests/ui/binding/irrefutable-slice-patterns.rs b/tests/ui/binding/irrefutable-slice-patterns.rs new file mode 100644 index 000000000..048e1e5e9 --- /dev/null +++ b/tests/ui/binding/irrefutable-slice-patterns.rs @@ -0,0 +1,14 @@ +// run-pass + +// Regression test for #47096. + +fn foo(s: &[i32]) -> &[i32] { + let &[ref xs @ ..] = s; + xs +} + +fn main() { + let x = [1, 2, 3]; + let y = foo(&x); + assert_eq!(x, y); +} diff --git a/tests/ui/binding/issue-53114-borrow-checks.rs b/tests/ui/binding/issue-53114-borrow-checks.rs new file mode 100644 index 000000000..7646472f4 --- /dev/null +++ b/tests/ui/binding/issue-53114-borrow-checks.rs @@ -0,0 +1,84 @@ +// Issue #53114: NLL's borrow check had some deviations from the old borrow +// checker, and both had some deviations from our ideal state. This test +// captures the behavior of how `_` bindings are handled with respect to how we +// flag expressions that are meant to request unsafe blocks. +#![allow(irrefutable_let_patterns)] +struct M; + +fn let_wild_gets_moved_expr() { + let m = M; + drop(m); + let _ = m; // accepted, and want it to continue to be + + let mm = (M, M); // variation on above with `_` in substructure + let (_x, _) = mm; + let (_, _y) = mm; + let (_, _) = mm; +} + +fn match_moved_expr_to_wild() { + let m = M; + drop(m); + match m { _ => { } } // #53114: should eventually be accepted too + //~^ ERROR [E0382] + + let mm = (M, M); // variation on above with `_` in substructure + match mm { (_x, _) => { } } + match mm { (_, _y) => { } } + //~^ ERROR [E0382] + match mm { (_, _) => { } } + //~^ ERROR [E0382] +} + +fn if_let_moved_expr_to_wild() { + let m = M; + drop(m); + if let _ = m { } // #53114: should eventually be accepted too + //~^ ERROR [E0382] + + let mm = (M, M); // variation on above with `_` in substructure + if let (_x, _) = mm { } + if let (_, _y) = mm { } + //~^ ERROR [E0382] + if let (_, _) = mm { } + //~^ ERROR [E0382] +} + +fn let_wild_gets_borrowed_expr() { + let mut m = M; + let r = &mut m; + let _ = m; // accepted, and want it to continue to be + // let _x = m; // (compare with this error.) + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + let (_, _) = mm; + drop((r1, r2)); +} + +fn match_borrowed_expr_to_wild() { + let mut m = M; + let r = &mut m; + match m { _ => {} } ; // accepted, and want it to continue to be + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + match mm { (_, _) => { } } + drop((r1, r2)); +} + +fn if_let_borrowed_expr_to_wild() { + let mut m = M; + let r = &mut m; + if let _ = m { } // accepted, and want it to continue to be + drop(r); + + let mut mm = (M, M); // variation on above with `_` in substructure + let (r1, r2) = (&mut mm.0, &mut mm.1); + if let (_, _) = mm { } + drop((r1, r2)); +} + +fn main() { } diff --git a/tests/ui/binding/issue-53114-borrow-checks.stderr b/tests/ui/binding/issue-53114-borrow-checks.stderr new file mode 100644 index 000000000..0ec2ae883 --- /dev/null +++ b/tests/ui/binding/issue-53114-borrow-checks.stderr @@ -0,0 +1,81 @@ +error[E0382]: use of moved value: `m` + --> $DIR/issue-53114-borrow-checks.rs:22:11 + | +LL | let m = M; + | - move occurs because `m` has type `M`, which does not implement the `Copy` trait +LL | drop(m); + | - value moved here +LL | match m { _ => { } } // #53114: should eventually be accepted too + | ^ value used here after move + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:27:11 + | +LL | match mm { (_x, _) => { } } + | -- value partially moved here +LL | match mm { (_, _y) => { } } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (ref _x, _) => { } } + | +++ + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:29:11 + | +LL | match mm { (_, _y) => { } } + | -- value partially moved here +LL | +LL | match mm { (_, _) => { } } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (_, ref _y) => { } } + | +++ + +error[E0382]: use of moved value: `m` + --> $DIR/issue-53114-borrow-checks.rs:36:16 + | +LL | let m = M; + | - move occurs because `m` has type `M`, which does not implement the `Copy` trait +LL | drop(m); + | - value moved here +LL | if let _ = m { } // #53114: should eventually be accepted too + | ^ value used here after move + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:41:22 + | +LL | if let (_x, _) = mm { } + | -- value partially moved here +LL | if let (_, _y) = mm { } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (ref _x, _) = mm { } + | +++ + +error[E0382]: use of partially moved value: `mm` + --> $DIR/issue-53114-borrow-checks.rs:43:21 + | +LL | if let (_, _y) = mm { } + | -- value partially moved here +LL | +LL | if let (_, _) = mm { } + | ^^ value used here after partial move + | + = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (_, ref _y) = mm { } + | +++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/binding/issue-53114-safety-checks.rs b/tests/ui/binding/issue-53114-safety-checks.rs new file mode 100644 index 000000000..d0eb28c57 --- /dev/null +++ b/tests/ui/binding/issue-53114-safety-checks.rs @@ -0,0 +1,51 @@ +// Issue #53114: NLL's borrow check had some deviations from the old borrow +// checker, and both had some deviations from our ideal state. This test +// captures the behavior of how `_` bindings are handled with respect to how we +// flag expressions that are meant to request unsafe blocks. + +#[derive(Copy, Clone)] +struct I(i64); +#[derive(Copy, Clone)] +struct F(f64); + +union U { a: I, b: F } + +#[repr(packed)] +struct P { + a: &'static i8, + b: &'static u32, +} + +fn let_wild_gets_unsafe_field() { + let u1 = U { a: I(0) }; + let u2 = U { a: I(1) }; + let p = P { a: &2, b: &3 }; + let _ = &p.b; //~ ERROR reference to packed field + //~^ WARN will become a hard error + let _ = u1.a; // #53114: should eventually signal error as well + let _ = &u2.a; //~ ERROR [E0133] + + // variation on above with `_` in substructure + let (_,) = (&p.b,); //~ ERROR reference to packed field + //~^ WARN will become a hard error + let (_,) = (u1.a,); //~ ERROR [E0133] + let (_,) = (&u2.a,); //~ ERROR [E0133] +} + +fn match_unsafe_field_to_wild() { + let u1 = U { a: I(0) }; + let u2 = U { a: I(1) }; + let p = P { a: &2, b: &3 }; + match &p.b { _ => { } } //~ ERROR reference to packed field + //~^ WARN will become a hard error + match u1.a { _ => { } } //~ ERROR [E0133] + match &u2.a { _ => { } } //~ ERROR [E0133] + + // variation on above with `_` in substructure + match (&p.b,) { (_,) => { } } //~ ERROR reference to packed field + //~^ WARN will become a hard error + match (u1.a,) { (_,) => { } } //~ ERROR [E0133] + match (&u2.a,) { (_,) => { } } //~ ERROR [E0133] +} + +fn main() { } diff --git a/tests/ui/binding/issue-53114-safety-checks.stderr b/tests/ui/binding/issue-53114-safety-checks.stderr new file mode 100644 index 000000000..57a065d6d --- /dev/null +++ b/tests/ui/binding/issue-53114-safety-checks.stderr @@ -0,0 +1,156 @@ +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:23:13 + | +LL | let _ = &p.b; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:26:13 + | +LL | let _ = &u2.a; + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:31:17 + | +LL | let (_,) = (u1.a,); + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:32:17 + | +LL | let (_,) = (&u2.a,); + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:41:11 + | +LL | match u1.a { _ => { } } + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:42:11 + | +LL | match &u2.a { _ => { } } + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:47:12 + | +LL | match (u1.a,) { (_,) => { } } + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/issue-53114-safety-checks.rs:48:12 + | +LL | match (&u2.a,) { (_,) => { } } + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0133`. +Future incompatibility report: Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:23:13 + | +LL | let _ = &p.b; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:29:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:39:11 + | +LL | match &p.b { _ => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + +Future breakage diagnostic: +error: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:45:12 + | +LL | match (&p.b,) { (_,) => { } } + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523> + = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + = note: `#[deny(unaligned_references)]` on by default + diff --git a/tests/ui/binding/let-assignability.rs b/tests/ui/binding/let-assignability.rs new file mode 100644 index 000000000..b85f4a96a --- /dev/null +++ b/tests/ui/binding/let-assignability.rs @@ -0,0 +1,11 @@ +// run-pass + +fn f() { + let a: Box<_> = Box::new(1); + let b: &isize = &*a; + println!("{}", b); +} + +pub fn main() { + f(); +} diff --git a/tests/ui/binding/let-destruct-ref.rs b/tests/ui/binding/let-destruct-ref.rs new file mode 100644 index 000000000..28d7294eb --- /dev/null +++ b/tests/ui/binding/let-destruct-ref.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = 3_usize; + let ref y = x; + assert_eq!(x, *y); +} diff --git a/tests/ui/binding/let-var-hygiene.rs b/tests/ui/binding/let-var-hygiene.rs new file mode 100644 index 000000000..571207bd7 --- /dev/null +++ b/tests/ui/binding/let-var-hygiene.rs @@ -0,0 +1,11 @@ +// run-pass +// shouldn't affect evaluation of $ex: + +macro_rules! bad_macro { + ($ex:expr) => ({let _x = 9; $ex}) +} + +pub fn main() { + let _x = 8; + assert_eq!(bad_macro!(_x),8) +} diff --git a/tests/ui/binding/match-arm-statics.rs b/tests/ui/binding/match-arm-statics.rs new file mode 100644 index 000000000..e6d17def1 --- /dev/null +++ b/tests/ui/binding/match-arm-statics.rs @@ -0,0 +1,165 @@ +// run-pass +#![allow(dead_code)] +// compile-flags: -g +// ignore-asmjs wasm2js does not support source maps yet + +#[derive(PartialEq, Eq)] +struct NewBool(bool); + +#[derive(PartialEq, Eq)] +enum Direction { + North, + East, + South, + West +} + +#[derive(PartialEq, Eq)] +struct Foo { + bar: Option<Direction>, + baz: NewBool +} + +#[derive(PartialEq, Eq)] +enum EnumWithStructVariants { + Variant1(bool), + Variant2 { + dir: Direction + } +} + +const TRUE_TRUE: (bool, bool) = (true, true); +const NONE: Option<Direction> = None; +const EAST: Direction = Direction::East; +const NEW_FALSE: NewBool = NewBool(false); +const STATIC_FOO: Foo = Foo { bar: Some(Direction::South), baz: NEW_FALSE }; +const VARIANT2_NORTH: EnumWithStructVariants = EnumWithStructVariants::Variant2 { + dir: Direction::North }; + +pub mod glfw { + #[derive(Copy, Clone, PartialEq, Eq)] + pub struct InputState(usize); + + pub const RELEASE : InputState = InputState(0); + pub const PRESS : InputState = InputState(1); + pub const REPEAT : InputState = InputState(2); +} + +fn issue_6533() { + fn action_to_str(state: glfw::InputState) -> &'static str { + use glfw::{RELEASE, PRESS, REPEAT}; + match state { + RELEASE => { "Released" } + PRESS => { "Pressed" } + REPEAT => { "Repeated" } + _ => { "Unknown" } + } + } + + assert_eq!(action_to_str(glfw::RELEASE), "Released"); + assert_eq!(action_to_str(glfw::PRESS), "Pressed"); + assert_eq!(action_to_str(glfw::REPEAT), "Repeated"); +} + +fn issue_13626() { + const VAL: [u8; 1] = [0]; + match [1] { + VAL => unreachable!(), + _ => () + } +} + +fn issue_14576() { + type Foo = (i32, i32); + const ON: Foo = (1, 1); + const OFF: Foo = (0, 0); + + match (1, 1) { + OFF => unreachable!(), + ON => (), + _ => unreachable!() + } + + #[derive(PartialEq, Eq)] + enum C { D = 3, E = 4 } + const F : C = C::D; + + assert_eq!(match C::D { F => 1, _ => 2, }, 1); + + // test gaps + #[derive(PartialEq, Eq)] + enum G { H = 3, I = 5 } + const K : G = G::I; + + assert_eq!(match G::I { K => 1, _ => 2, }, 1); +} + +fn issue_13731() { + #[derive(PartialEq, Eq)] + enum A { AA(()) } + const B: A = A::AA(()); + + match A::AA(()) { + B => () + } +} + +fn issue_15393() { + #![allow(dead_code)] + #[derive(PartialEq, Eq)] + struct Flags { + bits: usize + } + + const FOO: Flags = Flags { bits: 0x01 }; + const BAR: Flags = Flags { bits: 0x02 }; + match (Flags { bits: 0x02 }) { + FOO => unreachable!(), + BAR => (), + _ => unreachable!() + } +} + +fn main() { + assert_eq!(match (true, false) { + TRUE_TRUE => 1, + (false, false) => 2, + (false, true) => 3, + (true, false) => 4 + }, 4); + + assert_eq!(match Some(Some(Direction::North)) { + Some(NONE) => 1, + Some(Some(Direction::North)) => 2, + Some(Some(EAST)) => 3, + Some(Some(Direction::South)) => 4, + Some(Some(Direction::West)) => 5, + None => 6 + }, 2); + + assert_eq!(match (Foo { bar: Some(Direction::West), baz: NewBool(true) }) { + Foo { bar: None, baz: NewBool(true) } => 1, + Foo { bar: NONE, baz: NEW_FALSE } => 2, + STATIC_FOO => 3, + Foo { bar: _, baz: NEW_FALSE } => 4, + Foo { bar: Some(Direction::West), baz: NewBool(true) } => 5, + Foo { bar: Some(Direction::South), baz: NewBool(true) } => 6, + Foo { bar: Some(EAST), .. } => 7, + Foo { bar: Some(Direction::North), baz: NewBool(true) } => 8 + }, 5); + + assert_eq!(match (EnumWithStructVariants::Variant2 { dir: Direction::North }) { + EnumWithStructVariants::Variant1(true) => 1, + EnumWithStructVariants::Variant1(false) => 2, + EnumWithStructVariants::Variant2 { dir: Direction::West } => 3, + VARIANT2_NORTH => 4, + EnumWithStructVariants::Variant2 { dir: Direction::South } => 5, + EnumWithStructVariants::Variant2 { dir: Direction::East } => 6 + }, 4); + + issue_6533(); + issue_13626(); + issue_13731(); + issue_14576(); + issue_15393(); +} diff --git a/tests/ui/binding/match-beginning-vert.rs b/tests/ui/binding/match-beginning-vert.rs new file mode 100644 index 000000000..79267400b --- /dev/null +++ b/tests/ui/binding/match-beginning-vert.rs @@ -0,0 +1,19 @@ +// run-pass +enum Foo { + A, + B, + C, + D, + E, +} +use Foo::*; + +fn main() { + for foo in &[A, B, C, D, E] { + match *foo { + | A => println!("A"), + | B | C if 1 < 2 => println!("BC!"), + | _ => {}, + } + } +} diff --git a/tests/ui/binding/match-borrowed_str.rs b/tests/ui/binding/match-borrowed_str.rs new file mode 100644 index 000000000..22782032e --- /dev/null +++ b/tests/ui/binding/match-borrowed_str.rs @@ -0,0 +1,48 @@ +// run-pass + +fn f1(ref_string: &str) -> String { + match ref_string { + "a" => "found a".to_string(), + "b" => "found b".to_string(), + _ => "not found".to_string() + } +} + +fn f2(ref_string: &str) -> String { + match ref_string { + "a" => "found a".to_string(), + "b" => "found b".to_string(), + s => format!("not found ({})", s) + } +} + +fn g1(ref_1: &str, ref_2: &str) -> String { + match (ref_1, ref_2) { + ("a", "b") => "found a,b".to_string(), + ("b", "c") => "found b,c".to_string(), + _ => "not found".to_string() + } +} + +fn g2(ref_1: &str, ref_2: &str) -> String { + match (ref_1, ref_2) { + ("a", "b") => "found a,b".to_string(), + ("b", "c") => "found b,c".to_string(), + (s1, s2) => format!("not found ({}, {})", s1, s2) + } +} + +pub fn main() { + assert_eq!(f1("b"), "found b".to_string()); + assert_eq!(f1("c"), "not found".to_string()); + assert_eq!(f1("d"), "not found".to_string()); + assert_eq!(f2("b"), "found b".to_string()); + assert_eq!(f2("c"), "not found (c)".to_string()); + assert_eq!(f2("d"), "not found (d)".to_string()); + assert_eq!(g1("b", "c"), "found b,c".to_string()); + assert_eq!(g1("c", "d"), "not found".to_string()); + assert_eq!(g1("d", "e"), "not found".to_string()); + assert_eq!(g2("b", "c"), "found b,c".to_string()); + assert_eq!(g2("c", "d"), "not found (c, d)".to_string()); + assert_eq!(g2("d", "e"), "not found (d, e)".to_string()); +} diff --git a/tests/ui/binding/match-bot-2.rs b/tests/ui/binding/match-bot-2.rs new file mode 100644 index 000000000..95b3406f0 --- /dev/null +++ b/tests/ui/binding/match-bot-2.rs @@ -0,0 +1,6 @@ +// run-pass +#![allow(unreachable_code)] +// n.b. This was only ever failing with optimization disabled. + +fn a() -> isize { match return 1 { 2 => 3, _ => panic!() } } +pub fn main() { a(); } diff --git a/tests/ui/binding/match-bot.rs b/tests/ui/binding/match-bot.rs new file mode 100644 index 000000000..5c4472c7a --- /dev/null +++ b/tests/ui/binding/match-bot.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let i: isize = + match Some::<isize>(3) { None::<isize> => { panic!() } Some::<isize>(_) => { 5 } }; + println!("{}", i); +} diff --git a/tests/ui/binding/match-byte-array-patterns.rs b/tests/ui/binding/match-byte-array-patterns.rs new file mode 100644 index 000000000..f0c988c01 --- /dev/null +++ b/tests/ui/binding/match-byte-array-patterns.rs @@ -0,0 +1,44 @@ +// run-pass + +fn main() { + let buf = &[0u8; 4]; + match buf { + &[0, 1, 0, 0] => unimplemented!(), + b"true" => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, 1, 0, 0] => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, x, 0, 0] => assert_eq!(x, 0), + _ => unimplemented!(), + } + + let buf: &[u8] = buf; + + match buf { + &[0, 1, 0, 0] => unimplemented!(), + &[_] => unimplemented!(), + &[_, _, _, _, _, ..] => unimplemented!(), + b"true" => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, 1, 0, 0] => unimplemented!(), + _ => {} + } + + match buf { + b"true" => unimplemented!(), + &[0, x, 0, 0] => assert_eq!(x, 0), + _ => unimplemented!(), + } +} diff --git a/tests/ui/binding/match-enum-struct-0.rs b/tests/ui/binding/match-enum-struct-0.rs new file mode 100644 index 000000000..e2623ece8 --- /dev/null +++ b/tests/ui/binding/match-enum-struct-0.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +// regression test for issue #5625 + + +enum E { + Foo{f : isize}, + Bar +} + +pub fn main() { + let e = E::Bar; + match e { + E::Foo{f: _f} => panic!(), + _ => (), + } +} diff --git a/tests/ui/binding/match-enum-struct-1.rs b/tests/ui/binding/match-enum-struct-1.rs new file mode 100644 index 000000000..f035432ec --- /dev/null +++ b/tests/ui/binding/match-enum-struct-1.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +enum E { + Foo{f : isize}, + Bar +} + +pub fn main() { + let e = E::Foo{f: 1}; + match e { + E::Foo{..} => (), + _ => panic!(), + } + match e { + E::Foo{f: _f} => (), + _ => panic!(), + } +} diff --git a/tests/ui/binding/match-implicit-copy-unique.rs b/tests/ui/binding/match-implicit-copy-unique.rs new file mode 100644 index 000000000..74ffe2ecd --- /dev/null +++ b/tests/ui/binding/match-implicit-copy-unique.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Pair { a: Box<isize>, b: Box<isize> } + +pub fn main() { + let mut x: Box<_> = Box::new(Pair { a: Box::new(10), b: Box::new(20) }); + let x_internal = &mut *x; + match *x_internal { + Pair {a: ref mut a, b: ref mut _b} => { + assert_eq!(**a, 10); + *a = Box::new(30); + assert_eq!(**a, 30); + } + } +} diff --git a/tests/ui/binding/match-in-macro.rs b/tests/ui/binding/match-in-macro.rs new file mode 100644 index 000000000..0840cc440 --- /dev/null +++ b/tests/ui/binding/match-in-macro.rs @@ -0,0 +1,17 @@ +// run-pass + +enum Foo { + B { b1: isize, bb1: isize}, +} + +macro_rules! match_inside_expansion { + () => ( + match (Foo::B { b1:29 , bb1: 100}) { + Foo::B { b1:b2 , bb1:bb2 } => b2+bb2 + } + ) +} + +pub fn main() { + assert_eq!(match_inside_expansion!(),129); +} diff --git a/tests/ui/binding/match-join.rs b/tests/ui/binding/match-join.rs new file mode 100644 index 000000000..60f2a4584 --- /dev/null +++ b/tests/ui/binding/match-join.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(unused_mut)] +fn foo<T>(y: Option<T>) { + let mut x: isize; + let mut rs: Vec<isize> = Vec::new(); + /* tests that x doesn't get put in the precondition for the + entire if expression */ + + if true { + } else { + match y { + None::<T> => x = 17, + _ => x = 42 + } + rs.push(x); + } + return; +} + +pub fn main() { println!("hello"); foo::<isize>(Some::<isize>(5)); } diff --git a/tests/ui/binding/match-larger-const.rs b/tests/ui/binding/match-larger-const.rs new file mode 100644 index 000000000..6f9a35320 --- /dev/null +++ b/tests/ui/binding/match-larger-const.rs @@ -0,0 +1,12 @@ +// run-pass +#[derive(Eq, PartialEq)] +pub struct Data([u8; 4]); + +const DATA: Data = Data([1, 2, 3, 4]); + +fn main() { + match DATA { + DATA => (), + _ => (), + } +} diff --git a/tests/ui/binding/match-naked-record-expr.rs b/tests/ui/binding/match-naked-record-expr.rs new file mode 100644 index 000000000..c23ff8c94 --- /dev/null +++ b/tests/ui/binding/match-naked-record-expr.rs @@ -0,0 +1,12 @@ +// run-pass +// pretty-expanded FIXME #23616 + +struct X { x: isize } + +pub fn main() { + let _x = match 0 { + _ => X { + x: 0 + }.x + }; +} diff --git a/tests/ui/binding/match-naked-record.rs b/tests/ui/binding/match-naked-record.rs new file mode 100644 index 000000000..f7479152e --- /dev/null +++ b/tests/ui/binding/match-naked-record.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +struct X { x: isize } + +pub fn main() { + let _x = match 0 { + _ => X { + x: 0 + } + }; +} diff --git a/tests/ui/binding/match-path.rs b/tests/ui/binding/match-path.rs new file mode 100644 index 000000000..286214eb8 --- /dev/null +++ b/tests/ui/binding/match-path.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +// pretty-expanded FIXME #23616 + +mod m1 { + pub enum foo { foo1, foo2, } +} + +fn bar(x: m1::foo) { match x { m1::foo::foo1 => { } m1::foo::foo2 => { } } } + +pub fn main() { } diff --git a/tests/ui/binding/match-pattern-bindings.rs b/tests/ui/binding/match-pattern-bindings.rs new file mode 100644 index 000000000..4ec533677 --- /dev/null +++ b/tests/ui/binding/match-pattern-bindings.rs @@ -0,0 +1,21 @@ +// run-pass + +fn main() { + let value = Some(1); + assert_eq!(match value { + ref a @ Some(_) => a, + ref b @ None => b + }, &Some(1)); + assert_eq!(match value { + ref c @ Some(_) => c, + ref b @ None => b + }, &Some(1)); + assert_eq!(match "foobarbaz" { + b @ _ => b + }, "foobarbaz"); + let a @ _ = "foobarbaz"; + assert_eq!(a, "foobarbaz"); + let value = Some(true); + let ref a @ _ = value; + assert_eq!(a, &Some(true)); +} diff --git a/tests/ui/binding/match-pattern-lit.rs b/tests/ui/binding/match-pattern-lit.rs new file mode 100644 index 000000000..c9c6135e2 --- /dev/null +++ b/tests/ui/binding/match-pattern-lit.rs @@ -0,0 +1,15 @@ +// run-pass + + +fn altlit(f: isize) -> isize { + match f { + 10 => { println!("case 10"); return 20; } + 11 => { println!("case 11"); return 22; } + _ => panic!("the impossible happened") + } +} + +pub fn main() { + assert_eq!(altlit(10), 20); + assert_eq!(altlit(11), 22); +} diff --git a/tests/ui/binding/match-pattern-no-type-params.rs b/tests/ui/binding/match-pattern-no-type-params.rs new file mode 100644 index 000000000..1fc7ddda0 --- /dev/null +++ b/tests/ui/binding/match-pattern-no-type-params.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +enum maybe<T> { nothing, just(T), } + +fn foo(x: maybe<isize>) { + match x { + maybe::nothing => { println!("A"); } + maybe::just(_a) => { println!("B"); } + } +} + +pub fn main() { } diff --git a/tests/ui/binding/match-pattern-simple.rs b/tests/ui/binding/match-pattern-simple.rs new file mode 100644 index 000000000..3f56cd479 --- /dev/null +++ b/tests/ui/binding/match-pattern-simple.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(dead_code)] + + +// pretty-expanded FIXME #23616 + +fn altsimple(f: isize) { match f { _x => () } } + +pub fn main() { } diff --git a/tests/ui/binding/match-phi.rs b/tests/ui/binding/match-phi.rs new file mode 100644 index 000000000..92a3f6e0f --- /dev/null +++ b/tests/ui/binding/match-phi.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +// pretty-expanded FIXME #23616 +#![allow(non_camel_case_types)] +#![allow(unused_variables)] + +enum thing { a, b, c, } + +fn foo<F>(it: F) where F: FnOnce(isize) { it(10); } + +pub fn main() { + let mut x = true; + match thing::a { + thing::a => { x = true; foo(|_i| { } ) } + thing::b => { x = false; } + thing::c => { x = false; } + } +} diff --git a/tests/ui/binding/match-pipe-binding.rs b/tests/ui/binding/match-pipe-binding.rs new file mode 100644 index 000000000..7d4a7c708 --- /dev/null +++ b/tests/ui/binding/match-pipe-binding.rs @@ -0,0 +1,60 @@ +// run-pass + +fn test1() { + // from issue 6338 + match ((1, "a".to_string()), (2, "b".to_string())) { + ((1, a), (2, b)) | ((2, b), (1, a)) => { + assert_eq!(a, "a".to_string()); + assert_eq!(b, "b".to_string()); + }, + _ => panic!(), + } +} + +fn test2() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => panic!(), + } +} + +fn test3() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => panic!(), + } +} + +fn test4() { + match (1, 2, 3) { + (1, a, b) | (2, b, a) if a == 2 => { + assert_eq!(a, 2); + assert_eq!(b, 3); + }, + _ => panic!(), + } +} + +fn test5() { + match (1, 2, 3) { + (1, ref a, ref b) | (2, ref b, ref a) if *a == 2 => { + assert_eq!(*a, 2); + assert_eq!(*b, 3); + }, + _ => panic!(), + } +} + +pub fn main() { + test1(); + test2(); + test3(); + test4(); + test5(); +} diff --git a/tests/ui/binding/match-range-infer.rs b/tests/ui/binding/match-range-infer.rs new file mode 100644 index 000000000..19d1cb89d --- /dev/null +++ b/tests/ui/binding/match-range-infer.rs @@ -0,0 +1,17 @@ +// run-pass +// Test that type inference for range patterns works correctly (is bi-directional). + +pub fn main() { + match 1 { + 1 ..= 3 => {} + _ => panic!("should match range") + } + match 1 { + 1 ..= 3u16 => {} + _ => panic!("should match range with inferred start type") + } + match 1 { + 1u16 ..= 3 => {} + _ => panic!("should match range with inferred end type") + } +} diff --git a/tests/ui/binding/match-range-static.rs b/tests/ui/binding/match-range-static.rs new file mode 100644 index 000000000..f01a3505e --- /dev/null +++ b/tests/ui/binding/match-range-static.rs @@ -0,0 +1,13 @@ +// run-pass +// pretty-expanded FIXME #23616 +#![allow(non_upper_case_globals)] + +const s: isize = 1; +const e: isize = 42; + +pub fn main() { + match 7 { + s..=e => (), + _ => (), + } +} diff --git a/tests/ui/binding/match-range.rs b/tests/ui/binding/match-range.rs new file mode 100644 index 000000000..1dca84dfd --- /dev/null +++ b/tests/ui/binding/match-range.rs @@ -0,0 +1,51 @@ +// run-pass +#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 +#![feature(exclusive_range_pattern)] + +pub fn main() { + match 5_usize { + 1_usize..=5_usize => {} + _ => panic!("should match range"), + } + match 1_usize { + 1_usize..5_usize => {} + _ => panic!("should match range start"), + } + match 5_usize { + 6_usize..=7_usize => panic!("shouldn't match range"), + _ => {} + } + match 7_usize { + 6_usize..7_usize => panic!("shouldn't match range end"), + _ => {}, + } + match 5_usize { + 1_usize => panic!("should match non-first range"), + 2_usize..=6_usize => {} + _ => panic!("math is broken") + } + match 'c' { + 'a'..='z' => {} + _ => panic!("should support char ranges") + } + match -3 { + -7..=5 => {} + _ => panic!("should match signed range") + } + match 3.0f64 { + 1.0..=5.0 => {} + _ => panic!("should match float range") + } + match -1.5f64 { + -3.6..=3.6 => {} + _ => panic!("should match negative float range") + } + match 3.5 { + 0.0..3.5 => panic!("should not match the range end"), + _ => {}, + } + match 0.0 { + 0.0..3.5 => {}, + _ => panic!("should match the range start"), + } +} diff --git a/tests/ui/binding/match-reassign.rs b/tests/ui/binding/match-reassign.rs new file mode 100644 index 000000000..19b48579c --- /dev/null +++ b/tests/ui/binding/match-reassign.rs @@ -0,0 +1,21 @@ +// run-pass +// Regression test for #23698: The reassignment checker only cared +// about the last assignment in a match arm body + +// Use an extra function to make sure no extra assignments +// are introduced by macros in the match statement +fn check_eq(x: i32, y: i32) { + assert_eq!(x, y); +} + +#[allow(unused_assignments)] +fn main() { + let mut x = Box::new(1); + match x { + y => { + x = Box::new(2); + let _tmp = 1; // This assignment used to throw off the reassignment checker + check_eq(*y, 1); + } + } +} diff --git a/tests/ui/binding/match-ref-binding-in-guard-3256.rs b/tests/ui/binding/match-ref-binding-in-guard-3256.rs new file mode 100644 index 000000000..9075a34d4 --- /dev/null +++ b/tests/ui/binding/match-ref-binding-in-guard-3256.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::sync::Mutex; + +pub fn main() { + let x = Some(Mutex::new(true)); + match x { + Some(ref z) if *z.lock().unwrap() => { + assert!(*z.lock().unwrap()); + }, + _ => panic!() + } +} diff --git a/tests/ui/binding/match-ref-binding-mut-option.rs b/tests/ui/binding/match-ref-binding-mut-option.rs new file mode 100644 index 000000000..c25639b72 --- /dev/null +++ b/tests/ui/binding/match-ref-binding-mut-option.rs @@ -0,0 +1,10 @@ +// run-pass + +pub fn main() { + let mut v = Some(22); + match v { + None => {} + Some(ref mut p) => { *p += 1; } + } + assert_eq!(v, Some(23)); +} diff --git a/tests/ui/binding/match-ref-binding-mut.rs b/tests/ui/binding/match-ref-binding-mut.rs new file mode 100644 index 000000000..d7afd61bc --- /dev/null +++ b/tests/ui/binding/match-ref-binding-mut.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Rec { + f: isize +} + +fn destructure(x: &mut Rec) { + match *x { + Rec {f: ref mut f} => *f += 1 + } +} + +pub fn main() { + let mut v = Rec {f: 22}; + destructure(&mut v); + assert_eq!(v.f, 23); +} diff --git a/tests/ui/binding/match-ref-binding.rs b/tests/ui/binding/match-ref-binding.rs new file mode 100644 index 000000000..ac6a07eab --- /dev/null +++ b/tests/ui/binding/match-ref-binding.rs @@ -0,0 +1,12 @@ +// run-pass + +fn destructure(x: Option<isize>) -> isize { + match x { + None => 0, + Some(ref v) => *v + } +} + +pub fn main() { + assert_eq!(destructure(Some(22)), 22); +} diff --git a/tests/ui/binding/match-ref-unsized.rs b/tests/ui/binding/match-ref-unsized.rs new file mode 100644 index 000000000..53784ebb9 --- /dev/null +++ b/tests/ui/binding/match-ref-unsized.rs @@ -0,0 +1,11 @@ +// run-pass +// Binding unsized expressions to ref patterns + +pub fn main() { + let ref a = *"abcdef"; + assert_eq!(a, "abcdef"); + + match *"12345" { + ref b => { assert_eq!(b, "12345") } + } +} diff --git a/tests/ui/binding/match-str.rs b/tests/ui/binding/match-str.rs new file mode 100644 index 000000000..0ee18ea18 --- /dev/null +++ b/tests/ui/binding/match-str.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// Issue #53 +#![allow(non_camel_case_types)] + + +pub fn main() { + match "test" { "not-test" => panic!(), "test" => (), _ => panic!() } + + enum t { tag1(String), tag2, } + + + match t::tag1("test".to_string()) { + t::tag2 => panic!(), + t::tag1(ref s) if "test" != &**s => panic!(), + t::tag1(ref s) if "test" == &**s => (), + _ => panic!() + } + + let x = match "a" { "a" => 1, "b" => 2, _ => panic!() }; + assert_eq!(x, 1); + + match "a" { "a" => { } "b" => { }, _ => panic!() } + +} diff --git a/tests/ui/binding/match-struct-0.rs b/tests/ui/binding/match-struct-0.rs new file mode 100644 index 000000000..c49f3ed61 --- /dev/null +++ b/tests/ui/binding/match-struct-0.rs @@ -0,0 +1,21 @@ +// run-pass + +struct Foo{ + f : isize, +} + +pub fn main() { + let f = Foo{f: 1}; + match f { + Foo{f: 0} => panic!(), + Foo{..} => (), + } + match f { + Foo{f: 0} => panic!(), + Foo{f: _f} => (), + } + match f { + Foo{f: 0} => panic!(), + _ => (), + } +} diff --git a/tests/ui/binding/match-tag.rs b/tests/ui/binding/match-tag.rs new file mode 100644 index 000000000..407716aa2 --- /dev/null +++ b/tests/ui/binding/match-tag.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + + +#[allow(unused_tuple_struct_fields)] +enum color { + rgb(isize, isize, isize), + rgba(isize, isize, isize, isize), + hsl(isize, isize, isize), +} + +fn process(c: color) -> isize { + let mut x: isize; + match c { + color::rgb(r, _, _) => { x = r; } + color::rgba(_, _, _, a) => { x = a; } + color::hsl(_, s, _) => { x = s; } + } + return x; +} + +pub fn main() { + let gray: color = color::rgb(127, 127, 127); + let clear: color = color::rgba(50, 150, 250, 0); + let red: color = color::hsl(0, 255, 255); + assert_eq!(process(gray), 127); + assert_eq!(process(clear), 0); + assert_eq!(process(red), 255); +} diff --git a/tests/ui/binding/match-unique-bind.rs b/tests/ui/binding/match-unique-bind.rs new file mode 100644 index 000000000..507478983 --- /dev/null +++ b/tests/ui/binding/match-unique-bind.rs @@ -0,0 +1,11 @@ +// run-pass +#![feature(box_patterns)] + +pub fn main() { + match Box::new(100) { + box x => { + println!("{}", x); + assert_eq!(x, 100); + } + } +} diff --git a/tests/ui/binding/match-unsized.rs b/tests/ui/binding/match-unsized.rs new file mode 100644 index 000000000..41937a557 --- /dev/null +++ b/tests/ui/binding/match-unsized.rs @@ -0,0 +1,9 @@ +// run-pass +fn main() { + let data: &'static str = "Hello, World!"; + match data { + &ref xs => { + assert_eq!(data, xs); + } + } +} diff --git a/tests/ui/binding/match-value-binding-in-guard-3291.rs b/tests/ui/binding/match-value-binding-in-guard-3291.rs new file mode 100644 index 000000000..0d750da79 --- /dev/null +++ b/tests/ui/binding/match-value-binding-in-guard-3291.rs @@ -0,0 +1,17 @@ +// run-pass +// pretty-expanded FIXME #23616 + +fn foo(x: Option<Box<isize>>, b: bool) -> isize { + match x { + None => { 1 } + Some(ref x) if b => { *x.clone() } + Some(_) => { 0 } + } +} + +pub fn main() { + foo(Some(Box::new(22)), true); + foo(Some(Box::new(22)), false); + foo(None, true); + foo(None, false); +} diff --git a/tests/ui/binding/match-var-hygiene.rs b/tests/ui/binding/match-var-hygiene.rs new file mode 100644 index 000000000..43740bbcf --- /dev/null +++ b/tests/ui/binding/match-var-hygiene.rs @@ -0,0 +1,11 @@ +// run-pass +// shouldn't affect evaluation of $ex. +macro_rules! bad_macro { ($ex:expr) => ( + {match 9 {_x => $ex}} +)} + +fn main() { + match 8 { + _x => assert_eq!(bad_macro!(_x),8) + } +} diff --git a/tests/ui/binding/match-vec-alternatives.rs b/tests/ui/binding/match-vec-alternatives.rs new file mode 100644 index 000000000..af95eb95d --- /dev/null +++ b/tests/ui/binding/match-vec-alternatives.rs @@ -0,0 +1,80 @@ +// run-pass + +fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[..]) | (&[..], &[]) => "one empty", + (&[..], &[..]) => "both non-empty" + } +} + +fn match_vecs_cons<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[_, ..]) | (&[_, ..], &[]) => "one empty", + (&[_, ..], &[_, ..]) => "both non-empty" + } +} + +fn match_vecs_snoc<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { + match (l1, l2) { + (&[], &[]) => "both empty", + (&[], &[.., _]) | (&[.., _], &[]) => "one empty", + (&[.., _], &[.., _]) => "both non-empty" + } +} + +fn match_nested_vecs_cons<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str { + match (l1, l2) { + (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)", + (Some(&[_, ..]), Ok(_)) | (Some(&[_, ..]), Err(())) => "Some(non-empty), any", + (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)", + (None, Ok(&[_, _, ..])) => "None, Ok(at least two elements)", + _ => "other" + } +} + +fn match_nested_vecs_snoc<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str { + match (l1, l2) { + (Some(&[]), Ok(&[])) => "Some(empty), Ok(empty)", + (Some(&[.., _]), Ok(_)) | (Some(&[.., _]), Err(())) => "Some(non-empty), any", + (None, Ok(&[])) | (None, Err(())) | (None, Ok(&[_])) => "None, Ok(less than one element)", + (None, Ok(&[.., _, _])) => "None, Ok(at least two elements)", + _ => "other" + } +} + +fn main() { + assert_eq!(match_vecs(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs::<usize>(&[], &[]), "both empty"); + assert_eq!(match_vecs(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_vecs_cons(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs_cons(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs_cons::<usize>(&[], &[]), "both empty"); + assert_eq!(match_vecs_cons(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_vecs_snoc(&[1, 2], &[2, 3]), "both non-empty"); + assert_eq!(match_vecs_snoc(&[], &[1, 2, 3, 4]), "one empty"); + assert_eq!(match_vecs_snoc::<usize>(&[], &[]), "both empty"); + assert_eq!(match_vecs_snoc(&[1, 2, 3], &[]), "one empty"); + + assert_eq!(match_nested_vecs_cons(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), + "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_cons::<usize>(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_cons::<bool>(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[(42, ())]), Ok::<&[_], ()>(&[(1, ())])), + "Some(non-empty), any"); + + assert_eq!(match_nested_vecs_snoc(None, Ok::<&[_], ()>(&[4_usize, 2_usize])), + "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_snoc::<usize>(None, Err(())), "None, Ok(less than one element)"); + assert_eq!(match_nested_vecs_snoc::<bool>(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[1]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[(42, ())]), Ok::<&[_], ()>(&[(1, ())])), + "Some(non-empty), any"); +} diff --git a/tests/ui/binding/match-vec-rvalue.rs b/tests/ui/binding/match-vec-rvalue.rs new file mode 100644 index 000000000..fead2254c --- /dev/null +++ b/tests/ui/binding/match-vec-rvalue.rs @@ -0,0 +1,15 @@ +// run-pass +// Tests that matching rvalues with drops does not crash. + + + +pub fn main() { + match vec![1, 2, 3] { + x => { + assert_eq!(x.len(), 3); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + } + } +} diff --git a/tests/ui/binding/match-with-ret-arm.rs b/tests/ui/binding/match-with-ret-arm.rs new file mode 100644 index 000000000..58a909641 --- /dev/null +++ b/tests/ui/binding/match-with-ret-arm.rs @@ -0,0 +1,12 @@ +// run-pass +pub fn main() { + // sometimes we have had trouble finding + // the right type for f, as we unified + // bot and u32 here + let f = match "1234".parse::<usize>().ok() { + None => return (), + Some(num) => num as u32 + }; + assert_eq!(f, 1234); + println!("{}", f) +} diff --git a/tests/ui/binding/multi-let.rs b/tests/ui/binding/multi-let.rs new file mode 100644 index 000000000..064d32a70 --- /dev/null +++ b/tests/ui/binding/multi-let.rs @@ -0,0 +1,7 @@ +// run-pass + +pub fn main() { + let x = 10; + let y = x; + assert_eq!(y, 10); +} diff --git a/tests/ui/binding/mut-in-ident-patterns.rs b/tests/ui/binding/mut-in-ident-patterns.rs new file mode 100644 index 000000000..1d1dd660e --- /dev/null +++ b/tests/ui/binding/mut-in-ident-patterns.rs @@ -0,0 +1,76 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(non_camel_case_types)] +#![allow(non_shorthand_field_patterns)] + +trait Foo { + fn foo(&self, mut x: isize) -> isize { + let val = x; + x = 37 * x; + val + x + } +} + +struct X; +impl Foo for X {} + +pub fn main() { + let (a, mut b) = (23, 4); + assert_eq!(a, 23); + assert_eq!(b, 4); + b = a + b; + assert_eq!(b, 27); + + + assert_eq!(X.foo(2), 76); + + enum Bar { + Foo(isize), + Baz(f32, u8) + } + + let (x, mut y) = (32, Bar::Foo(21)); + + match x { + mut z @ 32 => { + assert_eq!(z, 32); + z = 34; + assert_eq!(z, 34); + } + _ => {} + } + + check_bar(&y); + y = Bar::Baz(10.0, 3); + check_bar(&y); + + fn check_bar(y: &Bar) { + match y { + &Bar::Foo(a) => { + assert_eq!(a, 21); + } + &Bar::Baz(a, b) => { + assert_eq!(a, 10.0); + assert_eq!(b, 3); + } + } + } + + fn foo1((x, mut y): (f64, isize), mut z: isize) -> isize { + y = 2 * 6; + z = y + (x as isize); + y - z + } + + struct A { + x: isize + } + let A { x: mut x } = A { x: 10 }; + assert_eq!(x, 10); + x = 30; + assert_eq!(x, 30); + + (|A { x: mut t }: A| { t = t+1; t })(A { x: 34 }); + +} diff --git a/tests/ui/binding/nested-matchs.rs b/tests/ui/binding/nested-matchs.rs new file mode 100644 index 000000000..29490fd48 --- /dev/null +++ b/tests/ui/binding/nested-matchs.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_mut)] // under NLL we get warning about `bar` below +fn baz() -> ! { panic!(); } + +fn foo() { + match Some::<isize>(5) { + Some::<isize>(_x) => { + let mut bar; + match None::<isize> { None::<isize> => { bar = 5; } _ => { baz(); } } + println!("{}", bar); + } + None::<isize> => { println!("hello"); } + } +} + +pub fn main() { foo(); } diff --git a/tests/ui/binding/nested-pattern.rs b/tests/ui/binding/nested-pattern.rs new file mode 100644 index 000000000..7d14c9ad9 --- /dev/null +++ b/tests/ui/binding/nested-pattern.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// a bug was causing this to complain about leaked memory on exit + +enum t { foo(isize, usize), bar(isize, Option<isize>), } + +fn nested(o: t) { + match o { + t::bar(_i, Some::<isize>(_)) => { println!("wrong pattern matched"); panic!(); } + _ => { println!("succeeded"); } + } +} + +pub fn main() { nested(t::bar(1, None::<isize>)); } diff --git a/tests/ui/binding/nil-pattern.rs b/tests/ui/binding/nil-pattern.rs new file mode 100644 index 000000000..268af351d --- /dev/null +++ b/tests/ui/binding/nil-pattern.rs @@ -0,0 +1,4 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub fn main() { let x = (); match x { () => { } } } diff --git a/tests/ui/binding/nullary-or-pattern.rs b/tests/ui/binding/nullary-or-pattern.rs new file mode 100644 index 000000000..7a3d9d60e --- /dev/null +++ b/tests/ui/binding/nullary-or-pattern.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum blah { a, b, } + +fn or_alt(q: blah) -> isize { + match q { blah::a | blah::b => { 42 } } +} + +pub fn main() { + assert_eq!(or_alt(blah::a), 42); + assert_eq!(or_alt(blah::b), 42); +} diff --git a/tests/ui/binding/optional_comma_in_match_arm.rs b/tests/ui/binding/optional_comma_in_match_arm.rs new file mode 100644 index 000000000..fc268bf2a --- /dev/null +++ b/tests/ui/binding/optional_comma_in_match_arm.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(unused_unsafe)] +// ignore-pretty issue #37199 +#![allow(while_true)] + +fn main() { + let x = 1; + + match x { + 1 => loop { break; }, + 2 => while true { break; }, + 3 => if true { () }, + 4 => if true { () } else { () }, + 5 => match () { () => () }, + 6 => { () }, + 7 => unsafe { () }, + _ => (), + } + + match x { + 1 => loop { break; } + 2 => while true { break; } + 3 => if true { () } + 4 => if true { () } else { () } + 5 => match () { () => () } + 6 => { () } + 7 => unsafe { () } + _ => () + } + + let r: &i32 = &x; + + match r { + // Absence of comma should not cause confusion between a pattern + // and a bitwise and. + &1 => if true { () } else { () } + &2 => (), + _ =>() + } +} diff --git a/tests/ui/binding/or-pattern.rs b/tests/ui/binding/or-pattern.rs new file mode 100644 index 000000000..47623a3d7 --- /dev/null +++ b/tests/ui/binding/or-pattern.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_camel_case_types)] + +enum blah { a(isize, isize, #[allow(unused_tuple_struct_fields)] usize), b(isize, isize), c, } + +fn or_alt(q: blah) -> isize { + match q { blah::a(x, y, _) | blah::b(x, y) => { return x + y; } blah::c => { return 0; } } +} + +pub fn main() { + assert_eq!(or_alt(blah::c), 0); + assert_eq!(or_alt(blah::a(10, 100, 0)), 110); + assert_eq!(or_alt(blah::b(20, 200)), 220); +} diff --git a/tests/ui/binding/order-drop-with-match.rs b/tests/ui/binding/order-drop-with-match.rs new file mode 100644 index 000000000..f50632ede --- /dev/null +++ b/tests/ui/binding/order-drop-with-match.rs @@ -0,0 +1,57 @@ +// run-pass + +// Test to make sure the destructors run in the right order. +// Each destructor sets it's tag in the corresponding entry +// in ORDER matching up to when it ran. +// Correct order is: matched, inner, outer + + +static mut ORDER: [usize; 3] = [0, 0, 0]; +static mut INDEX: usize = 0; + +struct A; +impl Drop for A { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 1; + INDEX = INDEX + 1; + } + } +} + +struct B; +impl Drop for B { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 2; + INDEX = INDEX + 1; + } + } +} + +struct C; +impl Drop for C { + fn drop(&mut self) { + unsafe { + ORDER[INDEX] = 3; + INDEX = INDEX + 1; + } + } +} + +fn main() { + { + let matched = A; + let _outer = C; + { + match matched { + _s => {} + } + let _inner = B; + } + } + unsafe { + let expected: &[_] = &[1, 2, 3]; + assert_eq!(expected, ORDER); + } +} diff --git a/tests/ui/binding/pat-ranges.rs b/tests/ui/binding/pat-ranges.rs new file mode 100644 index 000000000..19b304578 --- /dev/null +++ b/tests/ui/binding/pat-ranges.rs @@ -0,0 +1,20 @@ +// run-pass +// Parsing of range patterns + +#![allow(ellipsis_inclusive_range_patterns)] + +const NUM1: i32 = 10; + +mod m { + pub const NUM2: i32 = 16; +} + +fn main() { + if let NUM1 ... m::NUM2 = 10 {} else { panic!() } + if let ::NUM1 ... ::m::NUM2 = 11 {} else { panic!() } + if let -13 ... -10 = 12 { panic!() } else {} + + if let NUM1 ..= m::NUM2 = 10 {} else { panic!() } + if let ::NUM1 ..= ::m::NUM2 = 11 {} else { panic!() } + if let -13 ..= -10 = 12 { panic!() } else {} +} diff --git a/tests/ui/binding/pat-tuple-1.rs b/tests/ui/binding/pat-tuple-1.rs new file mode 100644 index 000000000..b09d4a22d --- /dev/null +++ b/tests/ui/binding/pat-tuple-1.rs @@ -0,0 +1,93 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + match x { + (a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + (.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + (a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + (.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(a, b, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + } + } + match x { + S(.., b, c) => { + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, .., c) => { + assert_eq!(a, 1); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(a, b, c, ..) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } + match x { + S(.., a, b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-2.rs b/tests/ui/binding/pat-tuple-2.rs new file mode 100644 index 000000000..810fd2641 --- /dev/null +++ b/tests/ui/binding/pat-tuple-2.rs @@ -0,0 +1,23 @@ +// run-pass +fn tuple() { + let x = (1,); + match x { + (2, ..) => panic!(), + (..) => () + } +} + +fn tuple_struct() { + struct S(u8); + + let x = S(1); + match x { + S(2, ..) => panic!(), + S(..) => () + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-3.rs b/tests/ui/binding/pat-tuple-3.rs new file mode 100644 index 000000000..9bec89861 --- /dev/null +++ b/tests/ui/binding/pat-tuple-3.rs @@ -0,0 +1,29 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + let branch = match x { + (1, 1, ..) => 0, + (1, 2, 3, ..) => 1, + (1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + let branch = match x { + S(1, 1, ..) => 0, + S(1, 2, 3, ..) => 1, + S(1, 2, ..) => 2, + _ => 3 + }; + assert_eq!(branch, 1); +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-4.rs b/tests/ui/binding/pat-tuple-4.rs new file mode 100644 index 000000000..71a548502 --- /dev/null +++ b/tests/ui/binding/pat-tuple-4.rs @@ -0,0 +1,57 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3); + match x { + (1, 2, 4) => unreachable!(), + (0, 2, 3, ..) => unreachable!(), + (0, .., 3) => unreachable!(), + (0, ..) => unreachable!(), + (1, 2, 3) => (), + (_, _, _) => unreachable!(), + } + match x { + (..) => (), + } + match x { + (_, _, _, ..) => (), + } + match x { + (a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8); + + let x = S(1, 2, 3); + match x { + S(1, 2, 4) => unreachable!(), + S(0, 2, 3, ..) => unreachable!(), + S(0, .., 3) => unreachable!(), + S(0, ..) => unreachable!(), + S(1, 2, 3) => (), + S(_, _, _) => unreachable!(), + } + match x { + S(..) => (), + } + match x { + S(_, _, _, ..) => (), + } + match x { + S(a, b, c) => { + assert_eq!(1, a); + assert_eq!(2, b); + assert_eq!(3, c); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-5.rs b/tests/ui/binding/pat-tuple-5.rs new file mode 100644 index 000000000..c8cdd37dd --- /dev/null +++ b/tests/ui/binding/pat-tuple-5.rs @@ -0,0 +1,29 @@ +// run-pass +fn tuple() { + struct S; + struct Z; + struct W; + let x = (S, Z, W); + match x { (S, ..) => {} } + match x { (.., W) => {} } + match x { (S, .., W) => {} } + match x { (.., Z, _) => {} } +} + +fn tuple_struct() { + struct SS(S, Z, W); + + struct S; + struct Z; + struct W; + let x = SS(S, Z, W); + match x { SS(S, ..) => {} } + match x { SS(.., W) => {} } + match x { SS(S, .., W) => {} } + match x { SS(.., Z, _) => {} } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-6.rs b/tests/ui/binding/pat-tuple-6.rs new file mode 100644 index 000000000..877f0e414 --- /dev/null +++ b/tests/ui/binding/pat-tuple-6.rs @@ -0,0 +1,45 @@ +// run-pass +fn tuple() { + let x = (1, 2, 3, 4, 5); + match x { + (a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + (a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn tuple_struct() { + struct S(u8, u8, u8, u8, u8); + + let x = S(1, 2, 3, 4, 5); + match x { + S(a, .., b, c) => { + assert_eq!(a, 1); + assert_eq!(b, 4); + assert_eq!(c, 5); + } + } + match x { + S(a, b, c, .., d) => { + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); + assert_eq!(d, 5); + } + } +} + +fn main() { + tuple(); + tuple_struct(); +} diff --git a/tests/ui/binding/pat-tuple-7.rs b/tests/ui/binding/pat-tuple-7.rs new file mode 100644 index 000000000..7835e2c35 --- /dev/null +++ b/tests/ui/binding/pat-tuple-7.rs @@ -0,0 +1,8 @@ +// run-pass + +fn main() { + #[allow(unused_parens)] + match 0 { + (pat) => assert_eq!(pat, 0) + } +} diff --git a/tests/ui/binding/pattern-bound-var-in-for-each.rs b/tests/ui/binding/pattern-bound-var-in-for-each.rs new file mode 100644 index 000000000..3f725cddc --- /dev/null +++ b/tests/ui/binding/pattern-bound-var-in-for-each.rs @@ -0,0 +1,20 @@ +// run-pass +// Tests that codegen_path checks whether a +// pattern-bound var is an upvar (when codegenning +// the for-each body) + + +fn foo(src: usize) { + + match Some(src) { + Some(src_id) => { + for _i in 0_usize..10_usize { + let yyy = src_id; + assert_eq!(yyy, 0_usize); + } + } + _ => { } + } +} + +pub fn main() { foo(0_usize); } diff --git a/tests/ui/binding/pattern-in-closure.rs b/tests/ui/binding/pattern-in-closure.rs new file mode 100644 index 000000000..3ac8d5768 --- /dev/null +++ b/tests/ui/binding/pattern-in-closure.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(non_shorthand_field_patterns)] + +struct Foo { + x: isize, + y: isize +} + +pub fn main() { + let f = |(x, _): (isize, isize)| println!("{}", x + 1); + let g = |Foo { x: x, y: _y }: Foo| println!("{}", x + 1); + f((2, 3)); + g(Foo { x: 1, y: 2 }); +} diff --git a/tests/ui/binding/range-inclusive-pattern-precedence.rs b/tests/ui/binding/range-inclusive-pattern-precedence.rs new file mode 100644 index 000000000..858239bb1 --- /dev/null +++ b/tests/ui/binding/range-inclusive-pattern-precedence.rs @@ -0,0 +1,23 @@ +// run-pass +#![feature(box_patterns)] + +const VALUE: usize = 21; + +pub fn main() { + match &18 { + &(18..=18) => {} + _ => { unreachable!(); } + } + match &21 { + &(VALUE..=VALUE) => {} + _ => { unreachable!(); } + } + match Box::new(18) { + box (18..=18) => {} + _ => { unreachable!(); } + } + match Box::new(21) { + box (VALUE..=VALUE) => {} + _ => { unreachable!(); } + } +} diff --git a/tests/ui/binding/shadow.rs b/tests/ui/binding/shadow.rs new file mode 100644 index 000000000..2495c8f47 --- /dev/null +++ b/tests/ui/binding/shadow.rs @@ -0,0 +1,24 @@ +// run-pass + +#![allow(non_camel_case_types)] +#![allow(dead_code)] +fn foo(c: Vec<isize> ) { + let a: isize = 5; + let mut b: Vec<isize> = Vec::new(); + + + match t::none::<isize> { + t::some::<isize>(_) => { + for _i in &c { + println!("{}", a); + let a = 17; + b.push(a); + } + } + _ => { } + } +} + +enum t<T> { none, some(T), } + +pub fn main() { let x = 10; let x = x + 20; assert_eq!(x, 30); foo(Vec::new()); } diff --git a/tests/ui/binding/simple-generic-match.rs b/tests/ui/binding/simple-generic-match.rs new file mode 100644 index 000000000..2cf050d01 --- /dev/null +++ b/tests/ui/binding/simple-generic-match.rs @@ -0,0 +1,8 @@ +// run-pass +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 + +enum clam<T> { a(#[allow(unused_tuple_struct_fields)] T), } + +pub fn main() { let c = clam::a(2); match c { clam::a::<isize>(_) => { } } } diff --git a/tests/ui/binding/use-uninit-match.rs b/tests/ui/binding/use-uninit-match.rs new file mode 100644 index 000000000..9250dbf0c --- /dev/null +++ b/tests/ui/binding/use-uninit-match.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + + +fn foo<T>(o: myoption<T>) -> isize { + let mut x: isize = 5; + match o { + myoption::none::<T> => { } + myoption::some::<T>(_t) => { x += 1; } + } + return x; +} + +enum myoption<T> { none, some(T), } + +pub fn main() { println!("{}", 5); } diff --git a/tests/ui/binding/use-uninit-match2.rs b/tests/ui/binding/use-uninit-match2.rs new file mode 100644 index 000000000..910273062 --- /dev/null +++ b/tests/ui/binding/use-uninit-match2.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_mut)] +#![allow(non_camel_case_types)] + + +fn foo<T>(o: myoption<T>) -> isize { + let mut x: isize; + match o { + myoption::none::<T> => { panic!(); } + myoption::some::<T>(_t) => { x = 5; } + } + return x; +} + +enum myoption<T> { none, some(T), } + +pub fn main() { println!("{}", 5); } diff --git a/tests/ui/binding/zero_sized_subslice_match.rs b/tests/ui/binding/zero_sized_subslice_match.rs new file mode 100644 index 000000000..187c29836 --- /dev/null +++ b/tests/ui/binding/zero_sized_subslice_match.rs @@ -0,0 +1,11 @@ +// run-pass + +fn main() { + let x = [(), ()]; + + // The subslice used to go out of bounds for zero-sized array items, check that this doesn't + // happen anymore + match x { + [_, ref y @ ..] => assert_eq!(&x[1] as *const (), &y[0] as *const ()) + } +} |