|
2 | 2 |
|
3 | 3 | use std::convert::TryFrom;
|
4 | 4 |
|
| 5 | +use rustc_hir::Mutability; |
5 | 6 | use rustc_middle::mir;
|
6 | 7 | use rustc_middle::ty::{self, TyCtxt};
|
7 | 8 | use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
8 | 9 |
|
9 |
| -use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx}; |
| 10 | +use crate::interpret::{ |
| 11 | + intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MemPlaceMeta, Scalar, |
| 12 | +}; |
10 | 13 |
|
11 | 14 | mod error;
|
12 | 15 | mod eval_queries;
|
@@ -67,3 +70,40 @@ pub(crate) fn destructure_const<'tcx>(
|
67 | 70 |
|
68 | 71 | mir::DestructuredConst { variant, fields }
|
69 | 72 | }
|
| 73 | + |
| 74 | +pub(crate) fn deref_const<'tcx>( |
| 75 | + tcx: TyCtxt<'tcx>, |
| 76 | + param_env: ty::ParamEnv<'tcx>, |
| 77 | + val: &'tcx ty::Const<'tcx>, |
| 78 | +) -> &'tcx ty::Const<'tcx> { |
| 79 | + trace!("deref_const: {:?}", val); |
| 80 | + let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); |
| 81 | + let op = ecx.const_to_op(val, None).unwrap(); |
| 82 | + let mplace = ecx.deref_operand(op).unwrap(); |
| 83 | + if let Scalar::Ptr(ptr) = mplace.ptr { |
| 84 | + assert_eq!( |
| 85 | + ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability, |
| 86 | + Mutability::Not, |
| 87 | + "deref_const cannot be used with mutable allocations as \ |
| 88 | + that could allow pattern matching to observe mutable statics", |
| 89 | + ); |
| 90 | + } |
| 91 | + |
| 92 | + let ty = match mplace.meta { |
| 93 | + MemPlaceMeta::None => mplace.layout.ty, |
| 94 | + MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace), |
| 95 | + // In case of unsized types, figure out the real type behind. |
| 96 | + MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind { |
| 97 | + ty::Dynamic(..) => ecx.read_drop_type_from_vtable(scalar).unwrap().1, |
| 98 | + ty::Str => bug!("there's no sized equivalent of a `str`"), |
| 99 | + ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()), |
| 100 | + _ => bug!( |
| 101 | + "type {} should not have metadata, but had {:?}", |
| 102 | + mplace.layout.ty, |
| 103 | + mplace.meta |
| 104 | + ), |
| 105 | + }, |
| 106 | + }; |
| 107 | + |
| 108 | + tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, mplace.into())), ty }) |
| 109 | +} |
0 commit comments