about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-02-10 17:53:35 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-28 16:30:16 +0000
commit4cfaf9a93121f3b4a57f59ebfc1991c6f4b892a8 (patch)
tree1c3af4badd433ae2b9c929a341bde5e2d03ab59b
parent1c5bfb17703975ff9952243c24c46cf54fe0d49c (diff)
downloadrust-4cfaf9a93121f3b4a57f59ebfc1991c6f4b892a8.tar.gz
rust-4cfaf9a93121f3b4a57f59ebfc1991c6f4b892a8.zip
Normalize all projections in mir validation again
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs7
-rw-r--r--src/test/ui/impl-trait/projection.rs29
2 files changed, 35 insertions, 1 deletions
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<Self::It>;
+}
+
+impl<'a> Tr for &'a D {
+    type It = ();
+    fn foo(self) -> Option<()> { None }
+}
+
+fn run<F>(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