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.
This commit is contained in:
commit
e63424db19
5 changed files with 99 additions and 24 deletions
|
|
@ -396,6 +396,32 @@ where
|
|||
|
||||
generalizer.relate(value, value)
|
||||
}
|
||||
|
||||
fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
|
||||
let mut generalize = |ty, ty_is_expected| {
|
||||
let var = self.infcx.next_ty_var_id_in_universe(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.delegate.span(),
|
||||
},
|
||||
ty::UniverseIndex::ROOT,
|
||||
);
|
||||
if ty_is_expected {
|
||||
self.relate_ty_var((ty, var))
|
||||
} else {
|
||||
self.relate_ty_var((var, ty))
|
||||
}
|
||||
};
|
||||
let (a, b) = match (a.kind(), b.kind()) {
|
||||
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
|
||||
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.delegate.register_opaque_type(a, b, true)?;
|
||||
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
|
||||
Ok(a)
|
||||
}
|
||||
}
|
||||
|
||||
/// When we instantiate an inference variable with a value in
|
||||
|
|
@ -572,32 +598,16 @@ where
|
|||
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
|
||||
|
||||
(&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
|
||||
self.infcx.super_combine_tys(self, a, b)
|
||||
infcx.commit_if_ok(|_| infcx.super_combine_tys(self, a, b)).or_else(|err| {
|
||||
self.tcx().sess.delay_span_bug(
|
||||
self.delegate.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
);
|
||||
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
|
||||
})
|
||||
}
|
||||
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
|
||||
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
|
||||
let mut generalize = |ty, ty_is_expected| {
|
||||
let var = infcx.next_ty_var_id_in_universe(
|
||||
TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.delegate.span(),
|
||||
},
|
||||
ty::UniverseIndex::ROOT,
|
||||
);
|
||||
if ty_is_expected {
|
||||
self.relate_ty_var((ty, var))
|
||||
} else {
|
||||
self.relate_ty_var((var, ty))
|
||||
}
|
||||
};
|
||||
let (a, b) = match (a.kind(), b.kind()) {
|
||||
(&ty::Opaque(..), _) => (a, generalize(b, false)?),
|
||||
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
self.delegate.register_opaque_type(a, b, true)?;
|
||||
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
|
||||
Ok(a)
|
||||
self.relate_opaques(a, b)
|
||||
}
|
||||
|
||||
(&ty::Projection(projection_ty), _)
|
||||
|
|
|
|||
8
src/test/ui/impl-trait/issue-100075-2.rs
Normal file
8
src/test/ui/impl-trait/issue-100075-2.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fn opaque<T>(t: T) -> impl Sized {
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
//~| WARNING function cannot return without recursing
|
||||
opaque(Some(t))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn main() {}
|
||||
24
src/test/ui/impl-trait/issue-100075-2.stderr
Normal file
24
src/test/ui/impl-trait/issue-100075-2.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
warning: function cannot return without recursing
|
||||
--> $DIR/issue-100075-2.rs:1:1
|
||||
|
|
||||
LL | fn opaque<T>(t: T) -> impl Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
|
||||
...
|
||||
LL | opaque(Some(t))
|
||||
| --------------- recursive call site
|
||||
|
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
|
||||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/issue-100075-2.rs:1:23
|
||||
|
|
||||
LL | fn opaque<T>(t: T) -> impl Sized {
|
||||
| ^^^^^^^^^^ recursive opaque type
|
||||
...
|
||||
LL | opaque(Some(t))
|
||||
| --------------- returning here with type `impl Sized`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
21
src/test/ui/impl-trait/issue-100075.rs
Normal file
21
src/test/ui/impl-trait/issue-100075.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
trait Marker {}
|
||||
impl<T> Marker for T {}
|
||||
|
||||
fn maybe<T>(
|
||||
_t: T,
|
||||
) -> Option<
|
||||
//removing the line below makes it compile
|
||||
&'static T,
|
||||
> {
|
||||
None
|
||||
}
|
||||
|
||||
fn _g<T>(t: &'static T) -> &'static impl Marker {
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
if let Some(t) = maybe(t) {
|
||||
return _g(t);
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
12
src/test/ui/impl-trait/issue-100075.stderr
Normal file
12
src/test/ui/impl-trait/issue-100075.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error[E0720]: cannot resolve opaque type
|
||||
--> $DIR/issue-100075.rs:13:37
|
||||
|
|
||||
LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
|
||||
| ^^^^^^^^^^^ recursive opaque type
|
||||
...
|
||||
LL | return _g(t);
|
||||
| ----- returning here with type `&impl Marker`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0720`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue