]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_parse/src/parser/ty.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_parse / src / parser / ty.rs
index 400c8dbe9bc6b83d85a307cb78dc0acf655dc227..a29b696aea83c5a86615c6c1e2bc527399b09981 100644 (file)
@@ -1,10 +1,9 @@
 use super::{Parser, PathStyle, TokenType};
 
 use crate::errors::{
-    DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
+    self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
     FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
-    InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
-    NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
+    InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
     ReturnTypesUseThinArrow,
 };
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
@@ -14,8 +13,9 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
-    self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
-    MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
+    self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam,
+    Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier,
+    TraitObjectSyntax, Ty, TyKind,
 };
 use rustc_errors::{Applicability, PResult};
 use rustc_span::source_map::Span;
@@ -23,10 +23,10 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use thin_vec::{thin_vec, ThinVec};
 
-/// Any `?` or `~const` modifiers that appear at the start of a bound.
+/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound.
 struct BoundModifiers {
     /// `?Trait`.
-    maybe: Option<Span>,
+    bound_polarity: BoundPolarity,
 
     /// `~const Trait`.
     maybe_const: Option<Span>,
@@ -34,11 +34,13 @@ struct BoundModifiers {
 
 impl BoundModifiers {
     fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
-        match (self.maybe, self.maybe_const) {
-            (None, None) => TraitBoundModifier::None,
-            (Some(_), None) => TraitBoundModifier::Maybe,
-            (None, Some(_)) => TraitBoundModifier::MaybeConst,
-            (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
+        match (self.bound_polarity, self.maybe_const) {
+            (BoundPolarity::Positive, None) => TraitBoundModifier::None,
+            (BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative,
+            (BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe,
+            (BoundPolarity::Positive, Some(_)) => TraitBoundModifier::MaybeConst,
+            (BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative,
+            (BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
         }
     }
 }
@@ -315,9 +317,8 @@ impl<'a> Parser<'a> {
             }
         } else {
             let msg = format!("expected type, found {}", super::token_descr(&self.token));
-            let mut err = self.struct_span_err(self.token.span, &msg);
+            let mut err = self.struct_span_err(self.token.span, msg);
             err.span_label(self.token.span, "expected type");
-            self.maybe_annotate_with_ascription(&mut err, true);
             return Err(err);
         };
 
@@ -369,7 +370,7 @@ impl<'a> Parser<'a> {
 
     fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> {
         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)?;
+        let bounds = self.parse_generic_bounds_common(allow_plus)?;
         if lt_no_plus {
             self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
         }
@@ -396,7 +397,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, TyKind> {
         if plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
-            bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
+            bounds.append(&mut self.parse_generic_bounds()?);
         }
         Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
     }
@@ -588,24 +589,18 @@ impl<'a> Parser<'a> {
         // Always parse bounds greedily for better error recovery.
         if self.token.is_lifetime() {
             self.look_ahead(1, |t| {
-                if let token::Ident(symname, _) = t.kind {
+                if let token::Ident(sym, _) = t.kind {
                     // parse pattern with "'a Sized" we're supposed to give suggestion like
                     // "'a + Sized"
-                    self.struct_span_err(
-                        self.token.span,
-                        &format!("expected `+` between lifetime and {}", symname),
-                    )
-                    .span_suggestion_verbose(
-                        self.token.span.shrink_to_hi(),
-                        "add `+`",
-                        " +",
-                        Applicability::MaybeIncorrect,
-                    )
-                    .emit();
+                    self.sess.emit_err(errors::MissingPlusBounds {
+                        span: self.token.span,
+                        hi: self.token.span.shrink_to_hi(),
+                        sym,
+                    });
                 }
             })
         }
-        let bounds = self.parse_generic_bounds(None)?;
+        let bounds = self.parse_generic_bounds()?;
         *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
         Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds))
     }
@@ -636,7 +631,7 @@ impl<'a> Parser<'a> {
         };
 
         // Always parse bounds greedily for better error recovery.
-        let bounds = self.parse_generic_bounds(None)?;
+        let bounds = self.parse_generic_bounds()?;
         *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
         Ok(TyKind::TraitObject(bounds, syntax))
     }
@@ -657,11 +652,7 @@ impl<'a> Parser<'a> {
         let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
-            Ok(TyKind::MacCall(P(MacCall {
-                path,
-                args: self.parse_delim_args()?,
-                prior_type_ascription: self.last_type_ascription,
-            })))
+            Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
             self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
@@ -671,23 +662,15 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn parse_generic_bounds(
-        &mut self,
-        colon_span: Option<Span>,
-    ) -> PResult<'a, GenericBounds> {
-        self.parse_generic_bounds_common(AllowPlus::Yes, colon_span)
+    pub(super) fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> {
+        self.parse_generic_bounds_common(AllowPlus::Yes)
     }
 
     /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
     ///
     /// See `parse_generic_bound` for the `BOUND` grammar.
-    fn parse_generic_bounds_common(
-        &mut self,
-        allow_plus: AllowPlus,
-        colon_span: Option<Span>,
-    ) -> PResult<'a, GenericBounds> {
+    fn parse_generic_bounds_common(&mut self, allow_plus: AllowPlus) -> PResult<'a, GenericBounds> {
         let mut bounds = Vec::new();
-        let mut negative_bounds = Vec::new();
 
         // In addition to looping while we find generic bounds:
         // We continue even if we find a keyword. This is necessary for error recovery on,
@@ -704,19 +687,12 @@ impl<'a> Parser<'a> {
                 self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
                 self.bump();
             }
-            match self.parse_generic_bound()? {
-                Ok(bound) => bounds.push(bound),
-                Err(neg_sp) => negative_bounds.push(neg_sp),
-            }
+            bounds.push(self.parse_generic_bound()?);
             if allow_plus == AllowPlus::No || !self.eat_plus() {
                 break;
             }
         }
 
-        if !negative_bounds.is_empty() {
-            self.error_negative_bounds(colon_span, &bounds, negative_bounds);
-        }
-
         Ok(bounds)
     }
 
@@ -724,55 +700,22 @@ impl<'a> Parser<'a> {
     fn can_begin_bound(&mut self) -> bool {
         // This needs to be synchronized with `TokenKind::can_begin_bound`.
         self.check_path()
-        || self.check_lifetime()
-        || self.check(&token::Not) // Used for error reporting only.
-        || self.check(&token::Question)
-        || self.check(&token::Tilde)
-        || self.check_keyword(kw::For)
-        || self.check(&token::OpenDelim(Delimiter::Parenthesis))
-    }
-
-    fn error_negative_bounds(
-        &self,
-        colon_span: Option<Span>,
-        bounds: &[GenericBound],
-        negative_bounds: Vec<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() {
-                let mut snippets = bounds.iter().map(|bound| self.span_to_snippet(bound.span()));
-                while let Some(Ok(snippet)) = snippets.next() {
-                    new_bound_list.push_str(" + ");
-                    new_bound_list.push_str(&snippet);
-                }
-                new_bound_list = new_bound_list.replacen(" +", ":", 1);
-            }
-
-            Some(NegativeBoundsNotSupportedSugg {
-                bound_list,
-                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 });
+            || self.check_lifetime()
+            || self.check(&token::Not)
+            || self.check(&token::Question)
+            || self.check(&token::Tilde)
+            || self.check_keyword(kw::For)
+            || self.check(&token::OpenDelim(Delimiter::Parenthesis))
     }
 
     /// Parses a bound according to the grammar:
     /// ```ebnf
     /// BOUND = TY_BOUND | LT_BOUND
     /// ```
-    fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
-        let anchor_lo = self.prev_token.span;
+    fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
         let lo = self.token.span;
         let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
         let inner_lo = self.token.span;
-        let is_negative = self.eat(&token::Not);
 
         let modifiers = self.parse_ty_bound_modifiers()?;
         let bound = if self.token.is_lifetime() {
@@ -782,7 +725,7 @@ impl<'a> Parser<'a> {
             self.parse_generic_ty_bound(lo, has_parens, modifiers)?
         };
 
-        Ok(if is_negative { Err(anchor_lo.to(self.prev_token.span)) } else { Ok(bound) })
+        Ok(bound)
     }
 
     /// Parses a lifetime ("outlives") bound, e.g. `'a`, according to:
@@ -807,16 +750,17 @@ impl<'a> Parser<'a> {
     /// Emits an error if any trait bound modifiers were present.
     fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
         if let Some(span) = modifiers.maybe_const {
-            self.struct_span_err(
-                span,
-                "`~const` may only modify trait bounds, not lifetime bounds",
-            )
-            .emit();
+            self.sess.emit_err(errors::TildeConstLifetime { span });
         }
 
-        if let Some(span) = modifiers.maybe {
-            self.struct_span_err(span, "`?` may only modify trait bounds, not lifetime bounds")
-                .emit();
+        match modifiers.bound_polarity {
+            BoundPolarity::Positive => {}
+            BoundPolarity::Negative(span) => {
+                self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" });
+            }
+            BoundPolarity::Maybe(span) => {
+                self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" });
+            }
         }
     }
 
@@ -824,19 +768,14 @@ impl<'a> Parser<'a> {
     fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()> {
         let inner_span = inner_lo.to(self.prev_token.span);
         self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
-        let mut err = self.struct_span_err(
-            lo.to(self.prev_token.span),
-            "parenthesized lifetime bounds are not supported",
-        );
-        if let Ok(snippet) = self.span_to_snippet(inner_span) {
-            err.span_suggestion_short(
-                lo.to(self.prev_token.span),
-                "remove the parentheses",
-                snippet,
-                Applicability::MachineApplicable,
-            );
-        }
-        err.emit();
+        let span = lo.to(self.prev_token.span);
+        let (sugg, snippet) = if let Ok(snippet) = self.span_to_snippet(inner_span) {
+            (Some(span), snippet)
+        } else {
+            (None, String::new())
+        };
+
+        self.sess.emit_err(errors::ParenthesizedLifetime { span, sugg, snippet });
         Ok(())
     }
 
@@ -857,24 +796,23 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(kw::Const) {
             let span = self.prev_token.span;
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
-
-            self.struct_span_err(span, "const bounds must start with `~`")
-                .span_suggestion(
-                    span.shrink_to_lo(),
-                    "add `~`",
-                    "~",
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
 
             Some(span)
         } else {
             None
         };
 
-        let maybe = self.eat(&token::Question).then_some(self.prev_token.span);
+        let bound_polarity = if self.eat(&token::Question) {
+            BoundPolarity::Maybe(self.prev_token.span)
+        } else if self.eat(&token::Not) {
+            self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
+            BoundPolarity::Negative(self.prev_token.span)
+        } else {
+            BoundPolarity::Positive
+        };
 
-        Ok(BoundModifiers { maybe, maybe_const })
+        Ok(BoundModifiers { bound_polarity, maybe_const })
     }
 
     /// Parses a type bound according to:
@@ -944,14 +882,10 @@ impl<'a> Parser<'a> {
                 self.parse_remaining_bounds(bounds, true)?;
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
                 let sp = vec![lo, self.prev_token.span];
-                let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())];
-                self.struct_span_err(sp, "incorrect braces around trait bounds")
-                    .multipart_suggestion(
-                        "remove the parentheses",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(errors::IncorrectBracesTraitBounds {
+                    span: sp,
+                    sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
+                });
             } else {
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
             }