about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcore/mem/maybe_uninit.rs12
-rw-r--r--src/librustc/error_codes.rs17
-rw-r--r--src/librustc/middle/cstore.rs9
-rw-r--r--src/librustc/middle/lang_items.rs34
-rw-r--r--src/librustc/middle/stability.rs8
-rw-r--r--src/librustc/mir/interpret/error.rs6
-rw-r--r--src/librustc/ty/print/pretty.rs2
-rw-r--r--src/librustc_data_structures/lib.rs2
-rw-r--r--src/librustc_data_structures/stable_map.rs99
-rw-r--r--src/librustc_data_structures/stable_set.rs77
-rw-r--r--src/librustc_metadata/creader.rs15
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_mir/const_eval.rs10
-rw-r--r--src/librustc_mir/interpret/machine.rs17
-rw-r--r--src/librustc_mir/interpret/memory.rs2
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/interpret/place.rs6
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs510
-rw-r--r--src/librustc_typeck/check/expr.rs78
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/collect.rs4
-rw-r--r--src/libsyntax/print/pprust.rs15
-rw-r--r--src/libsyntax_ext/format.rs12
-rw-r--r--src/libsyntax_pos/symbol.rs8
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.rs29
-rw-r--r--src/test/mir-opt/const_prop/reify_fn_ptr.rs2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.rs2
-rw-r--r--src/test/run-fail/overflowing-lsh-1.rs1
-rw-r--r--src/test/run-fail/overflowing-lsh-2.rs1
-rw-r--r--src/test/run-fail/overflowing-lsh-3.rs1
-rw-r--r--src/test/run-fail/overflowing-lsh-4.rs1
-rw-r--r--src/test/run-fail/overflowing-rsh-1.rs1
-rw-r--r--src/test/run-fail/overflowing-rsh-2.rs1
-rw-r--r--src/test/run-fail/overflowing-rsh-3.rs1
-rw-r--r--src/test/run-fail/overflowing-rsh-4.rs1
-rw-r--r--src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs14
-rw-r--r--src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr28
-rw-r--r--src/test/ui/async-await/await-keyword/2018-edition-error.rs4
-rw-r--r--src/test/ui/async-await/await-keyword/2018-edition-error.stderr20
-rw-r--r--src/test/ui/async-await/no-const-async.rs2
-rw-r--r--src/test/ui/async-await/no-const-async.stderr4
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.rs1
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.stderr12
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.rs12
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.stderr6
-rw-r--r--src/test/ui/derived-errors/issue-30580.stderr2
-rw-r--r--src/test/ui/duplicate_entry_error.stderr2
-rw-r--r--src/test/ui/editions/edition-keywords-2015-2018-expansion.rs2
-rw-r--r--src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr4
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2015-parsing.rs4
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr8
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-expansion.rs2
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr4
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-parsing.rs4
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr8
-rw-r--r--src/test/ui/error-codes/E0152.stderr2
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr15
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr15
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr15
-rw-r--r--src/test/ui/feature-gates/feature-gate-staged_api.stderr5
-rw-r--r--src/test/ui/issues/issue-27592.rs2
-rw-r--r--src/test/ui/issues/issue-27592.stderr7
-rw-r--r--src/test/ui/issues/issue-31011.stderr3
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.rs2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.stderr38
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts2.rs2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts2.stderr8
-rw-r--r--src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs12
-rw-r--r--src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs19
-rw-r--r--src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr21
-rw-r--r--src/test/ui/panic-handler/panic-handler-std.stderr2
-rw-r--r--src/test/ui/parser/mut-patterns.rs2
-rw-r--r--src/test/ui/parser/mut-patterns.stderr4
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr7
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-non-staged.stderr7
-rw-r--r--src/test/ui/structs/struct-pat-derived-error.stderr2
-rw-r--r--src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs54
-rw-r--r--src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr75
-rw-r--r--src/tools/tidy/src/features.rs2
80 files changed, 1044 insertions, 416 deletions
diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs
index 9e9e901c76d..792ce9dfad4 100644
--- a/src/libcore/mem/maybe_uninit.rs
+++ b/src/libcore/mem/maybe_uninit.rs
@@ -5,12 +5,12 @@ use crate::mem::ManuallyDrop;
 ///
 /// # Initialization invariant
 ///
-/// The compiler, in general, assumes that variables are properly initialized
-/// at their respective type. For example, a variable of reference type must
-/// be aligned and non-NULL. This is an invariant that must *always* be upheld,
-/// even in unsafe code. As a consequence, zero-initializing a variable of reference
-/// type causes instantaneous [undefined behavior][ub], no matter whether that reference
-/// ever gets used to access memory:
+/// The compiler, in general, assumes that a variable is properly initialized
+/// according to the requirements of the variable's type. For example, a variable of
+/// reference type must be aligned and non-NULL. This is an invariant that must
+/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a
+/// variable of reference type causes instantaneous [undefined behavior][ub],
+/// no matter whether that reference ever gets used to access memory:
 ///
 /// ```rust,no_run
 /// # #![allow(invalid_value)]
diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs
index f6564f1fcd4..968b0b9f2f2 100644
--- a/src/librustc/error_codes.rs
+++ b/src/librustc/error_codes.rs
@@ -2217,6 +2217,23 @@ Examples of erroneous code:
 static X: u32 = 42;
 ```
 "##,
+
+E0734: r##"
+A stability attribute has been used outside of the standard library.
+
+Erroneous code examples:
+
+```compile_fail,E0734
+#[rustc_deprecated(since = "b", reason = "text")] // invalid
+#[stable(feature = "a", since = "b")] // invalid
+#[unstable(feature = "b", issue = "0")] // invalid
+fn foo(){}
+```
+
+These attributes are meant to only be used by the standard library and are
+rejected in your own crates.
+"##,
+
 ;
 //  E0006, // merged with E0005
 //  E0101, // replaced with E0282
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index de84fcd7160..ddf6262b738 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -126,10 +126,17 @@ pub struct ExternCrate {
     /// used to select the extern with the shortest path
     pub path_len: usize,
 
+    /// Crate that depends on this crate
+    pub dependency_of: CrateNum,
+}
+
+impl ExternCrate {
     /// If true, then this crate is the crate named by the extern
     /// crate referenced above. If false, then this crate is a dep
     /// of the crate.
-    pub direct: bool,
+    pub fn is_direct(&self) -> bool {
+        self.dependency_of == LOCAL_CRATE
+    }
 }
 
 #[derive(Copy, Clone, Debug, HashStable)]
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index c5d9a722ae1..cab929389d6 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -13,6 +13,7 @@ use crate::hir::def_id::DefId;
 use crate::hir::check_attr::Target;
 use crate::ty::{self, TyCtxt};
 use crate::middle::weak_lang_items;
+use crate::middle::cstore::ExternCrate;
 use crate::util::nodemap::FxHashMap;
 
 use syntax::ast;
@@ -182,16 +183,39 @@ impl LanguageItemCollector<'tcx> {
                         E0152,
                         "duplicate lang item found: `{}`.",
                         name),
-                    None => self.tcx.sess.struct_err(&format!(
-                            "duplicate lang item in crate `{}`: `{}`.",
-                            self.tcx.crate_name(item_def_id.krate),
-                            name)),
+                    None => {
+                        match self.tcx.extern_crate(item_def_id) {
+                            Some(ExternCrate {dependency_of, ..}) => {
+                                self.tcx.sess.struct_err(&format!(
+                                "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
+                                self.tcx.crate_name(item_def_id.krate),
+                                self.tcx.crate_name(*dependency_of),
+                                name))
+                            },
+                            _ => {
+                                self.tcx.sess.struct_err(&format!(
+                                "duplicate lang item in crate `{}`: `{}`.",
+                                self.tcx.crate_name(item_def_id.krate),
+                                name))
+                            }
+                        }
+                    },
                 };
                 if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
                     span_note!(&mut err, span, "first defined here.");
                 } else {
-                    err.note(&format!("first defined in crate `{}`.",
+                    match self.tcx.extern_crate(original_def_id) {
+                        Some(ExternCrate {dependency_of, ..}) => {
+                            err.note(&format!(
+                            "first defined in crate `{}` (which `{}` depends on).",
+                                      self.tcx.crate_name(original_def_id.krate),
+                                      self.tcx.crate_name(*dependency_of)));
+                        },
+                        _ => {
+                            err.note(&format!("first defined in crate `{}`.",
                                       self.tcx.crate_name(original_def_id.krate)));
+                        }
+                    }
                 }
                 err.emit();
             }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 9e053ce4e69..30a88d155f5 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -199,8 +199,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
                 let name = attr.name_or_empty();
                 if [sym::unstable, sym::stable, sym::rustc_deprecated].contains(&name) {
                     attr::mark_used(attr);
-                    self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
-                                                        outside of the standard library");
+                    struct_span_err!(
+                        self.tcx.sess,
+                        attr.span,
+                        E0734,
+                        "stability attributes may not be used outside of the standard library",
+                    ).emit();
                 }
             }
 
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index ac99ccd45ea..71967b513a0 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -389,6 +389,10 @@ pub enum UnsupportedOpInfo<'tcx> {
     /// Free-form case. Only for errors that are never caught!
     Unsupported(String),
 
+    /// FIXME(#64506) Error used to work around accessing projections of
+    /// uninhabited types.
+    UninhabitedValue,
+
     // -- Everything below is not categorized yet --
     FunctionAbiMismatch(Abi, Abi),
     FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
@@ -552,6 +556,8 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
                     not a power of two"),
             Unsupported(ref msg) =>
                 write!(f, "{}", msg),
+            UninhabitedValue =>
+                write!(f, "tried to use an uninhabited value"),
         }
     }
 }
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index e004fa07f2c..0adb7562697 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -278,7 +278,7 @@ pub trait PrettyPrinter<'tcx>:
             match self.tcx().extern_crate(def_id) {
                 Some(&ExternCrate {
                     src: ExternCrateSource::Extern(def_id),
-                    direct: true,
+                    dependency_of: LOCAL_CRATE,
                     span,
                     ..
                 }) => {
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index f7593501959..d6e9c479c9b 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -73,6 +73,7 @@ pub mod box_region;
 pub mod const_cstr;
 pub mod flock;
 pub mod fx;
+pub mod stable_map;
 pub mod graph;
 pub mod indexed_vec;
 pub mod jobserver;
@@ -84,6 +85,7 @@ pub mod small_c_str;
 pub mod snapshot_map;
 pub use ena::snapshot_vec;
 pub mod sorted_map;
+pub mod stable_set;
 #[macro_use] pub mod stable_hasher;
 pub mod sync;
 pub mod sharded;
diff --git a/src/librustc_data_structures/stable_map.rs b/src/librustc_data_structures/stable_map.rs
new file mode 100644
index 00000000000..f69f28e14b2
--- /dev/null
+++ b/src/librustc_data_structures/stable_map.rs
@@ -0,0 +1,99 @@
+pub use rustc_hash::FxHashMap;
+use std::borrow::Borrow;
+use std::collections::hash_map::Entry;
+use std::fmt;
+use std::hash::Hash;
+
+/// A deterministic wrapper around FxHashMap that does not provide iteration support.
+///
+/// It supports insert, remove, get and get_mut functions from FxHashMap.
+/// It also allows to convert hashmap to a sorted vector with the method `into_sorted_vector()`.
+#[derive(Clone)]
+pub struct StableMap<K, V> {
+    base: FxHashMap<K, V>,
+}
+
+impl<K, V> Default for StableMap<K, V>
+where
+    K: Eq + Hash,
+{
+    fn default() -> StableMap<K, V> {
+        StableMap::new()
+    }
+}
+
+impl<K, V> fmt::Debug for StableMap<K, V>
+where
+    K: Eq + Hash + fmt::Debug,
+    V: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self.base)
+    }
+}
+
+impl<K, V> PartialEq for StableMap<K, V>
+where
+    K: Eq + Hash,
+    V: PartialEq,
+{
+    fn eq(&self, other: &StableMap<K, V>) -> bool {
+        self.base == other.base
+    }
+}
+
+impl<K, V> Eq for StableMap<K, V>
+where
+    K: Eq + Hash,
+    V: Eq,
+{}
+
+impl<K, V> StableMap<K, V>
+where
+    K: Eq + Hash,
+{
+    pub fn new() -> StableMap<K, V> {
+        StableMap { base: FxHashMap::default() }
+    }
+
+    pub fn into_sorted_vector(self) -> Vec<(K, V)>
+    where
+        K: Ord + Copy,
+    {
+        let mut vector = self.base.into_iter().collect::<Vec<_>>();
+        vector.sort_unstable_by_key(|pair| pair.0);
+        vector
+    }
+
+    pub fn entry(&mut self, k: K) -> Entry<'_, K, V> {
+        self.base.entry(k)
+    }
+
+    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get(k)
+    }
+
+    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get_mut(k)
+    }
+
+    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+        self.base.insert(k, v)
+    }
+
+    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.remove(k)
+    }
+}
diff --git a/src/librustc_data_structures/stable_set.rs b/src/librustc_data_structures/stable_set.rs
new file mode 100644
index 00000000000..c7ca74f5fbd
--- /dev/null
+++ b/src/librustc_data_structures/stable_set.rs
@@ -0,0 +1,77 @@
+pub use rustc_hash::FxHashSet;
+use std::borrow::Borrow;
+use std::fmt;
+use std::hash::Hash;
+
+/// A deterministic wrapper around FxHashSet that does not provide iteration support.
+///
+/// It supports insert, remove, get functions from FxHashSet.
+/// It also allows to convert hashset to a sorted vector with the method `into_sorted_vector()`.
+#[derive(Clone)]
+pub struct StableSet<T> {
+    base: FxHashSet<T>,
+}
+
+impl<T> Default for StableSet<T>
+where
+    T: Eq + Hash,
+{
+    fn default() -> StableSet<T> {
+        StableSet::new()
+    }
+}
+
+impl<T> fmt::Debug for StableSet<T>
+where
+    T: Eq + Hash + fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self.base)
+    }
+}
+
+impl<T> PartialEq<StableSet<T>> for StableSet<T>
+where
+    T: Eq + Hash,
+{
+    fn eq(&self, other: &StableSet<T>) -> bool {
+        self.base == other.base
+    }
+}
+
+impl<T> Eq for StableSet<T> where T: Eq + Hash {}
+
+impl<T: Hash + Eq> StableSet<T> {
+    pub fn new() -> StableSet<T> {
+        StableSet { base: FxHashSet::default() }
+    }
+
+    pub fn into_sorted_vector(self) -> Vec<T>
+    where
+        T: Ord,
+    {
+        let mut vector = self.base.into_iter().collect::<Vec<_>>();
+        vector.sort_unstable();
+        vector
+    }
+
+    pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
+    where
+        T: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.get(value)
+    }
+
+    pub fn insert(&mut self, value: T) -> bool {
+        self.base.insert(value)
+    }
+
+    pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
+    where
+        T: Borrow<Q>,
+        Q: Hash + Eq,
+    {
+        self.base.remove(value)
+    }
+}
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 0a2a481bb15..682835d81a6 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -17,6 +17,7 @@ use rustc::middle::cstore::{ExternCrate, ExternCrateSource};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
+use rustc::hir::def_id::LOCAL_CRATE;
 
 use std::ops::Deref;
 use std::path::PathBuf;
@@ -430,7 +431,7 @@ impl<'a> CrateLoader<'a> {
                            mut extern_crate: ExternCrate,
                            visited: &mut FxHashSet<(CrateNum, bool)>)
     {
-        if !visited.insert((cnum, extern_crate.direct)) { return }
+        if !visited.insert((cnum, extern_crate.is_direct())) { return }
 
         let cmeta = self.cstore.get_crate_data(cnum);
         let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
@@ -441,14 +442,14 @@ impl<'a> CrateLoader<'a> {
         // - shorter paths to longer (tuple.2).
         let new_rank = (
             true,
-            extern_crate.direct,
+            extern_crate.is_direct(),
             cmp::Reverse(extern_crate.path_len),
         );
         let old_rank = match *old_extern_crate {
             None => (false, false, cmp::Reverse(usize::max_value())),
             Some(ref c) => (
                 true,
-                c.direct,
+                c.is_direct(),
                 cmp::Reverse(c.path_len),
             ),
         };
@@ -460,7 +461,7 @@ impl<'a> CrateLoader<'a> {
         drop(old_extern_crate);
 
         // Propagate the extern crate info to dependencies.
-        extern_crate.direct = false;
+        extern_crate.dependency_of = cnum;
         for &dep_cnum in cmeta.dependencies.borrow().iter() {
             self.update_extern_crate(dep_cnum, extern_crate, visited);
         }
@@ -1030,7 +1031,7 @@ impl<'a> CrateLoader<'a> {
                         src: ExternCrateSource::Extern(def_id),
                         span: item.span,
                         path_len,
-                        direct: true,
+                        dependency_of: LOCAL_CRATE,
                     },
                     &mut FxHashSet::default(),
                 );
@@ -1057,7 +1058,7 @@ impl<'a> CrateLoader<'a> {
                 span,
                 // to have the least priority in `update_extern_crate`
                 path_len: usize::max_value(),
-                direct: true,
+                dependency_of: LOCAL_CRATE,
             },
             &mut FxHashSet::default(),
         );
@@ -1081,7 +1082,7 @@ impl<'a> CrateLoader<'a> {
                 span,
                 // to have the least priority in `update_extern_crate`
                 path_len: usize::max_value(),
-                direct: true,
+                dependency_of: LOCAL_CRATE,
             },
             &mut FxHashSet::default(),
         );
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 8a7e599ebeb..83182df31cf 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -233,7 +233,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
 
     missing_extern_crate_item => {
         let r = match *cdata.extern_crate.borrow() {
-            Some(extern_crate) if !extern_crate.direct => true,
+            Some(extern_crate) if !extern_crate.is_direct() => true,
             _ => false,
         };
         r
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index ca238867421..bb02b99dd8d 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -21,7 +21,7 @@ use syntax::source_map::{Span, DUMMY_SP};
 
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
-    RawConst, ConstValue,
+    RawConst, ConstValue, Machine,
     InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
     Allocation, AllocId, MemoryKind, Memory,
     snapshot, RefTracking, intern_const_alloc_recursive,
@@ -41,7 +41,7 @@ const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
 /// that inform us about the generic bounds of the constant. E.g., using an associated constant
 /// of a function's generic parameter will require knowledge about the bounds on the generic
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
-pub(crate) fn mk_eval_cx<'mir, 'tcx>(
+fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
     span: Span,
     param_env: ty::ParamEnv<'tcx>,
@@ -169,7 +169,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 }
 
 #[derive(Clone, Debug)]
-enum ConstEvalError {
+pub enum ConstEvalError {
     NeedsRfc(String),
 }
 
@@ -521,8 +521,8 @@ pub fn const_variant_index<'tcx>(
 /// Turn an interpreter error into something to report to the user.
 /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
 /// Should be called only if the error is actually going to to be reported!
-pub fn error_to_const_error<'mir, 'tcx>(
-    ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+pub fn error_to_const_error<'mir, 'tcx, M: Machine<'mir, 'tcx>>(
+    ecx: &InterpCx<'mir, 'tcx, M>,
     mut error: InterpErrorInfo<'tcx>,
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index bb74a50156e..c30c59bbf10 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -12,6 +12,7 @@ use rustc::ty::{self, Ty, TyCtxt};
 use super::{
     Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
     InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
+    Frame, Operand,
 };
 
 /// Whether this kind of memory is allowed to leak
@@ -184,6 +185,22 @@ pub trait Machine<'mir, 'tcx>: Sized {
         dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> InterpResult<'tcx>;
 
+    /// Called to read the specified `local` from the `frame`.
+    fn access_local(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
+        local: mir::Local,
+    ) -> InterpResult<'tcx, Operand<Self::PointerTag>> {
+        frame.locals[local].access()
+    }
+
+    /// Called before a `StaticKind::Static` value is accessed.
+    fn before_access_static(
+        _allocation: &Allocation,
+    ) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
     /// Called to initialize the "extra" state of an allocation and make the pointers
     /// it contains (in relocations) tagged.  The way we construct allocations is
     /// to always first construct it without extra and then add the extra.
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 62b1760508b..924474c5317 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -462,6 +462,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     // Make sure we use the ID of the resolved memory, not the lazy one!
                     let id = raw_const.alloc_id;
                     let allocation = tcx.alloc_map.lock().unwrap_memory(id);
+
+                    M::before_access_static(allocation)?;
                     Cow::Borrowed(allocation)
                 }
             }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index f5d1ec3eb75..861e5ebef87 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -458,7 +458,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Do not read from ZST, they might not be initialized
             Operand::Immediate(Scalar::zst().into())
         } else {
-            frame.locals[local].access()?
+            M::access_local(&self, frame, local)?
         };
         Ok(OpTy { op, layout })
     }
@@ -481,7 +481,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     // Evaluate a place with the goal of reading from it.  This lets us sometimes
     // avoid allocations.
-    pub(super) fn eval_place_to_op(
+    pub fn eval_place_to_op(
         &self,
         place: &mir::Place<'tcx>,
         layout: Option<TyLayout<'tcx>>,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 2f1b35757fe..1166ca9bf24 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -9,7 +9,7 @@ use rustc::mir;
 use rustc::mir::interpret::truncate;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{
-    self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
+    self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt
 };
 use rustc::ty::TypeFoldable;
 
@@ -385,6 +385,10 @@ where
                 stride * field
             }
             layout::FieldPlacement::Union(count) => {
+                // FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved
+                if base.layout.abi == Abi::Uninhabited {
+                    throw_unsup!(UninhabitedValue);
+                }
                 assert!(field < count as u64,
                         "Tried to access field {} of union with {} fields", field, count);
                 // Offset is always 0
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index affca10bf52..daca7a25787 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -132,7 +132,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ///
     /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
     /// type writes its results directly into the memory specified by the place.
-    fn eval_rvalue_into_place(
+    pub fn eval_rvalue_into_place(
         &mut self,
         rvalue: &mir::Rvalue<'tcx>,
         place: &mir::Place<'tcx>,
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 857757ada53..612822b6d9d 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -1,22 +1,26 @@
 //! Propagates constants for early reporting of statically known
 //! assertion failures
 
+use std::borrow::Cow;
 use std::cell::Cell;
 
 use rustc::hir::def::DefKind;
+use rustc::hir::def_id::DefId;
 use rustc::mir::{
     AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
-    Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
-    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
-    SourceScope, SourceScopeLocalData, LocalDecl,
+    Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
+    TerminatorKind, Terminator,  ClearCrossCrate, SourceInfo, BinOp,
+    SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
 };
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, PanicInfo};
+use rustc::mir::interpret::{Scalar, InterpResult, PanicInfo};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
+use syntax::ast::Mutability;
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::layout::{
     LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout,
@@ -24,11 +28,11 @@ use rustc::ty::layout::{
 
 use crate::interpret::{
     self, InterpCx, ScalarMaybeUndef, Immediate, OpTy,
-    ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
-};
-use crate::const_eval::{
-    CompileTimeInterpreter, error_to_const_error, mk_eval_cx,
+    StackPopCleanup, LocalValue, LocalState, AllocId, Frame,
+    Allocation, MemoryKind, ImmTy, Pointer, Memory, PlaceTy,
+    Operand as InterpOperand,
 };
+use crate::const_eval::error_to_const_error;
 use crate::transform::{MirPass, MirSource};
 
 pub struct ConstProp;
@@ -57,6 +61,14 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return
         }
 
+        let is_generator = tcx.type_of(source.def_id()).is_generator();
+        // FIXME(welseywiser) const prop doesn't work on generators because of query cycles
+        // computing their layout.
+        if is_generator {
+            trace!("ConstProp skipped for generator {:?}", source.def_id());
+            return
+        }
+
         trace!("ConstProp starting for {:?}", source.def_id());
 
         // Steal some data we need from `body`.
@@ -103,11 +115,154 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
     }
 }
 
+struct ConstPropMachine;
+
+impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
+    type MemoryKinds= !;
+    type PointerTag = ();
+    type ExtraFnVal = !;
+
+    type FrameExtra = ();
+    type MemoryExtra = ();
+    type AllocExtra = ();
+
+    type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
+
+    const STATIC_KIND: Option<!> = None;
+
+    const CHECK_ALIGN: bool = false;
+
+    #[inline(always)]
+    fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
+        false
+    }
+
+    fn find_fn(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _instance: ty::Instance<'tcx>,
+        _args: &[OpTy<'tcx>],
+        _dest: Option<PlaceTy<'tcx>>,
+        _ret: Option<BasicBlock>,
+    ) -> InterpResult<'tcx, Option<&'mir Body<'tcx>>> {
+        Ok(None)
+    }
+
+    fn call_extra_fn(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        fn_val: !,
+        _args: &[OpTy<'tcx>],
+        _dest: Option<PlaceTy<'tcx>>,
+        _ret: Option<BasicBlock>,
+    ) -> InterpResult<'tcx> {
+        match fn_val {}
+    }
+
+    fn call_intrinsic(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _instance: ty::Instance<'tcx>,
+        _args: &[OpTy<'tcx>],
+        _dest: PlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("calling intrinsics isn't supported in ConstProp");
+    }
+
+    fn ptr_to_int(
+        _mem: &Memory<'mir, 'tcx, Self>,
+        _ptr: Pointer,
+    ) -> InterpResult<'tcx, u64> {
+        throw_unsup_format!("ptr-to-int casts aren't supported in ConstProp");
+    }
+
+    fn binary_ptr_op(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _bin_op: BinOp,
+        _left: ImmTy<'tcx>,
+        _right: ImmTy<'tcx>,
+    ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
+        // We can't do this because aliasing of memory can differ between const eval and llvm
+        throw_unsup_format!("pointer arithmetic or comparisons aren't supported in ConstProp");
+    }
+
+    fn find_foreign_static(
+        _tcx: TyCtxt<'tcx>,
+        _def_id: DefId,
+    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
+        throw_unsup!(ReadForeignStatic)
+    }
+
+    #[inline(always)]
+    fn tag_allocation<'b>(
+        _memory_extra: &(),
+        _id: AllocId,
+        alloc: Cow<'b, Allocation>,
+        _kind: Option<MemoryKind<!>>,
+    ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
+        // We do not use a tag so we can just cheaply forward the allocation
+        (alloc, ())
+    }
+
+    #[inline(always)]
+    fn tag_static_base_pointer(
+        _memory_extra: &(),
+        _id: AllocId,
+    ) -> Self::PointerTag {
+        ()
+    }
+
+    fn box_alloc(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _dest: PlaceTy<'tcx>,
+    ) -> InterpResult<'tcx> {
+        throw_unsup_format!("can't const prop `box` keyword");
+    }
+
+    fn access_local(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
+        local: Local,
+    ) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> {
+        let l = &frame.locals[local];
+
+        if l.value == LocalValue::Uninitialized {
+            throw_unsup_format!("tried to access an uninitialized local");
+        }
+
+        l.access()
+    }
+
+    fn before_access_static(
+        allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
+    ) -> InterpResult<'tcx> {
+        // if the static allocation is mutable or if it has relocations (it may be legal to mutate
+        // the memory behind that in the future), then we can't const prop it
+        if allocation.mutability == Mutability::Mutable || allocation.relocations().len() > 0 {
+            throw_unsup_format!("can't eval mutable statics in ConstProp");
+        }
+
+        Ok(())
+    }
+
+    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
+    #[inline(always)]
+    fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
+    /// Called immediately before a stack frame gets popped.
+    #[inline(always)]
+    fn stack_pop(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
+        Ok(())
+    }
+}
+
 type Const<'tcx> = OpTy<'tcx>;
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
-    ecx: InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+    ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
     tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
     can_const_prop: IndexVec<Local, bool>,
@@ -150,7 +305,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         let def_id = source.def_id();
         let param_env = tcx.param_env(def_id);
         let span = tcx.def_span(def_id);
-        let mut ecx = mk_eval_cx(tcx, span, param_env);
+        let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine, ());
         let can_const_prop = CanConstProp::check(body);
 
         ecx.push_stack_frame(
@@ -282,53 +437,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        let mut eval = match place.base {
-            PlaceBase::Local(loc) => self.get_const(loc).clone()?,
-            PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
-                let generics = self.tcx.generics_of(self.source.def_id());
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
-                }
-                let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
-                let instance = Instance::new(self.source.def_id(), substs);
-                let cid = GlobalId {
-                    instance,
-                    promoted: Some(promoted),
-                };
-                let res = self.use_ecx(source_info, |this| {
-                    this.ecx.const_eval_raw(cid)
-                })?;
-                trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                res.into()
-            }
-            _ => return None,
-        };
-
-        for (i, elem) in place.projection.iter().enumerate() {
-            let proj_base = &place.projection[..i];
-
-            match elem {
-                ProjectionElem::Field(field, _) => {
-                    trace!("field proj on {:?}", proj_base);
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.operand_field(eval, field.index() as u64)
-                    })?;
-                },
-                ProjectionElem::Deref => {
-                    trace!("processing deref");
-                    eval = self.use_ecx(source_info, |this| {
-                        this.ecx.deref_operand(eval)
-                    })?.into();
-                }
-                // We could get more projections by using e.g., `operand_projection`,
-                // but we do not even have the stack frame set up properly so
-                // an `Index` projection would throw us off-track.
-                _ => return None,
-            }
-        }
-
-        Some(eval)
+        self.use_ecx(source_info, |this| {
+            this.ecx.eval_place_to_op(place, None)
+        })
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
@@ -344,166 +455,118 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         rvalue: &Rvalue<'tcx>,
         place_layout: TyLayout<'tcx>,
         source_info: SourceInfo,
+        place: &Place<'tcx>,
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
-        match *rvalue {
-            Rvalue::Use(ref op) => {
-                self.eval_operand(op, source_info)
-            },
-            Rvalue::Ref(_, _, ref place) => {
-                let src = self.eval_place(place, source_info)?;
-                let mplace = src.try_as_mplace().ok()?;
-                Some(ImmTy::from_scalar(mplace.ptr.into(), place_layout).into())
-            },
+
+        // if this isn't a supported operation, then return None
+        match rvalue {
             Rvalue::Repeat(..) |
             Rvalue::Aggregate(..) |
             Rvalue::NullaryOp(NullOp::Box, _) |
-            Rvalue::Discriminant(..) => None,
-
-            Rvalue::Cast(kind, ref operand, _) => {
-                let op = self.eval_operand(operand, source_info)?;
-                self.use_ecx(source_info, |this| {
-                    let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
-                    this.ecx.cast(op, kind, dest.into())?;
-                    Ok(dest.into())
-                })
-            },
-            Rvalue::Len(ref place) => {
-                let place = self.eval_place(&place, source_info)?;
-                let mplace = place.try_as_mplace().ok()?;
-
-                if let ty::Slice(_) = mplace.layout.ty.kind {
-                    let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
-
-                    Some(ImmTy::from_uint(
-                        len,
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ).into())
-                } else {
-                    trace!("not slice: {:?}", mplace.layout.ty.kind);
-                    None
-                }
-            },
-            Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
-                type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
-                    ImmTy::from_uint(
-                        n,
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ).into()
-                ))
-            }
-            Rvalue::UnaryOp(op, ref arg) => {
-                let def_id = if self.tcx.is_closure(self.source.def_id()) {
-                    self.tcx.closure_base_def_id(self.source.def_id())
-                } else {
-                    self.source.def_id()
-                };
-                let generics = self.tcx.generics_of(def_id);
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
-                }
+            Rvalue::Discriminant(..) => return None,
+
+            Rvalue::Use(_) |
+            Rvalue::Len(_) |
+            Rvalue::Cast(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::Ref(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::BinaryOp(..) => { }
+        }
 
-                let arg = self.eval_operand(arg, source_info)?;
-                let oflo_check = self.tcx.sess.overflow_checks();
-                let val = self.use_ecx(source_info, |this| {
-                    let prim = this.ecx.read_immediate(arg)?;
-                    match op {
-                        UnOp::Neg => {
-                            // We check overflow in debug mode already
-                            // so should only check in release mode.
-                            if !oflo_check
-                            && prim.layout.ty.is_signed()
-                            && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
-                                throw_panic!(OverflowNeg)
-                            }
-                        }
-                        UnOp::Not => {
-                            // Cannot overflow
+        // perform any special checking for specific Rvalue types
+        if let Rvalue::UnaryOp(op, arg) = rvalue {
+            trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
+            let overflow_check = self.tcx.sess.overflow_checks();
+
+            self.use_ecx(source_info, |this| {
+                // We check overflow in debug mode already
+                // so should only check in release mode.
+                if *op == UnOp::Neg && !overflow_check {
+                    let ty = arg.ty(&this.local_decls, this.tcx);
+
+                    if ty.is_integral() {
+                        let arg = this.ecx.eval_operand(arg, None)?;
+                        let prim = this.ecx.read_immediate(arg)?;
+                        // Need to do overflow check here: For actual CTFE, MIR
+                        // generation emits code that does this before calling the op.
+                        if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
+                            throw_panic!(OverflowNeg)
                         }
                     }
-                    // Now run the actual operation.
-                    this.ecx.unary_op(op, prim)
-                })?;
-                Some(val.into())
-            }
-            Rvalue::CheckedBinaryOp(op, ref left, ref right) |
-            Rvalue::BinaryOp(op, ref left, ref right) => {
-                trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
-                let right = self.eval_operand(right, source_info)?;
-                let def_id = if self.tcx.is_closure(self.source.def_id()) {
-                    self.tcx.closure_base_def_id(self.source.def_id())
-                } else {
-                    self.source.def_id()
-                };
-                let generics = self.tcx.generics_of(def_id);
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
+                }
+
+                Ok(())
+            })?;
+        } else if let Rvalue::BinaryOp(op, left, right) = rvalue {
+            trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
+
+            let r = self.use_ecx(source_info, |this| {
+                this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
+            })?;
+            if *op == BinOp::Shr || *op == BinOp::Shl {
+                let left_bits = place_layout.size.bits();
+                let right_size = r.layout.size;
+                let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
+                if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
+                    let source_scope_local_data = match self.source_scope_local_data {
+                        ClearCrossCrate::Set(ref data) => data,
+                        ClearCrossCrate::Clear => return None,
+                    };
+                    let dir = if *op == BinOp::Shr {
+                        "right"
+                    } else {
+                        "left"
+                    };
+                    let hir_id = source_scope_local_data[source_info.scope].lint_root;
+                    self.tcx.lint_hir(
+                        ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
+                        hir_id,
+                        span,
+                        &format!("attempt to shift {} with overflow", dir));
                     return None;
                 }
+            }
+            self.use_ecx(source_info, |this| {
+                let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
+                let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
+
+                // We check overflow in debug mode already
+                // so should only check in release mode.
+                if !this.tcx.sess.overflow_checks() && overflow {
+                    let err = err_panic!(Overflow(*op)).into();
+                    return Err(err);
+                }
 
-                let r = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(right)
-                })?;
-                if op == BinOp::Shr || op == BinOp::Shl {
-                    let left_ty = left.ty(&self.local_decls, self.tcx);
-                    let left_bits = self
-                        .tcx
-                        .layout_of(self.param_env.and(left_ty))
-                        .unwrap()
-                        .size
-                        .bits();
-                    let right_size = right.layout.size;
-                    let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
-                    if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
-                        let source_scope_local_data = match self.source_scope_local_data {
-                            ClearCrossCrate::Set(ref data) => data,
-                            ClearCrossCrate::Clear => return None,
-                        };
-                        let dir = if op == BinOp::Shr {
-                            "right"
-                        } else {
-                            "left"
-                        };
-                        let hir_id = source_scope_local_data[source_info.scope].lint_root;
-                        self.tcx.lint_hir(
-                            ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
-                            hir_id,
-                            span,
-                            &format!("attempt to shift {} with overflow", dir));
-                        return None;
-                    }
+                Ok(())
+            })?;
+        } else if let Rvalue::Ref(_, _, place) = rvalue {
+            trace!("checking Ref({:?})", place);
+            // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
+            // from a function argument that hasn't been assigned to in this function.
+            if let Place {
+                base: PlaceBase::Local(local),
+                projection: box []
+            } = place {
+                let alive =
+                    if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
+                        true
+                    } else { false };
+
+                if local.as_usize() <= self.ecx.frame().body.arg_count && !alive {
+                    trace!("skipping Ref({:?})", place);
+                    return None;
                 }
-                let left = self.eval_operand(left, source_info)?;
-                let l = self.use_ecx(source_info, |this| {
-                    this.ecx.read_immediate(left)
-                })?;
-                trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
-                let (val, overflow, _ty) = self.use_ecx(source_info, |this| {
-                    this.ecx.overflowing_binary_op(op, l, r)
-                })?;
-                let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
-                    Immediate::ScalarPair(
-                        val.into(),
-                        Scalar::from_bool(overflow).into(),
-                    )
-                } else {
-                    // We check overflow in debug mode already
-                    // so should only check in release mode.
-                    if !self.tcx.sess.overflow_checks() && overflow {
-                        let err = err_panic!(Overflow(op)).into();
-                        let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
-                        return None;
-                    }
-                    Immediate::Scalar(val.into())
-                };
-                let res = ImmTy {
-                    imm: val,
-                    layout: place_layout,
-                };
-                Some(res.into())
-            },
+            }
         }
+
+        self.use_ecx(source_info, |this| {
+            trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place);
+            this.ecx.eval_rvalue_into_place(rvalue, place)?;
+            this.ecx.eval_place_to_op(place, Some(place_layout))
+        })
     }
 
     fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Operand<'tcx> {
@@ -577,14 +640,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     }
 }
 
-fn type_size_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<u64> {
-    tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
-}
-
 struct CanConstProp {
     can_const_prop: IndexVec<Local, bool>,
     // false at the beginning, once set, there are not allowed to be any more assignments
@@ -670,15 +725,19 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                 .ty(&self.local_decls, self.tcx)
                 .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
-                if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
-                    if let Place {
-                        base: PlaceBase::Local(local),
-                        projection: box [],
-                    } = *place {
+                if let Place {
+                    base: PlaceBase::Local(local),
+                    projection: box [],
+                } = *place {
+                    if let Some(value) = self.const_prop(rval,
+                                                         place_layout,
+                                                         statement.source_info,
+                                                         place) {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
-                            assert!(self.get_const(local).is_none());
+                            assert!(self.get_const(local).is_none() ||
+                                    self.get_const(local) == Some(value));
                             self.set_const(local, value);
 
                             if self.should_const_prop() {
@@ -692,7 +751,22 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                     }
                 }
             }
+        } else {
+            match statement.kind {
+                StatementKind::StorageLive(local) |
+                StatementKind::StorageDead(local) if self.can_const_prop[local] => {
+                    let frame = self.ecx.frame_mut();
+                    frame.locals[local].value =
+                        if let StatementKind::StorageLive(_) = statement.kind {
+                            LocalValue::Uninitialized
+                        } else {
+                            LocalValue::Dead
+                        };
+                }
+                _ => {}
+            }
         }
+
         self.super_statement(statement, location);
     }
 
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 0cdf2fa2a5b..6bed321d27f 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -1394,30 +1394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if self.method_exists(field, expr_t, expr.hir_id, true) {
             self.ban_take_value_of_method(expr, expr_t, field);
         } else if !expr_t.is_primitive_ty() {
-            let mut err = self.no_such_field_err(field.span, field, expr_t);
-
-            match expr_t.kind {
-                ty::Adt(def, _) if !def.is_enum() => {
-                    self.suggest_fields_on_recordish(&mut err, def, field);
-                }
-                ty::Array(_, len) => {
-                    self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
-                }
-                ty::RawPtr(..) => {
-                    self.suggest_first_deref_field(&mut err, expr, base, field);
-                }
-                _ => {}
-            }
-
-            if field.name == kw::Await {
-                // We know by construction that `<expr>.await` is either on Rust 2015
-                // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
-                err.note("to `.await` a `Future`, switch to Rust 2018");
-                err.help("set `edition = \"2018\"` in `Cargo.toml`");
-                err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
-            }
-
-            err.emit();
+            self.ban_nonexisting_field(field, base, expr, expr_t);
         } else {
             type_error_struct!(
                 self.tcx().sess,
@@ -1433,6 +1410,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.tcx().types.err
     }
 
+    fn ban_nonexisting_field(
+        &self,
+        field: ast::Ident,
+        base: &'tcx hir::Expr,
+        expr: &'tcx hir::Expr,
+        expr_t: Ty<'tcx>,
+    ) {
+        let mut err = self.no_such_field_err(field.span, field, expr_t);
+
+        match expr_t.peel_refs().kind {
+            ty::Array(_, len) => {
+                self.maybe_suggest_array_indexing(&mut err, expr, base, field, len);
+            }
+            ty::RawPtr(..) => {
+                self.suggest_first_deref_field(&mut err, expr, base, field);
+            }
+            ty::Adt(def, _) if !def.is_enum() => {
+                self.suggest_fields_on_recordish(&mut err, def, field);
+            }
+            ty::Param(param_ty) => {
+                self.point_at_param_definition(&mut err, param_ty);
+            }
+            _ => {}
+        }
+
+        if field.name == kw::Await {
+            // We know by construction that `<expr>.await` is either on Rust 2015
+            // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
+            err.note("to `.await` a `Future`, switch to Rust 2018");
+            err.help("set `edition = \"2018\"` in `Cargo.toml`");
+            err.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+        }
+
+        err.emit();
+    }
+
     fn ban_private_field_access(
         &self,
         expr: &hir::Expr,
@@ -1495,6 +1508,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.emit();
     }
 
+    fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) {
+        let generics = self.tcx.generics_of(self.body_id.owner_def_id());
+        let generic_param = generics.type_param(&param, self.tcx);
+        if let ty::GenericParamDefKind::Type{synthetic: Some(..), ..} = generic_param.kind {
+            return;
+        }
+        let param_def_id = generic_param.def_id;
+        let param_hir_id = match self.tcx.hir().as_local_hir_id(param_def_id) {
+            Some(x) => x,
+            None    => return,
+        };
+        let param_span = self.tcx.hir().span(param_hir_id);
+        let param_name = self.tcx.hir().ty_param_name(param_hir_id);
+
+        err.span_label(param_span, &format!("type parameter '{}' declared here", param_name));
+    }
+
     fn suggest_fields_on_recordish(
         &self,
         err: &mut DiagnosticBuilder<'_>,
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index d06d51dc819..aeb2c40e2ef 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -63,7 +63,7 @@ fn equate_intrinsic_type<'tcx>(
 }
 
 /// Returns `true` if the given intrinsic is unsafe to call or not.
-pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
+pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
     match intrinsic {
         "size_of" | "min_align_of" | "needs_drop" |
         "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
@@ -130,7 +130,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
     } else if &name[..] == "abort" || &name[..] == "unreachable" {
         (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
     } else {
-        let unsafety = intrisic_operation_unsafety(&name[..]);
+        let unsafety = intrinsic_operation_unsafety(&name[..]);
         let (n_tps, inputs, output) = match &name[..] {
             "breakpoint" => (0, Vec::new(), tcx.mk_unit()),
             "size_of" |
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index db017394cd5..8c3d6357f0b 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -16,7 +16,7 @@
 
 use crate::astconv::{AstConv, Bounds, SizedByDefault};
 use crate::constrained_generic_params as cgp;
-use crate::check::intrinsic::intrisic_operation_unsafety;
+use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::lint;
 use crate::middle::resolve_lifetime as rl;
 use crate::middle::weak_lang_items;
@@ -2366,7 +2366,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     abi: abi::Abi,
 ) -> ty::PolyFnSig<'tcx> {
     let unsafety = if abi == abi::Abi::RustIntrinsic {
-        intrisic_operation_unsafety(&*tcx.item_name(def_id).as_str())
+        intrinsic_operation_unsafety(&*tcx.item_name(def_id).as_str())
     } else {
         hir::Unsafety::Unsafe
     };
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a5792dab474..4b9c2d13f26 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1657,9 +1657,18 @@ impl<'a> State<'a> {
                 }
             }
             ast::StmtKind::Semi(ref expr) => {
-                self.space_if_not_bol();
-                self.print_expr_outer_attr_style(expr, false);
-                self.s.word(";");
+                match expr.kind {
+                    // Filter out empty `Tup` exprs created for the `redundant_semicolon`
+                    // lint, as they shouldn't be visible and interact poorly
+                    // with proc macros.
+                    ast::ExprKind::Tup(ref exprs) if exprs.is_empty()
+                      && expr.attrs.is_empty() => (),
+                    _ => {
+                        self.space_if_not_bol();
+                        self.print_expr_outer_attr_style(expr, false);
+                        self.s.word(";");
+                    }
+                }
             }
             ast::StmtKind::Mac(ref mac) => {
                 let (ref mac, style, ref attrs) = **mac;
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 2765346b333..8fc64021b51 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -695,7 +695,7 @@ impl<'a, 'b> Context<'a, 'b> {
         // Now create a vector containing all the arguments
         let args = locals.into_iter().chain(counts.into_iter());
 
-        let args_array = self.ecx.expr_vec(self.fmtsp, args.collect());
+        let args_array = self.ecx.expr_vec(self.macsp, args.collect());
 
         // Constructs an AST equivalent to:
         //
@@ -724,12 +724,12 @@ impl<'a, 'b> Context<'a, 'b> {
         //
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
-        let pat = self.ecx.pat_tuple(self.fmtsp, pats);
-        let arm = self.ecx.arm(self.fmtsp, pat, args_array);
-        let head = self.ecx.expr(self.fmtsp, ast::ExprKind::Tup(heads));
-        let result = self.ecx.expr_match(self.fmtsp, head, vec![arm]);
+        let pat = self.ecx.pat_tuple(self.macsp, pats);
+        let arm = self.ecx.arm(self.macsp, pat, args_array);
+        let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
+        let result = self.ecx.expr_match(self.macsp, head, vec![arm]);
 
-        let args_slice = self.ecx.expr_addr_of(self.fmtsp, result);
+        let args_slice = self.ecx.expr_addr_of(self.macsp, result);
 
         // Now create the fmt::Arguments struct with all our locals we created.
         let (fn_name, fn_args) = if self.all_pieces_simple {
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 32af930ffb8..44a34070dec 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -83,11 +83,11 @@ symbols! {
         Yield:              "yield",
 
         // Edition-specific keywords that are used in stable Rust.
+        Async:              "async", // >= 2018 Edition only
+        Await:              "await", // >= 2018 Edition only
         Dyn:                "dyn", // >= 2018 Edition only
 
         // Edition-specific keywords that are used in unstable Rust or reserved for future use.
-        Async:              "async", // >= 2018 Edition only
-        Await:              "await", // >= 2018 Edition only
         Try:                "try", // >= 2018 Edition only
 
         // Special lifetime names
@@ -1088,11 +1088,11 @@ pub mod sym {
 
 impl Symbol {
     fn is_used_keyword_2018(self) -> bool {
-        self == kw::Dyn
+        self >= kw::Async && self <= kw::Dyn
     }
 
     fn is_unused_keyword_2018(self) -> bool {
-        self >= kw::Async && self <= kw::Try
+        self == kw::Try
     }
 
     /// Used for sanity checking rustdoc keyword sections.
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
new file mode 100644
index 00000000000..c2902dbd7c1
--- /dev/null
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -0,0 +1,29 @@
+// compile-flags: -O
+
+static FOO: u8 = 2;
+
+fn main() {
+    let x = FOO + FOO;
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _2 = (FOO: u8);
+//      ...
+//      _3 = (FOO: u8);
+//      _1 = Add(move _2, move _3);
+//      ...
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      _2 = const 2u8;
+//      ...
+//      _3 = const 2u8;
+//      _1 = Add(move _2, move _3);
+//      ...
+//  }
+// END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
index 7e36b2a6b1b..e9b61690cf8 100644
--- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs
+++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs
@@ -16,7 +16,7 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const Scalar(AllocId(1).0x0) : fn();
+//      _3 = const Scalar(AllocId(0).0x0) : fn();
 //      _2 = move _3 as usize (Misc);
 //      ...
 //      _1 = move _2 as *const fn() (Misc);
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 5babeb195a8..05595ce147c 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -34,7 +34,7 @@ fn main() {
 //      assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
 //  }
 //  bb1: {
-//      _1 = (*_2)[_6];
+//      _1 = const 2u32;
 //      ...
 //      return;
 //  }
diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs
index c69da0f49ad..37fbf01e487 100644
--- a/src/test/run-fail/overflowing-lsh-1.rs
+++ b/src/test/run-fail/overflowing-lsh-1.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1_i32 << 32;
diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs
index 21659bd5239..7b0b37dfed0 100644
--- a/src/test/run-fail/overflowing-lsh-2.rs
+++ b/src/test/run-fail/overflowing-lsh-2.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1 << -1;
diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs
index 8f06cd11533..1768a8e6d31 100644
--- a/src/test/run-fail/overflowing-lsh-3.rs
+++ b/src/test/run-fail/overflowing-lsh-3.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = 1_u64 << 64;
diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs
index 084c147094d..ec304b4144e 100644
--- a/src/test/run-fail/overflowing-lsh-4.rs
+++ b/src/test/run-fail/overflowing-lsh-4.rs
@@ -5,6 +5,7 @@
 // sidestep the overflow checking.
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     // this signals overflow when checking is on
diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs
index 24a77da896d..14514540c06 100644
--- a/src/test/run-fail/overflowing-rsh-1.rs
+++ b/src/test/run-fail/overflowing-rsh-1.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i32 >> 32;
diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs
index b5615cacc20..83dcbd13d2a 100644
--- a/src/test/run-fail/overflowing-rsh-2.rs
+++ b/src/test/run-fail/overflowing-rsh-2.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i32 >> -1;
diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs
index 7598e026d81..3521c050659 100644
--- a/src/test/run-fail/overflowing-rsh-3.rs
+++ b/src/test/run-fail/overflowing-rsh-3.rs
@@ -2,6 +2,7 @@
 // compile-flags: -C debug-assertions
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     let _x = -1_i64 >> 64;
diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs
index a8d3b69392a..ed1191849e5 100644
--- a/src/test/run-fail/overflowing-rsh-4.rs
+++ b/src/test/run-fail/overflowing-rsh-4.rs
@@ -5,6 +5,7 @@
 // truncation does not sidestep the overflow checking.
 
 #![warn(exceeding_bitshifts)]
+#![warn(const_err)]
 
 fn main() {
     // this signals overflow when checking is on
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
index 5d85b0a243e..9e78f7c5120 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs
@@ -3,21 +3,21 @@
 #![allow(non_camel_case_types)]
 
 mod outer_mod {
-    pub mod await { //~ ERROR expected identifier, found reserved keyword `await`
-        pub struct await; //~ ERROR expected identifier, found reserved keyword `await`
+    pub mod await { //~ ERROR expected identifier, found keyword `await`
+        pub struct await; //~ ERROR expected identifier, found keyword `await`
     }
 }
-use self::outer_mod::await::await; //~ ERROR expected identifier, found reserved keyword `await`
-//~^ ERROR expected identifier, found reserved keyword `await`
+use self::outer_mod::await::await; //~ ERROR expected identifier, found keyword `await`
+//~^ ERROR expected identifier, found keyword `await`
 
 struct Foo { await: () }
-//~^ ERROR expected identifier, found reserved keyword `await`
+//~^ ERROR expected identifier, found keyword `await`
 
 impl Foo { fn await() {} }
-//~^ ERROR expected identifier, found reserved keyword `await`
+//~^ ERROR expected identifier, found keyword `await`
 
 macro_rules! await {
-//~^ ERROR expected identifier, found reserved keyword `await`
+//~^ ERROR expected identifier, found keyword `await`
     () => {}
 }
 
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
index 05f28d0a5b2..0e859466322 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
@@ -1,68 +1,68 @@
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:6:13
    |
 LL |     pub mod await {
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     pub mod r#await {
    |             ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:7:20
    |
 LL |         pub struct await;
-   |                    ^^^^^ expected identifier, found reserved keyword
+   |                    ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |         pub struct r#await;
    |                    ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:10:22
    |
 LL | use self::outer_mod::await::await;
-   |                      ^^^^^ expected identifier, found reserved keyword
+   |                      ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | use self::outer_mod::r#await::await;
    |                      ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:10:29
    |
 LL | use self::outer_mod::await::await;
-   |                             ^^^^^ expected identifier, found reserved keyword
+   |                             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | use self::outer_mod::await::r#await;
    |                             ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14
    |
 LL | struct Foo { await: () }
-   |              ^^^^^ expected identifier, found reserved keyword
+   |              ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | struct Foo { r#await: () }
    |              ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:16:15
    |
 LL | impl Foo { fn await() {} }
-   |               ^^^^^ expected identifier, found reserved keyword
+   |               ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | impl Foo { fn r#await() {} }
    |               ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error-in-non-macro-position.rs:19:14
    |
 LL | macro_rules! await {
-   |              ^^^^^ expected identifier, found reserved keyword
+   |              ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | macro_rules! r#await {
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error.rs b/src/test/ui/async-await/await-keyword/2018-edition-error.rs
index e620c27f9e3..7ce52259aca 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error.rs
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error.rs
@@ -7,9 +7,9 @@ mod outer_mod {
     }
 }
 use self::outer_mod::await::await; //~ ERROR expected identifier
-    //~^ ERROR expected identifier, found reserved keyword `await`
+    //~^ ERROR expected identifier, found keyword `await`
 
-macro_rules! await { () => {}; } //~ ERROR expected identifier, found reserved keyword `await`
+macro_rules! await { () => {}; } //~ ERROR expected identifier, found keyword `await`
 
 fn main() {
     await!(); //~ ERROR expected expression, found `)`
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error.stderr
index 9304928cfde..71f403f278e 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error.stderr
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error.stderr
@@ -1,48 +1,48 @@
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error.rs:5:13
    |
 LL |     pub mod await {
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     pub mod r#await {
    |             ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error.rs:6:20
    |
 LL |         pub struct await;
-   |                    ^^^^^ expected identifier, found reserved keyword
+   |                    ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |         pub struct r#await;
    |                    ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error.rs:9:22
    |
 LL | use self::outer_mod::await::await;
-   |                      ^^^^^ expected identifier, found reserved keyword
+   |                      ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | use self::outer_mod::r#await::await;
    |                      ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error.rs:9:29
    |
 LL | use self::outer_mod::await::await;
-   |                             ^^^^^ expected identifier, found reserved keyword
+   |                             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | use self::outer_mod::await::r#await;
    |                             ^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/2018-edition-error.rs:12:14
    |
 LL | macro_rules! await { () => {}; }
-   |              ^^^^^ expected identifier, found reserved keyword
+   |              ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | macro_rules! r#await { () => {}; }
diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs
index bd78a18a40e..ef7edf85049 100644
--- a/src/test/ui/async-await/no-const-async.rs
+++ b/src/test/ui/async-await/no-const-async.rs
@@ -3,5 +3,5 @@
 // compile-flags: --crate-type lib
 
 pub const async fn x() {}
-//~^ ERROR expected identifier, found reserved keyword `async`
+//~^ ERROR expected identifier, found keyword `async`
 //~^^ expected `:`, found keyword `fn`
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index 6d7df57e7b6..fe059145785 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -1,8 +1,8 @@
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/no-const-async.rs:5:11
    |
 LL | pub const async fn x() {}
-   |           ^^^^^ expected identifier, found reserved keyword
+   |           ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL | pub const r#async fn x() {}
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index b85cecda16e..274967ef60d 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -11,6 +11,7 @@ struct Sum<A,B>(A,B);
 
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
     const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error
+    //~| ERROR any use of this value will cause an error
 }
 
 fn foo<T>(_: T) -> &'static u8 {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 707dfee7cd5..de3459c72dd 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -9,13 +9,21 @@ LL |     const MAX: u8 = A::MAX + B::MAX;
    = note: `#[deny(const_err)]` on by default
 
 error[E0080]: evaluation of constant expression failed
-  --> $DIR/issue-50814.rs:17:5
+  --> $DIR/issue-50814.rs:18:5
    |
 LL |     &Sum::<U8,U8>::MAX
    |     ^-----------------
    |      |
    |      referenced constant has errors
 
-error: aborting due to 2 previous errors
+error: any use of this value will cause an error
+  --> $DIR/issue-50814.rs:13:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |     ----------------^^^^^^^^^^^^^^^-
+   |                     |
+   |                     attempt to add with overflow
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.rs b/src/test/ui/consts/const-prop-read-static-in-const.rs
new file mode 100644
index 00000000000..7504fd52595
--- /dev/null
+++ b/src/test/ui/consts/const-prop-read-static-in-const.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+// run-pass
+
+#![allow(dead_code)]
+
+const TEST: u8 = MY_STATIC;
+//~^ skipping const checks
+
+static MY_STATIC: u8 = 4;
+
+fn main() {
+}
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr
new file mode 100644
index 00000000000..bbd5b12ed7d
--- /dev/null
+++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr
@@ -0,0 +1,6 @@
+warning: skipping const checks
+  --> $DIR/const-prop-read-static-in-const.rs:6:18
+   |
+LL | const TEST: u8 = MY_STATIC;
+   |                  ^^^^^^^^^
+
diff --git a/src/test/ui/derived-errors/issue-30580.stderr b/src/test/ui/derived-errors/issue-30580.stderr
index 14c575f2699..7bd0eaf77a9 100644
--- a/src/test/ui/derived-errors/issue-30580.stderr
+++ b/src/test/ui/derived-errors/issue-30580.stderr
@@ -2,7 +2,7 @@ error[E0609]: no field `c` on type `&Foo`
   --> $DIR/issue-30580.rs:12:11
    |
 LL |         b.c;
-   |           ^
+   |           ^ help: a field with a similar name exists: `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/duplicate_entry_error.stderr b/src/test/ui/duplicate_entry_error.stderr
index 1892ad38a59..02be11d1fd0 100644
--- a/src/test/ui/duplicate_entry_error.stderr
+++ b/src/test/ui/duplicate_entry_error.stderr
@@ -7,7 +7,7 @@ LL | |     loop {}
 LL | | }
    | |_^
    |
-   = note: first defined in crate `std`.
+   = note: first defined in crate `std` (which `duplicate_entry_error` depends on).
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
index 2684c8e00b2..9f34a3887b7 100644
--- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
+++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs
@@ -5,7 +5,7 @@
 extern crate edition_kw_macro_2018;
 
 mod one_async {
-    produces_async! {} //~ ERROR expected identifier, found reserved keyword
+    produces_async! {} //~ ERROR expected identifier, found keyword
 }
 mod two_async {
     produces_async_raw! {} // OK
diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
index 321545740cf..04a70cf9830 100644
--- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
+++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr
@@ -1,8 +1,8 @@
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2015-2018-expansion.rs:8:5
    |
 LL |     produces_async! {}
-   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 help: you can escape reserved keywords to use them as identifiers
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
index fb8e0cdb4c3..dbc0465b08e 100644
--- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
+++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -5,7 +5,7 @@
 extern crate edition_kw_macro_2015;
 
 pub fn check_async() {
-    let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
+    let mut async = 1; //~ ERROR expected identifier, found keyword `async`
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
@@ -15,6 +15,6 @@ pub fn check_async() {
 
     if passes_ident!(async) == 1 {}
     if passes_ident!(r#async) == 1 {} // OK
-    module::async(); //~ ERROR expected identifier, found reserved keyword `async`
+    module::async(); //~ ERROR expected identifier, found keyword `async`
     module::r#async(); // OK
 }
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
index 3c4a1533534..be991cd0c81 100644
--- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -1,18 +1,18 @@
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13
    |
 LL |     let mut async = 1;
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     let mut r#async = 1;
    |             ^^^^^^^
 
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13
    |
 LL |     module::async();
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     module::r#async();
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs
index 6f766550d47..a8e69fed695 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs
+++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs
@@ -5,7 +5,7 @@
 extern crate edition_kw_macro_2018;
 
 mod one_async {
-    produces_async! {} //~ ERROR expected identifier, found reserved keyword `async`
+    produces_async! {} //~ ERROR expected identifier, found keyword `async`
 }
 mod two_async {
     produces_async_raw! {} // OK
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
index 8942e3ce430..fb12051eed4 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr
@@ -1,8 +1,8 @@
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2018-2018-expansion.rs:8:5
    |
 LL |     produces_async! {}
-   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found reserved keyword
+   |     ^^^^^^^^^^^^^^^^^^ expected identifier, found keyword
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 help: you can escape reserved keywords to use them as identifiers
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
index 88cebf45ad8..5aca0839f0f 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
+++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -5,7 +5,7 @@
 extern crate edition_kw_macro_2018;
 
 pub fn check_async() {
-    let mut async = 1; //~ ERROR expected identifier, found reserved keyword `async`
+    let mut async = 1; //~ ERROR expected identifier, found keyword `async`
     let mut r#async = 1; // OK
 
     r#async = consumes_async!(async); // OK
@@ -15,6 +15,6 @@ pub fn check_async() {
 
     if passes_ident!(async) == 1 {}
     if passes_ident!(r#async) == 1 {} // OK
-    module::async(); //~ ERROR expected identifier, found reserved keyword `async`
+    module::async(); //~ ERROR expected identifier, found keyword `async`
     module::r#async(); // OK
 }
diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
index 46aa9ca34e1..93a7627f887 100644
--- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -1,18 +1,18 @@
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13
    |
 LL |     let mut async = 1;
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     let mut r#async = 1;
    |             ^^^^^^^
 
-error: expected identifier, found reserved keyword `async`
+error: expected identifier, found keyword `async`
   --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13
    |
 LL |     module::async();
-   |             ^^^^^ expected identifier, found reserved keyword
+   |             ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     module::r#async();
diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr
index 26e6e2e1bce..d4b59a1148e 100644
--- a/src/test/ui/error-codes/E0152.stderr
+++ b/src/test/ui/error-codes/E0152.stderr
@@ -4,7 +4,7 @@ error[E0152]: duplicate lang item found: `arc`.
 LL | struct Foo;
    | ^^^^^^^^^^^
    |
-   = note: first defined in crate `alloc`.
+   = note: first defined in crate `alloc` (which `std` depends on).
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
index 4eead369103..8c6c26f7b2d 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -1,40 +1,40 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:7:1
    |
 LL | #![rustc_deprecated()]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:10:1
    |
 LL | #[rustc_deprecated()]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:13:17
    |
 LL |     mod inner { #![rustc_deprecated()] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:16:5
    |
 LL |     #[rustc_deprecated()] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:19:5
    |
 LL |     #[rustc_deprecated()] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:22:5
    |
 LL |     #[rustc_deprecated()] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:25:5
    |
 LL |     #[rustc_deprecated()] impl S { }
@@ -42,3 +42,4 @@ LL |     #[rustc_deprecated()] impl S { }
 
 error: aborting due to 7 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
index 03410eabe36..09dabd293ff 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -1,40 +1,40 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:7:1
    |
 LL | #![stable()]
    | ^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:10:1
    |
 LL | #[stable()]
    | ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:13:17
    |
 LL |     mod inner { #![stable()] }
    |                 ^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:16:5
    |
 LL |     #[stable()] fn f() { }
    |     ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:19:5
    |
 LL |     #[stable()] struct S;
    |     ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:22:5
    |
 LL |     #[stable()] type T = S;
    |     ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-stable.rs:25:5
    |
 LL |     #[stable()] impl S { }
@@ -42,3 +42,4 @@ LL |     #[stable()] impl S { }
 
 error: aborting due to 7 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
index 5952b3836aa..49da2c59580 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -1,40 +1,40 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:7:1
    |
 LL | #![unstable()]
    | ^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:10:1
    |
 LL | #[unstable()]
    | ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:13:17
    |
 LL |     mod inner { #![unstable()] }
    |                 ^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:16:5
    |
 LL |     #[unstable()] fn f() { }
    |     ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:19:5
    |
 LL |     #[unstable()] struct S;
    |     ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:22:5
    |
 LL |     #[unstable()] type T = S;
    |     ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/issue-43106-gating-of-unstable.rs:25:5
    |
 LL |     #[unstable()] impl S { }
@@ -42,3 +42,4 @@ LL |     #[unstable()] impl S { }
 
 error: aborting due to 7 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/feature-gates/feature-gate-staged_api.stderr b/src/test/ui/feature-gates/feature-gate-staged_api.stderr
index f0db47fe8a8..a71d26ce16f 100644
--- a/src/test/ui/feature-gates/feature-gate-staged_api.stderr
+++ b/src/test/ui/feature-gates/feature-gate-staged_api.stderr
@@ -1,10 +1,10 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/feature-gate-staged_api.rs:1:1
    |
 LL | #![stable(feature = "a", since = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/feature-gate-staged_api.rs:8:1
    |
 LL | #[stable(feature = "a", since = "b")]
@@ -12,3 +12,4 @@ LL | #[stable(feature = "a", since = "b")]
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/issues/issue-27592.rs b/src/test/ui/issues/issue-27592.rs
index b023ea18ac9..88f70f58402 100644
--- a/src/test/ui/issues/issue-27592.rs
+++ b/src/test/ui/issues/issue-27592.rs
@@ -15,5 +15,5 @@ impl ::std::fmt::Write for Stream {
 fn main() {
     write(|| format_args!("{}", String::from("Hello world")));
     //~^ ERROR cannot return value referencing temporary value
-    //~| ERROR cannot return value referencing temporary value
+    //~| ERROR cannot return reference to temporary value
 }
diff --git a/src/test/ui/issues/issue-27592.stderr b/src/test/ui/issues/issue-27592.stderr
index 9d3eaa9705d..c8649d82d74 100644
--- a/src/test/ui/issues/issue-27592.stderr
+++ b/src/test/ui/issues/issue-27592.stderr
@@ -7,14 +7,11 @@ LL |     write(|| format_args!("{}", String::from("Hello world")));
    |              |                  temporary value created here
    |              returns a value referencing data owned by the current function
 
-error[E0515]: cannot return value referencing temporary value
+error[E0515]: cannot return reference to temporary value
   --> $DIR/issue-27592.rs:16:14
    |
 LL |     write(|| format_args!("{}", String::from("Hello world")));
-   |              ^^^^^^^^^^^^^----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |            |
-   |              |            temporary value created here
-   |              returns a value referencing data owned by the current function
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-31011.stderr b/src/test/ui/issues/issue-31011.stderr
index ab0069510fc..c7618e0835b 100644
--- a/src/test/ui/issues/issue-31011.stderr
+++ b/src/test/ui/issues/issue-31011.stderr
@@ -4,6 +4,9 @@ error[E0609]: no field `trace` on type `&T`
 LL |         if $ctx.trace {
    |                 ^^^^^
 ...
+LL | fn wrap<T>(context: &T) -> ()
+   |         - type parameter 'T' declared here
+LL | {
 LL |     log!(context, "entered wrapper");
    |     --------------------------------- in this macro invocation
 
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs
index 0f397a7efe8..dd3b8393429 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs
@@ -1,3 +1,5 @@
+// compile-flags: -O
+
 #![deny(exceeding_bitshifts, const_err)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
index f9f168c14de..25e079b6d81 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.stderr
@@ -1,113 +1,113 @@
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:7:15
+  --> $DIR/lint-exceeding-bitshifts.rs:9:15
    |
 LL |       let n = 1u8 << 8;
    |               ^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:1:9
+  --> $DIR/lint-exceeding-bitshifts.rs:3:9
    |
 LL | #![deny(exceeding_bitshifts, const_err)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:9:15
+  --> $DIR/lint-exceeding-bitshifts.rs:11:15
    |
 LL |       let n = 1u16 << 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:11:15
+  --> $DIR/lint-exceeding-bitshifts.rs:13:15
    |
 LL |       let n = 1u32 << 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:13:15
+  --> $DIR/lint-exceeding-bitshifts.rs:15:15
    |
 LL |       let n = 1u64 << 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:15:15
+  --> $DIR/lint-exceeding-bitshifts.rs:17:15
    |
 LL |       let n = 1i8 << 8;
    |               ^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:17:15
+  --> $DIR/lint-exceeding-bitshifts.rs:19:15
    |
 LL |       let n = 1i16 << 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:19:15
+  --> $DIR/lint-exceeding-bitshifts.rs:21:15
    |
 LL |       let n = 1i32 << 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:21:15
+  --> $DIR/lint-exceeding-bitshifts.rs:23:15
    |
 LL |       let n = 1i64 << 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:24:15
+  --> $DIR/lint-exceeding-bitshifts.rs:26:15
    |
 LL |       let n = 1u8 >> 8;
    |               ^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:26:15
+  --> $DIR/lint-exceeding-bitshifts.rs:28:15
    |
 LL |       let n = 1u16 >> 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:28:15
+  --> $DIR/lint-exceeding-bitshifts.rs:30:15
    |
 LL |       let n = 1u32 >> 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:30:15
+  --> $DIR/lint-exceeding-bitshifts.rs:32:15
    |
 LL |       let n = 1u64 >> 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:32:15
+  --> $DIR/lint-exceeding-bitshifts.rs:34:15
    |
 LL |       let n = 1i8 >> 8;
    |               ^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:34:15
+  --> $DIR/lint-exceeding-bitshifts.rs:36:15
    |
 LL |       let n = 1i16 >> 16;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:36:15
+  --> $DIR/lint-exceeding-bitshifts.rs:38:15
    |
 LL |       let n = 1i32 >> 32;
    |               ^^^^^^^^^^
 
 error: attempt to shift right with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:38:15
+  --> $DIR/lint-exceeding-bitshifts.rs:40:15
    |
 LL |       let n = 1i64 >> 64;
    |               ^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:42:15
+  --> $DIR/lint-exceeding-bitshifts.rs:44:15
    |
 LL |       let n = n << 8;
    |               ^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:44:15
+  --> $DIR/lint-exceeding-bitshifts.rs:46:15
    |
 LL |       let n = 1u8 << -8;
    |               ^^^^^^^^^
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
index bde4865aa3f..69b627355b8 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs
@@ -1,3 +1,5 @@
+// compile-flags: -O
+
 #![deny(exceeding_bitshifts, const_err)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
index 8a6d2a89c70..cb96982a789 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr
@@ -1,23 +1,23 @@
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:7:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:9:15
    |
 LL |       let n = 1u8 << (4+4);
    |               ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/lint-exceeding-bitshifts2.rs:1:9
+  --> $DIR/lint-exceeding-bitshifts2.rs:3:9
    |
 LL | #![deny(exceeding_bitshifts, const_err)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:15:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:17:15
    |
 LL |       let n = 1_isize << BITS;
    |               ^^^^^^^^^^^^^^^
 
 error: attempt to shift left with overflow
-  --> $DIR/lint-exceeding-bitshifts2.rs:16:15
+  --> $DIR/lint-exceeding-bitshifts2.rs:18:15
    |
 LL |       let n = 1_usize << BITS;
    |               ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs
new file mode 100644
index 00000000000..5a94ccd7468
--- /dev/null
+++ b/src/test/ui/lint/redundant-semicolon/auxiliary/redundant-semi-proc-macro-def.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type="proc-macro"]
+#![crate_name="redundant_semi_proc_macro"]
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn should_preserve_spans(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    eprintln!("{:?}", item);
+    item
+}
diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs
new file mode 100644
index 00000000000..f207b235735
--- /dev/null
+++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs
@@ -0,0 +1,19 @@
+// aux-build:redundant-semi-proc-macro-def.rs
+
+#![deny(redundant_semicolon)]
+extern crate redundant_semi_proc_macro;
+use redundant_semi_proc_macro::should_preserve_spans;
+
+#[should_preserve_spans]
+fn span_preservation()  {
+    let tst = 123;; //~ ERROR unnecessary trailing semicolon
+    match tst {
+        // Redundant semicolons are parsed as empty tuple exprs
+        // for the lint, so ensure the lint doesn't affect
+        // empty tuple exprs explicitly in source.
+        123 => (),
+        _ => ()
+    };;; //~ ERROR unnecessary trailing semicolons
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
new file mode 100644
index 00000000000..5f289c0914d
--- /dev/null
+++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
@@ -0,0 +1,21 @@
+TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }]
+error: unnecessary trailing semicolon
+  --> $DIR/redundant-semi-proc-macro.rs:9:19
+   |
+LL |     let tst = 123;;
+   |                   ^ help: remove this semicolon
+   |
+note: lint level defined here
+  --> $DIR/redundant-semi-proc-macro.rs:3:9
+   |
+LL | #![deny(redundant_semicolon)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary trailing semicolons
+  --> $DIR/redundant-semi-proc-macro.rs:16:7
+   |
+LL |     };;;
+   |       ^^ help: remove these semicolons
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr
index 32240311116..e6d24348ca8 100644
--- a/src/test/ui/panic-handler/panic-handler-std.stderr
+++ b/src/test/ui/panic-handler/panic-handler-std.stderr
@@ -6,7 +6,7 @@ LL | |     loop {}
 LL | | }
    | |_^
    |
-   = note: first defined in crate `std`.
+   = note: first defined in crate `std` (which `panic_handler_std` depends on).
 
 error: argument should be `&PanicInfo`
   --> $DIR/panic-handler-std.rs:7:16
diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs
index d46186a0fea..66fd5893af5 100644
--- a/src/test/ui/parser/mut-patterns.rs
+++ b/src/test/ui/parser/mut-patterns.rs
@@ -28,7 +28,7 @@ pub fn main() {
     //~| ERROR `mut` must be attached to each individual binding
     //~| ERROR expected identifier, found reserved keyword `yield`
     //~| ERROR expected identifier, found reserved keyword `become`
-    //~| ERROR expected identifier, found reserved keyword `await`
+    //~| ERROR expected identifier, found keyword `await`
 
     struct W<T, U>(T, U);
     struct B { f: Box<u8> }
diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr
index 18ffaa52558..b1cf99189f1 100644
--- a/src/test/ui/parser/mut-patterns.stderr
+++ b/src/test/ui/parser/mut-patterns.stderr
@@ -62,11 +62,11 @@ help: you can escape reserved keywords to use them as identifiers
 LL |     let mut mut yield(r#become, await) = r#yield(0, 0);
    |                       ^^^^^^^^
 
-error: expected identifier, found reserved keyword `await`
+error: expected identifier, found keyword `await`
   --> $DIR/mut-patterns.rs:26:31
    |
 LL |     let mut mut yield(become, await) = r#yield(0, 0);
-   |                               ^^^^^ expected identifier, found reserved keyword
+   |                               ^^^^^ expected identifier, found keyword
 help: you can escape reserved keywords to use them as identifiers
    |
 LL |     let mut mut yield(become, r#await) = r#yield(0, 0);
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
index 77f896a86d5..32b0f405d6f 100644
--- a/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged-force-unstable.stderr
@@ -1,16 +1,16 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged-force-unstable.rs:3:1
    |
 LL | #[unstable()]
    | ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged-force-unstable.rs:4:1
    |
 LL | #[stable()]
    | ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged-force-unstable.rs:5:1
    |
 LL | #[rustc_deprecated()]
@@ -18,3 +18,4 @@ LL | #[rustc_deprecated()]
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr b/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
index e98f789f54c..7648effc480 100644
--- a/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-non-staged.stderr
@@ -1,16 +1,16 @@
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged.rs:1:1
    |
 LL | #[unstable()]
    | ^^^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged.rs:2:1
    |
 LL | #[stable()]
    | ^^^^^^^^^^^
 
-error: stability attributes may not be used outside of the standard library
+error[E0734]: stability attributes may not be used outside of the standard library
   --> $DIR/stability-attribute-non-staged.rs:3:1
    |
 LL | #[rustc_deprecated()]
@@ -18,3 +18,4 @@ LL | #[rustc_deprecated()]
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0734`.
diff --git a/src/test/ui/structs/struct-pat-derived-error.stderr b/src/test/ui/structs/struct-pat-derived-error.stderr
index 673715cd3ef..6526ef58a44 100644
--- a/src/test/ui/structs/struct-pat-derived-error.stderr
+++ b/src/test/ui/structs/struct-pat-derived-error.stderr
@@ -2,7 +2,7 @@ error[E0609]: no field `d` on type `&A`
   --> $DIR/struct-pat-derived-error.rs:8:31
    |
 LL |         let A { x, y } = self.d;
-   |                               ^
+   |                               ^ help: a field with a similar name exists: `b`
 
 error[E0026]: struct `A` does not have fields named `x`, `y`
   --> $DIR/struct-pat-derived-error.rs:8:17
diff --git a/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs
new file mode 100644
index 00000000000..c57e8149574
--- /dev/null
+++ b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs
@@ -0,0 +1,54 @@
+// Fix issue 52082: Confusing error if accidentially defining a type paramter with the same name as
+// an existing type
+//
+// To this end, make sure that when trying to retrieve a field of a (reference to) type parameter,
+// rustc points to the point where the parameter was defined.
+#[derive(Debug)]
+struct Point
+{
+    x: i32,
+    y: i32
+}
+
+impl Point
+{
+    fn add(a: &Point, b: &Point) -> Point
+    {
+        Point {x: a.x + b.x, y: a.y + b.y}
+    }
+}
+
+trait Eq
+{
+    fn equals_ref<T>(a: &T, b: &T) -> bool;
+    fn equals_val<T>(a: T, b: T) -> bool;
+}
+
+impl Eq for Point
+{
+    fn equals_ref<Point>(a: &Point, b: &Point) -> bool
+    {
+        a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `&Point` [E0609]
+                                 //~|ERROR no field `x` on type `&Point` [E0609]
+                                 //~|ERROR no field `y` on type `&Point` [E0609]
+                                 //~|ERROR no field `y` on type `&Point` [E0609]
+    }
+
+    fn equals_val<Point>(a: Point, b: Point) -> bool
+    {
+        a.x == b.x && a.y == b.y //~ ERROR no field `x` on type `Point` [E0609]
+                                 //~|ERROR no field `x` on type `Point` [E0609]
+                                 //~|ERROR no field `y` on type `Point` [E0609]
+                                 //~|ERROR no field `y` on type `Point` [E0609]
+    }
+}
+
+fn main()
+{
+    let p1 = Point {x:  0, y: 10};
+    let p2 = Point {x: 20, y: 42};
+    println!("{:?}", Point::add(&p1, &p2));
+    println!("p1: {:?}, p2: {:?}", p1, p2);
+    println!("&p1 == &p2: {:?}", Point::equals_ref(&p1, &p2));
+    println!("p1 == p2: {:?}", Point::equals_val(p1, p2));
+}
diff --git a/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr
new file mode 100644
index 00000000000..4be4c91dfc2
--- /dev/null
+++ b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr
@@ -0,0 +1,75 @@
+error[E0609]: no field `x` on type `&Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:11
+   |
+LL |     fn equals_ref<Point>(a: &Point, b: &Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |           ^
+
+error[E0609]: no field `x` on type `&Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:18
+   |
+LL |     fn equals_ref<Point>(a: &Point, b: &Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                  ^
+
+error[E0609]: no field `y` on type `&Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:25
+   |
+LL |     fn equals_ref<Point>(a: &Point, b: &Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                         ^
+
+error[E0609]: no field `y` on type `&Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:32
+   |
+LL |     fn equals_ref<Point>(a: &Point, b: &Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                                ^
+
+error[E0609]: no field `x` on type `Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:11
+   |
+LL |     fn equals_val<Point>(a: Point, b: Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |           ^
+
+error[E0609]: no field `x` on type `Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:18
+   |
+LL |     fn equals_val<Point>(a: Point, b: Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                  ^
+
+error[E0609]: no field `y` on type `Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:25
+   |
+LL |     fn equals_val<Point>(a: Point, b: Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                         ^
+
+error[E0609]: no field `y` on type `Point`
+  --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:32
+   |
+LL |     fn equals_val<Point>(a: Point, b: Point) -> bool
+   |                   ----- type parameter 'Point' declared here
+LL |     {
+LL |         a.x == b.x && a.y == b.y
+   |                                ^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 6d38cfc8630..a824546d436 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -384,7 +384,7 @@ fn map_lib_features(base_src_path: &Path,
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
         if !filename.ends_with(".rs") || filename == "features.rs" ||
-           filename == "diagnostic_list.rs" {
+           filename == "diagnostic_list.rs" || filename == "error_codes.rs" {
             return;
         }