Skip to content

Commit c6fb0f3

Browse files
committed
diagnostics: use DeepRejectCtxt for check
This makes more things match, particularly applicable blankets.
1 parent 3312f5d commit c6fb0f3

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

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

+28-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_hir as hir;
44
use rustc_hir::def::DefKind;
55
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
66
use rustc_middle::ty::error::{ExpectedFound, TypeError};
7+
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
78
use rustc_middle::ty::print::{FmtPrinter, Printer};
89
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
910
use rustc_span::def_id::DefId;
@@ -313,9 +314,15 @@ impl<T> Trait<T> for X {
313314
(ty::Dynamic(t, _, ty::DynKind::Dyn), _)
314315
if let Some(def_id) = t.principal_def_id() =>
315316
{
316-
let has_non_blanket_impl =
317-
tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some();
318-
if has_non_blanket_impl {
317+
let mut has_matching_impl = false;
318+
tcx.for_each_relevant_impl(def_id, values.found, |did| {
319+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
320+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
321+
{
322+
has_matching_impl = true;
323+
}
324+
});
325+
if has_matching_impl {
319326
let trait_name = tcx.item_name(def_id);
320327
diag.help(format!(
321328
"`{}` implements `{trait_name}` so you could box the found value \
@@ -328,9 +335,15 @@ impl<T> Trait<T> for X {
328335
(_, ty::Dynamic(t, _, ty::DynKind::Dyn))
329336
if let Some(def_id) = t.principal_def_id() =>
330337
{
331-
let has_non_blanket_impl =
332-
tcx.non_blanket_impls_for_ty(def_id, values.expected).next().is_some();
333-
if has_non_blanket_impl {
338+
let mut has_matching_impl = false;
339+
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
340+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
341+
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
342+
{
343+
has_matching_impl = true;
344+
}
345+
});
346+
if has_matching_impl {
334347
let trait_name = tcx.item_name(def_id);
335348
diag.help(format!(
336349
"`{}` implements `{trait_name}` so you could change the expected \
@@ -342,9 +355,15 @@ impl<T> Trait<T> for X {
342355
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
343356
if let Some(def_id) = t.principal_def_id() =>
344357
{
345-
let has_non_blanket_impl =
346-
tcx.non_blanket_impls_for_ty(def_id, values.found).next().is_some();
347-
if has_non_blanket_impl {
358+
let mut has_matching_impl = false;
359+
tcx.for_each_relevant_impl(def_id, values.found, |did| {
360+
if DeepRejectCtxt::new(tcx, TreatParams::ForLookup)
361+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
362+
{
363+
has_matching_impl = true;
364+
}
365+
});
366+
if has_matching_impl {
348367
let trait_name = tcx.item_name(def_id);
349368
diag.help(format!(
350369
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \

tests/ui/cast/ptr-to-trait-obj-different-args.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ LL | let y: *const dyn Trait<Y> = x as _;
1414
|
1515
= note: expected trait object `dyn Trait<X>`
1616
found trait object `dyn Trait<Y>`
17+
= help: `dyn Trait<Y>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
1718

1819
error[E0308]: mismatched types
1920
--> $DIR/ptr-to-trait-obj-different-args.rs:27:34
@@ -25,6 +26,7 @@ LL | let _: *const dyn Trait<T> = x as _;
2526
|
2627
= note: expected trait object `dyn Trait<X>`
2728
found trait object `dyn Trait<T>`
29+
= help: `dyn Trait<T>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
2830

2931
error[E0308]: mismatched types
3032
--> $DIR/ptr-to-trait-obj-different-args.rs:28:34
@@ -37,6 +39,7 @@ LL | let _: *const dyn Trait<X> = t as _;
3739
|
3840
= note: expected trait object `dyn Trait<T>`
3941
found trait object `dyn Trait<X>`
42+
= help: `dyn Trait<X>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
4043

4144
error[E0308]: mismatched types
4245
--> $DIR/ptr-to-trait-obj-different-args.rs:36:5

tests/ui/traits/upcast_soundness_bug.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ LL | let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
66
|
77
= note: expected trait object `dyn Trait<u8, u8>`
88
found trait object `dyn Trait<u8, u16>`
9+
= help: `dyn Trait<u8, u16>` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
910

1011
error: aborting due to 1 previous error
1112

0 commit comments

Comments
 (0)