]>
Commit | Line | Data |
---|---|---|
b7449926 XL |
1 | // Not in interpret to make sure we do not use private implementation details |
2 | ||
b7449926 | 3 | use rustc::mir; |
dfeec247 XL |
4 | use rustc::ty::layout::VariantIdx; |
5 | use rustc::ty::{self, TyCtxt}; | |
6 | use rustc_span::{source_map::DUMMY_SP, symbol::Symbol}; | |
0bf4aa26 | 7 | |
dfeec247 | 8 | use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx}; |
0bf4aa26 | 9 | |
dfeec247 XL |
10 | mod error; |
11 | mod eval_queries; | |
12 | mod fn_queries; | |
13 | mod machine; | |
0bf4aa26 | 14 | |
dfeec247 XL |
15 | pub use error::*; |
16 | pub use eval_queries::*; | |
17 | pub use fn_queries::*; | |
18 | pub 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 | 23 | pub(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 | 46 | pub(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 | |
66 | pub(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 | } |