about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-05-10 23:00:47 +0000
committerMichael Goulet <michael@errs.io>2023-05-15 17:14:59 +0000
commita5763ff8d3e67c156ebe8160de1db26a644d4c5d (patch)
tree7ed43464a4909c0c7547136f7ceb4b0267ff3cef
parent2913ad6db0f72fed5139253faed73200c7af3535 (diff)
downloadrust-a5763ff8d3e67c156ebe8160de1db26a644d4c5d.tar.gz
rust-a5763ff8d3e67c156ebe8160de1db26a644d4c5d.zip
Recover `impl<T ?Sized>` correctly
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs5
-rw-r--r--tests/ui/parser/impl-on-unsized-typo.rs6
-rw-r--r--tests/ui/parser/impl-on-unsized-typo.stderr8
3 files changed, 19 insertions, 0 deletions
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index e6d0f9fbc76..cd779b0b43e 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -453,6 +453,8 @@ impl<'a> Parser<'a> {
         //     `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
         //     `<` (LIFETIME|IDENT) `=` - generic parameter with a default
         //     `<` const                - generic const parameter
+        //     `<` IDENT `?`            - RECOVERY for `impl<T ?Bound` missing a `:`, meant to
+        //                                avoid the `T?` to `Option<T>` recovery for types.
         // The only truly ambiguous case is
         //     `<` IDENT `>` `::` IDENT ...
         // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
@@ -463,6 +465,9 @@ impl<'a> Parser<'a> {
                 || self.look_ahead(start + 1, |t| t.is_lifetime() || t.is_ident())
                     && self.look_ahead(start + 2, |t| {
                         matches!(t.kind, token::Gt | token::Comma | token::Colon | token::Eq)
+                        // Recovery-only branch -- this could be removed,
+                        // since it only affects diagnostics currently.
+                            || matches!(t.kind, token::Question)
                     })
                 || self.is_keyword_ahead(start + 1, &[kw::Const]))
     }
diff --git a/tests/ui/parser/impl-on-unsized-typo.rs b/tests/ui/parser/impl-on-unsized-typo.rs
new file mode 100644
index 00000000000..e09c0463045
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.rs
@@ -0,0 +1,6 @@
+trait Tr {}
+
+impl<T ?Sized> Tr for T {}
+//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `?`
+
+fn main() {}
diff --git a/tests/ui/parser/impl-on-unsized-typo.stderr b/tests/ui/parser/impl-on-unsized-typo.stderr
new file mode 100644
index 00000000000..23dcc1efd68
--- /dev/null
+++ b/tests/ui/parser/impl-on-unsized-typo.stderr
@@ -0,0 +1,8 @@
+error: expected one of `,`, `:`, `=`, or `>`, found `?`
+  --> $DIR/impl-on-unsized-typo.rs:3:8
+   |
+LL | impl<T ?Sized> Tr for T {}
+   |        ^ expected one of `,`, `:`, `=`, or `>`
+
+error: aborting due to previous error
+