From d486bfcbff107e8a6769e00c59d02b13c664b6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 12 Nov 2020 00:00:00 +0000 Subject: [PATCH 1/2] Normalize function type during validation During inlining, the callee body is normalized and has types revealed, but some of locals corresponding to the arguments might come from the caller body which is not. As a result the caller body does not pass validation without additional normalization. --- compiler/rustc_mir/src/transform/validate.rs | 2 ++ .../auxiliary/lib.rs | 4 ---- .../ui/mir/mir-inlining/ice-issue-77306-1.rs | 18 ++++++++++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index e1e6e71acb5a..2fbfe13082f8 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -357,7 +357,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } TerminatorKind::Call { func, args, destination, cleanup, .. } => { + let param_env = self.param_env.with_reveal_all_normalized(self.tcx); let func_ty = func.ty(&self.body.local_decls, self.tcx); + let func_ty = self.tcx.normalize_erasing_regions(param_env, func_ty); match func_ty.kind() { ty::FnPtr(..) | ty::FnDef(..) => {} _ => self.fail( diff --git a/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs b/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs index fb4bf2b8b44e..f3a51b415fac 100644 --- a/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs +++ b/src/test/ui/issues/issue-50865-private-impl-trait/auxiliary/lib.rs @@ -1,7 +1,3 @@ -// revisions: default miropt -//[miropt]compile-flags: -Z mir-opt-level=2 -// ~^ This flag is for #77668, it used to be ICE. - #![crate_type = "lib"] pub fn bar

( // Error won't happen if "bar" is not generic diff --git a/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs b/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs index 4d083bf23215..ccb279f7fa21 100644 --- a/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs +++ b/src/test/ui/mir/mir-inlining/ice-issue-77306-1.rs @@ -1,17 +1,27 @@ -// run-pass +// Regression test for various issues related to normalization & inlining. +// * #68347, #77306, #77668 - missed normalization during inlining. +// * #78442 - missed normalization in validator after inlining. +// +// build-pass // compile-flags:-Zmir-opt-level=2 -// Previously ICEd because we did not normalize during inlining, -// see https://github.com/rust-lang/rust/pull/77306 for more discussion. - pub fn write() { create()() } +pub fn write_generic(_t: T) { + hide()(); +} + pub fn create() -> impl FnOnce() { || () } +pub fn hide() -> impl Fn() { + write +} + fn main() { write(); + write_generic(()); } From 99be78d135e73197e04221c139a219ea6436e72a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 12 Nov 2020 00:00:00 +0000 Subject: [PATCH 2/2] Always use param_env_reveal_all_normalized in validator --- compiler/rustc_mir/src/transform/validate.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index 2fbfe13082f8..876ecee80c6a 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -38,7 +38,9 @@ pub struct Validator { impl<'tcx> MirPass<'tcx> for Validator { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let param_env = tcx.param_env(def_id); + // We need to param_env_reveal_all_normalized, as some optimizations + // change types in ways that require unfolding opaque types. + let param_env = tcx.param_env_reveal_all_normalized(def_id); let mir_phase = self.mir_phase; let always_live_locals = AlwaysLiveLocals::new(body); @@ -79,7 +81,6 @@ pub fn equal_up_to_regions( } // Normalize lifetimes away on both sides, then compare. - let param_env = param_env.with_reveal_all_normalized(tcx); let normalize = |ty: Ty<'tcx>| { tcx.normalize_erasing_regions( param_env, @@ -167,17 +168,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return true; } // Normalize projections and things like that. - // FIXME: We need to reveal_all, as some optimizations change types in ways - // that require unfolding opaque types. - 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); + let src = self.tcx.normalize_erasing_regions(self.param_env, src); + let dest = self.tcx.normalize_erasing_regions(self.param_env, dest); // Type-changing assignments can happen when subtyping is used. While // all normal lifetimes are erased, higher-ranked types with their // late-bound lifetimes are still around and can lead to type // differences. So we compare ignoring lifetimes. - equal_up_to_regions(self.tcx, param_env, src, dest) + equal_up_to_regions(self.tcx, self.param_env, src, dest) } } @@ -357,9 +355,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } TerminatorKind::Call { func, args, destination, cleanup, .. } => { - let param_env = self.param_env.with_reveal_all_normalized(self.tcx); let func_ty = func.ty(&self.body.local_decls, self.tcx); - let func_ty = self.tcx.normalize_erasing_regions(param_env, func_ty); + let func_ty = self.tcx.normalize_erasing_regions(self.param_env, func_ty); match func_ty.kind() { ty::FnPtr(..) | ty::FnDef(..) => {} _ => self.fail(