diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-22 08:16:39 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-24 00:59:38 +0100 |
| commit | a05c83b2ebc4e85e32f723e708a40dbd3f165cd0 (patch) | |
| tree | 8a5fe4fb32c7968db725c058c3991bcd4a3cdfd0 /src/librustc_parse | |
| parent | a63f35daeefc4ae89ba5b6bd0323d97bb0d050e6 (diff) | |
| download | rust-a05c83b2ebc4e85e32f723e708a40dbd3f165cd0.tar.gz rust-a05c83b2ebc4e85e32f723e708a40dbd3f165cd0.zip | |
parse: use `parse_item_common` in `parse_assoc_item_`.
Diffstat (limited to 'src/librustc_parse')
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 216 |
1 files changed, 72 insertions, 144 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ecd2049963b..8c5add46bfc 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -5,12 +5,12 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; +use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; -use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; -use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; +use syntax::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; @@ -81,7 +81,7 @@ impl<'a> Parser<'a> { Some(item) }); - let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed)?; + let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; if let Some(ref item) = item { self.error_on_illegal_default(item.defaultness); } @@ -91,21 +91,25 @@ impl<'a> Parser<'a> { fn parse_item_common( &mut self, mut attrs: Vec<Attribute>, - macros_allowed: bool, - attributes_allowed: bool, + mac_allowed: bool, + attrs_allowed: bool, + req_name: ReqName, ) -> PResult<'a, Option<Item>> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis, &mut def)?; + let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?; if let Some((ident, kind)) = kind { - return Ok(Some(self.mk_item(lo, ident, kind, vis, def, attrs))); + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + let item = Item { ident, attrs, id, kind, vis, defaultness: def, span, tokens: None }; + return Ok(Some(item)); } // At this point, we have failed to parse an item. self.error_on_unmatched_vis(&vis); self.error_on_unmatched_defaultness(def); - if !attributes_allowed { + if !attrs_allowed { self.recover_attrs_no_item(&attrs)?; } Ok(None) @@ -151,6 +155,7 @@ impl<'a> Parser<'a> { lo: Span, vis: &Visibility, def: &mut Defaultness, + req_name: ReqName, ) -> PResult<'a, Option<ItemInfo>> { let info = if self.eat_keyword(kw::Use) { // USE ITEM @@ -159,7 +164,7 @@ impl<'a> Parser<'a> { (Ident::invalid(), ItemKind::Use(P(tree))) } else if self.check_fn_front_matter() { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; + let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, req_name)?; (ident, ItemKind::Fn(sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -367,23 +372,6 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Given this code `path(`, it seems like this is not - /// setting the visibility of a macro invocation, - /// but rather a mistyped method declaration. - /// Create a diagnostic pointing out that `fn` is missing. - /// - /// ``` - /// x | pub path(&self) { - /// | ^ missing `fn`, `type`, `const`, or `static` - /// ``` - fn missing_nested_item_kind_err(&self, prev_span: Span) -> DiagnosticBuilder<'a> { - let sp = prev_span.between(self.token.span); - let expected_kinds = "missing `fn`, `type`, `const`, or `static`"; - let mut err = self.struct_span_err(sp, &format!("{} for item declaration", expected_kinds)); - err.span_label(sp, expected_kinds); - err - } - /// Parses an implementation item. /// /// ``` @@ -457,8 +445,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let impl_items = - self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?; + let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item())?; let item_kind = match ty_second { Some(ty_second) => { @@ -517,7 +504,7 @@ impl<'a> Parser<'a> { fn parse_item_list<T>( &mut self, attrs: &mut Vec<Attribute>, - mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option<Option<T>>>, + mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>, ) -> PResult<'a, Vec<T>> { let open_brace_span = self.token.span; self.expect(&token::OpenDelim(token::Brace))?; @@ -528,8 +515,7 @@ impl<'a> Parser<'a> { if self.recover_doc_comment_before_brace() { continue; } - let mut at_end = false; - match parse_item(self, &mut at_end) { + match parse_item(self) { Ok(None) => { // We have to bail or we'll potentially never make progress. let non_item_span = self.token.span; @@ -543,11 +529,11 @@ impl<'a> Parser<'a> { } Ok(Some(item)) => items.extend(item), Err(mut err) => { - err.emit(); - if !at_end { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - break; - } + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + err.span_label(open_brace_span, "while parsing this item list starting here") + .span_label(self.prev_span, "the item list ends here") + .emit(); + break; } } } @@ -644,103 +630,69 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let items = self.parse_item_list(attrs, |p, at_end| { - p.parse_trait_item(at_end).map(Some).map(Some) - })?; + let items = self.parse_item_list(attrs, |p| p.parse_trait_item())?; Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> { - maybe_whole!(self, NtImplItem, |x| x); - self.parse_assoc_item(at_end, |_| true) + pub fn parse_impl_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> { + maybe_whole!(self, NtImplItem, |x| Some(Some(x))); + self.parse_assoc_item(|_| true) } - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, P<AssocItem>> { - maybe_whole!(self, NtTraitItem, |x| x); + pub fn parse_trait_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> { + maybe_whole!(self, NtTraitItem, |x| Some(Some(x))); // 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_item(at_end, |t| t.span.rust_2018()) + self.parse_assoc_item(|t| t.span.rust_2018()) } /// Parses associated items. - fn parse_assoc_item( - &mut self, - at_end: &mut bool, - req_name: ReqName, - ) -> PResult<'a, P<AssocItem>> { + fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option<Option<P<AssocItem>>>> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_assoc_item_(at_end, attrs, req_name); + let item = this.parse_assoc_item_(attrs, req_name); unclosed_delims.append(&mut this.unclosed_delims); item })?; self.unclosed_delims.append(&mut unclosed_delims); // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - self.error_on_assoc_static(&item); - Ok(P(item)) - } - - fn error_on_assoc_static(&self, item: &AssocItem) { - if let AssocItemKind::Static(..) = item.kind { - self.struct_span_err(item.span, "associated `static` items are not allowed").emit(); + if let Some(Some(item)) = &mut item { + if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { + item.tokens = Some(tokens); + } } + Ok(item) } fn parse_assoc_item_( &mut self, - at_end: &mut bool, - mut attrs: Vec<Attribute>, - req_name: ReqName, - ) -> PResult<'a, AssocItem> { - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - let defaultness = self.parse_defaultness(); - let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, req_name, &vis)?; - let span = lo.to(self.prev_span); - let id = DUMMY_NODE_ID; - Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) - } - - fn parse_assoc_item_kind( - &mut self, - at_end: &mut bool, - attrs: &mut Vec<Attribute>, + attrs: Vec<Attribute>, req_name: ReqName, - vis: &Visibility, - ) -> PResult<'a, (Ident, AssocItemKind)> { - if self.eat_keyword(kw::Type) { - match self.parse_type_alias()? { - (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))), - _ => unreachable!(), - } - } else if self.check_fn_front_matter() { - let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?; - Ok((ident, AssocItemKind::Fn(sig, generics, body))) - } else if self.is_static_global() { - self.bump(); // `static` - let mutbl = self.parse_mutability(); - let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - Ok((ident, AssocItemKind::Static(ty, mutbl, expr))) - } else if self.eat_keyword(kw::Const) { - let (ident, ty, expr) = self.parse_item_const_common(None)?; - Ok((ident, AssocItemKind::Const(ty, expr))) - } else if self.isnt_macro_invocation() { - Err(self.missing_nested_item_kind_err(self.prev_span)) - } else if self.token.is_path_start() { - let mac = self.parse_item_macro(&vis)?; - *at_end = true; - Ok((Ident::invalid(), AssocItemKind::Macro(mac))) - } else { - self.recover_attrs_no_item(attrs)?; - self.unexpected() - } + ) -> PResult<'a, Option<Option<P<AssocItem>>>> { + let it = self.parse_item_common(attrs, true, false, req_name)?; + Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { + let kind = match kind { + ItemKind::Mac(a) => AssocItemKind::Macro(a), + ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), + ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), + ItemKind::Const(a, c) => AssocItemKind::Const(a, c), + ItemKind::Static(a, _, b) => { + self.struct_span_err(span, "associated `static` items are not allowed").emit(); + AssocItemKind::Const(a, b) + } + _ => { + let span = self.sess.source_map().def_span(span); + self.struct_span_err(span, "item kind not supported in `trait` or `impl`") + .emit(); + return None; + } + }; + Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) + })) } /// Parses a `type` alias with the following grammar: @@ -907,7 +859,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_item_foreign_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?; let module = ast::ForeignMod { abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } @@ -917,17 +869,17 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); let attrs = self.parse_outer_attributes()?; - let it = self.parse_item_common(attrs, true, false)?; + let it = self.parse_item_common(attrs, true, false, |_| true)?; Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { self.error_on_illegal_default(defaultness); let kind = match kind { - ItemKind::Mac(a) => AssocItemKind::Macro(a), - ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), - ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), - ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c), + ItemKind::Mac(a) => ForeignItemKind::Macro(a), + ItemKind::Fn(a, b, c) => ForeignItemKind::Fn(a, b, c), + ItemKind::TyAlias(a, b, c) => ForeignItemKind::TyAlias(a, b, c), + ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), ItemKind::Const(a, b) => { self.error_on_foreign_const(span, ident); - AssocItemKind::Static(a, Mutability::Not, b) + ForeignItemKind::Static(a, Mutability::Not, b) } _ => { let span = self.sess.source_map().def_span(span); @@ -989,22 +941,6 @@ impl<'a> Parser<'a> { /// /// When `m` is `"const"`, `$ident` may also be `"_"`. fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> { - let (id, ty, expr) = self.parse_item_const_common(m)?; - let item = match m { - Some(m) => ItemKind::Static(ty, m, expr), - None => ItemKind::Const(ty, expr), - }; - Ok((id, item)) - } - - /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with - /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. - /// - /// When `m` is `"const"`, `$ident` may also be `"_"`. - fn parse_item_const_common( - &mut self, - m: Option<Mutability>, - ) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; // Parse the type of a `const` or `static mut?` item. @@ -1017,7 +953,12 @@ impl<'a> Parser<'a> { let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - Ok((id, ty, expr)) + + let item = match m { + Some(m) => ItemKind::Static(ty, m, expr), + None => ItemKind::Const(ty, expr), + }; + Ok((id, item)) } /// We were supposed to parse `:` but the `:` was missing. @@ -1477,19 +1418,6 @@ impl<'a> Parser<'a> { } Ok(true) } - - fn mk_item<K>( - &self, - lo: Span, - ident: Ident, - kind: K, - vis: Visibility, - defaultness: Defaultness, - attrs: Vec<Attribute>, - ) -> Item<K> { - let span = lo.to(self.prev_span); - Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, defaultness, span, tokens: None } - } } /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). |
