diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh index d8ff74078220e..4c047069571bd 100755 --- a/src/ci/publish_toolstate.sh +++ b/src/ci/publish_toolstate.sh @@ -14,12 +14,15 @@ printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \ > "$HOME/.git-credentials" git clone --depth=1 $TOOLSTATE_REPO +GIT_COMMIT="$(git rev-parse HEAD)" +GIT_COMMIT_MSG="$(git log --format=%s -n1 HEAD)" + cd rust-toolstate FAILURE=1 for RETRY_COUNT in 1 2 3 4 5; do # The purpose is to publish the new "current" toolstate in the toolstate repo. - "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \ - "$(git log --format=%s -n1 HEAD)" \ + "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$GIT_COMMIT" \ + "$GIT_COMMIT_MSG" \ "$MESSAGE_FILE" \ "$TOOLSTATE_REPO_ACCESS_TOKEN" # `git commit` failing means nothing to commit. diff --git a/src/libcore/any.rs b/src/libcore/any.rs index a2aa6b3fea50c..5126fe01a3f00 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -74,6 +74,16 @@ use crate::intrinsics; /// See the [module-level documentation][mod] for more details. /// /// [mod]: index.html +// This trait is not unsafe, though we rely on the specifics of it's sole impl's +// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be +// a problem, but because the only impl of `Any` is a blanket implementation, no +// other code can implement `Any`. +// +// We could plausibly make this trait unsafe -- it would not cause breakage, +// since we control all the implementations -- but we choose not to as that's +// both not really necessary and may confuse users about the distinction of +// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, +// but we would likely want to indicate as such in documentation). #[stable(feature = "rust1", since = "1.0.0")] pub trait Any: 'static { /// Gets the `TypeId` of `self`. diff --git a/src/libcore/iter_private.rs b/src/libcore/iter_private.rs deleted file mode 100644 index 890db47b19700..0000000000000 --- a/src/libcore/iter_private.rs +++ /dev/null @@ -1,17 +0,0 @@ -/// An iterator whose items are random accessible efficiently -/// -/// # Safety -/// -/// The iterator's .len() and size_hint() must be exact. -/// `.len()` must be cheap to call. -/// -/// .get_unchecked() must return distinct mutable references for distinct -/// indices (if applicable), and must return a valid reference if index is in -/// 0..self.len(). -#[doc(hidden)] -pub unsafe trait TrustedRandomAccess : ExactSizeIterator { - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item; - /// Returns `true` if getting an iterator element may have - /// side effects. Remember to take inner iterators into account. - fn may_have_side_effect() -> bool; -} diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index fff876752db55..80bac92d00354 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -101,6 +101,7 @@ mod error; mod value; mod allocation; mod pointer; +mod queries; pub use self::error::{ InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error, @@ -116,9 +117,10 @@ pub use self::pointer::{Pointer, PointerArithmetic, CheckInAllocMsg}; 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 0000000000000..5fd49a056d22c --- /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/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index a038ca23ae92d..f48d22291c6a4 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -236,14 +236,22 @@ impl<'tcx, Tag> Scalar { Scalar::Raw { data: c as u128, size: 4 } } + #[inline] + pub fn try_from_uint(i: impl Into, size: Size) -> Option { + let i = i.into(); + if truncate(i, size) == i { + Some(Scalar::Raw { data: i, size: size.bytes() as u8 }) + } else { + None + } + } + #[inline] pub fn from_uint(i: impl Into, size: Size) -> Self { let i = i.into(); - assert_eq!( - truncate(i, size), i, - "Unsigned value {:#x} does not fit in {} bits", i, size.bits() - ); - Scalar::Raw { data: i, size: size.bytes() as u8 } + Self::try_from_uint(i, size).unwrap_or_else(|| { + bug!("Unsigned value {:#x} does not fit in {} bits", i, size.bits()) + }) } #[inline] @@ -267,15 +275,23 @@ impl<'tcx, Tag> Scalar { } #[inline] - pub fn from_int(i: impl Into, size: Size) -> Self { + pub fn try_from_int(i: impl Into, size: Size) -> Option { let i = i.into(); // `into` performed sign extension, we have to truncate let truncated = truncate(i as u128, size); - assert_eq!( - sign_extend(truncated, size) as i128, i, - "Signed value {:#x} does not fit in {} bits", i, size.bits() - ); - Scalar::Raw { data: truncated, size: size.bytes() as u8 } + if sign_extend(truncated, size) as i128 == i { + Some(Scalar::Raw { data: truncated, size: size.bytes() as u8 }) + } else { + None + } + } + + #[inline] + pub fn from_int(i: impl Into, size: Size) -> Self { + let i = i.into(); + Self::try_from_int(i, size).unwrap_or_else(|| { + bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()) + }) } #[inline] diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index cc02165f60579..a9dd856e75857 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -448,7 +448,8 @@ rustc_queries! { /// /// **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 @@ rustc_queries! { /// 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 27731990d2b62..3fd2415c83c0c 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 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { 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 f1cd002d19b64..afc8a4d9e1415 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -33,7 +33,6 @@ use crate::dep_graph::{DepKind, DepNodeIndex}; 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } 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 37a443a2c7469..30356d59a7ce6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -19,7 +19,7 @@ use crate::middle::cstore::CrateStoreDyn; 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 @@ impl<'tcx> AdtDef { 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 02efe8df03d80..604dc03ea17bc 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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::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 @@ impl<'tcx> Const<'tcx> { 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 e1750887ac43e..78a86d33a145b 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -8,7 +8,7 @@ use crate::value::Value; 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 e178050b36918..e5a7583a8cc70 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -14,7 +14,6 @@ use rustc_codegen_ssa::glue; 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 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "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 dabd097b000b5..a532c23a6e0a2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -638,12 +638,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 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 fb8f504d04b10..fc17e2c0c71b7 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -43,17 +43,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 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 5b21dfbdf1c69..98d239d353d3a 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -473,14 +473,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }), 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 de541ef5af3e3..340af64adad56 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1147,19 +1147,9 @@ declare_lint_pass!( 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/build/block.rs b/src/librustc_mir/build/block.rs index 7353ca9285ddb..aceed09757e7e 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -33,8 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode) }); - this.cfg.terminate(unpack!(block_exit), source_info, - TerminatorKind::Goto { target: exit_block }); + this.cfg.goto(unpack!(block_exit), source_info, exit_block); exit_block.unit() } else { this.ast_block_stmts(destination, block, span, stmts, expr, diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 6bd8d2f7c0792..0e685486c3f99 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -85,4 +85,9 @@ impl<'tcx> CFG<'tcx> { kind, }); } + + /// In the `origin` block, push a `goto -> target` terminator. + pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) { + self.terminate(origin, source_info, TerminatorKind::Goto { target }) + } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 608415408e35c..a9fa7cfa04a89 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -140,17 +140,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); - this.cfg.terminate( - true_block, - source_info, - TerminatorKind::Goto { target: join_block }, - ); - this.cfg.terminate( - false_block, - source_info, - TerminatorKind::Goto { target: join_block }, - ); - + // Link up both branches: + this.cfg.goto(true_block, source_info, join_block); + this.cfg.goto(false_block, source_info, join_block); join_block.unit() } ExprKind::Loop { body } => { @@ -167,12 +159,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let loop_block = this.cfg.start_new_block(); let exit_block = this.cfg.start_new_block(); - // start the loop - this.cfg.terminate( - block, - source_info, - TerminatorKind::Goto { target: loop_block }, - ); + // Start the loop. + this.cfg.goto(block, source_info, loop_block); this.in_breakable_scope( Some(loop_block), @@ -196,11 +184,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. let body_block_end = unpack!(this.into(&tmp, body_block, body)); - this.cfg.terminate( - body_block_end, - source_info, - TerminatorKind::Goto { target: loop_block }, - ); + this.cfg.goto(body_block_end, source_info, loop_block); }, ); exit_block.unit() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index bf0b2439c00b5..6869930509cbe 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -26,6 +26,7 @@ mod simplify; mod test; mod util; +use itertools::Itertools; use std::convert::TryFrom; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -258,11 +259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scrutinee_span, match_scope, ); - this.cfg.terminate( - binding_end, - source_info, - TerminatorKind::Goto { target: arm_block }, - ); + this.cfg.goto(binding_end, source_info, arm_block); } } @@ -278,11 +275,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let end_block = self.cfg.start_new_block(); for arm_block in arm_end_blocks { - self.cfg.terminate( - unpack!(arm_block), - outer_source_info, - TerminatorKind::Goto { target: end_block }, - ); + self.cfg.goto(unpack!(arm_block), outer_source_info, end_block); } self.source_scope = outer_source_info.scope; @@ -822,9 +815,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); let (matched_candidates, unmatched_candidates) = candidates.split_at_mut(fully_matched); - let block: BasicBlock; - - if !matched_candidates.is_empty() { + let block: BasicBlock = if !matched_candidates.is_empty() { let otherwise_block = self.select_matched_candidates( matched_candidates, start_block, @@ -832,35 +823,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); if let Some(last_otherwise_block) = otherwise_block { - block = last_otherwise_block + last_otherwise_block } else { // Any remaining candidates are unreachable. if unmatched_candidates.is_empty() { return; } - block = self.cfg.start_new_block(); - }; + self.cfg.start_new_block() + } } else { - block = *start_block.get_or_insert_with(|| self.cfg.start_new_block()); - } + *start_block.get_or_insert_with(|| self.cfg.start_new_block()) + }; // If there are no candidates that still need testing, we're // done. Since all matches are exhaustive, execution should // never reach this point. if unmatched_candidates.is_empty() { let source_info = self.source_info(span); - if let Some(otherwise) = otherwise_block { - self.cfg.terminate( - block, - source_info, - TerminatorKind::Goto { target: otherwise }, - ); - } else { - self.cfg.terminate( - block, - source_info, - TerminatorKind::Unreachable, - ) + match otherwise_block { + Some(otherwise) => self.cfg.goto(block, source_info, otherwise), + None => self.cfg.terminate(block, source_info, TerminatorKind::Unreachable), } return; } @@ -885,7 +867,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// ... /// /// We generate real edges from: - /// * `block` to the prebinding_block of the first pattern, + /// * `start_block` to the `prebinding_block` of the first pattern, /// * the otherwise block of the first pattern to the second pattern, /// * the otherwise block of the third pattern to the a block with an /// Unreachable terminator. @@ -948,32 +930,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let first_candidate = &reachable_candidates[0]; let first_prebinding_block = first_candidate.pre_binding_block; + // `goto -> first_prebinding_block` from the `start_block` if there is one. if let Some(start_block) = *start_block { let source_info = self.source_info(first_candidate.span); - self.cfg.terminate( - start_block, - source_info, - TerminatorKind::Goto { target: first_prebinding_block }, - ); + self.cfg.goto(start_block, source_info, first_prebinding_block); } else { *start_block = Some(first_prebinding_block); } - for window in reachable_candidates.windows(2) { - if let [first_candidate, second_candidate] = window { - let source_info = self.source_info(first_candidate.span); - if let Some(otherwise_block) = first_candidate.otherwise_block { - self.false_edges( - otherwise_block, - second_candidate.pre_binding_block, - first_candidate.next_candidate_pre_binding_block, - source_info, - ); - } else { - bug!("candidate other than the last has no guard"); - } + for (first_candidate, second_candidate) in reachable_candidates.iter().tuple_windows() { + let source_info = self.source_info(first_candidate.span); + if let Some(otherwise_block) = first_candidate.otherwise_block { + self.false_edges( + otherwise_block, + second_candidate.pre_binding_block, + first_candidate.next_candidate_pre_binding_block, + source_info, + ); } else { - bug!("<[_]>::windows returned incorrectly sized window"); + bug!("candidate other than the last has no guard"); } } @@ -992,8 +967,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - let last_candidate = reachable_candidates.last().unwrap(); + let last_candidate = reachable_candidates.last().unwrap(); if let Some(otherwise) = last_candidate.otherwise_block { let source_info = self.source_info(last_candidate.span); let block = self.cfg.start_new_block(); diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index e320811ca0556..bdc1bdd5b9855 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Test { span: match_pair.pattern.span, kind: TestKind::Switch { - adt_def: adt_def.clone(), + adt_def, variants: BitSet::new_empty(adt_def.variants.len()), }, } diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index ec8b3c5e24bf2..87481d1d69bc7 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -109,15 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); } - _ => { - self.cfg.terminate( - from_block, - source_info, - TerminatorKind::Goto { - target: real_target - } - ); - } + _ => self.cfg.goto(from_block, source_info, real_target), } } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 6b6a58102fa82..3b85a5d3c911b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -606,14 +606,11 @@ where let fn_end = span.shrink_to_hi(); let source_info = builder.source_info(fn_end); let return_block = builder.return_block(); - builder.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: return_block }); - builder.cfg.terminate(return_block, source_info, - TerminatorKind::Return); + builder.cfg.goto(block, source_info, return_block); + builder.cfg.terminate(return_block, source_info, TerminatorKind::Return); // Attribute any unreachable codepaths to the function's closing brace if let Some(unreachable_block) = builder.cached_unreachable_block { - builder.cfg.terminate(unreachable_block, source_info, - TerminatorKind::Unreachable); + builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable); } return_block.unit() })); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 00a30af806a89..9c5966263dfc0 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -564,14 +564,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = scope.source_info(span); block = match scope.cached_exits.entry((target, region_scope)) { Entry::Occupied(e) => { - self.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: *e.get() }); + self.cfg.goto(block, source_info, *e.get()); return; } Entry::Vacant(v) => { let b = self.cfg.start_new_block(); - self.cfg.terminate(block, source_info, - TerminatorKind::Goto { target: b }); + self.cfg.goto(block, source_info, b); v.insert(b); b } @@ -596,8 +594,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope = next_scope; } - let source_info = self.scopes.source_info(scope_count, span); - self.cfg.terminate(block, source_info, TerminatorKind::Goto { target }); + self.cfg.goto(block, self.scopes.source_info(scope_count, span), target); } /// Creates a path that performs all required cleanup for dropping a generator. @@ -616,14 +613,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { while let Some(scope) = scopes.next() { block = if let Some(b) = scope.cached_generator_drop { - self.cfg.terminate(block, src_info, - TerminatorKind::Goto { target: b }); + self.cfg.goto(block, src_info, b); return Some(result); } else { let b = self.cfg.start_new_block(); scope.cached_generator_drop = Some(b); - self.cfg.terminate(block, src_info, - TerminatorKind::Goto { target: b }); + self.cfg.goto(block, src_info, b); b }; @@ -1243,8 +1238,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, // block for our StorageDead statements. let block = cfg.start_new_cleanup_block(); let source_info = SourceInfo { span: DUMMY_SP, scope: source_scope }; - cfg.terminate(block, source_info, - TerminatorKind::Goto { target: target }); + cfg.goto(block, source_info, target); target = block; target_built_by_us = true; } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index b219fec31dc59..a2f066bee08d1 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 c05641fe8bf0a..589016a2ca253 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -5,7 +5,7 @@ use crate::hair::cx::to_ref::ToRef; 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}; @@ -511,21 +511,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 9d0a67151fb60..fdef6633925da 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -11,7 +11,7 @@ use crate::hair::constant::*; 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}; @@ -771,57 +771,37 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { 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 { @@ -829,6 +809,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }); 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 67f0aed243da1..46782ef0a806b 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -11,7 +11,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::TyCtxt; use rustc::mir::{ self, BinOp, - interpret::{InterpResult, Scalar, GlobalId, ConstValue} + interpret::{InterpResult, Scalar, ConstValue} }; use super::{ @@ -123,11 +123,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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/operand.rs b/src/librustc_mir/interpret/operand.rs index 93ab7b9aab7fb..0af203079b153 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -218,11 +218,20 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { ImmTy { imm: val.into(), layout } } + #[inline] + pub fn try_from_uint(i: impl Into, layout: TyLayout<'tcx>) -> Option { + Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout)) + } #[inline] pub fn from_uint(i: impl Into, layout: TyLayout<'tcx>) -> Self { Self::from_scalar(Scalar::from_uint(i, layout.size), layout) } + #[inline] + pub fn try_from_int(i: impl Into, layout: TyLayout<'tcx>) -> Option { + Some(Self::from_scalar(Scalar::try_from_int(i, layout.size)?, layout)) + } + #[inline] pub fn from_int(i: impl Into, layout: TyLayout<'tcx>) -> Self { Self::from_scalar(Scalar::from_int(i, layout.size), layout) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 8923b167fdee8..a1e6eb69b9d0d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -626,11 +626,6 @@ where 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, @@ -646,7 +641,7 @@ where // 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 f6b3c5b8e5e82..cf54530317c43 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 83a4f224aa257..ac627d32392b8 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -189,7 +189,7 @@ use rustc::session::config::EntryFnType; 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 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { 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 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { // 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_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 802d38e299712..a768fdc779ed9 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -173,7 +173,7 @@ impl<'a> Parser<'a> { let args = if self.eat_lt() { // `<'a, T, A = U>` let (args, constraints) = - self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; + self.parse_generic_args_with_leading_angle_bracket_recovery(style, lo)?; self.expect_gt()?; let span = lo.to(self.prev_span); AngleBracketedArgs { args, constraints, span }.into() @@ -212,7 +212,7 @@ impl<'a> Parser<'a> { /// bar::<<<::Output>(); /// ^^ help: remove extra angle brackets /// ``` - fn parse_generic_args_with_leaning_angle_bracket_recovery( + fn parse_generic_args_with_leading_angle_bracket_recovery( &mut self, style: PathStyle, lo: Span, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 17b168cfab05a..a6ae10b3dea39 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -31,7 +31,6 @@ use rustc::hir::ptr::P; 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::adjustment::{ 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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 5895b8d25d3d6..ea295103982b0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -106,7 +106,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 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/inline.rs b/src/librustdoc/clean/inline.rs index 7ee1054dc4846..b7e01708fbfcf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -7,7 +7,7 @@ use syntax::symbol::sym; use syntax_pos::hygiene::MacroKind; use syntax_pos::Span; -use rustc::hir; +use rustc::hir::{self, Mutability}; use rustc::hir::def::{Res, DefKind, CtorKind}; use rustc::hir::def_id::DefId; use rustc_metadata::creader::LoadedMacro; @@ -472,7 +472,7 @@ fn build_const(cx: &DocContext<'_>, did: DefId) -> clean::Constant { fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static { clean::Static { type_: cx.tcx.type_of(did).clean(cx), - mutability: if mutable {clean::Mutable} else {clean::Immutable}, + mutability: if mutable { Mutability::Mut } else { Mutability::Not }, expr: "\n\n\n".to_string(), // trigger the "[definition]" links } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 03fb0d9997822..4afa0be55a64c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -15,7 +15,6 @@ use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; 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}; @@ -46,7 +45,6 @@ pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res}; pub use self::types::*; pub use self::types::Type::*; -pub use self::types::Mutability::*; pub use self::types::ItemEnum::*; pub use self::types::SelfTy::*; pub use self::types::FunctionRetTy::*; @@ -1328,26 +1326,19 @@ impl Clean for hir::Ty { match self.kind { TyKind::Never => Never, - TyKind::Ptr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)), + TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)), TyKind::Rptr(ref l, ref m) => { let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) }; - BorrowedRef {lifetime, mutability: m.mutbl.clean(cx), - type_: box m.ty.clean(cx)} + BorrowedRef {lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx)} } 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() @@ -1541,23 +1532,14 @@ impl<'tcx> Clean for Ty<'tcx> { 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) } - ty::RawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)), + ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)), ty::Ref(r, ty, mutbl) => BorrowedRef { lifetime: r.clean(cx), - mutability: mutbl.clean(cx), + mutability: mutbl, type_: box ty.clean(cx), }, ty::FnDef(..) | @@ -2080,7 +2062,7 @@ impl Clean for doctree::Static<'_> { deprecation: cx.deprecation(self.id).clean(cx), inner: StaticItem(Static { type_: self.type_.clean(cx), - mutability: self.mutability.clean(cx), + mutability: self.mutability, expr: print_const_expr(cx, self.expr), }), } @@ -2105,15 +2087,6 @@ impl Clean for doctree::Constant<'_> { } } -impl Clean for hir::Mutability { - fn clean(&self, _: &DocContext<'_>) -> Mutability { - match self { - &hir::Mutability::Mut => Mutable, - &hir::Mutability::Not => Immutable, - } - } -} - impl Clean for ty::ImplPolarity { fn clean(&self, _: &DocContext<'_>) -> ImplPolarity { match self { @@ -2303,7 +2276,7 @@ impl Clean for doctree::ForeignItem<'_> { hir::ForeignItemKind::Static(ref ty, mutbl) => { ForeignStaticItem(Static { type_: ty.clean(cx), - mutability: mutbl.clean(cx), + mutability: *mutbl, expr: String::new(), }) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index bd3f2a3690a27..706aef720310f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use rustc::middle::lang_items; use rustc::middle::stability; -use rustc::hir; +use rustc::hir::{self, Mutability}; use rustc::hir::def::Res; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::ty::layout::VariantIdx; @@ -1450,12 +1450,6 @@ pub struct Constant { pub expr: String, } -#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] -pub enum Mutability { - Mutable, - Immutable, -} - #[derive(Clone, PartialEq, Debug)] pub enum ImplPolarity { Positive, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index fd620d467de48..501147ed4593b 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -670,8 +670,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Never => primitive_link(f, PrimitiveType::Never, "!"), clean::RawPointer(m, ref t) => { let m = match m { - clean::Immutable => "const", - clean::Mutable => "mut", + hir::Mutability::Mut => "mut", + hir::Mutability::Not => "const", }; match **t { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { @@ -1082,6 +1082,15 @@ impl PrintWithSpace for hir::IsAsync { } } +impl PrintWithSpace for hir::Mutability { + fn print_with_space(&self) -> &str { + match self { + hir::Mutability::Not => "", + hir::Mutability::Mut => "mut ", + } + } +} + impl clean::Import { crate fn print(&self) -> impl fmt::Display + '_ { display_fn(move |f| { @@ -1151,15 +1160,6 @@ impl clean::TypeBinding { } } -impl clean::Mutability { - crate fn print_with_space(&self) -> &str { - match self { - clean::Immutable => "", - clean::Mutable => "mut ", - } - } -} - crate fn print_abi_with_space(abi: Abi) -> impl fmt::Display { display_fn(move |f| { let quot = if f.alternate() { "\"" } else { """ }; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e764b7ee5276b..100aed1af193a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -54,12 +54,12 @@ use syntax_pos::hygiene::MacroKind; use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; -use rustc::hir; +use rustc::hir::{self, Mutability}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::flock; use rustc_feature::UnstableFeatures; -use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, Mutability}; +use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy}; use crate::config::RenderOptions; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; @@ -3298,7 +3298,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { let (by_mut_ref, by_box, by_value) = match self_ty { SelfTy::SelfBorrowed(_, mutability) | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { - (mutability == Mutability::Mutable, false, false) + (mutability == Mutability::Mut, false, false) }, SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => { (false, Some(did) == cache().owned_box_did, false)