From 4898753d5d20a1a871053eece96ec8d5a4f690f8 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Tue, 11 Feb 2025 01:10:05 +0100 Subject: [PATCH 1/2] add test for const type_id misoptimization --- ...type_id_polymorphic.cursed_is_i32.GVN.diff | 13 +++++++++++ tests/mir-opt/gvn_type_id_polymorphic.rs | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff create mode 100644 tests/mir-opt/gvn_type_id_polymorphic.rs diff --git a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff new file mode 100644 index 0000000000000..c9d641472d035 --- /dev/null +++ b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff @@ -0,0 +1,13 @@ +- // MIR for `cursed_is_i32` before GVN ++ // MIR for `cursed_is_i32` after GVN + + fn cursed_is_i32() -> bool { + let mut _0: bool; + + bb0: { +- _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); ++ _0 = const false; + return; + } + } + diff --git a/tests/mir-opt/gvn_type_id_polymorphic.rs b/tests/mir-opt/gvn_type_id_polymorphic.rs new file mode 100644 index 0000000000000..a5b936e52dafa --- /dev/null +++ b/tests/mir-opt/gvn_type_id_polymorphic.rs @@ -0,0 +1,22 @@ +//@ test-mir-pass: GVN +//@ compile-flags: -C opt-level=2 + +#![feature(core_intrinsics)] + +fn generic() {} + +const fn type_id_of_val(_: &T) -> u128 { + std::intrinsics::type_id::() +} + +// EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff +fn cursed_is_i32() -> bool { + // CHECK-LABEL: fn cursed_is_i32( + // CHECK: _0 = const false; + // CHECK-NEXT: return; + (const { type_id_of_val(&generic::) } == const { type_id_of_val(&generic::) }) +} + +fn main() { + dbg!(cursed_is_i32::()); +} From c1da4f1d3c4fc4beb5edcfa8a303a1dcbe27b65e Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Mon, 10 Feb 2025 22:06:19 +0000 Subject: [PATCH 2/2] fix ensure_monomorphic_enough --- .../rustc_const_eval/src/interpret/util.rs | 44 ++----------------- ...type_id_polymorphic.cursed_is_i32.GVN.diff | 3 +- tests/mir-opt/gvn_type_id_polymorphic.rs | 2 +- 3 files changed, 5 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index eb98e3b538051..ba579e25f036a 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,12 +1,8 @@ -use std::ops::ControlFlow; - use rustc_hir::def_id::LocalDefId; use rustc_middle::mir; use rustc_middle::mir::interpret::{AllocInit, Allocation, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, -}; +use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt}; use tracing::debug; use super::{InterpCx, MPlaceTy, MemoryKind, interp_ok, throw_inval}; @@ -20,44 +16,10 @@ where T: TypeVisitable>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.has_param() { - return interp_ok(()); - } - - struct FoundParam; - struct UsedParamsNeedInstantiationVisitor {} - - impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor { - type Result = ControlFlow; - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - if !ty.has_param() { - return ControlFlow::Continue(()); - } - - match *ty.kind() { - ty::Param(_) => ControlFlow::Break(FoundParam), - ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::FnDef(..) => { - ControlFlow::Continue(()) - } - _ => ty.super_visit_with(self), - } - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { - match c.kind() { - ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), - _ => c.super_visit_with(self), - } - } - } - - let mut vis = UsedParamsNeedInstantiationVisitor {}; - if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { + if ty.has_param() { throw_inval!(TooGeneric); - } else { - interp_ok(()) } + interp_ok(()) } impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> { diff --git a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff index c9d641472d035..2f83f54d2afdb 100644 --- a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff +++ b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff @@ -5,8 +5,7 @@ let mut _0: bool; bb0: { -- _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); -+ _0 = const false; + _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); return; } } diff --git a/tests/mir-opt/gvn_type_id_polymorphic.rs b/tests/mir-opt/gvn_type_id_polymorphic.rs index a5b936e52dafa..39bc5c24ecc68 100644 --- a/tests/mir-opt/gvn_type_id_polymorphic.rs +++ b/tests/mir-opt/gvn_type_id_polymorphic.rs @@ -12,7 +12,7 @@ const fn type_id_of_val(_: &T) -> u128 { // EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff fn cursed_is_i32() -> bool { // CHECK-LABEL: fn cursed_is_i32( - // CHECK: _0 = const false; + // CHECK: _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); // CHECK-NEXT: return; (const { type_id_of_val(&generic::) } == const { type_id_of_val(&generic::) }) }