about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs54
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs1
3 files changed, 44 insertions, 13 deletions
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index b44d2a01d57..ed5489652fb 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -51,6 +51,8 @@ pub fn provide(providers: &mut Providers) {
     providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
+    providers.hooks.validate_scalar_in_layout =
+        |tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout);
 }
 
 /// `rustc_driver::main` installs a handler that will set this to `true` if
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index a729d9325c8..79baf91c3ce 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,9 +1,10 @@
 use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants};
-use rustc_middle::bug;
 use rustc_middle::ty::layout::{
     HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
 };
-use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
+use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt};
+use rustc_middle::{bug, ty};
+use rustc_span::DUMMY_SP;
 
 use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
 use crate::interpret::{InterpCx, MemoryKind};
@@ -34,7 +35,7 @@ pub fn check_validity_requirement<'tcx>(
 
     let layout_cx = LayoutCx::new(tcx, input.typing_env);
     if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
-        check_validity_requirement_strict(layout, &layout_cx, kind)
+        Ok(check_validity_requirement_strict(layout, &layout_cx, kind))
     } else {
         check_validity_requirement_lax(layout, &layout_cx, kind)
     }
@@ -46,10 +47,10 @@ fn check_validity_requirement_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx>,
     kind: ValidityRequirement,
-) -> Result<bool, &'tcx LayoutError<'tcx>> {
+) -> bool {
     let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
 
-    let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine);
+    let mut cx = InterpCx::new(cx.tcx(), DUMMY_SP, cx.typing_env, machine);
 
     let allocated = cx
         .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
@@ -69,14 +70,13 @@ fn check_validity_requirement_strict<'tcx>(
     // due to this.
     // The value we are validating is temporary and discarded at the end of this function, so
     // there is no point in reseting provenance and padding.
-    Ok(cx
-        .validate_operand(
-            &allocated.into(),
-            /*recursive*/ false,
-            /*reset_provenance_and_padding*/ false,
-        )
-        .discard_err()
-        .is_some())
+    cx.validate_operand(
+        &allocated.into(),
+        /*recursive*/ false,
+        /*reset_provenance_and_padding*/ false,
+    )
+    .discard_err()
+    .is_some()
 }
 
 /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
@@ -168,3 +168,31 @@ fn check_validity_requirement_lax<'tcx>(
 
     Ok(true)
 }
+
+pub(crate) fn validate_scalar_in_layout<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    scalar: ScalarInt,
+    ty: Ty<'tcx>,
+) -> bool {
+    let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
+
+    let typing_env = ty::TypingEnv::fully_monomorphized();
+    let mut cx = InterpCx::new(tcx, DUMMY_SP, typing_env, machine);
+
+    let Ok(layout) = cx.layout_of(ty) else {
+        bug!("could not compute layout of {scalar:?}:{ty:?}")
+    };
+    let allocated = cx
+        .allocate(layout, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
+        .expect("OOM: failed to allocate for uninit check");
+
+    cx.write_scalar(scalar, &allocated).unwrap();
+
+    cx.validate_operand(
+        &allocated.into(),
+        /*recursive*/ false,
+        /*reset_provenance_and_padding*/ false,
+    )
+    .discard_err()
+    .is_some()
+}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 25a9dbb2c11..5be5ee8d1ae 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -8,6 +8,7 @@ mod type_name;
 
 pub use self::alignment::{is_disaligned, is_within_packed};
 pub use self::check_validity_requirement::check_validity_requirement;
+pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
 pub use self::compare_types::{relate_types, sub_types};
 pub use self::type_name::type_name;