Skip to content

Commit 97de8ca

Browse files
committed
Parse auto traits the same as traits.
This moves the well formedness checks to the AST validation pass. Tests were adjusted. The auto keyword should be back-compat now.
1 parent 9d181ac commit 97de8ca

File tree

7 files changed

+83
-110
lines changed

7 files changed

+83
-110
lines changed

src/librustc_passes/ast_validation.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
229229
}
230230
}
231231
}
232-
ItemKind::Trait(.., ref bounds, ref trait_items) => {
232+
ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
233+
if is_auto == IsAuto::Yes {
234+
// Auto traits cannot have generics, super traits nor contain items.
235+
if !generics.ty_params.is_empty() {
236+
self.err_handler().span_err(item.span,
237+
"auto traits cannot have generics");
238+
}
239+
if !bounds.is_empty() {
240+
self.err_handler().span_err(item.span,
241+
"auto traits cannot have super traits");
242+
}
243+
if !trait_items.is_empty() {
244+
self.err_handler().span_err(item.span,
245+
"auto traits cannot contain items");
246+
}
247+
}
233248
self.no_questions_in_bounds(bounds, "supertraits", true);
234249
for trait_item in trait_items {
235250
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {

src/libsyntax/parse/parser.rs

Lines changed: 32 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
1616
use ast::Block;
1717
use ast::{BlockCheckMode, CaptureBy};
1818
use ast::{Constness, Crate};
19-
use ast::Generics;
2019
use ast::Defaultness;
2120
use ast::EnumDef;
2221
use ast::{Expr, ExprKind, RangeLimits};
@@ -3874,6 +3873,16 @@ impl<'a> Parser<'a> {
38743873
self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
38753874
}
38763875

3876+
fn eat_auto_trait(&mut self) -> bool {
3877+
if self.token.is_keyword(keywords::Auto)
3878+
&& self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
3879+
{
3880+
self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
3881+
} else {
3882+
false
3883+
}
3884+
}
3885+
38773886
fn is_defaultness(&self) -> bool {
38783887
// `pub` is included for better error messages
38793888
self.token.is_keyword(keywords::Default) &&
@@ -5052,7 +5061,7 @@ impl<'a> Parser<'a> {
50525061
}
50535062

50545063
/// Parse trait Foo { ... }
5055-
fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
5064+
fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
50565065
let ident = self.parse_ident()?;
50575066
let mut tps = self.parse_generics()?;
50585067

@@ -5079,17 +5088,7 @@ impl<'a> Parser<'a> {
50795088
}
50805089
}
50815090
}
5082-
Ok((ident, ItemKind::Trait(IsAuto::No, unsafety, tps, bounds, trait_items), None))
5083-
}
5084-
5085-
fn parse_item_auto_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
5086-
let ident = self.parse_ident()?;
5087-
self.expect(&token::OpenDelim(token::Brace))?;
5088-
self.expect(&token::CloseDelim(token::Brace))?;
5089-
// Auto traits cannot have generics, super traits nor contain items.
5090-
Ok((ident,
5091-
ItemKind::Trait(IsAuto::Yes, unsafety, Generics::default(), Vec::new(), Vec::new()),
5092-
None))
5091+
Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
50935092
}
50945093

50955094
/// Parses items implementations variants
@@ -5999,44 +5998,19 @@ impl<'a> Parser<'a> {
59995998
return Ok(Some(item));
60005999
}
60016000
if self.check_keyword(keywords::Unsafe) &&
6002-
self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
6001+
(self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
6002+
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
60036003
{
60046004
// UNSAFE TRAIT ITEM
60056005
self.expect_keyword(keywords::Unsafe)?;
6006-
self.expect_keyword(keywords::Trait)?;
6006+
let is_auto = if self.eat_keyword(keywords::Trait) {
6007+
IsAuto::No
6008+
} else {
6009+
self.eat_auto_trait();
6010+
IsAuto::Yes
6011+
};
60076012
let (ident, item_, extra_attrs) =
6008-
self.parse_item_trait(ast::Unsafety::Unsafe)?;
6009-
let prev_span = self.prev_span;
6010-
let item = self.mk_item(lo.to(prev_span),
6011-
ident,
6012-
item_,
6013-
visibility,
6014-
maybe_append(attrs, extra_attrs));
6015-
return Ok(Some(item));
6016-
}
6017-
if self.eat_keyword(keywords::Auto) {
6018-
self.expect_keyword(keywords::Trait)?;
6019-
// AUTO TRAIT ITEM
6020-
let (ident,
6021-
item_,
6022-
extra_attrs) = self.parse_item_auto_trait(ast::Unsafety::Normal)?;
6023-
let prev_span = self.prev_span;
6024-
let item = self.mk_item(lo.to(prev_span),
6025-
ident,
6026-
item_,
6027-
visibility,
6028-
maybe_append(attrs, extra_attrs));
6029-
return Ok(Some(item));
6030-
}
6031-
if self.check_keyword(keywords::Unsafe) &&
6032-
self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) {
6033-
self.expect_keyword(keywords::Unsafe)?;
6034-
self.expect_keyword(keywords::Auto)?;
6035-
self.expect_keyword(keywords::Trait)?;
6036-
// UNSAFE AUTO TRAIT ITEM
6037-
let (ident,
6038-
item_,
6039-
extra_attrs) = self.parse_item_auto_trait(ast::Unsafety::Unsafe)?;
6013+
self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
60406014
let prev_span = self.prev_span;
60416015
let item = self.mk_item(lo.to(prev_span),
60426016
ident,
@@ -6139,10 +6113,19 @@ impl<'a> Parser<'a> {
61396113
maybe_append(attrs, extra_attrs));
61406114
return Ok(Some(item));
61416115
}
6142-
if self.eat_keyword(keywords::Trait) {
6116+
if self.check_keyword(keywords::Trait)
6117+
|| (self.check_keyword(keywords::Auto)
6118+
&& self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
6119+
{
6120+
let is_auto = if self.eat_keyword(keywords::Trait) {
6121+
IsAuto::No
6122+
} else {
6123+
self.eat_auto_trait();
6124+
IsAuto::Yes
6125+
};
61436126
// TRAIT ITEM
61446127
let (ident, item_, extra_attrs) =
6145-
self.parse_item_trait(ast::Unsafety::Normal)?;
6128+
self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
61466129
let prev_span = self.prev_span;
61476130
let item = self.mk_item(lo.to(prev_span),
61486131
ident,

src/test/compile-fail/auto-is-contextual.rs

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2017 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+
#![feature(optin_builtin_traits)]
12+
13+
auto trait Generic<T> {}
14+
//~^ ERROR auto traits cannot have generics
15+
//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
16+
auto trait Bound : Copy {}
17+
//~^ ERROR auto traits cannot have super traits
18+
//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
19+
auto trait MyTrait { fn foo() {} }
20+
//~^ ERROR auto traits cannot contain items
21+
//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
22+
fn main() {}

src/test/parse-fail/auto-trait-no-rename.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/test/parse-fail/auto-trait-no-super.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/test/parse-fail/auto-trait-no-generics.rs renamed to src/test/run-pass/auto-is-contextual.rs

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

11-
// compile-flags: -Z parse-only
11+
macro_rules! auto {
12+
() => (struct S;)
13+
}
1214

13-
auto trait Auto<T> { }
14-
//~^ ERROR: expected `{`, found `<`
15+
auto!();
16+
17+
fn auto() {}
18+
19+
fn main() {
20+
auto();
21+
let auto = 10;
22+
auto;
23+
auto as u8;
24+
}

0 commit comments

Comments
 (0)