about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-17 04:25:53 +0000
committerbors <bors@rust-lang.org>2023-01-17 04:25:53 +0000
commit85357e3e2ed5f4ae4760d4418bbeab9985a784aa (patch)
treea06ef4ab57aa35b7ba5f99fd72efa04ad25b8ed9 /compiler/rustc_parse/src/parser
parent4781233a77e879e49cb5ce3c98d2abba6a6ade7a (diff)
parentd6e79ab9c859cb06da0798f24ac31e1e33c932d3 (diff)
downloadrust-85357e3e2ed5f4ae4760d4418bbeab9985a784aa.tar.gz
rust-85357e3e2ed5f4ae4760d4418bbeab9985a784aa.zip
Auto merge of #106966 - matthiaskrgr:rollup-e34pevi, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #106591 (suggestion for attempted integer identifier in patterns)
 - #106712 (make error emitted on `impl &Trait` nicer)
 - #106829 (Unify `Opaque`/`Projection` handling in region outlives code)
 - #106869 (rustdoc: remove redundant item kind class from `.item-decl > pre`)
 - #106949 (ConstBlocks are poly if their substs are poly)
 - #106953 (Document `EarlyBinder::subst_identity` and `skip_binder`)
 - #106958 (Don't add A-bootstrap to PRs modifying Cargo.lock)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_parse/src/parser')
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs40
1 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a6f702e5428..1766b0293de 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -727,11 +727,13 @@ impl<'a> Parser<'a> {
         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,
+        // for example, `impl fn()`. The only keyword that can go after generic bounds is
+        // `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()
-            // Continue even if we find a keyword.
-            // This is necessary for error recover on, for example, `impl fn()`.
-            //
-            // The only keyword that can go after generic bounds is `where`, so stop if it's it.
+            || self.token.can_begin_type()
             || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
         {
             if self.token.is_keyword(kw::Dyn) {
@@ -939,6 +941,36 @@ impl<'a> Parser<'a> {
             && let Some(path) = self.recover_path_from_fn()
         {
             path
+        } else if !self.token.is_path_start() && self.token.can_begin_type() {
+            let ty = self.parse_ty_no_plus()?;
+            // Instead of finding a path (a trait), we found a type.
+            let mut err = self.struct_span_err(ty.span, "expected a trait, found type");
+
+            // If we can recover, try to extract a path from the type. Note
+            // that we do not use the try operator when parsing the type because
+            // if it fails then we get a parser error which we don't want (we're trying
+            // to recover from errors, not make more).
+            let path = if self.may_recover()
+                && matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..))
+                && let TyKind::Path(_, path) = &ty.peel_refs().kind {
+                // Just get the indirection part of the type.
+                let span = ty.span.until(path.span);
+
+                err.span_suggestion_verbose(
+                    span,
+                    "consider removing the indirection",
+                    "",
+                    Applicability::MaybeIncorrect,
+                );
+
+                path.clone()
+            } else {
+                return Err(err);
+            };
+
+            err.emit();
+
+            path
         } else {
             self.parse_path(PathStyle::Type)?
         };