]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_parse/src/parser/ty.rs
Do not eagerly recover for bad impl-trait in macros
[rust.git] / compiler / rustc_parse / src / parser / ty.rs
index 8b4f0ab8feb848a0008a9a212aae65bbc0f332ec..5b92563fc358b68b1bbf824feacef2d9542e4a09 100644 (file)
@@ -1,6 +1,12 @@
 use super::{Parser, PathStyle, TokenType};
 
-use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
+use crate::errors::{
+    DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
+    FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
+    InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
+    NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
+    ReturnTypesUseThinArrow,
+};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 use ast::DUMMY_NODE_ID;
@@ -11,8 +17,7 @@
     self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
     MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
 };
-use rustc_ast_pretty::pprust;
-use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
+use rustc_errors::{Applicability, PResult};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
@@ -44,24 +49,17 @@ pub(super) enum AllowPlus {
     No,
 }
 
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq)]
 pub(super) enum RecoverQPath {
     Yes,
     No,
 }
 
-#[derive(PartialEq, Clone, Copy)]
 pub(super) enum RecoverQuestionMark {
     Yes,
     No,
 }
 
-#[derive(PartialEq, Clone, Copy)]
-pub(super) enum RecoverAnonEnum {
-    Yes,
-    No,
-}
-
 /// Signals whether parsing a type should recover `->`.
 ///
 /// More specifically, when parsing a function like:
@@ -94,7 +92,7 @@ fn can_recover(self, token: &TokenKind) -> bool {
 }
 
 // Is `...` (`CVarArgs`) legal at this level of type parsing?
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq)]
 enum AllowCVariadic {
     Yes,
     No,
@@ -119,7 +117,6 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::Yes,
             None,
             RecoverQuestionMark::Yes,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -134,7 +131,6 @@ pub(super) fn parse_ty_with_generics_recovery(
             RecoverReturnSign::Yes,
             Some(ty_params),
             RecoverQuestionMark::Yes,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -149,7 +145,6 @@ pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::Yes,
             None,
             RecoverQuestionMark::Yes,
-            RecoverAnonEnum::Yes,
         )
     }
 
@@ -167,7 +162,6 @@ pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::Yes,
             None,
             RecoverQuestionMark::Yes,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -181,7 +175,6 @@ pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::Yes,
             None,
             RecoverQuestionMark::No,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -193,7 +186,6 @@ pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::Yes,
             None,
             RecoverQuestionMark::No,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -206,7 +198,6 @@ pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
             RecoverReturnSign::OnlyFatArrow,
             None,
             RecoverQuestionMark::Yes,
-            RecoverAnonEnum::No,
         )
     }
 
@@ -226,21 +217,13 @@ pub(super) fn parse_ret_ty(
                 recover_return_sign,
                 None,
                 RecoverQuestionMark::Yes,
-                RecoverAnonEnum::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else if recover_return_sign.can_recover(&self.token.kind) {
             // Don't `eat` to prevent `=>` from being added as an expected token which isn't
             // actually expected and could only confuse users
             self.bump();
-            self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
-                .span_suggestion_short(
-                    self.prev_token.span,
-                    "use `->` instead",
-                    "->",
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
             let ty = self.parse_ty_common(
                 allow_plus,
                 AllowCVariadic::No,
@@ -248,7 +231,6 @@ pub(super) fn parse_ret_ty(
                 recover_return_sign,
                 None,
                 RecoverQuestionMark::Yes,
-                RecoverAnonEnum::Yes,
             )?;
             FnRetTy::Ty(ty)
         } else {
@@ -264,7 +246,6 @@ fn parse_ty_common(
         recover_return_sign: RecoverReturnSign,
         ty_generics: Option<&Generics>,
         recover_question_mark: RecoverQuestionMark,
-        recover_anon_enum: RecoverAnonEnum,
     ) -> PResult<'a, P<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
@@ -328,7 +309,7 @@ fn parse_ty_common(
                 AllowCVariadic::No => {
                     // FIXME(Centril): Should we just allow `...` syntactically
                     // anywhere in a type and use semantic restrictions instead?
-                    self.error_illegal_c_varadic_ty(lo);
+                    self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
                     TyKind::Err
                 }
             }
@@ -348,50 +329,9 @@ fn parse_ty_common(
             AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
             AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
         }
-        if RecoverQuestionMark::Yes == recover_question_mark {
+        if let RecoverQuestionMark::Yes = recover_question_mark {
             ty = self.maybe_recover_from_question_mark(ty);
         }
-        if recover_anon_enum == RecoverAnonEnum::Yes
-            && self.check_noexpect(&token::BinOp(token::Or))
-            && self.look_ahead(1, |t| t.can_begin_type())
-        {
-            let mut pipes = vec![self.token.span];
-            let mut types = vec![ty];
-            loop {
-                if !self.eat(&token::BinOp(token::Or)) {
-                    break;
-                }
-                pipes.push(self.prev_token.span);
-                types.push(self.parse_ty_common(
-                    allow_plus,
-                    allow_c_variadic,
-                    recover_qpath,
-                    recover_return_sign,
-                    ty_generics,
-                    recover_question_mark,
-                    RecoverAnonEnum::No,
-                )?);
-            }
-            let mut err = self.struct_span_err(pipes, "anonymous enums are not supported");
-            for ty in &types {
-                err.span_label(ty.span, "");
-            }
-            err.help(&format!(
-                "create a named `enum` and use it here instead:\nenum Name {{\n{}\n}}",
-                types
-                    .iter()
-                    .enumerate()
-                    .map(|(i, t)| format!(
-                        "    Variant{}({}),",
-                        i + 1, // Lets not confuse people with zero-indexing :)
-                        pprust::to_string(|s| s.print_type(&t)),
-                    ))
-                    .collect::<Vec<_>>()
-                    .join("\n"),
-            ));
-            err.emit();
-            return Ok(self.mk_ty(lo.to(self.prev_token.span), TyKind::Err));
-        }
         if allow_qpath_recovery { self.maybe_recover_from_bad_qpath(ty) } else { Ok(ty) }
     }
 
@@ -431,8 +371,7 @@ fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResul
         let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
         let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
         if lt_no_plus {
-            self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
-                .emit();
+            self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
         }
         Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
     }
@@ -466,14 +405,10 @@ fn parse_remaining_bounds(
     fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
         let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
             let span = self.prev_token.span;
-            self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
-                .span_suggestions(
-                    span.shrink_to_hi(),
-                    "add `mut` or `const` here",
-                    ["mut ".to_string(), "const ".to_string()],
-                    Applicability::HasPlaceholders,
-                )
-                .emit();
+            self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
+                span,
+                after_asterisk: span.shrink_to_hi(),
+            });
             Mutability::Not
         });
         let ty = self.parse_ty_no_plus()?;
@@ -528,16 +463,13 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
                 let lifetime_span = self.token.span;
                 let span = and_span.to(lifetime_span);
 
-                let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
-                if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
-                    err.span_suggestion(
-                        span,
-                        "place the lifetime before `mut`",
-                        format!("&{} mut", lifetime_src),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                err.emit();
+                let (suggest_lifetime, snippet) =
+                    if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
+                        (Some(span), lifetime_src)
+                    } else {
+                        (None, String::new())
+                    };
+                self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
 
                 opt_lifetime = Some(self.expect_lifetime());
             }
@@ -547,14 +479,7 @@ fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         {
             // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
             let span = and_span.to(self.look_ahead(1, |t| t.span));
-            let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
-            err.span_suggestion(
-                span,
-                "place `mut` before `dyn`",
-                "&mut dyn",
-                Applicability::MachineApplicable,
-            );
-            err.emit();
+            self.sess.emit_err(DynAfterMut { span });
 
             // Recovery
             mutbl = Mutability::Mut;
@@ -608,10 +533,10 @@ fn parse_ty_bare_fn(
             // If we ever start to allow `const fn()`, then update
             // feature gating for `#![feature(const_extern_fn)]` to
             // cover it.
-            self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
+            self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
         }
         if let ast::Async::Yes { span, .. } = asyncness {
-            self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
+            self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
         }
         let decl_span = span_start.to(self.token.span);
         Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
@@ -659,19 +584,6 @@ fn recover_fn_ptr_with_generics(
         Ok(())
     }
 
-    /// Emit an error for the given bad function pointer qualifier.
-    fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
-        self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
-            .span_label(qual_span, format!("`{}` because of this", qual))
-            .span_suggestion_short(
-                qual_span,
-                &format!("remove the `{}` qualifier", qual),
-                "",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
-    }
-
     /// Parses an `impl B0 + ... + Bn` type.
     fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
         // Always parse bounds greedily for better error recovery.
@@ -702,7 +614,7 @@ fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
     /// Is a `dyn B0 + ... + Bn` type allowed here?
     fn is_explicit_dyn_type(&mut self) -> bool {
         self.check_keyword(kw::Dyn)
-            && (!self.token.uninterpolated_span().rust_2015()
+            && (self.token.uninterpolated_span().rust_2018()
                 || self.look_ahead(1, |t| {
                     (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
                         && !can_continue_type_after_non_fn_ident(t)
@@ -758,16 +670,6 @@ fn parse_path_start_ty(
         }
     }
 
-    fn error_illegal_c_varadic_ty(&self, lo: Span) {
-        struct_span_err!(
-            self.sess.span_diagnostic,
-            lo.to(self.prev_token.span),
-            E0743,
-            "C-variadic type `...` may not be nested inside another type",
-        )
-        .emit();
-    }
-
     pub(super) fn parse_generic_bounds(
         &mut self,
         colon_span: Option<Span>,
@@ -792,20 +694,13 @@ fn parse_generic_bounds_common(
         // `where`, so stop if it's it.
         // We also continue if we find types (not traits), again for error recovery.
         while self.can_begin_bound()
-            || self.token.can_begin_type()
-            || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
+            || (self.may_recover()
+                && (self.token.can_begin_type()
+                    || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))))
         {
             if self.token.is_keyword(kw::Dyn) {
                 // Account for `&dyn Trait + dyn Other`.
-                self.struct_span_err(self.token.span, "invalid `dyn` keyword")
-                    .help("`dyn` is only needed at the start of a trait `+`-separated list")
-                    .span_suggestion(
-                        self.token.span,
-                        "remove this keyword",
-                        "",
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
                 self.bump();
             }
             match self.parse_generic_bound()? {
@@ -842,11 +737,7 @@ fn error_negative_bounds(
         bounds: &[GenericBound],
         negative_bounds: Vec<Span>,
     ) {
-        let negative_bounds_len = negative_bounds.len();
-        let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
-        let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
-        err.span_label(last_span, "negative bounds are not supported");
-        if let Some(bound_list) = colon_span {
+        let sub = if let Some(bound_list) = colon_span {
             let bound_list = bound_list.to(self.prev_token.span);
             let mut new_bound_list = String::new();
             if !bounds.is_empty() {
@@ -857,14 +748,18 @@ fn error_negative_bounds(
                 }
                 new_bound_list = new_bound_list.replacen(" +", ":", 1);
             }
-            err.tool_only_span_suggestion(
+
+            Some(NegativeBoundsNotSupportedSugg {
                 bound_list,
-                &format!("remove the bound{}", pluralize!(negative_bounds_len)),
-                new_bound_list,
-                Applicability::MachineApplicable,
-            );
-        }
-        err.emit();
+                num_bounds: negative_bounds.len(),
+                fixed: new_bound_list,
+            })
+        } else {
+            None
+        };
+
+        let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
+        self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
     }
 
     /// Parses a bound according to the grammar: