Skip to content

Commit 65ccf24

Browse files
author
Agustin Chiappe Berrini
committed
and refactor to just move the checking
1 parent a289940 commit 65ccf24

File tree

7 files changed

+100
-39
lines changed

7 files changed

+100
-39
lines changed

src/librustc_passes/ast_validation.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use rustc::session::Session;
2121
use syntax::ast::*;
2222
use syntax::attr;
2323
use syntax::codemap::Spanned;
24-
use syntax::symbol::keywords;
2524
use syntax::visit::{self, Visitor};
2625
use syntax_pos::Span;
2726
use errors;
@@ -35,8 +34,16 @@ impl<'a> AstValidator<'a> {
3534
&self.session.parse_sess.span_diagnostic
3635
}
3736

37+
fn check_lifetime(&self, lifetime: &Lifetime) {
38+
if !lifetime.ident.without_first_quote().is_valid() &&
39+
!lifetime.ident.name.is_static_keyword() {
40+
self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
41+
}
42+
}
43+
3844
fn check_label(&self, label: Ident, span: Span) {
39-
if label.name == keywords::StaticLifetime.name() || label.name == "'_" {
45+
if label.name.is_static_keyword() || !label.without_first_quote().is_valid()
46+
|| label.name == "'_" {
4047
self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
4148
}
4249
}
@@ -202,19 +209,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
202209

203210
fn visit_item(&mut self, item: &'a Item) {
204211
match item.node {
205-
ItemKind::Impl(.., Some(..), _, ref impl_items) => {
212+
ItemKind::Impl(.., ref generics, Some(..), _, ref impl_items) => {
206213
self.invalid_visibility(&item.vis, item.span, None);
207214
for impl_item in impl_items {
208215
self.invalid_visibility(&impl_item.vis, impl_item.span, None);
209216
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
210217
self.check_trait_fn_not_const(sig.constness);
211218
}
212219
}
220+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
213221
}
214-
ItemKind::Impl(.., None, _, _) => {
222+
ItemKind::Impl(.., ref generics, None, _, _) => {
215223
self.invalid_visibility(&item.vis,
216224
item.span,
217225
Some("place qualifiers on individual impl items instead"));
226+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
218227
}
219228
ItemKind::AutoImpl(..) => {
220229
self.invalid_visibility(&item.vis, item.span, None);
@@ -225,13 +234,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
225234
Some("place qualifiers on individual foreign items \
226235
instead"));
227236
}
228-
ItemKind::Enum(ref def, _) => {
237+
ItemKind::Enum(ref def, ref generics) => {
229238
for variant in &def.variants {
230239
self.invalid_non_exhaustive_attribute(variant);
231240
for field in variant.node.data.fields() {
232241
self.invalid_visibility(&field.vis, field.span, None);
233242
}
234243
}
244+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
235245
}
236246
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
237247
if is_auto == IsAuto::Yes {
@@ -268,6 +278,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
268278
}
269279
}
270280
}
281+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
271282
}
272283
ItemKind::Mod(_) => {
273284
// Ensure that `path` attributes on modules are recorded as used (c.f. #35584).
@@ -278,7 +289,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
278289
self.session.buffer_lint(lint, item.id, item.span, msg);
279290
}
280291
}
281-
ItemKind::Union(ref vdata, _) => {
292+
ItemKind::Union(ref vdata, ref generics) => {
282293
if !vdata.is_struct() {
283294
self.err_handler().span_err(item.span,
284295
"tuple and unit unions are not permitted");
@@ -287,6 +298,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
287298
self.err_handler().span_err(item.span,
288299
"unions cannot have zero fields");
289300
}
301+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
302+
}
303+
ItemKind::Fn(.., ref generics, _) |
304+
ItemKind::Ty(_, ref generics) |
305+
ItemKind::Struct(_, ref generics) => {
306+
generics.lifetimes.iter().for_each(|l| self.check_lifetime(&l.lifetime))
290307
}
291308
_ => {}
292309
}

src/libsyntax/parse/lexer/mod.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use codemap::{CodeMap, FilePathMapping};
1414
use errors::{FatalError, DiagnosticBuilder};
1515
use parse::{token, ParseSess};
1616
use str::char_at;
17-
use symbol::{Symbol, keywords};
17+
use symbol::{Symbol};
1818
use std_unicode::property::Pattern_White_Space;
1919

2020
use std::borrow::Cow;
@@ -1296,18 +1296,6 @@ impl<'a> StringReader<'a> {
12961296
self.mk_ident(&format!("'{}", lifetime_name))
12971297
});
12981298

1299-
// Conjure up a "keyword checking ident" to make sure that
1300-
// the lifetime name is not a keyword.
1301-
let keyword_checking_ident = self.with_str_from(start, |lifetime_name| {
1302-
self.mk_ident(lifetime_name)
1303-
});
1304-
let keyword_checking_token = &token::Ident(keyword_checking_ident);
1305-
let last_bpos = self.pos;
1306-
if keyword_checking_token.is_reserved_ident() &&
1307-
!keyword_checking_token.is_keyword(keywords::Static) {
1308-
self.err_span_(start, last_bpos, "lifetimes cannot use keyword names");
1309-
}
1310-
13111299
return Ok(token::Lifetime(ident));
13121300
}
13131301

src/libsyntax/parse/token.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,12 @@ impl Token {
364364

365365
/// Returns `true` if the token is a keyword used in the language.
366366
pub fn is_used_keyword(&self) -> bool {
367-
match self.ident() {
368-
Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(),
369-
_ => false,
370-
}
367+
self.ident().map(|id| id.name.is_used_keyword()).unwrap_or(false)
371368
}
372369

373370
/// Returns `true` if the token is a keyword reserved for possible future use.
374371
pub fn is_unused_keyword(&self) -> bool {
375-
match self.ident() {
376-
Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(),
377-
_ => false,
378-
}
372+
self.ident().map(|id| id.name.is_unused_keyword()).unwrap_or(false)
379373
}
380374

381375
pub fn glue(self, joint: Token) -> Option<Token> {

src/libsyntax_pos/symbol.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ impl Ident {
3535
Ident::with_empty_ctxt(Symbol::intern(string))
3636
}
3737

38+
pub fn without_first_quote(&self) -> Ident {
39+
Ident { name: self.name.without_first_quote(), ctxt: self.ctxt }
40+
}
41+
3842
pub fn modern(self) -> Ident {
3943
Ident { name: self.name, ctxt: self.ctxt.modern() }
4044
}
45+
46+
pub fn is_valid(&self) -> bool {
47+
!self.name.is_used_keyword() && !self.name.is_unused_keyword()
48+
}
4149
}
4250

4351
impl fmt::Debug for Ident {
@@ -113,6 +121,24 @@ impl Symbol {
113121
pub fn as_u32(self) -> u32 {
114122
self.0
115123
}
124+
125+
/// Returns `true` if the token is a keyword used in the language.
126+
pub fn is_used_keyword(&self) -> bool {
127+
self >= &keywords::As.name() && self <= &keywords::While.name()
128+
}
129+
130+
/// Returns `true` if the token is a keyword reserved for possible future use.
131+
pub fn is_unused_keyword(&self) -> bool {
132+
self >= &keywords::Abstract.name() && self <= &keywords::Yield.name()
133+
}
134+
135+
pub fn is_static_keyword(&self) -> bool {
136+
self == &keywords::StaticLifetime.name()
137+
}
138+
139+
pub fn without_first_quote(&self) -> Symbol {
140+
Symbol::from(self.as_str().trim_left_matches('\''))
141+
}
116142
}
117143

118144
impl<'a> From<&'a str> for Symbol {
@@ -428,4 +454,30 @@ mod tests {
428454
// gensym of *existing* string gets new number:
429455
assert_eq!(i.gensym("dog"), Symbol(4294967293));
430456
}
457+
458+
#[test]
459+
fn is_used_keyword_test() {
460+
let s = Symbol(5);
461+
assert_eq!(s.is_used_keyword(), true);
462+
}
463+
464+
#[test]
465+
fn is_unused_keyword_test() {
466+
let s = Symbol(40);
467+
assert_eq!(s.is_unused_keyword(), true);
468+
}
469+
470+
#[test]
471+
fn is_valid_test() {
472+
let i = Ident { name: Symbol(40), ctxt: SyntaxContext(0) };
473+
assert_eq!(i.is_valid(), false);
474+
let i = Ident { name: Symbol(61), ctxt: SyntaxContext(0) };
475+
assert_eq!(i.is_valid(), true);
476+
}
477+
478+
#[test]
479+
fn without_first_quote_test() {
480+
let i = Ident::from_str("'break");
481+
assert_eq!(i.without_first_quote().name, keywords::Break.name());
482+
}
431483
}

src/test/parse-fail/issue-10412.rs renamed to src/test/compile-fail/issue-10412.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,18 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only -Z continue-parse-after-error
12-
13-
1411
trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
15-
fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR lifetimes cannot use keyword names
16-
fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
12+
fn serialize(val : &'self T) -> Vec<u8> ;
13+
fn deserialize(repr : &[u8]) -> &'self T;
1714
}
1815

19-
impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
16+
impl<'self> Serializable<str> for &'self str {
2017
//~^ ERROR lifetimes cannot use keyword names
21-
fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
18+
//~| ERROR missing lifetime specifier
19+
fn serialize(val : &'self str) -> Vec<u8> {
2220
vec![1]
2321
}
24-
fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR lifetimes cannot use keyword names
22+
fn deserialize(repr: &[u8]) -> &'self str {
2523
"hi"
2624
}
2725
}

src/test/compile-fail/issue-46311.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
'break: loop { //~ ERROR invalid label name `'break`
13+
}
14+
}

src/test/parse-fail/lifetime-no-keyword.rs renamed to src/test/compile-fail/lifetime-no-keyword.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only -Z continue-parse-after-error
12-
1311
fn foo<'a>(a: &'a isize) { }
1412
fn bar(a: &'static isize) { }
15-
fn baz(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names
16-
fn zab(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names
13+
fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names
14+
fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names
1715

1816
fn main() { }

0 commit comments

Comments
 (0)