about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/libcore/iter/mod.rs5
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/mem/manually_drop.rs2
-rw-r--r--src/libcore/num/mod.rs29
-rw-r--r--src/libcore/ptr/const_ptr.rs5
-rw-r--r--src/librustc/lib.rs19
-rw-r--r--src/librustc/middle/mod.rs35
-rw-r--r--src/librustc/mir/interpret/allocation.rs8
-rw-r--r--src/librustc/mir/interpret/queries.rs2
-rw-r--r--src/librustc/query/mod.rs2
-rw-r--r--src/librustc/traits/project.rs3
-rw-r--r--src/librustc/ty/context.rs12
-rw-r--r--src/librustc/ty/instance.rs19
-rw-r--r--src/librustc/ty/query/mod.rs3
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs3
-rw-r--r--src/librustc_interface/passes.rs4
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs22
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs22
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs8
-rw-r--r--src/librustc_mir/interpret/memory.rs62
-rw-r--r--src/librustc_mir/interpret/validity.rs15
-rw-r--r--src/librustc_mir/transform/const_prop.rs71
-rw-r--r--src/librustc_mir/transform/inline.rs13
-rw-r--r--src/librustc_passes/diagnostic_items.rs (renamed from src/librustc/middle/diagnostic_items.rs)26
-rw-r--r--src/librustc_passes/lib.rs6
-rw-r--r--src/librustc_passes/lib_features.rs (renamed from src/librustc/middle/lib_features.rs)44
-rw-r--r--src/librustc_passes/reachable.rs (renamed from src/librustc/middle/reachable.rs)38
-rw-r--r--src/librustc_resolve/resolve_imports.rs26
-rw-r--r--src/librustc_typeck/check/pat.rs31
-rw-r--r--src/libstd/keyword_docs.rs27
-rw-r--r--src/libsyntax_expand/expand.rs11
-rw-r--r--src/test/mir-opt/inline/inline-specialization.rs48
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs24
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr52
-rw-r--r--src/test/ui/consts/huge-values.rs11
-rw-r--r--src/test/ui/consts/trait_specialization.rs65
-rw-r--r--src/test/ui/error-codes/E0308-4.stderr6
-rw-r--r--src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr2
-rw-r--r--src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr2
-rw-r--r--src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs1
-rw-r--r--src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr23
-rw-r--r--src/test/ui/issues/issue-38715.rs2
-rw-r--r--src/test/ui/issues/issue-38715.stderr14
-rw-r--r--src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs3
-rw-r--r--src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr15
-rw-r--r--src/test/ui/match/match-range-fail.stderr4
-rw-r--r--src/test/ui/parser/pat-tuple-5.stderr2
-rw-r--r--src/test/ui/parser/recover-range-pats.stderr48
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules-fail.rs21
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules-fail.stderr26
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules.rs8
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules.stderr12
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.rs6
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.stderr46
-rw-r--r--src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr5
56 files changed, 700 insertions, 323 deletions
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f2a7d1d00cf..b5c8de057d0 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -736,7 +736,7 @@ impl Step for Tidy {
 
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
             builder.info("fmt check");
-            crate::format::format(&builder.build, true);
+            crate::format::format(&builder.build, !builder.config.cmd.bless());
         }
     }
 
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 80294de714d..0d5af3986fb 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -216,6 +216,11 @@
 //! Common iterator adapters include [`map`], [`take`], and [`filter`].
 //! For more, see their documentation.
 //!
+//! If an iterator adapter panics, the iterator will be in an unspecified (but
+//! memory safe) state.  This state is also not guaranteed to stay the same
+//! across versions of Rust, so you should avoid relying on the exact values
+//! returned by an iterator which panicked.
+//!
 //! [`map`]: trait.Iterator.html#method.map
 //! [`take`]: trait.Iterator.html#method.take
 //! [`filter`]: trait.Iterator.html#method.filter
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 7d11dd2800f..590f4e46c1d 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -71,6 +71,8 @@
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
+#![feature(const_if_match)]
+#![feature(const_panic)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
 #![feature(const_ptr_offset_from)]
diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs
index af4635f89f6..36064488eb2 100644
--- a/src/libcore/mem/manually_drop.rs
+++ b/src/libcore/mem/manually_drop.rs
@@ -121,7 +121,7 @@ impl<T: ?Sized> ManuallyDrop<T> {
     /// This function runs the destructor of the contained value and thus the wrapped value
     /// now represents uninitialized data. It is up to the user of this method to ensure the
     /// uninitialized data is not actually used.
-    /// In particular, this function can only be called called at most once
+    /// In particular, this function can only be called at most once
     /// for a given instance of `ManuallyDrop<T>`.
     ///
     /// [`ManuallyDrop::into_inner`]: #method.into_inner
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 8a32479b2ff..14540394cab 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1416,18 +1416,14 @@ $EndFeature, "
 ```"),
             #[stable(feature = "no_panic_abs", since = "1.13.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow_internal_unstable(const_if_match)]
             #[inline]
             pub const fn wrapping_abs(self) -> Self {
-                // sign is -1 (all ones) for negative numbers, 0 otherwise.
-                let sign = self >> ($BITS - 1);
-                // For positive self, sign == 0 so the expression is simply
-                // (self ^ 0).wrapping_sub(0) == self == abs(self).
-                //
-                // For negative self, self ^ sign == self ^ all_ones.
-                // But all_ones ^ self == all_ones - self == -1 - self.
-                // So for negative numbers, (self ^ sign).wrapping_sub(sign) is
-                // (-1 - self).wrapping_sub(-1) == -self == abs(self).
-                (self ^ sign).wrapping_sub(sign)
+                 if self.is_negative() {
+                     self.wrapping_neg()
+                 } else {
+                     self
+                 }
             }
         }
 
@@ -1713,8 +1709,13 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self
             #[inline]
             #[stable(feature = "wrapping", since = "1.7.0")]
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
+            #[allow_internal_unstable(const_if_match)]
             pub const fn overflowing_neg(self) -> (Self, bool) {
-                ((!self).wrapping_add(1), self == Self::min_value())
+                if self == Self::min_value() {
+                    (Self::min_value(), true)
+                } else {
+                    (-self, false)
+                }
             }
         }
 
@@ -2041,7 +2042,11 @@ $EndFeature, "
             #[rustc_const_unstable(feature = "const_int_sign", issue = "53718")]
             #[inline]
             pub const fn signum(self) -> Self {
-                (self > 0) as Self - (self < 0) as Self
+                match self {
+                    n if n > 0 =>  1,
+                    0          =>  0,
+                    _          => -1,
+                }
             }
         }
 
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index e5297a0c1e0..fc3c02e1f06 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -288,10 +288,7 @@ impl<T: ?Sized> *const T {
         T: Sized,
     {
         let pointee_size = mem::size_of::<T>();
-        let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize;
-        // assert that the pointee size is valid in a const eval compatible way
-        // FIXME: do this with a real assert at some point
-        [()][(!ok) as usize];
+        assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
         intrinsics::ptr_offset_from(self, origin)
     }
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 55713aedbcb..76588dfa5e2 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -95,24 +95,7 @@ pub mod hir;
 pub mod ich;
 pub mod infer;
 pub mod lint;
-
-pub mod middle {
-    pub mod cstore;
-    pub mod dependency_format;
-    pub mod diagnostic_items;
-    pub mod exported_symbols;
-    pub mod free_region;
-    pub mod lang_items;
-    pub mod lib_features;
-    pub mod privacy;
-    pub mod reachable;
-    pub mod recursion_limit;
-    pub mod region;
-    pub mod resolve_lifetime;
-    pub mod stability;
-    pub mod weak_lang_items;
-}
-
+pub mod middle;
 pub mod mir;
 pub use rustc_session as session;
 pub mod traits;
diff --git a/src/librustc/middle/mod.rs b/src/librustc/middle/mod.rs
new file mode 100644
index 00000000000..030bcf3bf42
--- /dev/null
+++ b/src/librustc/middle/mod.rs
@@ -0,0 +1,35 @@
+pub mod cstore;
+pub mod dependency_format;
+pub mod exported_symbols;
+pub mod free_region;
+pub mod lang_items;
+pub mod lib_features {
+    use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+    use syntax::symbol::Symbol;
+
+    #[derive(HashStable)]
+    pub struct LibFeatures {
+        // A map from feature to stabilisation version.
+        pub stable: FxHashMap<Symbol, Symbol>,
+        pub unstable: FxHashSet<Symbol>,
+    }
+
+    impl LibFeatures {
+        pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
+            let mut all_features: Vec<_> = self
+                .stable
+                .iter()
+                .map(|(f, s)| (*f, Some(*s)))
+                .chain(self.unstable.iter().map(|f| (*f, None)))
+                .collect();
+            all_features.sort_unstable_by_key(|f| f.0.as_str());
+            all_features
+        }
+    }
+}
+pub mod privacy;
+pub mod recursion_limit;
+pub mod region;
+pub mod resolve_lifetime;
+pub mod stability;
+pub mod weak_lang_items;
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
index 67f1c8072d6..a06b23367e6 100644
--- a/src/librustc/mir/interpret/allocation.rs
+++ b/src/librustc/mir/interpret/allocation.rs
@@ -594,6 +594,14 @@ pub struct AllocationDefinedness {
     ranges: smallvec::SmallVec<[u64; 1]>,
 }
 
+impl AllocationDefinedness {
+    pub fn all_bytes_undef(&self) -> bool {
+        // The `ranges` are run-length encoded and of alternating definedness.
+        // So if `ranges.len() > 1` then the second block is a range of defined.
+        self.initial == false && self.ranges.len() == 1
+    }
+}
+
 /// Transferring the definedness mask to other allocations.
 impl<Tag, Extra> Allocation<Tag, Extra> {
     /// Creates a run-length encoding of the undef mask.
diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs
index e6caa146a62..c593a51e457 100644
--- a/src/librustc/mir/interpret/queries.rs
+++ b/src/librustc/mir/interpret/queries.rs
@@ -18,7 +18,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let substs = InternalSubsts::identity_for_item(self, def_id);
         let instance = ty::Instance::new(def_id, substs);
         let cid = GlobalId { instance, promoted: None };
-        let param_env = self.param_env(def_id);
+        let param_env = self.param_env(def_id).with_reveal_all();
         self.const_eval_validated(param_env.and(cid))
     }
 
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 24841a1ccf4..9b7ae099335 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -510,7 +510,7 @@ rustc_queries! {
     }
 
     Other {
-        query reachable_set(_: CrateNum) -> ReachableSet {
+        query reachable_set(_: CrateNum) -> Lrc<HirIdSet> {
             desc { "reachability" }
         }
 
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 90381895f0a..bcb012ea514 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1028,6 +1028,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // In either case, we handle this by not adding a
                 // candidate for an impl if it contains a `default`
                 // type.
+                //
+                // NOTE: This should be kept in sync with the similar code in
+                // `rustc::ty::instance::resolve_associated_item()`.
                 let node_item =
                     assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id);
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 95860397036..b84b0e4f45d 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2751,22 +2751,10 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         assert_eq!(id, LOCAL_CRATE);
         tcx.crate_name
     };
-    providers.get_lib_features = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        tcx.arena.alloc(middle::lib_features::collect(tcx))
-    };
     providers.get_lang_items = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
         tcx.arena.alloc(middle::lang_items::collect(tcx))
     };
-    providers.diagnostic_items = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        middle::diagnostic_items::collect(tcx)
-    };
-    providers.all_diagnostic_items = |tcx, id| {
-        assert_eq!(id, LOCAL_CRATE);
-        middle::diagnostic_items::collect_all(tcx)
-    };
     providers.maybe_unused_trait_import = |tcx, id| tcx.maybe_unused_trait_imports.contains(&id);
     providers.maybe_unused_extern_crates = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index faa83ceadde..cfd1779c080 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -346,6 +346,25 @@ fn resolve_associated_item<'tcx>(
         traits::VtableImpl(impl_data) => {
             let (def_id, substs) =
                 traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data);
+
+            let resolved_item = tcx.associated_item(def_id);
+
+            // Since this is a trait item, we need to see if the item is either a trait default item
+            // or a specialization because we can't resolve those unless we can `Reveal::All`.
+            // NOTE: This should be kept in sync with the similar code in
+            // `rustc::traits::project::assemble_candidates_from_impls()`.
+            let eligible = if !resolved_item.defaultness.is_default() {
+                true
+            } else if param_env.reveal == traits::Reveal::All {
+                !trait_ref.needs_subst()
+            } else {
+                false
+            };
+
+            if !eligible {
+                return None;
+            }
+
             let substs = tcx.erase_regions(&substs);
             Some(ty::Instance::new(def_id, substs))
         }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 8be0536a18e..f523cee49ec 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -10,7 +10,6 @@ use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use crate::middle::lang_items::{LangItem, LanguageItems};
 use crate::middle::lib_features::LibFeatures;
 use crate::middle::privacy::AccessLevels;
-use crate::middle::reachable::ReachableSet;
 use crate::middle::region;
 use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
 use crate::middle::stability::{self, DeprecationEntry};
@@ -37,7 +36,7 @@ use crate::ty::subst::SubstsRef;
 use crate::ty::util::NeedsDrop;
 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use crate::util::common::ErrorReported;
-use crate::util::nodemap::{DefIdMap, DefIdSet};
+use crate::util::nodemap::{DefIdMap, DefIdSet, HirIdSet};
 use rustc_data_structures::profiling::ProfileCategory::*;
 
 use rustc_data_structures::fingerprint::Fingerprint;
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 07ff5c362eb..5bdb310f9b5 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -65,7 +65,6 @@ fn reachable_non_generics_provider(
 
     let mut reachable_non_generics: DefIdMap<_> = tcx
         .reachable_set(LOCAL_CRATE)
-        .0
         .iter()
         .filter_map(|&hir_id| {
             // We want to ignore some FFI functions that are not exposed from
@@ -313,7 +312,7 @@ fn upstream_monomorphizations_for_provider(
 
 fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
-        !tcx.reachable_set(LOCAL_CRATE).0.contains(&hir_id)
+        !tcx.reachable_set(LOCAL_CRATE).contains(&hir_id)
     } else {
         bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
     }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 9d0ec585c20..b4522f4c665 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -10,7 +10,7 @@ use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::hir::lowering::lower_crate;
 use rustc::lint;
 use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
-use rustc::middle::{self, reachable, resolve_lifetime, stability};
+use rustc::middle::{self, resolve_lifetime, stability};
 use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType};
 use rustc::session::config::{PpMode, PpSourceMode};
 use rustc::session::search_paths::PathKind;
@@ -678,14 +678,12 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
     plugin::build::provide(providers);
     hir::provide(providers);
     mir::provide(providers);
-    reachable::provide(providers);
     resolve_lifetime::provide(providers);
     rustc_privacy::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
     traits::provide(providers);
     stability::provide(providers);
-    reachable::provide(providers);
     rustc_passes::provide(providers);
     rustc_traits::provide(providers);
     middle::region::provide(providers);
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 79221329ead..af6fcb6922a 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -882,9 +882,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 err.span_label(
                     drop_span,
                     format!(
-                        "...but `{}` will be dropped here, when the function `{}` returns",
+                        "...but `{}` will be dropped here, when the {} returns",
                         name,
-                        self.infcx.tcx.hir().name(fn_hir_id),
+                        self.infcx
+                            .tcx
+                            .hir()
+                            .opt_name(fn_hir_id)
+                            .map(|name| format!("function `{}`", name))
+                            .unwrap_or_else(|| {
+                                match &self
+                                    .infcx
+                                    .tcx
+                                    .typeck_tables_of(self.mir_def_id)
+                                    .node_type(fn_hir_id)
+                                    .kind
+                                {
+                                    ty::Closure(..) => "enclosing closure",
+                                    ty::Generator(..) => "enclosing generator",
+                                    kind => bug!("expected closure or generator, found {:?}", kind),
+                                }
+                                .to_string()
+                            })
                     ),
                 );
 
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 745b6aabfa6..6c4b69d9d76 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -212,11 +212,7 @@ pub fn const_eval_validated_provider<'tcx>(
         key.param_env.reveal = Reveal::UserFacing;
         match tcx.const_eval_validated(key) {
             // try again with reveal all as requested
-            Err(ErrorHandled::TooGeneric) => {
-                // Promoteds should never be "too generic" when getting evaluated.
-                // They either don't get evaluated, or we are in a monomorphic context
-                assert!(key.value.promoted.is_none());
-            }
+            Err(ErrorHandled::TooGeneric) => {}
             // dedupliate calls
             other => return other,
         }
@@ -301,10 +297,18 @@ pub fn const_eval_raw_provider<'tcx>(
                 // Ensure that if the above error was either `TooGeneric` or `Reported`
                 // an error must be reported.
                 let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
-                tcx.sess.delay_span_bug(
-                    err.span,
-                    &format!("static eval failure did not emit an error: {:#?}", v),
-                );
+
+                // If this is `Reveal:All`, then we need to make sure an error is reported but if
+                // this is `Reveal::UserFacing`, then it's expected that we could get a
+                // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either
+                // succeed or we'll report this error then.
+                if key.param_env.reveal == Reveal::All {
+                    tcx.sess.delay_span_bug(
+                        err.span,
+                        &format!("static eval failure did not emit an error: {:#?}", v),
+                    );
+                }
+
                 v
             } else if def_id.is_local() {
                 // constant defined in this crate, we can figure out a lint level!
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index c782eda917f..3c0bdd00391 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -742,7 +742,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let kind = match res {
             Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => {
                 let substs = self.tables.node_substs(id);
-                match self.tcx.const_eval_resolve(self.param_env, def_id, substs, Some(span)) {
+                // Use `Reveal::All` here because patterns are always monomorphic even if their function isn't.
+                match self.tcx.const_eval_resolve(
+                    self.param_env.with_reveal_all(),
+                    def_id,
+                    substs,
+                    Some(span),
+                ) {
                     Ok(value) => {
                         let pattern = self.const_to_pat(value, id, span);
                         if !is_associated_const {
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 71e6d3e8ca1..cb676821fd4 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -841,11 +841,38 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
 
         let tcx = self.tcx.tcx;
 
+        // The bits have to be saved locally before writing to dest in case src and dest overlap.
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+
         // This checks relocation edges on the src.
         let src_bytes =
             self.get_raw(src.alloc_id)?.get_bytes_with_undef_and_ptr(&tcx, src, size)?.as_ptr();
         let dest_bytes =
-            self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?.as_mut_ptr();
+            self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?;
+
+        // If `dest_bytes` is empty we just optimize to not run anything for zsts.
+        // See #67539
+        if dest_bytes.is_empty() {
+            return Ok(());
+        }
+
+        let dest_bytes = dest_bytes.as_mut_ptr();
+
+        // Prepare a copy of the undef mask.
+        let compressed = self.get_raw(src.alloc_id)?.compress_undef_range(src, size);
+
+        if compressed.all_bytes_undef() {
+            // Fast path: If all bytes are `undef` then there is nothing to copy. The target range
+            // is marked as undef but we otherwise omit changing the byte representation which may
+            // be arbitrary for undef bytes.
+            // This also avoids writing to the target bytes so that the backing allocation is never
+            // touched if the bytes stay undef for the whole interpreter execution. On contemporary
+            // operating system this can avoid physically allocating the page.
+            let dest_alloc = self.get_raw_mut(dest.alloc_id)?;
+            dest_alloc.mark_definedness(dest, size * length, false);
+            dest_alloc.mark_relocation_range(relocations);
+            return Ok(());
+        }
 
         // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
         // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
@@ -881,8 +908,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             }
         }
 
-        // copy definedness to the destination
-        self.copy_undef_mask(src, dest, size, length)?;
+        // now fill in all the data
+        self.get_raw_mut(dest.alloc_id)?.mark_compressed_undef_range(
+            &compressed,
+            dest,
+            size,
+            length,
+        );
+
         // copy the relocations to the destination
         self.get_raw_mut(dest.alloc_id)?.mark_relocation_range(relocations);
 
@@ -890,29 +923,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     }
 }
 
-/// Undefined bytes
+/// Machine pointer introspection.
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
-    // FIXME: Add a fast version for the common, nonoverlapping case
-    fn copy_undef_mask(
-        &mut self,
-        src: Pointer<M::PointerTag>,
-        dest: Pointer<M::PointerTag>,
-        size: Size,
-        repeat: u64,
-    ) -> InterpResult<'tcx> {
-        // The bits have to be saved locally before writing to dest in case src and dest overlap.
-        assert_eq!(size.bytes() as usize as u64, size.bytes());
-
-        let src_alloc = self.get_raw(src.alloc_id)?;
-        let compressed = src_alloc.compress_undef_range(src, size);
-
-        // now fill in all the data
-        let dest_allocation = self.get_raw_mut(dest.alloc_id)?;
-        dest_allocation.mark_compressed_undef_range(&compressed, dest, size, repeat);
-
-        Ok(())
-    }
-
     pub fn force_ptr(
         &self,
         scalar: Scalar<M::PointerTag>,
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index df8cb5d692b..448a2765fd3 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -580,10 +580,19 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
             }
             ty::Array(tys, ..) | ty::Slice(tys)
                 if {
-                    // This optimization applies only for integer and floating point types
-                    // (i.e., types that can hold arbitrary bytes).
+                    // This optimization applies for types that can hold arbitrary bytes (such as
+                    // integer and floating point types) or for structs or tuples with no fields.
+                    // FIXME(wesleywiser) This logic could be extended further to arbitrary structs
+                    // or tuples made up of integer/floating point types or inhabited ZSTs with no
+                    // padding.
                     match tys.kind {
                         ty::Int(..) | ty::Uint(..) | ty::Float(..) => true,
+                        ty::Tuple(tys) if tys.len() == 0 => true,
+                        ty::Adt(adt_def, _)
+                            if adt_def.is_struct() && adt_def.all_fields().next().is_none() =>
+                        {
+                            true
+                        }
                         _ => false,
                     }
                 } =>
@@ -609,7 +618,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 // Size is not 0, get a pointer.
                 let ptr = self.ecx.force_ptr(mplace.ptr)?;
 
-                // This is the optimization: we just check the entire range at once.
+                // Optimization: we just check the entire range at once.
                 // NOTE: Keep this in sync with the handling of integer and float
                 // types above, in `visit_primitive`.
                 // In run-time mode, we accept pointers in here.  This is actually more
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a6b30ab5e68..c36f7935115 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -6,6 +6,7 @@ use std::cell::Cell;
 
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::DefId;
+use rustc::hir::HirId;
 use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
@@ -20,7 +21,7 @@ use rustc::ty::layout::{
     HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
 };
 use rustc::ty::subst::InternalSubsts;
-use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
+use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::IndexVec;
 use syntax::ast::Mutability;
@@ -260,6 +261,9 @@ struct ConstPropagator<'mir, 'tcx> {
     source_scopes: IndexVec<SourceScope, SourceScopeData>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
     ret: Option<OpTy<'tcx, ()>>,
+    // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
+    // the last known `SourceInfo` here and just keep revisiting it.
+    source_info: Option<SourceInfo>,
 }
 
 impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
@@ -293,13 +297,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         source: MirSource<'tcx>,
     ) -> ConstPropagator<'mir, 'tcx> {
         let def_id = source.def_id();
-        let param_env = tcx.param_env(def_id);
+        let substs = &InternalSubsts::identity_for_item(tcx, def_id);
+        let mut param_env = tcx.param_env(def_id);
+
+        // If we're evaluating inside a monomorphic function, then use `Reveal::All` because
+        // we want to see the same instances that codegen will see. This allows us to `resolve()`
+        // specializations.
+        if !substs.needs_subst() {
+            param_env = param_env.with_reveal_all();
+        }
+
         let span = tcx.def_span(def_id);
         let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ());
         let can_const_prop = CanConstProp::check(body);
 
-        let substs = &InternalSubsts::identity_for_item(tcx, def_id);
-
         let ret = ecx
             .layout_of(body.return_ty().subst(tcx, substs))
             .ok()
@@ -331,6 +342,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
             local_decls: body.local_decls.clone(),
             ret: ret.map(Into::into),
+            source_info: None,
         }
     }
 
@@ -352,6 +364,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
     }
 
+    fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
+        match &self.source_scopes[source_info.scope].local_data {
+            ClearCrossCrate::Set(data) => Some(data.lint_root),
+            ClearCrossCrate::Clear => None,
+        }
+    }
+
     fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
     where
         F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
@@ -360,10 +379,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         // FIXME(eddyb) move this to the `Panic(_)` error case, so that
         // `f(self)` is always called, and that the only difference when the
         // scope's `local_data` is missing, is that the lint isn't emitted.
-        let lint_root = match &self.source_scopes[source_info.scope].local_data {
-            ClearCrossCrate::Set(data) => data.lint_root,
-            ClearCrossCrate::Clear => return None,
-        };
+        let lint_root = self.lint_root(source_info)?;
         let r = match f(self) {
             Ok(val) => Some(val),
             Err(error) => {
@@ -409,13 +425,31 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         r
     }
 
-    fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_constant(
+        &mut self,
+        c: &Constant<'tcx>,
+        source_info: SourceInfo,
+    ) -> Option<Const<'tcx>> {
         self.ecx.tcx.span = c.span;
         match self.ecx.eval_const_to_op(c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
                 let err = error_to_const_error(&self.ecx, error);
-                err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                match self.lint_root(source_info) {
+                    Some(lint_root) if c.literal.needs_subst() => {
+                        // Out of backwards compatibility we cannot report hard errors in unused
+                        // generic functions using associated constants of the generic parameters.
+                        err.report_as_lint(
+                            self.ecx.tcx,
+                            "erroneous constant used",
+                            lint_root,
+                            Some(c.span),
+                        );
+                    }
+                    _ => {
+                        err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                    }
+                }
                 None
             }
         }
@@ -428,7 +462,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *op {
-            Operand::Constant(ref c) => self.eval_constant(c),
+            Operand::Constant(ref c) => self.eval_constant(c, source_info),
             Operand::Move(ref place) | Operand::Copy(ref place) => {
                 self.eval_place(place, source_info)
             }
@@ -495,10 +529,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     let right_size = r.layout.size;
                     let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
                     if r_bits.map_or(false, |b| b >= left_bits as u128) {
-                        let lint_root = match &self.source_scopes[source_info.scope].local_data {
-                            ClearCrossCrate::Set(data) => data.lint_root,
-                            ClearCrossCrate::Clear => return None,
-                        };
+                        let lint_root = self.lint_root(source_info)?;
                         let dir = if *op == BinOp::Shr { "right" } else { "left" };
                         self.tcx.lint_hir(
                             ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
@@ -748,18 +779,19 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
     fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
-        self.eval_constant(constant);
+        self.eval_constant(constant, self.source_info.unwrap());
     }
 
     fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
         trace!("visit_statement: {:?}", statement);
+        let source_info = statement.source_info;
+        self.source_info = Some(source_info);
         if let StatementKind::Assign(box (ref place, ref mut rval)) = statement.kind {
             let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
                 if let Some(local) = place.as_local() {
-                    let source = statement.source_info;
                     let can_const_prop = self.can_const_prop[local];
-                    if let Some(()) = self.const_prop(rval, place_layout, source, place) {
+                    if let Some(()) = self.const_prop(rval, place_layout, source_info, place) {
                         if can_const_prop == ConstPropMode::FullConstProp
                             || can_const_prop == ConstPropMode::OnlyPropagateInto
                         {
@@ -802,8 +834,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
     }
 
     fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
-        self.super_terminator(terminator, location);
         let source_info = terminator.source_info;
+        self.source_info = Some(source_info);
+        self.super_terminator(terminator, location);
         match &mut terminator.kind {
             TerminatorKind::Assert { expected, ref msg, ref mut cond, .. } => {
                 if let Some(value) = self.eval_operand(&cond, source_info) {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index aa0c71ff0f1..98cd3417709 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -8,8 +8,8 @@ use rustc_index::vec::{Idx, IndexVec};
 
 use rustc::mir::visit::*;
 use rustc::mir::*;
-use rustc::ty::subst::{Subst, SubstsRef};
-use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
+use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
 
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 use crate::transform::{MirPass, MirSource};
@@ -66,7 +66,14 @@ impl Inliner<'tcx> {
 
         let mut callsites = VecDeque::new();
 
-        let param_env = self.tcx.param_env(self.source.def_id());
+        let mut param_env = self.tcx.param_env(self.source.def_id());
+
+        let substs = &InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
+
+        // For monomorphic functions, we can use `Reveal::All` to resolve specialized instances.
+        if !substs.needs_subst() {
+            param_env = param_env.with_reveal_all();
+        }
 
         // Only do inlining into fn bodies.
         let id = self.tcx.hir().as_local_hir_id(self.source.def_id()).unwrap();
diff --git a/src/librustc/middle/diagnostic_items.rs b/src/librustc_passes/diagnostic_items.rs
index 32ef1338712..65138fad43b 100644
--- a/src/librustc/middle/diagnostic_items.rs
+++ b/src/librustc_passes/diagnostic_items.rs
@@ -9,12 +9,13 @@
 //!
 //! * Compiler internal types like `Ty` and `TyCtxt`
 
-use crate::hir::def_id::{DefId, LOCAL_CRATE};
-use crate::ty::TyCtxt;
-use crate::util::nodemap::FxHashMap;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::ty::query::Providers;
+use rustc::ty::TyCtxt;
+use rustc::util::nodemap::FxHashMap;
 
-use crate::hir;
-use crate::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use syntax::ast;
 use syntax::symbol::{sym, Symbol};
 
@@ -93,7 +94,7 @@ fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
 }
 
 /// Traverse and collect the diagnostic items in the current
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
+fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
     // Initialize the collector.
     let mut collector = DiagnosticItemCollector::new(tcx);
 
@@ -104,7 +105,7 @@ pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
 }
 
 /// Traverse and collect all the diagnostic items in all crates.
-pub fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
+fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
     // Initialize the collector.
     let mut collector = FxHashMap::default();
 
@@ -117,3 +118,14 @@ pub fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
 
     tcx.arena.alloc(collector)
 }
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.diagnostic_items = |tcx, id| {
+        assert_eq!(id, LOCAL_CRATE);
+        collect(tcx)
+    };
+    providers.all_diagnostic_items = |tcx, id| {
+        assert_eq!(id, LOCAL_CRATE);
+        collect_all(tcx)
+    };
+}
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 5c2ccd28383..da781f2bae5 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -22,17 +22,23 @@ use rustc::ty::query::Providers;
 pub mod ast_validation;
 mod check_const;
 pub mod dead;
+mod diagnostic_items;
 pub mod entry;
 pub mod hir_stats;
 mod intrinsicck;
 pub mod layout_test;
+mod lib_features;
 mod liveness;
 pub mod loops;
+mod reachable;
 
 pub fn provide(providers: &mut Providers<'_>) {
     check_const::provide(providers);
+    diagnostic_items::provide(providers);
     entry::provide(providers);
+    lib_features::provide(providers);
     loops::provide(providers);
     liveness::provide(providers);
     intrinsicck::provide(providers);
+    reachable::provide(providers);
 }
diff --git a/src/librustc/middle/lib_features.rs b/src/librustc_passes/lib_features.rs
index b4ddb09861d..0b0183f3cce 100644
--- a/src/librustc/middle/lib_features.rs
+++ b/src/librustc_passes/lib_features.rs
@@ -4,38 +4,19 @@
 // and `#[unstable (..)]`), but are not declared in one single location
 // (unlike lang features), which means we need to collect them instead.
 
-use crate::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use crate::ty::TyCtxt;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_macros::HashStable;
+use rustc::hir::def_id::LOCAL_CRATE;
+use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::middle::lib_features::LibFeatures;
+use rustc::ty::query::Providers;
+use rustc::ty::TyCtxt;
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
 use syntax::symbol::Symbol;
 use syntax_pos::{sym, Span};
 
 use rustc_error_codes::*;
 
-#[derive(HashStable)]
-pub struct LibFeatures {
-    // A map from feature to stabilisation version.
-    pub stable: FxHashMap<Symbol, Symbol>,
-    pub unstable: FxHashSet<Symbol>,
-}
-
-impl LibFeatures {
-    fn new() -> LibFeatures {
-        LibFeatures { stable: Default::default(), unstable: Default::default() }
-    }
-
-    pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
-        let mut all_features: Vec<_> = self
-            .stable
-            .iter()
-            .map(|(f, s)| (*f, Some(*s)))
-            .chain(self.unstable.iter().map(|f| (*f, None)))
-            .collect();
-        all_features.sort_unstable_by_key(|f| f.0.as_str());
-        all_features
-    }
+fn new_lib_features() -> LibFeatures {
+    LibFeatures { stable: Default::default(), unstable: Default::default() }
 }
 
 pub struct LibFeatureCollector<'tcx> {
@@ -45,7 +26,7 @@ pub struct LibFeatureCollector<'tcx> {
 
 impl LibFeatureCollector<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> {
-        LibFeatureCollector { tcx, lib_features: LibFeatures::new() }
+        LibFeatureCollector { tcx, lib_features: new_lib_features() }
     }
 
     fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
@@ -142,7 +123,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
     }
 }
 
-pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
+fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     let krate = tcx.hir().krate();
     for attr in krate.non_exported_macro_attrs {
@@ -151,3 +132,10 @@ pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
     intravisit::walk_crate(&mut collector, krate);
     collector.lib_features
 }
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.get_lib_features = |tcx, id| {
+        assert_eq!(id, LOCAL_CRATE);
+        tcx.arena.alloc(collect(tcx))
+    };
+}
diff --git a/src/librustc/middle/reachable.rs b/src/librustc_passes/reachable.rs
index c6598f2d328..5241d9ea43f 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -5,23 +5,22 @@
 // makes all other generics or inline functions that it references
 // reachable as well.
 
-use crate::hir::def::{DefKind, Res};
-use crate::hir::def_id::{CrateNum, DefId};
-use crate::hir::Node;
-use crate::hir::{CodegenFnAttrFlags, CodegenFnAttrs};
-use crate::middle::privacy;
-use crate::session::config;
-use crate::ty::query::Providers;
-use crate::ty::{self, TyCtxt};
-use crate::util::nodemap::{FxHashSet, HirIdSet};
+use rustc::hir::def::{DefKind, Res};
+use rustc::hir::def_id::{CrateNum, DefId};
+use rustc::hir::Node;
+use rustc::hir::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc::middle::privacy;
+use rustc::session::config;
+use rustc::ty::query::Providers;
+use rustc::ty::{self, TyCtxt};
+use rustc::util::nodemap::{FxHashSet, HirIdSet};
 use rustc_data_structures::sync::Lrc;
 
-use crate::hir;
-use crate::hir::def_id::LOCAL_CRATE;
-use crate::hir::intravisit;
-use crate::hir::intravisit::{NestedVisitorMap, Visitor};
-use crate::hir::itemlikevisit::ItemLikeVisitor;
-use rustc_macros::HashStable;
+use rustc::hir;
+use rustc::hir::def_id::LOCAL_CRATE;
+use rustc::hir::intravisit;
+use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc_target::spec::abi::Abi;
 
 // Returns true if the given item must be inlined because it may be
@@ -378,12 +377,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
     }
 }
 
-// We introduce a new-type here, so we can have a specialized HashStable
-// implementation for it.
-#[derive(Clone, HashStable)]
-pub struct ReachableSet(pub Lrc<HirIdSet>);
-
-fn reachable_set(tcx: TyCtxt<'_>, crate_num: CrateNum) -> ReachableSet {
+fn reachable_set(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Lrc<HirIdSet> {
     debug_assert!(crate_num == LOCAL_CRATE);
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
@@ -429,7 +423,7 @@ fn reachable_set(tcx: TyCtxt<'_>, crate_num: CrateNum) -> ReachableSet {
     debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols);
 
     // Return the set of reachable symbols.
-    ReachableSet(Lrc::new(reachable_context.reachable_symbols))
+    Lrc::new(reachable_context.reachable_symbols)
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 800c40ffdb1..afbfb647b3c 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -528,31 +528,7 @@ impl<'a> Resolver<'a> {
                         resolution.shadowed_glob = Some(glob_binding);
                     }
                     (false, false) => {
-                        if let (&NameBindingKind::Res(_, true), &NameBindingKind::Res(_, true)) =
-                            (&old_binding.kind, &binding.kind)
-                        {
-                            this.session
-                                .struct_span_err(
-                                    binding.span,
-                                    &format!(
-                                        "a macro named `{}` has already been exported",
-                                        key.ident
-                                    ),
-                                )
-                                .span_label(
-                                    binding.span,
-                                    format!("`{}` already exported", key.ident),
-                                )
-                                .span_note(
-                                    old_binding.span,
-                                    "previous macro export is now shadowed",
-                                )
-                                .emit();
-
-                            resolution.binding = Some(binding);
-                        } else {
-                            return Err(old_binding);
-                        }
+                        return Err(old_binding);
                     }
                 }
             } else {
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 156126a748a..2f53378303b 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -353,13 +353,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_range(
         &self,
         span: Span,
-        begin: &'tcx hir::Expr<'tcx>,
-        end: &'tcx hir::Expr<'tcx>,
+        lhs: &'tcx hir::Expr<'tcx>,
+        rhs: &'tcx hir::Expr<'tcx>,
         expected: Ty<'tcx>,
         discrim_span: Option<Span>,
     ) -> Option<Ty<'tcx>> {
-        let lhs_ty = self.check_expr(begin);
-        let rhs_ty = self.check_expr(end);
+        let lhs_ty = self.check_expr(lhs);
+        let rhs_ty = self.check_expr(rhs);
 
         // Check that both end-points are of numeric or char type.
         let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error();
@@ -367,7 +367,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let rhs_fail = !numeric_or_char(rhs_ty);
 
         if lhs_fail || rhs_fail {
-            self.emit_err_pat_range(span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
+            self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
             return None;
         }
 
@@ -376,11 +376,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let common_type = self.resolve_vars_if_possible(&lhs_ty);
 
         // Subtyping doesn't matter here, as the value is some kind of scalar.
-        self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span);
-        self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span);
+        let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
+            self.demand_eqtype_pat_diag(x_span, expected, x_ty, discrim_span).map(|mut err| {
+                self.endpoint_has_type(&mut err, y_span, y_ty);
+                err.emit();
+            });
+        };
+        demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
+        demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);
+
         Some(common_type)
     }
 
+    fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
+        if !ty.references_error() {
+            err.span_label(span, &format!("this is of type `{}`", ty));
+        }
+    }
+
     fn emit_err_pat_range(
         &self,
         span: Span,
@@ -408,9 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
         let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
             err.span_label(first_span, &msg(first_ty));
-            if !second_ty.references_error() {
-                err.span_label(second_span, &format!("this is of type `{}`", second_ty));
-            }
+            self.endpoint_has_type(&mut err, second_span, second_ty);
         };
         if lhs_fail && rhs_fail {
             err.span_label(begin_span, &msg(lhs_ty));
diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs
index 7901c8197b5..5c7ee9bded9 100644
--- a/src/libstd/keyword_docs.rs
+++ b/src/libstd/keyword_docs.rs
@@ -1149,20 +1149,39 @@ mod where_keyword {}
 //
 /// Return a [`Future`] instead of blocking the current thread.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// Use `async` in front of `fn`, `closure`, or a `block` to turn the marked code into a `Future`.
+/// As such the code will not be run immediately, but will only be evaluated when the returned
+/// future is `.await`ed.
+///
+/// We have written an [async book] detailing async/await and trade-offs compared to using threads.
+///
+/// ## Editions
+///
+/// `async` is a keyword from the 2018 edition onwards.
+///
+/// It is available for use in stable rust from version 1.39 onwards.
 ///
 /// [`Future`]: ./future/trait.Future.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// [async book]: https://rust-lang.github.io/async-book/
 mod async_keyword {}
 
 #[doc(keyword = "await")]
 //
 /// Suspend execution until the result of a [`Future`] is ready.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `.await`ing a future will suspend the current function's execution until the `executor`
+/// has run the future to completion.
+///
+/// Read the [async book] for details on how async/await and executors work.
+///
+/// ## Editions
+///
+/// `await` is a keyword from the 2018 edition onwards.
+///
+/// It is available for use in stable rust from version 1.39 onwards.
 ///
 /// [`Future`]: ./future/trait.Future.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// [async book]: https://rust-lang.github.io/async-book/
 mod await_keyword {}
 
 #[doc(keyword = "dyn")]
diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs
index 4df51ff41f3..089dd471f3b 100644
--- a/src/libsyntax_expand/expand.rs
+++ b/src/libsyntax_expand/expand.rs
@@ -717,13 +717,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         let kind = match item {
-            Annotatable::Item(item) => match &item.kind {
-                ItemKind::Mod(m) if m.inline => "modules",
-                _ => return,
-            },
-            Annotatable::TraitItem(_) | Annotatable::ImplItem(_) | Annotatable::ForeignItem(_) => {
-                return;
-            }
+            Annotatable::Item(_)
+            | Annotatable::TraitItem(_)
+            | Annotatable::ImplItem(_)
+            | Annotatable::ForeignItem(_) => return,
             Annotatable::Stmt(_) => "statements",
             Annotatable::Expr(_) => "expressions",
             Annotatable::Arm(..)
diff --git a/src/test/mir-opt/inline/inline-specialization.rs b/src/test/mir-opt/inline/inline-specialization.rs
new file mode 100644
index 00000000000..9591019bb4f
--- /dev/null
+++ b/src/test/mir-opt/inline/inline-specialization.rs
@@ -0,0 +1,48 @@
+#![feature(specialization)]
+
+fn main() {
+    let x = <Vec::<()> as Foo>::bar();
+}
+
+trait Foo {
+    fn bar() -> u32;
+}
+
+impl<T> Foo for Vec<T> {
+    #[inline(always)]
+    default fn bar() -> u32 { 123 }
+}
+
+// END RUST SOURCE
+// START rustc.main.Inline.before.mir
+// let mut _0: ();
+// let _1: u32;
+// scope 1 {
+//   debug x => _1;
+// }
+// bb0: {
+//   StorageLive(_1);
+//   _1 = const <std::vec::Vec<()> as Foo>::bar() -> bb1;
+// }
+// bb1: {
+//   _0 = ();
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.Inline.before.mir
+// START rustc.main.Inline.after.mir
+// let mut _0: ();
+// let _1: u32;
+// scope 1 {
+//   debug x => _1;
+// }
+// scope 2 {
+// }
+// bb0: {
+//   StorageLive(_1);
+//   _1 = const 123u32;
+//   _0 = ();
+//   StorageDead(_1);
+//   return;
+// }
+// END rustc.main.Inline.after.mir
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
new file mode 100644
index 00000000000..f18e00fd633
--- /dev/null
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
@@ -0,0 +1,24 @@
+#![feature(const_fn)]
+#![feature(const_transmute)]
+
+const fn foo() -> ! {
+    unsafe { std::mem::transmute(()) }
+    //~^ WARN any use of this value will cause an error [const_err]
+    //~| WARN the type `!` does not permit zero-initialization [invalid_value]
+}
+
+#[derive(Clone, Copy)]
+enum Empty { }
+
+#[warn(const_err)]
+const FOO: [Empty; 3] = [foo(); 3];
+
+#[warn(const_err)]
+const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+//~^ ERROR it is undefined behavior to use this value
+//~| WARN the type `Empty` does not permit zero-initialization
+
+fn main() {
+    FOO;
+    BAR;
+}
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
new file mode 100644
index 00000000000..bde7f2536fa
--- /dev/null
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr
@@ -0,0 +1,52 @@
+warning: any use of this value will cause an error
+  --> $DIR/validate_uninhabited_zsts.rs:5:14
+   |
+LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              entering unreachable code
+   |              inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26
+...
+LL | const FOO: [Empty; 3] = [foo(); 3];
+   | -----------------------------------
+   |
+note: lint level defined here
+  --> $DIR/validate_uninhabited_zsts.rs:13:8
+   |
+LL | #[warn(const_err)]
+   |        ^^^^^^^^^
+
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/validate_uninhabited_zsts.rs:17:1
+   |
+LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+warning: the type `!` does not permit zero-initialization
+  --> $DIR/validate_uninhabited_zsts.rs:5:14
+   |
+LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              this code causes undefined behavior when executed
+   |              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: `#[warn(invalid_value)]` on by default
+   = note: The never type (`!`) has no valid value
+
+warning: the type `Empty` does not permit zero-initialization
+  --> $DIR/validate_uninhabited_zsts.rs:17:35
+   |
+LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+   |                                   |
+   |                                   this code causes undefined behavior when executed
+   |                                   help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+   |
+   = note: 0-variant enums have no valid value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/huge-values.rs b/src/test/ui/consts/huge-values.rs
new file mode 100644
index 00000000000..ab09922d761
--- /dev/null
+++ b/src/test/ui/consts/huge-values.rs
@@ -0,0 +1,11 @@
+// build-pass
+// ignore-32bit
+
+#[derive(Clone, Copy)]
+struct Foo;
+
+fn main() {
+    let _ = [(); 4_000_000_000];
+    let _ = [0u8; 4_000_000_000];
+    let _ = [Foo; 4_000_000_000];
+}
diff --git a/src/test/ui/consts/trait_specialization.rs b/src/test/ui/consts/trait_specialization.rs
new file mode 100644
index 00000000000..8010d2fe1ae
--- /dev/null
+++ b/src/test/ui/consts/trait_specialization.rs
@@ -0,0 +1,65 @@
+// ignore-wasm32-bare which doesn't support `std::process:exit()`
+// compile-flags: -Zmir-opt-level=2
+// run-pass
+
+// Tests that specialization does not cause optimizations running on polymorphic MIR to resolve
+// to a `default` implementation.
+
+#![feature(specialization)]
+
+trait Marker {}
+
+trait SpecializedTrait {
+    const CONST_BOOL: bool;
+    const CONST_STR: &'static str;
+    fn method() -> &'static str;
+}
+impl <T> SpecializedTrait for T {
+    default const CONST_BOOL: bool = false;
+    default const CONST_STR: &'static str = "in default impl";
+    #[inline(always)]
+    default fn method() -> &'static str {
+        "in default impl"
+    }
+}
+impl <T: Marker> SpecializedTrait for T {
+    const CONST_BOOL: bool = true;
+    const CONST_STR: &'static str = "in specialized impl";
+    fn method() -> &'static str {
+        "in specialized impl"
+    }
+}
+
+fn const_bool<T>() -> &'static str {
+    if <T as SpecializedTrait>::CONST_BOOL {
+        "in specialized impl"
+    } else {
+        "in default impl"
+    }
+}
+fn const_str<T>() -> &'static str {
+    <T as SpecializedTrait>::CONST_STR
+}
+fn run_method<T>() -> &'static str {
+    <T as SpecializedTrait>::method()
+}
+
+struct TypeA;
+impl Marker for TypeA {}
+struct TypeB;
+
+#[inline(never)]
+fn exit_if_not_eq(left: &str, right: &str) {
+    if left != right {
+        std::process::exit(1);
+    }
+}
+
+pub fn main() {
+    exit_if_not_eq("in specialized impl", const_bool::<TypeA>());
+    exit_if_not_eq("in default impl", const_bool::<TypeB>());
+    exit_if_not_eq("in specialized impl", const_str::<TypeA>());
+    exit_if_not_eq("in default impl", const_str::<TypeB>());
+    exit_if_not_eq("in specialized impl", run_method::<TypeA>());
+    exit_if_not_eq("in default impl", run_method::<TypeB>());
+}
diff --git a/src/test/ui/error-codes/E0308-4.stderr b/src/test/ui/error-codes/E0308-4.stderr
index 127fdaadbc5..46805d6e13b 100644
--- a/src/test/ui/error-codes/E0308-4.stderr
+++ b/src/test/ui/error-codes/E0308-4.stderr
@@ -1,10 +1,12 @@
 error[E0308]: mismatched types
-  --> $DIR/E0308-4.rs:4:9
+  --> $DIR/E0308-4.rs:4:15
    |
 LL |     match x {
    |           - this match expression has type `u8`
 LL |         0u8..=3i8 => (),
-   |         ^^^^^^^^^ expected `u8`, found `i8`
+   |         ---   ^^^ expected `u8`, found `i8`
+   |         |
+   |         this is of type `u8`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
index 2029cfaf75d..04538cd74b1 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
 LL |         [_, 99.., _] => {},
-   |             ^^^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `std::ops::Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
index 6a88d05837a..c918d0a385c 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
 LL |         [_, 99..] => {},
-   |             ^^^^ expected struct `std::ops::Range`, found integer
+   |             ^^ expected struct `std::ops::Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
index 95e58b1d48c..1557f592b2a 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs
@@ -6,6 +6,7 @@ fn main() {
         //~^ ERROR `..X` range patterns are not supported
         //~| ERROR mismatched types
         //~| ERROR mismatched types
+        //~| ERROR mismatched types
         _ => {},
     }
 }
diff --git a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
index 5c49fbe4c5c..e6ee3817b35 100644
--- a/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr
@@ -5,12 +5,12 @@ LL |         [..9, 99..100, _] => {},
    |          ^^^ help: try using the minimum value for the type: `MIN..9`
 
 error[E0308]: mismatched types
-  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
    |
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
 LL |         [..9, 99..100, _] => {},
-   |          ^^^ expected struct `std::ops::Range`, found integer
+   |            ^ expected struct `std::ops::Range`, found integer
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
@@ -21,11 +21,26 @@ error[E0308]: mismatched types
 LL |     match [5..4, 99..105, 43..44] {
    |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
 LL |         [..9, 99..100, _] => {},
-   |               ^^^^^^^ expected struct `std::ops::Range`, found integer
+   |               ^^  --- this is of type `{integer}`
+   |               |
+   |               expected struct `std::ops::Range`, found integer
+   |
+   = note: expected struct `std::ops::Range<{integer}>`
+                found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
+   |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this match expression has type `std::ops::Range<{integer}>`
+LL |         [..9, 99..100, _] => {},
+   |               --  ^^^ expected struct `std::ops::Range`, found integer
+   |               |
+   |               this is of type `{integer}`
    |
    = note: expected struct `std::ops::Range<{integer}>`
                 found type `{integer}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-38715.rs b/src/test/ui/issues/issue-38715.rs
index 7e9defab588..9a9a501cae1 100644
--- a/src/test/ui/issues/issue-38715.rs
+++ b/src/test/ui/issues/issue-38715.rs
@@ -2,6 +2,6 @@
 macro_rules! foo { ($i:ident) => {} }
 
 #[macro_export]
-macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
+macro_rules! foo { () => {} } //~ ERROR the name `foo` is defined multiple times
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-38715.stderr b/src/test/ui/issues/issue-38715.stderr
index d7c4f88ff50..c87d9f7360b 100644
--- a/src/test/ui/issues/issue-38715.stderr
+++ b/src/test/ui/issues/issue-38715.stderr
@@ -1,14 +1,14 @@
-error: a macro named `foo` has already been exported
+error[E0428]: the name `foo` is defined multiple times
   --> $DIR/issue-38715.rs:5:1
    |
+LL | macro_rules! foo { ($i:ident) => {} }
+   | ---------------- previous definition of the macro `foo` here
+...
 LL | macro_rules! foo { () => {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported
-   |
-note: previous macro export is now shadowed
-  --> $DIR/issue-38715.rs:2:1
+   | ^^^^^^^^^^^^^^^^ `foo` redefined here
    |
-LL | macro_rules! foo { ($i:ident) => {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `foo` must be defined only once in the macro namespace of this module
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs
new file mode 100644
index 00000000000..19d7f019047
--- /dev/null
+++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.rs
@@ -0,0 +1,3 @@
+fn main() {
+    [0].iter().flat_map(|a| [0].iter().map(|_| &a)); //~ ERROR `a` does not live long enough
+}
diff --git a/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr
new file mode 100644
index 00000000000..cb0b481e748
--- /dev/null
+++ b/src/test/ui/lifetimes/unnamed-closure-doesnt-life-long-enough-issue-67634.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/unnamed-closure-doesnt-life-long-enough-issue-67634.rs:2:49
+   |
+LL |     [0].iter().flat_map(|a| [0].iter().map(|_| &a));
+   |                                             -   ^- ...but `a` will be dropped here, when the enclosing closure returns
+   |                                             |   |
+   |                                             |   `a` would have to be valid for `'_`...
+   |                                             has type `&i32`
+   |
+   = note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr
index adaaf29aae4..64105dc73d3 100644
--- a/src/test/ui/match/match-range-fail.stderr
+++ b/src/test/ui/match/match-range-fail.stderr
@@ -28,7 +28,9 @@ error[E0308]: mismatched types
   --> $DIR/match-range-fail.rs:18:9
    |
 LL |         'c' ..= 100 => { }
-   |         ^^^^^^^^^^^ expected integer, found `char`
+   |         ^^^     --- this is of type `{integer}`
+   |         |
+   |         expected integer, found `char`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/pat-tuple-5.stderr b/src/test/ui/parser/pat-tuple-5.stderr
index 3579a2c4e09..5b0253cd273 100644
--- a/src/test/ui/parser/pat-tuple-5.stderr
+++ b/src/test/ui/parser/pat-tuple-5.stderr
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
 LL |     match (0, 1) {
    |           ------ this match expression has type `({integer}, {integer})`
 LL |         (PAT ..) => {}
-   |          ^^^^^^ expected tuple, found `u8`
+   |          ^^^ expected tuple, found `u8`
    |
    = note: expected tuple `({integer}, {integer})`
                found type `u8`
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index af03b577548..50a44192707 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -417,13 +417,17 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:21:12
    |
 LL |     if let .0..Y = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |            ^^  - this is of type `u8`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:23:12
+  --> $DIR/recover-range-pats.rs:23:16
    |
 LL |     if let X.. .0 = 0 {}
-   |            ^^^^^^ expected integer, found floating-point number
+   |            -   ^^ expected integer, found floating-point number
+   |            |
+   |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:32:12
@@ -445,13 +449,17 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:34:12
    |
 LL |     if let .0..=Y = 0 {}
-   |            ^^^^^^ expected integer, found floating-point number
+   |            ^^   - this is of type `u8`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:36:12
+  --> $DIR/recover-range-pats.rs:36:16
    |
 LL |     if let X..=.0 = 0 {}
-   |            ^^^^^^ expected integer, found floating-point number
+   |            -   ^^ expected integer, found floating-point number
+   |            |
+   |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:45:12
@@ -473,13 +481,17 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:49:12
    |
 LL |     if let .0...Y = 0 {}
-   |            ^^^^^^ expected integer, found floating-point number
+   |            ^^   - this is of type `u8`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:52:12
+  --> $DIR/recover-range-pats.rs:52:17
    |
 LL |     if let X... .0 = 0 {}
-   |            ^^^^^^^ expected integer, found floating-point number
+   |            -    ^^ expected integer, found floating-point number
+   |            |
+   |            this is of type `u8`
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:60:12
@@ -491,7 +503,7 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:62:12
    |
 LL |     if let .0.. = 0 {}
-   |            ^^^^ expected integer, found floating-point number
+   |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:70:12
@@ -503,7 +515,7 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:72:12
    |
 LL |     if let .0..= = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:82:12
@@ -515,7 +527,7 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:85:12
    |
 LL |     if let .0... = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |            ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:94:14
@@ -524,10 +536,10 @@ LL |     if let ..true = 0 {}
    |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:96:12
+  --> $DIR/recover-range-pats.rs:96:15
    |
 LL |     if let .. .0 = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:104:15
@@ -536,10 +548,10 @@ LL |     if let ..=true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:106:12
+  --> $DIR/recover-range-pats.rs:106:15
    |
 LL |     if let ..=.0 = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |               ^^ expected integer, found floating-point number
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:116:15
@@ -548,10 +560,10 @@ LL |     if let ...true = 0 {}
    |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/recover-range-pats.rs:119:12
+  --> $DIR/recover-range-pats.rs:119:15
    |
 LL |     if let ....3 = 0 {}
-   |            ^^^^^ expected integer, found floating-point number
+   |               ^^ expected integer, found floating-point number
 
 error: aborting due to 85 previous errors
 
diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.rs b/src/test/ui/proc-macro/attributes-on-modules-fail.rs
index c8bc0b34374..c506e903e7f 100644
--- a/src/test/ui/proc-macro/attributes-on-modules-fail.rs
+++ b/src/test/ui/proc-macro/attributes-on-modules-fail.rs
@@ -3,7 +3,7 @@
 #[macro_use]
 extern crate test_macros;
 
-#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
+#[identity_attr]
 mod m {
     pub struct X;
 
@@ -19,11 +19,28 @@ mod n {}
 #[empty_attr]
 mod module; //~ ERROR non-inline modules in proc macro input are unstable
 
-#[empty_attr] //~ ERROR custom attributes cannot be applied to modules
+#[empty_attr]
 mod outer {
     mod inner; //~ ERROR non-inline modules in proc macro input are unstable
 
     mod inner_inline {} // OK
 }
 
+#[derive(Empty)]
+struct S {
+    field: [u8; {
+        #[path = "outer/inner.rs"]
+        mod inner; //~ ERROR non-inline modules in proc macro input are unstable
+        mod inner_inline {} // OK
+        0
+    }]
+}
+
+#[identity_attr]
+fn f() {
+    #[path = "outer/inner.rs"]
+    mod inner; //~ ERROR non-inline modules in proc macro input are unstable
+    mod inner_inline {} // OK
+}
+
 fn main() {}
diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
index 34a5a5aaa54..74b9932a916 100644
--- a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
+++ b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
@@ -1,12 +1,3 @@
-error[E0658]: custom attributes cannot be applied to modules
-  --> $DIR/attributes-on-modules-fail.rs:6:1
-   |
-LL | #[identity_attr]
-   | ^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
-   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
 error: `derive` may only be applied to structs, enums and unions
   --> $DIR/attributes-on-modules-fail.rs:16:1
    |
@@ -31,11 +22,20 @@ LL |     mod inner;
    = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to modules
-  --> $DIR/attributes-on-modules-fail.rs:22:1
+error[E0658]: non-inline modules in proc macro input are unstable
+  --> $DIR/attributes-on-modules-fail.rs:33:9
+   |
+LL |         mod inner;
+   |         ^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
+   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+  --> $DIR/attributes-on-modules-fail.rs:42:5
    |
-LL | #[empty_attr]
-   | ^^^^^^^^^^^^^
+LL |     mod inner;
+   |     ^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
diff --git a/src/test/ui/proc-macro/attributes-on-modules.rs b/src/test/ui/proc-macro/attributes-on-modules.rs
index 12c3ac6d947..6c73b0bf19c 100644
--- a/src/test/ui/proc-macro/attributes-on-modules.rs
+++ b/src/test/ui/proc-macro/attributes-on-modules.rs
@@ -1,13 +1,19 @@
+// check-pass
 // aux-build:test-macros.rs
 
 #[macro_use]
 extern crate test_macros;
 
-#[identity_attr] //~ ERROR custom attributes cannot be applied to modules
+#[identity_attr]
 mod m {
     pub struct S;
 }
 
+#[identity_attr]
+fn f() {
+    mod m {}
+}
+
 fn main() {
     let s = m::S;
 }
diff --git a/src/test/ui/proc-macro/attributes-on-modules.stderr b/src/test/ui/proc-macro/attributes-on-modules.stderr
deleted file mode 100644
index df75f0bf4b1..00000000000
--- a/src/test/ui/proc-macro/attributes-on-modules.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: custom attributes cannot be applied to modules
-  --> $DIR/attributes-on-modules.rs:6:1
-   |
-LL | #[identity_attr]
-   | ^^^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
-   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs
index 591c1e039bd..5df6ac422ac 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.rs
+++ b/src/test/ui/proc-macro/proc-macro-gates.rs
@@ -10,12 +10,8 @@ fn _test_inner() {
     #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
 }
 
-#[empty_attr] //~ ERROR: custom attributes cannot be applied to modules
-mod _test2 {}
-
 mod _test2_inner {
-    #![empty_attr] //~ ERROR: custom attributes cannot be applied to modules
-          //~| ERROR: non-builtin inner attributes are unstable
+    #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable
 }
 
 #[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
index e939434243b..fff96572e34 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -8,7 +8,7 @@ LL |     #![empty_attr]
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
 
 error[E0658]: non-builtin inner attributes are unstable
-  --> $DIR/proc-macro-gates.rs:17:5
+  --> $DIR/proc-macro-gates.rs:14:5
    |
 LL |     #![empty_attr]
    |     ^^^^^^^^^^^^^^
@@ -16,32 +16,14 @@ LL |     #![empty_attr]
    = note: for more information, see https://github.com/rust-lang/rust/issues/54726
    = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
 
-error[E0658]: custom attributes cannot be applied to modules
-  --> $DIR/proc-macro-gates.rs:13:1
-   |
-LL | #[empty_attr]
-   | ^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
-   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
-error[E0658]: custom attributes cannot be applied to modules
-  --> $DIR/proc-macro-gates.rs:17:5
-   |
-LL |     #![empty_attr]
-   |     ^^^^^^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/54727
-   = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
-
 error: key-value macro attributes are not supported
-  --> $DIR/proc-macro-gates.rs:21:1
+  --> $DIR/proc-macro-gates.rs:17:1
    |
 LL | #[empty_attr = "y"]
    | ^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: custom attributes cannot be applied to statements
-  --> $DIR/proc-macro-gates.rs:30:5
+  --> $DIR/proc-macro-gates.rs:26:5
    |
 LL |     #[empty_attr]
    |     ^^^^^^^^^^^^^
@@ -50,7 +32,7 @@ LL |     #[empty_attr]
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: custom attributes cannot be applied to statements
-  --> $DIR/proc-macro-gates.rs:34:5
+  --> $DIR/proc-macro-gates.rs:30:5
    |
 LL |     #[empty_attr]
    |     ^^^^^^^^^^^^^
@@ -59,7 +41,7 @@ LL |     #[empty_attr]
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: custom attributes cannot be applied to statements
-  --> $DIR/proc-macro-gates.rs:38:5
+  --> $DIR/proc-macro-gates.rs:34:5
    |
 LL |     #[empty_attr]
    |     ^^^^^^^^^^^^^
@@ -68,7 +50,7 @@ LL |     #[empty_attr]
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: custom attributes cannot be applied to expressions
-  --> $DIR/proc-macro-gates.rs:42:14
+  --> $DIR/proc-macro-gates.rs:38:14
    |
 LL |     let _x = #[identity_attr] 2;
    |              ^^^^^^^^^^^^^^^^
@@ -77,7 +59,7 @@ LL |     let _x = #[identity_attr] 2;
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: custom attributes cannot be applied to expressions
-  --> $DIR/proc-macro-gates.rs:45:15
+  --> $DIR/proc-macro-gates.rs:41:15
    |
 LL |     let _x = [#[identity_attr] 2];
    |               ^^^^^^^^^^^^^^^^
@@ -86,7 +68,7 @@ LL |     let _x = [#[identity_attr] 2];
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: custom attributes cannot be applied to expressions
-  --> $DIR/proc-macro-gates.rs:48:14
+  --> $DIR/proc-macro-gates.rs:44:14
    |
 LL |     let _x = #[identity_attr] println!();
    |              ^^^^^^^^^^^^^^^^
@@ -95,7 +77,7 @@ LL |     let _x = #[identity_attr] println!();
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: procedural macros cannot be expanded to patterns
-  --> $DIR/proc-macro-gates.rs:53:12
+  --> $DIR/proc-macro-gates.rs:49:12
    |
 LL |     if let identity!(Some(_x)) = Some(3) {}
    |            ^^^^^^^^^^^^^^^^^^^
@@ -104,7 +86,7 @@ LL |     if let identity!(Some(_x)) = Some(3) {}
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: procedural macros cannot be expanded to statements
-  --> $DIR/proc-macro-gates.rs:56:5
+  --> $DIR/proc-macro-gates.rs:52:5
    |
 LL |     empty!(struct S;);
    |     ^^^^^^^^^^^^^^^^^^
@@ -113,7 +95,7 @@ LL |     empty!(struct S;);
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: procedural macros cannot be expanded to statements
-  --> $DIR/proc-macro-gates.rs:57:5
+  --> $DIR/proc-macro-gates.rs:53:5
    |
 LL |     empty!(let _x = 3;);
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +104,7 @@ LL |     empty!(let _x = 3;);
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: procedural macros cannot be expanded to expressions
-  --> $DIR/proc-macro-gates.rs:59:14
+  --> $DIR/proc-macro-gates.rs:55:14
    |
 LL |     let _x = identity!(3);
    |              ^^^^^^^^^^^^
@@ -131,7 +113,7 @@ LL |     let _x = identity!(3);
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
 error[E0658]: procedural macros cannot be expanded to expressions
-  --> $DIR/proc-macro-gates.rs:60:15
+  --> $DIR/proc-macro-gates.rs:56:15
    |
 LL |     let _x = [empty!(3)];
    |               ^^^^^^^^^
@@ -139,6 +121,6 @@ LL |     let _x = [empty!(3)];
    = note: for more information, see https://github.com/rust-lang/rust/issues/54727
    = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
 
-error: aborting due to 16 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
index dc4050e44ab..db535b53fcf 100644
--- a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
+++ b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr
@@ -4,6 +4,11 @@ error[E0391]: cycle detected when const-evaluating + checking `Alpha::V3::{{cons
 LL |     V3 = Self::V1 {} as u8 + 2,
    |          ^^^^^^^^
    |
+note: ...which requires const-evaluating + checking `Alpha::V3::{{constant}}#0`...
+  --> $DIR/self-in-enum-definition.rs:5:10
+   |
+LL |     V3 = Self::V1 {} as u8 + 2,
+   |          ^^^^^^^^
 note: ...which requires const-evaluating `Alpha::V3::{{constant}}#0`...
   --> $DIR/self-in-enum-definition.rs:5:10
    |