about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-11-11 15:49:36 +0000
committerbors <bors@rust-lang.org>2017-11-11 15:49:36 +0000
commitb22679366a6faab9f3790697f8be0a1dce38c285 (patch)
tree2b94c0aedcf667fd9b50e240e3cc6537a42a36d7
parent965ace59f28c3ffec3faeb1f8c7cfa5adf69cf0f (diff)
parentf7b4b88840d872909a67e5f9623281e3e2165fba (diff)
downloadrust-b22679366a6faab9f3790697f8be0a1dce38c285.tar.gz
rust-b22679366a6faab9f3790697f8be0a1dce38c285.zip
Auto merge of #45775 - petrochenkov:patnopat, r=nikomatsakis
Accept interpolated patterns in trait method parameters

Permit this, basically
```rust
macro_rules! m {
    ($pat: pat) => {
        trait Tr {
            fn f($pat: u8) {}
        }
    }
}
```
it previously caused a parsing error during expansion because trait methods accept only very restricted set of patterns during parsing due to ambiguities caused by [anonymous parameters](https://github.com/rust-lang/rust/issues/41686), and this set didn't include interpolated patterns.

Some outdated messages from "no patterns allowed" errors are also removed.

Addresses https://github.com/rust-lang/rust/issues/35203#issuecomment-341937159
-rw-r--r--src/librustc_passes/ast_validation.rs45
-rw-r--r--src/librustc_passes/diagnostics.rs1
-rw-r--r--src/libsyntax/parse/parser.rs26
-rw-r--r--src/test/compile-fail/no-patterns-in-args-2.rs1
-rw-r--r--src/test/compile-fail/no-patterns-in-args-macro.rs36
-rw-r--r--src/test/compile-fail/no-patterns-in-args.rs4
6 files changed, 64 insertions, 49 deletions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 6d9c2948841..40adc6bcb12 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -72,7 +72,8 @@ impl<'a> AstValidator<'a> {
             match arg.pat.node {
                 PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
                 PatKind::Wild => {}
-                PatKind::Ident(..) => report_err(arg.pat.span, true),
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
+                    report_err(arg.pat.span, true),
                 _ => report_err(arg.pat.span, false),
             }
         }
@@ -151,14 +152,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         match ty.node {
             TyKind::BareFn(ref bfty) => {
                 self.check_decl_no_pat(&bfty.decl, |span, _| {
-                    let mut err = struct_span_err!(self.session,
-                                                   span,
-                                                   E0561,
-                                                   "patterns aren't allowed in function pointer \
-                                                    types");
-                    err.span_note(span,
-                                  "this is a recent error, see issue #35203 for more details");
-                    err.emit();
+                    struct_span_err!(self.session, span, E0561,
+                                     "patterns aren't allowed in function pointer types").emit();
                 });
             }
             TyKind::TraitObject(ref bounds, ..) => {
@@ -260,12 +255,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
                         self.check_trait_fn_not_const(sig.constness);
                         if block.is_none() {
-                            self.check_decl_no_pat(&sig.decl, |span, _| {
-                                self.session.buffer_lint(
-                                    lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
-                                    trait_item.id, span,
-                                    "patterns aren't allowed in methods \
-                                     without bodies");
+                            self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
+                                if mut_ident {
+                                    self.session.buffer_lint(
+                                        lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
+                                        trait_item.id, span,
+                                        "patterns aren't allowed in methods without bodies");
+                                } else {
+                                    struct_span_err!(self.session, span, E0642,
+                                        "patterns aren't allowed in methods without bodies").emit();
+                                }
                             });
                         }
                     }
@@ -299,18 +298,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
         match fi.node {
             ForeignItemKind::Fn(ref decl, _) => {
-                self.check_decl_no_pat(decl, |span, is_recent| {
-                    let mut err = struct_span_err!(self.session,
-                                                   span,
-                                                   E0130,
-                                                   "patterns aren't allowed in foreign function \
-                                                    declarations");
-                    err.span_label(span, "pattern not allowed in foreign function");
-                    if is_recent {
-                        err.span_note(span,
-                                      "this is a recent error, see issue #35203 for more details");
-                    }
-                    err.emit();
+                self.check_decl_no_pat(decl, |span, _| {
+                    struct_span_err!(self.session, span, E0130,
+                                     "patterns aren't allowed in foreign function declarations")
+                        .span_label(span, "pattern not allowed in foreign function").emit();
                 });
             }
             ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 1bfa5943ee9..3597a6f1828 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -264,4 +264,5 @@ register_diagnostics! {
     E0226, // only a single explicit lifetime bound is permitted
     E0472, // asm! is unsupported on this target
     E0561, // patterns aren't allowed in function pointer types
+    E0642, // patterns aren't allowed in methods without bodies
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e583981d981..c1819307928 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -360,10 +360,6 @@ impl TokenType {
     }
 }
 
-fn is_ident_or_underscore(t: &token::Token) -> bool {
-    t.is_ident() || *t == token::Underscore
-}
-
 // Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
 // `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
 fn can_continue_type_after_ident(t: &token::Token) -> bool {
@@ -1625,23 +1621,19 @@ impl<'a> Parser<'a> {
         Ok(MutTy { ty: t, mutbl: mutbl })
     }
 
-    pub fn is_named_argument(&mut self) -> bool {
+    fn is_named_argument(&mut self) -> bool {
         let offset = match self.token {
-            token::BinOp(token::And) |
-            token::AndAnd => 1,
+            token::Interpolated(ref nt) => match nt.0 {
+                token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
+                _ => 0,
+            }
+            token::BinOp(token::And) | token::AndAnd => 1,
             _ if self.token.is_keyword(keywords::Mut) => 1,
-            _ => 0
+            _ => 0,
         };
 
-        debug!("parser is_named_argument offset:{}", offset);
-
-        if offset == 0 {
-            is_ident_or_underscore(&self.token)
-                && self.look_ahead(1, |t| *t == token::Colon)
-        } else {
-            self.look_ahead(offset, |t| is_ident_or_underscore(t))
-                && self.look_ahead(offset + 1, |t| *t == token::Colon)
-        }
+        self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
+        self.look_ahead(offset + 1, |t| t == &token::Colon)
     }
 
     /// This version of parse arg doesn't necessarily require
diff --git a/src/test/compile-fail/no-patterns-in-args-2.rs b/src/test/compile-fail/no-patterns-in-args-2.rs
index 967c292fa68..4d2412c34a5 100644
--- a/src/test/compile-fail/no-patterns-in-args-2.rs
+++ b/src/test/compile-fail/no-patterns-in-args-2.rs
@@ -14,7 +14,6 @@ trait Tr {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
                         //~^ WARN was previously accepted
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
-                     //~^ WARN was previously accepted
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     #[allow(anonymous_parameters)]
diff --git a/src/test/compile-fail/no-patterns-in-args-macro.rs b/src/test/compile-fail/no-patterns-in-args-macro.rs
new file mode 100644
index 00000000000..f85ce8f57ea
--- /dev/null
+++ b/src/test/compile-fail/no-patterns-in-args-macro.rs
@@ -0,0 +1,36 @@
+// Copyright 2017 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.
+
+macro_rules! m {
+    ($pat: pat) => {
+        trait Tr {
+            fn trait_method($pat: u8);
+        }
+
+        type A = fn($pat: u8);
+
+        extern {
+            fn foreign_fn($pat: u8);
+        }
+    }
+}
+
+mod good_pat {
+    m!(good_pat); // OK
+}
+
+mod bad_pat {
+    m!((bad, pat));
+    //~^ ERROR patterns aren't allowed in function pointer types
+    //~| ERROR patterns aren't allowed in foreign function declarations
+    //~| ERROR patterns aren't allowed in methods without bodies
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/no-patterns-in-args.rs b/src/test/compile-fail/no-patterns-in-args.rs
index b0278476998..081d6caaa13 100644
--- a/src/test/compile-fail/no-patterns-in-args.rs
+++ b/src/test/compile-fail/no-patterns-in-args.rs
@@ -11,21 +11,17 @@
 extern {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                         //~^ NOTE pattern not allowed in foreign function
-                        //~| NOTE this is a recent error
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                      //~^ NOTE pattern not allowed in foreign function
     fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
                         //~^ NOTE pattern not allowed in foreign function
-                        //~| NOTE this is a recent error
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     // fn g3(u8); // Not yet
 }
 
 type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
-                           //~^ NOTE this is a recent error
 type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
-                        //~^ NOTE this is a recent error
 type B1 = fn(arg: u8); // OK
 type B2 = fn(_: u8); // OK
 type B3 = fn(u8); // OK