Skip to content

Commit d7f7425

Browse files
authored
Rollup merge of #111477 - y21:extra-impl-in-trait-impl, r=compiler-errors
better diagnostics for `impl<..> impl Trait for Type` Fixes #109963
2 parents 0b8f2bf + 7fe8334 commit d7f7425

File tree

6 files changed

+97
-4
lines changed

6 files changed

+97
-4
lines changed

compiler/rustc_parse/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ parse_missing_for_in_trait_impl = missing `for` in a trait impl
478478
479479
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
480480
481+
parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
482+
.suggestion = remove the extra `impl`
483+
.note = this is parsed as an `impl Trait` type, but a trait is expected at this position
484+
485+
481486
parse_non_item_in_item_list = non-item in item list
482487
.suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
483488
.label_list_start = item list starts here

compiler/rustc_parse/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,16 @@ pub(crate) struct ExpectedTraitInTraitImplFoundType {
15191519
pub span: Span,
15201520
}
15211521

1522+
#[derive(Diagnostic)]
1523+
#[diag(parse_extra_impl_keyword_in_trait_impl)]
1524+
pub(crate) struct ExtraImplKeywordInTraitImpl {
1525+
#[primary_span]
1526+
#[suggestion(code = "", applicability = "maybe-incorrect")]
1527+
pub extra_impl_kw: Span,
1528+
#[note]
1529+
pub impl_trait_span: Span,
1530+
}
1531+
15221532
#[derive(Diagnostic)]
15231533
#[diag(parse_bounds_not_allowed_on_trait_aliases)]
15241534
pub(crate) struct BoundsNotAllowedOnTraitAliases {

compiler/rustc_parse/src/parser/item.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -603,10 +603,24 @@ impl<'a> Parser<'a> {
603603
let path = match ty_first.kind {
604604
// This notably includes paths passed through `ty` macro fragments (#46438).
605605
TyKind::Path(None, path) => path,
606-
_ => {
607-
self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
608-
span: ty_first.span,
609-
});
606+
other => {
607+
if let TyKind::ImplTrait(_, bounds) = other
608+
&& let [bound] = bounds.as_slice()
609+
{
610+
// Suggest removing extra `impl` keyword:
611+
// `impl<T: Default> impl Default for Wrapper<T>`
612+
// ^^^^^
613+
let extra_impl_kw = ty_first.span.until(bound.span());
614+
self.sess
615+
.emit_err(errors::ExtraImplKeywordInTraitImpl {
616+
extra_impl_kw,
617+
impl_trait_span: ty_first.span
618+
});
619+
} else {
620+
self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
621+
span: ty_first.span,
622+
});
623+
}
610624
err_path(ty_first.span)
611625
}
612626
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-rustfix
2+
3+
struct S<T>(T);
4+
struct S2;
5+
6+
impl<T: Default> Default for S<T> {
7+
//~^ ERROR: unexpected `impl` keyword
8+
//~| HELP: remove the extra `impl`
9+
fn default() -> Self { todo!() }
10+
}
11+
12+
impl Default for S2 {
13+
//~^ ERROR: unexpected `impl` keyword
14+
//~| HELP: remove the extra `impl`
15+
fn default() -> Self { todo!() }
16+
}
17+
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-rustfix
2+
3+
struct S<T>(T);
4+
struct S2;
5+
6+
impl<T: Default> impl Default for S<T> {
7+
//~^ ERROR: unexpected `impl` keyword
8+
//~| HELP: remove the extra `impl`
9+
fn default() -> Self { todo!() }
10+
}
11+
12+
impl impl Default for S2 {
13+
//~^ ERROR: unexpected `impl` keyword
14+
//~| HELP: remove the extra `impl`
15+
fn default() -> Self { todo!() }
16+
}
17+
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: unexpected `impl` keyword
2+
--> $DIR/extra-impl-in-trait-impl.rs:6:18
3+
|
4+
LL | impl<T: Default> impl Default for S<T> {
5+
| ^^^^^ help: remove the extra `impl`
6+
|
7+
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
8+
--> $DIR/extra-impl-in-trait-impl.rs:6:18
9+
|
10+
LL | impl<T: Default> impl Default for S<T> {
11+
| ^^^^^^^^^^^^
12+
13+
error: unexpected `impl` keyword
14+
--> $DIR/extra-impl-in-trait-impl.rs:12:6
15+
|
16+
LL | impl impl Default for S2 {
17+
| ^^^^^ help: remove the extra `impl`
18+
|
19+
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
20+
--> $DIR/extra-impl-in-trait-impl.rs:12:6
21+
|
22+
LL | impl impl Default for S2 {
23+
| ^^^^^^^^^^^^
24+
25+
error: aborting due to 2 previous errors
26+

0 commit comments

Comments
 (0)