Skip to content

Commit

Permalink
Rollup merge of #111477 - y21:extra-impl-in-trait-impl, r=compiler-er…
Browse files Browse the repository at this point in the history
…rors

better diagnostics for `impl<..> impl Trait for Type`

Fixes #109963
  • Loading branch information
matthiaskrgr authored May 14, 2023
2 parents 0b8f2bf + 7fe8334 commit d7f7425
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 4 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,11 @@ parse_missing_for_in_trait_impl = missing `for` in a trait impl
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
parse_extra_impl_keyword_in_trait_impl = unexpected `impl` keyword
.suggestion = remove the extra `impl`
.note = this is parsed as an `impl Trait` type, but a trait is expected at this position
parse_non_item_in_item_list = non-item in item list
.suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
.label_list_start = item list starts here
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,16 @@ pub(crate) struct ExpectedTraitInTraitImplFoundType {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_extra_impl_keyword_in_trait_impl)]
pub(crate) struct ExtraImplKeywordInTraitImpl {
#[primary_span]
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub extra_impl_kw: Span,
#[note]
pub impl_trait_span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_bounds_not_allowed_on_trait_aliases)]
pub(crate) struct BoundsNotAllowedOnTraitAliases {
Expand Down
22 changes: 18 additions & 4 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,10 +603,24 @@ impl<'a> Parser<'a> {
let path = match ty_first.kind {
// This notably includes paths passed through `ty` macro fragments (#46438).
TyKind::Path(None, path) => path,
_ => {
self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
span: ty_first.span,
});
other => {
if let TyKind::ImplTrait(_, bounds) = other
&& let [bound] = bounds.as_slice()
{
// Suggest removing extra `impl` keyword:
// `impl<T: Default> impl Default for Wrapper<T>`
// ^^^^^
let extra_impl_kw = ty_first.span.until(bound.span());
self.sess
.emit_err(errors::ExtraImplKeywordInTraitImpl {
extra_impl_kw,
impl_trait_span: ty_first.span
});
} else {
self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
span: ty_first.span,
});
}
err_path(ty_first.span)
}
};
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// run-rustfix

struct S<T>(T);
struct S2;

impl<T: Default> Default for S<T> {
//~^ ERROR: unexpected `impl` keyword
//~| HELP: remove the extra `impl`
fn default() -> Self { todo!() }
}

impl Default for S2 {
//~^ ERROR: unexpected `impl` keyword
//~| HELP: remove the extra `impl`
fn default() -> Self { todo!() }
}


fn main() {}
19 changes: 19 additions & 0 deletions tests/ui/impl-trait/extra-impl-in-trait-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// run-rustfix

struct S<T>(T);
struct S2;

impl<T: Default> impl Default for S<T> {
//~^ ERROR: unexpected `impl` keyword
//~| HELP: remove the extra `impl`
fn default() -> Self { todo!() }
}

impl impl Default for S2 {
//~^ ERROR: unexpected `impl` keyword
//~| HELP: remove the extra `impl`
fn default() -> Self { todo!() }
}


fn main() {}
26 changes: 26 additions & 0 deletions tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: unexpected `impl` keyword
--> $DIR/extra-impl-in-trait-impl.rs:6:18
|
LL | impl<T: Default> impl Default for S<T> {
| ^^^^^ help: remove the extra `impl`
|
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
--> $DIR/extra-impl-in-trait-impl.rs:6:18
|
LL | impl<T: Default> impl Default for S<T> {
| ^^^^^^^^^^^^

error: unexpected `impl` keyword
--> $DIR/extra-impl-in-trait-impl.rs:12:6
|
LL | impl impl Default for S2 {
| ^^^^^ help: remove the extra `impl`
|
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
--> $DIR/extra-impl-in-trait-impl.rs:12:6
|
LL | impl impl Default for S2 {
| ^^^^^^^^^^^^

error: aborting due to 2 previous errors

0 comments on commit d7f7425

Please sign in to comment.