about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-07-30 03:38:54 +0000
committerbors <bors@rust-lang.org>2019-07-30 03:38:54 +0000
commit4eeaaa722d6ac6d24de6e4d3faefb7c44e674b37 (patch)
treeed3ee28acaee8ae750947dd3a224d9d1801e713d /src/test
parent04b88a9eba8abbac87eddcb2998beea09589c2c9 (diff)
parent91c10f8839156b3c3001271be17995806fb74e06 (diff)
downloadrust-4eeaaa722d6ac6d24de6e4d3faefb7c44e674b37.tar.gz
rust-4eeaaa722d6ac6d24de6e4d3faefb7c44e674b37.zip
Auto merge of #63124 - Centril:rollup-onohtqt, r=Centril
Rollup of 12 pull requests

Successful merges:

 - #61965 (Remove mentions of removed `offset_to` method from `align_offset` docs)
 - #62928 (Syntax: Recover on `for ( $pat in $expr ) $block`)
 - #63000 (Impl Debug for Chars)
 - #63083 (Make generic parameters always use modern hygiene)
 - #63087 (Add very simple edition check to tidy.)
 - #63093 (Properly check the defining scope of existential types)
 - #63096 (Add tests for some `existential_type` ICEs)
 - #63099 (vxworks: Remove Linux-specific comments.)
 - #63106 (ci: Skip installing SWIG/xz on OSX )
 - #63108 (Add links to None in Option doc)
 - #63109 (std: Fix a failing `fs` test on Windows)
 - #63111 (Add syntactic and semantic tests for rest patterns, i.e. `..`)

Failed merges:

r? @ghost
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-make/thumb-none-qemu/example/Cargo.toml2
-rw-r--r--src/test/run-make/thumb-none-qemu/example/src/main.rs16
-rw-r--r--src/test/ui/existential-type/issue-52843-closure-constrain.rs12
-rw-r--r--src/test/ui/existential-type/issue-52843-closure-constrain.stderr20
-rw-r--r--src/test/ui/existential_types/existential_type-pass.rs (renamed from src/test/ui/existential_type.rs)0
-rw-r--r--src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs19
-rw-r--r--src/test/ui/existential_types/issue-58887.rs (renamed from src/test/ui/existential-type/issue-58887.rs)0
-rw-r--r--src/test/ui/existential_types/issue-58887.stderr (renamed from src/test/ui/existential-type/issue-58887.stderr)0
-rw-r--r--src/test/ui/existential_types/issue-60371.rs (renamed from src/test/ui/existential-type/issue-60371.rs)0
-rw-r--r--src/test/ui/existential_types/issue-60371.stderr (renamed from src/test/ui/existential-type/issue-60371.stderr)0
-rw-r--r--src/test/ui/existential_types/issue-60407.rs15
-rw-r--r--src/test/ui/existential_types/issue-60564.rs26
-rw-r--r--src/test/ui/existential_types/issue-60564.stderr25
-rw-r--r--src/test/ui/hygiene/duplicate_lifetimes.rs19
-rw-r--r--src/test/ui/hygiene/duplicate_lifetimes.stderr27
-rw-r--r--src/test/ui/hygiene/generic_params.rs104
-rw-r--r--src/test/ui/hygiene/generic_params.stderr6
-rw-r--r--src/test/ui/hygiene/issue-61574-const-parameters.rs32
-rw-r--r--src/test/ui/hygiene/issue-61574-const-parameters.stderr6
-rw-r--r--src/test/ui/hygiene/ty_params.rs14
-rw-r--r--src/test/ui/parser/recover-for-loop-parens-around-head.rs15
-rw-r--r--src/test/ui/parser/recover-for-loop-parens-around-head.stderr27
-rw-r--r--src/test/ui/pattern/rest-pat-semantic-disallowed.rs82
-rw-r--r--src/test/ui/pattern/rest-pat-semantic-disallowed.stderr188
-rw-r--r--src/test/ui/pattern/rest-pat-syntactic.rs70
25 files changed, 701 insertions, 24 deletions
diff --git a/src/test/run-make/thumb-none-qemu/example/Cargo.toml b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
index 499553304c6..73fdee71f0c 100644
--- a/src/test/run-make/thumb-none-qemu/example/Cargo.toml
+++ b/src/test/run-make/thumb-none-qemu/example/Cargo.toml
@@ -2,7 +2,7 @@
 name = "example"
 version = "0.1.0"
 authors = ["Hideki Sekine <sekineh@me.com>"]
-# edition = "2018"
+edition = "2018"
 
 [dependencies]
 cortex-m = "0.5.4"
diff --git a/src/test/run-make/thumb-none-qemu/example/src/main.rs b/src/test/run-make/thumb-none-qemu/example/src/main.rs
index d88a327ef08..4a08419a07e 100644
--- a/src/test/run-make/thumb-none-qemu/example/src/main.rs
+++ b/src/test/run-make/thumb-none-qemu/example/src/main.rs
@@ -1,16 +1,14 @@
 // #![feature(stdsimd)]
 #![no_main]
 #![no_std]
-
-extern crate cortex_m;
-
-extern crate cortex_m_rt as rt;
-extern crate cortex_m_semihosting as semihosting;
-extern crate panic_halt;
-
 use core::fmt::Write;
 use cortex_m::asm;
-use rt::entry;
+use cortex_m_rt::entry;
+use cortex_m_semihosting as semihosting;
+
+//FIXME: This imports the provided #[panic_handler].
+#[allow(rust_2018_idioms)]
+extern crate panic_halt;
 
 entry!(main);
 
@@ -22,7 +20,7 @@ fn main() -> ! {
 
         // write something through semihosting interface
         let mut hstdout = semihosting::hio::hstdout().unwrap();
-        write!(hstdout, "x = {}\n", x);
+        let _ = write!(hstdout, "x = {}\n", x);
 
         // exit from qemu
         semihosting::debug::exit(semihosting::debug::EXIT_SUCCESS);
diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.rs b/src/test/ui/existential-type/issue-52843-closure-constrain.rs
new file mode 100644
index 00000000000..b2bbc1f1549
--- /dev/null
+++ b/src/test/ui/existential-type/issue-52843-closure-constrain.rs
@@ -0,0 +1,12 @@
+// Checks to ensure that we properly detect when a closure constrains an existential type
+#![feature(existential_type)]
+
+use std::fmt::Debug;
+
+fn main() {
+    existential type Existential: Debug;
+    fn _unused() -> Existential { String::new() }
+    //~^ ERROR: concrete type differs from previous defining existential type use
+    let null = || -> Existential { 0 };
+    println!("{:?}", null());
+}
diff --git a/src/test/ui/existential-type/issue-52843-closure-constrain.stderr b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr
new file mode 100644
index 00000000000..424d65a193c
--- /dev/null
+++ b/src/test/ui/existential-type/issue-52843-closure-constrain.stderr
@@ -0,0 +1,20 @@
+error: concrete type differs from previous defining existential type use
+  --> $DIR/issue-52843-closure-constrain.rs:8:5
+   |
+LL |     fn _unused() -> Existential { String::new() }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String`
+   |
+note: previous use here
+  --> $DIR/issue-52843-closure-constrain.rs:6:1
+   |
+LL | / fn main() {
+LL | |     existential type Existential: Debug;
+LL | |     fn _unused() -> Existential { String::new() }
+LL | |
+LL | |     let null = || -> Existential { 0 };
+LL | |     println!("{:?}", null());
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/existential_type.rs b/src/test/ui/existential_types/existential_type-pass.rs
index c2cf0eeed3d..c2cf0eeed3d 100644
--- a/src/test/ui/existential_type.rs
+++ b/src/test/ui/existential_types/existential_type-pass.rs
diff --git a/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs
new file mode 100644
index 00000000000..d964f2b74ff
--- /dev/null
+++ b/src/test/ui/existential_types/issue-53678-generator-and-const-fn.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(const_fn, generators, generator_trait, existential_type)]
+
+use std::ops::Generator;
+
+existential type GenOnce<Y, R>: Generator<Yield = Y, Return = R>;
+
+const fn const_generator<Y, R>(yielding: Y, returning: R) -> GenOnce<Y, R> {
+    move || {
+        yield yielding;
+
+        return returning;
+    }
+}
+
+const FOO: GenOnce<usize, usize> = const_generator(10, 100);
+
+fn main() {}
diff --git a/src/test/ui/existential-type/issue-58887.rs b/src/test/ui/existential_types/issue-58887.rs
index f038648ec21..f038648ec21 100644
--- a/src/test/ui/existential-type/issue-58887.rs
+++ b/src/test/ui/existential_types/issue-58887.rs
diff --git a/src/test/ui/existential-type/issue-58887.stderr b/src/test/ui/existential_types/issue-58887.stderr
index 800f4b7e059..800f4b7e059 100644
--- a/src/test/ui/existential-type/issue-58887.stderr
+++ b/src/test/ui/existential_types/issue-58887.stderr
diff --git a/src/test/ui/existential-type/issue-60371.rs b/src/test/ui/existential_types/issue-60371.rs
index f9def11d193..f9def11d193 100644
--- a/src/test/ui/existential-type/issue-60371.rs
+++ b/src/test/ui/existential_types/issue-60371.rs
diff --git a/src/test/ui/existential-type/issue-60371.stderr b/src/test/ui/existential_types/issue-60371.stderr
index 092cb31f97d..092cb31f97d 100644
--- a/src/test/ui/existential-type/issue-60371.stderr
+++ b/src/test/ui/existential_types/issue-60371.stderr
diff --git a/src/test/ui/existential_types/issue-60407.rs b/src/test/ui/existential_types/issue-60407.rs
new file mode 100644
index 00000000000..52162c491b5
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60407.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(existential_type)]
+
+existential type Debuggable: core::fmt::Debug;
+
+static mut TEST: Option<Debuggable> = None;
+
+fn main() {
+    unsafe { TEST = Some(foo()) }
+}
+
+fn foo() -> Debuggable {
+    0u32
+}
diff --git a/src/test/ui/existential_types/issue-60564.rs b/src/test/ui/existential_types/issue-60564.rs
new file mode 100644
index 00000000000..cb3914ddd1d
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60564.rs
@@ -0,0 +1,26 @@
+#![feature(existential_type)]
+
+trait IterBits {
+    type BitsIter: Iterator<Item = u8>;
+    fn iter_bits(self, n: u8) -> Self::BitsIter;
+}
+
+existential type IterBitsIter<T, E, I>: std::iter::Iterator<Item = I>;
+//~^ ERROR could not find defining uses
+
+impl<T, E> IterBits for T
+where
+    T: std::ops::Shr<Output = T>
+        + std::ops::BitAnd<T, Output = T>
+        + std::convert::From<u8>
+        + std::convert::TryInto<u8, Error = E>,
+    E: std::fmt::Debug,
+{
+    type BitsIter = IterBitsIter<T, E, u8>;
+    fn iter_bits(self, n: u8) -> Self::BitsIter {
+    //~^ ERROR type parameter `E` is part of concrete type but not used
+        (0u8..n)
+            .rev()
+            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+    }
+}
diff --git a/src/test/ui/existential_types/issue-60564.stderr b/src/test/ui/existential_types/issue-60564.stderr
new file mode 100644
index 00000000000..d8480b52157
--- /dev/null
+++ b/src/test/ui/existential_types/issue-60564.stderr
@@ -0,0 +1,25 @@
+error[E0601]: `main` function not found in crate `issue_60564`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-60564.rs`
+
+error: type parameter `E` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/issue-60564.rs:20:49
+   |
+LL |       fn iter_bits(self, n: u8) -> Self::BitsIter {
+   |  _________________________________________________^
+LL | |
+LL | |         (0u8..n)
+LL | |             .rev()
+LL | |             .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+LL | |     }
+   | |_____^
+
+error: could not find defining uses
+  --> $DIR/issue-60564.rs:8:1
+   |
+LL | existential type IterBitsIter<T, E, I>: std::iter::Iterator<Item = I>;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/hygiene/duplicate_lifetimes.rs b/src/test/ui/hygiene/duplicate_lifetimes.rs
new file mode 100644
index 00000000000..e7312b51dbc
--- /dev/null
+++ b/src/test/ui/hygiene/duplicate_lifetimes.rs
@@ -0,0 +1,19 @@
+// Ensure that lifetime parameter names are modernized before we check for
+// duplicates.
+
+#![feature(decl_macro, rustc_attrs)]
+
+#[rustc_macro_transparency = "semitransparent"]
+macro m($a:lifetime) {
+    fn g<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
+}
+
+#[rustc_macro_transparency = "transparent"]
+macro n($a:lifetime) {
+    fn h<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
+}
+
+m!('a);
+n!('a);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/duplicate_lifetimes.stderr b/src/test/ui/hygiene/duplicate_lifetimes.stderr
new file mode 100644
index 00000000000..7aaea6ff24e
--- /dev/null
+++ b/src/test/ui/hygiene/duplicate_lifetimes.stderr
@@ -0,0 +1,27 @@
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/duplicate_lifetimes.rs:8:14
+   |
+LL |     fn g<$a, 'a>() {}
+   |              ^^ declared twice
+...
+LL | m!('a);
+   | -------
+   | |  |
+   | |  previous declaration here
+   | in this macro invocation
+
+error[E0263]: lifetime name `'a` declared twice in the same scope
+  --> $DIR/duplicate_lifetimes.rs:13:14
+   |
+LL |     fn h<$a, 'a>() {}
+   |              ^^ declared twice
+...
+LL | n!('a);
+   | -------
+   | |  |
+   | |  previous declaration here
+   | in this macro invocation
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0263`.
diff --git a/src/test/ui/hygiene/generic_params.rs b/src/test/ui/hygiene/generic_params.rs
new file mode 100644
index 00000000000..9dc5adfce47
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.rs
@@ -0,0 +1,104 @@
+// Ensure that generic parameters always have modern hygiene.
+
+// check-pass
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro, rustc_attrs, const_generics)]
+
+mod type_params {
+    macro m($T:ident) {
+        fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
+            (t1.clone(), t2 == t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($T:ident) {
+        fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($T:ident) {
+        fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    m!(T);
+    n!(T);
+    p!(T);
+}
+
+mod lifetime_params {
+    macro m($a:lifetime) {
+        fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($a:lifetime) {
+        fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($a:lifetime) {
+        fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    m!('a);
+    n!('a);
+    p!('a);
+}
+
+mod const_params {
+    macro m($C:ident) {
+        fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($C:ident) {
+        fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($C:ident) {
+        fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    m!(C);
+    n!(C);
+    p!(C);
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr
new file mode 100644
index 00000000000..ecd228a5db5
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/generic_params.rs:6:37
+   |
+LL | #![feature(decl_macro, rustc_attrs, const_generics)]
+   |                                     ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.rs b/src/test/ui/hygiene/issue-61574-const-parameters.rs
new file mode 100644
index 00000000000..dcfb42287d5
--- /dev/null
+++ b/src/test/ui/hygiene/issue-61574-const-parameters.rs
@@ -0,0 +1,32 @@
+// A more comprehensive test that const parameters have correctly implemented
+// hygiene
+
+// check-pass
+
+#![feature(const_generics)]
+
+use std::ops::Add;
+
+struct VectorLike<T, const SIZE: usize>([T; {SIZE}]);
+
+macro_rules! impl_operator_overload {
+    ($trait_ident:ident, $method_ident:ident) => {
+
+        impl<T, const SIZE: usize> $trait_ident for VectorLike<T, {SIZE}>
+        where
+            T: $trait_ident,
+        {
+            type Output = VectorLike<T, {SIZE}>;
+
+            fn $method_ident(self, _: VectorLike<T, {SIZE}>) -> VectorLike<T, {SIZE}> {
+                let _ = SIZE;
+                unimplemented!()
+            }
+        }
+
+    }
+}
+
+impl_operator_overload!(Add, add);
+
+fn main() {}
diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr
new file mode 100644
index 00000000000..302b5fde887
--- /dev/null
+++ b/src/test/ui/hygiene/issue-61574-const-parameters.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61574-const-parameters.rs:6:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/hygiene/ty_params.rs b/src/test/ui/hygiene/ty_params.rs
deleted file mode 100644
index b296bfe5988..00000000000
--- a/src/test/ui/hygiene/ty_params.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// ignore-pretty pretty-printing is unhygienic
-
-#![feature(decl_macro)]
-
-macro m($T:ident) {
-    fn f<T, $T>(t: T, t2: $T) -> (T, $T) {
-        (t, t2)
-    }
-}
-
-m!(T);
-
-fn main() {}
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
new file mode 100644
index 00000000000..e6c59fcf22d
--- /dev/null
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs
@@ -0,0 +1,15 @@
+// Here we test that the parser is able to recover in a situation like
+// `for ( $pat in $expr )` since that is familiar syntax in other languages.
+// Instead we suggest that the user writes `for $pat in $expr`.
+
+#![deny(unused)] // Make sure we don't trigger `unused_parens`.
+
+fn main() {
+    let vec = vec![1, 2, 3];
+
+    for ( elem in vec ) {
+        //~^ ERROR expected one of `)`, `,`, or `@`, found `in`
+        //~| ERROR unexpected closing `)`
+        const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
new file mode 100644
index 00000000000..c160e646c28
--- /dev/null
+++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr
@@ -0,0 +1,27 @@
+error: expected one of `)`, `,`, or `@`, found `in`
+  --> $DIR/recover-for-loop-parens-around-head.rs:10:16
+   |
+LL |     for ( elem in vec ) {
+   |                ^^ expected one of `)`, `,`, or `@` here
+
+error: unexpected closing `)`
+  --> $DIR/recover-for-loop-parens-around-head.rs:10:23
+   |
+LL |     for ( elem in vec ) {
+   |         --------------^
+   |         |
+   |         opening `(`
+   |         help: remove parenthesis in `for` loop: `elem in vec`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-for-loop-parens-around-head.rs:13:38
+   |
+LL |         const RECOVERY_WITNESS: () = 0;
+   |                                      ^ expected (), found integer
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs
new file mode 100644
index 00000000000..36a45a3ccdc
--- /dev/null
+++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs
@@ -0,0 +1,82 @@
+// Here we test that rest patterns, i.e. `..`, are not allowed
+// outside of slice (+ ident patterns witin those), tuple,
+// and tuple struct patterns and that duplicates are caught in these contexts.
+
+#![feature(slice_patterns, box_patterns)]
+
+fn main() {}
+
+macro_rules! mk_pat {
+    () => { .. } //~ ERROR `..` patterns are not allowed here
+}
+
+fn rest_patterns() {
+    let mk_pat!();
+
+    // Top level:
+    fn foo(..: u8) {} //~ ERROR `..` patterns are not allowed here
+    let ..;  //~ ERROR `..` patterns are not allowed here
+
+    // Box patterns:
+    let box ..;  //~ ERROR `..` patterns are not allowed here
+
+    // In or-patterns:
+    match 1 {
+        1 | .. => {} //~ ERROR `..` patterns are not allowed here
+    }
+
+    // Ref patterns:
+    let &..; //~ ERROR `..` patterns are not allowed here
+    let &mut ..; //~ ERROR `..` patterns are not allowed here
+
+    // Ident patterns:
+    let x @ ..; //~ ERROR `..` patterns are not allowed here
+    let ref x @ ..; //~ ERROR `..` patterns are not allowed here
+    let ref mut x @ ..; //~ ERROR `..` patterns are not allowed here
+
+    // Tuple:
+    let (..): (u8,); // OK.
+    let (..,): (u8,); // OK.
+    let (
+        ..,
+        .., //~ ERROR `..` can only be used once per tuple pattern
+        .. //~ ERROR `..` can only be used once per tuple pattern
+    ): (u8, u8, u8);
+    let (
+        ..,
+        x,
+        .. //~ ERROR `..` can only be used once per tuple pattern
+    ): (u8, u8, u8);
+
+    struct A(u8, u8, u8);
+
+    // Tuple struct (same idea as for tuple patterns):
+    let A(..); // OK.
+    let A(..,); // OK.
+    let A(
+        ..,
+        .., //~ ERROR `..` can only be used once per tuple struct pattern
+        .. //~ ERROR `..` can only be used once per tuple struct pattern
+    );
+    let A(
+        ..,
+        x,
+        .. //~ ERROR `..` can only be used once per tuple struct pattern
+    );
+
+    // Array/Slice:
+    let [..]: &[u8]; // OK.
+    let [..,]: &[u8]; // OK.
+    let [
+        ..,
+        .., //~ ERROR `..` can only be used once per slice pattern
+        .. //~ ERROR `..` can only be used once per slice pattern
+    ]: &[u8];
+    let [
+        ..,
+        ref x @ .., //~ ERROR `..` can only be used once per slice pattern
+        ref mut y @ .., //~ ERROR `..` can only be used once per slice pattern
+        (ref z @ ..), //~ ERROR `..` patterns are not allowed here
+        .. //~ ERROR `..` can only be used once per slice pattern
+    ]: &[u8];
+}
diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
new file mode 100644
index 00000000000..826f76b356c
--- /dev/null
+++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
@@ -0,0 +1,188 @@
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:10:13
+   |
+LL |     () => { .. }
+   |             ^^
+...
+LL |     let mk_pat!();
+   |         --------- in this macro invocation
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:18:9
+   |
+LL |     let ..;
+   |         ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:21:13
+   |
+LL |     let box ..;
+   |             ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:25:13
+   |
+LL |         1 | .. => {}
+   |             ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:29:10
+   |
+LL |     let &..;
+   |          ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:30:14
+   |
+LL |     let &mut ..;
+   |              ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:33:13
+   |
+LL |     let x @ ..;
+   |             ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:34:17
+   |
+LL |     let ref x @ ..;
+   |                 ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:35:21
+   |
+LL |     let ref mut x @ ..;
+   |                     ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` can only be used once per tuple pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:42:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+   |         ^^ can only be used once per tuple pattern
+
+error: `..` can only be used once per tuple pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:43:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+LL |         ..
+   |         ^^ can only be used once per tuple pattern
+
+error: `..` can only be used once per tuple pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:48:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         x,
+LL |         ..
+   |         ^^ can only be used once per tuple pattern
+
+error: `..` can only be used once per tuple struct pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:58:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+   |         ^^ can only be used once per tuple struct pattern
+
+error: `..` can only be used once per tuple struct pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:59:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+LL |         ..
+   |         ^^ can only be used once per tuple struct pattern
+
+error: `..` can only be used once per tuple struct pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:64:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         x,
+LL |         ..
+   |         ^^ can only be used once per tuple struct pattern
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:72:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+   |         ^^ can only be used once per slice pattern
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:73:9
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ..,
+LL |         ..
+   |         ^^ can only be used once per slice pattern
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:77:17
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ref x @ ..,
+   |                 ^^ can only be used once per slice pattern
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:78:21
+   |
+LL |         ..,
+   |         -- previously used here
+LL |         ref x @ ..,
+LL |         ref mut y @ ..,
+   |                     ^^ can only be used once per slice pattern
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:79:18
+   |
+LL |         (ref z @ ..),
+   |                  ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/rest-pat-semantic-disallowed.rs:80:9
+   |
+LL |         ..,
+   |         -- previously used here
+...
+LL |         ..
+   |         ^^ can only be used once per slice pattern
+
+error: `..` patterns are not allowed here
+  --> $DIR/rest-pat-semantic-disallowed.rs:17:12
+   |
+LL |     fn foo(..: u8) {}
+   |            ^^
+   |
+   = note: only allowed in tuple, tuple struct, and slice patterns
+
+error: aborting due to 22 previous errors
+
diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs
new file mode 100644
index 00000000000..9656a0b5de9
--- /dev/null
+++ b/src/test/ui/pattern/rest-pat-syntactic.rs
@@ -0,0 +1,70 @@
+// Here we test that `..` is allowed in all pattern locations *syntactically*.
+// The semantic test is in `rest-pat-semantic-disallowed.rs`.
+
+// check-pass
+
+fn main() {}
+
+macro_rules! accept_pat {
+    ($p:pat) => {}
+}
+
+accept_pat!(..);
+
+#[cfg(FALSE)]
+fn rest_patterns() {
+    // Top level:
+    fn foo(..: u8) {}
+    let ..;
+
+    // Box patterns:
+    let box ..;
+
+    // In or-patterns:
+    match x {
+        .. | .. => {}
+    }
+
+    // Ref patterns:
+    let &..;
+    let &mut ..;
+
+    // Ident patterns:
+    let x @ ..;
+    let ref x @ ..;
+    let ref mut x @ ..;
+
+    // Tuple:
+    let (..); // This is interpreted as a tuple pattern, not a parenthesis one.
+    let (..,); // Allowing trailing comma.
+    let (.., .., ..); // Duplicates also.
+    let (.., P, ..); // Including with things in between.
+
+    // Tuple struct (same idea as for tuple patterns):
+    let A(..);
+    let A(..,);
+    let A(.., .., ..);
+    let A(.., P, ..);
+
+    // Array/Slice (like with tuple patterns):
+    let [..];
+    let [..,];
+    let [.., .., ..];
+    let [.., P, ..];
+
+    // Random walk to guard against special casing:
+    match x {
+        .. |
+        [
+            (
+                box ..,
+                &(..),
+                &mut ..,
+                x @ ..
+            ),
+            ref x @ ..,
+        ] |
+        ref mut x @ ..
+        => {}
+    }
+}