mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Prepare for using miri in trans
This commit is contained in:
parent
4c9b1b13dd
commit
b2b101befc
@ -60,15 +60,15 @@
|
||||
//! user of the `DepNode` API of having to know how to compute the expected
|
||||
//! fingerprint for a given set of node parameters.
|
||||
|
||||
use mir::interpret::{GlobalId};
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
|
||||
use hir::map::DefPathHash;
|
||||
use hir::{HirId, ItemLocalId};
|
||||
|
||||
use ich::Fingerprint;
|
||||
use ich::{Fingerprint, StableHashingContext};
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
||||
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
|
||||
use ty::subst::Substs;
|
||||
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
|
||||
use ich::StableHashingContext;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use syntax_pos::symbol::InternedString;
|
||||
@ -518,7 +518,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] TypeckTables(DefId),
|
||||
[] UsedTraitImports(DefId),
|
||||
[] HasTypeckTables(DefId),
|
||||
[] ConstEval { param_env: ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)> },
|
||||
[] ConstEval { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
|
||||
[] CheckMatch(DefId),
|
||||
[] SymbolName(DefId),
|
||||
[] InstanceSymbolName { instance: Instance<'tcx> },
|
||||
|
@ -585,3 +585,5 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::ClosureOutlivesSubjec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted });
|
||||
|
@ -926,13 +926,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
|
||||
ty::InstanceDef::ClosureOnceShim { call_once } => {
|
||||
call_once.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::InstanceDef::DropGlue(def_id, t) => {
|
||||
ty::InstanceDef::DropGlue(def_id, ty) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
t.hash_stable(hcx, hasher);
|
||||
ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::InstanceDef::CloneShim(def_id, t) => {
|
||||
ty::InstanceDef::CloneShim(def_id, ty) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
t.hash_stable(hcx, hasher);
|
||||
ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,9 @@
|
||||
// except according to those terms.
|
||||
|
||||
use infer::{RegionObligation, InferCtxt};
|
||||
use middle::const_val::ConstEvalErr;
|
||||
use middle::const_val::ErrKind::TypeckError;
|
||||
use mir::interpret::GlobalId;
|
||||
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
|
||||
use ty::error::ExpectedFound;
|
||||
use rustc_data_structures::obligation_forest::{ObligationForest, Error};
|
||||
@ -514,17 +517,34 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||
}
|
||||
Some(param_env) => {
|
||||
match selcx.tcx().lift_to_global(&substs) {
|
||||
Some(substs) => {
|
||||
let instance = ty::Instance::resolve(
|
||||
selcx.tcx().global_tcx(),
|
||||
param_env,
|
||||
def_id,
|
||||
substs,
|
||||
);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match selcx.tcx().at(obligation.cause.span)
|
||||
.const_eval(param_env.and(cid)) {
|
||||
Ok(_) => Ok(Some(vec![])),
|
||||
Err(e) => Err(CodeSelectionError(ConstEvalFailure(e)))
|
||||
}
|
||||
} else {
|
||||
Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
|
||||
span: selcx.tcx().def_span(def_id),
|
||||
kind: TypeckError,
|
||||
})))
|
||||
}
|
||||
},
|
||||
None => {
|
||||
pending_obligation.stalled_on = substs.types().collect();
|
||||
Ok(None)
|
||||
}
|
||||
Some(substs) => {
|
||||
match selcx.tcx().at(obligation.cause.span)
|
||||
.const_eval(param_env.and((def_id, substs))) {
|
||||
Ok(_) => Ok(Some(vec![])),
|
||||
Err(e) => Err(CodeSelectionError(ConstEvalFailure(e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ use hir::def_id::DefId;
|
||||
use infer::{InferCtxt, InferOk};
|
||||
use infer::type_variable::TypeVariableOrigin;
|
||||
use middle::const_val::ConstVal;
|
||||
use mir::interpret::{GlobalId};
|
||||
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
|
||||
use syntax::symbol::Symbol;
|
||||
use ty::subst::{Subst, Substs};
|
||||
@ -400,12 +401,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
|
||||
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if let ConstVal::Unevaluated(def_id, substs) = constant.val {
|
||||
if substs.needs_infer() {
|
||||
let identity_substs = Substs::identity_for_item(self.tcx(), def_id);
|
||||
let data = self.param_env.and((def_id, identity_substs));
|
||||
match self.tcx().lift_to_global(&data) {
|
||||
Some(data) => {
|
||||
match self.tcx().const_eval(data) {
|
||||
let tcx = self.selcx.tcx().global_tcx();
|
||||
if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
|
||||
if substs.needs_infer() {
|
||||
let identity_substs = Substs::identity_for_item(tcx, def_id);
|
||||
let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => {
|
||||
let evaluated = evaluated.subst(self.tcx(), substs);
|
||||
return self.fold_const(evaluated);
|
||||
@ -413,18 +419,20 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
} else {
|
||||
let data = self.param_env.and((def_id, substs));
|
||||
match self.tcx().lift_to_global(&data) {
|
||||
Some(data) => {
|
||||
match self.tcx().const_eval(data) {
|
||||
Ok(evaluated) => return self.fold_const(evaluated),
|
||||
Err(_) => {}
|
||||
} else {
|
||||
if let Some(substs) = self.tcx().lift_to_global(&substs) {
|
||||
let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(evaluated) => return self.fold_const(evaluated),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::fast_reject;
|
||||
use ty::relate::TypeRelation;
|
||||
use middle::lang_items;
|
||||
use mir::interpret::{GlobalId};
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use std::iter;
|
||||
@ -732,11 +733,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::Predicate::ConstEvaluatable(def_id, substs) => {
|
||||
match self.tcx().lift_to_global(&(obligation.param_env, substs)) {
|
||||
let tcx = self.tcx();
|
||||
match tcx.lift_to_global(&(obligation.param_env, substs)) {
|
||||
Some((param_env, substs)) => {
|
||||
match self.tcx().const_eval(param_env.and((def_id, substs))) {
|
||||
Ok(_) => EvaluatedToOk,
|
||||
Err(_) => EvaluatedToErr
|
||||
let instance = ty::Instance::resolve(
|
||||
tcx.global_tcx(),
|
||||
param_env,
|
||||
def_id,
|
||||
substs,
|
||||
);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match self.tcx().const_eval(param_env.and(cid)) {
|
||||
Ok(_) => EvaluatedToOk,
|
||||
Err(_) => EvaluatedToErr
|
||||
}
|
||||
} else {
|
||||
EvaluatedToErr
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -10,9 +10,10 @@
|
||||
|
||||
use dep_graph::SerializedDepNodeIndex;
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use mir::interpret::{GlobalId};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::maps::queries;
|
||||
use ty::subst::Substs;
|
||||
use ty::maps::queries;
|
||||
|
||||
use std::hash::Hash;
|
||||
use syntax_pos::symbol::InternedString;
|
||||
@ -152,8 +153,8 @@ impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
|
||||
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> String {
|
||||
format!("const-evaluating `{}`", tcx.item_path_str(key.value.0))
|
||||
fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
|
||||
format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,16 @@ impl<'tcx> Key for ty::Instance<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
self.instance.map_crate()
|
||||
}
|
||||
|
||||
fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||
self.instance.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Key for CrateNum {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
*self
|
||||
|
@ -29,6 +29,7 @@ use middle::lang_items::{LanguageItems, LangItem};
|
||||
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
|
||||
use mir::mono::{CodegenUnit, Stats};
|
||||
use mir;
|
||||
use mir::interpret::{GlobalId};
|
||||
use session::{CompileResult, CrateDisambiguator};
|
||||
use session::config::OutputFilenames;
|
||||
use traits::Vtable;
|
||||
@ -210,7 +211,7 @@ define_maps! { <'tcx>
|
||||
|
||||
/// Results of evaluating const items or constants embedded in
|
||||
/// other items (such as enum variant explicit discriminants).
|
||||
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
[] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> const_val::EvalResult<'tcx>,
|
||||
|
||||
[] fn check_match: CheckMatch(DefId)
|
||||
@ -450,7 +451,7 @@ fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
||||
DepConstructor::TypeckBodiesKrate
|
||||
}
|
||||
|
||||
fn const_eval_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
|
||||
fn const_eval_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> DepConstructor<'tcx> {
|
||||
DepConstructor::ConstEval { param_env }
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
|
||||
use middle::privacy::AccessLevels;
|
||||
use middle::resolve_lifetime::ObjectLifetimeDefault;
|
||||
use mir::Mir;
|
||||
use mir::interpret::{Value, PrimVal};
|
||||
use mir::interpret::{GlobalId, Value, PrimVal};
|
||||
use mir::GeneratorLayout;
|
||||
use session::CrateDisambiguator;
|
||||
use traits;
|
||||
@ -1835,7 +1835,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
|
||||
if let VariantDiscr::Explicit(expr_did) = v.discr {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
let instance = ty::Instance::new(expr_did, substs);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(&ty::Const {
|
||||
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
|
||||
..
|
||||
@ -1885,7 +1890,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
}
|
||||
ty::VariantDiscr::Explicit(expr_did) => {
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
|
||||
match tcx.const_eval(param_env.and((expr_did, substs))) {
|
||||
let instance = ty::Instance::new(expr_did, substs);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(&ty::Const {
|
||||
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
|
||||
..
|
||||
|
@ -20,7 +20,7 @@ use ty::subst::{UnpackedKind, Substs};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::fold::{TypeVisitor, TypeFolder};
|
||||
use ty::error::{ExpectedFound, TypeError};
|
||||
use mir::interpret::{Value, PrimVal};
|
||||
use mir::interpret::{GlobalId, Value, PrimVal};
|
||||
use util::common::ErrorReported;
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
@ -489,17 +489,29 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
|
||||
match tcx.lift_to_global(&substs) {
|
||||
Some(substs) => {
|
||||
match tcx.const_eval(param_env.and((def_id, substs))) {
|
||||
Ok(&ty::Const {
|
||||
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(b as u64 as u128, b);
|
||||
return Ok(b as u64);
|
||||
let instance = ty::Instance::resolve(
|
||||
tcx.global_tcx(),
|
||||
param_env,
|
||||
def_id,
|
||||
substs,
|
||||
);
|
||||
if let Some(instance) = instance {
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
match tcx.const_eval(param_env.and(cid)) {
|
||||
Ok(&ty::Const {
|
||||
val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(b as u64 as u128, b);
|
||||
return Ok(b as u64);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {}
|
||||
}
|
||||
tcx.sess.delay_span_bug(tcx.def_span(def_id),
|
||||
|
@ -57,6 +57,7 @@ CopyImpls! {
|
||||
::syntax::abi::Abi,
|
||||
::hir::def_id::DefId,
|
||||
::mir::Local,
|
||||
::mir::Promoted,
|
||||
::traits::Reveal,
|
||||
::syntax_pos::Span,
|
||||
}
|
||||
@ -589,7 +590,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
|
||||
type Lifted = interpret::EvalError<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
use mir::interpret::EvalErrorKind::*;
|
||||
use ::mir::interpret::EvalErrorKind::*;
|
||||
let kind = match self.kind {
|
||||
MachineError(ref err) => MachineError(err.clone()),
|
||||
FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
|
||||
@ -744,6 +745,42 @@ impl<'a, 'tcx> Lift<'tcx> for ty::layout::LayoutError<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
|
||||
type Lifted = ty::InstanceDef<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
match *self {
|
||||
ty::InstanceDef::Item(def_id) =>
|
||||
Some(ty::InstanceDef::Item(def_id)),
|
||||
ty::InstanceDef::Intrinsic(def_id) =>
|
||||
Some(ty::InstanceDef::Intrinsic(def_id)),
|
||||
ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
|
||||
Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?)),
|
||||
ty::InstanceDef::Virtual(def_id, n) =>
|
||||
Some(ty::InstanceDef::Virtual(def_id, n)),
|
||||
ty::InstanceDef::ClosureOnceShim { call_once } =>
|
||||
Some(ty::InstanceDef::ClosureOnceShim { call_once }),
|
||||
ty::InstanceDef::DropGlue(def_id, ref ty) =>
|
||||
Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?)),
|
||||
ty::InstanceDef::CloneShim(def_id, ref ty) =>
|
||||
Some(ty::InstanceDef::CloneShim(def_id, tcx.lift(ty)?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> {
|
||||
type Lifted = ty::Instance<'tcx>;
|
||||
def, substs
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for interpret::GlobalId<'a> {
|
||||
type Lifted = interpret::GlobalId<'tcx>;
|
||||
instance, promoted
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeFoldable implementations.
|
||||
//
|
||||
@ -945,6 +982,19 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
Self {
|
||||
instance: self.instance.fold_with(folder),
|
||||
promoted: self.promoted
|
||||
}
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.instance.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let sty = match self.sty {
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
use rustc::mir::interpret::{Value, PrimVal, GlobalId};
|
||||
use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
|
||||
use rustc::traits;
|
||||
use interpret::{eval_body_as_integer, check_body};
|
||||
@ -41,7 +41,11 @@ pub fn check<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
|
||||
let instance = Instance::mono(tcx, def_id);
|
||||
for i in 0.. mir.promoted.len() {
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
check_body(tcx, instance, Some(Promoted::new(i)), param_env);
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: Some(Promoted::new(i)),
|
||||
};
|
||||
check_body(tcx, cid, param_env);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +69,11 @@ impl<'a, 'tcx> ConstErrVisitor<'a, 'tcx> {
|
||||
},
|
||||
Literal::Promoted { index } => {
|
||||
let instance = Instance::mono(self.tcx, self.def_id);
|
||||
eval_body_as_integer(self.tcx, param_env, instance, Some(index)).unwrap()
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: Some(index),
|
||||
};
|
||||
eval_body_as_integer(self.tcx, cid, param_env).unwrap()
|
||||
}
|
||||
};
|
||||
Some(val)
|
||||
|
@ -12,7 +12,7 @@ use interpret::{const_val_field, const_discr};
|
||||
|
||||
use rustc::middle::const_val::{ConstEvalErr, ErrKind, ConstVal};
|
||||
use rustc::mir::{Field, BorrowKind, Mutability};
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
use rustc::mir::interpret::{GlobalId, Value, PrimVal};
|
||||
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
use rustc::hir::{self, PatKind, RangeEnd};
|
||||
@ -673,14 +673,18 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
|
||||
let kind = match def {
|
||||
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||
let substs = self.tables.node_substs(id);
|
||||
match self.tcx.at(span).const_eval(self.param_env.and((def_id, substs))) {
|
||||
let instance = ty::Instance::resolve(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
};
|
||||
match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
|
||||
Ok(value) => {
|
||||
let instance = ty::Instance::resolve(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
return self.const_to_pat(instance, value, id, span)
|
||||
},
|
||||
Err(e) => {
|
||||
|
@ -15,6 +15,7 @@ use hair::cx::block;
|
||||
use hair::cx::to_ref::ToRef;
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::mir::interpret::{GlobalId, Value, PrimVal};
|
||||
use rustc::ty::{self, AdtKind, VariantDef, Ty};
|
||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
@ -511,7 +512,17 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let c = &cx.tcx.hir.body(count).value;
|
||||
let def_id = cx.tcx.hir.body_owner_def_id(count);
|
||||
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
|
||||
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
|
||||
let instance = ty::Instance::resolve(
|
||||
cx.tcx.global_tcx(),
|
||||
cx.param_env,
|
||||
def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let global_id = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) {
|
||||
Ok(cv) => cv.val.unwrap_usize(cx.tcx),
|
||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||
};
|
||||
|
@ -1,11 +1,10 @@
|
||||
use rustc::ty::{self, TyCtxt, Ty, Instance};
|
||||
use rustc::ty::layout::{self, LayoutOf};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
use rustc::hir;
|
||||
use rustc::middle::const_val::ErrKind::{CheckMatchError, TypeckError};
|
||||
use rustc::middle::const_val::{ConstEvalErr, ConstVal};
|
||||
use const_eval::lookup_const_by_id;
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, TyCtxt, Ty, Instance};
|
||||
use rustc::ty::layout::{self, LayoutOf};
|
||||
use rustc::ty::subst::Subst;
|
||||
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::codemap::Span;
|
||||
@ -38,20 +37,18 @@ pub fn mk_eval_cx<'a, 'tcx>(
|
||||
|
||||
pub fn eval_body<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
cid: GlobalId<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
|
||||
eval_body_and_ecx(tcx, instance, promoted, param_env).0
|
||||
eval_body_and_ecx(tcx, cid, param_env).0
|
||||
}
|
||||
|
||||
pub fn check_body<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
cid: GlobalId<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) {
|
||||
let (res, ecx) = eval_body_and_ecx(tcx, instance, promoted, param_env);
|
||||
let (res, ecx) = eval_body_and_ecx(tcx, cid, param_env);
|
||||
if let Err(mut err) = res {
|
||||
ecx.report(&mut err);
|
||||
}
|
||||
@ -59,26 +56,22 @@ pub fn check_body<'a, 'tcx>(
|
||||
|
||||
fn eval_body_and_ecx<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
cid: GlobalId<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'tcx, CompileTimeEvaluator>) {
|
||||
debug!("eval_body: {:?}, {:?}", instance, param_env);
|
||||
debug!("eval_body: {:?}, {:?}", cid, param_env);
|
||||
let limits = super::ResourceLimits::default();
|
||||
let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
|
||||
let cid = GlobalId {
|
||||
instance,
|
||||
promoted,
|
||||
};
|
||||
|
||||
let res = (|| {
|
||||
if ecx.tcx.has_attr(instance.def_id(), "linkage") {
|
||||
let mut mir = ecx.load_mir(cid.instance.def)?;
|
||||
if let Some(index) = cid.promoted {
|
||||
mir = &mir.promoted[index];
|
||||
}
|
||||
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
|
||||
if ecx.tcx.has_attr(cid.instance.def_id(), "linkage") {
|
||||
return Err(ConstEvalError::NotConst("extern global".to_string()).into());
|
||||
}
|
||||
let instance_ty = instance.ty(tcx);
|
||||
if tcx.interpret_interner.borrow().get_cached(cid).is_none() {
|
||||
let mir = ecx.load_mir(instance.def)?;
|
||||
let layout = ecx.layout_of(instance_ty)?;
|
||||
assert!(!layout.is_unsized());
|
||||
let ptr = ecx.memory.allocate(
|
||||
layout.size.bytes(),
|
||||
@ -87,10 +80,10 @@ fn eval_body_and_ecx<'a, 'tcx>(
|
||||
)?;
|
||||
tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
|
||||
let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
|
||||
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
|
||||
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
|
||||
trace!("const_eval: pushing stack frame for global: {}", name);
|
||||
ecx.push_stack_frame(
|
||||
instance,
|
||||
cid.instance,
|
||||
mir.span,
|
||||
mir,
|
||||
Place::from_ptr(ptr, layout.align),
|
||||
@ -100,24 +93,22 @@ fn eval_body_and_ecx<'a, 'tcx>(
|
||||
while ecx.step()? {}
|
||||
}
|
||||
let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
|
||||
let align = ecx.layout_of(instance_ty)?.align;
|
||||
let ptr = MemoryPointer::new(alloc, 0).into();
|
||||
let value = match ecx.try_read_value(ptr, align, instance_ty)? {
|
||||
let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
|
||||
Some(val) => val,
|
||||
_ => Value::ByRef(ptr, align),
|
||||
_ => Value::ByRef(ptr, layout.align),
|
||||
};
|
||||
Ok((value, ptr, instance_ty))
|
||||
Ok((value, ptr, layout.ty))
|
||||
})();
|
||||
(res, ecx)
|
||||
}
|
||||
|
||||
pub fn eval_body_as_integer<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cid: GlobalId<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
promoted: Option<mir::Promoted>,
|
||||
) -> EvalResult<'tcx, u128> {
|
||||
let (value, _, ty) = eval_body(tcx, instance, promoted, param_env)?;
|
||||
let (value, _, ty) = eval_body(tcx, cid, param_env)?;
|
||||
match value {
|
||||
Value::ByVal(prim) => prim.to_bytes(),
|
||||
_ => err!(TypeNotPrimitive(ty)),
|
||||
@ -325,7 +316,7 @@ fn const_val_field_inner<'a, 'tcx>(
|
||||
field: mir::Field,
|
||||
value: Value,
|
||||
ty: Ty<'tcx>,
|
||||
) -> ::rustc::mir::interpret::EvalResult<'tcx, (Value, Ty<'tcx>)> {
|
||||
) -> EvalResult<'tcx, (Value, Ty<'tcx>)> {
|
||||
trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
|
||||
let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
|
||||
let (mut field, ty) = match value {
|
||||
@ -376,51 +367,47 @@ pub fn const_discr<'a, 'tcx>(
|
||||
|
||||
pub fn const_eval_provider<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>,
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc::middle::const_val::EvalResult<'tcx> {
|
||||
trace!("const eval: {:?}", key);
|
||||
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, key) {
|
||||
resolved
|
||||
} else {
|
||||
return Err(ConstEvalErr {
|
||||
span: tcx.def_span(key.value.0),
|
||||
kind: TypeckError
|
||||
});
|
||||
};
|
||||
let cid = key.value;
|
||||
let def_id = cid.instance.def.def_id();
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
let tables = tcx.typeck_tables_of(def_id);
|
||||
let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
let body_id = tcx.hir.body_owned_by(id);
|
||||
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
let tables = tcx.typeck_tables_of(def_id);
|
||||
|
||||
// Do match-check before building MIR
|
||||
if tcx.check_match(def_id).is_err() {
|
||||
return Err(ConstEvalErr {
|
||||
span: tcx.def_span(key.value.0),
|
||||
span,
|
||||
kind: CheckMatchError,
|
||||
});
|
||||
}
|
||||
|
||||
tcx.mir_const_qualif(def_id);
|
||||
tcx.hir.body(body_id)
|
||||
} else {
|
||||
tcx.extern_const_body(def_id).body
|
||||
if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
|
||||
tcx.mir_const_qualif(def_id);
|
||||
}
|
||||
|
||||
// Do not continue into miri if typeck errors occurred; it will fail horribly
|
||||
if tables.tainted_by_errors {
|
||||
return Err(ConstEvalErr {
|
||||
span,
|
||||
kind: TypeckError
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// do not continue into miri if typeck errors occurred
|
||||
// it will fail horribly
|
||||
if tables.tainted_by_errors {
|
||||
return Err(ConstEvalErr { span: body.value.span, kind: TypeckError })
|
||||
}
|
||||
|
||||
|
||||
let instance = ty::Instance::new(def_id, substs);
|
||||
match ::interpret::eval_body(tcx, instance, None, key.param_env) {
|
||||
match ::interpret::eval_body(tcx, cid, key.param_env) {
|
||||
Ok((miri_value, _, miri_ty)) => Ok(tcx.mk_const(ty::Const {
|
||||
val: ConstVal::Value(miri_value),
|
||||
ty: miri_ty,
|
||||
})),
|
||||
Err(err) => {
|
||||
Err(ConstEvalErr { span: body.value.span, kind: err.into() })
|
||||
Err(ConstEvalErr {
|
||||
span,
|
||||
kind: err.into()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
|
||||
use rustc::infer::anon_types::AnonTypeDecl;
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin};
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::{GlobalId};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
|
||||
use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
|
||||
@ -3999,7 +4000,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let count_def_id = tcx.hir.body_owner_def_id(count);
|
||||
let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing);
|
||||
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
|
||||
let count = tcx.const_eval(param_env.and((count_def_id, substs)));
|
||||
let instance = ty::Instance::resolve(
|
||||
tcx.global_tcx(),
|
||||
param_env,
|
||||
count_def_id,
|
||||
substs,
|
||||
).unwrap();
|
||||
let global_id = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
let count = tcx.const_eval(param_env.and(global_id));
|
||||
|
||||
if let Err(ref err) = count {
|
||||
err.report(tcx, tcx.def_span(count_def_id), "constant expression");
|
||||
|
@ -38,7 +38,7 @@ use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
use rustc::mir::interpret::{GlobalId, Value, PrimVal};
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
@ -524,7 +524,12 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
|
||||
let expr_did = tcx.hir.local_def_id(e.node_id);
|
||||
let substs = Substs::identity_for_item(tcx, expr_did);
|
||||
let result = tcx.at(variant.span).const_eval(param_env.and((expr_did, substs)));
|
||||
let instance = ty::Instance::new(expr_did, substs);
|
||||
let global_id = GlobalId {
|
||||
instance,
|
||||
promoted: None
|
||||
};
|
||||
let result = tcx.at(variant.span).const_eval(param_env.and(global_id));
|
||||
|
||||
// enum variant evaluation happens before the global constant check
|
||||
// so we need to report the real error
|
||||
|
Loading…
Reference in New Issue
Block a user