1
Fork 0

Alias TraitItem & ImplItem.

Allow defaultness on trait items syntactically.
This commit is contained in:
Mazdak Farrokhzad 2019-11-30 18:25:44 +01:00
parent 3eebe058e5
commit c4bbe9cbbe
13 changed files with 90 additions and 27 deletions

View file

@ -714,9 +714,9 @@ impl<'a> Parser<'a> {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
span: lo.to(self.prev_span), span: lo.to(self.prev_span),
ident: name, ident: name,
attrs,
vis, vis,
defaultness, defaultness,
attrs,
generics, generics,
kind, kind,
tokens: None, tokens: None,
@ -882,6 +882,7 @@ impl<'a> Parser<'a> {
) -> PResult<'a, TraitItem> { ) -> PResult<'a, TraitItem> {
let lo = self.token.span; let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?; let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
let (name, kind, generics) = if self.eat_keyword(kw::Type) { let (name, kind, generics) = if self.eat_keyword(kw::Type) {
self.parse_trait_item_assoc_ty()? self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() { } else if self.is_const_item() {
@ -895,12 +896,13 @@ impl<'a> Parser<'a> {
Ok(TraitItem { Ok(TraitItem {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
span: lo.to(self.prev_span),
ident: name, ident: name,
attrs, attrs,
vis, vis,
defaultness,
generics, generics,
kind, kind,
span: lo.to(self.prev_span),
tokens: None, tokens: None,
}) })
} }

View file

@ -271,6 +271,14 @@ impl<'a> AstValidator<'a> {
forbid, and warn are the only allowed built-in attributes in function parameters") forbid, and warn are the only allowed built-in attributes in function parameters")
}); });
} }
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
if let Defaultness::Default = defaultness {
self.err_handler()
.struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
.emit();
}
}
} }
enum GenericPosition { enum GenericPosition {
@ -746,6 +754,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_trait_item(&mut self, ti: &'a TraitItem) { fn visit_trait_item(&mut self, ti: &'a TraitItem) {
self.invalid_visibility(&ti.vis, None); self.invalid_visibility(&ti.vis, None);
self.check_defaultness(ti.span, ti.defaultness);
visit::walk_trait_item(self, ti); visit::walk_trait_item(self, ti);
} }
} }

View file

@ -1603,24 +1603,12 @@ pub struct FnSig {
pub decl: P<FnDecl>, pub decl: P<FnDecl>,
} }
/// Represents an item declaration within a trait declaration, pub type TraitItem = ImplItem<TraitItemKind>;
/// Represents the kind of an item declaration within a trait declaration,
/// possibly including a default implementation. A trait item is /// possibly including a default implementation. A trait item is
/// either required (meaning it doesn't have an implementation, just a /// either required (meaning it doesn't have an implementation, just a
/// signature) or provided (meaning it has a default implementation). /// signature) or provided (meaning it has a default implementation).
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitItem {
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub ident: Ident,
pub generics: Generics,
pub kind: TraitItemKind,
/// See `Item::tokens` for what this is.
pub tokens: Option<TokenStream>,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum TraitItemKind { pub enum TraitItemKind {
Const(P<Ty>, Option<P<Expr>>), Const(P<Ty>, Option<P<Expr>>),
@ -1631,7 +1619,7 @@ pub enum TraitItemKind {
/// Represents anything within an `impl` block. /// Represents anything within an `impl` block.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ImplItem { pub struct ImplItem<K = ImplItemKind> {
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
@ -1640,7 +1628,7 @@ pub struct ImplItem {
pub defaultness: Defaultness, pub defaultness: Defaultness,
pub generics: Generics, pub generics: Generics,
pub kind: ImplItemKind, pub kind: K,
/// See `Item::tokens` for what this is. /// See `Item::tokens` for what this is.
pub tokens: Option<TokenStream>, pub tokens: Option<TokenStream>,
} }

View file

@ -939,7 +939,8 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T) pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
-> SmallVec<[TraitItem; 1]> -> SmallVec<[TraitItem; 1]>
{ {
let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item; let TraitItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } =
&mut item;
visitor.visit_id(id); visitor.visit_id(id);
visitor.visit_ident(ident); visitor.visit_ident(ident);
visitor.visit_vis(vis); visitor.visit_vis(vis);

View file

@ -1550,6 +1550,7 @@ impl<'a> State<'a> {
self.hardbreak_if_not_bol(); self.hardbreak_if_not_bol();
self.maybe_print_comment(ti.span.lo()); self.maybe_print_comment(ti.span.lo());
self.print_outer_attributes(&ti.attrs); self.print_outer_attributes(&ti.attrs);
self.print_defaultness(ti.defaultness);
match ti.kind { match ti.kind {
ast::TraitItemKind::Const(ref ty, ref default) => { ast::TraitItemKind::Const(ref ty, ref default) => {
self.print_associated_const( self.print_associated_const(

View file

@ -53,6 +53,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visi
AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem { AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
id, span, ident, vis, attrs, generics, id, span, ident, vis, attrs, generics,
kind: ast::TraitItemKind::Macro(mac_placeholder()), kind: ast::TraitItemKind::Macro(mac_placeholder()),
defaultness: ast::Defaultness::Final,
tokens: None, tokens: None,
}]), }]),
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem { AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {

View file

@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
LL | }); LL | });
| ^ expected one of `.`, `;`, `?`, `else`, or an operator | ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
--> $DIR/issue-60075.rs:6:11 --> $DIR/issue-60075.rs:6:11
| |
LL | fn qux() -> Option<usize> { LL | fn qux() -> Option<usize> {

View file

@ -1,8 +1,8 @@
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
--> $DIR/issue-32446.rs:4:11 --> $DIR/issue-32446.rs:4:11
| |
LL | trait T { ... } LL | trait T { ... }
| ^^^ expected one of 9 possible tokens | ^^^ expected one of 10 possible tokens
error: aborting due to previous error error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
--> $DIR/trait-non-item-macros.rs:2:19 --> $DIR/trait-non-item-macros.rs:2:19
| |
LL | ($a:expr) => ($a) LL | ($a:expr) => ($a)
| ^^ expected one of 8 possible tokens | ^^ expected one of 9 possible tokens
... ...
LL | bah!(2); LL | bah!(2);
| -------- in this macro invocation | -------- in this macro invocation

View file

@ -7,11 +7,11 @@ LL | trait T {
LL | fn main() {} LL | fn main() {}
| ^ | ^
error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
--> $DIR/missing-close-brace-in-trait.rs:5:12 --> $DIR/missing-close-brace-in-trait.rs:5:12
| |
LL | pub(crate) struct Bar<T>(); LL | pub(crate) struct Bar<T>();
| ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` | ^^^^^^ expected one of 7 possible tokens
error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
--> $DIR/missing-close-brace-in-trait.rs:1:1 --> $DIR/missing-close-brace-in-trait.rs:1:1

View file

@ -0,0 +1,10 @@
fn main() {}
trait X {
default const A: u8; //~ ERROR `default` is only allowed on items in `impl` definitions
default const B: u8 = 0; //~ ERROR `default` is only allowed on items in `impl` definitions
default type D; //~ ERROR `default` is only allowed on items in `impl` definitions
default type C: Ord; //~ ERROR `default` is only allowed on items in `impl` definitions
default fn f1(); //~ ERROR `default` is only allowed on items in `impl` definitions
default fn f2() {} //~ ERROR `default` is only allowed on items in `impl` definitions
}

View file

@ -0,0 +1,38 @@
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:4:5
|
LL | default const A: u8;
| ^^^^^^^^^^^^^^^^^^^^
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:5:5
|
LL | default const B: u8 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5
|
LL | default type D;
| ^^^^^^^^^^^^^^^
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5
|
LL | default type C: Ord;
| ^^^^^^^^^^^^^^^^^^^^
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5
|
LL | default fn f1();
| ^^^^^^^^^^^^^^^^
error: `default` is only allowed on items in `impl` definitions
--> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5
|
LL | default fn f2() {}
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View file

@ -0,0 +1,13 @@
// check-pass
fn main() {}
#[cfg(FALSE)]
trait X {
default const A: u8;
default const B: u8 = 0;
default type D;
default type C: Ord;
default fn f1();
default fn f2() {}
}