about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src/const_eval/machine.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval/src/const_eval/machine.rs')
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs106
1 files changed, 18 insertions, 88 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 5f0bc8539ee..b27e3606f38 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,21 +1,19 @@
 use std::borrow::{Borrow, Cow};
 use std::fmt;
 use std::hash::Hash;
-use std::ops::ControlFlow;
 
+use rustc_abi::{Align, ExternAbi, Size};
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
+use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
-use rustc_target::abi::{Align, Size};
-use rustc_target::spec::abi::Abi as CallAbi;
 use tracing::debug;
 
 use super::error::*;
@@ -23,9 +21,9 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy,
-    InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, RangeSet, Scalar,
-    StackPopCleanup, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub,
-    throw_ub_custom, throw_unsup, throw_unsup_format,
+    InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine,
+    interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup,
+    throw_unsup_format,
 };
 
 /// When hitting this many interpreted terminators we emit a deny by default lint
@@ -227,8 +225,8 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[FnArg<'tcx>],
-        dest: &MPlaceTy<'tcx>,
-        ret: Option<mir::BasicBlock>,
+        _dest: &MPlaceTy<'tcx>,
+        _ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
 
@@ -251,95 +249,27 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         } else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
+            // FIXME(@lcnr): why does this use an empty env if we've got a `param_env` right here.
             let new_instance = ty::Instance::expect_resolve(
                 *self.tcx,
-                ty::ParamEnv::reveal_all(),
+                ty::TypingEnv::fully_monomorphized(),
                 const_def_id,
                 instance.args,
                 self.cur_span(),
             );
 
             return interp_ok(Some(new_instance));
-        } else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
-            let args = self.copy_fn_args(args);
-            // For align_offset, we replace the function call if the pointer has no address.
-            match self.align_offset(instance, &args, dest, ret)? {
-                ControlFlow::Continue(()) => return interp_ok(Some(instance)),
-                ControlFlow::Break(()) => return interp_ok(None),
-            }
         }
         interp_ok(Some(instance))
     }
 
-    /// `align_offset(ptr, target_align)` needs special handling in const eval, because the pointer
-    /// may not have an address.
-    ///
-    /// If `ptr` does have a known address, then we return `Continue(())` and the function call should
-    /// proceed as normal.
-    ///
-    /// If `ptr` doesn't have an address, but its underlying allocation's alignment is at most
-    /// `target_align`, then we call the function again with an dummy address relative to the
-    /// allocation.
-    ///
-    /// If `ptr` doesn't have an address and `target_align` is stricter than the underlying
-    /// allocation's alignment, then we return `usize::MAX` immediately.
-    fn align_offset(
-        &mut self,
-        instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
-        ret: Option<mir::BasicBlock>,
-    ) -> InterpResult<'tcx, ControlFlow<()>> {
-        assert_eq!(args.len(), 2);
-
-        let ptr = self.read_pointer(&args[0])?;
-        let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
-
-        if !target_align.is_power_of_two() {
-            throw_ub_custom!(
-                fluent::const_eval_align_offset_invalid_align,
-                target_align = target_align,
-            );
-        }
-
-        match self.ptr_try_get_alloc_id(ptr, 0) {
-            Ok((alloc_id, offset, _extra)) => {
-                let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
-
-                if target_align <= alloc_align.bytes() {
-                    // Extract the address relative to the allocation base that is definitely
-                    // sufficiently aligned and call `align_offset` again.
-                    let addr = ImmTy::from_uint(offset.bytes(), args[0].layout).into();
-                    let align = ImmTy::from_uint(target_align, args[1].layout).into();
-                    let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
-
-                    // Push the stack frame with our own adjusted arguments.
-                    self.init_stack_frame(
-                        instance,
-                        self.load_mir(instance.def, None)?,
-                        fn_abi,
-                        &[FnArg::Copy(addr), FnArg::Copy(align)],
-                        /* with_caller_location = */ false,
-                        dest,
-                        StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Unreachable },
-                    )?;
-                    interp_ok(ControlFlow::Break(()))
-                } else {
-                    // Not alignable in const, return `usize::MAX`.
-                    let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
-                    self.write_scalar(usize_max, dest)?;
-                    self.return_to_block(ret)?;
-                    interp_ok(ControlFlow::Break(()))
-                }
-            }
-            Err(_addr) => {
-                // The pointer has an address, continue with function call.
-                interp_ok(ControlFlow::Continue(()))
-            }
-        }
-    }
-
     /// See documentation on the `ptr_guaranteed_cmp` intrinsic.
+    /// Returns `2` if the result is unknown.
+    /// Returns `1` if the pointers are guaranteed equal.
+    /// Returns `0` if the pointers are guaranteed inequal.
+    ///
+    /// Note that this intrinsic is exposed on stable for comparison with null. In other words, any
+    /// change to this function that affects comparison with null is insta-stable!
     fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
         interp_ok(match (a, b) {
             // Comparisons between integers are always known.
@@ -411,7 +341,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'tcx, Self>,
         orig_instance: ty::Instance<'tcx>,
-        _abi: CallAbi,
+        _abi: ExternAbi,
         args: &[FnArg<'tcx>],
         dest: &MPlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
@@ -431,7 +361,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
             // sensitive check here. But we can at least rule out functions that are not const at
             // all. That said, we have to allow calling functions inside a trait marked with
             // #[const_trait]. These *are* const-checked!
-            // FIXME(effects): why does `is_const_fn` not classify them as const?
+            // FIXME(const_trait_impl): why does `is_const_fn` not classify them as const?
             if (!ecx.tcx.is_const_fn(def) && !ecx.tcx.is_const_default_method(def))
                 || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
             {
@@ -737,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
                 .is_some_and(|p| !p.immutable())
         {
             // That next check is expensive, that's why we have all the guards above.
-            let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env);
+            let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env());
             let place = ecx.ref_to_mplace(val)?;
             let new_place = if is_immutable {
                 place.map_provenance(CtfeProvenance::as_immutable)