From 28b6373b1d4f6fd58f3435da2551021034c4a9d4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 3 Aug 2022 03:16:31 +0000 Subject: [PATCH 1/2] Fall back when relating two opaques by substs in MIR typeck --- .../rustc_infer/src/infer/nll_relate/mod.rs | 54 ++++++++++--------- src/test/ui/impl-trait/issue-100075-2.rs | 8 +++ src/test/ui/impl-trait/issue-100075-2.stderr | 24 +++++++++ src/test/ui/impl-trait/issue-100075.rs | 21 ++++++++ src/test/ui/impl-trait/issue-100075.stderr | 12 +++++ 5 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/impl-trait/issue-100075-2.rs create mode 100644 src/test/ui/impl-trait/issue-100075-2.stderr create mode 100644 src/test/ui/impl-trait/issue-100075.rs create mode 100644 src/test/ui/impl-trait/issue-100075.stderr diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index bab4f3e9e362f..324aef9c01f6e 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -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), _) diff --git a/src/test/ui/impl-trait/issue-100075-2.rs b/src/test/ui/impl-trait/issue-100075-2.rs new file mode 100644 index 0000000000000..cf059af192512 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075-2.rs @@ -0,0 +1,8 @@ +fn opaque(t: T) -> impl Sized { + //~^ ERROR cannot resolve opaque type + //~| WARNING function cannot return without recursing + opaque(Some(t)) +} + +#[allow(dead_code)] +fn main() {} diff --git a/src/test/ui/impl-trait/issue-100075-2.stderr b/src/test/ui/impl-trait/issue-100075-2.stderr new file mode 100644 index 0000000000000..5a1f1a97d04e4 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075-2.stderr @@ -0,0 +1,24 @@ +warning: function cannot return without recursing + --> $DIR/issue-100075-2.rs:1:1 + | +LL | fn opaque(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) -> 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`. diff --git a/src/test/ui/impl-trait/issue-100075.rs b/src/test/ui/impl-trait/issue-100075.rs new file mode 100644 index 0000000000000..ea30abb4855f3 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075.rs @@ -0,0 +1,21 @@ +trait Marker {} +impl Marker for T {} + +fn maybe( + _t: T, +) -> Option< + //removing the line below makes it compile + &'static T, +> { + None +} + +fn _g(t: &'static T) -> &'static impl Marker { + //~^ ERROR cannot resolve opaque type + if let Some(t) = maybe(t) { + return _g(t); + } + todo!() +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-100075.stderr b/src/test/ui/impl-trait/issue-100075.stderr new file mode 100644 index 0000000000000..267ecfdaed124 --- /dev/null +++ b/src/test/ui/impl-trait/issue-100075.stderr @@ -0,0 +1,12 @@ +error[E0720]: cannot resolve opaque type + --> $DIR/issue-100075.rs:13:37 + | +LL | fn _g(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`. From 534426d0f3d12b735b0018bcf268b08a09cc09b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 10 Aug 2022 03:36:05 +0000 Subject: [PATCH 2/2] Delay a bug if we try and fail to relate an opaque to itself in TypeRelating --- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 324aef9c01f6e..e7e93116a66d1 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -599,6 +599,10 @@ where (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => { 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) } }) }