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,
span: lo.to(self.prev_span),
ident: name,
attrs,
vis,
defaultness,
attrs,
generics,
kind,
tokens: None,
@ -882,6 +882,7 @@ impl<'a> Parser<'a> {
) -> PResult<'a, TraitItem> {
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() {
@ -895,12 +896,13 @@ impl<'a> Parser<'a> {
Ok(TraitItem {
id: DUMMY_NODE_ID,
span: lo.to(self.prev_span),
ident: name,
attrs,
vis,
defaultness,
generics,
kind,
span: lo.to(self.prev_span),
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")
});
}
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 {
@ -746,6 +754,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
self.invalid_visibility(&ti.vis, None);
self.check_defaultness(ti.span, ti.defaultness);
visit::walk_trait_item(self, ti);
}
}

View File

@ -1603,24 +1603,12 @@ pub struct FnSig {
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
/// either required (meaning it doesn't have an implementation, just a
/// 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)]
pub enum TraitItemKind {
Const(P<Ty>, Option<P<Expr>>),
@ -1631,7 +1619,7 @@ pub enum TraitItemKind {
/// Represents anything within an `impl` block.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ImplItem {
pub struct ImplItem<K = ImplItemKind> {
pub attrs: Vec<Attribute>,
pub id: NodeId,
pub span: Span,
@ -1640,7 +1628,7 @@ pub struct ImplItem {
pub defaultness: Defaultness,
pub generics: Generics,
pub kind: ImplItemKind,
pub kind: K,
/// See `Item::tokens` for what this is.
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)
-> 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_ident(ident);
visitor.visit_vis(vis);

View File

@ -1550,6 +1550,7 @@ impl<'a> State<'a> {
self.hardbreak_if_not_bol();
self.maybe_print_comment(ti.span.lo());
self.print_outer_attributes(&ti.attrs);
self.print_defaultness(ti.defaultness);
match ti.kind {
ast::TraitItemKind::Const(ref ty, ref default) => {
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 {
id, span, ident, vis, attrs, generics,
kind: ast::TraitItemKind::Macro(mac_placeholder()),
defaultness: ast::Defaultness::Final,
tokens: None,
}]),
AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {

View File

@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
LL | });
| ^ 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
|
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
|
LL | trait T { ... }
| ^^^ expected one of 9 possible tokens
| ^^^ expected one of 10 possible tokens
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
|
LL | ($a:expr) => ($a)
| ^^ expected one of 8 possible tokens
| ^^ expected one of 9 possible tokens
...
LL | bah!(2);
| -------- in this macro invocation

View File

@ -7,11 +7,11 @@ LL | trait T {
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
|
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`
--> $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() {}
}