Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 0a6ae29

Browse files
committed
coherence: don't add hidden types for opaques
we can otherwise assign a hidden type to the opaque which causes ICE if we don't use `take_opaque_types` during coherence. This is annoying so I didn't bother. Added a test showing the behavior this prevents.
1 parent 200ed9f commit 0a6ae29

File tree

3 files changed

+59
-10
lines changed

3 files changed

+59
-10
lines changed

compiler/rustc_infer/src/infer/opaque_types.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -533,17 +533,29 @@ impl<'tcx> InferCtxt<'tcx> {
533533
// these are the same span, but not in cases like `-> (impl
534534
// Foo, impl Bar)`.
535535
let span = cause.span;
536-
let prev = self.inner.borrow_mut().opaque_types().register(
537-
opaque_type_key,
538-
OpaqueHiddenType { ty: hidden_ty, span },
539-
origin,
540-
);
541-
let mut obligations = if let Some(prev) = prev {
542-
self.at(&cause, param_env)
543-
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
544-
.obligations
536+
let mut obligations = if self.intercrate {
537+
// During intercrate we do not define opaque types but instead always
538+
// force ambiguity unless the hidden type is known to not implement
539+
// our trait.
540+
vec![traits::Obligation::new(
541+
self.tcx,
542+
cause.clone(),
543+
param_env,
544+
ty::PredicateKind::Ambiguous,
545+
)]
545546
} else {
546-
Vec::new()
547+
let prev = self.inner.borrow_mut().opaque_types().register(
548+
opaque_type_key,
549+
OpaqueHiddenType { ty: hidden_ty, span },
550+
origin,
551+
);
552+
if let Some(prev) = prev {
553+
self.at(&cause, param_env)
554+
.eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
555+
.obligations
556+
} else {
557+
Vec::new()
558+
}
547559
};
548560

549561
self.add_item_bounds_for_hidden_type(
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// When checking whether these two impls overlap, we could detect that we
2+
// would require the hidden type of `TAIT` to be equal to both `u32` and `i32`
3+
// and therefore accept them as disjoint. That is annoying to implement with
4+
// the current system because we would have to add the following to each
5+
// returning branch in coherence.
6+
//
7+
// let _ = infcx.take_opaque_types();
8+
//
9+
// @lcnr: Because of this I decided to not bother and cause this to fail instead.
10+
// In the future we can definitely modify the compiler to accept this
11+
// again.
12+
#![feature(type_alias_impl_trait)]
13+
14+
trait Trait {}
15+
16+
type TAIT = impl Sized;
17+
18+
impl Trait for (TAIT, TAIT) {}
19+
20+
impl Trait for (u32, i32) {}
21+
//~^ ERROR conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
22+
23+
fn define() -> TAIT {}
24+
25+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0119]: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
2+
--> $DIR/coherence_different_hidden_ty.rs:20:1
3+
|
4+
LL | impl Trait for (TAIT, TAIT) {}
5+
| --------------------------- first implementation here
6+
LL |
7+
LL | impl Trait for (u32, i32) {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(TAIT, TAIT)`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0119`.

0 commit comments

Comments
 (0)