1
Fork 0

Unify associated item parsing.

An exception is `fn` params.
This commit is contained in:
Mazdak Farrokhzad 2019-12-01 11:30:04 +01:00
parent 7672bff378
commit 63a9030e7b
4 changed files with 29 additions and 59 deletions

View file

@ -6,8 +6,7 @@ use crate::maybe_whole;
use rustc_errors::{PResult, Applicability, DiagnosticBuilder, StashKey};
use rustc_error_codes::*;
use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
use syntax::ast::{ItemKind, ImplItem, TraitItem, TraitItemKind, UseTree, UseTreeKind};
use syntax::ast::{AssocItemKind};
use syntax::ast::{AssocItem, AssocItemKind, ItemKind, UseTree, UseTreeKind};
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
@ -649,7 +648,7 @@ impl<'a> Parser<'a> {
Ok((Ident::invalid(), item_kind, Some(attrs)))
}
fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
fn parse_impl_body(&mut self) -> PResult<'a, (Vec<AssocItem>, Vec<Attribute>)> {
self.expect(&token::OpenDelim(token::Brace))?;
let attrs = self.parse_inner_attributes()?;
@ -671,12 +670,12 @@ impl<'a> Parser<'a> {
}
/// Parses an impl item.
pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> {
pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
maybe_whole!(self, NtImplItem, |x| x);
let attrs = self.parse_outer_attributes()?;
let mut unclosed_delims = vec![];
let (mut item, tokens) = self.collect_tokens(|this| {
let item = this.parse_impl_item_(at_end, attrs);
let item = this.parse_assoc_item(at_end, attrs, |_| true);
unclosed_delims.append(&mut this.unclosed_delims);
item
})?;
@ -689,38 +688,6 @@ impl<'a> Parser<'a> {
Ok(item)
}
fn parse_impl_item_(
&mut self,
at_end: &mut bool,
mut attrs: Vec<Attribute>,
) -> PResult<'a, ImplItem> {
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_assoc_ty()?
} else if self.is_const_item() {
self.parse_assoc_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? {
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
(Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default())
} else {
self.parse_assoc_fn(at_end, &mut attrs, |_| true)?
};
Ok(ImplItem {
id: DUMMY_NODE_ID,
span: lo.to(self.prev_span),
ident: name,
attrs,
vis,
defaultness,
generics,
kind,
tokens: None,
})
}
/// Parses defaultness (i.e., `default` or nothing).
fn parse_defaultness(&mut self) -> Defaultness {
// `pub` is included for better error messages
@ -843,12 +810,19 @@ impl<'a> Parser<'a> {
}
/// Parses the items in a trait declaration.
pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> {
pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, AssocItem> {
maybe_whole!(self, NtTraitItem, |x| x);
let attrs = self.parse_outer_attributes()?;
let mut unclosed_delims = vec![];
let (mut item, tokens) = self.collect_tokens(|this| {
let item = this.parse_trait_item_(at_end, attrs);
// This is somewhat dubious; We don't want to allow
// param names to be left off if there is a definition...
//
// We don't allow param names to be left off in edition 2018.
//
// FIXME(Centril): bake closure into param parsing.
// Also add semantic restrictions and add tests.
let item = this.parse_assoc_item(at_end, attrs, |t| t.span.rust_2018());
unclosed_delims.append(&mut this.unclosed_delims);
item
})?;
@ -860,11 +834,12 @@ impl<'a> Parser<'a> {
Ok(item)
}
fn parse_trait_item_(
fn parse_assoc_item(
&mut self,
at_end: &mut bool,
mut attrs: Vec<Attribute>,
) -> PResult<'a, TraitItem> {
is_name_required: fn(&token::Token) -> bool,
) -> PResult<'a, AssocItem> {
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
@ -872,18 +847,13 @@ impl<'a> Parser<'a> {
self.parse_assoc_ty()?
} else if self.is_const_item() {
self.parse_assoc_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
// trait item macro.
(Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
} else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? {
(Ident::invalid(), AssocItemKind::Macro(mac), Generics::default())
} else {
// This is somewhat dubious; We don't want to allow
// param names to be left off if there is a definition...
//
// We don't allow param names to be left off in edition 2018.
self.parse_assoc_fn(at_end, &mut attrs, |t| t.span.rust_2018())?
self.parse_assoc_fn(at_end, &mut attrs, is_name_required)?
};
Ok(TraitItem {
Ok(AssocItem {
id: DUMMY_NODE_ID,
span: lo.to(self.prev_span),
ident: name,

View file

@ -18,10 +18,10 @@ trait A { //~ ERROR missing
trait B {
fn xxx() { ### } //~ ERROR expected
}
trait C { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration
trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration
L = M;
}
trait D { //~ ERROR missing `fn`, `type`, or `const` for trait-item declaration
trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration
Z = { 2 + 3 };
}
trait E {

View file

@ -1,4 +1,4 @@
error: missing `fn`, `type`, or `const` for impl-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:1:13
|
LL | impl dyn A {
@ -6,7 +6,7 @@ LL | impl dyn A {
LL | | Y
| |____^ missing `fn`, `type`, or `const`
error: missing `fn`, `type`, or `const` for trait-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:7:10
|
LL | trait X {
@ -14,7 +14,7 @@ LL | trait X {
LL | | X() {}
| |____^ missing `fn`, `type`, or `const`
error: missing `fn`, `type`, or `const` for trait-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:15:10
|
LL | trait A {
@ -28,7 +28,7 @@ error: expected `[`, found `#`
LL | fn xxx() { ### }
| ^ expected `[`
error: missing `fn`, `type`, or `const` for trait-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:21:10
|
LL | trait C {
@ -36,7 +36,7 @@ LL | trait C {
LL | | L = M;
| |____^ missing `fn`, `type`, or `const`
error: missing `fn`, `type`, or `const` for trait-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:24:10
|
LL | trait D {
@ -50,7 +50,7 @@ error: expected one of `!` or `::`, found `(`
LL | ::Y ();
| ^ expected one of `!` or `::`
error: missing `fn`, `type`, or `const` for impl-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-40006.rs:32:8
|
LL | pub hello_method(&self) {

View file

@ -1,4 +1,4 @@
error: missing `fn`, `type`, or `const` for trait-item declaration
error: missing `fn`, `type`, or `const` for associated-item declaration
--> $DIR/issue-21153.rs:1:29
|
LL | trait MyTrait<T>: Iterator {