diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 8f21028c4bd..205b8bf0d20 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,8 +21,10 @@ use rustc::session::Session; use syntax::ast::*; use syntax::attr; use syntax::codemap::Spanned; +use syntax::parse::token; use syntax::visit::{self, Visitor}; use syntax_pos::Span; +use syntax_pos::symbol::keywords; use errors; struct AstValidator<'a> { @@ -35,15 +37,15 @@ impl<'a> AstValidator<'a> { } fn check_lifetime(&self, lifetime: &Lifetime) { - if !lifetime.ident.without_first_quote().is_valid() && - !lifetime.ident.name.is_static_keyword() { + 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.is_static_keyword() || !label.without_first_quote().is_valid() - || 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)); } } @@ -207,9 +209,14 @@ 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(.., ref generics, Some(..), _, ref impl_items) => { + ItemKind::Impl(.., Some(..), _, ref impl_items) => { self.invalid_visibility(&item.vis, item.span, None); for impl_item in impl_items { self.invalid_visibility(&impl_item.vis, impl_item.span, None); @@ -217,13 +224,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_trait_fn_not_const(sig.constness); } } - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) } - ItemKind::Impl(.., ref generics, None, _, _) => { + ItemKind::Impl(.., None, _, _) => { self.invalid_visibility(&item.vis, item.span, Some("place qualifiers on individual impl items instead")); - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) } ItemKind::AutoImpl(..) => { self.invalid_visibility(&item.vis, item.span, None); @@ -234,14 +239,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Some("place qualifiers on individual foreign items \ instead")); } - ItemKind::Enum(ref def, ref generics) => { + ItemKind::Enum(ref def, _) => { for variant in &def.variants { self.invalid_non_exhaustive_attribute(variant); for field in variant.node.data.fields() { self.invalid_visibility(&field.vis, field.span, None); } } - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) } ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => { if is_auto == IsAuto::Yes { @@ -278,7 +282,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) } ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). @@ -289,7 +292,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.session.buffer_lint(lint, item.id, item.span, msg); } } - ItemKind::Union(ref vdata, ref generics) => { + ItemKind::Union(ref vdata, _) => { if !vdata.is_struct() { self.err_handler().span_err(item.span, "tuple and unit unions are not permitted"); @@ -298,12 +301,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) - } - ItemKind::Fn(.., ref generics, _) | - ItemKind::Ty(_, ref generics) | - ItemKind::Struct(_, ref generics) => { - generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime)) } _ => {} } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 5de5e1fd5de..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}; +use symbol::Symbol; use std_unicode::property::Pattern_White_Space; use std::borrow::Cow; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 94b279d2bdc..ff87f146c0a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -364,12 +364,18 @@ impl Token { /// Returns `true` if the token is a keyword used in the language. pub fn is_used_keyword(&self) -> bool { - self.ident().map(|id| id.name.is_used_keyword()).unwrap_or(false) + match self.ident() { + Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(), + _ => false, + } } /// Returns `true` if the token is a keyword reserved for possible future use. pub fn is_unused_keyword(&self) -> bool { - self.ident().map(|id| id.name.is_unused_keyword()).unwrap_or(false) + match self.ident() { + Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(), + _ => false, + } } pub fn glue(self, joint: Token) -> Option { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c904e93e63a..0e90e0922b9 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -42,10 +42,6 @@ impl Ident { pub fn modern(self) -> Ident { Ident { name: self.name, ctxt: self.ctxt.modern() } } - - pub fn is_valid(&self) -> bool { - !self.name.is_used_keyword() && !self.name.is_unused_keyword() - } } impl fmt::Debug for Ident { @@ -122,20 +118,6 @@ impl Symbol { self.0 } - /// Returns `true` if the token is a keyword used in the language. - pub fn is_used_keyword(&self) -> bool { - self >= &keywords::As.name() && self <= &keywords::While.name() - } - - /// Returns `true` if the token is a keyword reserved for possible future use. - pub fn is_unused_keyword(&self) -> bool { - self >= &keywords::Abstract.name() && self <= &keywords::Yield.name() - } - - pub fn is_static_keyword(&self) -> bool { - self == &keywords::StaticLifetime.name() - } - pub fn without_first_quote(&self) -> Symbol { Symbol::from(self.as_str().trim_left_matches('\'')) } diff --git a/src/test/compile-fail/issue-10412.rs b/src/test/compile-fail/issue-10412.rs index 20421bfc7c4..03f4fd1b3c0 100644 --- a/src/test/compile-fail/issue-10412.rs +++ b/src/test/compile-fail/issue-10412.rs @@ -9,17 +9,21 @@ // except according to those terms. trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names - fn serialize(val : &'self T) -> Vec ; + 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 { +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] } fn deserialize(repr: &[u8]) -> &'self str { + //~^ ERROR lifetimes cannot use keyword names "hi" } } diff --git a/src/test/compile-fail/lifetime-no-keyword.rs b/src/test/compile-fail/lifetime-no-keyword.rs index e2465663dd0..d583c4fc6c6 100644 --- a/src/test/compile-fail/lifetime-no-keyword.rs +++ b/src/test/compile-fail/lifetime-no-keyword.rs @@ -11,6 +11,7 @@ fn foo<'a>(a: &'a isize) { } fn bar(a: &'static isize) { } 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() { }