diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index e68e1a055d9..263959f3cb3 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -169,8 +169,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Equal types, all is good. return true; } + // Normalization reveals opaque types, but we may be validating MIR while computing + // said opaque types, causing cycles. + if (src, dest).has_opaque_types() { + return true; + } // Normalize projections and things like that. - let param_env = self.param_env; + let param_env = self.param_env.with_reveal_all_normalized(self.tcx); let src = self.tcx.normalize_erasing_regions(param_env, src); let dest = self.tcx.normalize_erasing_regions(param_env, dest); diff --git a/src/test/ui/impl-trait/projection.rs b/src/test/ui/impl-trait/projection.rs new file mode 100644 index 00000000000..21fc6591e97 --- /dev/null +++ b/src/test/ui/impl-trait/projection.rs @@ -0,0 +1,29 @@ +// build-pass +// needs to be build-pass, because it is a regression test for a mir validation failure +// that only happens during codegen. + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { None } +} + +fn run(f: F) + where for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} \ No newline at end of file