summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_const_eval/src/interpret/intrinsics.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret/intrinsics.rs')
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs106
1 files changed, 41 insertions, 65 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index a77c699c2..ed64a7655 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -22,6 +22,8 @@ use super::{
Pointer,
};
+use crate::fluent_generated as fluent;
+
mod caller_location;
fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
@@ -70,12 +72,12 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
}
sym::pref_align_of => {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
- let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
+ let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(*e)))?;
ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
}
sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?;
- ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64())
+ ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128())
}
sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
@@ -167,8 +169,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let ty = match intrinsic_name {
sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
sym::needs_drop => self.tcx.types.bool,
- sym::type_id => self.tcx.types.u64,
- sym::type_name => self.tcx.mk_static_str(),
+ sym::type_id => self.tcx.types.u128,
+ sym::type_name => Ty::new_static_str(self.tcx.tcx),
_ => bug!(),
};
let val = self.ctfe_query(None, |tcx| {
@@ -198,15 +200,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty
),
};
- let (nonzero, intrinsic_name) = match intrinsic_name {
+ let (nonzero, actual_intrinsic_name) = match intrinsic_name {
sym::cttz_nonzero => (true, sym::cttz),
sym::ctlz_nonzero => (true, sym::ctlz),
other => (false, other),
};
if nonzero && bits == 0 {
- throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name);
+ throw_ub_custom!(
+ fluent::const_eval_call_nonzero_intrinsic,
+ name = intrinsic_name,
+ );
}
- let out_val = numeric_intrinsic(intrinsic_name, bits, kind);
+ let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind);
self.write_scalar(out_val, dest)?;
}
sym::saturating_add | sym::saturating_sub => {
@@ -229,37 +234,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let r = self.read_immediate(&args[1])?;
self.exact_div(&l, &r, dest)?;
}
- sym::unchecked_shl
- | sym::unchecked_shr
- | sym::unchecked_add
- | sym::unchecked_sub
- | sym::unchecked_mul
- | sym::unchecked_div
- | sym::unchecked_rem => {
- let l = self.read_immediate(&args[0])?;
- let r = self.read_immediate(&args[1])?;
- let bin_op = match intrinsic_name {
- sym::unchecked_shl => BinOp::Shl,
- sym::unchecked_shr => BinOp::Shr,
- sym::unchecked_add => BinOp::Add,
- sym::unchecked_sub => BinOp::Sub,
- sym::unchecked_mul => BinOp::Mul,
- sym::unchecked_div => BinOp::Div,
- sym::unchecked_rem => BinOp::Rem,
- _ => bug!(),
- };
- let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, &l, &r)?;
- if overflowed {
- let layout = self.layout_of(substs.type_at(0))?;
- let r_val = r.to_scalar().to_bits(layout.size)?;
- if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
- throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name);
- } else {
- throw_ub_format!("overflow executing `{}`", intrinsic_name);
- }
- }
- self.write_scalar(val, dest)?;
- }
sym::rotate_left | sym::rotate_right => {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
@@ -314,17 +288,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(Err(_), _) | (_, Err(_)) => {
// We managed to find a valid allocation for one pointer, but not the other.
// That means they are definitely not pointing to the same allocation.
- throw_ub_format!(
- "`{}` called on pointers into different allocations",
- intrinsic_name
+ throw_ub_custom!(
+ fluent::const_eval_different_allocations,
+ name = intrinsic_name,
);
}
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
// Found allocation for both. They must be into the same allocation.
if a_alloc_id != b_alloc_id {
- throw_ub_format!(
- "`{}` called on pointers into different allocations",
- intrinsic_name
+ throw_ub_custom!(
+ fluent::const_eval_different_allocations,
+ name = intrinsic_name,
);
}
// Use these offsets for distance calculation.
@@ -344,11 +318,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
if overflowed {
// a < b
if intrinsic_name == sym::ptr_offset_from_unsigned {
- throw_ub_format!(
- "`{}` called when first pointer has smaller offset than second: {} < {}",
- intrinsic_name,
- a_offset,
- b_offset,
+ throw_ub_custom!(
+ fluent::const_eval_unsigned_offset_from_overflow,
+ a_offset = a_offset,
+ b_offset = b_offset,
);
}
// The signed form of the intrinsic allows this. If we interpret the
@@ -356,9 +329,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// seems *positive*, they were more than isize::MAX apart.
let dist = val.to_target_isize(self)?;
if dist >= 0 {
- throw_ub_format!(
- "`{}` called when first pointer is too far before second",
- intrinsic_name
+ throw_ub_custom!(
+ fluent::const_eval_offset_from_underflow,
+ name = intrinsic_name,
);
}
dist
@@ -368,9 +341,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// If converting to isize produced a *negative* result, we had an overflow
// because they were more than isize::MAX apart.
if dist < 0 {
- throw_ub_format!(
- "`{}` called when first pointer is too far ahead of second",
- intrinsic_name
+ throw_ub_custom!(
+ fluent::const_eval_offset_from_overflow,
+ name = intrinsic_name,
);
}
dist
@@ -513,7 +486,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let op = self.eval_operand(op, None)?;
let cond = self.read_scalar(&op)?.to_bool()?;
if !cond {
- throw_ub_format!("`assume` called with `false`");
+ throw_ub_custom!(fluent::const_eval_assume_false);
}
Ok(())
}
@@ -542,7 +515,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?;
assert!(!overflow); // All overflow is UB, so this should never return on overflow.
if res.assert_bits(a.layout.size) != 0 {
- throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b)
+ throw_ub_custom!(
+ fluent::const_eval_exact_div_has_remainder,
+ a = format!("{a}"),
+ b = format!("{b}")
+ )
}
// `Rem` says this is all right, so we can let `Div` do its job.
self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
@@ -638,9 +615,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
let size = size.checked_mul(count, self).ok_or_else(|| {
- err_ub_format!(
- "overflow computing total size of `{}`",
- if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
+ err_ub_custom!(
+ fluent::const_eval_size_overflow,
+ name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
)
})?;
@@ -664,10 +641,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
- let len = layout
- .size
- .checked_mul(count, self)
- .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
+ let len = layout.size.checked_mul(count, self).ok_or_else(|| {
+ err_ub_custom!(fluent::const_eval_size_overflow, name = "write_bytes")
+ })?;
let bytes = std::iter::repeat(byte).take(len.bytes_usize());
self.write_bytes_ptr(dst, bytes)
@@ -691,7 +667,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
return Ok(&[]);
};
if alloc_ref.has_provenance() {
- throw_ub_format!("`raw_eq` on bytes with provenance");
+ throw_ub_custom!(fluent::const_eval_raw_eq_with_provenance);
}
alloc_ref.get_bytes_strip_provenance()
};