diff --git a/RELEASES.md b/RELEASES.md
index 766cf64410c77..e6512bb6f6de9 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -47,8 +47,6 @@ Stabilized APIs
 - [`<*mut T>::cast`]
 - [`Duration::as_secs_f32`]
 - [`Duration::as_secs_f64`]
-- [`Duration::div_duration_f32`]
-- [`Duration::div_duration_f64`]
 - [`Duration::div_f32`]
 - [`Duration::div_f64`]
 - [`Duration::from_secs_f32`]
@@ -100,8 +98,6 @@ Compatibility Notes
 [`<*mut T>::cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
 [`Duration::as_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f32
 [`Duration::as_secs_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs_f64
-[`Duration::div_duration_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f32
-[`Duration::div_duration_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_duration_f64
 [`Duration::div_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f32
 [`Duration::div_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.div_f64
 [`Duration::from_secs_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_secs_f32
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 956cb36c6b139..d2cae4719d935 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -23,8 +23,6 @@ use syntax::source_map::Spanned;
 use syntax::ext::base::MacroKind;
 use syntax_pos::{Span, DUMMY_SP};
 
-use std::result::Result::Err;
-
 pub mod blocks;
 mod collector;
 mod def_collector;
@@ -183,6 +181,44 @@ pub struct Map<'hir> {
     hir_to_node_id: FxHashMap<HirId, NodeId>,
 }
 
+struct ParentHirIterator<'map> {
+    current_id: HirId,
+    map: &'map Map<'map>,
+}
+
+impl<'map> ParentHirIterator<'map> {
+    fn new(current_id: HirId, map: &'map Map<'map>) -> ParentHirIterator<'map> {
+        ParentHirIterator {
+            current_id,
+            map,
+        }
+    }
+}
+
+impl<'map> Iterator for ParentHirIterator<'map> {
+    type Item = (HirId, Node<'map>);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.current_id == CRATE_HIR_ID {
+            return None;
+        }
+        loop { // There are nodes that do not have entries, so we need to skip them.
+            let parent_id = self.map.get_parent_node(self.current_id);
+
+            if parent_id == self.current_id {
+                self.current_id = CRATE_HIR_ID;
+                return None;
+            }
+
+            self.current_id = parent_id;
+            if let Some(entry) = self.map.find_entry(parent_id) {
+                return Some((parent_id, entry.node));
+            }
+            // If this `HirId` doesn't have an `Entry`, skip it and look for its `parent_id`.
+        }
+    }
+}
+
 impl<'hir> Map<'hir> {
     #[inline]
     fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
@@ -682,45 +718,6 @@ impl<'hir> Map<'hir> {
         }
     }
 
-
-    /// If there is some error when walking the parents (e.g., a node does not
-    /// have a parent in the map or a node can't be found), then we return the
-    /// last good `HirId` we found. Note that reaching the crate root (`id == 0`),
-    /// is not an error, since items in the crate module have the crate root as
-    /// parent.
-    fn walk_parent_nodes<F, F2>(&self,
-                                start_id: HirId,
-                                found: F,
-                                bail_early: F2)
-        -> Result<HirId, HirId>
-        where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool
-    {
-        let mut id = start_id;
-        loop {
-            let parent_id = self.get_parent_node(id);
-            if parent_id == CRATE_HIR_ID {
-                return Ok(CRATE_HIR_ID);
-            }
-            if parent_id == id {
-                return Err(id);
-            }
-
-            if let Some(entry) = self.find_entry(parent_id) {
-                if let Node::Crate = entry.node {
-                    return Err(id);
-                }
-                if found(&entry.node) {
-                    return Ok(parent_id);
-                } else if bail_early(&entry.node) {
-                    return Err(parent_id);
-                }
-                id = parent_id;
-            } else {
-                return Err(id);
-            }
-        }
-    }
-
     /// Retrieves the `HirId` for `id`'s enclosing method, unless there's a
     /// `while` or `loop` before reaching it, as block tail returns are not
     /// available in them.
@@ -744,29 +741,46 @@ impl<'hir> Map<'hir> {
     /// }
     /// ```
     pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
-        let match_fn = |node: &Node<'_>| {
-            match *node {
+        let mut iter = ParentHirIterator::new(id, &self).peekable();
+        let mut ignore_tail = false;
+        if let Some(entry) = self.find_entry(id) {
+            if let Node::Expr(Expr { node: ExprKind::Ret(_), .. }) = entry.node {
+                // When dealing with `return` statements, we don't care about climbing only tail
+                // expressions.
+                ignore_tail = true;
+            }
+        }
+        while let Some((hir_id, node)) = iter.next() {
+            if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) {
+                match next_node {
+                    Node::Block(Block { expr: None, .. }) => return None,
+                    Node::Block(Block { expr: Some(expr), .. }) => {
+                        if hir_id != expr.hir_id {
+                            // The current node is not the tail expression of its parent.
+                            return None;
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            match node {
                 Node::Item(_) |
                 Node::ForeignItem(_) |
                 Node::TraitItem(_) |
                 Node::Expr(Expr { node: ExprKind::Closure(..), ..}) |
-                Node::ImplItem(_) => true,
-                _ => false,
-            }
-        };
-        let match_non_returning_block = |node: &Node<'_>| {
-            match *node {
+                Node::ImplItem(_) => return Some(hir_id),
                 Node::Expr(ref expr) => {
                     match expr.node {
-                        ExprKind::Loop(..) | ExprKind::Ret(..) => true,
-                        _ => false,
+                        // Ignore `return`s on the first iteration
+                        ExprKind::Ret(..) | ExprKind::Loop(..) => return None,
+                        _ => {}
                     }
                 }
-                _ => false,
+                Node::Local(_) => return None,
+                _ => {}
             }
-        };
-
-        self.walk_parent_nodes(id, match_fn, match_non_returning_block).ok()
+        }
+        None
     }
 
     /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
@@ -774,16 +788,17 @@ impl<'hir> Map<'hir> {
     /// in the HIR which is recorded by the map and is an item, either an item
     /// in a module, trait, or impl.
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
-        match self.walk_parent_nodes(hir_id, |node| match *node {
-            Node::Item(_) |
-            Node::ForeignItem(_) |
-            Node::TraitItem(_) |
-            Node::ImplItem(_) => true,
-            _ => false,
-        }, |_| false) {
-            Ok(id) => id,
-            Err(id) => id,
+        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+            match node {
+                Node::Crate |
+                Node::Item(_) |
+                Node::ForeignItem(_) |
+                Node::TraitItem(_) |
+                Node::ImplItem(_) => return hir_id,
+                _ => {}
+            }
         }
+        hir_id
     }
 
     /// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no
@@ -795,60 +810,64 @@ impl<'hir> Map<'hir> {
     /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
     /// module parent is in this map.
     pub fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
-        match self.walk_parent_nodes(hir_id, |node| match *node {
-            Node::Item(&Item { node: ItemKind::Mod(_), .. }) => true,
-            _ => false,
-        }, |_| false) {
-            Ok(id) => id,
-            Err(id) => id,
+        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+            if let Node::Item(&Item { node: ItemKind::Mod(_), .. }) = node {
+                return hir_id;
+            }
         }
+        CRATE_HIR_ID
     }
 
     /// Returns the nearest enclosing scope. A scope is roughly an item or block.
     pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
-        self.walk_parent_nodes(hir_id, |node| match *node {
-            Node::Item(i) => {
-                match i.node {
-                    ItemKind::Fn(..)
-                    | ItemKind::Mod(..)
-                    | ItemKind::Enum(..)
-                    | ItemKind::Struct(..)
-                    | ItemKind::Union(..)
-                    | ItemKind::Trait(..)
-                    | ItemKind::Impl(..) => true,
-                    _ => false,
-                }
-            },
-            Node::ForeignItem(fi) => {
-                match fi.node {
-                    ForeignItemKind::Fn(..) => true,
-                    _ => false,
-                }
-            },
-            Node::TraitItem(ti) => {
-                match ti.node {
-                    TraitItemKind::Method(..) => true,
-                    _ => false,
-                }
-            },
-            Node::ImplItem(ii) => {
-                match ii.node {
-                    ImplItemKind::Method(..) => true,
-                    _ => false,
-                }
-            },
-            Node::Block(_) => true,
-            _ => false,
-        }, |_| false).ok()
+        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+            if match node {
+                Node::Item(i) => {
+                    match i.node {
+                        ItemKind::Fn(..)
+                        | ItemKind::Mod(..)
+                        | ItemKind::Enum(..)
+                        | ItemKind::Struct(..)
+                        | ItemKind::Union(..)
+                        | ItemKind::Trait(..)
+                        | ItemKind::Impl(..) => true,
+                        _ => false,
+                    }
+                },
+                Node::ForeignItem(fi) => {
+                    match fi.node {
+                        ForeignItemKind::Fn(..) => true,
+                        _ => false,
+                    }
+                },
+                Node::TraitItem(ti) => {
+                    match ti.node {
+                        TraitItemKind::Method(..) => true,
+                        _ => false,
+                    }
+                },
+                Node::ImplItem(ii) => {
+                    match ii.node {
+                        ImplItemKind::Method(..) => true,
+                        _ => false,
+                    }
+                },
+                Node::Block(_) => true,
+                _ => false,
+            } {
+                return Some(hir_id);
+            }
+        }
+        None
     }
 
     /// Returns the defining scope for an opaque type definition.
-    pub fn get_defining_scope(&self, id: HirId) -> Option<HirId> {
+    pub fn get_defining_scope(&self, id: HirId) -> HirId {
         let mut scope = id;
         loop {
-            scope = self.get_enclosing_scope(scope)?;
+            scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
             if scope == CRATE_HIR_ID {
-                return Some(CRATE_HIR_ID);
+                return CRATE_HIR_ID;
             }
             match self.get(scope) {
                 Node::Item(i) => {
@@ -861,7 +880,7 @@ impl<'hir> Map<'hir> {
                 _ => break,
             }
         }
-        Some(scope)
+        scope
     }
 
     pub fn get_parent_did(&self, id: HirId) -> DefId {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 6fdc126e216aa..97c3e85cf9807 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1563,7 +1563,7 @@ pub enum ExprKind {
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
     /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
     MethodCall(P<PathSegment>, Span, HirVec<Expr>),
-    /// A tuple (e.g., `(a, b, c ,d)`).
+    /// A tuple (e.g., `(a, b, c, d)`).
     Tup(HirVec<Expr>),
     /// A binary operation (e.g., `a + b`, `a * b`).
     Binary(BinOp, P<Expr>, P<Expr>),
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 0b746e5dfb623..512d91f8d2646 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -1215,7 +1215,7 @@ pub fn may_define_opaque_type(
     let mut hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Named opaque types can be defined by any siblings or children of siblings.
-    let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope");
+    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
     // We walk up the node tree until we hit the root or the scope of the opaque type.
     while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
         hir_id = tcx.hir().get_parent_item(hir_id);
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index ac99ccd45eafe..71967b513a049 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -389,6 +389,10 @@ pub enum UnsupportedOpInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
 
+    /// FIXME(#64506) Error used to work around accessing projections of
+    /// uninhabited types.
+    UninhabitedValue,
+
     // -- Everything below is not categorized yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -552,6 +556,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
                     not a power of two"),
             Unsupported(ref msg) =>
                 write!(f, "{}", msg),
+            UninhabitedValue =>
+                write!(f, "tried to use an uninhabited value"),
         }
     }
 }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 039973d80dbf1..4696d4da58ec0 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -378,7 +378,15 @@ fn orphan_check_trait_ref<'tcx>(
         //      Let Ti be the first such type.
         //     - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
         //
-        for input_ty in trait_ref.input_types() {
+        fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec<Ty<'_>> {
+            if fundamental_ty(ty) {
+                ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect()
+            } else {
+                vec![ty]
+            }
+        }
+
+        for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) {
             debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
             if ty_is_local(tcx, input_ty, in_crate) {
                 debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index a1828bb5ab7a7..d3e6789b826a9 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -15,6 +15,7 @@ use errors::DiagnosticBuilder;
 use errors::Level;
 use errors::Diagnostic;
 use errors::FatalError;
+use errors::Handler;
 use rustc_data_structures::fx::{FxHashMap};
 use rustc_data_structures::sync::{Lrc, Lock};
 use rustc_data_structures::sharded::Sharded;
@@ -321,9 +322,12 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn try_print_query_stack() {
+    pub fn try_print_query_stack(handler: &Handler) {
         eprintln!("query stack during panic:");
 
+        // Be careful reyling on global state here: this code is called from
+        // a panic hook, which means that the global `Handler` may be in a weird
+        // state if it was responsible for triggering the panic.
         tls::with_context_opt(|icx| {
             if let Some(icx) = icx {
                 let mut current_query = icx.query.clone();
@@ -336,7 +340,7 @@ impl<'tcx> TyCtxt<'tcx> {
                                  query.info.query.name(),
                                  query.info.query.describe(icx.tcx)));
                     diag.span = icx.tcx.sess.source_map().def_span(query.info.span).into();
-                    icx.tcx.sess.diagnostic().force_print_diagnostic(diag);
+                    handler.force_print_diagnostic(diag);
 
                     current_query = query.parent.clone();
                     i += 1;
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4a8681367410e..d0a319df2e6dc 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1231,7 +1231,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
 
     if backtrace {
-        TyCtxt::try_print_query_stack();
+        TyCtxt::try_print_query_stack(&handler);
     }
 
     #[cfg(windows)]
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index ca238867421ab..bb02b99dd8d87 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -21,7 +21,7 @@ use syntax::source_map::{Span, DUMMY_SP};
 
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
-    RawConst, ConstValue,
+    RawConst, ConstValue, Machine,
     InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
     Allocation, AllocId, MemoryKind, Memory,
     snapshot, RefTracking, intern_const_alloc_recursive,
@@ -41,7 +41,7 @@ const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
 /// that inform us about the generic bounds of the constant. E.g., using an associated constant
 /// of a function's generic parameter will require knowledge about the bounds on the generic
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-pub(crate) fn mk_eval_cx<'mir, 'tcx>(
+fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
@@ -169,7 +169,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 }
 
 #[derive(Clone, Debug)]
-enum ConstEvalError {
+pub enum ConstEvalError {
     NeedsRfc(String),
 }
 
@@ -521,8 +521,8 @@ pub fn const_variant_index<'tcx>(
 /// Turn an interpreter error into something to report to the user.
 /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
 /// Should be called only if the error is actually going to to be reported!
-pub fn error_to_const_error<'mir, 'tcx>(
-    ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+pub fn error_to_const_error<'mir, 'tcx, M: Machine<'mir, 'tcx>>(
+    ecx: &InterpCx<'mir, 'tcx, M>,
     mut error: InterpErrorInfo<'tcx>,
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index bb74a50156e56..c30c59bbf10c8 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -12,6 +12,7 @@ use rustc::ty::{self, Ty, TyCtxt};
 use super::{
     Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
     InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
+    Frame, Operand,
 };
 
 /// Whether this kind of memory is allowed to leak
@@ -184,6 +185,22 @@ pub trait Machine<'mir, 'tcx>: Sized {
         dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> InterpResult<'tcx>;
 
+    /// Called to read the specified `local` from the `frame`.
+    fn access_local(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
+        local: mir::Local,
+    ) -> InterpResult<'tcx, Operand<Self::PointerTag>> {
+        frame.locals[local].access()
+    }
+
+    /// Called before a `StaticKind::Static` value is accessed.
+    fn before_access_static(
+        _allocation: &Allocation,
+    ) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
     /// Called to initialize the "extra" state of an allocation and make the pointers
     /// it contains (in relocations) tagged.  The way we construct allocations is
     /// to always first construct it without extra and then add the extra.
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 62b1760508b4c..924474c53175c 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -462,6 +462,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     // Make sure we use the ID of the resolved memory, not the lazy one!
                     let id = raw_const.alloc_id;
                     let allocation = tcx.alloc_map.lock().unwrap_memory(id);
+
+                    M::before_access_static(allocation)?;
                     Cow::Borrowed(allocation)
                 }
             }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index f5d1ec3eb7556..861e5ebef877d 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -458,7 +458,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Do not read from ZST, they might not be initialized
             Operand::Immediate(Scalar::zst().into())
         } else {
-            frame.locals[local].access()?
+            M::access_local(&self, frame, local)?
         };
         Ok(OpTy { op, layout })
     }
@@ -481,7 +481,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     // Evaluate a place with the goal of reading from it.  This lets us sometimes
     // avoid allocations.
-    pub(super) fn eval_place_to_op(
+    pub fn eval_place_to_op(
         &self,
         place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 2f1b35757fe9c..1166ca9bf2444 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -9,7 +9,7 @@ use rustc::mir;
 use rustc::mir::interpret::truncate;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{
-    self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
+    self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
 };
 use rustc::ty::TypeFoldable;
 
@@ -385,6 +385,10 @@ where
                 stride * field
             }
             layout::FieldPlacement::Union(count) => {
+                // FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved
+                if base.layout.abi == Abi::Uninhabited {
+                    throw_unsup!(UninhabitedValue);
+                }
                 assert!(field < count as u64,
                         "Tried to access field {} of union with {} fields", field, count);
                 // Offset is always 0
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index affca10bf5265..daca7a25787ca 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -132,7 +132,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ///
     /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
     /// type writes its results directly into the memory specified by the place.
-    fn eval_rvalue_into_place(
+    pub fn eval_rvalue_into_place(
         &mut self,
         rvalue: &mir::Rvalue<'tcx>,
         place: &mir::Place<'tcx>,
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 857757ada53b7..612822b6d9d34 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -1,22 +1,26 @@
 //! Propagates constants for early reporting of statically known
 //! assertion failures
 
+use std::borrow::Cow;
 use std::cell::Cell;
 
 use rustc::hir::def::DefKind;
+use rustc::hir::def_id::DefId;
 use rustc::mir::{
     AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
-    Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
-    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
-    SourceScope, SourceScopeLocalData, LocalDecl,
+    Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
+    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp,
+    SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
 };
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
+use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
+use syntax::ast::Mutability;
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::layout::{
     LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout,
@@ -24,11 +28,11 @@ use rustc::ty::layout::{
 
 use crate::interpret::{
     self, InterpCx, ScalarMaybeUndef, Immediate, OpTy,
-    ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
-};
-use crate::const_eval::{
-    CompileTimeInterpreter, error_to_const_error, mk_eval_cx,
+    StackPopCleanup, LocalValue, LocalState, AllocId, Frame,
+    Allocation, MemoryKind, ImmTy, Pointer, Memory, PlaceTy,
+    Operand as InterpOperand,
 };
+use crate::const_eval::error_to_const_error;
 use crate::transform::{MirPass, MirSource};
 
 pub struct ConstProp;
@@ -57,6 +61,14 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return
         }
 
+        let is_generator = tcx.type_of(source.def_id()).is_generator();
+        // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
+        // computing their layout.
+        if is_generator {
+            trace!("ConstProp skipped for generator {:?}", source.def_id());
+            return
+        }
+
         trace!("ConstProp starting for {:?}", source.def_id());
 
         // Steal some data we need from `body`.
@@ -103,11 +115,154 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
     }
 }
 
+struct ConstPropMachine;
+
+impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
+    type MemoryKinds= !;
+    type PointerTag = ();
+    type ExtraFnVal = !;
+
+    type FrameExtra = ();
+    type MemoryExtra = ();
+    type AllocExtra = ();
+
+    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
+
+    const STATIC_KIND: Option<!> = None;
+
+    const CHECK_ALIGN: bool = false;
+
+    #[inline(always)]
+    fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+        false
+    }
+
+    fn find_fn(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _instance: ty::Instance<'tcx>,
+        _args: &[OpTy<'tcx>],
+        _dest: Option<PlaceTy<'tcx>>,
+        _ret: Option<BasicBlock>,
+    ) -> InterpResult<'tcx, Option<&'mir Body<'tcx>>> {
+        Ok(None)
+    }
+
+    fn call_extra_fn(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        fn_val: !,
+        _args: &[OpTy<'tcx>],
+        _dest: Option<PlaceTy<'tcx>>,
+        _ret: Option<BasicBlock>,
+    ) -> InterpResult<'tcx> {
+        match fn_val {}
+    }
+
+    fn call_intrinsic(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _instance: ty::Instance<'tcx>,
+        _args: &[OpTy<'tcx>],
+        _dest: PlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("calling intrinsics isn't supported in ConstProp");
+    }
+
+    fn ptr_to_int(
+        _mem: &Memory<'mir, 'tcx, Self>,
+        _ptr: Pointer,
+    ) -> InterpResult<'tcx, u64> {
+        throw_unsup_format!("ptr-to-int casts aren't supported in ConstProp");
+    }
+
+    fn binary_ptr_op(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _bin_op: BinOp,
+        _left: ImmTy<'tcx>,
+        _right: ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
+        // We can't do this because aliasing of memory can differ between const eval and llvm
+        throw_unsup_format!("pointer arithmetic or comparisons aren't supported in ConstProp");
+    }
+
+    fn find_foreign_static(
+        _tcx: TyCtxt<'tcx>,
+        _def_id: DefId,
+    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
+        throw_unsup!(ReadForeignStatic)
+    }
+
+    #[inline(always)]
+    fn tag_allocation<'b>(
+        _memory_extra: &(),
+        _id: AllocId,
+        alloc: Cow<'b, Allocation>,
+        _kind: Option<MemoryKind<!>>,
+    ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
+        // We do not use a tag so we can just cheaply forward the allocation
+        (alloc, ())
+    }
+
+    #[inline(always)]
+    fn tag_static_base_pointer(
+        _memory_extra: &(),
+        _id: AllocId,
+    ) -> Self::PointerTag {
+        ()
+    }
+
+    fn box_alloc(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _dest: PlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("can't const prop `box` keyword");
+    }
+
+    fn access_local(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
+        local: Local,
+    ) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> {
+        let l = &frame.locals[local];
+
+        if l.value == LocalValue::Uninitialized {
+            throw_unsup_format!("tried to access an uninitialized local");
+        }
+
+        l.access()
+    }
+
+    fn before_access_static(
+        allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
+    ) -> InterpResult<'tcx> {
+        // if the static allocation is mutable or if it has relocations (it may be legal to mutate
+        // the memory behind that in the future), then we can't const prop it
+        if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 {
+            throw_unsup_format!("can't eval mutable statics in ConstProp");
+        }
+
+        Ok(())
+    }
+
+    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
+    #[inline(always)]
+    fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
+    /// Called immediately before a stack frame gets popped.
+    #[inline(always)]
+    fn stack_pop(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
+        Ok(())
+    }
+}
+
 type Const<'tcx> = OpTy<'tcx>;
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
-    ecx: InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+    ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
     tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
     can_const_prop: IndexVec<Local, bool>,
@@ -150,7 +305,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         let def_id = source.def_id();
         let param_env = tcx.param_env(def_id);
         let span = tcx.def_span(def_id);
-        let mut ecx = mk_eval_cx(tcx, span, param_env);
+        let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ());
         let can_const_prop = CanConstProp::check(body);
 
         ecx.push_stack_frame(
@@ -282,53 +437,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        let mut eval = match place.base {
-            PlaceBase::Local(loc) => self.get_const(loc).clone()?,
-            PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
-                let generics = self.tcx.generics_of(self.source.def_id());
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
-                }
-                let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
-                let instance = Instance::new(self.source.def_id(), substs);
-                let cid = GlobalId {
-                    instance,
-                    promoted: Some(promoted),
-                };
-                let res = self.use_ecx(source_info, |this| {
-                    this.ecx.const_eval_raw(cid)
-                })?;
-                trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                res.into()
-            }
-            _ => return None,
-        };
-
-        for (i, elem) in place.projection.iter().enumerate() {
-            let proj_base = &place.projection[..i];
-
-            match elem {
-                ProjectionElem::Field(field, _) => {
-                    trace!("field proj on {:?}", proj_base);
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.operand_field(eval, field.index() as u64)
-                    })?;
-                },
-                ProjectionElem::Deref => {
-                    trace!("processing deref");
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.deref_operand(eval)
-                    })?.into();
-                }
-                // We could get more projections by using e.g., `operand_projection`,
-                // but we do not even have the stack frame set up properly so
-                // an `Index` projection would throw us off-track.
-                _ => return None,
-            }
-        }
-
-        Some(eval)
+        self.use_ecx(source_info, |this| {
+            this.ecx.eval_place_to_op(place, None)
+        })
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
@@ -344,166 +455,118 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         rvalue: &Rvalue<'tcx>,
         place_layout: TyLayout<'tcx>,
         source_info: SourceInfo,
+        place: &Place<'tcx>,
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
-        match *rvalue {
-            Rvalue::Use(ref op) => {
-                self.eval_operand(op, source_info)
-            },
-            Rvalue::Ref(_, _, ref place) => {
-                let src = self.eval_place(place, source_info)?;
-                let mplace = src.try_as_mplace().ok()?;
-                Some(ImmTy::from_scalar(mplace.ptr.into(), place_layout).into())
-            },
+
+        // if this isn't a supported operation, then return None
+        match rvalue {
             Rvalue::Repeat(..) |
             Rvalue::Aggregate(..) |
             Rvalue::NullaryOp(NullOp::Box, _) |
-            Rvalue::Discriminant(..) => None,
-
-            Rvalue::Cast(kind, ref operand, _) => {
-                let op = self.eval_operand(operand, source_info)?;
-                self.use_ecx(source_info, |this| {
-                    let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
-                    this.ecx.cast(op, kind, dest.into())?;
-                    Ok(dest.into())
-                })
-            },
-            Rvalue::Len(ref place) => {
-                let place = self.eval_place(&place, source_info)?;
-                let mplace = place.try_as_mplace().ok()?;
-
-                if let ty::Slice(_) = mplace.layout.ty.kind {
-                    let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
-
-                    Some(ImmTy::from_uint(
-                        len,
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ).into())
-                } else {
-                    trace!("not slice: {:?}", mplace.layout.ty.kind);
-                    None
-                }
-            },
-            Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
-                type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
-                    ImmTy::from_uint(
-                        n,
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ).into()
-                ))
-            }
-            Rvalue::UnaryOp(op, ref arg) => {
-                let def_id = if self.tcx.is_closure(self.source.def_id()) {
-                    self.tcx.closure_base_def_id(self.source.def_id())
-                } else {
-                    self.source.def_id()
-                };
-                let generics = self.tcx.generics_of(def_id);
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
-                }
+            Rvalue::Discriminant(..) => return None,
+
+            Rvalue::Use(_) |
+            Rvalue::Len(_) |
+            Rvalue::Cast(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::Ref(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::BinaryOp(..) => { }
+        }
 
-                let arg = self.eval_operand(arg, source_info)?;
-                let oflo_check = self.tcx.sess.overflow_checks();
-                let val = self.use_ecx(source_info, |this| {
-                    let prim = this.ecx.read_immediate(arg)?;
-                    match op {
-                        UnOp::Neg => {
-                            // We check overflow in debug mode already
-                            // so should only check in release mode.
-                            if !oflo_check
-                            && prim.layout.ty.is_signed()
-                            && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                                throw_panic!(OverflowNeg)
-                            }
-                        }
-                        UnOp::Not => {
-                            // Cannot overflow
+        // perform any special checking for specific Rvalue types
+        if let Rvalue::UnaryOp(op, arg) = rvalue {
+            trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
+            let overflow_check = self.tcx.sess.overflow_checks();
+
+            self.use_ecx(source_info, |this| {
+                // We check overflow in debug mode already
+                // so should only check in release mode.
+                if *op == UnOp::Neg && !overflow_check {
+                    let ty = arg.ty(&this.local_decls, this.tcx);
+
+                    if ty.is_integral() {
+                        let arg = this.ecx.eval_operand(arg, None)?;
+                        let prim = this.ecx.read_immediate(arg)?;
+                        // Need to do overflow check here: For actual CTFE, MIR
+                        // generation emits code that does this before calling the op.
+                        if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
+                            throw_panic!(OverflowNeg)
                         }
                     }
-                    // Now run the actual operation.
-                    this.ecx.unary_op(op, prim)
-                })?;
-                Some(val.into())
-            }
-            Rvalue::CheckedBinaryOp(op, ref left, ref right) |
-            Rvalue::BinaryOp(op, ref left, ref right) => {
-                trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
-                let right = self.eval_operand(right, source_info)?;
-                let def_id = if self.tcx.is_closure(self.source.def_id()) {
-                    self.tcx.closure_base_def_id(self.source.def_id())
-                } else {
-                    self.source.def_id()
-                };
-                let generics = self.tcx.generics_of(def_id);
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
+                }
+
+                Ok(())
+            })?;
+        } else if let Rvalue::BinaryOp(op, left, right) = rvalue {
+            trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
+
+            let r = self.use_ecx(source_info, |this| {
+                this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
+            })?;
+            if *op == BinOp::Shr || *op == BinOp::Shl {
+                let left_bits = place_layout.size.bits();
+                let right_size = r.layout.size;
+                let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
+                if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
+                    let source_scope_local_data = match self.source_scope_local_data {
+                        ClearCrossCrate::Set(ref data) => data,
+                        ClearCrossCrate::Clear => return None,
+                    };
+                    let dir = if *op == BinOp::Shr {
+                        "right"
+                    } else {
+                        "left"
+                    };
+                    let hir_id = source_scope_local_data[source_info.scope].lint_root;
+                    self.tcx.lint_hir(
+                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
+                        hir_id,
+                        span,
+                        &format!("attempt to shift {} with overflow", dir));
                     return None;
                 }
+            }
+            self.use_ecx(source_info, |this| {
+                let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
+                let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
+
+                // We check overflow in debug mode already
+                // so should only check in release mode.
+                if !this.tcx.sess.overflow_checks() && overflow {
+                    let err = err_panic!(Overflow(*op)).into();
+                    return Err(err);
+                }
 
-                let r = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(right)
-                })?;
-                if op == BinOp::Shr || op == BinOp::Shl {
-                    let left_ty = left.ty(&self.local_decls, self.tcx);
-                    let left_bits = self
-                        .tcx
-                        .layout_of(self.param_env.and(left_ty))
-                        .unwrap()
-                        .size
-                        .bits();
-                    let right_size = right.layout.size;
-                    let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
-                    if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
-                        let source_scope_local_data = match self.source_scope_local_data {
-                            ClearCrossCrate::Set(ref data) => data,
-                            ClearCrossCrate::Clear => return None,
-                        };
-                        let dir = if op == BinOp::Shr {
-                            "right"
-                        } else {
-                            "left"
-                        };
-                        let hir_id = source_scope_local_data[source_info.scope].lint_root;
-                        self.tcx.lint_hir(
-                            ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
-                            hir_id,
-                            span,
-                            &format!("attempt to shift {} with overflow", dir));
-                        return None;
-                    }
+                Ok(())
+            })?;
+        } else if let Rvalue::Ref(_, _, place) = rvalue {
+            trace!("checking Ref({:?})", place);
+            // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
+            // from a function argument that hasn't been assigned to in this function.
+            if let Place {
+                base: PlaceBase::Local(local),
+                projection: box []
+            } = place {
+                let alive =
+                    if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
+                        true
+                    } else { false };
+
+                if local.as_usize() <= self.ecx.frame().body.arg_count && !alive {
+                    trace!("skipping Ref({:?})", place);
+                    return None;
                 }
-                let left = self.eval_operand(left, source_info)?;
-                let l = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(left)
-                })?;
-                trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
-                let (val, overflow, _ty) = self.use_ecx(source_info, |this| {
-                    this.ecx.overflowing_binary_op(op, l, r)
-                })?;
-                let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
-                    Immediate::ScalarPair(
-                        val.into(),
-                        Scalar::from_bool(overflow).into(),
-                    )
-                } else {
-                    // We check overflow in debug mode already
-                    // so should only check in release mode.
-                    if !self.tcx.sess.overflow_checks() && overflow {
-                        let err = err_panic!(Overflow(op)).into();
-                        let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
-                        return None;
-                    }
-                    Immediate::Scalar(val.into())
-                };
-                let res = ImmTy {
-                    imm: val,
-                    layout: place_layout,
-                };
-                Some(res.into())
-            },
+            }
         }
+
+        self.use_ecx(source_info, |this| {
+            trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place);
+            this.ecx.eval_rvalue_into_place(rvalue, place)?;
+            this.ecx.eval_place_to_op(place, Some(place_layout))
+        })
     }
 
     fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Operand<'tcx> {
@@ -577,14 +640,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     }
 }
 
-fn type_size_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<u64> {
-    tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
-}
-
 struct CanConstProp {
     can_const_prop: IndexVec<Local, bool>,
     // false at the beginning, once set, there are not allowed to be any more assignments
@@ -670,15 +725,19 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                 .ty(&self.local_decls, self.tcx)
                 .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
-                if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
-                    if let Place {
-                        base: PlaceBase::Local(local),
-                        projection: box [],
-                    } = *place {
+                if let Place {
+                    base: PlaceBase::Local(local),
+                    projection: box [],
+                } = *place {
+                    if let Some(value) = self.const_prop(rval,
+                                                         place_layout,
+                                                         statement.source_info,
+                                                         place) {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
-                            assert!(self.get_const(local).is_none());
+                            assert!(self.get_const(local).is_none() ||
+                                    self.get_const(local) == Some(value));
                             self.set_const(local, value);
 
                             if self.should_const_prop() {
@@ -692,7 +751,22 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                     }
                 }
             }
+        } else {
+            match statement.kind {
+                StatementKind::StorageLive(local) |
+                StatementKind::StorageDead(local) if self.can_const_prop[local] => {
+                    let frame = self.ecx.frame_mut();
+                    frame.locals[local].value =
+                        if let StatementKind::StorageLive(_) = statement.kind {
+                            LocalValue::Uninitialized
+                        } else {
+                            LocalValue::Dead
+                        };
+                }
+                _ => {}
+            }
         }
+
         self.super_statement(statement, location);
     }
 
diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs
index 8c02bc61088b4..b9549ec2120dd 100644
--- a/src/librustc_target/spec/aarch64_unknown_none.rs
+++ b/src/librustc_target/spec/aarch64_unknown_none.rs
@@ -1,4 +1,4 @@
-// Generic AArch64 target for bare-metal code
+// Generic AArch64 target for bare-metal code - Floating point enabled
 //
 // Can be used in conjunction with the `target-feature` and
 // `target-cpu` compiler flags to opt-in more hardware-specific
@@ -11,7 +11,7 @@ use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy};
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
         linker: Some("rust-lld".to_owned()),
-        features: "+strict-align".to_string(),
+        features: "+strict-align,+neon,+fp-armv8".to_string(),
         executables: true,
         relocation_model: "static".to_string(),
         disable_redzone: true,
diff --git a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs
new file mode 100644
index 0000000000000..b91f2af68ecb8
--- /dev/null
+++ b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs
@@ -0,0 +1,37 @@
+// Generic AArch64 target for bare-metal code - Floating point disabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+//
+// For example, `-C target-cpu=cortex-a53`.
+
+use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy};
+
+pub fn target() -> Result<Target, String> {
+    let opts = TargetOptions {
+        linker: Some("rust-lld".to_owned()),
+        features: "+strict-align,-neon,-fp-armv8".to_string(),
+        executables: true,
+        relocation_model: "static".to_string(),
+        disable_redzone: true,
+        linker_is_gnu: true,
+        max_atomic_width: Some(128),
+        panic_strategy: PanicStrategy::Abort,
+        abi_blacklist: super::arm_base::abi_blacklist(),
+        .. Default::default()
+    };
+    Ok(Target {
+        llvm_target: "aarch64-unknown-none".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: String::new(),
+        target_vendor: String::new(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+        options: opts,
+    })
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 626fa374a1bd4..25add0cc6a4be 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -489,6 +489,7 @@ supported_targets! {
     ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
 
     ("aarch64-unknown-none", aarch64_unknown_none),
+    ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
 
     ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
 
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 97fcfd7151a1c..27fdd6caa2b0a 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -620,8 +620,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr
     ) -> Ty<'tcx> {
         if self.ret_coercion.is_none() {
-            struct_span_err!(self.tcx.sess, expr.span, E0572,
-                                "return statement outside of function body").emit();
+            struct_span_err!(
+                self.tcx.sess,
+                expr.span,
+                E0572,
+                "return statement outside of function body",
+            ).emit();
         } else if let Some(ref e) = expr_opt {
             if self.ret_coercion_span.borrow().is_none() {
                 *self.ret_coercion_span.borrow_mut() = Some(e.span);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 82d55e0df599b..9c7d2736e197f 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1717,9 +1717,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     }
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
-    let scope = tcx.hir()
-        .get_defining_scope(hir_id)
-        .expect("could not get defining scope");
+    let scope = tcx.hir().get_defining_scope(hir_id);
     let mut locator = ConstraintLocator {
         def_id,
         tcx,
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 8758ab1969116..853170542e083 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -35,7 +35,7 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
                 match ty {
                     clean::Generic(s) => params.entry(s).or_default()
                                                .extend(bounds),
-                    t => tybounds.push((t, ty_bounds(bounds))),
+                    t => tybounds.push((t, bounds)),
                 }
             }
             WP::RegionPredicate { lifetime, bounds } => {
@@ -45,11 +45,6 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
         }
     }
 
-    // Simplify the type parameter bounds on all the generics
-    let mut params = params.into_iter().map(|(k, v)| {
-        (k, ty_bounds(v))
-    }).collect::<BTreeMap<_, _>>();
-
     // Look for equality predicates on associated types that can be merged into
     // general bound predicates
     equalities.retain(|&(ref lhs, ref rhs)| {
@@ -73,7 +68,7 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
     // And finally, let's reassemble everything
     let mut clauses = Vec::new();
     clauses.extend(lifetimes.into_iter().map(|(lt, bounds)| {
-        WP::RegionPredicate { lifetime: lt, bounds: bounds }
+        WP::RegionPredicate { lifetime: lt, bounds }
     }));
     clauses.extend(params.into_iter().map(|(k, v)| {
         WP::BoundPredicate {
@@ -82,10 +77,10 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
         }
     }));
     clauses.extend(tybounds.into_iter().map(|(ty, bounds)| {
-        WP::BoundPredicate { ty: ty, bounds: bounds }
+        WP::BoundPredicate { ty, bounds }
     }));
     clauses.extend(equalities.into_iter().map(|(lhs, rhs)| {
-        WP::EqPredicate { lhs: lhs, rhs: rhs }
+        WP::EqPredicate { lhs, rhs }
     }));
     clauses
 }
@@ -122,9 +117,9 @@ pub fn merge_bounds(
                     },
                 });
             }
-            PP::Parenthesized { ref mut output, .. } => {
-                assert!(output.is_none());
-                if *rhs != clean::Type::Tuple(Vec::new()) {
+            PP::Parenthesized { ref mut output, .. } => match output {
+                Some(o) => assert_eq!(o, rhs),
+                None => if *rhs != clean::Type::Tuple(Vec::new()) {
                     *output = Some(rhs.clone());
                 }
             }
@@ -137,7 +132,7 @@ pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericP
     for param in &mut params {
         match param.kind {
             clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
-                *bounds = ty_bounds(mem::take(bounds));
+                *bounds = mem::take(bounds);
             }
             _ => panic!("expected only type parameters"),
         }
@@ -145,10 +140,6 @@ pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericP
     params
 }
 
-fn ty_bounds(bounds: Vec<clean::GenericBound>) -> Vec<clean::GenericBound> {
-    bounds
-}
-
 fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId,
                                trait_: DefId) -> bool {
     if child == trait_ {
diff --git a/src/libstd/sys/vxworks/process/process_vxworks.rs b/src/libstd/sys/vxworks/process/process_vxworks.rs
index beb20aa48169a..7446471ae3122 100644
--- a/src/libstd/sys/vxworks/process/process_vxworks.rs
+++ b/src/libstd/sys/vxworks/process/process_vxworks.rs
@@ -54,8 +54,8 @@ impl Command {
 
             let ret = libc::rtpSpawn(
                 self.get_argv()[0],                   // executing program
-                self.get_argv().as_ptr() as *const _, // argv
-                *sys::os::environ() as *const *const c_char,
+                self.get_argv().as_ptr() as *mut *const c_char, // argv
+                *sys::os::environ() as *mut *const c_char,
                 100 as c_int,                         // initial priority
                 thread::min_stack(),                  // initial stack size.
                 0,                                    // options
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 2765346b333cf..8fc64021b51fc 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -695,7 +695,7 @@ impl<'a, 'b> Context<'a, 'b> {
         // Now create a vector containing all the arguments
         let args = locals.into_iter().chain(counts.into_iter());
 
-        let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());
+        let args_array = self.ecx.expr_vec(self.macsp, args.collect());
 
         // Constructs an AST equivalent to:
         //
@@ -724,12 +724,12 @@ impl<'a, 'b> Context<'a, 'b> {
         //
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
-        let pat = self.ecx.pat_tuple(self.fmtsp, pats);
-        let arm = self.ecx.arm(self.fmtsp, pat, args_array);
-        let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
-        let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
+        let pat = self.ecx.pat_tuple(self.macsp, pats);
+        let arm = self.ecx.arm(self.macsp, pat, args_array);
+        let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
+        let result = self.ecx.expr_match(self.macsp, head, vec![arm]);
 
-        let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
+        let args_slice = self.ecx.expr_addr_of(self.macsp, result);
 
         // Now create the fmt::Arguments struct with all our locals we created.
         let (fn_name, fn_args) = if self.all_pieces_simple {
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index e441514e59738..bcda5384204d8 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -1546,6 +1546,7 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) ->
                 }
             }
         }
+        (&ShouldPanic::Yes, Ok(())) => TrFailedMsg("test did not panic as expected".to_string()),
         _ if desc.allow_fail => TrAllowedFail,
         _ => TrFailed,
     }
diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs
index 13ac8eb91f411..38ec7bd70930c 100644
--- a/src/libtest/tests.rs
+++ b/src/libtest/tests.rs
@@ -2,7 +2,7 @@ use super::*;
 
 use crate::test::{
     filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
-    ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
+    ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailedMsg,
     TrIgnored, TrOk,
 };
 use std::sync::mpsc::channel;
@@ -167,7 +167,7 @@ fn test_should_panic_but_succeeds() {
     let (tx, rx) = channel();
     run_test(&TestOpts::new(), false, desc, tx, Concurrent::No);
     let (_, res, _, _) = rx.recv().unwrap();
-    assert!(res == TrFailed);
+    assert!(res == TrFailedMsg("test did not panic as expected".to_string()));
 }
 
 fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
new file mode 100644
index 0000000000000..d16f812ad95db
--- /dev/null
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -0,0 +1,27 @@
+static FOO: u8 = 2;
+
+fn main() {
+    let x = FOO + FOO;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _2 = (FOO: u8);
+//      ...
+//      _3 = (FOO: u8);
+//      _1 = Add(move _2, move _3);
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _2 = const 2u8;
+//      ...
+//      _3 = const 2u8;
+//      _1 = Add(move _2, move _3);
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
index 7e36b2a6b1b39..e9b61690cf89e 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
@@ -16,7 +16,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(AllocId(1).0x0) : fn();
+//      _3 = const Scalar(AllocId(0).0x0) : fn();
 //      _2 = move _3 as usize (Misc);
 //      ...
 //      _1 = move _2 as *const fn() (Misc);
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 5babeb195a826..05595ce147c96 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -34,7 +34,7 @@ fn main() {
 //      assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
 //  }
 //  bb1: {
-//      _1 = (*_2)[_6];
+//      _1 = const 2u32;
 //      ...
 //      return;
 //  }
diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs
index c69da0f49adf1..37fbf01e487dc 100644
--- a/src/test/run-fail/overflowing-lsh-1.rs
+++ b/src/test/run-fail/overflowing-lsh-1.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1_i32 << 32;
diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs
index 21659bd52393a..7b0b37dfed043 100644
--- a/src/test/run-fail/overflowing-lsh-2.rs
+++ b/src/test/run-fail/overflowing-lsh-2.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1 << -1;
diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs
index 8f06cd1153354..1768a8e6d3138 100644
--- a/src/test/run-fail/overflowing-lsh-3.rs
+++ b/src/test/run-fail/overflowing-lsh-3.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1_u64 << 64;
diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs
index 084c147094dee..ec304b4144e0f 100644
--- a/src/test/run-fail/overflowing-lsh-4.rs
+++ b/src/test/run-fail/overflowing-lsh-4.rs
@@ -5,6 +5,7 @@
 // sidestep the overflow checking.
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     // this signals overflow when checking is on
diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs
index 24a77da896d9e..14514540c06e1 100644
--- a/src/test/run-fail/overflowing-rsh-1.rs
+++ b/src/test/run-fail/overflowing-rsh-1.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i32 >> 32;
diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs
index b5615cacc2055..83dcbd13d2ad8 100644
--- a/src/test/run-fail/overflowing-rsh-2.rs
+++ b/src/test/run-fail/overflowing-rsh-2.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i32 >> -1;
diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs
index 7598e026d8139..3521c0506591c 100644
--- a/src/test/run-fail/overflowing-rsh-3.rs
+++ b/src/test/run-fail/overflowing-rsh-3.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i64 >> 64;
diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs
index a8d3b69392a97..ed1191849e57c 100644
--- a/src/test/run-fail/overflowing-rsh-4.rs
+++ b/src/test/run-fail/overflowing-rsh-4.rs
@@ -5,6 +5,7 @@
 // truncation does not sidestep the overflow checking.
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     // this signals overflow when checking is on
diff --git a/src/test/rustdoc/auxiliary/issue-57180.rs b/src/test/rustdoc/auxiliary/issue-57180.rs
new file mode 100644
index 0000000000000..4e2f4b87c020e
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-57180.rs
@@ -0,0 +1,16 @@
+// compile-flags: -Cmetadata=aux
+
+pub trait Trait {
+}
+
+pub struct Struct<F>
+{
+    _p: ::std::marker::PhantomData<F>,
+}
+
+impl<F: Fn() -> u32>
+Trait for Struct<F>
+    where
+        F: Fn() -> u32,
+{
+}
diff --git a/src/test/rustdoc/issue-57180.rs b/src/test/rustdoc/issue-57180.rs
new file mode 100644
index 0000000000000..14bd2b0fec0d5
--- /dev/null
+++ b/src/test/rustdoc/issue-57180.rs
@@ -0,0 +1,7 @@
+// aux-build:issue-57180.rs
+
+extern crate issue_57180;
+use issue_57180::Trait;
+
+fn main() {
+}
diff --git a/src/test/ui/coherence/auxiliary/coherence_lib.rs b/src/test/ui/coherence/auxiliary/coherence_lib.rs
index 9a5ec82430639..c22819831ab24 100644
--- a/src/test/ui/coherence/auxiliary/coherence_lib.rs
+++ b/src/test/ui/coherence/auxiliary/coherence_lib.rs
@@ -5,11 +5,11 @@ pub trait Remote {
 }
 
 pub trait Remote1<T> {
-    fn foo(&self, t: T) { }
+    fn foo(&self, _t: T) { }
 }
 
 pub trait Remote2<T, U> {
-    fn foo(&self, t: T, u: U) { }
+    fn foo(&self, _t: T, _u: U) { }
 }
 
 pub struct Pair<T,U>(T,U);
diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs
new file mode 100644
index 0000000000000..b08fedc5e11c2
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote1<u32> for f64 {
+    //~^ ERROR only traits defined in the current crate
+    // | can be implemented for arbitrary types [E0117]
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
new file mode 100644
index 0000000000000..04e96f29230fb
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr
@@ -0,0 +1,12 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/impl-foreign[foreign]-for-foreign.rs:12:1
+   |
+LL | impl Remote1<u32> for f64 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
+   |
+   = note: the impl does not reference only types defined in this crate
+   = note: define and implement a trait or new type instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs
new file mode 100644
index 0000000000000..33e85c164763e
--- /dev/null
+++ b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote1<u32> for Local {
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs
new file mode 100644
index 0000000000000..54d4bf04a583c
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs
@@ -0,0 +1,14 @@
+#![feature(re_rebalance_coherence)]
+
+// check-pass
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+impl<T> Remote2<Rc<T>, Local> for usize { }
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs
new file mode 100644
index 0000000000000..66a4d9d273469
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs
@@ -0,0 +1,20 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<u32> for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+impl<'a, T> Remote1<u32> for &'a T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr
new file mode 100644
index 0000000000000..2467097b1a8b3
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:12:1
+   |
+LL | impl<T> Remote1<u32> for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:16:1
+   |
+LL | impl<'a, T> Remote1<u32> for &'a T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs
new file mode 100644
index 0000000000000..0a67ebcbba44c
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<u32> for T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
new file mode 100644
index 0000000000000..5c28406f113fc
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[foreign]-for-t.rs:12:1
+   |
+LL | impl<T> Remote1<u32> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs
new file mode 100644
index 0000000000000..71598dae96ab3
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs
@@ -0,0 +1,20 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Box<T>> for u32 {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+impl<'a, T> Remote1<&'a T> for u32 {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr
new file mode 100644
index 0000000000000..dd9702650795e
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:12:1
+   |
+LL | impl<T> Remote1<Box<T>> for u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:16:1
+   |
+LL | impl<'a, T> Remote1<&'a T> for u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs
new file mode 100644
index 0000000000000..7bf0306f29ba4
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs
@@ -0,0 +1,19 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<'a, T> Remote1<Box<T>> for &'a T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+impl<'a, T> Remote1<&'a T> for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr
new file mode 100644
index 0000000000000..eec57fccea762
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:12:1
+   |
+LL | impl<'a, T> Remote1<Box<T>> for &'a T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:15:1
+   |
+LL | impl<'a, T> Remote1<&'a T> for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs
new file mode 100644
index 0000000000000..54d577c749248
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs
@@ -0,0 +1,17 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Box<T>> for Local {}
+
+impl<'a, T> Remote1<&'a T> for Local {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs
new file mode 100644
index 0000000000000..7af929006ef7f
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs
@@ -0,0 +1,19 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Box<T>> for T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+impl<'a, T> Remote1<&'a T> for T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr
new file mode 100644
index 0000000000000..e017c3ffe6c05
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:12:1
+   |
+LL | impl<T> Remote1<Box<T>> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:15:1
+   |
+LL | impl<'a, T> Remote1<&'a T> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs
new file mode 100644
index 0000000000000..24e0f309c4555
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs
@@ -0,0 +1,20 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote2<Box<T>, Local> for u32 {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+impl<'a, T> Remote2<&'a T, Local> for u32 {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr
new file mode 100644
index 0000000000000..3d8561956ae7f
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:12:1
+   |
+LL | impl<T> Remote2<Box<T>, Local> for u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:16:1
+   |
+LL | impl<'a, T> Remote2<&'a T, Local> for u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs
new file mode 100644
index 0000000000000..81cf3c3f6eca9
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Local> for Rc<T> {}
+impl<T> Remote1<Local> for Vec<Box<T>> {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs
new file mode 100644
index 0000000000000..54425b6d708aa
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs
@@ -0,0 +1,20 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Local> for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+impl<T> Remote1<Local> for &T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr
new file mode 100644
index 0000000000000..7859665a7bb58
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:12:1
+   |
+LL | impl<T> Remote1<Local> for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:16:1
+   |
+LL | impl<T> Remote1<Local> for &T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs
new file mode 100644
index 0000000000000..6b1d93cd94442
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs
@@ -0,0 +1,15 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl Remote1<Local> for Local {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs
new file mode 100644
index 0000000000000..6f35c6c9dbc88
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<Local> for T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr
new file mode 100644
index 0000000000000..be7de8cccb467
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[local]-for-t.rs:12:1
+   |
+LL | impl<T> Remote1<Local> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs
new file mode 100644
index 0000000000000..be0875d0110fd
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs
@@ -0,0 +1,19 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+struct Local2<T>(Rc<T>);
+
+impl<T> Remote2<Local, Box<T>> for u32 {}
+impl<'a, T> Remote2<Local, &'a T> for u32 {}
+impl<T> Remote2<Local2<T>, Box<T>> for u32 {}
+impl<'a, T> Remote2<Local2<T>, &'a T> for u32 {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs
new file mode 100644
index 0000000000000..5e89c2077330a
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<T> for u32 {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr
new file mode 100644
index 0000000000000..5544729b5d640
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[t]-for-foreign.rs:12:1
+   |
+LL | impl<T> Remote1<T> for u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs
new file mode 100644
index 0000000000000..300a2c4d48a9c
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs
@@ -0,0 +1,20 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<T> for Box<T> {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+impl<'a, A, B> Remote1<A> for &'a B {
+    //~^ ERROR type parameter `B` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr
new file mode 100644
index 0000000000000..be8cc29a6e5b0
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr
@@ -0,0 +1,19 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:12:1
+   |
+LL | impl<T> Remote1<T> for Box<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct<B>`)
+  --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:16:1
+   |
+LL | impl<'a, A, B> Remote1<A> for &'a B {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `B` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs
new file mode 100644
index 0000000000000..769147ea7eabd
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs
@@ -0,0 +1,15 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+// check-pass
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<T> for Local {}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs
new file mode 100644
index 0000000000000..c8513380ff73e
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs
@@ -0,0 +1,16 @@
+#![feature(re_rebalance_coherence)]
+
+// compile-flags:--crate-name=test
+// aux-build:coherence_lib.rs
+
+extern crate coherence_lib as lib;
+use lib::*;
+use std::rc::Rc;
+
+struct Local;
+
+impl<T> Remote1<T> for T {
+    //~^ ERROR type parameter `T` must be used as the type parameter for some local type
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr
new file mode 100644
index 0000000000000..de857afd20b15
--- /dev/null
+++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr
@@ -0,0 +1,11 @@
+error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
+  --> $DIR/impl[t]-foreign[t]-for-t.rs:12:1
+   |
+LL | impl<T> Remote1<T> for T {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type
+   |
+   = note: only traits defined in the current crate can be implemented for a type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0210`.
diff --git a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs b/src/test/ui/coherence/re-rebalance-coherence-rpass.rs
deleted file mode 100644
index bacd3b89fad29..0000000000000
--- a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![allow(dead_code)]
-#![feature(re_rebalance_coherence)]
-
-// run-pass
-// aux-build:re_rebalance_coherence_lib.rs
-
-extern crate re_rebalance_coherence_lib as lib;
-use lib::*;
-
-struct Oracle;
-impl Backend for Oracle {}
-impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
-
-fn main() {}
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index b85cecda16e95..274967ef60de5 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -11,6 +11,7 @@ struct Sum<A,B>(A,B);
 
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
     const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+    //~| ERROR any use of this value will cause an error
 }
 
 fn foo<T>(_: T) -> &'static u8 {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 707dfee7cd5b8..de3459c72dd2b 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -9,13 +9,21 @@ LL |     const MAX: u8 = A::MAX + B::MAX;
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:17:5
+  --> $DIR/issue-50814.rs:18:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
    |      |
    |      referenced constant has errors
 
-error: aborting due to 2 previous errors
+error: any use of this value will cause an error
+  --> $DIR/issue-50814.rs:13:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |     ----------------^^^^^^^^^^^^^^^-
+   |                     |
+   |                     attempt to add with overflow
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.rs b/src/test/ui/consts/const-prop-read-static-in-const.rs
new file mode 100644
index 0000000000000..7504fd525955a
--- /dev/null
+++ b/src/test/ui/consts/const-prop-read-static-in-const.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+// run-pass
+
+#![allow(dead_code)]
+
+const TEST: u8 = MY_STATIC;
+//~^ skipping const checks
+
+static MY_STATIC: u8 = 4;
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr
new file mode 100644
index 0000000000000..bbd5b12ed7dfc
--- /dev/null
+++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr
@@ -0,0 +1,6 @@
+warning: skipping const checks
+  --> $DIR/const-prop-read-static-in-const.rs:6:18
+   |
+LL | const TEST: u8 = MY_STATIC;
+   |                  ^^^^^^^^^
+
diff --git a/src/test/ui/issues/issue-27592.rs b/src/test/ui/issues/issue-27592.rs
index b023ea18ac9a9..88f70f584022d 100644
--- a/src/test/ui/issues/issue-27592.rs
+++ b/src/test/ui/issues/issue-27592.rs
@@ -15,5 +15,5 @@ impl ::std::fmt::Write for Stream {
 fn main() {
     write(|| format_args!("{}", String::from("Hello world")));
     //~^ ERROR cannot return value referencing temporary value
-    //~| ERROR cannot return value referencing temporary value
+    //~| ERROR cannot return reference to temporary value
 }
diff --git a/src/test/ui/issues/issue-27592.stderr b/src/test/ui/issues/issue-27592.stderr
index 9d3eaa9705d44..c8649d82d7451 100644
--- a/src/test/ui/issues/issue-27592.stderr
+++ b/src/test/ui/issues/issue-27592.stderr
@@ -7,14 +7,11 @@ LL |     write(|| format_args!("{}", String::from("Hello world")));
    |              |                  temporary value created here
    |              returns a value referencing data owned by the current function
 
-error[E0515]: cannot return value referencing temporary value
+error[E0515]: cannot return reference to temporary value
   --> $DIR/issue-27592.rs:16:14
    |
 LL |     write(|| format_args!("{}", String::from("Hello world")));
-   |              ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |            |
-   |              |            temporary value created here
-   |              returns a value referencing data owned by the current function
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/struct-literal-variant-in-if.stderr b/src/test/ui/struct-literal-variant-in-if.stderr
index f91b9d7dce60f..85cbc787bc2db 100644
--- a/src/test/ui/struct-literal-variant-in-if.stderr
+++ b/src/test/ui/struct-literal-variant-in-if.stderr
@@ -49,9 +49,6 @@ LL |     if x == E::V { field } {}
 error[E0308]: mismatched types
   --> $DIR/struct-literal-variant-in-if.rs:10:20
    |
-LL | fn test_E(x: E) {
-   |                 - help: try adding a return type: `-> bool`
-LL |     let field = true;
 LL |     if x == E::V { field } {}
    |                    ^^^^^ expected (), found bool
    |