Skip to content

Commit 3e933f4

Browse files
committed
Keep statics' constant as ByRef
1 parent 6630678 commit 3e933f4

File tree

2 files changed

+44
-20
lines changed

2 files changed

+44
-20
lines changed

src/librustc_mir/interpret/const_eval.rs

+30-20
Original file line numberDiff line numberDiff line change
@@ -95,42 +95,35 @@ pub fn eval_body<'a, 'tcx>(
9595

9696
pub fn value_to_const_value<'tcx>(
9797
ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
98-
mut val: Value,
98+
val: Value,
9999
ty: Ty<'tcx>,
100100
) -> &'tcx ty::Const<'tcx> {
101-
let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
101+
let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
102102
match (val, &layout.abi) {
103+
(Value::ByVal(PrimVal::Undef), _) if layout.is_zst() => {},
103104
(Value::ByRef(..), _) |
104105
(Value::ByVal(_), &layout::Abi::Scalar(_)) |
105106
(Value::ByValPair(..), &layout::Abi::ScalarPair(..)) => {},
106107
_ => bug!("bad value/layout combo: {:#?}, {:#?}", val, layout),
107108
}
108109
let val = (|| {
109-
// Convert to ByVal or ByValPair if possible
110-
if let Value::ByRef(ptr, align) = val {
111-
if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
112-
val = read_val;
113-
}
114-
}
115110
match val {
116111
Value::ByVal(val) => Ok(ConstValue::ByVal(val)),
117112
Value::ByValPair(a, b) => Ok(ConstValue::ByValPair(a, b)),
118113
Value::ByRef(ptr, align) => {
119114
let ptr = ptr.primval.to_ptr().unwrap();
120-
assert_eq!(ptr.offset, 0);
121115
let alloc = ecx.memory.get(ptr.alloc_id)?;
122-
assert!(alloc.align.abi() >= layout.align.abi());
123-
assert!(alloc.bytes.len() as u64 == layout.size.bytes());
116+
assert!(alloc.align.abi() >= align.abi());
117+
assert!(alloc.bytes.len() as u64 - ptr.offset >= layout.size.bytes());
124118
let mut alloc = alloc.clone();
125-
// The align field is meaningless for values, so just use the layout's align
126-
alloc.align = layout.align;
119+
alloc.align = align;
127120
let alloc = ecx.tcx.intern_const_alloc(alloc);
128-
Ok(ConstValue::ByRef(alloc))
121+
Ok(ConstValue::ByRef(alloc, ptr.offset))
129122
}
130123
}
131124
})();
132-
match result {
133-
Ok(v) => ty::Const::from_const_value(tcx, val, ty),
125+
match val {
126+
Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty),
134127
Err(mut err) => {
135128
ecx.report(&mut err, true, None);
136129
bug!("miri error occured when converting Value to ConstValue")
@@ -427,7 +420,7 @@ pub fn const_val_field<'a, 'tcx>(
427420
Value::ByRef(ptr, align) => (ptr, align),
428421
Value::ByValPair(..) | Value::ByVal(_) => {
429422
let ptr = ecx.alloc_ptr(ty)?.into();
430-
ecx.write_value_to_ptr(value, ptr, ty)?;
423+
ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
431424
(ptr, layout.align)
432425
},
433426
};
@@ -438,7 +431,21 @@ pub fn const_val_field<'a, 'tcx>(
438431
};
439432
let (place, layout) = ecx.place_field(place, field, layout)?;
440433
let (ptr, align) = place.to_ptr_align();
441-
Ok((Value::ByRef(ptr, align), layout.ty))
434+
let mut new_value = Value::ByRef(ptr, align);
435+
new_value = ecx.try_read_by_ref(new_value, layout.ty)?;
436+
use rustc_data_structures::indexed_vec::Idx;
437+
match (value, new_value) {
438+
(Value::ByVal(_), Value::ByRef(..)) |
439+
(Value::ByValPair(..), Value::ByRef(..)) |
440+
(Value::ByVal(_), Value::ByValPair(..)) => bug!(
441+
"field {} of {:?} yielded {:?}",
442+
field.index(),
443+
value,
444+
new_value,
445+
),
446+
_ => {},
447+
}
448+
Ok(value_to_const_value(&ecx, new_value, layout.ty))
442449
})();
443450
result.map_err(|err| {
444451
let (trace, span) = ecx.generate_stacktrace(None);
@@ -535,8 +542,11 @@ pub fn const_eval_provider<'a, 'tcx>(
535542
};
536543

537544
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
538-
res.map(|(val, _, miri_ty)| {
539-
value_to_const_value(&ecx, val, miri_ty)
545+
res.and_then(|(mut val, _, miri_ty)| {
546+
if tcx.is_static(def_id).is_none() {
547+
val = ecx.try_read_by_ref(val, miri_ty)?;
548+
}
549+
Ok(value_to_const_value(&ecx, val, miri_ty))
540550
}).map_err(|mut err| {
541551
if tcx.is_static(def_id).is_some() {
542552
ecx.report(&mut err, true, None);

src/librustc_mir/interpret/eval_context.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1412,10 +1412,24 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
14121412
Ok(())
14131413
}
14141414

1415+
pub fn try_read_by_ref(&self, mut val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
1416+
// Convert to ByVal or ByValPair if possible
1417+
if let Value::ByRef(ptr, align) = val {
1418+
if let Some(read_val) = self.try_read_value(ptr, align, ty)? {
1419+
val = read_val;
1420+
}
1421+
}
1422+
Ok(val)
1423+
}
1424+
14151425
pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
14161426
let layout = self.layout_of(ty)?;
14171427
self.memory.check_align(ptr, ptr_align)?;
14181428

1429+
if layout.size.bytes() == 0 {
1430+
return Ok(Some(Value::ByVal(PrimVal::Undef)));
1431+
}
1432+
14191433
let ptr = ptr.to_ptr()?;
14201434

14211435
// Not the right place to do this

0 commit comments

Comments
 (0)