about summary refs log tree commit diff
path: root/tests/ui/rfcs/rfc-2005-default-binding-mode
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/rfcs/rfc-2005-default-binding-mode')
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs18
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs40
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs45
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs20
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs249
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs34
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs9
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs16
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs14
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs25
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs22
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs19
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs12
13 files changed, 523 insertions, 0 deletions
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs
new file mode 100644
index 00000000000..0d1cded36b6
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/box.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![allow(unreachable_patterns)]
+#![feature(box_patterns)]
+
+struct Foo{}
+
+pub fn main() {
+    let b = Box::new(Foo{});
+    let box f = &b;
+    let _: &Foo = f;
+
+    match &&&b {
+        box f => {
+            let _: &Foo = f;
+        },
+        _ => panic!(),
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs
new file mode 100644
index 00000000000..d5bca6a2474
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/constref.rs
@@ -0,0 +1,40 @@
+// run-pass
+const CONST_REF: &[u8; 3] = b"foo";
+
+trait Foo {
+    const CONST_REF_DEFAULT: &'static [u8; 3] = b"bar";
+    const CONST_REF: &'static [u8; 3];
+}
+
+impl Foo for i32 {
+    const CONST_REF: &'static [u8; 3] = b"jjj";
+}
+
+impl Foo for i64 {
+    const CONST_REF_DEFAULT: &'static [u8; 3] = b"ggg";
+    const CONST_REF: &'static [u8; 3] = b"fff";
+}
+
+// Check that (associated and free) const references are not mistaken for a
+// non-reference pattern (in which case they would be auto-dereferenced, making
+// the types mismatched).
+
+fn const_ref() -> bool {
+    let f = b"foo";
+    match f {
+        CONST_REF => true,
+        _ => false,
+    }
+}
+
+fn associated_const_ref() -> bool {
+    match (b"bar", b"jjj", b"ggg", b"fff") {
+        (i32::CONST_REF_DEFAULT, i32::CONST_REF, i64::CONST_REF_DEFAULT, i64::CONST_REF) => true,
+        _ => false,
+    }
+}
+
+pub fn main() {
+    assert!(const_ref());
+    assert!(associated_const_ref());
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
new file mode 100644
index 00000000000..52fbb90ed54
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/enum.rs
@@ -0,0 +1,45 @@
+// run-pass
+enum Wrapper {
+    Wrap(i32),
+}
+
+use Wrapper::Wrap;
+
+pub fn main() {
+    let Wrap(x) = &Wrap(3);
+    println!("{}", *x);
+
+    let Wrap(x) = &mut Wrap(3);
+    println!("{}", *x);
+
+    if let Some(x) = &Some(3) {
+        println!("{}", *x);
+    } else {
+        panic!();
+    }
+
+    if let Some(x) = &mut Some(3) {
+        println!("{}", *x);
+    } else {
+        panic!();
+    }
+
+    if let Some(x) = &mut Some(3) {
+        *x += 1;
+    } else {
+        panic!();
+    }
+
+    while let Some(x) = &Some(3) {
+        println!("{}", *x);
+        break;
+    }
+    while let Some(x) = &mut Some(3) {
+        println!("{}", *x);
+        break;
+    }
+    while let Some(x) = &mut Some(3) {
+        *x += 1;
+        break;
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
new file mode 100644
index 00000000000..a5a24a80634
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs
@@ -0,0 +1,20 @@
+// run-pass
+pub fn main() {
+    let mut tups = vec![(0u8, 1u8)];
+
+    for (n, m) in &tups {
+        let _: &u8 = n;
+        let _: &u8 = m;
+    }
+
+    for (n, m) in &mut tups {
+        *n += 1;
+        *m += 2;
+    }
+
+    assert_eq!(tups, vec![(1u8, 3u8)]);
+
+    for (n, m) in tups {
+        println!("{} {}", m, n);
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs
new file mode 100644
index 00000000000..0207f607be8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs
@@ -0,0 +1,249 @@
+// run-pass
+#![allow(unused_variables)]
+fn some_or_wildcard(r: &Option<i32>, b: &i32) {
+    let _: &i32 = match r {
+        Some(a) => a,
+        _ => b,
+    };
+}
+
+fn none_or_wildcard(r: &Option<i32>, b: &i32) {
+    let _: &i32 = match r {
+        None => b,
+        _ => b,
+    };
+}
+
+fn some_or_ref_none(r: &Option<i32>, b: &i32) {
+    let _: &i32 = match r {
+        Some(a) => a,
+        &None => b,
+    };
+}
+
+fn ref_some_or_none(r: &Option<i32>, b: &i32) {
+    let _: &i32 = match r {
+        &Some(ref a) => a,
+        None => b,
+    };
+}
+
+fn some_or_self(r: &Option<i32>) {
+    let _: &Option<i32> = match r {
+        Some(n) => {
+            let _: &i32 = n;
+            r
+        },
+        x => x,
+    };
+}
+
+fn multiple_deref(r: &&&&&Option<i32>) {
+    let _: i32 = match r {
+        Some(a) => *a,
+        None => 5,
+    };
+}
+
+fn match_with_or() {
+    // FIXME(tschottdorf): #44912.
+    //
+    // let x = &Some((3, 3));
+    // let _: &i32 = match x {
+    //     Some((x, 3)) | &Some((ref x, 5)) => x,
+    //     _ => &5i32,
+    // };
+}
+
+fn nested_mixed() {
+    match (&Some(5), &Some(6)) {
+        (Some(a), &Some(mut b)) => {
+            // Here, the `a` will be `&i32`, because in the first half of the tuple
+            // we hit a non-reference pattern and shift into `ref` mode.
+            //
+            // In the second half of the tuple there's no non-reference pattern,
+            // so `b` will be `i32` (bound with `move` mode). Moreover, `b` is
+            // mutable.
+            let _: &i32 = a;
+            b = 7;
+            let _: i32 = b;
+        },
+        _ => {},
+    };
+}
+
+fn nested_mixed_multiple_deref_1() {
+    let x = (1, &Some(5));
+    let y = &Some(x);
+    match y {
+        Some((a, Some(b))) => {
+            let _: &i32 = a;
+            let _: &i32 = b;
+        },
+        _ => {},
+    };
+}
+
+fn nested_mixed_multiple_deref_2() {
+    let x = &Some(5);
+    let y = &x;
+    match y {
+        Some(z) => {
+            let _: &i32 = z;
+        },
+        _ => {},
+    }
+}
+
+fn new_mutable_reference() {
+    let mut x = &mut Some(5);
+    match &mut x {
+        Some(y) => {
+            *y = 5;
+        },
+        None => { },
+    }
+
+    match &mut x {
+        Some(y) => {
+            println!("{}", *y);
+        },
+        None => {},
+    }
+}
+
+fn let_implicit_ref_binding() {
+    struct Foo(i32);
+
+    // Note that these rules apply to any pattern matching
+    // whether it be in a `match` or a `let`.
+    // For example, `x` here is a `ref` binding:
+    let Foo(x) = &Foo(3);
+    let _: &i32 = x;
+}
+
+fn explicit_mut_binding() {
+    match &Some(5i32) {
+        Some(mut n) => {
+            n += 1;
+            let _ = n;
+        }
+        None => {},
+    };
+
+    match &mut Some(5i32) {
+        Some(n) => {
+            *n += 1;
+            let _ = n;
+        }
+        None => {},
+    };
+
+    match &mut &mut Some(5i32) {
+        Some(n) => {
+             let _: &mut i32 = n;
+        }
+        None => {},
+    };
+}
+
+fn tuple_mut_and_mut_mut() {
+    match (Some(5i32), &Some(5i32)) {
+        (Some(n), Some(m)) => {
+            // `n` and `m` are bound as immutable references. Make new references from them to
+            // assert that.
+            let r = n;
+            let _ = r;
+            let q = m;
+            let _ = q;
+
+            // Assert the types. Note that we use `n` and `m` here which would fail had they been
+            // moved due to the assignments above.
+            let _: i32 = n;
+            let _: &i32 = m;
+        }
+        (_, _) => {},
+    };
+
+    match (&Some(5i32), &&Some(5i32)) {
+        (Some(n), Some(m)) => {
+            let _: &i32 = n;
+            let _: &i32 = m;
+        }
+        (_, _) => {},
+    };
+
+    match &mut &mut (Some(5i32), Some(5i32)) {
+        (Some(n), Some(m)) => {
+            // Dereferenced through &mut &mut, so a mutable binding results.
+            let _: &mut i32 = n;
+            let _: &mut i32 = m;
+        }
+        (_, _) => {},
+    };
+
+    match (&mut Some(5i32), &mut &mut Some(5i32)) {
+        (Some(n), Some(m)) => {
+            let _: &mut i32 = n;
+            let _: &mut i32 = m;
+        }
+        (_, _) => {},
+    };
+}
+
+fn min_mir_embedded_type() {
+    // The reduced invocation that an ICE was diagnosed with (was consuming
+    // adjustments in wrong order).
+    match (0u8, &&Some(5i32)) {
+        (_, Some(m)) => {
+            let _: &i32 = m;
+        }
+        (_, _) => {},
+    };
+}
+
+fn no_autoderef() {
+    // Binding.
+    let x = &3;
+    println!("{}", *x);
+
+    // Wildcard.
+    let _ = &3;
+
+    // Constant of generic type (string)
+    const Y: &'static str = "foo";
+    assert_eq!(0, match "foo" {
+        Y => 0,
+        _ => 1,
+    });
+
+    // Reference pattern.
+    let &x = &3;
+}
+
+pub fn main() {
+    let r: &Option<i32> = &Some(3);
+    let b = &4i32;
+
+    none_or_wildcard(r, b);
+    some_or_wildcard(r, b);
+    some_or_ref_none(r, b);
+    ref_some_or_none(r, b);
+
+    some_or_self(r);
+    multiple_deref(&&&&r);
+    match_with_or();
+
+    nested_mixed();
+    nested_mixed_multiple_deref_1();
+    nested_mixed_multiple_deref_2();
+
+    new_mutable_reference();
+    explicit_mut_binding();
+    tuple_mut_and_mut_mut();
+    min_mir_embedded_type();
+
+    let_implicit_ref_binding();
+
+    no_autoderef();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
new file mode 100644
index 00000000000..9379753598e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.rs
@@ -0,0 +1,34 @@
+// run-pass
+#![allow(dead_code)]
+fn with_u8() {
+    let s = 5u8;
+    let r = match &s {
+        4 => false,
+        5 => true,
+        _ => false,
+    };
+    assert!(r);
+}
+
+// A string literal isn't mistaken for a non-ref pattern (in which case we'd
+// deref `s` and mess things up).
+fn with_str() {
+    let s: &'static str = "abc";
+    match s {
+            "abc" => true,
+            _ => panic!(),
+    };
+}
+
+// Ditto with byte strings.
+fn with_bytes() {
+    let s: &'static [u8] = b"abc";
+    match s {
+        b"abc" => true,
+        _ => panic!(),
+    };
+}
+
+pub fn main() {
+    with_str();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs
new file mode 100644
index 00000000000..f8abd1b96d8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/range.rs
@@ -0,0 +1,9 @@
+// run-pass
+pub fn main() {
+    let i = 5;
+    match &&&&i {
+        1 ..= 3 => panic!(),
+        4 ..= 8 => {},
+        _ => panic!(),
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs
new file mode 100644
index 00000000000..b74e45c9328
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/ref-region.rs
@@ -0,0 +1,16 @@
+// run-pass
+fn foo<'a, 'b>(x: &'a &'b Option<u32>) -> &'a u32 {
+    let x: &'a &'a Option<u32> = x;
+    match x {
+        Some(r) => {
+            let _: &u32 = r;
+            r
+        },
+        &None => panic!(),
+    }
+}
+
+pub fn main() {
+    let x = Some(5);
+    foo(&&x);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs
new file mode 100644
index 00000000000..3b9d07610d2
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/reset-mode.rs
@@ -0,0 +1,14 @@
+// run-pass
+// Test that we "reset" the mode as we pass through a `&` pattern.
+//
+// cc #46688
+
+fn surprise(x: i32) {
+    assert_eq!(x, 2);
+}
+
+fn main() {
+    let x = &(1, &2);
+    let (_, &b) = x;
+    surprise(b);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
new file mode 100644
index 00000000000..33229a205f4
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+fn slice_pat() {
+    let sl: &[u8] = b"foo";
+
+    match sl {
+        [first, remainder @ ..] => {
+            let _: &u8 = first;
+            assert_eq!(first, &b'f');
+            assert_eq!(remainder, b"oo");
+        }
+        [] => panic!(),
+    }
+}
+
+fn slice_pat_omission() {
+     match &[0, 1, 2] {
+        [..] => {}
+     };
+}
+
+fn main() {
+    slice_pat();
+    slice_pat_omission();
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs
new file mode 100644
index 00000000000..5a00e5b6823
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/struct.rs
@@ -0,0 +1,22 @@
+// run-pass
+#[derive(Debug, PartialEq)]
+struct Foo {
+    x: u8,
+}
+
+pub fn main() {
+    let mut foo = Foo {
+        x: 1,
+    };
+
+    match &mut foo {
+        Foo{x: n} => {
+            *n += 1;
+        },
+    };
+
+    assert_eq!(foo, Foo{x: 2});
+
+    let Foo{x: n} = &foo;
+    assert_eq!(*n, 2);
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs
new file mode 100644
index 00000000000..0cf9ba1b4ca
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple-struct.rs
@@ -0,0 +1,19 @@
+// run-pass
+#![allow(dead_code)]
+enum Foo {
+    Bar(Option<i8>, (), (), Vec<i32>),
+    Baz,
+}
+
+pub fn main() {
+    let foo = Foo::Bar(Some(1), (), (), vec![2, 3]);
+
+    match &foo {
+        Foo::Baz => panic!(),
+        Foo::Bar(None, ..) => panic!(),
+        Foo::Bar(Some(n), .., v) => {
+            assert_eq!((*v).len(), 2);
+            assert_eq!(*n, 1);
+        }
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs
new file mode 100644
index 00000000000..4c22aa2d718
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/tuple.rs
@@ -0,0 +1,12 @@
+// run-pass
+pub fn main() {
+    let foo = (Some(1), (), (), vec![2, 3]);
+
+    match &foo {
+        (Some(n), .., v) => {
+            assert_eq!((*v).len(), 2);
+            assert_eq!(*n, 1);
+        }
+        (None, (), (), ..) => panic!(),
+    }
+}