]> git.lizzy.rs Git - rust.git/commitdiff
Reject `_` in `ident` matcher
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 17 Mar 2018 19:08:18 +0000 (22:08 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 17 Mar 2018 19:08:18 +0000 (22:08 +0300)
src/libsyntax/ext/tt/macro_parser.rs
src/test/run-pass/macro-pat.rs
src/test/ui/underscore-ident-matcher.rs [new file with mode: 0644]
src/test/ui/underscore-ident-matcher.stderr [new file with mode: 0644]

index beefdb3a6eac4eda796553d2be8a3696eb8eb205..667653b5f7f26686f62a9f245ee65a053b86bd52 100644 (file)
@@ -86,7 +86,7 @@
 
 use ast::Ident;
 use syntax_pos::{self, BytePos, Span};
-use codemap::Spanned;
+use codemap::respan;
 use errors::FatalError;
 use ext::tt::quoted::{self, TokenTree};
 use parse::{Directory, ParseSess};
@@ -709,6 +709,15 @@ pub fn parse(
     }
 }
 
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<Ident> {
+    match *token {
+        token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
+        _ => None,
+    }
+}
+
 /// Checks whether a non-terminal may begin with a particular token.
 ///
 /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
@@ -725,7 +734,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
     match name {
         "expr" => token.can_begin_expr(),
         "ty" => token.can_begin_type(),
-        "ident" => token.is_ident(),
+        "ident" => get_macro_ident(token).is_some(),
         "vis" => match *token {
             // The follow-set of :vis + "priv" keyword + interpolated
             Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
@@ -814,21 +823,14 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "expr" => token::NtExpr(panictry!(p.parse_expr())),
         "ty" => token::NtTy(panictry!(p.parse_ty())),
         // this could be handled like a token, since it is one
-        "ident" => match p.token {
-            token::Ident(sn) => {
-                p.bump();
-                token::NtIdent(Spanned::<Ident> {
-                    node: sn,
-                    span: p.prev_span,
-                })
-            }
-            _ => {
-                let token_str = pprust::token_to_string(&p.token);
-                p.fatal(&format!("expected ident, found {}", &token_str[..]))
-                    .emit();
-                FatalError.raise()
-            }
-        },
+        "ident" => if let Some(ident) = get_macro_ident(&p.token) {
+            p.bump();
+            token::NtIdent(respan(p.prev_span, ident))
+        } else {
+            let token_str = pprust::token_to_string(&p.token);
+            p.fatal(&format!("expected ident, found {}", &token_str)).emit();
+            FatalError.raise()
+        }
         "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
index 8de3996245f86421b07715eeec4b734f0c860805..48e521de57e90e94f0d7c187c8fb21c0d88968ac 100644 (file)
@@ -71,6 +71,4 @@ pub fn main() {
         let ident_pat!(x) = 2;
         x+1
     });
-
-    let ident_pat!(_) = 2; // OK
 }
diff --git a/src/test/ui/underscore-ident-matcher.rs b/src/test/ui/underscore-ident-matcher.rs
new file mode 100644 (file)
index 0000000..eee9929
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 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! identity {
+    ($i: ident) => (
+        $i
+    )
+}
+
+fn main() {
+    let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}
diff --git a/src/test/ui/underscore-ident-matcher.stderr b/src/test/ui/underscore-ident-matcher.stderr
new file mode 100644 (file)
index 0000000..7f2b6ac
--- /dev/null
@@ -0,0 +1,8 @@
+error: no rules expected the token `_`
+  --> $DIR/underscore-ident-matcher.rs:18:19
+   |
+LL |     let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+   |                   ^
+
+error: aborting due to previous error
+