diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 97cea5c9d64..05ad1643619 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,6 +21,7 @@ use rustc::session::Session; use syntax::ast::*; use syntax::attr; use syntax::codemap::Spanned; +use syntax::parse::token; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -35,8 +36,16 @@ impl<'a> AstValidator<'a> { &self.session.parse_sess.span_diagnostic } + fn check_lifetime(&self, lifetime: &Lifetime) { + let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()]; + if !valid_names.contains(&lifetime.ident.name) && + token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() { + self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names"); + } + } + fn check_label(&self, label: Ident, span: Span) { - if label.name == keywords::StaticLifetime.name() || label.name == "'_" { + if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" { self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name)); } } @@ -200,6 +209,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_use_tree(self, use_tree, id); } + fn visit_lifetime(&mut self, lifetime: &'a Lifetime) { + self.check_lifetime(lifetime); + visit::walk_lifetime(self, lifetime); + } + fn visit_item(&mut self, item: &'a Item) { match item.node { ItemKind::Impl(.., Some(..), _, ref impl_items) => { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 6f20104dda5..d9c33fa50bd 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -14,7 +14,7 @@ use codemap::{CodeMap, FilePathMapping}; use errors::{FatalError, DiagnosticBuilder}; use parse::{token, ParseSess}; use str::char_at; -use symbol::{Symbol, keywords}; +use symbol::Symbol; use std_unicode::property::Pattern_White_Space; use std::borrow::Cow; @@ -1296,18 +1296,6 @@ impl<'a> StringReader<'a> { self.mk_ident(&format!("'{}", lifetime_name)) }); - // Conjure up a "keyword checking ident" to make sure that - // the lifetime name is not a keyword. - let keyword_checking_ident = self.with_str_from(start, |lifetime_name| { - self.mk_ident(lifetime_name) - }); - let keyword_checking_token = &token::Ident(keyword_checking_ident); - let last_bpos = self.pos; - if keyword_checking_token.is_reserved_ident() && - !keyword_checking_token.is_keyword(keywords::Static) { - self.err_span_(start, last_bpos, "lifetimes cannot use keyword names"); - } - return Ok(token::Lifetime(ident)); } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 72760360711..aafdd696b74 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -35,6 +35,10 @@ impl Ident { Ident::with_empty_ctxt(Symbol::intern(string)) } + pub fn without_first_quote(&self) -> Ident { + Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt } + } + pub fn modern(self) -> Ident { Ident { name: self.name, ctxt: self.ctxt.modern() } } @@ -437,4 +441,10 @@ mod tests { // gensym of *existing* string gets new number: assert_eq!(i.gensym("dog"), Symbol(4294967293)); } + + #[test] + fn without_first_quote_test() { + let i = Ident::from_str("'break"); + assert_eq!(i.without_first_quote().name, keywords::Break.name()); + } } diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/compile-fail/issue-10412.rs similarity index 87% rename from src/test/parse-fail/issue-10412.rs rename to src/test/compile-fail/issue-10412.rs index d723d94c02c..ee553730a35 100644 --- a/src/test/parse-fail/issue-10412.rs +++ b/src/test/compile-fail/issue-10412.rs @@ -8,16 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only -Z continue-parse-after-error - - trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names - fn serialize(val : &'self T) -> Vec ; //~ ERROR lifetimes cannot use keyword names + fn serialize(val : &'self T) -> Vec; //~ ERROR lifetimes cannot use keyword names fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names } impl<'self> Serializable for &'self str { //~ ERROR lifetimes cannot use keyword names //~^ ERROR lifetimes cannot use keyword names + //~| ERROR missing lifetime specifier fn serialize(val : &'self str) -> Vec { //~ ERROR lifetimes cannot use keyword names vec![1] } diff --git a/src/test/compile-fail/issue-46311.rs b/src/test/compile-fail/issue-46311.rs new file mode 100644 index 00000000000..82f55f2c142 --- /dev/null +++ b/src/test/compile-fail/issue-46311.rs @@ -0,0 +1,14 @@ +// Copyright 2012-2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + 'break: loop { //~ ERROR invalid label name `'break` + } +} diff --git a/src/test/parse-fail/lifetime-no-keyword.rs b/src/test/compile-fail/lifetime-no-keyword.rs similarity index 68% rename from src/test/parse-fail/lifetime-no-keyword.rs rename to src/test/compile-fail/lifetime-no-keyword.rs index a8771ae93af..d583c4fc6c6 100644 --- a/src/test/parse-fail/lifetime-no-keyword.rs +++ b/src/test/compile-fail/lifetime-no-keyword.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only -Z continue-parse-after-error - fn foo<'a>(a: &'a isize) { } fn bar(a: &'static isize) { } -fn baz(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names -fn zab(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names - +fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names +fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names +//~^ ERROR lifetimes cannot use keyword names fn main() { }