Do not suggest 'Trait<Assoc=arg>' when in trait impl
because that would be illegal syntax
This commit is contained in:
parent
37fda989ea
commit
079b290439
@ -129,6 +129,44 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
if self.missing_lifetimes() { "lifetime" } else { "generic" }
|
||||
}
|
||||
|
||||
/// Returns true if the generic type is a trait
|
||||
/// and is being referred to from one of its trait impls
|
||||
fn is_in_trait_impl(&self) -> bool {
|
||||
if self.tcx.is_trait(self.def_id) {
|
||||
// Here we check if the reference to the generic type
|
||||
// is from the 'of_trait' field of the enclosing impl
|
||||
|
||||
let parent = self.tcx.hir().get_parent(self.path_segment.hir_id);
|
||||
let parent_item = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_by_def_id(self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id);
|
||||
|
||||
// Get the HIR id of the trait ref
|
||||
let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Get the HIR id of the 'of_trait' field of the impl
|
||||
let hir::Node::Item(hir::Item {
|
||||
kind:
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) = parent_item
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
// Check that trait is referred to from the of_trait field of impl
|
||||
trait_ref_id == id_in_of_trait
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn num_provided_args(&self) -> usize {
|
||||
if self.missing_lifetimes() {
|
||||
self.num_provided_lifetime_args()
|
||||
@ -948,9 +986,14 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
// If there is a single unbound associated type and a single excess generic param
|
||||
// suggest replacing the generic param with the associated type bound
|
||||
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
|
||||
// Don't suggest if we're in a trait impl as
|
||||
// that would result in invalid syntax (fixes #116464)
|
||||
if !self.is_in_trait_impl() {
|
||||
let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
|
||||
let suggestions = iter::zip(unused_generics, &unbound_types)
|
||||
.map(|(potential, name)| (potential.span().shrink_to_lo(), format!("{name} = ")))
|
||||
.map(|(potential, name)| {
|
||||
(potential.span().shrink_to_lo(), format!("{name} = "))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if !suggestions.is_empty() {
|
||||
@ -963,6 +1006,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if remove_entire_generics {
|
||||
let span = self
|
||||
.path_segment
|
||||
|
@ -0,0 +1,43 @@
|
||||
// Regression test for #116464
|
||||
// Checks that we do not suggest Trait<..., Assoc=arg> when the trait
|
||||
// is referred to from one of its impls but do so at all other places
|
||||
|
||||
pub trait Trait<T> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T, S> Trait<T> for i32 {
|
||||
type Assoc = String;
|
||||
}
|
||||
|
||||
// Should not not trigger suggestion here...
|
||||
impl<T, S> Trait<T, S> for () {}
|
||||
//~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
|
||||
//... but should do so in all of the below cases except the last one
|
||||
fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
|
||||
//~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
//~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
3
|
||||
}
|
||||
|
||||
struct Struct<T: Trait<u32, String>> {
|
||||
//~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
a: T
|
||||
}
|
||||
|
||||
trait AnotherTrait<T: Trait<T, i32>> {}
|
||||
//~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
|
||||
impl<T: Trait<u32, String>> Struct<T> {}
|
||||
//~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
|
||||
// Test for self type. Should not trigger suggestion as it doesn't have an
|
||||
// associated type
|
||||
trait YetAnotherTrait {}
|
||||
impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
|
||||
//~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied
|
||||
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:14:12
|
||||
|
|
||||
LL | impl<T, S> Trait<T, S> for () {}
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:18:12
|
||||
|
|
||||
LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
help: replace the generic bound with the associated type
|
||||
|
|
||||
LL | fn func<T: Trait<u32, Assoc = String>>(t: T) -> impl Trait<(), i32> {
|
||||
| +++++++
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:18:46
|
||||
|
|
||||
LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), i32> {
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
help: replace the generic bound with the associated type
|
||||
|
|
||||
LL | fn func<T: Trait<u32, String>>(t: T) -> impl Trait<(), Assoc = i32> {
|
||||
| +++++++
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:24:18
|
||||
|
|
||||
LL | struct Struct<T: Trait<u32, String>> {
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
help: replace the generic bound with the associated type
|
||||
|
|
||||
LL | struct Struct<T: Trait<u32, Assoc = String>> {
|
||||
| +++++++
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:29:23
|
||||
|
|
||||
LL | trait AnotherTrait<T: Trait<T, i32>> {}
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
help: replace the generic bound with the associated type
|
||||
|
|
||||
LL | trait AnotherTrait<T: Trait<T, Assoc = i32>> {}
|
||||
| +++++++
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:32:9
|
||||
|
|
||||
LL | impl<T: Trait<u32, String>> Struct<T> {}
|
||||
| ^^^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:5:11
|
||||
|
|
||||
LL | pub trait Trait<T> {
|
||||
| ^^^^^ -
|
||||
help: replace the generic bound with the associated type
|
||||
|
|
||||
LL | impl<T: Trait<u32, Assoc = String>> Struct<T> {}
|
||||
| +++++++
|
||||
|
||||
error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:38:58
|
||||
|
|
||||
LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
|
||||
| ^^^^^^ - help: remove this generic argument
|
||||
| |
|
||||
| expected 1 generic argument
|
||||
|
|
||||
note: struct defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:24:8
|
||||
|
|
||||
LL | struct Struct<T: Trait<u32, String>> {
|
||||
| ^^^^^^ -
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0107`.
|
Loading…
x
Reference in New Issue
Block a user