Make unnormalizable item ambiguous in coherence

This commit is contained in:
Michael Goulet 2025-03-31 18:56:09 +00:00
parent 830aeb6102
commit 6cd724bb43
3 changed files with 78 additions and 2 deletions

View File

@ -238,8 +238,24 @@ where
// delay a bug because we can have trivially false where clauses, so we
// treat it as rigid.
if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
match ecx.typing_mode() {
ty::TypingMode::Coherence => {
return ecx.evaluate_added_goals_and_make_canonical_response(
Certainty::AMBIGUOUS,
);
}
ty::TypingMode::Analysis { .. }
| ty::TypingMode::Borrowck { .. }
| ty::TypingMode::PostBorrowckAnalysis { .. }
| ty::TypingMode::PostAnalysis => {
ecx.structurally_instantiate_normalizes_to_term(
goal,
goal.predicate.alias,
);
return ecx
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
}
}
} else {
return error_response(ecx, cx.delay_bug("missing item"));
}

View File

@ -0,0 +1,45 @@
// Make sure we don't treat missing associated items as rigid
// during coherence, even if we know they've got an impossible
// `Sized`-bound. As we check whether the self type is definitely
// not `Sized` outside of coherence, this check can be incomplete.
//
// In this test we only use `impl<T> Overlap<u32> for T` to normalize
// the field of `MaybeUnsized<T, u32>` when checking whether it's
// definitely not `Sized`. However, for `MaybeUnsized<u32, u32>` we
// could also use `impl<U> Overlap<U> for u32` for normalization, which
// would result in a `Sized` type. cc #139000
struct MaybeUnsized<T: Overlap<U>, U>(<T as Overlap<U>>::MaybeUnsized);
trait ReqSized {
type Missing1
where
Self: Sized;
type Missing2
where
Self: Sized;
}
impl<T> ReqSized for MaybeUnsized<T, u32> {}
struct W<T: ?Sized>(T);
trait Eq<T> {}
impl<T> Eq<T> for W<T> {}
trait RelateReqSized {}
impl<T: ReqSized> RelateReqSized for T where W<T::Missing1>: Eq<T::Missing2> {}
trait Overlap<U> {
type MaybeUnsized: ?Sized;
}
impl<T> Overlap<u32> for T {
type MaybeUnsized = str;
}
impl<U> Overlap<U> for u32
//~^ ERROR conflicting implementations of trait `Overlap<u32>` for type `u32`
where
MaybeUnsized<U, u32>: RelateReqSized,
{
type MaybeUnsized = u32;
}
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0119]: conflicting implementations of trait `Overlap<u32>` for type `u32`
--> $DIR/trivial-unsized-projection-in-coherence.rs:37:1
|
LL | impl<T> Overlap<u32> for T {
| -------------------------- first implementation here
...
LL | / impl<U> Overlap<U> for u32
LL | |
LL | | where
LL | | MaybeUnsized<U, u32>: RelateReqSized,
| |_________________________________________^ conflicting implementation for `u32`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0119`.