Skip to content

Commit 43e46ab

Browse files
committed
Auto merge of #61626 - oli-obk:const_eval_intrinsics, r=eddyb
Get rid of special const intrinsic query in favour of `const_eval` r? @eddyb
2 parents 56a12b2 + f361410 commit 43e46ab

File tree

13 files changed

+121
-100
lines changed

13 files changed

+121
-100
lines changed

Diff for: src/librustc/mir/interpret/error.rs

+9
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
198198
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
199199
}
200200

201+
impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
202+
fn from(err: ErrorHandled) -> Self {
203+
match err {
204+
ErrorHandled::Reported => InterpError::ReferencedConstant,
205+
ErrorHandled::TooGeneric => InterpError::TooGeneric,
206+
}.into()
207+
}
208+
}
209+
201210
impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
202211
fn from(kind: InterpError<'tcx, u64>) -> Self {
203212
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {

Diff for: src/librustc/query/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -441,15 +441,6 @@ rustc_queries! {
441441
no_force
442442
desc { "extract field of const" }
443443
}
444-
445-
/// Produces an absolute path representation of the given type. See also the documentation
446-
/// on `std::any::type_name`.
447-
query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
448-
eval_always
449-
no_force
450-
desc { "get absolute path of type" }
451-
}
452-
453444
}
454445

455446
TypeChecking {

Diff for: src/librustc_codegen_llvm/intrinsic.rs

+13-23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_codegen_ssa::glue;
1717
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
1818
use rustc::ty::{self, Ty};
1919
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
20+
use rustc::mir::interpret::GlobalId;
2021
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
2122
use rustc::hir;
2223
use syntax::ast::{self, FloatTy};
@@ -83,13 +84,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
8384
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8485
fn codegen_intrinsic_call(
8586
&mut self,
86-
callee_ty: Ty<'tcx>,
87+
instance: ty::Instance<'tcx>,
8788
fn_ty: &FnType<'tcx, Ty<'tcx>>,
8889
args: &[OperandRef<'tcx, &'ll Value>],
8990
llresult: &'ll Value,
9091
span: Span,
9192
) {
9293
let tcx = self.tcx;
94+
let callee_ty = instance.ty(tcx);
9395

9496
let (def_id, substs) = match callee_ty.sty {
9597
ty::FnDef(def_id, substs) => (def_id, substs),
@@ -135,10 +137,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
135137
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
136138
self.call(llfn, &[], None)
137139
}
138-
"size_of" => {
139-
let tp_ty = substs.type_at(0);
140-
self.const_usize(self.size_of(tp_ty).bytes())
141-
}
142140
"va_start" => {
143141
self.va_start(args[0].immediate())
144142
}
@@ -190,10 +188,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
190188
self.const_usize(self.size_of(tp_ty).bytes())
191189
}
192190
}
193-
"min_align_of" => {
194-
let tp_ty = substs.type_at(0);
195-
self.const_usize(self.align_of(tp_ty).bytes())
196-
}
197191
"min_align_of_val" => {
198192
let tp_ty = substs.type_at(0);
199193
if let OperandValue::Pair(_, meta) = args[0].val {
@@ -203,18 +197,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
203197
self.const_usize(self.align_of(tp_ty).bytes())
204198
}
205199
}
206-
"pref_align_of" => {
207-
let tp_ty = substs.type_at(0);
208-
self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
209-
}
200+
"size_of" |
201+
"pref_align_of" |
202+
"min_align_of" |
203+
"needs_drop" |
204+
"type_id" |
210205
"type_name" => {
211-
let tp_ty = substs.type_at(0);
212-
let ty_name = self.tcx.type_name(tp_ty);
206+
let gid = GlobalId {
207+
instance,
208+
promoted: None,
209+
};
210+
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
213211
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
214212
}
215-
"type_id" => {
216-
self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
217-
}
218213
"init" => {
219214
let ty = substs.type_at(0);
220215
if !self.layout_of(ty).is_zst() {
@@ -237,11 +232,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
237232
"uninit" | "forget" => {
238233
return;
239234
}
240-
"needs_drop" => {
241-
let tp_ty = substs.type_at(0);
242-
243-
self.const_bool(self.type_needs_drop(tp_ty))
244-
}
245235
"offset" => {
246236
let ptr = args[0].immediate();
247237
let offset = args[1].immediate();

Diff for: src/librustc_codegen_ssa/mir/block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
662662
}).collect();
663663

664664

665-
let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
666-
bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
665+
bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
667666
terminator.source_info.span);
668667

669668
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {

Diff for: src/librustc_codegen_ssa/traits/intrinsic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::BackendTypes;
22
use crate::mir::operand::OperandRef;
3-
use rustc::ty::Ty;
3+
use rustc::ty::{self, Ty};
44
use rustc_target::abi::call::FnType;
55
use syntax_pos::Span;
66

@@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
1010
/// add them to librustc_codegen_llvm/context.rs
1111
fn codegen_intrinsic_call(
1212
&mut self,
13-
callee_ty: Ty<'tcx>,
13+
instance: ty::Instance<'tcx>,
1414
fn_ty: &FnType<'tcx, Ty<'tcx>>,
1515
args: &[OperandRef<'tcx, Self::Value>],
1616
llresult: Self::Value,

Diff for: src/librustc_mir/const_eval.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef};
1313
use rustc::mir;
1414
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
1515
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
16-
use rustc::ty::subst::Subst;
16+
use rustc::ty::subst::{Subst, SubstsRef};
1717
use rustc::traits::Reveal;
1818
use rustc::util::common::ErrorReported;
1919
use rustc_data_structures::fx::FxHashMap;
20+
use crate::interpret::alloc_type_name;
2021

2122
use syntax::source_map::{Span, DUMMY_SP};
2223

@@ -588,11 +589,63 @@ pub fn const_eval_provider<'tcx>(
588589
other => return other,
589590
}
590591
}
592+
593+
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
594+
let ty = key.value.instance.ty(tcx);
595+
let substs = match ty.sty {
596+
ty::FnDef(_, substs) => substs,
597+
_ => bug!("intrinsic with type {:?}", ty),
598+
};
599+
return Ok(eval_nulary_intrinsic(tcx, key.param_env, def_id, substs));
600+
}
601+
591602
tcx.const_eval_raw(key).and_then(|val| {
592603
validate_and_turn_into_const(tcx, val, key)
593604
})
594605
}
595606

607+
fn eval_nulary_intrinsic<'tcx>(
608+
tcx: TyCtxt<'tcx>,
609+
param_env: ty::ParamEnv<'tcx>,
610+
def_id: DefId,
611+
substs: SubstsRef<'tcx>,
612+
) -> &'tcx ty::Const<'tcx> {
613+
let tp_ty = substs.type_at(0);
614+
let name = &*tcx.item_name(def_id).as_str();
615+
match name {
616+
"type_name" => {
617+
let alloc = alloc_type_name(tcx, tp_ty);
618+
tcx.mk_const(ty::Const {
619+
val: ConstValue::Slice {
620+
data: alloc,
621+
start: 0,
622+
end: alloc.bytes.len(),
623+
},
624+
ty: tcx.mk_static_str(),
625+
})
626+
},
627+
"needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
628+
"size_of" |
629+
"min_align_of" |
630+
"pref_align_of" => {
631+
let layout = tcx.layout_of(param_env.and(tp_ty)).unwrap();
632+
let n = match name {
633+
"pref_align_of" => layout.align.pref.bytes(),
634+
"min_align_of" => layout.align.abi.bytes(),
635+
"size_of" => layout.size.bytes(),
636+
_ => bug!(),
637+
};
638+
ty::Const::from_usize(tcx, n)
639+
},
640+
"type_id" => ty::Const::from_bits(
641+
tcx,
642+
tcx.type_id_hash(tp_ty).into(),
643+
param_env.and(tcx.types.u64),
644+
),
645+
other => bug!("`{}` is not a zero arg intrinsic", other),
646+
}
647+
}
648+
596649
pub fn const_eval_raw_provider<'tcx>(
597650
tcx: TyCtxt<'tcx>,
598651
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,

Diff for: src/librustc_mir/interpret/eval_context.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
1414
use rustc::ty::query::TyCtxtAt;
1515
use rustc_data_structures::indexed_vec::IndexVec;
1616
use rustc::mir::interpret::{
17-
ErrorHandled,
1817
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
1918
InterpResult, InterpError,
2019
truncate, sign_extend,
@@ -652,12 +651,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
652651
// Our result will later be validated anyway, and there seems no good reason
653652
// to have to fail early here. This is also more consistent with
654653
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
655-
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
656-
match err {
657-
ErrorHandled::Reported => InterpError::ReferencedConstant,
658-
ErrorHandled::TooGeneric => InterpError::TooGeneric,
659-
}
660-
})?;
654+
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
661655
self.raw_const_to_mplace(val)
662656
}
663657

Diff for: src/librustc_mir/interpret/intrinsics.rs

+14-37
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ use rustc::ty;
77
use rustc::ty::layout::{LayoutOf, Primitive, Size};
88
use rustc::mir::BinOp;
99
use rustc::mir::interpret::{
10-
InterpResult, InterpError, Scalar,
10+
InterpResult, InterpError, Scalar, GlobalId,
1111
};
1212

1313
use super::{
14-
Machine, PlaceTy, OpTy, InterpretCx, Immediate,
14+
Machine, PlaceTy, OpTy, InterpretCx,
1515
};
1616

1717
mod type_name;
1818

19-
pub use type_name::*;
19+
pub(crate) use type_name::alloc_type_name;
2020

2121
fn numeric_intrinsic<'tcx, Tag>(
2222
name: &str,
@@ -51,41 +51,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
5151

5252
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
5353
match intrinsic_name {
54-
"min_align_of" => {
55-
let elem_ty = substs.type_at(0);
56-
let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
57-
let align_val = Scalar::from_uint(elem_align, dest.layout.size);
58-
self.write_scalar(align_val, dest)?;
59-
}
60-
61-
"needs_drop" => {
62-
let ty = substs.type_at(0);
63-
let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
64-
let val = Scalar::from_bool(ty_needs_drop);
65-
self.write_scalar(val, dest)?;
66-
}
67-
68-
"size_of" => {
69-
let ty = substs.type_at(0);
70-
let size = self.layout_of(ty)?.size.bytes() as u128;
71-
let size_val = Scalar::from_uint(size, dest.layout.size);
72-
self.write_scalar(size_val, dest)?;
73-
}
74-
75-
"type_id" => {
76-
let ty = substs.type_at(0);
77-
let type_id = self.tcx.type_id_hash(ty) as u128;
78-
let id_val = Scalar::from_uint(type_id, dest.layout.size);
79-
self.write_scalar(id_val, dest)?;
80-
}
81-
54+
"min_align_of" |
55+
"needs_drop" |
56+
"size_of" |
57+
"type_id" |
8258
"type_name" => {
83-
let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
84-
let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
85-
let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
86-
let alloc_len = alloc.bytes.len() as u64;
87-
let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
88-
self.write_immediate(name_val, dest)?;
59+
let gid = GlobalId {
60+
instance,
61+
promoted: None,
62+
};
63+
let val = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid))?;
64+
let val = self.eval_const_to_op(val, None)?;
65+
self.copy_op(val, dest)?;
8966
}
9067

9168
| "ctpop"

Diff for: src/librustc_mir/interpret/intrinsics/type_name.rs

+5-16
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc::ty::{
77
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
88
use rustc::hir::def_id::CrateNum;
99
use std::fmt::Write;
10-
use rustc::mir::interpret::{Allocation, ConstValue};
10+
use rustc::mir::interpret::Allocation;
1111

1212
struct AbsolutePathPrinter<'tcx> {
1313
tcx: TyCtxt<'tcx>,
@@ -213,22 +213,11 @@ impl Write for AbsolutePathPrinter<'_> {
213213
}
214214
}
215215

216-
/// Produces an absolute path representation of the given type. See also the documentation on
217-
/// `std::any::type_name`
218-
pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
219-
let alloc = alloc_type_name(tcx, ty);
220-
tcx.mk_const(ty::Const {
221-
val: ConstValue::Slice {
222-
data: alloc,
223-
start: 0,
224-
end: alloc.bytes.len(),
225-
},
226-
ty: tcx.mk_static_str(),
227-
})
228-
}
229-
230216
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
231-
pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
217+
pub(crate) fn alloc_type_name<'tcx>(
218+
tcx: TyCtxt<'tcx>,
219+
ty: Ty<'tcx>
220+
) -> &'tcx Allocation {
232221
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
233222
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
234223
tcx.intern_const_alloc(alloc)

Diff for: src/librustc_mir/interpret/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ pub use self::visitor::{ValueVisitor, MutValueVisitor};
3434

3535
pub use self::validity::RefTracking;
3636

37-
pub(super) use self::intrinsics::type_name;
38-
3937
pub use self::intern::intern_const_alloc_recursive;
38+
39+
pub(crate) use self::intrinsics::alloc_type_name;

Diff for: src/librustc_mir/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ pub fn provide(providers: &mut Providers<'_>) {
6969
let (param_env, (value, field)) = param_env_and_value.into_parts();
7070
const_eval::const_field(tcx, param_env, None, field, value)
7171
};
72-
providers.type_name = interpret::type_name;
7372
}
7473

7574
__build_diagnostic_array! { librustc_mir, DIAGNOSTICS }

Diff for: src/test/ui/consts/const-size_of-cycle.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
99
|
1010
LL | intrinsics::size_of::<T>()
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
13+
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
14+
|
15+
LL | pub fn size_of<T>() -> usize;
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
18+
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
19+
|
20+
LL | pub fn size_of<T>() -> usize;
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1222
= note: ...which requires computing layout of `Foo`...
1323
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
1424
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...

0 commit comments

Comments
 (0)