use crate::ThinVec;
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
use crate::symbol::{kw, sym, Symbol};
-use crate::parse::diagnostics::Error;
+use crate::parse::diagnostics::{Error, dummy_arg};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
use rustc_target::spec::abi::{self, Abi};
}
}
-/// Creates a placeholder argument.
-fn dummy_arg(span: Span) -> Arg {
- let ident = Ident::new(kw::Invalid, span);
- let pat = P(Pat {
- id: ast::DUMMY_NODE_ID,
- node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
- span,
- });
- let ty = Ty {
- node: TyKind::Err,
- span,
- id: ast::DUMMY_NODE_ID
- };
- Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }
-}
-
#[derive(Copy, Clone, Debug)]
crate enum TokenExpectType {
Expect,
let pat = self.parse_pat(Some("argument name"))?;
if let Err(mut err) = self.expect(&token::Colon) {
- self.argument_without_type(&mut err, pat, require_name, is_trait_item);
- return Err(err);
+ if let Some(ident) = self.argument_without_type(
+ &mut err,
+ pat,
+ require_name,
+ is_trait_item,
+ ) {
+ err.emit();
+ return Ok(dummy_arg(ident));
+ } else {
+ return Err(err);
+ }
}
self.eat_incorrect_doc_comment("a method argument's type");
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
let span_lo = self.span;
- if self.eat_lt() {
+ let (params, span) = if self.eat_lt() {
let params = self.parse_generic_params()?;
self.expect_gt()?;
- Ok(ast::Generics {
- params,
- where_clause: WhereClause {
- id: ast::DUMMY_NODE_ID,
- predicates: Vec::new(),
- span: DUMMY_SP,
- },
- span: span_lo.to(self.prev_span),
- })
+ (params, span_lo.to(self.prev_span))
} else {
- Ok(ast::Generics::default())
- }
+ (vec![], self.prev_span.between(self.span))
+ };
+ Ok(ast::Generics {
+ params,
+ where_clause: WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ span: DUMMY_SP,
+ },
+ span,
+ })
}
/// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
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(span)))
+ Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
}
}
}
// Parse the rest of the function parameter list.
let sep = SeqSep::trailing_allowed(token::Comma);
- let (fn_inputs, recovered) = if let Some(self_arg) = self_arg {
+ let (mut fn_inputs, recovered) = if let Some(self_arg) = self_arg {
if self.check(&token::CloseDelim(token::Paren)) {
(vec![self_arg], false)
} else if self.eat(&token::Comma) {
// Parse closing paren and return type.
self.expect(&token::CloseDelim(token::Paren))?;
}
+ // Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors.
+ self.deduplicate_recovered_arg_names(&mut fn_inputs);
+
Ok(P(FnDecl {
inputs: fn_inputs,
output: self.parse_ret_ty(true)?,
return Ok(Some(item));
}
- // `unsafe async fn` or `async fn`
- if (
- self.check_keyword(kw::Unsafe) &&
- self.is_keyword_ahead(1, &[kw::Async])
- ) || (
- self.check_keyword(kw::Async) &&
- self.is_keyword_ahead(1, &[kw::Fn])
- )
- {
- // ASYNC FUNCTION ITEM
- let unsafety = self.parse_unsafety();
- self.expect_keyword(kw::Async)?;
- let async_span = self.prev_span;
- self.expect_keyword(kw::Fn)?;
- let fn_span = self.prev_span;
- let (ident, item_, extra_attrs) =
- self.parse_item_fn(unsafety,
- respan(async_span, IsAsync::Async {
- closure_id: ast::DUMMY_NODE_ID,
- return_impl_trait_id: ast::DUMMY_NODE_ID,
- arguments: Vec::new(),
- }),
- respan(fn_span, Constness::NotConst),
- Abi::Rust)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- if self.span.rust_2015() {
- self.diagnostic().struct_span_err_with_code(
- async_span,
- "`async fn` is not permitted in the 2015 edition",
- DiagnosticId::Error("E0670".into())
- ).emit();
+ // Parse `async unsafe? fn`.
+ if self.check_keyword(kw::Async) {
+ let async_span = self.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 (ident, item_, extra_attrs) =
+ self.parse_item_fn(unsafety,
+ respan(async_span, IsAsync::Async {
+ closure_id: ast::DUMMY_NODE_ID,
+ return_impl_trait_id: ast::DUMMY_NODE_ID,
+ arguments: Vec::new(),
+ }),
+ respan(fn_span, Constness::NotConst),
+ Abi::Rust)?;
+ let prev_span = self.prev_span;
+ let item = self.mk_item(lo.to(prev_span),
+ ident,
+ item_,
+ visibility,
+ maybe_append(attrs, extra_attrs));
+ if self.span.rust_2015() {
+ self.diagnostic().struct_span_err_with_code(
+ async_span,
+ "`async fn` is not permitted in the 2015 edition",
+ DiagnosticId::Error("E0670".into())
+ ).emit();
+ }
+ return Ok(Some(item));
}
- return Ok(Some(item));
}
if self.check_keyword(kw::Unsafe) &&
self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])