Skip to content

Commit e63424d

Browse files
authored
Rollup merge of #100092 - compiler-errors:issue-100075, r=oli-obk
Fall back when relating two opaques by substs in MIR typeck This is certainly _one_ way to fix #100075. Not really confident it's the _best_ way to do it, though. The root cause of this issue is that during MIR type-check, we end up trying to equate an opaque against the same opaque def-id but with different substs. Because of the way that we replace RPITs during (HIR) typeck with an inference variable, we don't end up emitting a type-checking error, so the delayed MIR bug causes an ICE. See the `src/test/ui/impl-trait/issue-100075-2.rs` test below to make that clear -- in that example, we try to equate `{impl Sized} substs=[T]` and `{impl Sized} substs=[Option<T>]`, which causes an ICE. This new logic will instead cause us to infer `{impl Sized} substs=[Option<T>]` as the hidden type for `{impl Sized} substs=[T]`, which causes a proper error to be emitted later on when we check that an opaque isn't recursive. I'm open to closing this in favor of something else. Ideally we'd fix this in typeck, but the thing we do to ensure backwards compatibility with weird RPIT cases makes that difficult. Also open to discussing this further.
2 parents c731157 + 534426d commit e63424d

File tree

5 files changed

+99
-24
lines changed

5 files changed

+99
-24
lines changed

compiler/rustc_infer/src/infer/nll_relate/mod.rs

+34-24
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,32 @@ where
396396

397397
generalizer.relate(value, value)
398398
}
399+
400+
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
401+
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
402+
let mut generalize = |ty, ty_is_expected| {
403+
let var = self.infcx.next_ty_var_id_in_universe(
404+
TypeVariableOrigin {
405+
kind: TypeVariableOriginKind::MiscVariable,
406+
span: self.delegate.span(),
407+
},
408+
ty::UniverseIndex::ROOT,
409+
);
410+
if ty_is_expected {
411+
self.relate_ty_var((ty, var))
412+
} else {
413+
self.relate_ty_var((var, ty))
414+
}
415+
};
416+
let (a, b) = match (a.kind(), b.kind()) {
417+
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
418+
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
419+
_ => unreachable!(),
420+
};
421+
self.delegate.register_opaque_type(a, b, true)?;
422+
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
423+
Ok(a)
424+
}
399425
}
400426

401427
/// When we instantiate an inference variable with a value in
@@ -572,32 +598,16 @@ where
572598
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
573599

574600
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
575-
self.infcx.super_combine_tys(self, a, b)
601+
infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
602+
self.tcx().sess.delay_span_bug(
603+
self.delegate.span(),
604+
"failure to relate an opaque to itself should result in an error later on",
605+
);
606+
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
607+
})
576608
}
577609
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
578-
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
579-
let mut generalize = |ty, ty_is_expected| {
580-
let var = infcx.next_ty_var_id_in_universe(
581-
TypeVariableOrigin {
582-
kind: TypeVariableOriginKind::MiscVariable,
583-
span: self.delegate.span(),
584-
},
585-
ty::UniverseIndex::ROOT,
586-
);
587-
if ty_is_expected {
588-
self.relate_ty_var((ty, var))
589-
} else {
590-
self.relate_ty_var((var, ty))
591-
}
592-
};
593-
let (a, b) = match (a.kind(), b.kind()) {
594-
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
595-
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
596-
_ => unreachable!(),
597-
};
598-
self.delegate.register_opaque_type(a, b, true)?;
599-
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
600-
Ok(a)
610+
self.relate_opaques(a, b)
601611
}
602612

603613
(&ty::Projection(projection_ty), _)
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn opaque<T>(t: T) -> impl Sized {
2+
//~^ ERROR cannot resolve opaque type
3+
//~| WARNING function cannot return without recursing
4+
opaque(Some(t))
5+
}
6+
7+
#[allow(dead_code)]
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
warning: function cannot return without recursing
2+
--> $DIR/issue-100075-2.rs:1:1
3+
|
4+
LL | fn opaque<T>(t: T) -> impl Sized {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
6+
...
7+
LL | opaque(Some(t))
8+
| --------------- recursive call site
9+
|
10+
= note: `#[warn(unconditional_recursion)]` on by default
11+
= help: a `loop` may express intention better if this is on purpose
12+
13+
error[E0720]: cannot resolve opaque type
14+
--> $DIR/issue-100075-2.rs:1:23
15+
|
16+
LL | fn opaque<T>(t: T) -> impl Sized {
17+
| ^^^^^^^^^^ recursive opaque type
18+
...
19+
LL | opaque(Some(t))
20+
| --------------- returning here with type `impl Sized`
21+
22+
error: aborting due to previous error; 1 warning emitted
23+
24+
For more information about this error, try `rustc --explain E0720`.
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
trait Marker {}
2+
impl<T> Marker for T {}
3+
4+
fn maybe<T>(
5+
_t: T,
6+
) -> Option<
7+
//removing the line below makes it compile
8+
&'static T,
9+
> {
10+
None
11+
}
12+
13+
fn _g<T>(t: &'static T) -> &'static impl Marker {
14+
//~^ ERROR cannot resolve opaque type
15+
if let Some(t) = maybe(t) {
16+
return _g(t);
17+
}
18+
todo!()
19+
}
20+
21+
fn main() {}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0720]: cannot resolve opaque type
2+
--> $DIR/issue-100075.rs:13:37
3+
|
4+
LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
5+
| ^^^^^^^^^^^ recursive opaque type
6+
...
7+
LL | return _g(t);
8+
| ----- returning here with type `&impl Marker`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0720`.

0 commit comments

Comments
 (0)