]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/parse/parser.rs
Rollup merge of #61409 - varkor:condition-trait-param-ice, r=oli-obk
[rust.git] / src / libsyntax / parse / parser.rs
index a562d2a1d2b440577cf29f593161547e11722d37..671b313c7f24ba4a101883d02ce58b56910367a4 100644 (file)
@@ -47,7 +47,7 @@
 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};
@@ -451,22 +451,6 @@ fn from(expr: P<Expr>) -> Self {
     }
 }
 
-/// 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,
@@ -1528,8 +1512,17 @@ fn parse_arg_general(
             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");
@@ -5050,21 +5043,22 @@ fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a,
     /// 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.
@@ -5435,7 +5429,7 @@ fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
                             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))))
                         }
                     }
                 }
@@ -5588,7 +5582,7 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
 
         // 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) {
@@ -5611,6 +5605,9 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
             // 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)?,
@@ -7209,44 +7206,41 @@ fn parse_item_implementation(
             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])