Skip to content

better diagnostics for impl<..> impl Trait for Type #111477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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