Rollup merge of #116865 - estebank:issue-46969, r=compiler-errors
Suggest constraining assoc types in more cases Fix #46969. ``` error[E0308]: mismatched types --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` | = note: expected associated type `<C as O>::M` found type `u8` help: consider constraining the associated type `<C as O>::M` to `u8` | LL | impl<C: O<M = u8>> U<C> for u16 { | ++++++++ ```
This commit is contained in:
commit
d69cdb2ceb
@ -341,39 +341,48 @@ impl<T> Trait<T> for X {
|
|||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let assoc = tcx.associated_item(proj_ty.def_id);
|
let assoc = tcx.associated_item(proj_ty.def_id);
|
||||||
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
|
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
|
||||||
if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) {
|
let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else {
|
||||||
if let Some(hir_generics) = item.generics() {
|
return false;
|
||||||
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
|
};
|
||||||
// This will also work for `impl Trait`.
|
let Some(hir_generics) = item.generics() else {
|
||||||
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
|
return false;
|
||||||
let generics = tcx.generics_of(body_owner_def_id);
|
};
|
||||||
generics.type_param(param_ty, tcx).def_id
|
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
|
||||||
} else {
|
// This will also work for `impl Trait`.
|
||||||
return false;
|
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
|
||||||
};
|
let generics = tcx.generics_of(body_owner_def_id);
|
||||||
let Some(def_id) = def_id.as_local() else {
|
generics.type_param(param_ty, tcx).def_id
|
||||||
return false;
|
} else {
|
||||||
};
|
return false;
|
||||||
|
};
|
||||||
|
let Some(def_id) = def_id.as_local() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// First look in the `where` clause, as this might be
|
// First look in the `where` clause, as this might be
|
||||||
// `fn foo<T>(x: T) where T: Trait`.
|
// `fn foo<T>(x: T) where T: Trait`.
|
||||||
for pred in hir_generics.bounds_for_param(def_id) {
|
for pred in hir_generics.bounds_for_param(def_id) {
|
||||||
if self.constrain_generic_bound_associated_type_structured_suggestion(
|
if self.constrain_generic_bound_associated_type_structured_suggestion(
|
||||||
diag,
|
diag,
|
||||||
&trait_ref,
|
&trait_ref,
|
||||||
pred.bounds,
|
pred.bounds,
|
||||||
assoc,
|
assoc,
|
||||||
assoc_args,
|
assoc_args,
|
||||||
ty,
|
ty,
|
||||||
&msg,
|
&msg,
|
||||||
false,
|
false,
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
// If associated item, look to constrain the params of the trait/impl.
|
||||||
|
let hir_id = match item {
|
||||||
|
hir::Node::ImplItem(item) => item.hir_id(),
|
||||||
|
hir::Node::TraitItem(item) => item.hir_id(),
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
let parent = tcx.hir().get_parent_item(hir_id).def_id;
|
||||||
|
self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An associated type was expected and a different type was found.
|
/// An associated type was expected and a different type was found.
|
||||||
@ -426,21 +435,26 @@ impl<T> Trait<T> for X {
|
|||||||
let impl_comparison =
|
let impl_comparison =
|
||||||
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
|
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
|
||||||
let assoc = tcx.associated_item(proj_ty.def_id);
|
let assoc = tcx.associated_item(proj_ty.def_id);
|
||||||
if !callable_scope || impl_comparison {
|
if impl_comparison {
|
||||||
// We do not want to suggest calling functions when the reason of the
|
// We do not want to suggest calling functions when the reason of the
|
||||||
// type error is a comparison of an `impl` with its `trait` or when the
|
// type error is a comparison of an `impl` with its `trait`.
|
||||||
// scope is outside of a `Body`.
|
|
||||||
} else {
|
} else {
|
||||||
// If we find a suitable associated function that returns the expected type, we don't
|
let point_at_assoc_fn = if callable_scope
|
||||||
// want the more general suggestion later in this method about "consider constraining
|
&& self.point_at_methods_that_satisfy_associated_type(
|
||||||
// the associated type or calling a method that returns the associated type".
|
diag,
|
||||||
let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
|
assoc.container_id(tcx),
|
||||||
diag,
|
current_method_ident,
|
||||||
assoc.container_id(tcx),
|
proj_ty.def_id,
|
||||||
current_method_ident,
|
values.expected,
|
||||||
proj_ty.def_id,
|
) {
|
||||||
values.expected,
|
// If we find a suitable associated function that returns the expected type, we
|
||||||
);
|
// don't want the more general suggestion later in this method about "consider
|
||||||
|
// constraining the associated type or calling a method that returns the associated
|
||||||
|
// type".
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
// Possibly suggest constraining the associated type to conform to the
|
// Possibly suggest constraining the associated type to conform to the
|
||||||
// found type.
|
// found type.
|
||||||
if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
|
if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
// run-rustfix
|
||||||
|
trait O {
|
||||||
|
type M;
|
||||||
|
}
|
||||||
|
trait U<A: O> {
|
||||||
|
const N: A::M;
|
||||||
|
}
|
||||||
|
impl<D> O for D {
|
||||||
|
type M = u8;
|
||||||
|
}
|
||||||
|
impl<C: O<M = u8>> U<C> for u16 {
|
||||||
|
const N: C::M = 4u8; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
fn main() {}
|
@ -0,0 +1,14 @@
|
|||||||
|
// run-rustfix
|
||||||
|
trait O {
|
||||||
|
type M;
|
||||||
|
}
|
||||||
|
trait U<A: O> {
|
||||||
|
const N: A::M;
|
||||||
|
}
|
||||||
|
impl<D> O for D {
|
||||||
|
type M = u8;
|
||||||
|
}
|
||||||
|
impl<C: O> U<C> for u16 {
|
||||||
|
const N: C::M = 4u8; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
fn main() {}
|
@ -0,0 +1,16 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21
|
||||||
|
|
|
||||||
|
LL | const N: C::M = 4u8;
|
||||||
|
| ^^^ expected associated type, found `u8`
|
||||||
|
|
|
||||||
|
= note: expected associated type `<C as O>::M`
|
||||||
|
found type `u8`
|
||||||
|
help: consider constraining the associated type `<C as O>::M` to `u8`
|
||||||
|
|
|
||||||
|
LL | impl<C: O<M = u8>> U<C> for u16 {
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
x
Reference in New Issue
Block a user