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" }
|
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 {
|
fn num_provided_args(&self) -> usize {
|
||||||
if self.missing_lifetimes() {
|
if self.missing_lifetimes() {
|
||||||
self.num_provided_lifetime_args()
|
self.num_provided_lifetime_args()
|
||||||
@ -948,20 +986,26 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
|||||||
// If there is a single unbound associated type and a single excess generic param
|
// If there is a single unbound associated type and a single excess generic param
|
||||||
// suggest replacing the generic param with the associated type bound
|
// suggest replacing the generic param with the associated type bound
|
||||||
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
|
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
|
||||||
let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
|
// Don't suggest if we're in a trait impl as
|
||||||
let suggestions = iter::zip(unused_generics, &unbound_types)
|
// that would result in invalid syntax (fixes #116464)
|
||||||
.map(|(potential, name)| (potential.span().shrink_to_lo(), format!("{name} = ")))
|
if !self.is_in_trait_impl() {
|
||||||
.collect::<Vec<_>>();
|
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} = "))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !suggestions.is_empty() {
|
if !suggestions.is_empty() {
|
||||||
err.multipart_suggestion_verbose(
|
err.multipart_suggestion_verbose(
|
||||||
format!(
|
format!(
|
||||||
"replace the generic bound{s} with the associated type{s}",
|
"replace the generic bound{s} with the associated type{s}",
|
||||||
s = pluralize!(unbound_types.len())
|
s = pluralize!(unbound_types.len())
|
||||||
),
|
),
|
||||||
suggestions,
|
suggestions,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if remove_entire_generics {
|
} else if remove_entire_generics {
|
||||||
let span = self
|
let span = self
|
||||||
|
@ -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