Skip to content

Commit 2f2a11d

Browse files
committed
Auto merge of #50710 - Zoxc:value_to_constvalue, r=oli-obk
Fix conversion from Miri Value to ConstValue This fixes an error compiling the `immeta` 0.3.6 crate. #50707 may be fixed too. r? @oli-obk
2 parents e1151c9 + 41a032d commit 2f2a11d

File tree

2 files changed

+88
-56
lines changed

2 files changed

+88
-56
lines changed

src/librustc_mir/interpret/const_eval.rs

+67-56
Original file line numberDiff line numberDiff line change
@@ -93,50 +93,69 @@ pub fn eval_body<'a, 'tcx>(
9393
}
9494
}
9595

96-
pub fn value_to_const_value<'a, 'tcx>(
97-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
98-
val: Value,
96+
pub fn value_to_const_value<'tcx>(
97+
ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
98+
mut 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 result = (|| {
102+
// Convert to ByVal or ByValPair if possible
103+
if let Value::ByRef(ptr, align) = val {
104+
if let Some(read_val) = ecx.try_read_value(ptr, align, ty)? {
105+
val = read_val;
106+
}
107+
}
102108

103-
if layout.is_zst() {
104-
return ty::Const::from_const_value(
105-
tcx,
106-
ConstValue::ByVal(PrimVal::Undef),
107-
ty);
108-
}
109+
let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
109110

110-
let val = match layout.abi {
111-
layout::Abi::Scalar(..) => {
112-
if let Value::ByVal(val) = val {
113-
ConstValue::ByVal(val)
114-
} else {
115-
bug!("expected ByVal value, got {:?}", val);
116-
}
111+
if layout.is_zst() {
112+
return Ok(ty::Const::from_const_value(
113+
ecx.tcx.tcx,
114+
ConstValue::ByVal(PrimVal::Undef),
115+
ty));
117116
}
118-
layout::Abi::ScalarPair(..) => {
119-
if let Value::ByValPair(a, b) = val {
120-
ConstValue::ByValPair(a, b)
121-
} else {
122-
bug!("expected ByValPair value, got {:?}", val);
117+
118+
let val = match layout.abi {
119+
layout::Abi::Scalar(..) => {
120+
if let Value::ByVal(val) = val {
121+
ConstValue::ByVal(val)
122+
} else {
123+
bug!("expected ByVal value, got {:?}", val);
124+
}
123125
}
124-
}
125-
_ => {
126-
if let Value::ByRef(ptr, align) = val {
127-
let ptr = ptr.primval.to_ptr().unwrap();
128-
assert_eq!(ptr.offset, 0);
129-
let alloc = tcx.interpret_interner
130-
.get_alloc(ptr.alloc_id)
131-
.expect("miri allocation never successfully created");
132-
assert_eq!(align, alloc.align);
133-
ConstValue::ByRef(alloc)
134-
} else {
135-
bug!("expected ByRef value, got {:?}", val);
126+
layout::Abi::ScalarPair(..) => {
127+
if let Value::ByValPair(a, b) = val {
128+
ConstValue::ByValPair(a, b)
129+
} else {
130+
bug!("expected ByValPair value, got {:?}", val);
131+
}
136132
}
137-
},
138-
};
139-
ty::Const::from_const_value(tcx, val, ty)
133+
_ => {
134+
if let Value::ByRef(ptr, _) = val {
135+
let ptr = ptr.primval.to_ptr().unwrap();
136+
assert_eq!(ptr.offset, 0);
137+
let alloc = ecx.memory.get(ptr.alloc_id)?;
138+
assert!(alloc.align.abi() >= layout.align.abi());
139+
assert!(alloc.bytes.len() as u64 == layout.size.bytes());
140+
let mut alloc = alloc.clone();
141+
// The align field is meaningless for values, so just use the layout's align
142+
alloc.align = layout.align;
143+
let alloc = ecx.tcx.intern_const_alloc(alloc);
144+
ConstValue::ByRef(alloc)
145+
} else {
146+
bug!("expected ByRef value, got {:?}", val);
147+
}
148+
},
149+
};
150+
Ok(ty::Const::from_const_value(ecx.tcx.tcx, val, ty))
151+
})();
152+
match result {
153+
Ok(v) => v,
154+
Err(mut err) => {
155+
ecx.report(&mut err, true, None);
156+
bug!("miri error occured when converting Value to ConstValue")
157+
}
158+
}
140159
}
141160

142161
fn eval_body_and_ecx<'a, 'mir, 'tcx>(
@@ -423,7 +442,7 @@ pub fn const_val_field<'a, 'tcx>(
423442
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
424443
let result = (|| {
425444
let value = ecx.const_value_to_value(value, ty)?;
426-
let (mut field, ty) = match value {
445+
let (field, ty) = match value {
427446
Value::ByValPair(..) | Value::ByVal(_) =>
428447
ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
429448
Value::ByRef(ptr, align) => {
@@ -438,24 +457,16 @@ pub fn const_val_field<'a, 'tcx>(
438457
(Value::ByRef(ptr, align), layout.ty)
439458
}
440459
};
441-
if let Value::ByRef(ptr, align) = field {
442-
if let Some(val) = ecx.try_read_value(ptr, align, ty)? {
443-
field = val;
444-
}
445-
}
446-
Ok((field, ty))
460+
Ok(value_to_const_value(&ecx, field, ty))
447461
})();
448-
match result {
449-
Ok((field, ty)) => Ok(value_to_const_value(tcx, field, ty)),
450-
Err(err) => {
451-
let (trace, span) = ecx.generate_stacktrace(None);
452-
let err = ErrKind::Miri(err, trace);
453-
Err(ConstEvalErr {
454-
kind: err.into(),
455-
span,
456-
})
457-
},
458-
}
462+
result.map_err(|err| {
463+
let (trace, span) = ecx.generate_stacktrace(None);
464+
let err = ErrKind::Miri(err, trace);
465+
ConstEvalErr {
466+
kind: err.into(),
467+
span,
468+
}
469+
})
459470
}
460471

461472
pub fn const_variant_index<'a, 'tcx>(
@@ -541,7 +552,7 @@ pub fn const_eval_provider<'a, 'tcx>(
541552

542553
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
543554
res.map(|(val, _, miri_ty)| {
544-
value_to_const_value(tcx, val, miri_ty)
555+
value_to_const_value(&ecx, val, miri_ty)
545556
}).map_err(|mut err| {
546557
if tcx.is_static(def_id).is_some() {
547558
ecx.report(&mut err, true, None);
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[derive(Eq, PartialEq)]
12+
pub struct Data([u8; 4]);
13+
14+
const DATA: Data = Data([1, 2, 3, 4]);
15+
16+
fn main() {
17+
match DATA {
18+
DATA => (),
19+
_ => (),
20+
}
21+
}

0 commit comments

Comments
 (0)