Add simpler entry points to const eval for common usages.

This commit is contained in:
Ben Lewis 2019-11-30 08:42:56 +13:00
parent 6b561b4917
commit c010d843aa
23 changed files with 195 additions and 253 deletions

View File

@ -101,6 +101,7 @@ mod error;
mod value; mod value;
mod allocation; mod allocation;
mod pointer; mod pointer;
mod queries;
pub use self::error::{ pub use self::error::{
InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error, InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
@ -116,9 +117,10 @@ pub use self::pointer::{Pointer, PointerArithmetic, CheckInAllocMsg};
use crate::mir; use crate::mir;
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use crate::ty::{self, TyCtxt, Instance, subst::GenericArgKind}; use crate::ty::{self, TyCtxt, Instance};
use crate::ty::codec::TyDecoder; use crate::ty::codec::TyDecoder;
use crate::ty::layout::{self, Size}; use crate::ty::layout::{self, Size};
use crate::ty::subst::GenericArgKind;
use std::io; use std::io;
use std::fmt; use std::fmt;
use std::num::NonZeroU32; use std::num::NonZeroU32;

View File

@ -0,0 +1,89 @@
use super::{ConstEvalResult, ErrorHandled, GlobalId};
use crate::mir;
use crate::hir::def_id::DefId;
use crate::ty::{self, TyCtxt};
use crate::ty::subst::{InternalSubsts, SubstsRef};
use syntax_pos::Span;
impl<'tcx> TyCtxt<'tcx> {
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> {
// In some situations def_id will have substitutions within scope, but they aren't allowed
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any og them are
// encountered.
let substs = InternalSubsts::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, substs);
let cid = GlobalId {
instance,
promoted: None,
};
let param_env = self.param_env(def_id);
self.const_eval_validated(param_env.and(cid))
}
/// Resolves and evaluates a constant.
///
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
/// substitutions and environment are used to resolve the constant. Alternatively if the
/// constant has generic parameters in scope the substitutions are used to evaluate the value of
/// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
/// returned.
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
span: Option<Span>
) -> ConstEvalResult<'tcx> {
let instance = ty::Instance::resolve(
self,
param_env,
def_id,
substs,
);
if let Some(instance) = instance {
self.const_eval_instance(param_env, instance, span)
} else {
Err(ErrorHandled::TooGeneric)
}
}
pub fn const_eval_instance(
self,
param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>,
span: Option<Span>
) -> ConstEvalResult<'tcx> {
let cid = GlobalId {
instance,
promoted: None,
};
if let Some(span) = span {
self.at(span).const_eval_validated(param_env.and(cid))
} else {
self.const_eval_validated(param_env.and(cid))
}
}
/// Evaluate a promoted constant.
pub fn const_eval_promoted(
self,
instance: ty::Instance<'tcx>,
promoted: mir::Promoted
) -> ConstEvalResult<'tcx> {
let cid = GlobalId {
instance,
promoted: Some(promoted),
};
let param_env = ty::ParamEnv::reveal_all();
self.const_eval_validated(param_env.and(cid))
}
}

View File

@ -448,7 +448,8 @@ rustc_queries! {
/// ///
/// **Do not use this** outside const eval. Const eval uses this to break query cycles /// **Do not use this** outside const eval. Const eval uses this to break query cycles
/// during validation. Please add a comment to every use site explaining why using /// during validation. Please add a comment to every use site explaining why using
/// `const_eval` isn't sufficient. /// `const_eval_validated` isn't sufficient. The returned constant also isn't in a suitable
/// form to be used outside of const eval.
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> ConstEvalRawResult<'tcx> { -> ConstEvalRawResult<'tcx> {
no_force no_force
@ -460,7 +461,13 @@ rustc_queries! {
/// Results of evaluating const items or constants embedded in /// Results of evaluating const items or constants embedded in
/// other items (such as enum variant explicit discriminants). /// other items (such as enum variant explicit discriminants).
query const_eval(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) ///
/// In contrast to `const_eval_raw` this performs some validation on the constant, and
/// returns a proper constant that is usable by the rest of the compiler.
///
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_promoted`.
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-> ConstEvalResult<'tcx> { -> ConstEvalResult<'tcx> {
no_force no_force
desc { |tcx| desc { |tcx|

View File

@ -1,5 +1,4 @@
use crate::infer::{InferCtxt, ShallowResolver}; use crate::infer::{InferCtxt, ShallowResolver};
use crate::mir::interpret::{GlobalId, ErrorHandled};
use crate::ty::{self, Ty, TypeFoldable, ToPolyTraitRef}; use crate::ty::{self, Ty, TypeFoldable, ToPolyTraitRef};
use crate::ty::error::ExpectedFound; use crate::ty::error::ExpectedFound;
use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation};
@ -501,27 +500,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
ProcessResult::Unchanged ProcessResult::Unchanged
} else { } else {
if !substs.has_local_value() { if !substs.has_local_value() {
let instance = ty::Instance::resolve( match self.selcx.tcx().const_eval_resolve(obligation.param_env,
self.selcx.tcx(), def_id,
obligation.param_env, substs,
def_id, Some(obligation.cause.span)) {
substs, Ok(_) => ProcessResult::Changed(vec![]),
); Err(err) => ProcessResult::Error(
if let Some(instance) = instance { CodeSelectionError(ConstEvalFailure(err)))
let cid = GlobalId {
instance,
promoted: None,
};
match self.selcx.tcx().at(obligation.cause.span)
.const_eval(obligation.param_env.and(cid)) {
Ok(_) => ProcessResult::Changed(vec![]),
Err(err) => ProcessResult::Error(
CodeSelectionError(ConstEvalFailure(err)))
}
} else {
ProcessResult::Error(CodeSelectionError(
ConstEvalFailure(ErrorHandled::TooGeneric)
))
} }
} else { } else {
pending_obligation.stalled_on = pending_obligation.stalled_on =

View File

@ -33,7 +33,6 @@ use crate::dep_graph::{DepKind, DepNodeIndex};
use crate::hir::def_id::DefId; use crate::hir::def_id::DefId;
use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
use crate::middle::lang_items; use crate::middle::lang_items;
use crate::mir::interpret::GlobalId;
use crate::ty::fast_reject; use crate::ty::fast_reject;
use crate::ty::relate::TypeRelation; use crate::ty::relate::TypeRelation;
use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::subst::{Subst, SubstsRef};
@ -820,22 +819,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
ty::Predicate::ConstEvaluatable(def_id, substs) => { ty::Predicate::ConstEvaluatable(def_id, substs) => {
let tcx = self.tcx();
if !(obligation.param_env, substs).has_local_value() { if !(obligation.param_env, substs).has_local_value() {
let param_env = obligation.param_env; match self.tcx().const_eval_resolve(obligation.param_env,
let instance = def_id,
ty::Instance::resolve(tcx, param_env, def_id, substs); substs,
if let Some(instance) = instance { None) {
let cid = GlobalId { Ok(_) => Ok(EvaluatedToOk),
instance, Err(_) => Ok(EvaluatedToErr),
promoted: None,
};
match self.tcx().const_eval(param_env.and(cid)) {
Ok(_) => Ok(EvaluatedToOk),
Err(_) => Ok(EvaluatedToErr),
}
} else {
Ok(EvaluatedToErr)
} }
} else { } else {
// Inference variables still left in param_env or substs. // Inference variables still left in param_env or substs.

View File

@ -19,7 +19,7 @@ use crate::middle::cstore::CrateStoreDyn;
use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
use crate::mir::ReadOnlyBodyAndCache; use crate::mir::ReadOnlyBodyAndCache;
use crate::mir::interpret::{GlobalId, ErrorHandled}; use crate::mir::interpret::ErrorHandled;
use crate::mir::GeneratorLayout; use crate::mir::GeneratorLayout;
use crate::session::CrateDisambiguator; use crate::session::CrateDisambiguator;
use crate::traits::{self, Reveal}; use crate::traits::{self, Reveal};
@ -2344,13 +2344,7 @@ impl<'tcx> AdtDef {
pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> { pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
let param_env = tcx.param_env(expr_did); let param_env = tcx.param_env(expr_did);
let repr_type = self.repr.discr_type(); let repr_type = self.repr.discr_type();
let substs = InternalSubsts::identity_for_item(tcx, expr_did); match tcx.const_eval_poly(expr_did) {
let instance = ty::Instance::new(expr_did, substs);
let cid = GlobalId {
instance,
promoted: None
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => { Ok(val) => {
// FIXME: Find the right type and use it instead of `val.ty` here // FIXME: Find the right type and use it instead of `val.ty` here
if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) { if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {

View File

@ -15,7 +15,7 @@ use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFolda
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
use crate::ty::layout::VariantIdx; use crate::ty::layout::VariantIdx;
use crate::util::captures::Captures; use crate::util::captures::Captures;
use crate::mir::interpret::{Scalar, GlobalId}; use crate::mir::interpret::Scalar;
use polonius_engine::Atom; use polonius_engine::Atom;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
@ -2340,13 +2340,9 @@ impl<'tcx> Const<'tcx> {
let (param_env, substs) = param_env_and_substs.into_parts(); let (param_env, substs) = param_env_and_substs.into_parts();
// try to resolve e.g. associated constants to their definition on an impl // try to resolve e.g. associated constants to their definition on an impl, and then
let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; // evaluate the const.
let gid = GlobalId { tcx.const_eval_resolve(param_env, did, substs, None).ok()
instance,
promoted: None,
};
tcx.const_eval(param_env.and(gid)).ok()
}; };
match self.val { match self.val {

View File

@ -8,7 +8,7 @@ use crate::value::Value;
use libc::c_uint; use libc::c_uint;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint, use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint,
Pointer, ErrorHandled, GlobalId}; Pointer, ErrorHandled};
use rustc::mir::mono::MonoItem; use rustc::mir::mono::MonoItem;
use rustc::hir::Node; use rustc::hir::Node;
use rustc_target::abi::HasDataLayout; use rustc_target::abi::HasDataLayout;
@ -81,13 +81,7 @@ pub fn codegen_static_initializer(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
def_id: DefId, def_id: DefId,
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
let instance = ty::Instance::mono(cx.tcx, def_id); let static_ = cx.tcx.const_eval_poly(def_id)?;
let cid = GlobalId {
instance,
promoted: None,
};
let param_env = ty::ParamEnv::reveal_all();
let static_ = cx.tcx.const_eval(param_env.and(cid))?;
let alloc = match static_.val { let alloc = match static_.val {
ty::ConstKind::Value(ConstValue::ByRef { ty::ConstKind::Value(ConstValue::ByRef {

View File

@ -14,7 +14,6 @@ use rustc_codegen_ssa::glue;
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive}; use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive};
use rustc::mir::interpret::GlobalId;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc::hir; use rustc::hir;
use rustc_target::abi::HasDataLayout; use rustc_target::abi::HasDataLayout;
@ -202,11 +201,9 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
"needs_drop" | "needs_drop" |
"type_id" | "type_id" |
"type_name" => { "type_name" => {
let gid = GlobalId { let ty_name = self.tcx
instance, .const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
promoted: None, .unwrap();
};
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self) OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
} }
"init" => { "init" => {

View File

@ -638,12 +638,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
projection: &[], projection: &[],
} = place.as_ref() } = place.as_ref()
{ {
let param_env = ty::ParamEnv::reveal_all(); let c = bx.tcx().const_eval_promoted(self.instance, promoted);
let cid = mir::interpret::GlobalId {
instance: self.instance,
promoted: Some(promoted),
};
let c = bx.tcx().const_eval(param_env.and(cid));
let (llval, ty) = self.simd_shuffle_indices( let (llval, ty) = self.simd_shuffle_indices(
&bx, &bx,
terminator.source_info.span, terminator.source_info.span,

View File

@ -43,17 +43,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
match constant.literal.val { match constant.literal.val {
ty::ConstKind::Unevaluated(def_id, substs) => { ty::ConstKind::Unevaluated(def_id, substs) => {
let substs = self.monomorphize(&substs); let substs = self.monomorphize(&substs);
let instance = ty::Instance::resolve( self.cx.tcx()
self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs, .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None)
).unwrap(); .map_err(|err| {
let cid = mir::interpret::GlobalId { self.cx.tcx().sess.span_err(
instance, constant.span,
promoted: None, "erroneous constant encountered");
}; err
self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)).map_err(|err| { })
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
err
})
}, },
_ => Ok(self.monomorphize(&constant.literal)), _ => Ok(self.monomorphize(&constant.literal)),
} }

View File

@ -473,14 +473,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}), }),
projection: [], projection: [],
} => { } => {
let param_env = ty::ParamEnv::reveal_all();
let instance = Instance::new(*def_id, self.monomorphize(substs)); let instance = Instance::new(*def_id, self.monomorphize(substs));
let cid = mir::interpret::GlobalId {
instance: instance,
promoted: Some(*promoted),
};
let layout = cx.layout_of(self.monomorphize(&ty)); let layout = cx.layout_of(self.monomorphize(&ty));
match bx.tcx().const_eval(param_env.and(cid)) { match bx.tcx().const_eval_promoted(instance, *promoted) {
Ok(val) => match val.val { Ok(val) => match val.val {
ty::ConstKind::Value(mir::interpret::ConstValue::ByRef { ty::ConstKind::Value(mir::interpret::ConstValue::ByRef {
alloc, offset alloc, offset

View File

@ -1134,19 +1134,9 @@ declare_lint_pass!(
fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) { fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
let def_id = cx.tcx.hir().body_owner_def_id(body_id); let def_id = cx.tcx.hir().body_owner_def_id(body_id);
let param_env = if cx.tcx.is_static(def_id) {
// Use the same param_env as `codegen_static_initializer`, to reuse the cache.
ty::ParamEnv::reveal_all()
} else {
cx.tcx.param_env(def_id)
};
let cid = ::rustc::mir::interpret::GlobalId {
instance: ty::Instance::mono(cx.tcx, def_id),
promoted: None
};
// trigger the query once for all constants since that will already report the errors // trigger the query once for all constants since that will already report the errors
// FIXME: Use ensure here // FIXME: Use ensure here
let _ = cx.tcx.const_eval(param_env.and(cid)); let _ = cx.tcx.const_eval_poly(def_id);
} }
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {

View File

@ -652,7 +652,7 @@ fn validate_and_turn_into_const<'tcx>(
}) })
} }
pub fn const_eval_provider<'tcx>( pub fn const_eval_validated_provider<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
@ -660,7 +660,7 @@ pub fn const_eval_provider<'tcx>(
if key.param_env.reveal == Reveal::All { if key.param_env.reveal == Reveal::All {
let mut key = key.clone(); let mut key = key.clone();
key.param_env.reveal = Reveal::UserFacing; key.param_env.reveal = Reveal::UserFacing;
match tcx.const_eval(key) { match tcx.const_eval_validated(key) {
// try again with reveal all as requested // try again with reveal all as requested
Err(ErrorHandled::TooGeneric) => { Err(ErrorHandled::TooGeneric) => {
// Promoteds should never be "too generic" when getting evaluated. // Promoteds should never be "too generic" when getting evaluated.

View File

@ -5,7 +5,7 @@ use crate::hair::cx::to_ref::ToRef;
use crate::hair::util::UserAnnotatedTyHelpers; use crate::hair::util::UserAnnotatedTyHelpers;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind}; use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
use rustc::mir::interpret::{GlobalId, ErrorHandled, Scalar}; use rustc::mir::interpret::{ErrorHandled, Scalar};
use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::subst::{InternalSubsts, SubstsRef};
@ -514,21 +514,15 @@ fn make_mirror_unadjusted<'a, 'tcx>(
hir::ExprKind::Repeat(ref v, ref count) => { hir::ExprKind::Repeat(ref v, ref count) => {
let def_id = cx.tcx.hir().local_def_id(count.hir_id); let def_id = cx.tcx.hir().local_def_id(count.hir_id);
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id); let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
let instance = ty::Instance::resolve(
cx.tcx,
cx.param_env,
def_id,
substs,
).unwrap();
let global_id = GlobalId {
instance,
promoted: None
};
let span = cx.tcx.def_span(def_id); let span = cx.tcx.def_span(def_id);
let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) { let count = match cx.tcx.const_eval_resolve(cx.param_env,
def_id,
substs,
Some(span)) {
Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env), Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env),
Err(ErrorHandled::Reported) => 0, Err(ErrorHandled::Reported) => 0,
Err(ErrorHandled::TooGeneric) => { Err(ErrorHandled::TooGeneric) => {
let span = cx.tcx.def_span(def_id);
cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters"); cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");
0 0
}, },

View File

@ -11,7 +11,7 @@ use crate::hair::constant::*;
use rustc::mir::{Field, BorrowKind, Mutability}; use rustc::mir::{Field, BorrowKind, Mutability};
use rustc::mir::{UserTypeProjection}; use rustc::mir::{UserTypeProjection};
use rustc::mir::interpret::{GlobalId, ConstValue, get_slice_bytes, sign_extend}; use rustc::mir::interpret::{ConstValue, ErrorHandled, get_slice_bytes, sign_extend};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
use rustc::ty::subst::{SubstsRef, GenericArg}; use rustc::ty::subst::{SubstsRef, GenericArg};
@ -854,57 +854,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let kind = match res { let kind = match res {
Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
let substs = self.tables.node_substs(id); let substs = self.tables.node_substs(id);
match ty::Instance::resolve( match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) {
self.tcx, Ok(value) => {
self.param_env, let pattern = self.const_to_pat(value, id, span);
def_id, if !is_associated_const {
substs, return pattern;
) { }
Some(instance) => {
let cid = GlobalId {
instance,
promoted: None,
};
match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
Ok(value) => {
let pattern = self.const_to_pat(value, id, span);
if !is_associated_const {
return pattern;
}
let user_provided_types = self.tables().user_provided_types(); let user_provided_types = self.tables().user_provided_types();
return if let Some(u_ty) = user_provided_types.get(id) { return if let Some(u_ty) = user_provided_types.get(id) {
let user_ty = PatTyProj::from_user_type(*u_ty); let user_ty = PatTyProj::from_user_type(*u_ty);
Pat { Pat {
span, span,
kind: Box::new( kind: Box::new(
PatKind::AscribeUserType { PatKind::AscribeUserType {
subpattern: pattern, subpattern: pattern,
ascription: Ascription { ascription: Ascription {
/// Note that use `Contravariant` here. See the /// Note that use `Contravariant` here. See the
/// `variance` field documentation for details. /// `variance` field documentation for details.
variance: ty::Variance::Contravariant, variance: ty::Variance::Contravariant,
user_ty, user_ty,
user_ty_span: span, user_ty_span: span,
}, },
}
),
ty: value.ty,
} }
} else { ),
pattern ty: value.ty,
}
},
Err(_) => {
self.tcx.sess.span_err(
span,
"could not evaluate constant pattern",
);
PatKind::Wild
} }
} else {
pattern
} }
}, },
None => { Err(ErrorHandled::TooGeneric) => {
self.errors.push(if is_associated_const { self.errors.push(if is_associated_const {
PatternError::AssocConstInPattern(span) PatternError::AssocConstInPattern(span)
} else { } else {
@ -912,6 +892,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}); });
PatKind::Wild PatKind::Wild
}, },
Err(_) => {
self.tcx.sess.span_err(
span,
"could not evaluate constant pattern",
);
PatKind::Wild
}
} }
} }
_ => self.lower_variant_or_leaf(res, id, span, ty, vec![]), _ => self.lower_variant_or_leaf(res, id, span, ty, vec![]),

View File

@ -11,7 +11,7 @@ use rustc::hir::def_id::DefId;
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc::mir::{ use rustc::mir::{
self, BinOp, self, BinOp,
interpret::{InterpResult, Scalar, GlobalId, ConstValue} interpret::{InterpResult, Scalar, ConstValue}
}; };
use super::{ use super::{
@ -123,11 +123,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::size_of | sym::size_of |
sym::type_id | sym::type_id |
sym::type_name => { sym::type_name => {
let gid = GlobalId { let val = self.tcx.const_eval_instance(self.param_env,
instance, instance,
promoted: None, Some(self.tcx.span))?;
};
let val = self.tcx.const_eval(self.param_env.and(gid))?;
let val = self.eval_const_to_op(val, None)?; let val = self.eval_const_to_op(val, None)?;
self.copy_op(val, dest)?; self.copy_op(val, dest)?;
} }

View File

@ -619,11 +619,6 @@ where
let ty = place_static.ty; let ty = place_static.ty;
assert!(!ty.needs_subst()); assert!(!ty.needs_subst());
let layout = self.layout_of(ty)?; let layout = self.layout_of(ty)?;
let instance = ty::Instance::mono(*self.tcx, place_static.def_id);
let cid = GlobalId {
instance,
promoted: None
};
// Just create a lazy reference, so we can support recursive statics. // Just create a lazy reference, so we can support recursive statics.
// tcx takes care of assigning every static one and only one unique AllocId. // tcx takes care of assigning every static one and only one unique AllocId.
// When the data here is ever actually used, memory will notice, // When the data here is ever actually used, memory will notice,
@ -639,7 +634,7 @@ where
// Notice that statics have *two* AllocIds: the lazy one, and the resolved // Notice that statics have *two* AllocIds: the lazy one, and the resolved
// one. Here we make sure that the interpreted program never sees the // one. Here we make sure that the interpreted program never sees the
// resolved ID. Also see the doc comment of `Memory::get_static_alloc`. // resolved ID. Also see the doc comment of `Memory::get_static_alloc`.
let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(cid.instance.def_id()); let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(place_static.def_id);
let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id)); let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id));
MPlaceTy::from_aligned_ptr(ptr, layout) MPlaceTy::from_aligned_ptr(ptr, layout)
} }

View File

@ -56,7 +56,7 @@ pub fn provide(providers: &mut Providers<'_>) {
shim::provide(providers); shim::provide(providers);
transform::provide(providers); transform::provide(providers);
monomorphize::partitioning::provide(providers); monomorphize::partitioning::provide(providers);
providers.const_eval = const_eval::const_eval_provider; providers.const_eval_validated = const_eval::const_eval_validated_provider;
providers.const_eval_raw = const_eval::const_eval_raw_provider; providers.const_eval_raw = const_eval::const_eval_raw_provider;
providers.check_match = hair::pattern::check_match; providers.check_match = hair::pattern::check_match;
providers.const_caller_location = const_eval::const_caller_location; providers.const_caller_location = const_eval::const_caller_location;

View File

@ -189,7 +189,7 @@ use rustc::session::config::EntryFnType;
use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::{self, Location, PlaceBase, Static, StaticKind};
use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::visit::Visitor as MirVisitor;
use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::mono::{MonoItem, InstantiationMode};
use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; use rustc::mir::interpret::{Scalar, GlobalAlloc, ErrorHandled};
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap}; use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
use rustc::util::common::time; use rustc::util::common::time;
@ -379,13 +379,7 @@ fn collect_items_rec<'tcx>(
recursion_depth_reset = None; recursion_depth_reset = None;
let cid = GlobalId { if let Ok(val) = tcx.const_eval_poly(def_id) {
instance,
promoted: None,
};
let param_env = ty::ParamEnv::reveal_all();
if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors); collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
} }
} }
@ -681,12 +675,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
def_id, def_id,
.. ..
}) => { }) => {
let param_env = ty::ParamEnv::reveal_all(); let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs));
let cid = GlobalId { match self.tcx.const_eval_promoted(instance, *promoted) {
instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)),
promoted: Some(*promoted),
};
match self.tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(self.tcx, val, substs, self.output), Ok(val) => collect_const(self.tcx, val, substs, self.output),
Err(ErrorHandled::Reported) => {}, Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => { Err(ErrorHandled::TooGeneric) => {
@ -1041,14 +1031,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
// but even just declaring them must collect the items they refer to // but even just declaring them must collect the items they refer to
let def_id = self.tcx.hir().local_def_id(item.hir_id); let def_id = self.tcx.hir().local_def_id(item.hir_id);
let instance = Instance::mono(self.tcx, def_id); if let Ok(val) = self.tcx.const_eval_poly(def_id) {
let cid = GlobalId {
instance,
promoted: None,
};
let param_env = ty::ParamEnv::reveal_all();
if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output); collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
} }
} }
@ -1288,16 +1271,7 @@ fn collect_const<'tcx>(
} }
} }
ty::ConstKind::Unevaluated(def_id, substs) => { ty::ConstKind::Unevaluated(def_id, substs) => {
let instance = ty::Instance::resolve(tcx, match tcx.const_eval_resolve(param_env, def_id, substs, None) {
param_env,
def_id,
substs).unwrap();
let cid = GlobalId {
instance,
promoted: None,
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, param_substs, output), Ok(val) => collect_const(tcx, val, param_substs, output),
Err(ErrorHandled::Reported) => {}, Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!( Err(ErrorHandled::TooGeneric) => span_bug!(

View File

@ -31,7 +31,6 @@ use rustc::hir::ptr::P;
use rustc::infer; use rustc::infer;
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::middle::lang_items; use rustc::middle::lang_items;
use rustc::mir::interpret::GlobalId;
use rustc::ty; use rustc::ty;
use rustc::ty::adjustment::{ use rustc::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
@ -39,7 +38,6 @@ use rustc::ty::adjustment::{
use rustc::ty::{AdtKind, Visibility}; use rustc::ty::{AdtKind, Visibility};
use rustc::ty::Ty; use rustc::ty::Ty;
use rustc::ty::TypeFoldable; use rustc::ty::TypeFoldable;
use rustc::ty::subst::InternalSubsts;
use rustc::traits::{self, ObligationCauseCode}; use rustc::traits::{self, ObligationCauseCode};
use rustc_error_codes::*; use rustc_error_codes::*;
@ -1023,20 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let count = if self.const_param_def_id(count).is_some() { let count = if self.const_param_def_id(count).is_some() {
Ok(self.to_const(count, tcx.type_of(count_def_id))) Ok(self.to_const(count, tcx.type_of(count_def_id)))
} else { } else {
let param_env = ty::ParamEnv::empty(); tcx.const_eval_poly(count_def_id)
let substs = InternalSubsts::identity_for_item(tcx, count_def_id);
let instance = ty::Instance::resolve(
tcx,
param_env,
count_def_id,
substs,
).unwrap();
let global_id = GlobalId {
instance,
promoted: None
};
tcx.const_eval(param_env.and(global_id))
}; };
let uty = match expected { let uty = match expected {

View File

@ -106,7 +106,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc::middle::region; use rustc::middle::region;
use rustc::mir::interpret::{ConstValue, GlobalId}; use rustc::mir::interpret::ConstValue;
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{ use rustc::ty::{
self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind, self, AdtKind, CanonicalUserType, Ty, TyCtxt, Const, GenericParamDefKind,
@ -1836,13 +1836,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
// the consumer's responsibility to ensure all bytes that have been read // the consumer's responsibility to ensure all bytes that have been read
// have defined values. // have defined values.
let instance = ty::Instance::mono(tcx, id); if let Ok(static_) = tcx.const_eval_poly(id) {
let cid = GlobalId {
instance,
promoted: None
};
let param_env = ty::ParamEnv::reveal_all();
if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val { let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val {
alloc alloc
} else { } else {

View File

@ -15,7 +15,6 @@ use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
use rustc::middle::resolve_lifetime as rl; use rustc::middle::resolve_lifetime as rl;
use rustc::middle::lang_items; use rustc::middle::lang_items;
use rustc::middle::stability; use rustc::middle::stability;
use rustc::mir::interpret::GlobalId;
use rustc::hir; use rustc::hir;
use rustc::hir::def::{CtorKind, DefKind, Res}; use rustc::hir::def::{CtorKind, DefKind, Res};
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
@ -1334,13 +1333,7 @@ impl Clean<Type> for hir::Ty {
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => { TyKind::Array(ref ty, ref length) => {
let def_id = cx.tcx.hir().local_def_id(length.hir_id); let def_id = cx.tcx.hir().local_def_id(length.hir_id);
let param_env = cx.tcx.param_env(def_id); let length = match cx.tcx.const_eval_poly(def_id) {
let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
promoted: None
};
let length = match cx.tcx.const_eval(param_env.and(cid)) {
Ok(length) => print_const(cx, length), Ok(length) => print_const(cx, length),
Err(_) => cx.sess() Err(_) => cx.sess()
.source_map() .source_map()
@ -1534,16 +1527,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
ty::Slice(ty) => Slice(box ty.clean(cx)), ty::Slice(ty) => Slice(box ty.clean(cx)),
ty::Array(ty, n) => { ty::Array(ty, n) => {
let mut n = cx.tcx.lift(&n).expect("array lift failed"); let mut n = cx.tcx.lift(&n).expect("array lift failed");
if let ty::ConstKind::Unevaluated(def_id, substs) = n.val { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
let param_env = cx.tcx.param_env(def_id);
let cid = GlobalId {
instance: ty::Instance::new(def_id, substs),
promoted: None
};
if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
n = new_n;
}
};
let n = print_const(cx, n); let n = print_const(cx, n);
Array(box ty.clean(cx), n) Array(box ty.clean(cx), n)
} }