summaryrefslogtreecommitdiffstats
path: root/tests/ui/binding
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/binding')
-rw-r--r--tests/ui/binding/ambiguity-item.rs19
-rw-r--r--tests/ui/binding/ambiguity-item.stderr43
-rw-r--r--tests/ui/binding/bind-field-short-with-modifiers.rs26
-rw-r--r--tests/ui/binding/borrowed-ptr-pattern-2.rs13
-rw-r--r--tests/ui/binding/borrowed-ptr-pattern-3.rs13
-rw-r--r--tests/ui/binding/borrowed-ptr-pattern-infallible.rs8
-rw-r--r--tests/ui/binding/borrowed-ptr-pattern-option.rs15
-rw-r--r--tests/ui/binding/borrowed-ptr-pattern.rs12
-rw-r--r--tests/ui/binding/const-param.rs10
-rw-r--r--tests/ui/binding/const-param.stderr9
-rw-r--r--tests/ui/binding/empty-types-in-patterns.rs59
-rw-r--r--tests/ui/binding/exhaustive-bool-match-sanity.rs22
-rw-r--r--tests/ui/binding/expr-match-generic-unique1.rs18
-rw-r--r--tests/ui/binding/expr-match-generic-unique2.rs16
-rw-r--r--tests/ui/binding/expr-match-generic.rs29
-rw-r--r--tests/ui/binding/expr-match-panic-all.rs14
-rw-r--r--tests/ui/binding/expr-match-panic.rs14
-rw-r--r--tests/ui/binding/expr-match-unique.rs9
-rw-r--r--tests/ui/binding/expr-match.rs45
-rw-r--r--tests/ui/binding/fat-arrow-match.rs17
-rw-r--r--tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs69
-rw-r--r--tests/ui/binding/fn-pattern-expected-type-2.rs8
-rw-r--r--tests/ui/binding/fn-pattern-expected-type.rs9
-rw-r--r--tests/ui/binding/func-arg-incomplete-pattern.rs22
-rw-r--r--tests/ui/binding/func-arg-ref-pattern.rs26
-rw-r--r--tests/ui/binding/func-arg-wild-pattern.rs12
-rw-r--r--tests/ui/binding/if-let.rs60
-rw-r--r--tests/ui/binding/inconsistent-lifetime-mismatch.rs15
-rw-r--r--tests/ui/binding/inferred-suffix-in-pattern-range.rs24
-rw-r--r--tests/ui/binding/irrefutable-slice-patterns.rs14
-rw-r--r--tests/ui/binding/issue-53114-borrow-checks.rs84
-rw-r--r--tests/ui/binding/issue-53114-borrow-checks.stderr81
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.rs51
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.stderr156
-rw-r--r--tests/ui/binding/let-assignability.rs11
-rw-r--r--tests/ui/binding/let-destruct-ref.rs7
-rw-r--r--tests/ui/binding/let-var-hygiene.rs11
-rw-r--r--tests/ui/binding/match-arm-statics.rs165
-rw-r--r--tests/ui/binding/match-beginning-vert.rs19
-rw-r--r--tests/ui/binding/match-borrowed_str.rs48
-rw-r--r--tests/ui/binding/match-bot-2.rs6
-rw-r--r--tests/ui/binding/match-bot.rs7
-rw-r--r--tests/ui/binding/match-byte-array-patterns.rs44
-rw-r--r--tests/ui/binding/match-enum-struct-0.rs17
-rw-r--r--tests/ui/binding/match-enum-struct-1.rs19
-rw-r--r--tests/ui/binding/match-implicit-copy-unique.rs16
-rw-r--r--tests/ui/binding/match-in-macro.rs17
-rw-r--r--tests/ui/binding/match-join.rs20
-rw-r--r--tests/ui/binding/match-larger-const.rs12
-rw-r--r--tests/ui/binding/match-naked-record-expr.rs12
-rw-r--r--tests/ui/binding/match-naked-record.rs13
-rw-r--r--tests/ui/binding/match-path.rs14
-rw-r--r--tests/ui/binding/match-pattern-bindings.rs21
-rw-r--r--tests/ui/binding/match-pattern-lit.rs15
-rw-r--r--tests/ui/binding/match-pattern-no-type-params.rs14
-rw-r--r--tests/ui/binding/match-pattern-simple.rs9
-rw-r--r--tests/ui/binding/match-phi.rs19
-rw-r--r--tests/ui/binding/match-pipe-binding.rs60
-rw-r--r--tests/ui/binding/match-range-infer.rs17
-rw-r--r--tests/ui/binding/match-range-static.rs13
-rw-r--r--tests/ui/binding/match-range.rs51
-rw-r--r--tests/ui/binding/match-reassign.rs21
-rw-r--r--tests/ui/binding/match-ref-binding-in-guard-3256.rs13
-rw-r--r--tests/ui/binding/match-ref-binding-mut-option.rs10
-rw-r--r--tests/ui/binding/match-ref-binding-mut.rs18
-rw-r--r--tests/ui/binding/match-ref-binding.rs12
-rw-r--r--tests/ui/binding/match-ref-unsized.rs11
-rw-r--r--tests/ui/binding/match-str.rs25
-rw-r--r--tests/ui/binding/match-struct-0.rs21
-rw-r--r--tests/ui/binding/match-tag.rs30
-rw-r--r--tests/ui/binding/match-unique-bind.rs11
-rw-r--r--tests/ui/binding/match-unsized.rs9
-rw-r--r--tests/ui/binding/match-value-binding-in-guard-3291.rs17
-rw-r--r--tests/ui/binding/match-var-hygiene.rs11
-rw-r--r--tests/ui/binding/match-vec-alternatives.rs80
-rw-r--r--tests/ui/binding/match-vec-rvalue.rs15
-rw-r--r--tests/ui/binding/match-with-ret-arm.rs12
-rw-r--r--tests/ui/binding/multi-let.rs7
-rw-r--r--tests/ui/binding/mut-in-ident-patterns.rs76
-rw-r--r--tests/ui/binding/nested-matchs.rs16
-rw-r--r--tests/ui/binding/nested-pattern.rs16
-rw-r--r--tests/ui/binding/nil-pattern.rs4
-rw-r--r--tests/ui/binding/nullary-or-pattern.rs13
-rw-r--r--tests/ui/binding/optional_comma_in_match_arm.rs40
-rw-r--r--tests/ui/binding/or-pattern.rs14
-rw-r--r--tests/ui/binding/order-drop-with-match.rs57
-rw-r--r--tests/ui/binding/pat-ranges.rs20
-rw-r--r--tests/ui/binding/pat-tuple-1.rs93
-rw-r--r--tests/ui/binding/pat-tuple-2.rs23
-rw-r--r--tests/ui/binding/pat-tuple-3.rs29
-rw-r--r--tests/ui/binding/pat-tuple-4.rs57
-rw-r--r--tests/ui/binding/pat-tuple-5.rs29
-rw-r--r--tests/ui/binding/pat-tuple-6.rs45
-rw-r--r--tests/ui/binding/pat-tuple-7.rs8
-rw-r--r--tests/ui/binding/pattern-bound-var-in-for-each.rs20
-rw-r--r--tests/ui/binding/pattern-in-closure.rs14
-rw-r--r--tests/ui/binding/range-inclusive-pattern-precedence.rs23
-rw-r--r--tests/ui/binding/shadow.rs24
-rw-r--r--tests/ui/binding/simple-generic-match.rs8
-rw-r--r--tests/ui/binding/use-uninit-match.rs17
-rw-r--r--tests/ui/binding/use-uninit-match2.rs18
-rw-r--r--tests/ui/binding/zero_sized_subslice_match.rs11
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 ())
+ }
+}