diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b2d663865827..884e7d1f6ad7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4084,14 +4084,14 @@ impl<'a> Parser<'a> { self.token.is_keyword(keywords::Extern) && self.look_ahead(1, |t| t != &token::ModSep) } - fn eat_auto_trait(&mut self) -> bool { - if self.token.is_keyword(keywords::Auto) - && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) - { - self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait) - } else { - false - } + fn is_auto_trait_item(&mut self) -> bool { + // auto trait + (self.token.is_keyword(keywords::Auto) + && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))) + || // unsafe auto trait + (self.token.is_keyword(keywords::Unsafe) && + self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) && + self.look_ahead(2, |t| t.is_keyword(keywords::Trait))) } fn is_defaultness(&self) -> bool { @@ -4194,7 +4194,8 @@ impl<'a> Parser<'a> { node: StmtKind::Item(macro_def), span: lo.to(self.prev_span), } - // Starts like a simple path, but not a union item or item with `crate` visibility. + // Starts like a simple path, being careful to avoid contextual keywords + // such as a union items, item with `crate` visibility or auto trait items. // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts // like a path (1 token), but it fact not a path. // `union::b::c` - path, `union U { ... }` - not a path. @@ -4204,7 +4205,8 @@ impl<'a> Parser<'a> { !self.token.is_qpath_start() && !self.is_union_item() && !self.is_crate_vis() && - !self.is_extern_non_path() { + !self.is_extern_non_path() && + !self.is_auto_trait_item() { let pth = self.parse_path(PathStyle::Expr)?; if !self.eat(&token::Not) { @@ -6368,7 +6370,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_auto_trait(); + self.eat_keyword(keywords::Auto); + self.eat_keyword(keywords::Trait); IsAuto::Yes }; let (ident, item_, extra_attrs) = @@ -6482,7 +6485,8 @@ impl<'a> Parser<'a> { let is_auto = if self.eat_keyword(keywords::Trait) { IsAuto::No } else { - self.eat_auto_trait(); + self.eat_keyword(keywords::Auto); + self.eat_keyword(keywords::Trait); IsAuto::Yes }; // TRAIT ITEM diff --git a/src/test/run-pass/auto-traits.rs b/src/test/run-pass/auto-traits.rs index 2511488c94ee..2a18b402bc64 100644 --- a/src/test/run-pass/auto-traits.rs +++ b/src/test/run-pass/auto-traits.rs @@ -11,7 +11,6 @@ #![feature(optin_builtin_traits)] auto trait Auto {} - unsafe auto trait AutoUnsafe {} impl !Auto for bool {} @@ -26,6 +25,10 @@ fn take_auto(_: T) {} fn take_auto_unsafe(_: T) {} fn main() { + // Parse inside functions. + auto trait AutoInner {} + unsafe auto trait AutoUnsafeInner {} + take_auto(0); take_auto(AutoBool(true)); take_auto_unsafe(0);