about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-22 19:30:57 +0000
committerbors <bors@rust-lang.org>2019-12-22 19:30:57 +0000
commit9b98af84c4aa66392236fff59c86da2130d46d46 (patch)
tree963faec2cc41a9ad3ac9b844c7f421793ec81e1a /src
parent0d2817a439c2ad9fe343f6347eb6d90947893363 (diff)
parent9c5b73e9a4d1833f67da69ab41f4cc80300097fc (diff)
downloadrust-9b98af84c4aa66392236fff59c86da2130d46d46.tar.gz
rust-9b98af84c4aa66392236fff59c86da2130d46d46.zip
Auto merge of #67532 - Centril:rollup-3duj42d, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #66877 (Add simpler entry points to const eval for common usages.)
 - #67299 (Add `ImmTy::try_from_(u)int` methods)
 - #67487 (Rustdoc mutability removal)
 - #67499 (Misc MIR building cleanups)
 - #67506 (Remove iter_private.rs)
 - #67508 (Fix typo in path parser name)
 - #67519 (Document why Any is not an unsafe trait)
 - #67525 (Utilize rust-lang/rust commit hashes in toolstate)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rwxr-xr-xsrc/ci/publish_toolstate.sh7
-rw-r--r--src/libcore/any.rs10
-rw-r--r--src/libcore/iter_private.rs17
-rw-r--r--src/librustc/mir/interpret/mod.rs4
-rw-r--r--src/librustc/mir/interpret/queries.rs89
-rw-r--r--src/librustc/mir/interpret/value.rs38
-rw-r--r--src/librustc/query/mod.rs11
-rw-r--r--src/librustc/traits/fulfill.rs29
-rw-r--r--src/librustc/traits/select.rs22
-rw-r--r--src/librustc/ty/mod.rs10
-rw-r--r--src/librustc/ty/sty.rs12
-rw-r--r--src/librustc_codegen_llvm/consts.rs10
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs9
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs7
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs19
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs7
-rw-r--r--src/librustc_lint/builtin.rs12
-rw-r--r--src/librustc_mir/build/block.rs3
-rw-r--r--src/librustc_mir/build/cfg.rs5
-rw-r--r--src/librustc_mir/build/expr/into.rs28
-rw-r--r--src/librustc_mir/build/matches/mod.rs77
-rw-r--r--src/librustc_mir/build/matches/test.rs2
-rw-r--r--src/librustc_mir/build/matches/util.rs10
-rw-r--r--src/librustc_mir/build/mod.rs9
-rw-r--r--src/librustc_mir/build/scope.rs18
-rw-r--r--src/librustc_mir/const_eval.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs18
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs81
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs10
-rw-r--r--src/librustc_mir/interpret/operand.rs9
-rw-r--r--src/librustc_mir/interpret/place.rs7
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs38
-rw-r--r--src/librustc_parse/parser/path.rs4
-rw-r--r--src/librustc_typeck/check/expr.rs17
-rw-r--r--src/librustc_typeck/check/mod.rs10
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs43
-rw-r--r--src/librustdoc/clean/types.rs8
-rw-r--r--src/librustdoc/html/format.rs22
-rw-r--r--src/librustdoc/html/render.rs6
41 files changed, 320 insertions, 428 deletions
diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh
index d8ff7407822..4c047069571 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 a2aa6b3fea5..5126fe01a3f 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 890db47b197..00000000000
--- 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 fff876752db..80bac92d003 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 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 `<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))
+    }
+}
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index a038ca23ae9..f48d22291c6 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -237,13 +237,21 @@ impl<'tcx, Tag> Scalar<Tag> {
     }
 
     #[inline]
+    pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
+        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<u128>, 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<Tag> {
     }
 
     #[inline]
-    pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
+    pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
         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<i128>, 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 cc02165f605..a9dd856e758 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 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 @@ 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 f1cd002d19b..afc8a4d9e14 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 37a443a2c74..30356d59a7c 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<Discr<'tcx>> {
         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 02efe8df03d..604dc03ea17 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 e1750887ac4..78a86d33a14 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 e178050b369..e5a7583a8cc 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 dabd097b000..a532c23a6e0 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 fb8f504d04b..fc17e2c0c71 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 5b21dfbdf1c..98d239d353d 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 de541ef5af3..340af64adad 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 7353ca9285d..aceed09757e 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 6bd8d2f7c07..0e685486c3f 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 608415408e3..a9fa7cfa04a 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 bf0b2439c00..6869930509c 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 e320811ca05..bdc1bdd5b98 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 ec8b3c5e24b..87481d1d69b 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 6b6a58102fa..3b85a5d3c91 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 00a30af806a..9c5966263df 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 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 c05641fe8bf..589016a2ca2 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 9d0a67151fb..fdef6633925 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 67f0aed243d..46782ef0a80 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 93ab7b9aab7..0af203079b1 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -219,11 +219,20 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> {
     }
 
     #[inline]
+    pub fn try_from_uint(i: impl Into<u128>, layout: TyLayout<'tcx>) -> Option<Self> {
+        Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
+    }
+    #[inline]
     pub fn from_uint(i: impl Into<u128>, layout: TyLayout<'tcx>) -> Self {
         Self::from_scalar(Scalar::from_uint(i, layout.size), layout)
     }
 
     #[inline]
+    pub fn try_from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Option<Self> {
+        Some(Self::from_scalar(Scalar::try_from_int(i, layout.size)?, layout))
+    }
+
+    #[inline]
     pub fn from_int(i: impl Into<i128>, 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 8923b167fde..a1e6eb69b9d 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 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 83a4f224aa2..ac627d32392 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 802d38e2997..a768fdc779e 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::<<<<T as Foo>::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 17b168cfab0..a6ae10b3dea 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 5895b8d25d3..ea295103982 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 7ee1054dc48..b7e01708fbf 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 03fb0d99978..4afa0be55a6 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<Type> 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<Type> 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<Item> 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<Item> for doctree::Constant<'_> {
     }
 }
 
-impl Clean<Mutability> for hir::Mutability {
-    fn clean(&self, _: &DocContext<'_>) -> Mutability {
-        match self {
-            &hir::Mutability::Mut => Mutable,
-            &hir::Mutability::Not => Immutable,
-        }
-    }
-}
-
 impl Clean<ImplPolarity> for ty::ImplPolarity {
     fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
         match self {
@@ -2303,7 +2276,7 @@ impl Clean<Item> 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 bd3f2a3690a..706aef72031 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 fd620d467de..501147ed459 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 { "&quot;" };
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index e764b7ee527..100aed1af19 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)