Fall back when relating two opaques by substs in MIR typeck

This commit is contained in:
Michael Goulet 2022-08-03 03:16:31 +00:00
parent 34a6cae28e
commit 28b6373b1d
5 changed files with 95 additions and 24 deletions

View File

@ -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,12 @@ 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| {
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), _)

View 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() {}

View 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`.

View 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() {}

View 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`.