|
1 | 1 | // Not in interpret to make sure we do not use private implementation details
|
2 | 2 |
|
3 |
| -use std::convert::TryInto; |
4 |
| -use std::error::Error; |
5 |
| -use std::fmt; |
6 |
| -use std::hash::Hash; |
7 |
| - |
8 | 3 | use rustc::mir;
|
9 |
| -use rustc::ty::layout::{self, VariantIdx}; |
| 4 | +use rustc::ty::layout::VariantIdx; |
10 | 5 | use rustc::ty::{self, TyCtxt};
|
11 | 6 |
|
12 |
| -use syntax::{ |
13 |
| - source_map::{Span, DUMMY_SP}, |
14 |
| - symbol::Symbol, |
15 |
| -}; |
| 7 | +use syntax::{source_map::DUMMY_SP, symbol::Symbol}; |
16 | 8 |
|
17 |
| -use crate::interpret::{ |
18 |
| - intern_const_alloc_recursive, Allocation, ConstValue, ImmTy, Immediate, InterpCx, OpTy, Scalar, |
19 |
| -}; |
| 9 | +use crate::interpret::{intern_const_alloc_recursive, ConstValue, InterpCx}; |
20 | 10 |
|
21 | 11 | mod error;
|
22 | 12 | mod query;
|
23 | 13 |
|
24 | 14 | pub use error::*;
|
25 | 15 | pub use query::*;
|
26 | 16 |
|
27 |
| -/// The `InterpCx` is only meant to be used to do field and index projections into constants for |
28 |
| -/// `simd_shuffle` and const patterns in match arms. |
29 |
| -/// |
30 |
| -/// The function containing the `match` that is currently being analyzed may have generic bounds |
31 |
| -/// that inform us about the generic bounds of the constant. E.g., using an associated constant |
32 |
| -/// of a function's generic parameter will require knowledge about the bounds on the generic |
33 |
| -/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument. |
34 |
| -fn mk_eval_cx<'mir, 'tcx>( |
35 |
| - tcx: TyCtxt<'tcx>, |
36 |
| - span: Span, |
37 |
| - param_env: ty::ParamEnv<'tcx>, |
38 |
| - can_access_statics: bool, |
39 |
| -) -> CompileTimeEvalContext<'mir, 'tcx> { |
40 |
| - debug!("mk_eval_cx: {:?}", param_env); |
41 |
| - InterpCx::new( |
42 |
| - tcx.at(span), |
43 |
| - param_env, |
44 |
| - CompileTimeInterpreter::new(), |
45 |
| - MemoryExtra { can_access_statics }, |
46 |
| - ) |
47 |
| -} |
48 |
| - |
49 |
| -fn op_to_const<'tcx>( |
50 |
| - ecx: &CompileTimeEvalContext<'_, 'tcx>, |
51 |
| - op: OpTy<'tcx>, |
52 |
| -) -> &'tcx ty::Const<'tcx> { |
53 |
| - // We do not have value optimizations for everything. |
54 |
| - // Only scalars and slices, since they are very common. |
55 |
| - // Note that further down we turn scalars of undefined bits back to `ByRef`. These can result |
56 |
| - // from scalar unions that are initialized with one of their zero sized variants. We could |
57 |
| - // instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all |
58 |
| - // the usual cases of extracting e.g. a `usize`, without there being a real use case for the |
59 |
| - // `Undef` situation. |
60 |
| - let try_as_immediate = match op.layout.abi { |
61 |
| - layout::Abi::Scalar(..) => true, |
62 |
| - layout::Abi::ScalarPair(..) => match op.layout.ty.kind { |
63 |
| - ty::Ref(_, inner, _) => match inner.kind { |
64 |
| - ty::Slice(elem) => elem == ecx.tcx.types.u8, |
65 |
| - ty::Str => true, |
66 |
| - _ => false, |
67 |
| - }, |
68 |
| - _ => false, |
69 |
| - }, |
70 |
| - _ => false, |
71 |
| - }; |
72 |
| - let immediate = if try_as_immediate { |
73 |
| - Err(ecx.read_immediate(op).expect("normalization works on validated constants")) |
74 |
| - } else { |
75 |
| - // It is guaranteed that any non-slice scalar pair is actually ByRef here. |
76 |
| - // When we come back from raw const eval, we are always by-ref. The only way our op here is |
77 |
| - // by-val is if we are in const_field, i.e., if this is (a field of) something that we |
78 |
| - // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or |
79 |
| - // structs containing such. |
80 |
| - op.try_as_mplace() |
81 |
| - }; |
82 |
| - let val = match immediate { |
83 |
| - Ok(mplace) => { |
84 |
| - let ptr = mplace.ptr.to_ptr().unwrap(); |
85 |
| - let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); |
86 |
| - ConstValue::ByRef { alloc, offset: ptr.offset } |
87 |
| - } |
88 |
| - // see comment on `let try_as_immediate` above |
89 |
| - Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x { |
90 |
| - ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s), |
91 |
| - ScalarMaybeUndef::Undef => { |
92 |
| - // When coming out of "normal CTFE", we'll always have an `Indirect` operand as |
93 |
| - // argument and we will not need this. The only way we can already have an |
94 |
| - // `Immediate` is when we are called from `const_field`, and that `Immediate` |
95 |
| - // comes from a constant so it can happen have `Undef`, because the indirect |
96 |
| - // memory that was read had undefined bytes. |
97 |
| - let mplace = op.assert_mem_place(); |
98 |
| - let ptr = mplace.ptr.to_ptr().unwrap(); |
99 |
| - let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); |
100 |
| - ConstValue::ByRef { alloc, offset: ptr.offset } |
101 |
| - } |
102 |
| - }, |
103 |
| - Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => { |
104 |
| - let (data, start) = match a.not_undef().unwrap() { |
105 |
| - Scalar::Ptr(ptr) => { |
106 |
| - (ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes()) |
107 |
| - } |
108 |
| - Scalar::Raw { .. } => ( |
109 |
| - ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])), |
110 |
| - 0, |
111 |
| - ), |
112 |
| - }; |
113 |
| - let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap(); |
114 |
| - let start = start.try_into().unwrap(); |
115 |
| - let len: usize = len.try_into().unwrap(); |
116 |
| - ConstValue::Slice { data, start, end: start + len } |
117 |
| - } |
118 |
| - }; |
119 |
| - ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty }) |
120 |
| -} |
121 |
| - |
122 | 17 | /// Extracts a field of a (variant of a) const.
|
123 | 18 | // this function uses `unwrap` copiously, because an already validated constant must have valid
|
124 | 19 | // fields and can thus never fail outside of compiler bugs
|
|
0 commit comments