From c010d843aacc32ed2bc03d36121aa7f6e08ef045 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 30 Nov 2019 08:42:56 +1300 Subject: [PATCH] Add simpler entry points to const eval for common usages. --- src/librustc/mir/interpret/mod.rs | 4 +- src/librustc/mir/interpret/queries.rs | 89 ++++++++++++++++++++++ src/librustc/query/mod.rs | 11 ++- src/librustc/traits/fulfill.rs | 29 ++----- src/librustc/traits/select.rs | 22 ++---- src/librustc/ty/mod.rs | 10 +-- src/librustc/ty/sty.rs | 12 +-- src/librustc_codegen_llvm/consts.rs | 10 +-- src/librustc_codegen_llvm/intrinsic.rs | 9 +-- src/librustc_codegen_ssa/mir/block.rs | 7 +- src/librustc_codegen_ssa/mir/constant.rs | 19 ++--- src/librustc_codegen_ssa/mir/place.rs | 7 +- src/librustc_lint/builtin.rs | 12 +-- src/librustc_mir/const_eval.rs | 4 +- src/librustc_mir/hair/cx/expr.rs | 18 ++--- src/librustc_mir/hair/pattern/mod.rs | 81 +++++++++----------- src/librustc_mir/interpret/intrinsics.rs | 10 +-- src/librustc_mir/interpret/place.rs | 7 +- src/librustc_mir/lib.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 38 ++------- src/librustc_typeck/check/expr.rs | 17 +---- src/librustc_typeck/check/mod.rs | 10 +-- src/librustdoc/clean/mod.rs | 20 +---- 23 files changed, 195 insertions(+), 253 deletions(-) create mode 100644 src/librustc/mir/interpret/queries.rs diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index fff876752db..80bac92d003 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -101,6 +101,7 @@ macro_rules! throw_machine_stop { mod value; mod allocation; mod pointer; +mod queries; pub use self::error::{ InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error, @@ -116,9 +117,10 @@ macro_rules! throw_machine_stop { use crate::mir; 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::layout::{self, Size}; +use crate::ty::subst::GenericArgKind; use std::io; use std::fmt; use std::num::NonZeroU32; diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs new file mode 100644 index 00000000000..5fd49a056d2 --- /dev/null +++ b/src/librustc/mir/interpret/queries.rs @@ -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 `::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() { let _ = [0; bar::()]; }` the repeat count + /// constant `bar::()` 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 + ) -> 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 + ) -> 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)) + } +} diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index cc02165f605..a9dd856e758 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -448,7 +448,8 @@ /// /// **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 - /// `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>>) -> ConstEvalRawResult<'tcx> { no_force @@ -460,7 +461,13 @@ /// Results of evaluating const items or constants embedded in /// 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> { no_force desc { |tcx| diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 27731990d2b..3fd2415c83c 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -1,5 +1,4 @@ use crate::infer::{InferCtxt, ShallowResolver}; -use crate::mir::interpret::{GlobalId, ErrorHandled}; use crate::ty::{self, Ty, TypeFoldable, ToPolyTraitRef}; use crate::ty::error::ExpectedFound; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; @@ -501,27 +500,13 @@ fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy { ProcessResult::Unchanged } else { if !substs.has_local_value() { - let instance = ty::Instance::resolve( - self.selcx.tcx(), - obligation.param_env, - def_id, - substs, - ); - if let Some(instance) = instance { - 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) - )) + match self.selcx.tcx().const_eval_resolve(obligation.param_env, + def_id, + substs, + Some(obligation.cause.span)) { + Ok(_) => ProcessResult::Changed(vec![]), + Err(err) => ProcessResult::Error( + CodeSelectionError(ConstEvalFailure(err))) } } else { pending_obligation.stalled_on = diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 94a77c553e5..8d04c832f26 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -33,7 +33,6 @@ use crate::hir::def_id::DefId; use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; use crate::middle::lang_items; -use crate::mir::interpret::GlobalId; use crate::ty::fast_reject; use crate::ty::relate::TypeRelation; use crate::ty::subst::{Subst, SubstsRef}; @@ -820,22 +819,13 @@ fn evaluate_predicate_recursively<'o>( } ty::Predicate::ConstEvaluatable(def_id, substs) => { - let tcx = self.tcx(); if !(obligation.param_env, substs).has_local_value() { - let param_env = obligation.param_env; - let instance = - ty::Instance::resolve(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(_) => Ok(EvaluatedToOk), - Err(_) => Ok(EvaluatedToErr), - } - } else { - Ok(EvaluatedToErr) + match self.tcx().const_eval_resolve(obligation.param_env, + def_id, + substs, + None) { + Ok(_) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr), } } else { // Inference variables still left in param_env or substs. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 15bbfa7860f..c60d4a46935 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -19,7 +19,7 @@ use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::ReadOnlyBodyAndCache; -use crate::mir::interpret::{GlobalId, ErrorHandled}; +use crate::mir::interpret::ErrorHandled; use crate::mir::GeneratorLayout; use crate::session::CrateDisambiguator; use crate::traits::{self, Reveal}; @@ -2344,13 +2344,7 @@ pub fn variant_of_res(&self, res: Res) -> &VariantDef { pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option> { let param_env = tcx.param_env(expr_did); let repr_type = self.repr.discr_type(); - let substs = InternalSubsts::identity_for_item(tcx, expr_did); - let instance = ty::Instance::new(expr_did, substs); - let cid = GlobalId { - instance, - promoted: None - }; - match tcx.const_eval(param_env.and(cid)) { + match tcx.const_eval_poly(expr_did) { Ok(val) => { // 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) { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6cb0d1e9946..1e08c36ca50 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -15,7 +15,7 @@ use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; use crate::ty::layout::VariantIdx; use crate::util::captures::Captures; -use crate::mir::interpret::{Scalar, GlobalId}; +use crate::mir::interpret::Scalar; use polonius_engine::Atom; use rustc_index::vec::Idx; @@ -2340,13 +2340,9 @@ pub fn eval( let (param_env, substs) = param_env_and_substs.into_parts(); - // try to resolve e.g. associated constants to their definition on an impl - let instance = ty::Instance::resolve(tcx, param_env, did, substs)?; - let gid = GlobalId { - instance, - promoted: None, - }; - tcx.const_eval(param_env.and(gid)).ok() + // try to resolve e.g. associated constants to their definition on an impl, and then + // evaluate the const. + tcx.const_eval_resolve(param_env, did, substs, None).ok() }; match self.val { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 11a105c1828..c048321e383 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -8,7 +8,7 @@ use libc::c_uint; use rustc::hir::def_id::DefId; use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint, - Pointer, ErrorHandled, GlobalId}; + Pointer, ErrorHandled}; use rustc::mir::mono::MonoItem; use rustc::hir::Node; use rustc_target::abi::HasDataLayout; @@ -81,13 +81,7 @@ pub fn codegen_static_initializer( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { - let instance = ty::Instance::mono(cx.tcx, 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 static_ = cx.tcx.const_eval_poly(def_id)?; let alloc = match static_.val { ty::ConstKind::Value(ConstValue::ByRef { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 900f2d2defc..da776757fdf 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -14,7 +14,6 @@ use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types}; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, FnAbiExt, LayoutOf, HasTyCtxt, Primitive}; -use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use rustc_target::abi::HasDataLayout; @@ -202,11 +201,9 @@ fn codegen_intrinsic_call( "needs_drop" | "type_id" | "type_name" => { - let gid = GlobalId { - instance, - promoted: None, - }; - let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap(); + let ty_name = self.tcx + .const_eval_instance(ty::ParamEnv::reveal_all(), instance, None) + .unwrap(); OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self) } "init" => { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index dabd097b000..a532c23a6e0 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -638,12 +638,7 @@ fn codegen_call_terminator( projection: &[], } = place.as_ref() { - let param_env = ty::ParamEnv::reveal_all(); - let cid = mir::interpret::GlobalId { - instance: self.instance, - promoted: Some(promoted), - }; - let c = bx.tcx().const_eval(param_env.and(cid)); + let c = bx.tcx().const_eval_promoted(self.instance, promoted); let (llval, ty) = self.simd_shuffle_indices( &bx, terminator.source_info.span, diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index fb8f504d04b..fc17e2c0c71 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -43,17 +43,14 @@ pub fn eval_mir_constant( match constant.literal.val { ty::ConstKind::Unevaluated(def_id, substs) => { let substs = self.monomorphize(&substs); - let instance = ty::Instance::resolve( - self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs, - ).unwrap(); - let cid = mir::interpret::GlobalId { - instance, - promoted: None, - }; - 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 - }) + self.cx.tcx() + .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, None) + .map_err(|err| { + self.cx.tcx().sess.span_err( + constant.span, + "erroneous constant encountered"); + err + }) }, _ => Ok(self.monomorphize(&constant.literal)), } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e13cabced0..1132f9b2f03 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -473,14 +473,9 @@ pub fn codegen_place( }), projection: [], } => { - let param_env = ty::ParamEnv::reveal_all(); 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)); - match bx.tcx().const_eval(param_env.and(cid)) { + match bx.tcx().const_eval_promoted(instance, *promoted) { Ok(val) => match val.val { ty::ConstKind::Value(mir::interpret::ConstValue::ByRef { alloc, offset diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 10b00d35d9b..b46e8a8438f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1134,19 +1134,9 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) { fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) { 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 // 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 { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index b219fec31dc..a2f066bee08 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -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>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { @@ -660,7 +660,7 @@ pub fn const_eval_provider<'tcx>( if key.param_env.reveal == Reveal::All { let mut key = key.clone(); key.param_env.reveal = Reveal::UserFacing; - match tcx.const_eval(key) { + match tcx.const_eval_validated(key) { // try again with reveal all as requested Err(ErrorHandled::TooGeneric) => { // Promoteds should never be "too generic" when getting evaluated. diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8c852854be1..f116f7d14da 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -5,7 +5,7 @@ use crate::hair::util::UserAnnotatedTyHelpers; use rustc_index::vec::Idx; 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::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -514,21 +514,15 @@ fn make_mirror_unadjusted<'a, 'tcx>( hir::ExprKind::Repeat(ref v, ref count) => { let def_id = cx.tcx.hir().local_def_id(count.hir_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 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), Err(ErrorHandled::Reported) => 0, 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"); 0 }, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0086c3b0e10..e12f0322564 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -11,7 +11,7 @@ use rustc::mir::{Field, BorrowKind, Mutability}; 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::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; use rustc::ty::subst::{SubstsRef, GenericArg}; @@ -854,57 +854,37 @@ fn lower_path(&mut self, let kind = match res { Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { let substs = self.tables.node_substs(id); - match ty::Instance::resolve( - self.tcx, - self.param_env, - def_id, - substs, - ) { - 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; - } + match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) { + 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(); - return if let Some(u_ty) = user_provided_types.get(id) { - let user_ty = PatTyProj::from_user_type(*u_ty); - Pat { - span, - kind: Box::new( - PatKind::AscribeUserType { - subpattern: pattern, - ascription: Ascription { - /// Note that use `Contravariant` here. See the - /// `variance` field documentation for details. - variance: ty::Variance::Contravariant, - user_ty, - user_ty_span: span, - }, - } - ), - ty: value.ty, + let user_provided_types = self.tables().user_provided_types(); + return if let Some(u_ty) = user_provided_types.get(id) { + let user_ty = PatTyProj::from_user_type(*u_ty); + Pat { + span, + kind: Box::new( + PatKind::AscribeUserType { + subpattern: pattern, + ascription: Ascription { + /// Note that use `Contravariant` here. See the + /// `variance` field documentation for details. + variance: ty::Variance::Contravariant, + user_ty, + user_ty_span: span, + }, } - } else { - pattern - } - }, - Err(_) => { - self.tcx.sess.span_err( - span, - "could not evaluate constant pattern", - ); - PatKind::Wild + ), + ty: value.ty, } + } else { + pattern } }, - None => { + Err(ErrorHandled::TooGeneric) => { self.errors.push(if is_associated_const { PatternError::AssocConstInPattern(span) } else { @@ -912,6 +892,13 @@ fn lower_path(&mut self, }); 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![]), diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 67f0aed243d..46782ef0a80 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -11,7 +11,7 @@ use rustc::ty::TyCtxt; use rustc::mir::{ self, BinOp, - interpret::{InterpResult, Scalar, GlobalId, ConstValue} + interpret::{InterpResult, Scalar, ConstValue} }; use super::{ @@ -123,11 +123,9 @@ pub fn emulate_intrinsic( sym::size_of | sym::type_id | sym::type_name => { - let gid = GlobalId { - instance, - promoted: None, - }; - let val = self.tcx.const_eval(self.param_env.and(gid))?; + let val = self.tcx.const_eval_instance(self.param_env, + instance, + Some(self.tcx.span))?; let val = self.eval_const_to_op(val, None)?; self.copy_op(val, dest)?; } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 42fbfeca3f0..70ea3745b4d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -619,11 +619,6 @@ pub(super) fn eval_static_to_mplace( let ty = place_static.ty; assert!(!ty.needs_subst()); 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. // tcx takes care of assigning every static one and only one unique AllocId. // When the data here is ever actually used, memory will notice, @@ -639,7 +634,7 @@ pub(super) fn eval_static_to_mplace( // Notice that statics have *two* AllocIds: the lazy one, and the resolved // one. Here we make sure that the interpreted program never sees the // 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)); MPlaceTy::from_aligned_ptr(ptr, layout) } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f6b3c5b8e5e..cf54530317c 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -56,7 +56,7 @@ pub fn provide(providers: &mut Providers<'_>) { shim::provide(providers); transform::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.check_match = hair::pattern::check_match; providers.const_caller_location = const_eval::const_caller_location; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 93a76712b28..ab95c795c43 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -189,7 +189,7 @@ use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; 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::common::time; @@ -379,13 +379,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; - let cid = GlobalId { - instance, - promoted: None, - }; - let param_env = ty::ParamEnv::reveal_all(); - - if let Ok(val) = tcx.const_eval(param_env.and(cid)) { + if let Ok(val) = tcx.const_eval_poly(def_id) { collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors); } } @@ -681,12 +675,8 @@ fn visit_place_base(&mut self, def_id, .. }) => { - let param_env = ty::ParamEnv::reveal_all(); - let cid = GlobalId { - instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), - promoted: Some(*promoted), - }; - match self.tcx.const_eval(param_env.and(cid)) { + let instance = Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)); + match self.tcx.const_eval_promoted(instance, *promoted) { Ok(val) => collect_const(self.tcx, val, substs, self.output), Err(ErrorHandled::Reported) => {}, Err(ErrorHandled::TooGeneric) => { @@ -1041,14 +1031,7 @@ fn visit_item(&mut self, item: &'v hir::Item) { // 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 instance = Instance::mono(self.tcx, 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)) { + if let Ok(val) = self.tcx.const_eval_poly(def_id) { collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output); } } @@ -1288,16 +1271,7 @@ fn collect_const<'tcx>( } } ty::ConstKind::Unevaluated(def_id, substs) => { - let instance = ty::Instance::resolve(tcx, - param_env, - def_id, - substs).unwrap(); - - let cid = GlobalId { - instance, - promoted: None, - }; - match tcx.const_eval(param_env.and(cid)) { + match tcx.const_eval_resolve(param_env, def_id, substs, None) { Ok(val) => collect_const(tcx, val, param_substs, output), Err(ErrorHandled::Reported) => {}, Err(ErrorHandled::TooGeneric) => span_bug!( diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 19441be87b9..b287b39cb99 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -31,7 +31,6 @@ use rustc::infer; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::middle::lang_items; -use rustc::mir::interpret::GlobalId; use rustc::ty; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, @@ -39,7 +38,6 @@ use rustc::ty::{AdtKind, Visibility}; use rustc::ty::Ty; use rustc::ty::TypeFoldable; -use rustc::ty::subst::InternalSubsts; use rustc::traits::{self, ObligationCauseCode}; use rustc_error_codes::*; @@ -1023,20 +1021,7 @@ fn check_expr_repeat( let count = if self.const_param_def_id(count).is_some() { Ok(self.to_const(count, tcx.type_of(count_def_id))) } else { - let param_env = ty::ParamEnv::empty(); - 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)) + tcx.const_eval_poly(count_def_id) }; let uty = match expected { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 09771bb7625..84f5847ddd3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -106,7 +106,7 @@ use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc::middle::region; -use rustc::mir::interpret::{ConstValue, GlobalId}; +use rustc::mir::interpret::ConstValue; use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::{ 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 // the consumer's responsibility to ensure all bytes that have been read // have defined values. - let instance = ty::Instance::mono(tcx, 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)) { + if let Ok(static_) = tcx.const_eval_poly(id) { let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val { alloc } else { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e5f684cbca8..7eb1370c342 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -15,7 +15,6 @@ use rustc::middle::resolve_lifetime as rl; use rustc::middle::lang_items; use rustc::middle::stability; -use rustc::mir::interpret::GlobalId; use rustc::hir; use rustc::hir::def::{CtorKind, DefKind, Res}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; @@ -1334,13 +1333,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), TyKind::Array(ref ty, ref length) => { let def_id = cx.tcx.hir().local_def_id(length.hir_id); - let param_env = cx.tcx.param_env(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)) { + let length = match cx.tcx.const_eval_poly(def_id) { Ok(length) => print_const(cx, length), Err(_) => cx.sess() .source_map() @@ -1534,16 +1527,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { ty::Slice(ty) => Slice(box ty.clean(cx)), ty::Array(ty, n) => { let mut n = cx.tcx.lift(&n).expect("array lift failed"); - if let ty::ConstKind::Unevaluated(def_id, substs) = n.val { - 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; - } - }; + n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); Array(box ty.clean(cx), n) } -- 2.44.0