Skip to content

Commit 7b2f04a

Browse files
committed
fix #102182, recover from impl Trait in type param bound
1 parent 672e3f4 commit 7b2f04a

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

compiler/rustc_parse/src/parser/generics.rs

+34-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use super::{ForceCollect, Parser, TrailingToken};
22

33
use rustc_ast::token;
4-
use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause};
4+
use rustc_ast::{
5+
self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause,
6+
};
57
use rustc_errors::{Applicability, PResult};
68
use rustc_span::symbol::kw;
79

@@ -31,13 +33,43 @@ impl<'a> Parser<'a> {
3133
let mut colon_span = None;
3234
let bounds = if self.eat(&token::Colon) {
3335
colon_span = Some(self.prev_token.span);
36+
// recover from `impl Trait` in type param bound
37+
if self.token.is_keyword(kw::Impl) {
38+
let impl_span = self.token.span;
39+
let snapshot = self.create_snapshot_for_diagnostic();
40+
match self.parse_ty() {
41+
Ok(p) => {
42+
if let TyKind::ImplTrait(_, bounds) = &(*p).kind {
43+
let span = impl_span.to(self.token.span.shrink_to_lo());
44+
let mut err = self.struct_span_err(
45+
span,
46+
"expected trait bound, found `impl Trait` type",
47+
);
48+
err.span_label(span, "not a trait");
49+
if let [bound, ..] = &bounds[..] {
50+
err.span_suggestion_verbose(
51+
impl_span.until(bound.span()),
52+
"use the trait bounds directly",
53+
String::new(),
54+
Applicability::MachineApplicable,
55+
);
56+
}
57+
err.emit();
58+
return Err(err);
59+
}
60+
}
61+
Err(err) => {
62+
err.cancel();
63+
}
64+
}
65+
self.restore_snapshot(snapshot);
66+
}
3467
self.parse_generic_bounds(colon_span)?
3568
} else {
3669
Vec::new()
3770
};
3871

3972
let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
40-
4173
Ok(GenericParam {
4274
ident,
4375
id: ast::DUMMY_NODE_ID,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn foo<T: impl Trait>() {}
2+
//~^ ERROR expected trait bound, found `impl Trait` type
3+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: expected trait bound, found `impl Trait` type
2+
--> $DIR/issue-102182-impl-trait-recover.rs:1:11
3+
|
4+
LL | fn foo<T: impl Trait>() {}
5+
| ^^^^^^^^^^ not a trait
6+
|
7+
help: use the trait bounds directly
8+
|
9+
LL - fn foo<T: impl Trait>() {}
10+
LL + fn foo<T: Trait>() {}
11+
|
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)