about summary refs log tree commit diff
diff options
context:
space:
mode:
authorrleungx <rleungx@gmail.com>2018-05-03 19:09:34 +0800
committerrleungx <rleungx@gmail.com>2018-05-03 19:12:39 +0800
commit390c3cee6a8e0c0550eb6213c0e7e5f74c4fbc31 (patch)
tree110c99e429502761762734846a6c91488a67ef46
parent698b956a9fca9688632d617dd6d73cae834237a3 (diff)
downloadrust-390c3cee6a8e0c0550eb6213c0e7e5f74c4fbc31.tar.gz
rust-390c3cee6a8e0c0550eb6213c0e7e5f74c4fbc31.zip
check if the token is a lifetime before parsing
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs8
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/test/compile-fail/macro-non-lifetime.rs20
3 files changed, 28 insertions, 2 deletions
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index d9c3deb30da..71634ada894 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -835,7 +835,13 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
         "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))),
-        "lifetime" => token::NtLifetime(p.expect_lifetime().ident),
+        "lifetime" => if p.check_lifetime() {
+            token::NtLifetime(p.expect_lifetime().ident)
+        } else {
+            let token_str = pprust::token_to_string(&p.token);
+            p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit();
+            FatalError.raise();
+        }
         // this is not supposed to happen, since it has been checked
         // when compiling the macro.
         _ => p.span_bug(sp, "invalid fragment specifier"),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 324cadc84e8..bbee03bb0d5 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn check_lifetime(&mut self) -> bool {
+    pub fn check_lifetime(&mut self) -> bool {
         self.expected_tokens.push(TokenType::Lifetime);
         self.token.is_lifetime()
     }
diff --git a/src/test/compile-fail/macro-non-lifetime.rs b/src/test/compile-fail/macro-non-lifetime.rs
new file mode 100644
index 00000000000..a2706e83229
--- /dev/null
+++ b/src/test/compile-fail/macro-non-lifetime.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// Test for issue #50381: non-lifetime passed to :lifetime.
+
+#![feature(macro_lifetime_matcher)]
+
+macro_rules! m { ($x:lifetime) => { } }
+
+fn main() {
+    m!(a);
+    //~^ ERROR expected a lifetime, found `a`
+}