about summary refs log tree commit diff
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 00000000000..0f48340c2cd
--- /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 00000000000..f3620139642
--- /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 00000000000..b271f84e9ce
--- /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 00000000000..40df85b1479
--- /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 00000000000..f2607eee815
--- /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 00000000000..1bbc03e19ba
--- /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 00000000000..319b8631e8d
--- /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 00000000000..d5f94ab54e3
--- /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 00000000000..2d051808fe0
--- /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 00000000000..adda80810ea
--- /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 00000000000..0d0dbcaf40f
--- /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 00000000000..f83def21060
--- /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 00000000000..c5f38d81559
--- /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 00000000000..8977ca68efa
--- /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 00000000000..530fc676f7c
--- /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 00000000000..ac31b49a1e9
--- /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 00000000000..4b6b6e072c0
--- /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 00000000000..eec9e1f8b4a
--- /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 00000000000..575b38fbc95
--- /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 00000000000..aaf5be8cf74
--- /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 00000000000..0450fe8abbd
--- /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 00000000000..130ff3d4465
--- /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 00000000000..faeb7649636
--- /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 00000000000..eb94ee48f92
--- /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 00000000000..2d75c12140b
--- /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 00000000000..bcd82c679a5
--- /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 00000000000..28d57e92c37
--- /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 00000000000..87768c28cf4
--- /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 00000000000..079cc0a16db
--- /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 00000000000..048e1e5e9b4
--- /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 00000000000..7646472f45f
--- /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 00000000000..0ec2ae8839e
--- /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 00000000000..d0eb28c5714
--- /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 00000000000..57a065d6d4d
--- /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 00000000000..b85f4a96a6d
--- /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 00000000000..28d7294ebc8
--- /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 00000000000..571207bd7d6
--- /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 00000000000..e6d17def147
--- /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 00000000000..79267400b28
--- /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 00000000000..22782032ebf
--- /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 00000000000..95b3406f0b5
--- /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 00000000000..5c4472c7aea
--- /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 00000000000..f0c988c01c2
--- /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 00000000000..e2623ece84c
--- /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 00000000000..f035432ec99
--- /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 00000000000..74ffe2ecdb3
--- /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 00000000000..0840cc4404d
--- /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 00000000000..60f2a458489
--- /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 00000000000..6f9a353207f
--- /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 00000000000..c23ff8c9495
--- /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 00000000000..f7479152ebc
--- /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 00000000000..286214eb8ac
--- /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 00000000000..4ec533677d6
--- /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 00000000000..c9c6135e2e6
--- /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 00000000000..1fc7ddda023
--- /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 00000000000..3f56cd4796d
--- /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 00000000000..92a3f6e0f7f
--- /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 00000000000..7d4a7c708dd
--- /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 00000000000..19d1cb89d4a
--- /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 00000000000..f01a3505ee6
--- /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 00000000000..1dca84dfd45
--- /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 00000000000..19b48579cb4
--- /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 00000000000..9075a34d410
--- /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 00000000000..c25639b7213
--- /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 00000000000..d7afd61bc8e
--- /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 00000000000..ac6a07eabe1
--- /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 00000000000..53784ebb9fc
--- /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 00000000000..0ee18ea18de
--- /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 00000000000..c49f3ed6178
--- /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 00000000000..407716aa28a
--- /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 00000000000..507478983f6
--- /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 00000000000..41937a557ef
--- /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 00000000000..0d750da79e7
--- /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 00000000000..43740bbcf1d
--- /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 00000000000..af95eb95df0
--- /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 00000000000..fead2254c75
--- /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 00000000000..58a90964121
--- /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 00000000000..064d32a7084
--- /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 00000000000..1d1dd660e51
--- /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 00000000000..29490fd4888
--- /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 00000000000..7d14c9ad9b7
--- /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 00000000000..268af351d08
--- /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 00000000000..7a3d9d60eda
--- /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 00000000000..fc268bf2a45
--- /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 00000000000..47623a3d722
--- /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 00000000000..f50632ede9f
--- /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 00000000000..19b3045784f
--- /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 00000000000..b09d4a22df0
--- /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 00000000000..810fd264139
--- /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 00000000000..9bec898611e
--- /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 00000000000..71a54850268
--- /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 00000000000..c8cdd37dd85
--- /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 00000000000..877f0e4140e
--- /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 00000000000..7835e2c352f
--- /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 00000000000..3f725cddc5b
--- /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 00000000000..3ac8d57681a
--- /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 00000000000..858239bb177
--- /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 00000000000..2495c8f47e7
--- /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 00000000000..2cf050d011d
--- /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 00000000000..9250dbf0c43
--- /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 00000000000..9102730629b
--- /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 00000000000..187c2983633
--- /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 ())
+    }
+}