Skip to content

Commit f4f402a

Browse files
authored
Unrolled build for rust-lang#116865
Rollup merge of rust-lang#116865 - estebank:issue-46969, r=compiler-errors Suggest constraining assoc types in more cases Fix rust-lang#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 { | ++++++++ ```
2 parents e8b8c78 + dee86bf commit f4f402a

4 files changed

+102
-44
lines changed

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+58-44
Original file line numberDiff line numberDiff line change
@@ -341,39 +341,48 @@ impl<T> Trait<T> for X {
341341
let tcx = self.tcx;
342342
let assoc = tcx.associated_item(proj_ty.def_id);
343343
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
344-
if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) {
345-
if let Some(hir_generics) = item.generics() {
346-
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
347-
// This will also work for `impl Trait`.
348-
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
349-
let generics = tcx.generics_of(body_owner_def_id);
350-
generics.type_param(param_ty, tcx).def_id
351-
} else {
352-
return false;
353-
};
354-
let Some(def_id) = def_id.as_local() else {
355-
return false;
356-
};
357-
358-
// First look in the `where` clause, as this might be
359-
// `fn foo<T>(x: T) where T: Trait`.
360-
for pred in hir_generics.bounds_for_param(def_id) {
361-
if self.constrain_generic_bound_associated_type_structured_suggestion(
362-
diag,
363-
&trait_ref,
364-
pred.bounds,
365-
assoc,
366-
assoc_args,
367-
ty,
368-
&msg,
369-
false,
370-
) {
371-
return true;
372-
}
373-
}
344+
let Some(item) = tcx.hir().get_if_local(body_owner_def_id) else {
345+
return false;
346+
};
347+
let Some(hir_generics) = item.generics() else {
348+
return false;
349+
};
350+
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
351+
// This will also work for `impl Trait`.
352+
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
353+
let generics = tcx.generics_of(body_owner_def_id);
354+
generics.type_param(param_ty, tcx).def_id
355+
} else {
356+
return false;
357+
};
358+
let Some(def_id) = def_id.as_local() else {
359+
return false;
360+
};
361+
362+
// First look in the `where` clause, as this might be
363+
// `fn foo<T>(x: T) where T: Trait`.
364+
for pred in hir_generics.bounds_for_param(def_id) {
365+
if self.constrain_generic_bound_associated_type_structured_suggestion(
366+
diag,
367+
&trait_ref,
368+
pred.bounds,
369+
assoc,
370+
assoc_args,
371+
ty,
372+
&msg,
373+
false,
374+
) {
375+
return true;
374376
}
375377
}
376-
false
378+
// If associated item, look to constrain the params of the trait/impl.
379+
let hir_id = match item {
380+
hir::Node::ImplItem(item) => item.hir_id(),
381+
hir::Node::TraitItem(item) => item.hir_id(),
382+
_ => return false,
383+
};
384+
let parent = tcx.hir().get_parent_item(hir_id).def_id;
385+
self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
377386
}
378387

379388
/// An associated type was expected and a different type was found.
@@ -426,21 +435,26 @@ impl<T> Trait<T> for X {
426435
let impl_comparison =
427436
matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
428437
let assoc = tcx.associated_item(proj_ty.def_id);
429-
if !callable_scope || impl_comparison {
438+
if impl_comparison {
430439
// We do not want to suggest calling functions when the reason of the
431-
// type error is a comparison of an `impl` with its `trait` or when the
432-
// scope is outside of a `Body`.
440+
// type error is a comparison of an `impl` with its `trait`.
433441
} else {
434-
// If we find a suitable associated function that returns the expected type, we don't
435-
// want the more general suggestion later in this method about "consider constraining
436-
// the associated type or calling a method that returns the associated type".
437-
let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
438-
diag,
439-
assoc.container_id(tcx),
440-
current_method_ident,
441-
proj_ty.def_id,
442-
values.expected,
443-
);
442+
let point_at_assoc_fn = if callable_scope
443+
&& self.point_at_methods_that_satisfy_associated_type(
444+
diag,
445+
assoc.container_id(tcx),
446+
current_method_ident,
447+
proj_ty.def_id,
448+
values.expected,
449+
) {
450+
// If we find a suitable associated function that returns the expected type, we
451+
// don't want the more general suggestion later in this method about "consider
452+
// constraining the associated type or calling a method that returns the associated
453+
// type".
454+
true
455+
} else {
456+
false
457+
};
444458
// Possibly suggest constraining the associated type to conform to the
445459
// found type.
446460
if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-rustfix
2+
trait O {
3+
type M;
4+
}
5+
trait U<A: O> {
6+
const N: A::M;
7+
}
8+
impl<D> O for D {
9+
type M = u8;
10+
}
11+
impl<C: O<M = u8>> U<C> for u16 {
12+
const N: C::M = 4u8; //~ ERROR mismatched types
13+
}
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-rustfix
2+
trait O {
3+
type M;
4+
}
5+
trait U<A: O> {
6+
const N: A::M;
7+
}
8+
impl<D> O for D {
9+
type M = u8;
10+
}
11+
impl<C: O> U<C> for u16 {
12+
const N: C::M = 4u8; //~ ERROR mismatched types
13+
}
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21
3+
|
4+
LL | const N: C::M = 4u8;
5+
| ^^^ expected associated type, found `u8`
6+
|
7+
= note: expected associated type `<C as O>::M`
8+
found type `u8`
9+
help: consider constraining the associated type `<C as O>::M` to `u8`
10+
|
11+
LL | impl<C: O<M = u8>> U<C> for u16 {
12+
| ++++++++
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)