diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 32cc156783cc..3fbdbb4cb224 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -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, Vec)> { + fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { 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, - ) -> 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, - ) -> 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, diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index b3c1f60b7ebf..ea21592997bf 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -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 { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 30ae6ed4c6d4..d1e995013cb9 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -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) { diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 70f55f0aeb9f..6e20a9ce3c43 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -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: Iterator {