use super::{Parser, PResult, PathStyle}; use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim}; use crate::maybe_whole; use crate::ptr::P; use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, AnonConst, Item, ItemKind}; use crate::ast::{ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; use crate::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness}; use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField}; use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param}; use crate::parse::token; use crate::tokenstream::{TokenTree, TokenStream}; use crate::symbol::{kw, sym}; use crate::source_map::{self, respan, Span}; use crate::ThinVec; use log::debug; use std::mem; use rustc_target::spec::abi::Abi; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey}; use syntax_pos::BytePos; /// Whether the type alias or associated type is a concrete type or an opaque type. #[derive(Debug)] pub(super) enum AliasKind { /// Just a new name for the same type. Weak(P), /// Only trait impls of the type will be usable, not the actual type itself. OpaqueTy(GenericBounds), } pub(super) type ItemInfo = (Ident, ItemKind, Option>); impl<'a> Parser<'a> { pub fn parse_item(&mut self) -> PResult<'a, Option>> { let attrs = self.parse_outer_attributes()?; self.parse_item_(attrs, true, false) } pub(super) fn parse_item_( &mut self, attrs: Vec, macros_allowed: bool, attributes_allowed: bool, ) -> PResult<'a, Option>> { let mut unclosed_delims = vec![]; let (ret, tokens) = self.collect_tokens(|this| { let item = this.parse_item_implementation(attrs, macros_allowed, attributes_allowed); unclosed_delims.append(&mut this.unclosed_delims); item })?; self.unclosed_delims.append(&mut unclosed_delims); // Once we've parsed an item and recorded the tokens we got while // parsing we may want to store `tokens` into the item we're about to // return. Note, though, that we specifically didn't capture tokens // related to outer attributes. The `tokens` field here may later be // used with procedural macros to convert this item back into a token // stream, but during expansion we may be removing attributes as we go // along. // // If we've got inner attributes then the `tokens` we've got above holds // these inner attributes. If an inner attribute is expanded we won't // actually remove it from the token stream, so we'll just keep yielding // it (bad!). To work around this case for now we just avoid recording // `tokens` if we detect any inner attributes. This should help keep // expansion correct, but we should fix this bug one day! Ok(ret.map(|item| { item.map(|mut i| { if !i.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { i.tokens = Some(tokens); } i }) })) } /// Parses one of the items allowed by the flags. fn parse_item_implementation( &mut self, attrs: Vec, macros_allowed: bool, attributes_allowed: bool, ) -> PResult<'a, Option>> { maybe_whole!(self, NtItem, |item| { let mut item = item.into_inner(); let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs); Some(P(item)) }); let lo = self.token.span; let vis = self.parse_visibility(false)?; if self.eat_keyword(kw::Use) { // USE ITEM let item_ = ItemKind::Use(P(self.parse_use_tree()?)); self.expect_semi()?; let span = lo.to(self.prev_span); let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs); return Ok(Some(item)); } if self.eat_keyword(kw::Extern) { let extern_sp = self.prev_span; if self.eat_keyword(kw::Crate) { return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } let opt_abi = self.parse_opt_abi()?; if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM let fn_span = self.prev_span; let header = FnHeader { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), abi: opt_abi.unwrap_or(Abi::C), }; return self.parse_item_fn(lo, vis, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { return Ok(Some( self.parse_item_foreign_mod(lo, opt_abi, vis, attrs, extern_sp)?, )); } self.unexpected()?; } if self.is_static_global() { self.bump(); // STATIC ITEM let m = self.parse_mutability(); let info = self.parse_item_const(Some(m))?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.eat_keyword(kw::Const) { let const_span = self.prev_span; if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) { // CONST FUNCTION ITEM let unsafety = self.parse_unsafety(); if self.check_keyword(kw::Extern) { self.sess.gated_spans.const_extern_fn.borrow_mut().push( lo.to(self.token.span) ); } let abi = self.parse_extern_abi()?; self.bump(); // `fn` let header = FnHeader { unsafety, asyncness: respan(const_span, IsAsync::NotAsync), constness: respan(const_span, Constness::Const), abi, }; return self.parse_item_fn(lo, vis, attrs, header); } // CONST ITEM if self.eat_keyword(kw::Mut) { let prev_span = self.prev_span; self.struct_span_err(prev_span, "const globals cannot be mutable") .span_label(prev_span, "cannot be mutable") .span_suggestion( const_span, "you might want to declare a static instead", "static".to_owned(), Applicability::MaybeIncorrect, ) .emit(); } let info = self.parse_item_const(None)?; return self.mk_item_with_info(attrs, lo, vis, info); } // Parses `async unsafe? fn`. if self.check_keyword(kw::Async) { let async_span = self.token.span; if self.is_keyword_ahead(1, &[kw::Fn]) || self.is_keyword_ahead(2, &[kw::Fn]) { // ASYNC FUNCTION ITEM self.bump(); // `async` let unsafety = self.parse_unsafety(); // `unsafe`? self.expect_keyword(kw::Fn)?; // `fn` let fn_span = self.prev_span; let asyncness = respan(async_span, IsAsync::Async { closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID, }); self.ban_async_in_2015(async_span); let header = FnHeader { unsafety, asyncness, constness: respan(fn_span, Constness::NotConst), abi: Abi::Rust, }; return self.parse_item_fn(lo, vis, attrs, header); } } if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { // UNSAFE TRAIT ITEM self.bump(); // `unsafe` let info = self.parse_item_trait(lo, Unsafety::Unsafe)?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { // IMPL ITEM let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; let info = self.parse_item_impl(unsafety, defaultness)?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Fn) { // FUNCTION ITEM self.bump(); let fn_span = self.prev_span; let header = FnHeader { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), abi: Abi::Rust, }; return self.parse_item_fn(lo, vis, attrs, header); } if self.check_keyword(kw::Unsafe) && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { // UNSAFE FUNCTION ITEM self.bump(); // `unsafe` // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. self.check(&token::OpenDelim(token::Brace)); let abi = self.parse_extern_abi()?; self.expect_keyword(kw::Fn)?; let fn_span = self.prev_span; let header = FnHeader { unsafety: Unsafety::Unsafe, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), abi, }; return self.parse_item_fn(lo, vis, attrs, header); } if self.eat_keyword(kw::Mod) { // MODULE ITEM let info = self.parse_item_mod(&attrs[..])?; return self.mk_item_with_info(attrs, lo, vis, info); } if let Some(type_) = self.eat_type() { let (ident, alias, generics) = type_?; // TYPE ITEM let item_ = match alias { AliasKind::Weak(ty) => ItemKind::TyAlias(ty, generics), AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics), }; let span = lo.to(self.prev_span); return Ok(Some(self.mk_item(span, ident, item_, vis, attrs))); } if self.eat_keyword(kw::Enum) { // ENUM ITEM let info = self.parse_item_enum()?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM let info = self.parse_item_trait(lo, Unsafety::Normal)?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.eat_keyword(kw::Struct) { // STRUCT ITEM let info = self.parse_item_struct()?; return self.mk_item_with_info(attrs, lo, vis, info); } if self.is_union_item() { // UNION ITEM self.bump(); let info = self.parse_item_union()?; return self.mk_item_with_info(attrs, lo, vis, info); } if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? { return Ok(Some(macro_def)); } // Verify whether we have encountered a struct or method definition where the user forgot to // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { // Space between `pub` keyword and the identifier // // pub S {} // ^^^ `sp` points here let sp = self.prev_span.between(self.token.span); let full_sp = self.prev_span.to(self.token.span); let ident_sp = self.token.span; if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { // possible public struct definition where `struct` was forgotten let ident = self.parse_ident().unwrap(); let msg = format!("add `struct` here to parse `{}` as a public struct", ident); let mut err = self.diagnostic() .struct_span_err(sp, "missing `struct` for struct definition"); err.span_suggestion_short( sp, &msg, " struct ".into(), Applicability::MaybeIncorrect // speculative ); return Err(err); } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { let ident = self.parse_ident().unwrap(); self.bump(); // `(` let kw_name = self.recover_first_param(); self.consume_block(token::Paren, ConsumeClosingDelim::Yes); let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); self.bump(); // `{` ("fn", kw_name, false) } else if self.check(&token::OpenDelim(token::Brace)) { self.bump(); // `{` ("fn", kw_name, false) } else if self.check(&token::Colon) { let kw = "struct"; (kw, kw, false) } else { ("fn` or `struct", "function or struct", true) }; let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); if !ambiguous { self.consume_block(token::Brace, ConsumeClosingDelim::Yes); let suggestion = format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); err.span_suggestion_short( sp, &suggestion, format!(" {} ", kw), Applicability::MachineApplicable ); } else { if let Ok(snippet) = self.span_to_snippet(ident_sp) { err.span_suggestion( full_sp, "if you meant to call a macro, try", format!("{}!", snippet), // this is the `ambiguous` conditional branch Applicability::MaybeIncorrect ); } else { err.help("if you meant to call a macro, remove the `pub` \ and add a trailing `!` after the identifier"); } } return Err(err); } else if self.look_ahead(1, |t| *t == token::Lt) { let ident = self.parse_ident().unwrap(); self.eat_to_tokens(&[&token::Gt]); self.bump(); // `>` let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { ("fn", self.recover_first_param(), false) } else if self.check(&token::OpenDelim(token::Brace)) { ("struct", "struct", false) } else { ("fn` or `struct", "function or struct", true) }; let msg = format!("missing `{}` for {} definition", kw, kw_name); let mut err = self.diagnostic().struct_span_err(sp, &msg); if !ambiguous { err.span_suggestion_short( sp, &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), format!(" {} ", kw), Applicability::MachineApplicable, ); } return Err(err); } } self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) } pub(super) fn mk_item_with_info( &self, attrs: Vec, lo: Span, vis: Visibility, info: ItemInfo, ) -> PResult<'a, Option>> { let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); let attrs = Self::maybe_append(attrs, extra_attrs); Ok(Some(self.mk_item(span, ident, item, vis, attrs))) } fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { if let Some(ref mut rhs) = rhs { lhs.append(rhs); } lhs } /// This is the fall-through for parsing items. fn parse_macro_use_or_failure( &mut self, attrs: Vec , macros_allowed: bool, attributes_allowed: bool, lo: Span, visibility: Visibility ) -> PResult<'a, Option>> { if macros_allowed && self.token.is_path_start() && !(self.is_async_fn() && self.token.span.rust_2015()) { // MACRO INVOCATION ITEM let prev_span = self.prev_span; self.complain_if_pub_macro(&visibility.node, prev_span); let mac_lo = self.token.span; // Item macro let path = self.parse_path(PathStyle::Mod)?; self.expect(&token::Not)?; let (delim, tts) = self.expect_delimited_token_tree()?; if delim != MacDelimiter::Brace && !self.eat(&token::Semi) { self.report_invalid_macro_expansion_item(); } let hi = self.prev_span; let mac = Mac { path, tts, delim, span: mac_lo.to(hi), prior_type_ascription: self.last_type_ascription, }; let item = self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); return Ok(Some(item)); } // FAILURE TO PARSE ITEM match visibility.node { VisibilityKind::Inherited => {} _ => { return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`")); } } if !attributes_allowed && !attrs.is_empty() { self.expected_item_err(&attrs)?; } Ok(None) } /// Emits an expected-item-after-attributes error. fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { let message = match attrs.last() { Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment", _ => "expected item after attributes", }; let mut err = self.diagnostic().struct_span_err(self.prev_span, message); if attrs.last().unwrap().is_sugared_doc { err.span_label(self.prev_span, "this doc comment doesn't document anything"); } Err(err) } pub(super) fn is_async_fn(&self) -> bool { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>, at_end: &mut bool) -> PResult<'a, Option> { if self.token.is_path_start() && !(self.is_async_fn() && self.token.span.rust_2015()) { let prev_span = self.prev_span; let lo = self.token.span; let path = self.parse_path(PathStyle::Mod)?; if path.segments.len() == 1 { if !self.eat(&token::Not) { return Err(self.missing_assoc_item_kind_err(item_kind, prev_span)); } } else { self.expect(&token::Not)?; } if let Some(vis) = vis { self.complain_if_pub_macro(&vis.node, prev_span); } *at_end = true; // eat a matched-delimiter token tree: let (delim, tts) = self.expect_delimited_token_tree()?; if delim != MacDelimiter::Brace { self.expect_semi()?; } Ok(Some(Mac { path, tts, delim, span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, })) } else { Ok(None) } } fn missing_assoc_item_kind_err(&self, item_type: &str, prev_span: Span) -> DiagnosticBuilder<'a> { let expected_kinds = if item_type == "extern" { "missing `fn`, `type`, or `static`" } else { "missing `fn`, `type`, or `const`" }; // 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`, or `const` // pub path( // ^^ `sp` below will point to this let sp = prev_span.between(self.prev_span); let mut err = self.diagnostic().struct_span_err( sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); err.span_label(sp, expected_kinds); err } /// Parses an implementation item, `impl` keyword is already parsed. /// /// impl<'a, T> TYPE { /* impl items */ } /// impl<'a, T> TRAIT for TYPE { /* impl items */ } /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } /// /// We actually parse slightly more relaxed grammar for better error reporting and recovery. /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}` /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}` fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness) -> PResult<'a, ItemInfo> { // First, parse generic parameters if necessary. let mut generics = if self.choose_generics_over_qpath() { self.parse_generics()? } else { Generics::default() }; // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) { self.bump(); // `!` ast::ImplPolarity::Negative } else { ast::ImplPolarity::Positive }; // Parse both types and traits as a type, then reinterpret if necessary. let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span)); let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt) { let span = self.prev_span.between(self.token.span); self.struct_span_err(span, "missing trait in a trait impl").emit(); P(Ty { kind: TyKind::Path(None, err_path(span)), span, id: DUMMY_NODE_ID }) } else { self.parse_ty()? }; // If `for` is missing we try to recover. let has_for = self.eat_keyword(kw::For); let missing_for_span = self.prev_span.between(self.token.span); let ty_second = if self.token == token::DotDot { // We need to report this error after `cfg` expansion for compatibility reasons self.bump(); // `..`, do not add it to expected tokens Some(self.mk_ty(self.prev_span, TyKind::Err)) } else if has_for || self.token.can_begin_type() { Some(self.parse_ty()?) } else { None }; generics.where_clause = self.parse_where_clause()?; let (impl_items, attrs) = self.parse_impl_body()?; let item_kind = match ty_second { Some(ty_second) => { // impl Trait for Type if !has_for { self.struct_span_err(missing_for_span, "missing `for` in a trait impl") .span_suggestion_short( missing_for_span, "add `for` here", " for ".to_string(), Applicability::MachineApplicable, ).emit(); } let ty_first = ty_first.into_inner(); let path = match ty_first.kind { // This notably includes paths passed through `ty` macro fragments (#46438). TyKind::Path(None, path) => path, _ => { self.span_err(ty_first.span, "expected a trait, found type"); err_path(ty_first.span) } }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; ItemKind::Impl(unsafety, polarity, defaultness, generics, Some(trait_ref), ty_second, impl_items) } None => { // impl Type ItemKind::Impl(unsafety, polarity, defaultness, generics, None, ty_first, impl_items) } }; Ok((Ident::invalid(), item_kind, Some(attrs))) } fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { self.expect(&token::OpenDelim(token::Brace))?; let attrs = self.parse_inner_attributes()?; let mut impl_items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { let mut at_end = false; match self.parse_impl_item(&mut at_end) { Ok(impl_item) => impl_items.push(impl_item), Err(mut err) => { err.emit(); if !at_end { self.consume_block(token::Brace, ConsumeClosingDelim::Yes); break; } } } } Ok((impl_items, attrs)) } /// Parses an impl item. pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { 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); 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); } 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(false)?; let defaultness = self.parse_defaultness(); let (name, kind, generics) = if let Some(type_) = self.eat_type() { let (name, alias, generics) = type_?; let kind = match alias { AliasKind::Weak(typ) => ast::ImplItemKind::TyAlias(typ), AliasKind::OpaqueTy(bounds) => ast::ImplItemKind::OpaqueTy(bounds), }; (name, kind, generics) } else if self.is_const_item() { self.parse_impl_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 { let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?; attrs.extend(inner_attrs); (name, kind, generics) }; Ok(ImplItem { id: DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, vis, defaultness, attrs, generics, kind, tokens: None, }) } /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { // `pub` is included for better error messages if self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[ kw::Impl, kw::Const, kw::Async, kw::Fn, kw::Unsafe, kw::Extern, kw::Type, kw::Pub, ]) { self.bump(); // `default` Defaultness::Default } else { Defaultness::Final } } /// Returns `true` if we are looking at `const ID` /// (returns `false` for things like `const fn`, etc.). fn is_const_item(&self) -> bool { self.token.is_keyword(kw::Const) && !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } /// This parses the grammar: /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { self.expect_keyword(kw::Const)?; let name = self.parse_ident()?; self.expect(&token::Colon)?; let typ = self.parse_ty()?; self.expect(&token::Eq)?; let expr = self.parse_expr()?; self.expect_semi()?; Ok((name, ImplItemKind::Const(typ, expr), Generics::default())) } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; self.expect_keyword(kw::Trait)?; let ident = self.parse_ident()?; let mut tps = self.parse_generics()?; // Parse optional colon and supertrait bounds. let had_colon = self.eat(&token::Colon); let span_at_colon = self.prev_span; let bounds = if had_colon { self.parse_generic_bounds(Some(self.prev_span))? } else { Vec::new() }; let span_before_eq = self.prev_span; if self.eat(&token::Eq) { // It's a trait alias. if had_colon { let span = span_at_colon.to(span_before_eq); self.struct_span_err(span, "bounds are not allowed on trait aliases") .emit(); } let bounds = self.parse_generic_bounds(None)?; tps.where_clause = self.parse_where_clause()?; self.expect_semi()?; let whole_span = lo.to(self.prev_span); if is_auto == IsAuto::Yes { let msg = "trait aliases cannot be `auto`"; self.struct_span_err(whole_span, msg) .span_label(whole_span, msg) .emit(); } if unsafety != Unsafety::Normal { let msg = "trait aliases cannot be `unsafe`"; self.struct_span_err(whole_span, msg) .span_label(whole_span, msg) .emit(); } self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span); Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; self.expect(&token::OpenDelim(token::Brace))?; let mut trait_items = vec![]; while !self.eat(&token::CloseDelim(token::Brace)) { if let token::DocComment(_) = self.token.kind { if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { self.diagnostic().struct_span_err_with_code( self.token.span, "found a documentation comment that doesn't document anything", DiagnosticId::Error("E0584".into()), ) .help( "doc comments must come before what they document, maybe a \ comment was intended with `//`?", ) .emit(); self.bump(); continue; } } let mut at_end = false; match self.parse_trait_item(&mut at_end) { Ok(item) => trait_items.push(item), Err(mut e) => { e.emit(); if !at_end { self.consume_block(token::Brace, ConsumeClosingDelim::Yes); break; } } } } Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) } } /// Parses the items in a trait declaration. pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { 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); 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); } Ok(item) } fn parse_trait_item_( &mut self, at_end: &mut bool, mut attrs: Vec, ) -> PResult<'a, TraitItem> { let lo = self.token.span; self.eat_bad_pub(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { self.parse_trait_item_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 { self.parse_trait_item_method(at_end, &mut attrs)? }; Ok(TraitItem { id: DUMMY_NODE_ID, ident: name, attrs, generics, kind, span: lo.to(self.prev_span), tokens: None, }) } fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; let default = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; Ok((ident, TraitItemKind::Const(ty, default), Generics::default())) } /// Parses the following grammar: /// /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() }; generics.where_clause = self.parse_where_clause()?; let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; Ok((ident, TraitItemKind::Type(bounds, default), generics)) } /// Parses a `UseTree`. /// /// ``` /// USE_TREE = [`::`] `*` | /// [`::`] `{` USE_TREE_LIST `}` | /// PATH `::` `*` | /// PATH `::` `{` USE_TREE_LIST `}` | /// PATH [`as` IDENT] /// ``` fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { let lo = self.token.span; let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() }; let kind = if self.check(&token::OpenDelim(token::Brace)) || self.check(&token::BinOp(token::Star)) || self.is_import_coupler() { // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` let mod_sep_ctxt = self.token.span.ctxt(); if self.eat(&token::ModSep) { prefix.segments.push( PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) ); } self.parse_use_tree_glob_or_nested()? } else { // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` prefix = self.parse_path(PathStyle::Mod)?; if self.eat(&token::ModSep) { self.parse_use_tree_glob_or_nested()? } else { UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID) } }; Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) }) } /// Parses `*` or `{...}`. fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> { Ok(if self.eat(&token::BinOp(token::Star)) { UseTreeKind::Glob } else { UseTreeKind::Nested(self.parse_use_tree_list()?) }) } /// Parses a `UseTreeKind::Nested(list)`. /// /// ``` /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { self.parse_delim_comma_seq(token::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID))) .map(|(r, _)| r) } fn parse_rename(&mut self) -> PResult<'a, Option> { if self.eat_keyword(kw::As) { self.parse_ident_or_underscore().map(Some) } else { Ok(None) } } fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token.kind { token::Ident(name, false) if name == kw::Underscore => { let span = self.token.span; self.bump(); Ok(Ident::new(name, span)) } _ => self.parse_ident(), } } /// Parses `extern crate` links. /// /// # Examples /// /// ``` /// extern crate foo; /// extern crate bar as foo; /// ``` fn parse_item_extern_crate( &mut self, lo: Span, visibility: Visibility, attrs: Vec ) -> PResult<'a, P> { // Accept `extern crate name-like-this` for better diagnostics let orig_name = self.parse_crate_name_with_dashes()?; let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { (rename, Some(orig_name.name)) } else { (orig_name, None) }; self.expect_semi()?; let span = lo.to(self.prev_span); Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { let error_msg = "crate name using dashes are not valid in `extern crate` statements"; let suggestion_msg = "if the original crate name uses dashes you need to use underscores \ in the code"; let mut ident = if self.token.is_keyword(kw::SelfLower) { self.parse_path_segment_ident() } else { self.parse_ident() }?; let mut idents = vec![]; let mut replacement = vec![]; let mut fixed_crate_name = false; // Accept `extern crate name-like-this` for better diagnostics. let dash = token::BinOp(token::BinOpToken::Minus); if self.token == dash { // Do not include `-` as part of the expected tokens list. while self.eat(&dash) { fixed_crate_name = true; replacement.push((self.prev_span, "_".to_string())); idents.push(self.parse_ident()?); } } if fixed_crate_name { let fixed_name_sp = ident.span.to(idents.last().unwrap().span); let mut fixed_name = format!("{}", ident.name); for part in idents { fixed_name.push_str(&format!("_{}", part.name)); } ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp); self.struct_span_err(fixed_name_sp, error_msg) .span_label(fixed_name_sp, "dash-separated idents are not valid") .multipart_suggestion(suggestion_msg, replacement, Applicability::MachineApplicable) .emit(); } Ok(ident) } /// Parses `extern` for foreign ABIs modules. /// /// `extern` is expected to have been /// consumed before calling this method. /// /// # Examples /// /// ```ignore (only-for-syntax-highlight) /// extern "C" {} /// extern {} /// ``` fn parse_item_foreign_mod( &mut self, lo: Span, opt_abi: Option, visibility: Visibility, mut attrs: Vec, extern_sp: Span, ) -> PResult<'a, P> { self.expect(&token::OpenDelim(token::Brace))?; let abi = opt_abi.unwrap_or(Abi::C); attrs.extend(self.parse_inner_attributes()?); let mut foreign_items = vec![]; while !self.eat(&token::CloseDelim(token::Brace)) { foreign_items.push(self.parse_foreign_item(extern_sp)?); } let prev_span = self.prev_span; let m = ast::ForeignMod { abi, items: foreign_items }; let invalid = Ident::invalid(); Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) } /// Parses a foreign item. pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, ForeignItem> { maybe_whole!(self, NtForeignItem, |ni| ni); let attrs = self.parse_outer_attributes()?; let lo = self.token.span; let visibility = self.parse_visibility(false)?; // FOREIGN STATIC ITEM // Treat `const` as `static` for error recovery, but don't add it to expected tokens. if self.check_keyword(kw::Static) || self.token.is_keyword(kw::Const) { if self.token.is_keyword(kw::Const) { let mut err = self .struct_span_err(self.token.span, "extern items cannot be `const`"); // The user wrote 'const fn' if self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) { err.emit(); // Consume `const` self.bump(); // Consume `unsafe` if present, since `extern` blocks // don't allow it. This will leave behind a plain 'fn' self.eat_keyword(kw::Unsafe); // Treat 'const fn` as a plain `fn` for error recovery purposes. // We've already emitted an error, so compilation is guaranteed // to fail return Ok(self.parse_item_foreign_fn(visibility, lo, attrs, extern_sp)?); } err.span_suggestion( self.token.span, "try using a static value", "static".to_owned(), Applicability::MachineApplicable ); err.emit(); } self.bump(); // `static` or `const` return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?); } // FOREIGN FUNCTION ITEM if self.check_keyword(kw::Fn) { return Ok(self.parse_item_foreign_fn(visibility, lo, attrs, extern_sp)?); } // FOREIGN TYPE ITEM if self.check_keyword(kw::Type) { return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?); } match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? { Some(mac) => { Ok( ForeignItem { ident: Ident::invalid(), span: lo.to(self.prev_span), id: DUMMY_NODE_ID, attrs, vis: visibility, kind: ForeignItemKind::Macro(mac), } ) } None => { if !attrs.is_empty() { self.expected_item_err(&attrs)?; } self.unexpected() } } } /// Parses a static item from a foreign module. /// Assumes that the `static` keyword is already parsed. fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec) -> PResult<'a, ForeignItem> { let mutbl = self.parse_mutability(); let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; let hi = self.token.span; self.expect_semi()?; Ok(ForeignItem { ident, attrs, kind: ForeignItemKind::Static(ty, mutbl), id: DUMMY_NODE_ID, span: lo.to(hi), vis, }) } /// Parses a type from a foreign module. fn parse_item_foreign_type(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec) -> PResult<'a, ForeignItem> { self.expect_keyword(kw::Type)?; let ident = self.parse_ident()?; let hi = self.token.span; self.expect_semi()?; Ok(ast::ForeignItem { ident, attrs, kind: ForeignItemKind::Ty, id: DUMMY_NODE_ID, span: lo.to(hi), vis }) } fn is_static_global(&mut self) -> bool { if self.check_keyword(kw::Static) { // Check if this could be a closure. !self.look_ahead(1, |token| { if token.is_keyword(kw::Move) { return true; } match token.kind { token::BinOp(token::Or) | token::OrOr => true, _ => false, } }) } else { false } } /// 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(&mut self, m: Option) -> PResult<'a, ItemInfo> { 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. // That is, the `":" $ty` fragment. let ty = if self.token == token::Eq { self.recover_missing_const_type(id, m) } else { // Not `=` so expect `":"" $ty` as usual. self.expect(&token::Colon)?; self.parse_ty()? }; self.expect(&token::Eq)?; let e = self.parse_expr()?; self.expect_semi()?; let item = match m { Some(m) => ItemKind::Static(ty, m, e), None => ItemKind::Const(ty, e), }; Ok((id, item, None)) } /// We were supposed to parse `:` but instead, we're already at `=`. /// This means that the type is missing. fn recover_missing_const_type(&mut self, id: Ident, m: Option) -> P { // Construct the error and stash it away with the hope // that typeck will later enrich the error with a type. let kind = match m { Some(Mutability::Mutable) => "static mut", Some(Mutability::Immutable) => "static", None => "const", }; let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind)); err.span_suggestion( id.span, "provide a type for the item", format!("{}: ", id), Applicability::HasPlaceholders, ); err.stash(id.span, StashKey::ItemNoType); // The user intended that the type be inferred, // so treat this as if the user wrote e.g. `const A: _ = expr;`. P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID, }) } /// Parses `type Foo = Bar;` or returns `None` /// without modifying the parser state. fn eat_type(&mut self) -> Option> { // This parses the grammar: // Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";" if self.eat_keyword(kw::Type) { Some(self.parse_type_alias()) } else { None } } /// Parses a type alias or opaque type. fn parse_type_alias(&mut self) -> PResult<'a, (Ident, AliasKind, Generics)> { let ident = self.parse_ident()?; let mut tps = self.parse_generics()?; tps.where_clause = self.parse_where_clause()?; self.expect(&token::Eq)?; let alias = if self.check_keyword(kw::Impl) { self.bump(); let bounds = self.parse_generic_bounds(Some(self.prev_span))?; AliasKind::OpaqueTy(bounds) } else { let ty = self.parse_ty()?; AliasKind::Weak(ty) }; self.expect_semi()?; Ok((ident, alias, tps)) } /// Parses an enum declaration. fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { let id = self.parse_ident()?; let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; self.expect(&token::OpenDelim(token::Brace))?; let enum_definition = self.parse_enum_def(&generics).map_err(|e| { self.recover_stmt(); self.eat(&token::CloseDelim(token::Brace)); e })?; Ok((id, ItemKind::Enum(enum_definition, generics), None)) } /// Parses the part of an enum declaration following the `{`. fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> { let mut variants = Vec::new(); while self.token != token::CloseDelim(token::Brace) { let variant_attrs = self.parse_outer_attributes()?; let vlo = self.token.span; self.eat_bad_pub(); let ident = self.parse_ident()?; let struct_def = if self.check(&token::OpenDelim(token::Brace)) { // Parse a struct variant. let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) } else if self.check(&token::OpenDelim(token::Paren)) { VariantData::Tuple( self.parse_tuple_struct_body()?, DUMMY_NODE_ID, ) } else { VariantData::Unit(DUMMY_NODE_ID) }; let disr_expr = if self.eat(&token::Eq) { Some(AnonConst { id: DUMMY_NODE_ID, value: self.parse_expr()?, }) } else { None }; let vr = ast::Variant { ident, id: DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, disr_expr, span: vlo.to(self.prev_span), is_placeholder: false, }; variants.push(vr); if !self.eat(&token::Comma) { if self.token.is_ident() && !self.token.is_reserved_ident() { let sp = self.sess.source_map().next_point(self.prev_span); self.struct_span_err(sp, "missing comma") .span_suggestion_short( sp, "missing comma", ",".to_owned(), Applicability::MaybeIncorrect, ) .emit(); } else { break; } } } self.expect(&token::CloseDelim(token::Brace))?; Ok(ast::EnumDef { variants }) } /// Parses `struct Foo { ... }`. fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { let class_name = self.parse_ident()?; let mut generics = self.parse_generics()?; // There is a special case worth noting here, as reported in issue #17904. // If we are parsing a tuple struct it is the case that the where clause // should follow the field list. Like so: // // struct Foo(T) where T: Copy; // // If we are parsing a normal record-style struct it is the case // that the where clause comes before the body, and after the generics. // So if we look ahead and see a brace or a where-clause we begin // parsing a record style struct. // // Otherwise if we look ahead and see a paren we parse a tuple-style // struct. let vdata = if self.token.is_keyword(kw::Where) { generics.where_clause = self.parse_where_clause()?; if self.eat(&token::Semi) { // If we see a: `struct Foo where T: Copy;` style decl. VariantData::Unit(DUMMY_NODE_ID) } else { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { VariantData::Unit(DUMMY_NODE_ID) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID); generics.where_clause = self.parse_where_clause()?; self.expect_semi()?; body } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( "expected `where`, `{{`, `(`, or `;` after struct name, found {}", token_str )); err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name"); return Err(err); }; Ok((class_name, ItemKind::Struct(vdata, generics), None)) } /// Parses `union Foo { ... }`. fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { let class_name = self.parse_ident()?; let mut generics = self.parse_generics()?; let vdata = if self.token.is_keyword(kw::Where) { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; VariantData::Struct(fields, recovered) } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( "expected `where` or `{{` after union name, found {}", token_str)); err.span_label(self.token.span, "expected `where` or `{` after union name"); return Err(err); }; Ok((class_name, ItemKind::Union(vdata, generics), None)) } pub(super) fn is_union_item(&self) -> bool { self.token.is_keyword(kw::Union) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec, /* recovered */ bool)> { let mut fields = Vec::new(); let mut recovered = false; if self.eat(&token::OpenDelim(token::Brace)) { while self.token != token::CloseDelim(token::Brace) { let field = self.parse_struct_decl_field().map_err(|e| { self.consume_block(token::Brace, ConsumeClosingDelim::No); recovered = true; e }); match field { Ok(field) => fields.push(field), Err(mut err) => { err.emit(); break; } } } self.eat(&token::CloseDelim(token::Brace)); } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( "expected `where`, or `{{` after struct name, found {}", token_str)); err.span_label(self.token.span, "expected `where`, or `{` after struct name"); return Err(err); } Ok((fields, recovered)) } fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec> { // This is the case where we find `struct Foo(T) where T: Copy;` // Unit like structs are handled in parse_item_struct function self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; let lo = p.token.span; let vis = p.parse_visibility(true)?; let ty = p.parse_ty()?; Ok(StructField { span: lo.to(ty.span), vis, ident: None, id: DUMMY_NODE_ID, ty, attrs, is_placeholder: false, }) }).map(|(r, _)| r) } /// Parses an element of a struct declaration. fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; let vis = self.parse_visibility(false)?; self.parse_single_struct_field(lo, vis, attrs) } /// Parses a structure field declaration. fn parse_single_struct_field(&mut self, lo: Span, vis: Visibility, attrs: Vec ) -> PResult<'a, StructField> { let mut seen_comma: bool = false; let a_var = self.parse_name_and_ty(lo, vis, attrs)?; if self.token == token::Comma { seen_comma = true; } match self.token.kind { token::Comma => { self.bump(); } token::CloseDelim(token::Brace) => {} token::DocComment(_) => { let previous_span = self.prev_span; let mut err = self.span_fatal_err(self.token.span, Error::UselessDocComment); self.bump(); // consume the doc comment let comma_after_doc_seen = self.eat(&token::Comma); // `seen_comma` is always false, because we are inside doc block // condition is here to make code more readable if seen_comma == false && comma_after_doc_seen == true { seen_comma = true; } if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) { err.emit(); } else { if seen_comma == false { let sp = self.sess.source_map().next_point(previous_span); err.span_suggestion( sp, "missing comma here", ",".into(), Applicability::MachineApplicable ); } return Err(err); } } _ => { let sp = self.sess.source_map().next_point(self.prev_span); let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found {}", self.this_token_descr())); if self.token.is_ident() { // This is likely another field; emit the diagnostic and keep going err.span_suggestion( sp, "try adding a comma", ",".into(), Applicability::MachineApplicable, ); err.emit(); } else { return Err(err) } } } Ok(a_var) } /// Parses a structure field. fn parse_name_and_ty( &mut self, lo: Span, vis: Visibility, attrs: Vec ) -> PResult<'a, StructField> { let name = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; Ok(StructField { span: lo.to(self.prev_span), ident: Some(name), vis, id: DUMMY_NODE_ID, ty, attrs, is_placeholder: false, }) } pub(super) fn eat_macro_def( &mut self, attrs: &[Attribute], vis: &Visibility, lo: Span ) -> PResult<'a, Option>> { let token_lo = self.token.span; let (ident, def) = if self.eat_keyword(kw::Macro) { let ident = self.parse_ident()?; let tokens = if self.check(&token::OpenDelim(token::Brace)) { match self.parse_token_tree() { TokenTree::Delimited(_, _, tts) => tts, _ => unreachable!(), } } else if self.check(&token::OpenDelim(token::Paren)) { let args = self.parse_token_tree(); let body = if self.check(&token::OpenDelim(token::Brace)) { self.parse_token_tree() } else { self.unexpected()?; unreachable!() }; TokenStream::new(vec![ args.into(), TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(), body.into(), ]) } else { self.unexpected()?; unreachable!() }; (ident, ast::MacroDef { tokens: tokens.into(), legacy: false }) } else if self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) { let prev_span = self.prev_span; self.complain_if_pub_macro(&vis.node, prev_span); self.bump(); self.bump(); let ident = self.parse_ident()?; let (delim, tokens) = self.expect_delimited_token_tree()?; if delim != MacDelimiter::Brace && !self.eat(&token::Semi) { self.report_invalid_macro_expansion_item(); } (ident, ast::MacroDef { tokens, legacy: true }) } else { return Ok(None); }; let span = lo.to(self.prev_span); if !def.legacy { self.sess.gated_spans.decl_macro.borrow_mut().push(span); } Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) } fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { match *vis { VisibilityKind::Inherited => {} _ => { let mut err = if self.token.is_keyword(sym::macro_rules) { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); err.span_suggestion( sp, "try exporting the macro", "#[macro_export]".to_owned(), Applicability::MaybeIncorrect // speculative ); err } else { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro invocation with `pub`"); err.help("try adjusting the macro to put `pub` inside the invocation"); err }; err.emit(); } } } fn report_invalid_macro_expansion_item(&self) { self.struct_span_err( self.prev_span, "macros that expand to items must be delimited with braces or followed by a semicolon", ).multipart_suggestion( "change the delimiters to curly braces", vec![ (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")), (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), ], Applicability::MaybeIncorrect, ).span_suggestion( self.sess.source_map().next_point(self.prev_span), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, ).emit(); } fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility, attrs: Vec) -> P { P(Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None, }) } } /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). pub(super) struct ParamCfg { /// Is `self` is allowed as the first parameter? pub is_self_allowed: bool, /// Is `...` allowed as the tail of the parameter list? pub allow_c_variadic: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, } /// Parsing of functions and methods. impl<'a> Parser<'a> { /// Parses an item-position function declaration. fn parse_item_fn( &mut self, lo: Span, vis: Visibility, attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ItemKind::Fn(decl, header, generics, body); self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) } /// Parses a function declaration from a foreign module. fn parse_item_foreign_fn( &mut self, vis: ast::Visibility, lo: Span, attrs: Vec, extern_sp: Span, ) -> PResult<'a, ForeignItem> { self.expect_keyword(kw::Fn)?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, allow_c_variadic: true, is_name_required: |_| true, })?; let span = lo.to(self.token.span); self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; Ok(ast::ForeignItem { ident, attrs, kind: ForeignItemKind::Fn(decl, generics), id: DUMMY_NODE_ID, span, vis, }) } /// Parses a method or a macro invocation in a trait impl. fn parse_impl_method( &mut self, at_end: &mut bool, ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { let (ident, sig, generics) = self.parse_method_sig(|_| true)?; *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) } fn parse_trait_item_method( &mut self, at_end: &mut bool, attrs: &mut Vec, ) -> PResult<'a, (Ident, TraitItemKind, Generics)> { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a definition... // // We don't allow argument names to be left off in edition 2018. let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; let body = self.parse_trait_method_body(at_end, attrs)?; Ok((ident, TraitItemKind::Method(sig, body), generics)) } /// Parse the "body" of a method in a trait item definition. /// This can either be `;` when there's no body, /// or e.g. a block when the method is a provided one. fn parse_trait_method_body( &mut self, at_end: &mut bool, attrs: &mut Vec, ) -> PResult<'a, Option>> { Ok(match self.token.kind { token::Semi => { debug!("parse_trait_method_body(): parsing required method"); self.bump(); *at_end = true; None } token::OpenDelim(token::Brace) => { debug!("parse_trait_method_body(): parsing provided method"); *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(inner_attrs.iter().cloned()); Some(body) } token::Interpolated(ref nt) => { match **nt { token::NtBlock(..) => { *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(inner_attrs.iter().cloned()); Some(body) } _ => return self.expected_semi_or_open_brace(), } } _ => return self.expected_semi_or_open_brace(), }) } /// Parse the "signature", including the identifier, parameters, and generics /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. fn parse_method_sig( &mut self, is_name_required: fn(&token::Token) -> bool, ) -> PResult<'a, (Ident, MethodSig, Generics)> { let header = self.parse_fn_front_matter()?; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: true, allow_c_variadic: false, is_name_required, })?; Ok((ident, MethodSig { header, decl }, generics)) } /// Parses all the "front matter" for a `fn` declaration, up to /// and including the `fn` keyword: /// /// - `const fn` /// - `unsafe fn` /// - `const unsafe fn` /// - `extern fn` /// - etc. fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { let is_const_fn = self.eat_keyword(kw::Const); let const_span = self.prev_span; let asyncness = self.parse_asyncness(); if let IsAsync::Async { .. } = asyncness { self.ban_async_in_2015(self.prev_span); } let asyncness = respan(self.prev_span, asyncness); let unsafety = self.parse_unsafety(); let (constness, unsafety, abi) = if is_const_fn { (respan(const_span, Constness::Const), unsafety, Abi::Rust) } else { let abi = self.parse_extern_abi()?; (respan(self.prev_span, Constness::NotConst), unsafety, abi) }; if !self.eat_keyword(kw::Fn) { // It is possible for `expect_one_of` to recover given the contents of // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't // account for this. if !self.expect_one_of(&[], &[])? { unreachable!() } } Ok(FnHeader { constness, unsafety, asyncness, abi }) } /// Parse the "signature", including the identifier, parameters, and generics of a function. fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl(cfg, true)?; generics.where_clause = self.parse_where_clause()?; Ok((ident, decl, generics)) } /// Parses the parameter list and result type of a function declaration. pub(super) fn parse_fn_decl( &mut self, cfg: ParamCfg, ret_allow_plus: bool, ) -> PResult<'a, P> { Ok(P(FnDecl { inputs: self.parse_fn_params(cfg)?, output: self.parse_ret_ty(ret_allow_plus)?, })) } /// Parses the parameter list of a function, including the `(` and `)` delimiters. fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { let sp = self.token.span; let is_trait_item = cfg.is_self_allowed; let mut c_variadic = false; // Parse the arguments, starting out with `self` being possibly allowed... let (params, _) = self.parse_paren_comma_seq(|p| { let param = p.parse_param_general(&cfg, is_trait_item); // ...now that we've parsed the first argument, `self` is no longer allowed. cfg.is_self_allowed = false; match param { Ok(param) => Ok( if let TyKind::CVarArgs = param.ty.kind { c_variadic = true; if p.token != token::CloseDelim(token::Paren) { p.span_err( p.token.span, "`...` must be the last argument of a C-variadic function", ); // FIXME(eddyb) this should probably still push `CVarArgs`. // Maybe AST validation/HIR lowering should emit the above error? None } else { Some(param) } } else { Some(param) } ), Err(mut e) => { e.emit(); let lo = p.prev_span; // Skip every token until next possible arg or end. p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); // Create a placeholder argument for proper arg count (issue #34264). let span = lo.to(p.prev_span); Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) } } })?; let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. self.deduplicate_recovered_params_names(&mut params); if c_variadic && params.len() <= 1 { self.span_err( sp, "C-variadic function must be declared with at least one named argument", ); } Ok(params) } /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. /// This version of parse param doesn't necessarily require identifier names. fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = self.parse_self_param()? { param.attrs = attrs.into(); return if cfg.is_self_allowed { Ok(param) } else { self.recover_bad_self_param(param, is_trait_item) }; } let is_name_required = match self.token.kind { token::DotDotDot => false, _ => (cfg.is_name_required)(&self.token), }; let (pat, ty) = if is_name_required || self.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { return if let Some(ident) = self.parameter_without_type( &mut err, pat, is_name_required, cfg.is_self_allowed, is_trait_item, ) { err.emit(); Ok(dummy_arg(ident)) } else { Err(err) }; } self.eat_incorrect_doc_comment_for_param_type(); (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, // so we are going to rollback and re-parse for recovery. ty = self.unexpected(); } match ty { Ok(ty) => { let ident = Ident::new(kw::Invalid, self.prev_span); let bm = BindingMode::ByValue(Mutability::Immutable); let pat = self.mk_pat_ident(ty.span, bm, ident); (pat, ty) } // If this is a C-variadic argument and we hit an error, return the error. Err(err) if self.token == token::DotDotDot => return Err(err), // Recover from attempting to parse the argument as a type without pattern. Err(mut err) => { err.cancel(); mem::replace(self, parser_snapshot_before_ty); self.recover_arg_parse()? } } }; let span = lo.to(self.token.span); Ok(Param { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty, }) } /// Returns the parsed optional self parameter and whether a self shortcut was used. /// /// See `parse_self_param_with_attrs` to collect attributes. fn parse_self_param(&mut self) -> PResult<'a, Option> { // Extract an identifier *after* having confirmed that the token is one. let expect_self_ident = |this: &mut Self| { match this.token.kind { // Preserve hygienic context. token::Ident(name, _) => { let span = this.token.span; this.bump(); Ident::new(name, span) } _ => unreachable!(), } }; // Is `self` `n` tokens ahead? let is_isolated_self = |this: &Self, n| { this.is_keyword_ahead(n, &[kw::SelfLower]) && this.look_ahead(n + 1, |t| t != &token::ModSep) }; // Is `mut self` `n` tokens ahead? let is_isolated_mut_self = |this: &Self, n| { this.is_keyword_ahead(n, &[kw::Mut]) && is_isolated_self(this, n + 1) }; // Parse `self` or `self: TYPE`. We already know the current token is `self`. let parse_self_possibly_typed = |this: &mut Self, m| { let eself_ident = expect_self_ident(this); let eself_hi = this.prev_span; let eself = if this.eat(&token::Colon) { SelfKind::Explicit(this.parse_ty()?, m) } else { SelfKind::Value(m) }; Ok((eself, eself_ident, eself_hi)) }; // Recover for the grammar `*self`, `*const self`, and `*mut self`. let recover_self_ptr = |this: &mut Self| { let msg = "cannot pass `self` by raw pointer"; let span = this.token.span; this.struct_span_err(span, msg) .span_label(span, msg) .emit(); Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span)) }; // Parse optional `self` parameter of a method. // Only a limited set of initial token sequences is considered `self` parameters; anything // else is parsed as a normal function parameter list, so some lookahead is required. let eself_lo = self.token.span; let (eself, eself_ident, eself_hi) = match self.token.kind { token::BinOp(token::And) => { let eself = if is_isolated_self(self, 1) { // `&self` self.bump(); SelfKind::Region(None, Mutability::Immutable) } else if is_isolated_mut_self(self, 1) { // `&mut self` self.bump(); self.bump(); SelfKind::Region(None, Mutability::Mutable) } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { // `&'lt self` self.bump(); let lt = self.expect_lifetime(); SelfKind::Region(Some(lt), Mutability::Immutable) } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { // `&'lt mut self` self.bump(); let lt = self.expect_lifetime(); self.bump(); SelfKind::Region(Some(lt), Mutability::Mutable) } else { // `¬_self` return Ok(None); }; (eself, expect_self_ident(self), self.prev_span) } // `*self` token::BinOp(token::Star) if is_isolated_self(self, 1) => { self.bump(); recover_self_ptr(self)? } // `*mut self` and `*const self` token::BinOp(token::Star) if self.look_ahead(1, |t| t.is_mutability()) && is_isolated_self(self, 2) => { self.bump(); self.bump(); recover_self_ptr(self)? } // `self` and `self: TYPE` token::Ident(..) if is_isolated_self(self, 0) => { parse_self_possibly_typed(self, Mutability::Immutable)? } // `mut self` and `mut self: TYPE` token::Ident(..) if is_isolated_mut_self(self, 0) => { self.bump(); parse_self_possibly_typed(self, Mutability::Mutable)? } _ => return Ok(None), }; let eself = source_map::respan(eself_lo.to(eself_hi), eself); Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) } fn is_named_param(&self) -> bool { let offset = match self.token.kind { token::Interpolated(ref nt) => match **nt { token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), _ => 0, } token::BinOp(token::And) | token::AndAnd => 1, _ if self.token.is_keyword(kw::Mut) => 1, _ => 0, }; self.look_ahead(offset, |t| t.is_ident()) && self.look_ahead(offset + 1, |t| t == &token::Colon) } fn recover_first_param(&mut self) -> &'static str { match self.parse_outer_attributes() .and_then(|_| self.parse_self_param()) .map_err(|mut e| e.cancel()) { Ok(Some(_)) => "method", _ => "function", } } }