Skip to content

Commit b50c1b2

Browse files
committed
Make const_eval_raw query return just an AllocId
1 parent 39852ca commit b50c1b2

18 files changed

+97
-64
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ impl_stable_hash_for!(
317317
ByRef(id, alloc, offset),
318318
}
319319
);
320+
impl_stable_hash_for!(struct ::mir::interpret::RawConst<'tcx> {
321+
alloc_id,
322+
ty,
323+
});
320324

321325
impl_stable_hash_for! {
322326
impl<Tag> for struct mir::interpret::Pointer<Tag> {

src/librustc/mir/interpret/error.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ty::{self, Ty, layout};
1616
use ty::layout::{Size, Align, LayoutError};
1717
use rustc_target::spec::abi::Abi;
1818

19-
use super::{Pointer, InboundsCheck, ScalarMaybeUndef};
19+
use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef};
2020

2121
use backtrace::Backtrace;
2222

@@ -46,6 +46,7 @@ impl ErrorHandled {
4646
}
4747
}
4848

49+
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
4950
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
5051

5152
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]

src/librustc/mir/interpret/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ mod pointer;
2222

2323
pub use self::error::{
2424
EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
25-
FrameInfo, ConstEvalResult, ErrorHandled,
25+
FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
2626
};
2727

28-
pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
28+
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
2929

3030
pub use self::allocation::{
3131
InboundsCheck, Allocation, AllocationExtra,

src/librustc/mir/interpret/value.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,28 @@
1010

1111
use std::fmt;
1212

13-
use ty::layout::{HasDataLayout, Size};
14-
use ty::subst::Substs;
15-
use hir::def_id::DefId;
13+
use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}};
14+
use crate::hir::def_id::DefId;
1615

1716
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
1817

18+
/// Represents the result of a raw const operation, pre-validation.
19+
#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
20+
pub struct RawConst<'tcx> {
21+
// the value lives here, at offset 0, and that allocation definitely is a `AllocType::Memory`
22+
// (so you can use `AllocMap::unwrap_memory`).
23+
pub alloc_id: AllocId,
24+
pub ty: Ty<'tcx>,
25+
}
26+
1927
/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
2028
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
2129
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
2230
pub enum ConstValue<'tcx> {
2331
/// Never returned from the `const_eval` query, but the HIR contains these frequently in order
2432
/// to allow HIR creation to happen for everything before needing to be able to run constant
2533
/// evaluation
34+
/// FIXME: The query should then return a type that does not even have this variant.
2635
Unevaluated(DefId, &'tcx Substs<'tcx>),
2736

2837
/// Used only for types with layout::abi::Scalar ABI and ZSTs

src/librustc/ty/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use middle::stability::{self, DeprecationEntry};
2727
use middle::lib_features::LibFeatures;
2828
use middle::lang_items::{LanguageItems, LangItem};
2929
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
30-
use mir::interpret::ConstEvalResult;
30+
use mir::interpret::{ConstEvalRawResult, ConstEvalResult};
3131
use mir::mono::CodegenUnit;
3232
use mir;
3333
use mir::interpret::GlobalId;
@@ -309,7 +309,7 @@ define_queries! { <'tcx>
309309
/// validation. Please add a comment to every use site explaining why using `const_eval`
310310
/// isn't sufficient
311311
[] fn const_eval_raw: const_eval_raw_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
312-
-> ConstEvalResult<'tcx>,
312+
-> ConstEvalRawResult<'tcx>,
313313

314314
/// Results of evaluating const items or constants embedded in
315315
/// other items (such as enum variant explicit discriminants).

src/librustc_mir/const_eval.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ use rustc::util::common::ErrorReported;
3131
use syntax::ast::Mutability;
3232
use syntax::source_map::{Span, DUMMY_SP};
3333

34-
use interpret::{self,
35-
PlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, ConstValue, Pointer,
34+
use crate::interpret::{self,
35+
PlaceTy, MPlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, RawConst, ConstValue, Pointer,
3636
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
3737
Allocation, AllocId, MemoryKind,
3838
snapshot, RefTracking,
@@ -94,11 +94,13 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
9494
cid: GlobalId<'tcx>,
9595
mir: &'mir mir::Mir<'tcx>,
9696
param_env: ty::ParamEnv<'tcx>,
97-
) -> EvalResult<'tcx, OpTy<'tcx>> {
97+
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
9898
let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
9999
eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
100100
}
101101

102+
// FIXME: This thing is a bad hack. We should get rid of it. Ideally constants are always
103+
// in an allocation.
102104
pub fn op_to_const<'tcx>(
103105
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
104106
op: OpTy<'tcx>,
@@ -150,7 +152,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
150152
cid: GlobalId<'tcx>,
151153
mir: Option<&'mir mir::Mir<'tcx>>,
152154
param_env: ty::ParamEnv<'tcx>,
153-
) -> (EvalResult<'tcx, OpTy<'tcx>>, CompileTimeEvalContext<'a, 'mir, 'tcx>) {
155+
) -> (EvalResult<'tcx, MPlaceTy<'tcx>>, CompileTimeEvalContext<'a, 'mir, 'tcx>) {
154156
// we start out with the best span we have
155157
// and try improving it down the road when more information is available
156158
let span = tcx.def_span(cid.instance.def_id());
@@ -166,7 +168,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
166168
cid: GlobalId<'tcx>,
167169
mir: Option<&'mir mir::Mir<'tcx>>,
168170
param_env: ty::ParamEnv<'tcx>,
169-
) -> EvalResult<'tcx, OpTy<'tcx>> {
171+
) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
170172
debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
171173
let tcx = ecx.tcx.tcx;
172174
let mut mir = match mir {
@@ -206,7 +208,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
206208
ecx.memory.intern_static(ret.ptr.to_ptr()?.alloc_id, mutability)?;
207209

208210
debug!("eval_body_using_ecx done: {:?}", *ret);
209-
Ok(ret.into())
211+
Ok(ret)
210212
}
211213

212214
impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
@@ -534,15 +536,17 @@ pub fn error_to_const_error<'a, 'mir, 'tcx>(
534536
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
535537
}
536538

537-
fn validate_const<'a, 'tcx>(
539+
fn validate_and_turn_into_const<'a, 'tcx>(
538540
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
539-
constant: &'tcx ty::Const<'tcx>,
541+
constant: RawConst<'tcx>,
540542
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
541543
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
542544
let cid = key.value;
543545
let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
544546
let val = (|| {
545-
let op = ecx.const_to_op(constant)?;
547+
let op = ecx.raw_const_to_mplace(constant)?.into();
548+
// FIXME: Once the visitor infrastructure landed, change validation to
549+
// work directly on `MPlaceTy`.
546550
let mut ref_tracking = RefTracking::new(op);
547551
while let Some((op, path)) = ref_tracking.todo.pop() {
548552
ecx.validate_operand(
@@ -552,7 +556,10 @@ fn validate_const<'a, 'tcx>(
552556
/* const_mode */ true,
553557
)?;
554558
}
555-
Ok(constant)
559+
// Now that we validated, turn this into a proper constant
560+
let def_id = cid.instance.def.def_id();
561+
let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
562+
op_to_const(&ecx, op, normalize)
556563
})();
557564

558565
val.map_err(|error| {
@@ -591,14 +598,14 @@ pub fn const_eval_provider<'a, 'tcx>(
591598
}
592599
}
593600
tcx.const_eval_raw(key).and_then(|val| {
594-
validate_const(tcx, val, key)
601+
validate_and_turn_into_const(tcx, val, key)
595602
})
596603
}
597604

598605
pub fn const_eval_raw_provider<'a, 'tcx>(
599606
tcx: TyCtxt<'a, 'tcx, 'tcx>,
600607
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
601-
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
608+
) -> ::rustc::mir::interpret::ConstEvalRawResult<'tcx> {
602609
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
603610
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
604611
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
@@ -648,16 +655,11 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
648655
};
649656

650657
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
651-
res.and_then(|op| {
652-
let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
653-
if !normalize {
654-
// Sanity check: These must always be a MemPlace
655-
match op.op {
656-
Operand::Indirect(_) => { /* all is good */ },
657-
Operand::Immediate(_) => bug!("const eval gave us an Immediate"),
658-
}
659-
}
660-
op_to_const(&ecx, op, normalize)
658+
res.and_then(|place| {
659+
Ok(RawConst {
660+
alloc_id: place.to_ptr().expect("we allocated this ptr!").alloc_id,
661+
ty: place.layout.ty
662+
})
661663
}).map_err(|error| {
662664
let err = error_to_const_error(&ecx, error);
663665
// errors in statics are always emitted as fatal errors

src/librustc_mir/interpret/memory.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap};
2828
use syntax::ast::Mutability;
2929

3030
use super::{
31-
Pointer, AllocId, Allocation, ConstValue, GlobalId, AllocationExtra, InboundsCheck,
31+
Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck,
3232
EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
3333
Machine, AllocMap, MayLeak, ScalarMaybeUndef, ErrorHandled,
3434
};
@@ -374,14 +374,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
374374
ErrorHandled::Reported => EvalErrorKind::ReferencedConstant.into(),
375375
ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric.into(),
376376
}
377-
}).map(|const_val| {
378-
if let ConstValue::ByRef(_, allocation, _) = const_val.val {
379-
// We got tcx memory. Let the machine figure out whether and how to
380-
// turn that into memory with the right pointer tag.
381-
M::adjust_static_allocation(allocation)
382-
} else {
383-
bug!("Matching on non-ByRef static")
384-
}
377+
}).map(|raw_const| {
378+
let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id);
379+
// We got tcx memory. Let the machine figure out whether and how to
380+
// turn that into memory with the right pointer tag.
381+
M::adjust_static_allocation(allocation)
385382
})
386383
}
387384

src/librustc_mir/interpret/operand.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
536536
}
537537

538538
// Also used e.g. when miri runs into a constant.
539-
pub(super) fn const_value_to_op(
539+
// FIXME: Can we avoid converting with ConstValue and Const? We should be using RawConst.
540+
fn const_value_to_op(
540541
&self,
541542
val: ConstValue<'tcx>,
542543
) -> EvalResult<'tcx, Operand<M::PointerTag>> {

src/librustc_mir/interpret/place.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@ use rustc::mir;
2020
use rustc::ty::{self, Ty};
2121
use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
2222

23-
use rustc::mir::interpret::{
24-
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
25-
};
2623
use super::{
24+
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
2725
EvalContext, Machine, AllocMap, AllocationExtra,
28-
Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
26+
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
2927
};
3028

3129
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -981,6 +979,19 @@ where
981979
Ok(OpTy { op, layout: place.layout })
982980
}
983981

982+
pub fn raw_const_to_mplace(
983+
&self,
984+
raw: RawConst<'tcx>,
985+
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
986+
// This must be an allocation in `tcx`
987+
assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some());
988+
let layout = self.layout_of(raw.ty)?;
989+
Ok(MPlaceTy::from_aligned_ptr(
990+
Pointer::new(raw.alloc_id, Size::ZERO).with_default_tag(),
991+
layout,
992+
))
993+
}
994+
984995
/// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
985996
/// Also return some more information so drop doesn't have to run the same code twice.
986997
pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx, M::PointerTag>)

src/librustc_mir/transform/const_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
309309
eval_promoted(this.tcx, cid, this.mir, this.param_env)
310310
})?;
311311
trace!("evaluated promoted {:?} to {:?}", promoted, res);
312-
Some((res, source_info.span))
312+
Some((res.into(), source_info.span))
313313
},
314314
_ => None,
315315
}

0 commit comments

Comments
 (0)