diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 87fb61623d1..2d027f16e5d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -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")); } diff --git a/tests/ui/traits/trivial-unsized-projection-in-coherence.rs b/tests/ui/traits/trivial-unsized-projection-in-coherence.rs new file mode 100644 index 00000000000..4407d544b4e --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-in-coherence.rs @@ -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() {} diff --git a/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr b/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr new file mode 100644 index 00000000000..52fca9479ca --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr @@ -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`.