Alias TraitItem
& ImplItem
.
Allow defaultness on trait items syntactically.
This commit is contained in:
parent
3eebe058e5
commit
c4bbe9cbbe
13 changed files with 90 additions and 27 deletions
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
13
src/test/ui/parser/trait-item-with-defaultness-pass.rs
Normal file
13
src/test/ui/parser/trait-item-with-defaultness-pass.rs
Normal 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() {}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue