about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-05-02 21:37:18 -0700
committerbors <bors@rust-lang.org>2016-05-02 21:37:18 -0700
commit43c5fef47dcaebea4c77771cc6f187b2a72b3639 (patch)
tree4d740e1808a7d721e17781274bd8b07632b6b433
parent44b3cd8c462a420ab64a44ef8f70c007001a1f44 (diff)
parent638cf9f675174316ba5ecfaf2913c9d60da9772c (diff)
downloadrust-43c5fef47dcaebea4c77771cc6f187b2a72b3639.tar.gz
rust-43c5fef47dcaebea4c77771cc6f187b2a72b3639.zip
Auto merge of #33354 - Manishearth:rollup, r=Manishearth
Rollup of 14 pull requests

- Successful merges: #32756, #33129, #33225, #33260, #33309, #33320, #33323, #33324, #33325, #33330, #33332, #33334, #33335, #33346
- Failed merges:
-rw-r--r--src/libcore/intrinsics.rs7
-rw-r--r--src/libcore/mem.rs3
-rw-r--r--src/librustc/diagnostics.rs12
-rw-r--r--src/librustc_const_eval/check_match.rs23
-rw-r--r--src/librustc_incremental/persist/util.rs26
-rw-r--r--src/librustc_resolve/diagnostics.rs11
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/libstd/io/mod.rs4
-rw-r--r--src/libsyntax/parse/lexer/mod.rs9
-rw-r--r--src/libsyntax/print/pp.rs129
-rw-r--r--src/test/compile-fail/issue-29124.rs4
-rw-r--r--src/test/compile-fail/issue-31221.rs49
12 files changed, 167 insertions, 114 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 45890cd3d81..8a9f662bf83 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -192,11 +192,8 @@ extern "rust-intrinsic" {
 
     /// The size of a type in bytes.
     ///
-    /// This is the exact number of bytes in memory taken up by a
-    /// value of the given type. In other words, a memset of this size
-    /// would *exactly* overwrite a value. When laid out in vectors
-    /// and structures there may be additional padding between
-    /// elements.
+    /// More specifically, this is the offset in bytes between successive
+    /// items of the same type, including alignment padding.
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 2c648d1516b..56d268bf37c 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -117,6 +117,9 @@ pub fn forget<T>(t: T) {
 
 /// Returns the size of a type in bytes.
 ///
+/// More specifically, this is the offset in bytes between successive
+/// items of the same type, including alignment padding.
+///
 /// # Examples
 ///
 /// ```
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index efef259dcad..5ee8a79f621 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -635,7 +635,17 @@ fn foo(x: u8) -> u8 {
 ```
 
 It is advisable to find out what the unhandled cases are and check for them,
-returning an appropriate value or panicking if necessary.
+returning an appropriate value or panicking if necessary. Check if you need
+to remove a semicolon from the last expression, like in this case:
+
+```ignore
+fn foo(x: u8) -> u8 {
+    inner(2*x + 1);
+}
+```
+
+The semicolon discards the return value of `inner`, instead of returning
+it from `foo`.
 "##,
 
 E0270: r##"
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index ead6ab099a8..0207fa52d8d 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -341,7 +341,15 @@ fn check_arms(cx: &MatchCheckCtxt,
                         },
 
                         hir::MatchSource::Normal => {
-                            span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
+                            let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
+                                                           "unreachable pattern");
+                            // if we had a catchall pattern, hint at that
+                            for row in &seen.0 {
+                                if pat_is_catchall(&cx.tcx.def_map.borrow(), row[0]) {
+                                    span_note!(err, row[0].span, "this pattern matches any value");
+                                }
+                            }
+                            err.emit();
                         },
 
                         hir::MatchSource::TryDesugar => {
@@ -361,7 +369,18 @@ fn check_arms(cx: &MatchCheckCtxt,
     }
 }
 
-fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
+/// Checks for common cases of "catchall" patterns that may not be intended as such.
+fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool {
+    match p.node {
+        PatKind::Ident(_, _, None) => pat_is_binding(dm, p),
+        PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s),
+        PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s),
+        PatKind::Tup(ref v) => v.iter().all(|p| pat_is_catchall(dm, &p)),
+        _ => false
+    }
+}
+
+fn raw_pat(p: &Pat) -> &Pat {
     match p.node {
         PatKind::Ident(_, _, Some(ref s)) => raw_pat(&s),
         _ => p
diff --git a/src/librustc_incremental/persist/util.rs b/src/librustc_incremental/persist/util.rs
index 9b4e5997efe..5b4e88def01 100644
--- a/src/librustc_incremental/persist/util.rs
+++ b/src/librustc_incremental/persist/util.rs
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 use rustc::ty;
+
 use std::fs;
-use std::path::PathBuf;
+use std::io;
+use std::path::{PathBuf, Path};
 
 pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
     // For now, just save/load dep-graph from
     // directory/dep_graph.rbml
     tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| {
-        match fs::create_dir_all(&incr_dir){
+        match create_dir_racy(&incr_dir) {
             Ok(()) => {}
             Err(err) => {
                 tcx.sess.err(
@@ -30,3 +32,23 @@ pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
     })
 }
 
+// Like std::fs::create_dir_all, except handles concurrent calls among multiple
+// threads or processes.
+fn create_dir_racy(path: &Path) -> io::Result<()> {
+    match fs::create_dir(path) {
+        Ok(()) => return Ok(()),
+        Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()),
+        Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
+        Err(e) => return Err(e),
+    }
+    match path.parent() {
+        Some(p) => try!(create_dir_racy(p)),
+        None => return Err(io::Error::new(io::ErrorKind::Other,
+                                          "failed to create whole tree")),
+    }
+    match fs::create_dir(path) {
+        Ok(()) => Ok(()),
+        Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),
+        Err(e) => Err(e),
+    }
+}
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 0a8fce49ebb..56d3b927dc5 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -916,11 +916,14 @@ An import was unresolved. Erroneous code example:
 use something::Foo; // error: unresolved import `something::Foo`.
 ```
 
-Please verify you didn't misspell the import name or the import does exist
-in the module from where you tried to import it. Example:
+Paths in `use` statements are relative to the crate root. To import items
+relative to the current and parent modules, use the `self::` and `super::`
+prefixes, respectively. Also verify that you didn't misspell the import
+name and that the import exists in the module from where you tried to
+import it. Example:
 
 ```ignore
-use something::Foo; // ok!
+use self::something::Foo; // ok!
 
 mod something {
     pub struct Foo;
@@ -928,7 +931,7 @@ mod something {
 ```
 
 Or, if you tried to use a module from an external crate, you may have missed
-the `extern crate` declaration:
+the `extern crate` declaration (which is usually placed in the crate root):
 
 ```ignore
 extern crate homura; // Required to use the `homura` crate
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index b541ca151c8..4ba8f2c9d62 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -156,10 +156,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 if let Some(expr) = rcvr_expr {
                     if let Ok (expr_string) = cx.sess.codemap().span_to_snippet(expr.span) {
                         report_function!(expr.span, expr_string);
-                        err.span_suggestion(expr.span,
-                                            "try calling the base function:",
-                                            format!("{}()",
-                                                    expr_string));
                     }
                     else if let Expr_::ExprPath(_, path) = expr.node.clone() {
                         if let Some(segment) = path.segments.last() {
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index d914d143e70..ca15aa2d56c 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -195,7 +195,7 @@
 //!
 //! ## Functions
 //!
-//! There are a number of [functions][functions] that offer access to various
+//! There are a number of [functions][functions-list] that offer access to various
 //! features. For example, we can use three of these functions to copy everything
 //! from standard input to standard output:
 //!
@@ -208,7 +208,7 @@
 //! # }
 //! ```
 //!
-//! [functions]: #functions
+//! [functions-list]: #functions-1
 //!
 //! ## io::Result
 //!
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 881663a056c..da62e5286d4 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -931,11 +931,10 @@ impl<'a> StringReader<'a> {
             _ => {
                 if ascii_only && first_source_char > '\x7F' {
                     let last_pos = self.last_pos;
-                    self.err_span_char(start,
-                                       last_pos,
-                                       "byte constant must be ASCII. Use a \\xHH escape for a \
-                                        non-ASCII byte",
-                                       first_source_char);
+                    self.err_span_(start,
+                                   last_pos,
+                                   "byte constant must be ASCII. Use a \\xHH escape for a \
+                                    non-ASCII byte");
                     return false;
                 }
             }
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index c381a3a8437..4a92ad8ddb2 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -61,8 +61,9 @@
 //! line (which it can't) and so naturally place the content on its own line to
 //! avoid combining it with other lines and making matters even worse.
 
+use std::collections::VecDeque;
+use std::fmt;
 use std::io;
-use std::string;
 
 #[derive(Clone, Copy, PartialEq)]
 pub enum Breaks {
@@ -112,35 +113,30 @@ impl Token {
     }
 }
 
-pub fn tok_str(token: &Token) -> String {
-    match *token {
-        Token::String(ref s, len) => format!("STR({},{})", s, len),
-        Token::Break(_) => "BREAK".to_string(),
-        Token::Begin(_) => "BEGIN".to_string(),
-        Token::End => "END".to_string(),
-        Token::Eof => "EOF".to_string()
+impl fmt::Display for Token {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Token::String(ref s, len) => write!(f, "STR({},{})", s, len),
+            Token::Break(_) => f.write_str("BREAK"),
+            Token::Begin(_) => f.write_str("BEGIN"),
+            Token::End => f.write_str("END"),
+            Token::Eof => f.write_str("EOF"),
+        }
     }
 }
 
-pub fn buf_str(toks: &[Token],
-               szs: &[isize],
-               left: usize,
-               right: usize,
-               lim: usize)
-               -> String {
+fn buf_str(toks: &[Token], szs: &[isize], left: usize, right: usize, lim: usize) -> String {
     let n = toks.len();
     assert_eq!(n, szs.len());
     let mut i = left;
     let mut l = lim;
-    let mut s = string::String::from("[");
+    let mut s = String::from("[");
     while i != right && l != 0 {
         l -= 1;
         if i != left {
             s.push_str(", ");
         }
-        s.push_str(&format!("{}={}",
-                           szs[i],
-                           tok_str(&toks[i])));
+        s.push_str(&format!("{}={}", szs[i], &toks[i]));
         i += 1;
         i %= n;
     }
@@ -169,7 +165,7 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
     debug!("mk_printer {}", linewidth);
     let token = vec![Token::Eof; n];
     let size = vec![0; n];
-    let scan_stack = vec![0; n];
+    let scan_stack = VecDeque::with_capacity(n);
     Printer {
         out: out,
         buf_len: n,
@@ -182,9 +178,6 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
         left_total: 0,
         right_total: 0,
         scan_stack: scan_stack,
-        scan_stack_empty: true,
-        top: 0,
-        bottom: 0,
         print_stack: Vec::new(),
         pending_indentation: 0
     }
@@ -246,9 +239,8 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
 /// approximation for purposes of line breaking).
 ///
 /// The "input side" of the printer is managed as an abstract process called
-/// SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
-/// manage calculating 'size'. SCAN is, in other words, the process of
-/// calculating 'size' entries.
+/// SCAN, which uses 'scan_stack', to manage calculating 'size'. SCAN is, in
+/// other words, the process of calculating 'size' entries.
 ///
 /// The "output side" of the printer is managed by an abstract process called
 /// PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
@@ -291,13 +283,7 @@ pub struct Printer<'a> {
     /// Begin (if there is any) on top of it. Stuff is flushed off the
     /// bottom as it becomes irrelevant due to the primary ring-buffer
     /// advancing.
-    scan_stack: Vec<usize> ,
-    /// Top==bottom disambiguator
-    scan_stack_empty: bool,
-    /// Index of top of scan_stack
-    top: usize,
-    /// Index of bottom of scan_stack
-    bottom: usize,
+    scan_stack: VecDeque<usize> ,
     /// Stack of blocks-in-progress being flushed by print
     print_stack: Vec<PrintStackElem> ,
     /// Buffered indentation to avoid writing trailing whitespace
@@ -316,7 +302,7 @@ impl<'a> Printer<'a> {
         debug!("pp Vec<{},{}>", self.left, self.right);
         match token {
           Token::Eof => {
-            if !self.scan_stack_empty {
+            if !self.scan_stack.is_empty() {
                 self.check_stack(0);
                 self.advance_left()?;
             }
@@ -324,7 +310,7 @@ impl<'a> Printer<'a> {
             Ok(())
           }
           Token::Begin(b) => {
-            if self.scan_stack_empty {
+            if self.scan_stack.is_empty() {
                 self.left_total = 1;
                 self.right_total = 1;
                 self.left = 0;
@@ -339,7 +325,7 @@ impl<'a> Printer<'a> {
             Ok(())
           }
           Token::End => {
-            if self.scan_stack_empty {
+            if self.scan_stack.is_empty() {
                 debug!("pp End/print Vec<{},{}>", self.left, self.right);
                 self.print(token, 0)
             } else {
@@ -353,7 +339,7 @@ impl<'a> Printer<'a> {
             }
           }
           Token::Break(b) => {
-            if self.scan_stack_empty {
+            if self.scan_stack.is_empty() {
                 self.left_total = 1;
                 self.right_total = 1;
                 self.left = 0;
@@ -370,7 +356,7 @@ impl<'a> Printer<'a> {
             Ok(())
           }
           Token::String(s, len) => {
-            if self.scan_stack_empty {
+            if self.scan_stack.is_empty() {
                 debug!("pp String('{}')/print Vec<{},{}>",
                        s, self.left, self.right);
                 self.print(Token::String(s, len), len)
@@ -392,12 +378,10 @@ impl<'a> Printer<'a> {
         if self.right_total - self.left_total > self.space {
             debug!("scan window is {}, longer than space on line ({})",
                    self.right_total - self.left_total, self.space);
-            if !self.scan_stack_empty {
-                if self.left == self.scan_stack[self.bottom] {
-                    debug!("setting {} to infinity and popping", self.left);
-                    let scanned = self.scan_pop_bottom();
-                    self.size[scanned] = SIZE_INFINITY;
-                }
+            if Some(&self.left) == self.scan_stack.back() {
+                debug!("setting {} to infinity and popping", self.left);
+                let scanned = self.scan_pop_bottom();
+                self.size[scanned] = SIZE_INFINITY;
             }
             self.advance_left()?;
             if self.left != self.right {
@@ -408,43 +392,21 @@ impl<'a> Printer<'a> {
     }
     pub fn scan_push(&mut self, x: usize) {
         debug!("scan_push {}", x);
-        if self.scan_stack_empty {
-            self.scan_stack_empty = false;
-        } else {
-            self.top += 1;
-            self.top %= self.buf_len;
-            assert!((self.top != self.bottom));
-        }
-        self.scan_stack[self.top] = x;
+        self.scan_stack.push_front(x);
     }
     pub fn scan_pop(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        let x = self.scan_stack[self.top];
-        if self.top == self.bottom {
-            self.scan_stack_empty = true;
-        } else {
-            self.top += self.buf_len - 1; self.top %= self.buf_len;
-        }
-        return x;
+        self.scan_stack.pop_front().unwrap()
     }
     pub fn scan_top(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        return self.scan_stack[self.top];
+        *self.scan_stack.front().unwrap()
     }
     pub fn scan_pop_bottom(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        let x = self.scan_stack[self.bottom];
-        if self.top == self.bottom {
-            self.scan_stack_empty = true;
-        } else {
-            self.bottom += 1; self.bottom %= self.buf_len;
-        }
-        return x;
+        self.scan_stack.pop_back().unwrap()
     }
     pub fn advance_right(&mut self) {
         self.right += 1;
         self.right %= self.buf_len;
-        assert!((self.right != self.left));
+        assert!(self.right != self.left);
     }
     pub fn advance_left(&mut self) -> io::Result<()> {
         debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
@@ -481,7 +443,7 @@ impl<'a> Printer<'a> {
         Ok(())
     }
     pub fn check_stack(&mut self, k: isize) {
-        if !self.scan_stack_empty {
+        if !self.scan_stack.is_empty() {
             let x = self.scan_top();
             match self.token[x] {
                 Token::Begin(_) => {
@@ -512,19 +474,16 @@ impl<'a> Printer<'a> {
         let ret = write!(self.out, "\n");
         self.pending_indentation = 0;
         self.indent(amount);
-        return ret;
+        ret
     }
     pub fn indent(&mut self, amount: isize) {
         debug!("INDENT {}", amount);
         self.pending_indentation += amount;
     }
     pub fn get_top(&mut self) -> PrintStackElem {
-        let print_stack = &mut self.print_stack;
-        let n = print_stack.len();
-        if n != 0 {
-            (*print_stack)[n - 1]
-        } else {
-            PrintStackElem {
+        match self.print_stack.last() {
+            Some(el) => *el,
+            None => PrintStackElem {
                 offset: 0,
                 pbreak: PrintStackBreak::Broken(Breaks::Inconsistent)
             }
@@ -538,7 +497,7 @@ impl<'a> Printer<'a> {
         write!(self.out, "{}", s)
     }
     pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
-        debug!("print {} {} (remaining line space={})", tok_str(&token), l,
+        debug!("print {} {} (remaining line space={})", token, l,
                self.space);
         debug!("{}", buf_str(&self.token,
                              &self.size,
@@ -566,7 +525,7 @@ impl<'a> Printer<'a> {
           Token::End => {
             debug!("print End -> pop End");
             let print_stack = &mut self.print_stack;
-            assert!((!print_stack.is_empty()));
+            assert!(!print_stack.is_empty());
             print_stack.pop().unwrap();
             Ok(())
           }
@@ -603,12 +562,12 @@ impl<'a> Printer<'a> {
               }
             }
           }
-          Token::String(s, len) => {
+          Token::String(ref s, len) => {
             debug!("print String({})", s);
             assert_eq!(l, len);
             // assert!(l <= space);
             self.space -= len;
-            self.print_str(&s[..])
+            self.print_str(s)
           }
           Token::Eof => {
             // Eof should never get here.
@@ -652,15 +611,15 @@ pub fn eof(p: &mut Printer) -> io::Result<()> {
 }
 
 pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize))
+    p.pretty_print(Token::String(wrd.to_string(), wrd.len() as isize))
 }
 
 pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY))
+    p.pretty_print(Token::String(wrd.to_string(), SIZE_INFINITY))
 }
 
 pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0))
+    p.pretty_print(Token::String(wrd.to_string(), 0))
 }
 
 pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> {
diff --git a/src/test/compile-fail/issue-29124.rs b/src/test/compile-fail/issue-29124.rs
index b3dc043f502..a72dac0d5dd 100644
--- a/src/test/compile-fail/issue-29124.rs
+++ b/src/test/compile-fail/issue-29124.rs
@@ -25,11 +25,7 @@ fn main() {
     obj::func.x();
     //~^ ERROR no method named `x` found for type `fn() -> ret {obj::func}` in the current scope
     //~^^ NOTE obj::func is a function, perhaps you wish to call it
-    //~^^^ HELP try calling the base function:
-    //~| SUGGESTION obj::func().x();
     func.x();
     //~^ ERROR no method named `x` found for type `fn() -> ret {func}` in the current scope
     //~^^ NOTE func is a function, perhaps you wish to call it
-    //~^^^ HELP try calling the base function:
-    //~| SUGGESTION func().x();
 }
diff --git a/src/test/compile-fail/issue-31221.rs b/src/test/compile-fail/issue-31221.rs
new file mode 100644
index 00000000000..2b3df9ad1d8
--- /dev/null
+++ b/src/test/compile-fail/issue-31221.rs
@@ -0,0 +1,49 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Enum {
+    Var1,
+    Var2,
+}
+
+fn main() {
+    use Enum::*;
+    let s = Var1;
+    match s {
+        Var1 => (),
+        Var3 => (),
+        //~^ NOTE this pattern matches any value
+        Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    match &s {
+        &Var1 => (),
+        &Var3 => (),
+        //~^ NOTE this pattern matches any value
+        &Var2 => (),
+        //~^ ERROR unreachable pattern
+    };
+    let t = (Var1, Var1);
+    match t {
+        (Var1, b) => (),
+        (c, d) => (),
+        //~^ NOTE this pattern matches any value
+        anything => ()
+        //~^ ERROR unreachable pattern
+    };
+    // `_` need not emit a note, it is pretty obvious already.
+    let t = (Var1, Var1);
+    match t {
+        (Var1, b) => (),
+        _ => (),
+        anything => ()
+        //~^ ERROR unreachable pattern
+    };
+}