about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src/interpret
diff options
context:
space:
mode:
authorThe Miri Conjob Bot <miri@cron.bot>2024-02-17 05:17:43 +0000
committerThe Miri Conjob Bot <miri@cron.bot>2024-02-17 05:17:43 +0000
commitd523cab910d6b89b01dad9b283a67fb2256bc41e (patch)
tree4bdb17aaad138aa83a9464e32a25528bd360f020 /compiler/rustc_const_eval/src/interpret
parent63240d758b0a6d48a8ea24799230ae2c47540fdd (diff)
parent4316d0c6252cb1f833e582dfa68adb98efd5ddfb (diff)
downloadrust-d523cab910d6b89b01dad9b283a67fb2256bc41e.tar.gz
rust-d523cab910d6b89b01dad9b283a67fb2256bc41e.zip
Merge from rustc
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret')
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs89
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs4
3 files changed, 44 insertions, 51 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index b2207c3d310..e72ace8be35 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -526,7 +526,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         match instance.def {
             ty::InstanceDef::Intrinsic(def_id) => {
-                assert!(self.tcx.is_intrinsic(def_id));
+                assert!(self.tcx.intrinsic(def_id).is_some());
                 // FIXME: Should `InPlace` arguments be reset to uninit?
                 M::call_intrinsic(
                     self,
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 08a2e38bfa1..792e1c9e736 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -5,7 +5,7 @@
 //! to be const-safe.
 
 use std::fmt::Write;
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 
 use either::{Left, Right};
 
@@ -445,22 +445,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             // Determine whether this pointer expects to be pointing to something mutable.
             let ptr_expected_mutbl = match ptr_kind {
                 PointerKind::Box => Mutability::Mut,
-                PointerKind::Ref => {
-                    let tam = value.layout.ty.builtin_deref(false).unwrap();
-                    // ZST never require mutability. We do not take into account interior mutability
-                    // here since we cannot know if there really is an `UnsafeCell` inside
-                    // `Option<UnsafeCell>` -- so we check that in the recursive descent behind this
-                    // reference.
-                    if size == Size::ZERO { Mutability::Not } else { tam.mutbl }
+                PointerKind::Ref(mutbl) => {
+                    // We do not take into account interior mutability here since we cannot know if
+                    // there really is an `UnsafeCell` inside `Option<UnsafeCell>` -- so we check
+                    // that in the recursive descent behind this reference (controlled by
+                    // `allow_immutable_unsafe_cell`).
+                    mutbl
                 }
             };
             // Proceed recursively even for ZST, no reason to skip them!
             // `!` is a ZST and we want to validate it.
             if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr()) {
+                let mut skip_recursive_check = false;
                 // Let's see what kind of memory this points to.
                 // `unwrap` since dangling pointers have already been handled.
                 let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id).unwrap();
-                match alloc_kind {
+                let alloc_actual_mutbl = match alloc_kind {
                     GlobalAlloc::Static(did) => {
                         // Special handling for pointers to statics (irrespective of their type).
                         assert!(!self.ecx.tcx.is_thread_local_static(did));
@@ -474,12 +474,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                                     .no_bound_vars()
                                     .expect("statics should not have generic parameters")
                                     .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all());
-                        // Mutability check.
-                        if ptr_expected_mutbl == Mutability::Mut {
-                            if !is_mut {
-                                throw_validation_failure!(self.path, MutableRefToImmutable);
-                            }
-                        }
                         // Mode-specific checks
                         match self.ctfe_mode {
                             Some(
@@ -494,15 +488,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                                 // trigger cycle errors if we try to compute the value of the other static
                                 // and that static refers back to us (potentially through a promoted).
                                 // This could miss some UB, but that's fine.
-                                return Ok(());
+                                skip_recursive_check = true;
                             }
                             Some(CtfeValidationMode::Const { .. }) => {
-                                // For consts on the other hand we have to recursively check;
-                                // pattern matching assumes a valid value. However we better make
-                                // sure this is not mutable.
-                                if is_mut {
-                                    throw_validation_failure!(self.path, ConstRefToMutable);
-                                }
                                 // We can't recursively validate `extern static`, so we better reject them.
                                 if self.ecx.tcx.is_foreign_item(did) {
                                     throw_validation_failure!(self.path, ConstRefToExtern);
@@ -510,26 +498,39 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                             }
                             None => {}
                         }
+                        // Return alloc mutability
+                        if is_mut { Mutability::Mut } else { Mutability::Not }
                     }
-                    GlobalAlloc::Memory(alloc) => {
-                        if alloc.inner().mutability == Mutability::Mut
-                            && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
-                        {
-                            throw_validation_failure!(self.path, ConstRefToMutable);
-                        }
-                        if ptr_expected_mutbl == Mutability::Mut
-                            && alloc.inner().mutability == Mutability::Not
-                        {
-                            throw_validation_failure!(self.path, MutableRefToImmutable);
-                        }
-                    }
+                    GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
                     GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => {
                         // These are immutable, we better don't allow mutable pointers here.
-                        if ptr_expected_mutbl == Mutability::Mut {
-                            throw_validation_failure!(self.path, MutableRefToImmutable);
-                        }
+                        Mutability::Not
+                    }
+                };
+                // Mutability check.
+                // If this allocation has size zero, there is no actual mutability here.
+                let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
+                if size != Size::ZERO {
+                    if ptr_expected_mutbl == Mutability::Mut
+                        && alloc_actual_mutbl == Mutability::Not
+                    {
+                        throw_validation_failure!(self.path, MutableRefToImmutable);
+                    }
+                    if ptr_expected_mutbl == Mutability::Mut
+                        && self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref())
+                    {
+                        throw_validation_failure!(self.path, MutableRefInConstOrStatic);
+                    }
+                    if alloc_actual_mutbl == Mutability::Mut
+                        && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. }))
+                    {
+                        throw_validation_failure!(self.path, ConstRefToMutable);
                     }
                 }
+                // Potentially skip recursive check.
+                if skip_recursive_check {
+                    return Ok(());
+                }
             }
             let path = &self.path;
             ref_tracking.track(place, || {
@@ -598,16 +599,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 }
                 Ok(true)
             }
-            ty::Ref(_, ty, mutbl) => {
-                if self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref())
-                    && *mutbl == Mutability::Mut
-                {
-                    let layout = self.ecx.layout_of(*ty)?;
-                    if !layout.is_zst() {
-                        throw_validation_failure!(self.path, MutableRefInConst);
-                    }
-                }
-                self.check_safe_pointer(value, PointerKind::Ref)?;
+            ty::Ref(_, _ty, mutbl) => {
+                self.check_safe_pointer(value, PointerKind::Ref(*mutbl))?;
                 Ok(true)
             }
             ty::FnPtr(_sig) => {
@@ -785,7 +778,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
     fn visit_union(
         &mut self,
         op: &OpTy<'tcx, M::Provenance>,
-        _fields: NonZeroUsize,
+        _fields: NonZero<usize>,
     ) -> InterpResult<'tcx> {
         // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
         if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 340a496a689..b200ecbf73a 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty;
 use rustc_target::abi::FieldIdx;
 use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
 
-use std::num::NonZeroUsize;
+use std::num::NonZero;
 
 use super::{InterpCx, MPlaceTy, Machine, Projectable};
 
@@ -43,7 +43,7 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
     }
     /// Visits the given value as a union. No automatic recursion can happen here.
     #[inline(always)]
-    fn visit_union(&mut self, _v: &Self::V, _fields: NonZeroUsize) -> InterpResult<'tcx> {
+    fn visit_union(&mut self, _v: &Self::V, _fields: NonZero<usize>) -> InterpResult<'tcx> {
         Ok(())
     }
     /// Visits the given value as the pointer of a `Box`. There is nothing to recurse into.