diff --git a/Cargo.lock b/Cargo.lock
index 365d14c579bdb..5e6bde1db7cd5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,7 @@ dependencies = [
  "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index b2eb3566c04a7..861c7cecb8879 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -15,6 +15,7 @@ compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.6"
+rand_xorshift = "0.1"
 
 [[test]]
 name = "collectionstests"
diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs
index 20b9091a07bfc..6e2b5e06b7a91 100644
--- a/src/liballoc/benches/btree/map.rs
+++ b/src/liballoc/benches/btree/map.rs
@@ -12,7 +12,7 @@
 use std::iter::Iterator;
 use std::vec::Vec;
 use std::collections::BTreeMap;
-use rand::{Rng, thread_rng};
+use rand::{Rng, seq::SliceRandom, thread_rng};
 use test::{Bencher, black_box};
 
 macro_rules! map_insert_rand_bench {
@@ -78,7 +78,7 @@ macro_rules! map_find_rand_bench {
                 map.insert(k, k);
             }
 
-            rng.shuffle(&mut keys);
+            keys.shuffle(&mut rng);
 
             // measure
             let mut i = 0;
diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs
index b4f4fd74f3a39..9502a7dc3c075 100644
--- a/src/liballoc/benches/lib.rs
+++ b/src/liballoc/benches/lib.rs
@@ -13,6 +13,7 @@
 #![feature(test)]
 
 extern crate rand;
+extern crate rand_xorshift;
 extern crate test;
 
 mod btree;
diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs
index 490320f57cbf7..fc58899406332 100644
--- a/src/liballoc/benches/slice.rs
+++ b/src/liballoc/benches/slice.rs
@@ -12,8 +12,9 @@ use rand::{thread_rng};
 use std::mem;
 use std::ptr;
 
-use rand::{Rng, SeedableRng, XorShiftRng};
+use rand::{Rng, SeedableRng};
 use rand::distributions::{Standard, Alphanumeric};
+use rand_xorshift::XorShiftRng;
 use test::{Bencher, black_box};
 
 #[bench]
diff --git a/src/liballoc/benches/str.rs b/src/liballoc/benches/str.rs
index 38c94d4d8b5f3..c5e1576d24e26 100644
--- a/src/liballoc/benches/str.rs
+++ b/src/liballoc/benches/str.rs
@@ -274,11 +274,11 @@ make_test!(split_a_str, s, s.split("a").count());
 make_test!(trim_ascii_char, s, {
     s.trim_matches(|c: char| c.is_ascii())
 });
-make_test!(trim_left_ascii_char, s, {
-    s.trim_left_matches(|c: char| c.is_ascii())
+make_test!(trim_start_ascii_char, s, {
+    s.trim_start_matches(|c: char| c.is_ascii())
 });
-make_test!(trim_right_ascii_char, s, {
-    s.trim_right_matches(|c: char| c.is_ascii())
+make_test!(trim_end_ascii_char, s, {
+    s.trim_end_matches(|c: char| c.is_ascii())
 });
 
 make_test!(find_underscore_char, s, s.find('_'));
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 156d55b9e2fe6..0fd5963c99d4a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1979,6 +1979,15 @@ pub enum FunctionRetTy {
     Return(P<Ty>),
 }
 
+impl fmt::Display for FunctionRetTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Return(ref ty) => print::to_string(print::NO_ANN, |s| s.print_type(ty)).fmt(f),
+            DefaultReturn(_) => "()".fmt(f),
+        }
+    }
+}
+
 impl FunctionRetTy {
     pub fn span(&self) -> Span {
         match *self {
@@ -2119,7 +2128,7 @@ impl StructField {
 /// Id of the whole enum lives in `Item`.
 ///
 /// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
-/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of
+/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of
 /// the variant itself" from enum variants.
 /// Id of the whole struct lives in `Item`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index d82020f59a10e..6852e2c69618b 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -47,7 +47,6 @@ impl_stable_hash_for!(enum mir::BorrowKind {
 impl_stable_hash_for!(enum mir::UnsafetyViolationKind {
     General,
     GeneralAndConstFn,
-    GatedConstFnCall,
     ExternStatic(lint_node_id),
     BorrowPacked(lint_node_id),
 });
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 934d7c12be552..d2175c28309b1 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -25,6 +25,8 @@ use middle::privacy;
 use ty::{self, TyCtxt};
 use util::nodemap::FxHashSet;
 
+use rustc_data_structures::fx::FxHashMap;
+
 use syntax::{ast, source_map};
 use syntax::attr;
 use syntax_pos;
@@ -55,12 +57,15 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
     in_pat: bool,
     inherited_pub_visibility: bool,
     ignore_variant_stack: Vec<DefId>,
+    // maps from tuple struct constructors to tuple struct items
+    struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     fn check_def_id(&mut self, def_id: DefId) {
         if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
-            if should_explore(self.tcx, node_id) {
+            if should_explore(self.tcx, node_id) ||
+               self.struct_constructors.contains_key(&node_id) {
                 self.worklist.push(node_id);
             }
             self.live_symbols.insert(node_id);
@@ -137,19 +142,23 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 continue
             }
 
-            if let Some(ref node) = self.tcx.hir().find(id) {
+            // in the case of tuple struct constructors we want to check the item, not the generated
+            // tuple struct constructor function
+            let id = self.struct_constructors.get(&id).cloned().unwrap_or(id);
+
+            if let Some(node) = self.tcx.hir().find(id) {
                 self.live_symbols.insert(id);
                 self.visit_node(node);
             }
         }
     }
 
-    fn visit_node(&mut self, node: &Node<'tcx>) {
+    fn visit_node(&mut self, node: Node<'tcx>) {
         let had_repr_c = self.repr_has_repr_c;
         self.repr_has_repr_c = false;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
         self.inherited_pub_visibility = false;
-        match *node {
+        match node {
             Node::Item(item) => {
                 match item.node {
                     hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
@@ -337,6 +346,8 @@ struct LifeSeeder<'k, 'tcx: 'k> {
     worklist: Vec<ast::NodeId>,
     krate: &'k hir::Crate,
     tcx: TyCtxt<'k, 'tcx, 'tcx>,
+    // see `MarkSymbolVisitor::struct_constructors`
+    struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
 }
 
 impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
@@ -379,6 +390,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
                     }
                 }
             }
+            hir::ItemKind::Struct(ref variant_data, _) => {
+                self.struct_constructors.insert(variant_data.id(), item.id);
+            }
             _ => ()
         }
     }
@@ -392,11 +406,11 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
     }
 }
 
-fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      access_levels: &privacy::AccessLevels,
-                                      krate: &hir::Crate)
-                                      -> Vec<ast::NodeId>
-{
+fn create_and_seed_worklist<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    access_levels: &privacy::AccessLevels,
+    krate: &hir::Crate,
+) -> (Vec<ast::NodeId>, FxHashMap<ast::NodeId, ast::NodeId>) {
     let worklist = access_levels.map.iter().filter_map(|(&id, level)| {
         if level >= &privacy::AccessLevel::Reachable {
             Some(id)
@@ -413,17 +427,18 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         worklist,
         krate,
         tcx,
+        struct_constructors: Default::default(),
     };
     krate.visit_all_item_likes(&mut life_seeder);
 
-    return life_seeder.worklist;
+    (life_seeder.worklist, life_seeder.struct_constructors)
 }
 
 fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        access_levels: &privacy::AccessLevels,
                        krate: &hir::Crate)
                        -> FxHashSet<ast::NodeId> {
-    let worklist = create_and_seed_worklist(tcx, access_levels, krate);
+    let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate);
     let mut symbol_visitor = MarkSymbolVisitor {
         worklist,
         tcx,
@@ -433,20 +448,12 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         in_pat: false,
         inherited_pub_visibility: false,
         ignore_variant_stack: vec![],
+        struct_constructors,
     };
     symbol_visitor.mark_live_symbols();
     symbol_visitor.live_symbols
 }
 
-fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
-    match item.node {
-        hir::ItemKind::Struct(ref struct_def, _) if !struct_def.is_struct() => {
-            Some(struct_def.id())
-        }
-        _ => None
-    }
-}
-
 struct DeadVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     live_symbols: FxHashSet<ast::NodeId>,
@@ -464,46 +471,35 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
             | hir::ItemKind::Union(..) => true,
             _ => false
         };
-        let ctor_id = get_struct_ctor_id(item);
-        should_warn && !self.symbol_is_live(item.id, ctor_id)
+        should_warn && !self.symbol_is_live(item.id)
     }
 
     fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
         let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id));
         !field.is_positional()
-            && !self.symbol_is_live(field.id, None)
+            && !self.symbol_is_live(field.id)
             && !field_type.is_phantom_data()
             && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs)
     }
 
     fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
-        !self.symbol_is_live(variant.data.id(), None)
+        !self.symbol_is_live(variant.data.id())
             && !has_allow_dead_code_or_lang_attr(self.tcx,
                                                  variant.data.id(),
                                                  &variant.attrs)
     }
 
     fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
-        !self.symbol_is_live(fi.id, None)
+        !self.symbol_is_live(fi.id)
             && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs)
     }
 
     // id := node id of an item's definition.
-    // ctor_id := `Some` if the item is a struct_ctor (tuple struct),
-    //            `None` otherwise.
-    // If the item is a struct_ctor, then either its `id` or
-    // `ctor_id` (unwrapped) is in the live_symbols set. More specifically,
-    // DefMap maps the ExprKind::Path of a struct_ctor to the node referred by
-    // `ctor_id`. On the other hand, in a statement like
-    // `type <ident> <generics> = <ty>;` where <ty> refers to a struct_ctor,
-    // DefMap maps <ty> to `id` instead.
-    fn symbol_is_live(&mut self,
-                      id: ast::NodeId,
-                      ctor_id: Option<ast::NodeId>)
-                      -> bool {
-        if self.live_symbols.contains(&id)
-           || ctor_id.map_or(false, |ctor| self.live_symbols.contains(&ctor))
-        {
+    fn symbol_is_live(
+        &mut self,
+        id: ast::NodeId,
+    ) -> bool {
+        if self.live_symbols.contains(&id) {
             return true;
         }
         // If it's a type whose items are live, then it's live, too.
@@ -611,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
         match impl_item.node {
             hir::ImplItemKind::Const(_, body_id) => {
-                if !self.symbol_is_live(impl_item.id, None) {
+                if !self.symbol_is_live(impl_item.id) {
                     self.warn_dead_code(impl_item.id,
                                         impl_item.span,
                                         impl_item.ident.name,
@@ -621,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                 self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Method(_, body_id) => {
-                if !self.symbol_is_live(impl_item.id, None) {
+                if !self.symbol_is_live(impl_item.id) {
                     let span = self.tcx.sess.source_map().def_span(impl_item.span);
                     self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used");
                 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index dc14450e8d22d..120350a573b6e 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2792,9 +2792,6 @@ impl Location {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum UnsafetyViolationKind {
     General,
-    /// Right now function calls to `const unsafe fn` are only permitted behind a feature gate
-    /// Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations.
-    GatedConstFnCall,
     /// Permitted in const fn and regular fns
     GeneralAndConstFn,
     ExternStatic(ast::NodeId),
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 90aa9f6cbc763..5fad4a24b262e 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
         bx: &mut Bx,
         llindex: V
     ) -> Self {
+        // Statically compute the offset if we can, otherwise just use the element size,
+        // as this will yield the lowest alignment.
+        let layout = self.layout.field(bx, 0);
+        let offset = if bx.is_const_integral(llindex) {
+            layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size)
+        } else {
+            layout.size
+        };
+
         PlaceRef {
             llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
             llextra: None,
-            layout: self.layout.field(bx.cx(), 0),
-            align: self.align
+            layout,
+            align: self.align.restrict_for_offset(offset),
         }
     }
 
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index c932ffd1c1bda..052342dd7597b 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
                 header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
 
+                let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
                 cg_elem.val.store(&mut body_bx,
-                    PlaceRef::new_sized(current, cg_elem.layout, dest.align));
+                    PlaceRef::new_sized(current, cg_elem.layout, align));
 
                 let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
                 body_bx.br(header_bx.llbb());
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 146bf53830656..64defaf78a487 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -126,18 +126,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ExprKind::LogicalOp { op, lhs, rhs } => {
                 // And:
                 //
-                // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block]
-                //        |                          | (false)
-                //        +----------false-----------+------------------> [false_block]
+                // [block: If(lhs)] -true-> [else_block: dest = (rhs)]
+                //        | (false)
+                //  [shortcurcuit_block: dest = false]
                 //
                 // Or:
                 //
-                // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block]
-                //        | (true)                   | (false)
-                //  [true_block]               [false_block]
+                // [block: If(lhs)] -false-> [else_block: dest = (rhs)]
+                //        | (true)
+                //  [shortcurcuit_block: dest = true]
 
-                let (true_block, false_block, mut else_block, join_block) = (
-                    this.cfg.start_new_block(),
+                let (shortcircuit_block, mut else_block, join_block) = (
                     this.cfg.start_new_block(),
                     this.cfg.start_new_block(),
                     this.cfg.start_new_block(),
@@ -145,47 +144,41 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
                 let lhs = unpack!(block = this.as_local_operand(block, lhs));
                 let blocks = match op {
-                    LogicalOp::And => (else_block, false_block),
-                    LogicalOp::Or => (true_block, else_block),
+                    LogicalOp::And => (else_block, shortcircuit_block),
+                    LogicalOp::Or => (shortcircuit_block, else_block),
                 };
                 let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1);
                 this.cfg.terminate(block, source_info, term);
 
-                let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
-                let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block);
-                this.cfg.terminate(else_block, source_info, term);
-
                 this.cfg.push_assign_constant(
-                    true_block,
+                    shortcircuit_block,
                     source_info,
                     destination,
                     Constant {
                         span: expr_span,
                         ty: this.hir.bool_ty(),
                         user_ty: None,
-                        literal: this.hir.true_literal(),
+                        literal: match op {
+                            LogicalOp::And => this.hir.false_literal(),
+                            LogicalOp::Or => this.hir.true_literal(),
+                        },
                     },
                 );
-
-                this.cfg.push_assign_constant(
-                    false_block,
+                this.cfg.terminate(
+                    shortcircuit_block,
                     source_info,
-                    destination,
-                    Constant {
-                        span: expr_span,
-                        ty: this.hir.bool_ty(),
-                        user_ty: None,
-                        literal: this.hir.false_literal(),
-                    },
+                    TerminatorKind::Goto { target: join_block },
                 );
 
-                this.cfg.terminate(
-                    true_block,
+                let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
+                this.cfg.push_assign(
+                    else_block,
                     source_info,
-                    TerminatorKind::Goto { target: join_block },
+                    destination,
+                    Rvalue::Use(rhs),
                 );
                 this.cfg.terminate(
-                    false_block,
+                    else_block,
                     source_info,
                     TerminatorKind::Goto { target: join_block },
                 );
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index f6b7f817aad53..89d9c03f74e3e 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -23,7 +23,6 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
 
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax::feature_gate::{emit_feature_err, GateIssue};
 
 use std::ops::Bound;
 
@@ -97,7 +96,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 if let hir::Unsafety::Unsafe = sig.unsafety() {
                     self.require_unsafe("call to unsafe function",
                         "consult the function's documentation for information on how to avoid \
-                         undefined behavior", UnsafetyViolationKind::GatedConstFnCall)
+                         undefined behavior", UnsafetyViolationKind::GeneralAndConstFn)
                 }
             }
         }
@@ -325,11 +324,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                             // compat lint
                             violation.kind = UnsafetyViolationKind::General;
                         },
-                        UnsafetyViolationKind::GatedConstFnCall => {
-                            // safe code can't call unsafe const fns, this `UnsafetyViolationKind`
-                            // is only relevant for `Safety::ExplicitUnsafe` in `unsafe const fn`s
-                            violation.kind = UnsafetyViolationKind::General;
-                        }
                     }
                     if !self.violations.contains(&violation) {
                         self.violations.push(violation)
@@ -346,19 +340,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 }
                 // only some unsafety is allowed in const fn
                 if self.min_const_fn {
-                    let min_const_unsafe_fn = self.tcx.features().min_const_unsafe_fn;
                     for violation in violations {
                         match violation.kind {
-                            UnsafetyViolationKind::GatedConstFnCall if min_const_unsafe_fn => {
-                                // these function calls to unsafe functions are allowed
-                                // if `#![feature(min_const_unsafe_fn)]` is active
-                            },
-                            UnsafetyViolationKind::GatedConstFnCall => {
-                                // without the feature gate, we report errors
-                                if !self.violations.contains(&violation) {
-                                    self.violations.push(violation.clone())
-                                }
-                            }
                             // these unsafe things are stable in const fn
                             UnsafetyViolationKind::GeneralAndConstFn => {},
                             // these things are forbidden in const fns
@@ -620,16 +603,6 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                     .note(&details.as_str()[..])
                     .emit();
             }
-            UnsafetyViolationKind::GatedConstFnCall => {
-                emit_feature_err(
-                    &tcx.sess.parse_sess,
-                    "min_const_unsafe_fn",
-                    source_info.span,
-                    GateIssue::Language,
-                    "calls to `const unsafe fn` in const fns are unstable",
-                );
-
-            }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
                 tcx.lint_node_note(SAFE_EXTERN_STATICS,
                               lint_node_id,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index b854f029e5106..646a671d4a2ce 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -518,7 +518,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
 
                 // Only allow statics (not consts) to refer to other statics.
                 if self.mode == Mode::Static || self.mode == Mode::StaticMut {
-                    if context.is_mutating_use() {
+                    if self.mode == Mode::Static && context.is_mutating_use() {
                         // this is not strictly necessary as miri will also bail out
                         // For interior mutability we can't really catch this statically as that
                         // goes through raw pointers and intermediate temporaries, so miri has
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 794e5741d62ca..e543677ef0621 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3213,23 +3213,43 @@ impl<'a> Resolver<'a> {
                 let enum_candidates =
                     this.lookup_import_candidates(ident, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
-                    .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
+                    .map(|suggestion| {
+                        import_candidate_to_enum_paths(&suggestion)
+                    }).collect::<Vec<_>>();
                 enum_candidates.sort();
-                for (sp, variant_path, enum_path) in enum_candidates {
-                    if sp.is_dummy() {
-                        let msg = format!("there is an enum variant `{}`, \
-                                           try using `{}`?",
-                                          variant_path,
-                                          enum_path);
-                        err.help(&msg);
+
+                if !enum_candidates.is_empty() {
+                    // contextualize for E0412 "cannot find type", but don't belabor the point
+                    // (that it's a variant) for E0573 "expected type, found variant"
+                    let preamble = if def.is_none() {
+                        let others = match enum_candidates.len() {
+                            1 => String::new(),
+                            2 => " and 1 other".to_owned(),
+                            n => format!(" and {} others", n)
+                        };
+                        format!("there is an enum variant `{}`{}; ",
+                                enum_candidates[0].0, others)
                     } else {
-                        err.span_suggestion_with_applicability(
-                            span,
-                            "you can try using the variant's enum",
-                            enum_path,
-                            Applicability::MachineApplicable,
-                        );
-                    }
+                        String::new()
+                    };
+                    let msg = format!("{}try using the variant's enum", preamble);
+
+                    err.span_suggestions_with_applicability(
+                        span,
+                        &msg,
+                        enum_candidates.into_iter()
+                            .map(|(_variant_path, enum_ty_path)| enum_ty_path)
+                            // variants reƫxported in prelude doesn't mean `prelude::v1` is the
+                            // type name! FIXME: is there a more principled way to do this that
+                            // would work for other reƫxports?
+                            .filter(|enum_ty_path| enum_ty_path != "std::prelude::v1")
+                            // also say `Option` rather than `std::prelude::v1::Option`
+                            .map(|enum_ty_path| {
+                                // FIXME #56861: DRYer prelude filtering
+                                enum_ty_path.trim_start_matches("std::prelude::v1::").to_owned()
+                            }),
+                        Applicability::MachineApplicable,
+                    );
                 }
             }
             if path.len() == 1 && this.self_type_is_available(span) {
@@ -5128,8 +5148,8 @@ fn path_names_to_string(path: &Path) -> String {
                         .collect::<Vec<_>>())
 }
 
-/// Get the path for an enum and the variant from an `ImportSuggestion` for an enum variant.
-fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, String) {
+/// Get the stringified path for an enum from an `ImportSuggestion` for an enum variant.
+fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) {
     let variant_path = &suggestion.path;
     let variant_path_string = path_names_to_string(variant_path);
 
@@ -5140,7 +5160,7 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
     };
     let enum_path_string = path_names_to_string(&enum_path);
 
-    (suggestion.path.span, variant_path_string, enum_path_string)
+    (variant_path_string, enum_path_string)
 }
 
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 9a1f9784192c1..8b2be84942388 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1169,7 +1169,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
             // `expression_ty` will be unit).
             //
             // Another example is `break` with no argument expression.
-            assert!(expression_ty.is_unit());
             assert!(expression_ty.is_unit(), "if let hack without unit type");
             fcx.at(cause, fcx.param_env)
                .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
@@ -1210,13 +1209,14 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
+                let reason_label = "expected because of this statement";
                 let mut db;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
                         db = struct_span_err!(
                             fcx.tcx.sess, cause.span, E0069,
                             "`return;` in a function whose return type is not `()`");
-                        db.span_label(cause.span, "return type is not ()");
+                        db.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
@@ -1234,9 +1234,19 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                             cause.span,
                             blk_id,
                         );
+                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                            if !sp.overlaps(cause.span) {
+                                db.span_label(*sp, reason_label);
+                            }
+                        }
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
+                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                            if !sp.overlaps(cause.span) {
+                                db.span_label(*sp, reason_label);
+                            }
+                        }
                     }
                 }
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index db4b68611c51b..996b57f558cc5 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -123,6 +123,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         let sole_field_ty = sole_field.ty(self.tcx, substs);
                         if self.can_coerce(expr_ty, sole_field_ty) {
                             let variant_path = self.tcx.item_path_str(variant.did);
+                            // FIXME #56861: DRYer prelude filtering
                             Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
                         } else {
                             None
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d45f8fd6de8d9..0665452e30a57 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -538,6 +538,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     err_count_on_creation: usize,
 
     ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>,
+    ret_coercion_span: RefCell<Option<Span>>,
 
     yield_ty: Option<Ty<'tcx>>,
 
@@ -1987,6 +1988,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             param_env,
             err_count_on_creation: inh.tcx.sess.err_count(),
             ret_coercion: None,
+            ret_coercion_span: RefCell::new(None),
             yield_ty: None,
             ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
                                                      ast::CRATE_NODE_ID)),
@@ -3440,7 +3442,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             len.assert_usize(self.tcx),
                             field.as_str().parse::<u64>()
                         ) {
-                            let base = self.tcx.hir().node_to_pretty_string(base.id);
+                            let base = self.tcx.sess.source_map()
+                                .span_to_snippet(base.span)
+                                .unwrap_or_else(|_| self.tcx.hir().node_to_pretty_string(base.id));
                             let help = "instead of using tuple indexing, use array indexing";
                             let suggestion = format!("{}[{}]", base, field);
                             let applicability = if len < user_index {
@@ -3454,11 +3458,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         }
                     }
                     ty::RawPtr(..) => {
-                        let base = self.tcx.hir().node_to_pretty_string(base.id);
-                        let msg = format!("`{}` is a native pointer; try dereferencing it", base);
+                        let base = self.tcx.sess.source_map()
+                            .span_to_snippet(base.span)
+                            .unwrap_or_else(|_| self.tcx.hir().node_to_pretty_string(base.id));
+                        let msg = format!("`{}` is a raw pointer; try dereferencing it", base);
                         let suggestion = format!("(*{}).{}", base, field);
                         err.span_suggestion_with_applicability(
-                            field.span,
+                            expr.span,
                             &msg,
                             suggestion,
                             Applicability::MaybeIncorrect,
@@ -4168,11 +4174,30 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     struct_span_err!(self.tcx.sess, expr.span, E0572,
                                      "return statement outside of function body").emit();
                 } else if let Some(ref e) = *expr_opt {
+                    *self.ret_coercion_span.borrow_mut() = Some(e.span);
                     self.check_return_expr(e);
                 } else {
                     let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
+                    *self.ret_coercion_span.borrow_mut() = Some(expr.span);
                     let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
-                    coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+                    if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
+                        coercion.coerce_forced_unit(
+                            self,
+                            &cause,
+                            &mut |db| {
+                                db.span_label(
+                                    fn_decl.output.span(),
+                                    format!(
+                                        "expected `{}` because of this return type",
+                                        fn_decl.output,
+                                    ),
+                                );
+                            },
+                            true,
+                        );
+                    } else {
+                        coercion.coerce_forced_unit(self, &cause, &mut |_| (), true);
+                    }
                 }
                 tcx.types.never
             }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 0d3de34fe6438..99a682832286e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -273,7 +273,6 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![cfg_attr(not(stage0), feature(min_const_unsafe_fn))]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 941a3a288da5c..2238e429a58e0 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -486,9 +486,6 @@ declare_features! (
 
     // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`.
     (active, extern_crate_self, "1.31.0", Some(56409), None),
-
-    // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
-    (active, min_const_unsafe_fn, "1.31.0", Some(55607), None),
 );
 
 declare_features! (
@@ -694,6 +691,8 @@ declare_features! (
     (accepted, underscore_imports, "1.33.0", Some(48216), None),
     // Allows `#[repr(packed(N))]` attribute on structs.
     (accepted, repr_packed, "1.33.0", Some(33158), None),
+    // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
+    (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
 );
 
 // If you change this, please modify `src/doc/unstable-book` as well. You must
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs
index 6f9dc247a7897..265ff5f57e4c0 100644
--- a/src/libsyntax/parse/lexer/tokentrees.rs
+++ b/src/libsyntax/parse/lexer/tokentrees.rs
@@ -11,7 +11,7 @@
 use print::pprust::token_to_string;
 use parse::lexer::StringReader;
 use parse::{token, PResult};
-use tokenstream::{DelimSpan, TokenStream, TokenTree};
+use tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree};
 
 impl<'a> StringReader<'a> {
     // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
@@ -186,8 +186,7 @@ impl<'a> StringReader<'a> {
                 let raw = self.span_src_raw;
                 self.real_token();
                 let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token);
-
-                Ok(if is_joint { tt.joint() } else { tt.into() })
+                Ok(TokenStream::Tree(tt, if is_joint { Joint } else { NonJoint }))
             }
         }
     }
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 013ecd3d343c2..b04495d751a85 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -123,7 +123,7 @@ impl TokenTree {
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream::JointTree(self)
+        TokenStream::Tree(self, Joint)
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -156,8 +156,7 @@ impl TokenTree {
 #[derive(Clone, Debug)]
 pub enum TokenStream {
     Empty,
-    Tree(TokenTree),
-    JointTree(TokenTree),
+    Tree(TokenTree, IsJoint),
     Stream(Lrc<Vec<TokenStream>>),
 }
 
@@ -165,6 +164,14 @@ pub enum TokenStream {
 #[cfg(target_arch = "x86_64")]
 static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum IsJoint {
+    Joint,
+    NonJoint
+}
+
+use self::IsJoint::*;
+
 impl TokenStream {
     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
     /// separating the two arguments with a comma for diagnostic suggestions.
@@ -176,16 +183,16 @@ impl TokenStream {
             while let Some((pos, ts)) = iter.next() {
                 if let Some((_, next)) = iter.peek() {
                     let sp = match (&ts, &next) {
-                        (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) |
-                        (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => {
-                            continue;
-                        }
-                        (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp,
-                        (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(),
+                        (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint), _) |
+                        (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint))
+                          => continue,
+                        (TokenStream::Tree(TokenTree::Token(sp, _), NonJoint), _) => *sp,
+                        (TokenStream::Tree(TokenTree::Delimited(sp, ..), NonJoint), _) =>
+                            sp.entire(),
                         _ => continue,
                     };
                     let sp = sp.shrink_to_hi();
-                    let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma));
+                    let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma), NonJoint);
                     suggestion = Some((pos, comma, sp));
                 }
             }
@@ -204,7 +211,7 @@ impl TokenStream {
 
 impl From<TokenTree> for TokenStream {
     fn from(tt: TokenTree) -> TokenStream {
-        TokenStream::Tree(tt)
+        TokenStream::Tree(tt, NonJoint)
     }
 }
 
@@ -232,7 +239,7 @@ impl Extend<TokenStream> for TokenStream {
                 vec.reserve(iter.size_hint().0);
                 vec
             }
-            TokenStream::Tree(_) | TokenStream::JointTree(_) => {
+            TokenStream::Tree(..) => {
                 let mut vec = Vec::new();
                 vec.reserve(1 + iter.size_hint().0);
                 vec.push(this);
@@ -369,8 +376,7 @@ impl TokenStream {
     /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`.
     pub fn as_tree(self) -> (TokenTree, bool /* joint? */) {
         match self {
-            TokenStream::Tree(tree) => (tree, false),
-            TokenStream::JointTree(tree) => (tree, true),
+            TokenStream::Tree(tree, is_joint) => (tree, is_joint == Joint),
             _ => unreachable!(),
         }
     }
@@ -381,8 +387,7 @@ impl TokenStream {
         let mut i = 0;
         while let Some(stream) = trees.next_as_stream() {
             result.push(match stream {
-                TokenStream::Tree(tree) => f(i, tree).into(),
-                TokenStream::JointTree(tree) => f(i, tree).joint(),
+                TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(i, tree), is_joint),
                 _ => unreachable!()
             });
             i += 1;
@@ -395,27 +400,25 @@ impl TokenStream {
         let mut result = Vec::new();
         while let Some(stream) = trees.next_as_stream() {
             result.push(match stream {
-                TokenStream::Tree(tree) => f(tree).into(),
-                TokenStream::JointTree(tree) => f(tree).joint(),
+                TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
                 _ => unreachable!()
             });
         }
         TokenStream::new(result)
     }
 
-    fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> {
+    fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
         match self {
             TokenStream::Empty => None,
-            TokenStream::Tree(ref tree) => Some((tree.clone(), false)),
-            TokenStream::JointTree(ref tree) => Some((tree.clone(), true)),
+            TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
             TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
         }
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
         match self {
-            TokenStream::Empty | TokenStream::Tree(..) => None,
-            TokenStream::JointTree(ref tree) => Some(tree.clone()),
+            TokenStream::Empty | TokenStream::Tree(_, NonJoint) => None,
+            TokenStream::Tree(ref tree, Joint) => Some(tree.clone()),
             TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
         }
     }
@@ -439,11 +442,7 @@ impl TokenStreamBuilder {
                     self.push_all_but_last_tree(&last_stream);
                     let glued_span = last_span.to(span);
                     let glued_tt = TokenTree::Token(glued_span, glued_tok);
-                    let glued_tokenstream = if is_joint {
-                        glued_tt.joint()
-                    } else {
-                        glued_tt.into()
-                    };
+                    let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint);
                     self.0.push(glued_tokenstream);
                     self.push_all_but_first_tree(&stream);
                     return
@@ -493,8 +492,7 @@ pub struct Cursor(CursorKind);
 #[derive(Clone)]
 enum CursorKind {
     Empty,
-    Tree(TokenTree, bool /* consumed? */),
-    JointTree(TokenTree, bool /* consumed? */),
+    Tree(TokenTree, IsJoint, bool /* consumed? */),
     Stream(StreamCursor),
 }
 
@@ -516,9 +514,9 @@ impl StreamCursor {
                 self.index += 1;
                 let next = self.stream[self.index - 1].clone();
                 match next {
-                    TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next),
-                    TokenStream::Stream(stream) => self.insert(stream),
                     TokenStream::Empty => {}
+                    TokenStream::Tree(..) => return Some(next),
+                    TokenStream::Stream(stream) => self.insert(stream),
                 }
             } else if let Some((stream, index)) = self.stack.pop() {
                 self.stream = stream;
@@ -540,7 +538,7 @@ impl Iterator for Cursor {
 
     fn next(&mut self) -> Option<TokenTree> {
         self.next_as_stream().map(|stream| match stream {
-            TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree,
+            TokenStream::Tree(tree, _) => tree,
             _ => unreachable!()
         })
     }
@@ -550,18 +548,15 @@ impl Cursor {
     fn new(stream: TokenStream) -> Self {
         Cursor(match stream {
             TokenStream::Empty => CursorKind::Empty,
-            TokenStream::Tree(tree) => CursorKind::Tree(tree, false),
-            TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false),
+            TokenStream::Tree(tree, is_joint) => CursorKind::Tree(tree, is_joint, false),
             TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
         })
     }
 
     pub fn next_as_stream(&mut self) -> Option<TokenStream> {
         let (stream, consumed) = match self.0 {
-            CursorKind::Tree(ref tree, ref mut consumed @ false) =>
-                (tree.clone().into(), consumed),
-            CursorKind::JointTree(ref tree, ref mut consumed @ false) =>
-                (tree.clone().joint(), consumed),
+            CursorKind::Tree(ref tree, ref is_joint, ref mut consumed @ false) =>
+                (TokenStream::Tree(tree.clone(), *is_joint), consumed),
             CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(),
             _ => return None,
         };
@@ -574,7 +569,7 @@ impl Cursor {
         match self.0 {
             _ if stream.is_empty() => return,
             CursorKind::Empty => *self = stream.trees(),
-            CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => {
+            CursorKind::Tree(_, _, consumed) => {
                 *self = TokenStream::new(vec![self.original_stream(), stream]).trees();
                 if consumed {
                     self.next();
@@ -589,8 +584,8 @@ impl Cursor {
     pub fn original_stream(&self) -> TokenStream {
         match self.0 {
             CursorKind::Empty => TokenStream::empty(),
-            CursorKind::Tree(ref tree, _) => tree.clone().into(),
-            CursorKind::JointTree(ref tree, _) => tree.clone().joint(),
+            CursorKind::Tree(ref tree, ref is_joint, _) =>
+                TokenStream::Tree(tree.clone(), *is_joint),
             CursorKind::Stream(ref cursor) => TokenStream::Stream(
                 cursor.stack.get(0).cloned().map(|(stream, _)| stream)
                     .unwrap_or_else(|| cursor.stream.clone())
@@ -602,9 +597,8 @@ impl Cursor {
         fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> {
             for stream in streams {
                 n = match stream {
-                    TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree)
-                        if n == 0 => return Ok(tree.clone()),
-                    TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1,
+                    TokenStream::Tree(ref tree, _) if n == 0 => return Ok(tree.clone()),
+                    TokenStream::Tree(..) => n - 1,
                     TokenStream::Stream(ref stream) => match look_ahead(stream, n) {
                         Ok(tree) => return Ok(tree),
                         Err(n) => n,
@@ -617,10 +611,8 @@ impl Cursor {
 
         match self.0 {
             CursorKind::Empty |
-            CursorKind::Tree(_, true) |
-            CursorKind::JointTree(_, true) => Err(n),
-            CursorKind::Tree(ref tree, false) |
-            CursorKind::JointTree(ref tree, false) => look_ahead(&[tree.clone().into()], n),
+            CursorKind::Tree(_, _, true) => Err(n),
+            CursorKind::Tree(ref tree, _, false) => look_ahead(&[tree.clone().into()], n),
             CursorKind::Stream(ref cursor) => {
                 look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| {
                     for &(ref stream, index) in cursor.stack.iter().rev() {
@@ -653,8 +645,7 @@ impl From<TokenStream> for ThinTokenStream {
     fn from(stream: TokenStream) -> ThinTokenStream {
         ThinTokenStream(match stream {
             TokenStream::Empty => None,
-            TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])),
-            TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])),
+            TokenStream::Tree(..) => Some(Lrc::new(vec![stream])),
             TokenStream::Stream(stream) => Some(stream),
         })
     }
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index ca960cbe41b5d..507ceb53432d6 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -21,7 +21,7 @@ use syntax::ast;
 use syntax::ext::base::ExtCtxt;
 use syntax::parse::lexer::comments;
 use syntax::parse::{self, token, ParseSess};
-use syntax::tokenstream::{self, DelimSpan, TokenStream};
+use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream};
 use syntax_pos::hygiene::{SyntaxContext, Transparency};
 use syntax_pos::symbol::{keywords, Symbol};
 use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
@@ -278,11 +278,7 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
         };
 
         let tree = tokenstream::TokenTree::Token(span, token);
-        if joint {
-            tree.joint()
-        } else {
-            tree.into()
-        }
+        TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
     }
 }
 
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9aafb9fc549fc..ae2259d525898 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -334,6 +334,13 @@ impl Span {
         span.lo <= other.lo && other.hi <= span.hi
     }
 
+    /// Return `true` if `self` touches `other`.
+    pub fn overlaps(self, other: Span) -> bool {
+        let span = self.data();
+        let other = other.data();
+        span.lo < other.hi && other.lo < span.hi
+    }
+
     /// Return true if the spans are equal with regards to the source text.
     ///
     /// Use this instead of `==` when either span could be generated code,
diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs
new file mode 100644
index 0000000000000..0544ff86aacfa
--- /dev/null
+++ b/src/test/codegen/issue-56927.rs
@@ -0,0 +1,44 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+use std::usize;
+
+#[repr(align(16))]
+pub struct S {
+    arr: [u32; 4],
+}
+
+// CHECK-LABEL: @test1
+// CHECK: store i32 0, i32* %{{.+}}, align 16
+// CHECK: store i32 1, i32* %{{.+}}, align 4
+// CHECK: store i32 2, i32* %{{.+}}, align 8
+// CHECK: store i32 3, i32* %{{.+}}, align 4
+#[no_mangle]
+pub fn test1(s: &mut S) {
+    s.arr[0] = 0;
+    s.arr[1] = 1;
+    s.arr[2] = 2;
+    s.arr[3] = 3;
+}
+
+// CHECK-LABEL: @test2
+// CHECK: store i32 4, i32* %{{.+}}, align 4
+#[allow(const_err)]
+#[no_mangle]
+pub fn test2(s: &mut S) {
+    s.arr[usize::MAX / 4 + 1] = 4;
+}
+
+// CHECK-LABEL: @test3
+// CHECK: store i32 5, i32* %{{.+}}, align 4
+#[no_mangle]
+pub fn test3(s: &mut S, i: usize) {
+    s.arr[i] = 5;
+}
+
+// CHECK-LABEL: @test4
+// CHECK: store i32 6, i32* %{{.+}}, align 4
+#[no_mangle]
+pub fn test4(s: &mut S) {
+    s.arr = [6; 4];
+}
diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs
index fb6507fd22a4b..3b4e89f12e0ad 100644
--- a/src/test/codegen/packed.rs
+++ b/src/test/codegen/packed.rs
@@ -83,6 +83,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
     BigPacked2 { dealign: 0, data: f() }
 }
 
+// CHECK-LABEL: @write_packed_array1
+// CHECK: store i32 0, i32* %{{.+}}, align 1
+// CHECK: store i32 1, i32* %{{.+}}, align 1
+// CHECK: store i32 2, i32* %{{.+}}, align 1
+#[no_mangle]
+pub fn write_packed_array1(p: &mut BigPacked1) {
+    p.data.0[0] = 0;
+    p.data.0[1] = 1;
+    p.data.0[2] = 2;
+}
+
+// CHECK-LABEL: @write_packed_array2
+// CHECK: store i32 0, i32* %{{.+}}, align 2
+// CHECK: store i32 1, i32* %{{.+}}, align 2
+// CHECK: store i32 2, i32* %{{.+}}, align 2
+#[no_mangle]
+pub fn write_packed_array2(p: &mut BigPacked2) {
+    p.data.0[0] = 0;
+    p.data.0[1] = 1;
+    p.data.0[2] = 2;
+}
+
+// CHECK-LABEL: @repeat_packed_array1
+// CHECK: store i32 42, i32* %{{.+}}, align 1
+#[no_mangle]
+pub fn repeat_packed_array1(p: &mut BigPacked1) {
+    p.data.0 = [42; 8];
+}
+
+// CHECK-LABEL: @repeat_packed_array2
+// CHECK: store i32 42, i32* %{{.+}}, align 2
+#[no_mangle]
+pub fn repeat_packed_array2(p: &mut BigPacked2) {
+    p.data.0 = [42; 8];
+}
+
 #[repr(packed)]
 #[derive(Copy, Clone)]
 pub struct Packed1Pair(u8, u32);
diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs
index 0fd7ccd55fb2d..3cd622a33b173 100644
--- a/src/test/run-pass-fulldeps/newtype_index.rs
+++ b/src/test/run-pass-fulldeps/newtype_index.rs
@@ -1,4 +1,4 @@
-#![feature(rustc_attrs, rustc_private, step_trait, min_const_unsafe_fn)]
+#![feature(rustc_attrs, rustc_private, step_trait)]
 
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_serialize;
diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs
index 8ac0d07ceefe4..f38fab91de7c4 100644
--- a/src/test/rustdoc/const-display.rs
+++ b/src/test/rustdoc/const-display.rs
@@ -15,7 +15,6 @@
             issue = "0")]
 
 #![feature(rustc_const_unstable, const_fn, foo, foo2)]
-#![feature(min_const_unsafe_fn)]
 #![feature(staged_api)]
 
 // @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32'
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
index 92e99c6228a9b..da875fe7a6b77 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
@@ -8,27 +8,62 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-min_const_unsafe_fn
+//------------------------------------------------------------------------------
+// OK
+//------------------------------------------------------------------------------
 
-// ok
 const unsafe fn ret_i32_no_unsafe() -> i32 { 42 }
 const unsafe fn ret_null_ptr_no_unsafe<T>() -> *const T { 0 as *const T }
 const unsafe fn ret_null_mut_ptr_no_unsafe<T>() -> *mut T { 0 as *mut T }
 const fn no_unsafe() { unsafe {} }
 
-// not ok
 const fn call_unsafe_const_fn() -> i32 {
-    unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
+    unsafe { ret_i32_no_unsafe() }
 }
 const fn call_unsafe_generic_const_fn() -> *const String {
     unsafe { ret_null_ptr_no_unsafe::<String>() }
-    //~^ ERROR calls to `const unsafe fn` in const fns are unstable
 }
-const fn call_unsafe_generic_cell_const_fn() -> *const Vec<std::cell::Cell<u32>> {
+const fn call_unsafe_generic_cell_const_fn()
+    -> *const Vec<std::cell::Cell<u32>>
+{
     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
-    //~^ ERROR calls to `const unsafe fn` in const fns
 }
-const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
+
+const unsafe fn call_unsafe_const_unsafe_fn() -> i32 {
+    unsafe { ret_i32_no_unsafe() }
+}
+const unsafe fn call_unsafe_generic_const_unsafe_fn() -> *const String {
+    unsafe { ret_null_ptr_no_unsafe::<String>() }
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn()
+    -> *const Vec<std::cell::Cell<u32>>
+{
+    unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
+}
+
+const unsafe fn call_unsafe_const_unsafe_fn_immediate() -> i32 {
+    ret_i32_no_unsafe()
+}
+const unsafe fn call_unsafe_generic_const_unsafe_fn_immediate() -> *const String {
+    ret_null_ptr_no_unsafe::<String>()
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate()
+    -> *const Vec<std::cell::Cell<u32>>
+{
+    ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>()
+}
+
+//------------------------------------------------------------------------------
+// NOT OK
+//------------------------------------------------------------------------------
+
+const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
+//~^ dereferencing raw pointers in constant functions
+
+const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
+//~^ dereferencing raw pointers in constant functions
+
+const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
 //~^ dereferencing raw pointers in constant functions
 
 fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
index fafc89d149368..68b782bf0e7ea 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
@@ -1,43 +1,44 @@
 error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe.rs:31:59
+  --> $DIR/min_const_fn_unsafe.rs:60:77
    |
-LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x }
-   |                                                           ^^
+LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
+   |                                                                             ^^^
    |
    = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: unions in const fn are unstable (see issue #51909)
-  --> $DIR/min_const_fn_unsafe.rs:38:5
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:63:70
    |
-LL |     Foo { x: () }.y
-   |     ^^^^^^^^^^^^^^^
+LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x }
+   |                                                                      ^^
    |
-   = help: add #![feature(const_fn_union)] to the crate attributes to enable
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
-  --> $DIR/min_const_fn_unsafe.rs:21:14
+error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
+  --> $DIR/min_const_fn_unsafe.rs:66:83
    |
-LL |     unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
-   |              ^^^^^^^^^^^^^^^^^^^
+LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x }
+   |                                                                                   ^^^
    |
-   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
+   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
 
-error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
-  --> $DIR/min_const_fn_unsafe.rs:24:14
+error[E0658]: unions in const fn are unstable (see issue #51909)
+  --> $DIR/min_const_fn_unsafe.rs:73:5
    |
-LL |     unsafe { ret_null_ptr_no_unsafe::<String>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     Foo { x: () }.y
+   |     ^^^^^^^^^^^^^^^
    |
-   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
+   = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
-error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
-  --> $DIR/min_const_fn_unsafe.rs:28:14
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+  --> $DIR/min_const_fn_unsafe.rs:60:77
    |
-LL |     unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
+   |                                                                             ^^^ dereference of raw pointer
    |
-   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors occurred: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
deleted file mode 100644
index 67a4820612642..0000000000000
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(min_const_unsafe_fn)]
-
-// ok
-const unsafe fn foo4() -> i32 { 42 }
-const unsafe fn foo5<T>() -> *const T { 0 as *const T }
-const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
-const fn no_unsafe() { unsafe {} }
-
-const fn foo8() -> i32 {
-    unsafe { foo4() }
-}
-const fn foo9() -> *const String {
-    unsafe { foo5::<String>() }
-}
-const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
-    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
-}
-const unsafe fn foo8_3() -> i32 {
-    unsafe { foo4() }
-}
-const unsafe fn foo9_3() -> *const String {
-    unsafe { foo5::<String>() }
-}
-const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
-    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
-}
-const unsafe fn foo8_2() -> i32 {
-    foo4()
-}
-const unsafe fn foo9_2() -> *const String {
-    foo5::<String>()
-}
-const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
-    foo6::<Vec<std::cell::Cell<u32>>>()
-}
-const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
-//~^ dereferencing raw pointers in constant functions
-
-const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
-//~^ dereferencing raw pointers in constant functions
-
-const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
-//~^ dereferencing raw pointers in constant functions
-
-fn main() {}
-
-const unsafe fn no_union() {
-    union Foo { x: (), y: () }
-    Foo { x: () }.y
-    //~^ unions in const fn
-}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
deleted file mode 100644
index 63bf9a53e509c..0000000000000
--- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51
-   |
-LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x }
-   |                                                   ^^
-   |
-   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
-
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60
-   |
-LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x }
-   |                                                            ^^^
-   |
-   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
-
-error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
-   |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
-   |                                                              ^^^
-   |
-   = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable
-
-error[E0658]: unions in const fn are unstable (see issue #51909)
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5
-   |
-LL |     Foo { x: () }.y
-   |     ^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(const_fn_union)] to the crate attributes to enable
-
-error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
-  --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62
-   |
-LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe
-   |                                                              ^^^ dereference of raw pointer
-   |
-   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
-
-error: aborting due to 5 previous errors
-
-Some errors occurred: E0133, E0658.
-For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
index f559c23ff0f54..33fcea9818959 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs
@@ -14,7 +14,6 @@
             issue = "0")]
 
 #![feature(rustc_const_unstable, const_fn, foo, foo2)]
-#![feature(min_const_unsafe_fn)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
index 37be2889173f8..2a0ef0e6b9651 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr
@@ -1,23 +1,23 @@
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:41
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:25:41
    |
 LL | const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn`
    |                                         ^^^^^
 
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:42
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:32:42
    |
 LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn`
    |                                          ^^^^^^
 
 error: only int, `bool` and `char` operations are stable in const fn
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:37:33
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:36:33
    |
 LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
    |                                 ^^^^^^^^^^^^^
 
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:45:48
+  --> $DIR/min_const_unsafe_fn_libstd_stability.rs:44:48
    |
 LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other
    |                                                ^^^^^^^^^^^^
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
index 131bc97c85a2a..68205edd63bc9 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs
@@ -14,7 +14,6 @@
             issue = "0")]
 
 #![feature(rustc_const_unstable, const_fn, foo, foo2)]
-#![feature(min_const_unsafe_fn)]
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
index 0b58dc1294be0..6153301518563 100644
--- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr
@@ -1,17 +1,17 @@
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:26:32
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:25:32
    |
 LL | const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn`
    |                                ^^^^^
 
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:33
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:32:33
    |
 LL | const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn`
    |                                 ^^^^^^
 
 error: can only call other `min_const_fn` within a `min_const_fn`
-  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:41:39
+  --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:40:39
    |
 LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn`
    |                                       ^^^^^^^^^^^^
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs
new file mode 100644
index 0000000000000..27e1a111163b1
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs
@@ -0,0 +1,7 @@
+// compile-pass
+
+static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
+
+pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
new file mode 100644
index 0000000000000..4180b1e295ab0
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -0,0 +1,9 @@
+#![feature(const_let)]
+
+static mut STDERR_BUFFER_SPACE: u8 = 0;
+
+pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+//~^ ERROR references in statics may only refer to immutable values
+//~| ERROR static contains unimplemented expression type
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
new file mode 100644
index 0000000000000..f0ae1545056b7
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
@@ -0,0 +1,16 @@
+error[E0017]: references in statics may only refer to immutable values
+  --> $DIR/static_mut_containing_mut_ref2.rs:5:46
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
+
+error[E0019]: static contains unimplemented expression type
+  --> $DIR/static_mut_containing_mut_ref2.rs:5:45
+   |
+LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs
new file mode 100644
index 0000000000000..0bc7faa9afdec
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs
@@ -0,0 +1,8 @@
+#![feature(const_let)]
+
+static mut FOO: (u8, u8) = (42, 43);
+
+static mut BAR: () = unsafe { FOO.0 = 99; };
+//~^ ERROR could not evaluate static initializer
+
+fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr
new file mode 100644
index 0000000000000..cae53c6fee9dd
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr
@@ -0,0 +1,9 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/static_mut_containing_mut_ref3.rs:5:31
+   |
+LL | static mut BAR: () = unsafe { FOO.0 = 99; };
+   |                               ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs
new file mode 100644
index 0000000000000..496ce4fb378ae
--- /dev/null
+++ b/src/test/ui/dead-code-tuple-struct-field.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![deny(dead_code)]
+
+const LEN: usize = 4;
+
+#[derive(Debug)]
+struct Wrapper([u8; LEN]);
+
+fn main() {
+    println!("{:?}", Wrapper([0, 1, 2, 3]));
+}
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs
new file mode 100644
index 0000000000000..264cfa449942c
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs
@@ -0,0 +1,15 @@
+enum PutDown { Set }
+enum AffixHeart { Set }
+enum CauseToBe { Set }
+enum Determine { Set }
+enum TableDishesAction { Set }
+enum Solidify { Set }
+enum UnorderedCollection { Set }
+
+fn setup() -> Set { Set }
+//~^ ERROR cannot find type `Set` in this scope
+//~| ERROR cannot find value `Set` in this scope
+
+fn main() {
+    setup();
+}
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
new file mode 100644
index 0000000000000..6107ca32a5d75
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
@@ -0,0 +1,38 @@
+error[E0412]: cannot find type `Set` in this scope
+  --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:15
+   |
+LL | fn setup() -> Set { Set }
+   |               ^^^ not found in this scope
+help: there is an enum variant `AffixHeart::Set` and 7 others; try using the variant's enum
+   |
+LL | fn setup() -> AffixHeart { Set }
+   |               ^^^^^^^^^^
+LL | fn setup() -> CauseToBe { Set }
+   |               ^^^^^^^^^
+LL | fn setup() -> Determine { Set }
+   |               ^^^^^^^^^
+LL | fn setup() -> PutDown { Set }
+   |               ^^^^^^^
+and 3 other candidates
+
+error[E0425]: cannot find value `Set` in this scope
+  --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
+   |
+LL | fn setup() -> Set { Set }
+   |                     ^^^ not found in this scope
+help: possible candidates are found in other modules, you can import them into scope
+   |
+LL | use AffixHeart::Set;
+   |
+LL | use CauseToBe::Set;
+   |
+LL | use Determine::Set;
+   |
+LL | use PutDown::Set;
+   |
+and 3 other candidates
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr
index 7a786af71bb3f..eb869f5539f36 100644
--- a/src/test/ui/enum/enum-variant-type-2.stderr
+++ b/src/test/ui/enum/enum-variant-type-2.stderr
@@ -5,7 +5,7 @@ LL | fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar`
    |           ^^^^^^^^
    |           |
    |           not a type
-   |           help: you can try using the variant's enum: `Foo`
+   |           help: try using the variant's enum: `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr
index 0ba1ed456635f..12b778f42e22c 100644
--- a/src/test/ui/error-codes/E0069.stderr
+++ b/src/test/ui/error-codes/E0069.stderr
@@ -1,8 +1,10 @@
 error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/E0069.rs:12:5
    |
+LL | fn foo() -> u8 {
+   |             -- expected `u8` because of this return type
 LL |     return;
-   |     ^^^^^^ return type is not ()
+   |     ^^^^^^ return type is not `()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index e277d4e28cb2b..f1d2071bbdb9e 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality.rs:25:5
    |
+LL |         return 1_i32;
+   |                ----- expected because of this statement
+LL |     }
 LL |     0_u32
    |     ^^^^^ expected i32, found u32
    |
diff --git a/src/test/ui/issues/issue-11004.stderr b/src/test/ui/issues/issue-11004.stderr
index 215120c9c25ea..eb5b568b34738 100644
--- a/src/test/ui/issues/issue-11004.stderr
+++ b/src/test/ui/issues/issue-11004.stderr
@@ -2,13 +2,17 @@ error[E0609]: no field `x` on type `*mut A`
   --> $DIR/issue-11004.rs:17:21
    |
 LL |     let x : i32 = n.x; //~ no field `x` on type `*mut A`
-   |                     ^ help: `n` is a native pointer; try dereferencing it: `(*n).x`
+   |                   --^
+   |                   |
+   |                   help: `n` is a raw pointer; try dereferencing it: `(*n).x`
 
 error[E0609]: no field `y` on type `*mut A`
   --> $DIR/issue-11004.rs:18:21
    |
 LL |     let y : f64 = n.y; //~ no field `y` on type `*mut A`
-   |                     ^ help: `n` is a native pointer; try dereferencing it: `(*n).y`
+   |                   --^
+   |                   |
+   |                   help: `n` is a raw pointer; try dereferencing it: `(*n).y`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 39f7d5fcc04bc..a8ab5e8eb7745 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -5,7 +5,7 @@ LL |     fn new() -> NoResult<MyEnum, String> {
    |                 --------^^^^^^^^^^^^^^^^
    |                 |
    |                 did you mean `Result`?
-   |                 help: you can try using the variant's enum: `foo::MyEnum`
+   |                 help: try using the variant's enum: `foo::MyEnum`
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:32:17
@@ -48,7 +48,7 @@ LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               --------^^^^^^^^^^^^^^^^^^^^^
    |               |
    |               did you mean `Result`?
-   |               help: you can try using the variant's enum: `foo::MyEnum`
+   |               help: try using the variant's enum: `foo::MyEnum`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/issues/issue-30535.stderr
index c3838fdb9cf07..35ef227acfce6 100644
--- a/src/test/ui/issues/issue-30535.stderr
+++ b/src/test/ui/issues/issue-30535.stderr
@@ -2,9 +2,10 @@ error[E0573]: expected type, found variant `foo::Foo::FooV`
   --> $DIR/issue-30535.rs:16:8
    |
 LL |     _: foo::Foo::FooV //~ ERROR expected type, found variant `foo::Foo::FooV`
-   |        ^^^^^^^^^^^^^^ not a type
-   |
-   = help: there is an enum variant `foo::Foo::FooV`, try using `foo::Foo`?
+   |        ^^^^^^^^^^^^^^
+   |        |
+   |        not a type
+   |        help: try using the variant's enum: `foo::Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-35075.stderr b/src/test/ui/issues/issue-35075.stderr
index 9b2f17f038b8f..ead07a5f0c8fe 100644
--- a/src/test/ui/issues/issue-35075.stderr
+++ b/src/test/ui/issues/issue-35075.stderr
@@ -2,19 +2,21 @@ error[E0412]: cannot find type `Foo` in this scope
   --> $DIR/issue-35075.rs:12:12
    |
 LL |     inner: Foo<T> //~ ERROR cannot find type `Foo` in this scope
-   |            ^^^---
-   |            |
-   |            not found in this scope
-   |            help: you can try using the variant's enum: `Baz`
+   |            ^^^ not found in this scope
+help: there is an enum variant `Baz::Foo`; try using the variant's enum
+   |
+LL |     inner: Baz //~ ERROR cannot find type `Foo` in this scope
+   |            ^^^
 
 error[E0412]: cannot find type `Foo` in this scope
   --> $DIR/issue-35075.rs:16:9
    |
 LL |     Foo(Foo<T>) //~ ERROR cannot find type `Foo` in this scope
-   |         ^^^---
-   |         |
-   |         not found in this scope
-   |         help: you can try using the variant's enum: `Baz`
+   |         ^^^ not found in this scope
+help: there is an enum variant `Baz::Foo`; try using the variant's enum
+   |
+LL |     Foo(Baz) //~ ERROR cannot find type `Foo` in this scope
+   |         ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr
index fef8de3a28d9e..652e1695a85a6 100644
--- a/src/test/ui/issues/issue-35675.stderr
+++ b/src/test/ui/issues/issue-35675.stderr
@@ -2,10 +2,11 @@ error[E0412]: cannot find type `Apple` in this scope
   --> $DIR/issue-35675.rs:17:29
    |
 LL | fn should_return_fruit() -> Apple {
+   |                             ^^^^^ not found in this scope
+help: there is an enum variant `Fruit::Apple`; try using the variant's enum
+   |
+LL | fn should_return_fruit() -> Fruit {
    |                             ^^^^^
-   |                             |
-   |                             not found in this scope
-   |                             help: you can try using the variant's enum: `Fruit`
 
 error[E0425]: cannot find function `Apple` in this scope
   --> $DIR/issue-35675.rs:19:5
@@ -24,7 +25,7 @@ LL | fn should_return_fruit_too() -> Fruit::Apple {
    |                                 ^^^^^^^^^^^^
    |                                 |
    |                                 not a type
-   |                                 help: you can try using the variant's enum: `Fruit`
+   |                                 help: try using the variant's enum: `Fruit`
 
 error[E0425]: cannot find function `Apple` in this scope
   --> $DIR/issue-35675.rs:25:5
@@ -40,28 +41,29 @@ error[E0573]: expected type, found variant `Ok`
   --> $DIR/issue-35675.rs:29:13
    |
 LL | fn foo() -> Ok {
-   |             ^^ not a type
-   |
-   = help: there is an enum variant `std::prelude::v1::Ok`, try using `std::prelude::v1`?
-   = help: there is an enum variant `std::result::Result::Ok`, try using `std::result::Result`?
+   |             ^^
+   |             |
+   |             not a type
+   |             help: try using the variant's enum: `std::result::Result`
 
 error[E0412]: cannot find type `Variant3` in this scope
   --> $DIR/issue-35675.rs:34:13
    |
 LL | fn bar() -> Variant3 {
-   |             ^^^^^^^^
-   |             |
-   |             not found in this scope
-   |             help: you can try using the variant's enum: `x::Enum`
+   |             ^^^^^^^^ not found in this scope
+help: there is an enum variant `x::Enum::Variant3`; try using the variant's enum
+   |
+LL | fn bar() -> x::Enum {
+   |             ^^^^^^^
 
 error[E0573]: expected type, found variant `Some`
   --> $DIR/issue-35675.rs:38:13
    |
 LL | fn qux() -> Some {
-   |             ^^^^ not a type
-   |
-   = help: there is an enum variant `std::prelude::v1::Option::Some`, try using `std::prelude::v1::Option`?
-   = help: there is an enum variant `std::prelude::v1::Some`, try using `std::prelude::v1`?
+   |             ^^^^
+   |             |
+   |             not a type
+   |             help: try using the variant's enum: `Option`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/parenthesised-deref-suggestion.rs b/src/test/ui/parenthesised-deref-suggestion.rs
new file mode 100644
index 0000000000000..0b4ccdd5a56d4
--- /dev/null
+++ b/src/test/ui/parenthesised-deref-suggestion.rs
@@ -0,0 +1,11 @@
+struct Session {
+    opts: u8,
+}
+
+fn main() {
+    let sess: &Session = &Session { opts: 0 };
+    (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+
+    let x = [0u32];
+    (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+}
diff --git a/src/test/ui/parenthesised-deref-suggestion.stderr b/src/test/ui/parenthesised-deref-suggestion.stderr
new file mode 100644
index 0000000000000..71a2bf67f06ae
--- /dev/null
+++ b/src/test/ui/parenthesised-deref-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0609]: no field `opts` on type `*const Session`
+  --> $DIR/parenthesised-deref-suggestion.rs:7:30
+   |
+LL |     (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session`
+   |                              ^^^^
+help: `(sess as *const Session)` is a raw pointer; try dereferencing it
+   |
+LL |     (*(sess as *const Session)).opts; //~ ERROR no field `opts` on type `*const Session`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0609]: no field `0` on type `[u32; 1]`
+  --> $DIR/parenthesised-deref-suggestion.rs:10:21
+   |
+LL |     (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]`
+   |     ----------------^
+   |     |
+   |     help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/ret-non-nil.stderr b/src/test/ui/ret-non-nil.stderr
index 01f126bd11ea2..e0fdc8c67edf7 100644
--- a/src/test/ui/ret-non-nil.stderr
+++ b/src/test/ui/ret-non-nil.stderr
@@ -2,7 +2,9 @@ error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/ret-non-nil.rs:15:19
    |
 LL | fn g() -> isize { return; }
-   |                   ^^^^^^ return type is not ()
+   |           -----   ^^^^^^ return type is not `()`
+   |           |
+   |           expected `isize` because of this return type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/return/return-unit-from-diverging.stderr b/src/test/ui/return/return-unit-from-diverging.stderr
index 38d4ca37366ff..5a9f0877cc6b6 100644
--- a/src/test/ui/return/return-unit-from-diverging.stderr
+++ b/src/test/ui/return/return-unit-from-diverging.stderr
@@ -1,8 +1,10 @@
 error[E0069]: `return;` in a function whose return type is not `()`
   --> $DIR/return-unit-from-diverging.rs:15:5
    |
+LL | fn fail() -> ! {
+   |              - expected `!` because of this return type
 LL |     return; //~ ERROR in a function whose return type is not
-   |     ^^^^^^ return type is not ()
+   |     ^^^^^^ return type is not `()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
index 13fcbb347c94b..7525f67051567 100644
--- a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
+++ b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
@@ -2,7 +2,9 @@ error[E0609]: no field `f` on type `*const Rec`
   --> $DIR/unsafe-fn-autoderef.rs:29:14
    |
 LL |     return p.f; //~ ERROR no field `f` on type `*const Rec`
-   |              ^ help: `p` is a native pointer; try dereferencing it: `(*p).f`
+   |            --^
+   |            |
+   |            help: `p` is a raw pointer; try dereferencing it: `(*p).f`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variants/variant-used-as-type.stderr b/src/test/ui/variants/variant-used-as-type.stderr
index 972fe8a8a616b..c72729923ef6d 100644
--- a/src/test/ui/variants/variant-used-as-type.stderr
+++ b/src/test/ui/variants/variant-used-as-type.stderr
@@ -3,28 +3,24 @@ error[E0573]: expected type, found variant `Ty::A`
    |
 LL |     B(Ty::A),
    |       ^^^^^ not a type
-help: you can try using the variant's enum
-   |
-LL |     B(Ty),
-   |       ^^
-help: you can try using the variant's enum
+help: try using the variant's enum
    |
 LL |     B(E),
    |       ^
+LL |     B(Ty),
+   |       ^^
 
 error[E0573]: expected type, found variant `E::A`
   --> $DIR/variant-used-as-type.rs:27:6
    |
 LL | impl E::A {}
    |      ^^^^ not a type
-help: you can try using the variant's enum
-   |
-LL | impl Ty {}
-   |      ^^
-help: you can try using the variant's enum
+help: try using the variant's enum
    |
 LL | impl E {}
    |      ^
+LL | impl Ty {}
+   |      ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs
index 191f09b54ee73..983b5d48e60fc 100644
--- a/src/test/ui/write-to-static-mut-in-static.rs
+++ b/src/test/ui/write-to-static-mut-in-static.rs
@@ -12,10 +12,10 @@
 
 pub static mut A: u32 = 0;
 pub static mut B: () = unsafe { A = 1; };
-//~^ ERROR cannot mutate statics in the initializer of another static
+//~^ ERROR could not evaluate static initializer
 
 pub static mut C: u32 = unsafe { C = 1; 0 };
-//~^ ERROR cannot mutate statics in the initializer of another static
+//~^ ERROR cycle detected
 
 pub static D: u32 = D;
 
diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr
index 673a71b4642f3..335f849fb2472 100644
--- a/src/test/ui/write-to-static-mut-in-static.stderr
+++ b/src/test/ui/write-to-static-mut-in-static.stderr
@@ -1,14 +1,28 @@
-error: cannot mutate statics in the initializer of another static
+error[E0080]: could not evaluate static initializer
   --> $DIR/write-to-static-mut-in-static.rs:14:33
    |
 LL | pub static mut B: () = unsafe { A = 1; };
-   |                                 ^^^^^
+   |                                 ^^^^^ tried to modify a static's initial value from another static's initializer
 
-error: cannot mutate statics in the initializer of another static
+error[E0391]: cycle detected when const-evaluating `C`
   --> $DIR/write-to-static-mut-in-static.rs:17:34
    |
 LL | pub static mut C: u32 = unsafe { C = 1; 0 };
    |                                  ^^^^^
+   |
+note: ...which requires const-evaluating `C`...
+  --> $DIR/write-to-static-mut-in-static.rs:17:1
+   |
+LL | pub static mut C: u32 = unsafe { C = 1; 0 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires const-evaluating `C`, completing the cycle
+note: cycle used when const-evaluating + checking `C`
+  --> $DIR/write-to-static-mut-in-static.rs:17:1
+   |
+LL | pub static mut C: u32 = unsafe { C = 1; 0 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
+Some errors occurred: E0080, E0391.
+For more information about an error, try `rustc --explain E0080`.