]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/const_eval.rs
New upstream version 1.42.0+dfsg1
[rustc.git] / src / librustc_mir / const_eval.rs
CommitLineData
b7449926
XL
1// Not in interpret to make sure we do not use private implementation details
2
b7449926 3use rustc::mir;
dfeec247
XL
4use rustc::ty::layout::VariantIdx;
5use rustc::ty::{self, TyCtxt};
6use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
0bf4aa26 7
dfeec247 8use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
0bf4aa26 9
dfeec247
XL
10mod error;
11mod eval_queries;
12mod fn_queries;
13mod machine;
0bf4aa26 14
dfeec247
XL
15pub use error::*;
16pub use eval_queries::*;
17pub use fn_queries::*;
18pub use machine::*;
b7449926 19
dc9dc135 20/// Extracts a field of a (variant of a) const.
532ac7d7
XL
21// this function uses `unwrap` copiously, because an already validated constant must have valid
22// fields and can thus never fail outside of compiler bugs
dfeec247 23pub(crate) fn const_field<'tcx>(
dc9dc135 24 tcx: TyCtxt<'tcx>,
b7449926 25 param_env: ty::ParamEnv<'tcx>,
a1dfa0c6 26 variant: Option<VariantIdx>,
b7449926 27 field: mir::Field,
dc9dc135
XL
28 value: &'tcx ty::Const<'tcx>,
29) -> &'tcx ty::Const<'tcx> {
9fa01778 30 trace!("const_field: {:?}, {:?}", field, value);
dfeec247 31 let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
532ac7d7
XL
32 // get the operand again
33 let op = ecx.eval_const_to_op(value, None).unwrap();
34 // downcast
35 let down = match variant {
36 None => op,
37 Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
38 };
39 // then project
40 let field = ecx.operand_field(down, field.index() as u64).unwrap();
41 // and finally move back to the const world, always normalizing because
42 // this is not called for statics.
43 op_to_const(&ecx, field)
b7449926
XL
44}
45
dfeec247 46pub(crate) fn const_caller_location<'tcx>(
e74abb32
XL
47 tcx: TyCtxt<'tcx>,
48 (file, line, col): (Symbol, u32, u32),
49) -> &'tcx ty::Const<'tcx> {
50 trace!("const_caller_location: {}:{}:{}", file, line, col);
dfeec247 51 let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
e74abb32 52
60c5eb7d
XL
53 let loc_ty = tcx.caller_location_ty();
54 let loc_place = ecx.alloc_caller_location(file, line, col);
dfeec247 55 intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
e74abb32
XL
56 let loc_const = ty::Const {
57 ty: loc_ty,
60c5eb7d 58 val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
e74abb32
XL
59 };
60
61 tcx.mk_const(loc_const)
62}
63
dfeec247
XL
64// this function uses `unwrap` copiously, because an already validated constant
65// must have valid fields and can thus never fail outside of compiler bugs
66pub(crate) fn destructure_const<'tcx>(
dc9dc135 67 tcx: TyCtxt<'tcx>,
b7449926 68 param_env: ty::ParamEnv<'tcx>,
dc9dc135 69 val: &'tcx ty::Const<'tcx>,
dfeec247
XL
70) -> mir::DestructuredConst<'tcx> {
71 trace!("destructure_const: {:?}", val);
72 let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
532ac7d7 73 let op = ecx.eval_const_to_op(val, None).unwrap();
a1dfa0c6 74
dfeec247 75 let variant = ecx.read_discriminant(op).unwrap().1;
b7449926 76
dfeec247
XL
77 let field_count = match val.ty.kind {
78 ty::Array(_, len) => len.eval_usize(tcx, param_env),
79 ty::Adt(def, _) => def.variants[variant].fields.len() as u64,
80 ty::Tuple(substs) => substs.len() as u64,
81 _ => bug!("cannot destructure constant {:?}", val),
82 };
b7449926 83
dfeec247
XL
84 let down = ecx.operand_downcast(op, variant).unwrap();
85 let fields_iter = (0..field_count).map(|i| {
86 let field_op = ecx.operand_field(down, i).unwrap();
87 op_to_const(&ecx, field_op)
88 });
89 let fields = tcx.arena.alloc_from_iter(fields_iter);
b7449926 90
dfeec247 91 mir::DestructuredConst { variant, fields }
b7449926 92}