Skip to content

Commit 6cd724b

Browse files
Make unnormalizable item ambiguous in coherence
1 parent 830aeb6 commit 6cd724b

File tree

3 files changed

+78
-2
lines changed

3 files changed

+78
-2
lines changed

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,24 @@ where
238238
// delay a bug because we can have trivially false where clauses, so we
239239
// treat it as rigid.
240240
if cx.impl_self_is_guaranteed_unsized(impl_def_id) {
241-
ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
242-
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
241+
match ecx.typing_mode() {
242+
ty::TypingMode::Coherence => {
243+
return ecx.evaluate_added_goals_and_make_canonical_response(
244+
Certainty::AMBIGUOUS,
245+
);
246+
}
247+
ty::TypingMode::Analysis { .. }
248+
| ty::TypingMode::Borrowck { .. }
249+
| ty::TypingMode::PostBorrowckAnalysis { .. }
250+
| ty::TypingMode::PostAnalysis => {
251+
ecx.structurally_instantiate_normalizes_to_term(
252+
goal,
253+
goal.predicate.alias,
254+
);
255+
return ecx
256+
.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
257+
}
258+
}
243259
} else {
244260
return error_response(ecx, cx.delay_bug("missing item"));
245261
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Make sure we don't treat missing associated items as rigid
2+
// during coherence, even if we know they've got an impossible
3+
// `Sized`-bound. As we check whether the self type is definitely
4+
// not `Sized` outside of coherence, this check can be incomplete.
5+
//
6+
// In this test we only use `impl<T> Overlap<u32> for T` to normalize
7+
// the field of `MaybeUnsized<T, u32>` when checking whether it's
8+
// definitely not `Sized`. However, for `MaybeUnsized<u32, u32>` we
9+
// could also use `impl<U> Overlap<U> for u32` for normalization, which
10+
// would result in a `Sized` type. cc #139000
11+
12+
struct MaybeUnsized<T: Overlap<U>, U>(<T as Overlap<U>>::MaybeUnsized);
13+
14+
trait ReqSized {
15+
type Missing1
16+
where
17+
Self: Sized;
18+
type Missing2
19+
where
20+
Self: Sized;
21+
}
22+
impl<T> ReqSized for MaybeUnsized<T, u32> {}
23+
24+
struct W<T: ?Sized>(T);
25+
trait Eq<T> {}
26+
impl<T> Eq<T> for W<T> {}
27+
28+
trait RelateReqSized {}
29+
impl<T: ReqSized> RelateReqSized for T where W<T::Missing1>: Eq<T::Missing2> {}
30+
31+
trait Overlap<U> {
32+
type MaybeUnsized: ?Sized;
33+
}
34+
impl<T> Overlap<u32> for T {
35+
type MaybeUnsized = str;
36+
}
37+
impl<U> Overlap<U> for u32
38+
//~^ ERROR conflicting implementations of trait `Overlap<u32>` for type `u32`
39+
where
40+
MaybeUnsized<U, u32>: RelateReqSized,
41+
{
42+
type MaybeUnsized = u32;
43+
}
44+
45+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0119]: conflicting implementations of trait `Overlap<u32>` for type `u32`
2+
--> $DIR/trivial-unsized-projection-in-coherence.rs:37:1
3+
|
4+
LL | impl<T> Overlap<u32> for T {
5+
| -------------------------- first implementation here
6+
...
7+
LL | / impl<U> Overlap<U> for u32
8+
LL | |
9+
LL | | where
10+
LL | | MaybeUnsized<U, u32>: RelateReqSized,
11+
| |_________________________________________^ conflicting implementation for `u32`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)