Skip to content

Commit 1dd711a

Browse files
committed
Remove the nullary intrinsic const eval logic and treat them like other intrinsics
1 parent bc4193c commit 1dd711a

File tree

4 files changed

+74
-117
lines changed

4 files changed

+74
-117
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::const_eval::CheckAlignment;
2020
use crate::interpret::{
2121
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind,
2222
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, create_static_alloc,
23-
eval_nullary_intrinsic, intern_const_alloc_recursive, interp_ok, throw_exhaust,
23+
intern_const_alloc_recursive, interp_ok, throw_exhaust,
2424
};
2525
use crate::{CTRL_C_RECEIVED, errors};
2626

@@ -280,34 +280,6 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
280280
tcx: TyCtxt<'tcx>,
281281
key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
282282
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
283-
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
284-
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
285-
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
286-
let ty = key.value.instance.ty(tcx, key.typing_env);
287-
let ty::FnDef(_, args) = ty.kind() else {
288-
bug!("intrinsic with type {:?}", ty);
289-
};
290-
return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err(
291-
|error| {
292-
let span = tcx.def_span(def_id);
293-
294-
// FIXME(oli-obk): why don't we have any tests for this code path?
295-
super::report(
296-
tcx,
297-
error.into_kind(),
298-
span,
299-
|| (span, vec![]),
300-
|diag, span, _| {
301-
diag.span_label(
302-
span,
303-
crate::fluent_generated::const_eval_nullary_intrinsic_fail,
304-
);
305-
},
306-
)
307-
},
308-
);
309-
}
310-
311283
tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
312284
}
313285

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 72 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,18 @@ use std::assert_matches::assert_matches;
66

77
use rustc_abi::Size;
88
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
9-
use rustc_hir::def_id::DefId;
109
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1110
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
12-
use rustc_middle::ty::{GenericArgsRef, Ty, TyCtxt};
11+
use rustc_middle::ty::{Ty, TyCtxt};
1312
use rustc_middle::{bug, ty};
1413
use rustc_span::{Symbol, sym};
1514
use tracing::trace;
1615

1716
use super::memory::MemoryKind;
1817
use super::util::ensure_monomorphic_enough;
1918
use super::{
20-
Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, Machine,
21-
OpTy, PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, err_ub_custom,
19+
Allocation, CheckInAllocMsg, ConstAllocation, ImmTy, InterpCx, InterpResult, Machine, OpTy,
20+
PlaceTy, Pointer, PointerArithmetic, Provenance, Scalar, err_inval, err_ub_custom,
2221
err_unsup_format, interp_ok, throw_inval, throw_ub_custom, throw_ub_format,
2322
};
2423
use crate::fluent_generated as fluent;
@@ -30,73 +29,6 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
3029
tcx.mk_const_alloc(alloc)
3130
}
3231

33-
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
34-
/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
35-
pub(crate) fn eval_nullary_intrinsic<'tcx>(
36-
tcx: TyCtxt<'tcx>,
37-
typing_env: ty::TypingEnv<'tcx>,
38-
def_id: DefId,
39-
args: GenericArgsRef<'tcx>,
40-
) -> InterpResult<'tcx, ConstValue<'tcx>> {
41-
let tp_ty = args.type_at(0);
42-
let name = tcx.item_name(def_id);
43-
interp_ok(match name {
44-
sym::type_name => {
45-
ensure_monomorphic_enough(tcx, tp_ty)?;
46-
let alloc = alloc_type_name(tcx, tp_ty);
47-
ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() }
48-
}
49-
sym::needs_drop => {
50-
ensure_monomorphic_enough(tcx, tp_ty)?;
51-
ConstValue::from_bool(tp_ty.needs_drop(tcx, typing_env))
52-
}
53-
sym::type_id => {
54-
ensure_monomorphic_enough(tcx, tp_ty)?;
55-
ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128())
56-
}
57-
sym::variant_count => match match tp_ty.kind() {
58-
// Pattern types have the same number of variants as their base type.
59-
// Even if we restrict e.g. which variants are valid, the variants are essentially just uninhabited.
60-
// And `Result<(), !>` still has two variants according to `variant_count`.
61-
ty::Pat(base, _) => *base,
62-
_ => tp_ty,
63-
}
64-
.kind()
65-
{
66-
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
67-
ty::Adt(adt, _) => ConstValue::from_target_usize(adt.variants().len() as u64, &tcx),
68-
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
69-
throw_inval!(TooGeneric)
70-
}
71-
ty::Pat(..) => unreachable!(),
72-
ty::Bound(_, _) => bug!("bound ty during ctfe"),
73-
ty::Bool
74-
| ty::Char
75-
| ty::Int(_)
76-
| ty::Uint(_)
77-
| ty::Float(_)
78-
| ty::Foreign(_)
79-
| ty::Str
80-
| ty::Array(_, _)
81-
| ty::Slice(_)
82-
| ty::RawPtr(_, _)
83-
| ty::Ref(_, _, _)
84-
| ty::FnDef(_, _)
85-
| ty::FnPtr(..)
86-
| ty::Dynamic(_, _, _)
87-
| ty::Closure(_, _)
88-
| ty::CoroutineClosure(_, _)
89-
| ty::Coroutine(_, _)
90-
| ty::CoroutineWitness(..)
91-
| ty::UnsafeBinder(_)
92-
| ty::Never
93-
| ty::Tuple(_)
94-
| ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
95-
},
96-
other => bug!("`{}` is not a zero arg intrinsic", other),
97-
})
98-
}
99-
10032
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10133
/// Returns `true` if emulation happened.
10234
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
@@ -110,8 +42,77 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
11042
) -> InterpResult<'tcx, bool> {
11143
let instance_args = instance.args;
11244
let intrinsic_name = self.tcx.item_name(instance.def_id());
45+
let tcx = self.tcx.tcx;
11346

11447
match intrinsic_name {
48+
sym::type_name => {
49+
let tp_ty = instance.args.type_at(0);
50+
ensure_monomorphic_enough(tcx, tp_ty)?;
51+
let alloc = alloc_type_name(tcx, tp_ty);
52+
let val = ConstValue::Slice { data: alloc, meta: alloc.inner().size().bytes() };
53+
let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?;
54+
self.copy_op(&val, dest)?;
55+
}
56+
sym::needs_drop => {
57+
let tp_ty = instance.args.type_at(0);
58+
ensure_monomorphic_enough(tcx, tp_ty)?;
59+
let val = ConstValue::from_bool(tp_ty.needs_drop(tcx, self.typing_env));
60+
let val = self.const_val_to_op(val, tcx.types.bool, Some(dest.layout))?;
61+
self.copy_op(&val, dest)?;
62+
}
63+
sym::type_id => {
64+
let tp_ty = instance.args.type_at(0);
65+
ensure_monomorphic_enough(tcx, tp_ty)?;
66+
let val = ConstValue::from_u128(tcx.type_id_hash(tp_ty).as_u128());
67+
let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?;
68+
self.copy_op(&val, dest)?;
69+
}
70+
sym::variant_count => {
71+
let tp_ty = instance.args.type_at(0);
72+
let ty = match tp_ty.kind() {
73+
// Pattern types have the same number of variants as their base type.
74+
// Even if we restrict e.g. which variants are valid, the variants are essentially just uninhabited.
75+
// And `Result<(), !>` still has two variants according to `variant_count`.
76+
ty::Pat(base, _) => *base,
77+
_ => tp_ty,
78+
};
79+
let val = match ty.kind() {
80+
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
81+
ty::Adt(adt, _) => {
82+
ConstValue::from_target_usize(adt.variants().len() as u64, &tcx)
83+
}
84+
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
85+
throw_inval!(TooGeneric)
86+
}
87+
ty::Pat(..) => unreachable!(),
88+
ty::Bound(_, _) => bug!("bound ty during ctfe"),
89+
ty::Bool
90+
| ty::Char
91+
| ty::Int(_)
92+
| ty::Uint(_)
93+
| ty::Float(_)
94+
| ty::Foreign(_)
95+
| ty::Str
96+
| ty::Array(_, _)
97+
| ty::Slice(_)
98+
| ty::RawPtr(_, _)
99+
| ty::Ref(_, _, _)
100+
| ty::FnDef(_, _)
101+
| ty::FnPtr(..)
102+
| ty::Dynamic(_, _, _)
103+
| ty::Closure(_, _)
104+
| ty::CoroutineClosure(_, _)
105+
| ty::Coroutine(_, _)
106+
| ty::CoroutineWitness(..)
107+
| ty::UnsafeBinder(_)
108+
| ty::Never
109+
| ty::Tuple(_)
110+
| ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
111+
};
112+
let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?;
113+
self.copy_op(&val, dest)?;
114+
}
115+
115116
sym::caller_location => {
116117
let span = self.find_closest_untracked_caller_location();
117118
let val = self.tcx.span_as_caller_location(span);
@@ -137,21 +138,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
137138
self.write_scalar(Scalar::from_target_usize(result, self), dest)?;
138139
}
139140

140-
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
141-
let gid = GlobalId { instance, promoted: None };
142-
let ty = self
143-
.tcx
144-
.fn_sig(instance.def_id())
145-
.instantiate(self.tcx.tcx, instance.args)
146-
.output()
147-
.no_bound_vars()
148-
.unwrap();
149-
let val = self
150-
.ctfe_query(|tcx| tcx.const_eval_global_id(self.typing_env, gid, tcx.span))?;
151-
let val = self.const_val_to_op(val, ty, Some(dest.layout))?;
152-
self.copy_op(&val, dest)?;
153-
}
154-
155141
sym::fadd_algebraic
156142
| sym::fsub_algebraic
157143
| sym::fmul_algebraic

compiler/rustc_const_eval/src/interpret/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ pub use self::intern::{
2929
HasStaticRootDefId, InternKind, InternResult, intern_const_alloc_for_constprop,
3030
intern_const_alloc_recursive,
3131
};
32-
pub(crate) use self::intrinsics::eval_nullary_intrinsic;
3332
pub use self::machine::{AllocMap, Machine, MayLeak, ReturnAction, compile_time_machine};
3433
pub use self::memory::{AllocInfo, AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
3534
use self::operand::Operand;

tests/ui/consts/const-fn-type-name.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![allow(dead_code)]
66

77
const fn type_name_wrapper<T>(_: &T) -> &'static str {
8-
core::intrinsics::type_name::<T>()
8+
const { core::intrinsics::type_name::<T>() }
99
}
1010

1111
struct Struct<TA, TB, TC> {

0 commit comments

Comments
 (0)