about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs6
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs6
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/tests.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs15
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs52
-rw-r--r--compiler/rustc_expand/src/build.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs59
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_metadata/src/creader.rs40
-rw-r--r--compiler/rustc_metadata/src/locator.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs8
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs11
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/thir.rs31
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs9
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs93
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs8
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs26
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs38
-rw-r--r--compiler/rustc_mir/src/const_eval/error.rs8
-rw-r--r--compiler/rustc_mir/src/const_eval/eval_queries.rs27
-rw-r--r--compiler/rustc_mir/src/transform/check_unsafety.rs1
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs34
-rw-r--r--compiler/rustc_mir/src/util/pretty.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs22
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs9
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs11
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs16
-rw-r--r--compiler/rustc_mir_build/src/thir/visit.rs11
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--compiler/rustc_passes/src/check_attr.rs7
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs16
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs19
-rw-r--r--compiler/rustc_typeck/src/collect.rs50
48 files changed, 325 insertions, 376 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 93d7a597681..d3f5a37fd6e 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1017,7 +1017,7 @@ pub struct Local {
 /// ```
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Arm {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
     pub pat: P<Pat>,
     /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
@@ -2293,7 +2293,7 @@ pub struct EnumDef {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Variant {
     /// Attributes of the variant.
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
     pub id: NodeId,
     /// Span
@@ -2474,7 +2474,7 @@ impl VisibilityKind {
 /// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FieldDef {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 0b6099fd330..296766f8019 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -420,7 +420,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 
 pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
-    visit_attrs(attrs, vis);
+    visit_thin_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -504,7 +504,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     visitor.visit_id(id);
     visitor.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -918,7 +918,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     smallvec![fd]
 }
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 357a2e65cf7..acc41d9f644 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -652,7 +652,7 @@ impl<'a> AstValidator<'a> {
                 self.err_handler()
                     .struct_span_err(
                         *span,
-                        "only foreign or `unsafe extern \"C\" functions may be C-variadic",
+                        "only foreign or `unsafe extern \"C\"` functions may be C-variadic",
                     )
                     .emit();
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs
index b1a73a0bf02..8abd85a5a52 100644
--- a/compiler/rustc_ast_pretty/src/pprust/tests.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs
@@ -49,7 +49,7 @@ fn test_variant_to_string() {
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
-            attrs: Vec::new(),
+            attrs: ast::AttrVec::new(),
             id: ast::DUMMY_NODE_ID,
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index 01a57bea14e..c5f3a9d3379 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -124,12 +124,7 @@ pub fn expand_deriving_rustc_encodable(
             explicit_self: borrowed_explicit_self(),
             args: vec![(
                 Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
-                // FIXME: we could use `sym::s` here, but making `s` a static
-                // symbol changes the symbol index ordering in a way that makes
-                // ui/lint/rfc-2457-non-ascii-idents/lint-confusable-idents.rs
-                // fail. The linting code should be fixed so that its output
-                // does not depend on the symbol index ordering.
-                Symbol::intern("s"),
+                sym::s,
             )],
             ret_ty: Literal(Path::new_(
                 pathvec_std!(result::Result),
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 7e88b58c0e2..00f2f37146d 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args(
 
     let msg = "format argument must be a string literal";
     let fmt_sp = efmt.span;
+    let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
     let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
         Ok(mut fmt) if append_newline => {
             fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
@@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args(
 
     if !parser.errors.is_empty() {
         let err = parser.errors.remove(0);
-        let sp = fmt_span.from_inner(err.span);
+        let sp = if efmt_kind_is_lit {
+            fmt_span.from_inner(err.span)
+        } else {
+            // The format string could be another macro invocation, e.g.:
+            //     format!(concat!("abc", "{}"), 4);
+            // However, `err.span` is an inner span relative to the *result* of
+            // the macro invocation, which is why we would get a nonsensical
+            // result calling `fmt_span.from_inner(err.span)` as above, and
+            // might even end up inside a multibyte character (issue #86085).
+            // Therefore, we conservatively report the error for the entire
+            // argument span here.
+            fmt_span
+        };
         let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
         e.span_label(sp, err.label + " in format string");
         if let Some(note) = err.note {
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index 01cd1cec924..65689ab769c 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -94,13 +94,15 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
         Q: Ord + ?Sized,
         K: Borrow<Q>,
     {
-        // FIXME: This should be in the standard library as `equal_range`. See rust-lang/rfcs#2184.
         match self.binary_search_idx(key) {
             Err(_) => self.idxs_to_items_enumerated(&[]),
 
             Ok(idx) => {
-                let start = self.find_lower_bound(key, idx);
-                let end = self.find_upper_bound(key, idx);
+                let start = self.idx_sorted_by_item_key[..idx]
+                    .partition_point(|&i| self.items[i].0.borrow() != key);
+                let end = idx
+                    + self.idx_sorted_by_item_key[idx..]
+                        .partition_point(|&i| self.items[i].0.borrow() == key);
                 self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end])
             }
         }
@@ -114,50 +116,6 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
         self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key))
     }
 
-    /// Returns the index into the `idx_sorted_by_item_key` array of the first item equal to
-    /// `key`.
-    ///
-    /// `initial` must be an index into that same array for an item that is equal to `key`.
-    fn find_lower_bound<Q>(&self, key: &Q, initial: usize) -> usize
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
-
-        // FIXME: At present, this uses linear search, meaning lookup is only `O(log n)` if duplicate
-        // entries are rare. It would be better to start with a linear search for the common case but
-        // fall back to an exponential search if many duplicates are found. This applies to
-        // `upper_bound` as well.
-        let mut start = initial;
-        while start != 0 && self.items[self.idx_sorted_by_item_key[start - 1]].0.borrow() == key {
-            start -= 1;
-        }
-
-        start
-    }
-
-    /// Returns the index into the `idx_sorted_by_item_key` array of the first item greater than
-    /// `key`, or `self.len()` if no such item exists.
-    ///
-    /// `initial` must be an index into that same array for an item that is equal to `key`.
-    fn find_upper_bound<Q>(&self, key: &Q, initial: usize) -> usize
-    where
-        Q: Ord + ?Sized,
-        K: Borrow<Q>,
-    {
-        debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key);
-
-        // See the FIXME for `find_lower_bound`.
-        let mut end = initial + 1;
-        let len = self.items.len();
-        while end < len && self.items[self.idx_sorted_by_item_key[end]].0.borrow() == key {
-            end += 1;
-        }
-
-        end
-    }
-
     fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator<Item = (I, &'a V)> {
         idxs.iter().map(move |&idx| (idx, &self.items[idx].1))
     }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index ef5b97a9469..824df2757ea 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -432,7 +432,7 @@ impl<'a> ExtCtxt<'a> {
 
     pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
-            attrs: vec![],
+            attrs: AttrVec::new(),
             pat,
             guard: None,
             body: expr,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 577d43b1c8e..bb8d6386d8a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1205,8 +1205,6 @@ pub struct ExprField<'hir> {
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
-    PushUnsafeBlock(UnsafeSource),
-    PopUnsafeBlock(UnsafeSource),
 }
 
 #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 2b932b7c953..d11dca1cba4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1070,8 +1070,6 @@ impl<'a> State<'a> {
     ) {
         match blk.rules {
             hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
-            hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
-            hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
             hir::BlockCheckMode::DefaultBlock => (),
         }
         self.maybe_print_comment(blk.span.lo());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index 17a56046a5c..8dcdd4b149e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -56,33 +56,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
         let poly_fn_sig = self.tcx().fn_sig(id);
         let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig);
-        body.params.iter().enumerate().find_map(|(index, param)| {
-            // May return None; sometimes the tables are not yet populated.
-            let ty = fn_sig.inputs()[index];
-            let mut found_anon_region = false;
-            let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
-                if *r == *anon_region {
-                    found_anon_region = true;
-                    replace_region
+        body.params
+            .iter()
+            .take(if fn_sig.c_variadic {
+                fn_sig.inputs().len()
+            } else {
+                assert_eq!(fn_sig.inputs().len(), body.params.len());
+                body.params.len()
+            })
+            .enumerate()
+            .find_map(|(index, param)| {
+                // May return None; sometimes the tables are not yet populated.
+                let ty = fn_sig.inputs()[index];
+                let mut found_anon_region = false;
+                let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
+                    if *r == *anon_region {
+                        found_anon_region = true;
+                        replace_region
+                    } else {
+                        r
+                    }
+                });
+                if found_anon_region {
+                    let ty_hir_id = fn_decl.inputs[index].hir_id;
+                    let param_ty_span = hir.span(ty_hir_id);
+                    let is_first = index == 0;
+                    Some(AnonymousParamInfo {
+                        param,
+                        param_ty: new_param_ty,
+                        param_ty_span,
+                        bound_region,
+                        is_first,
+                    })
                 } else {
-                    r
+                    None
                 }
-            });
-            if found_anon_region {
-                let ty_hir_id = fn_decl.inputs[index].hir_id;
-                let param_ty_span = hir.span(ty_hir_id);
-                let is_first = index == 0;
-                Some(AnonymousParamInfo {
-                    param,
-                    param_ty: new_param_ty,
-                    param_ty_span,
-                    bound_region,
-                    is_first,
-                })
-            } else {
-                None
-            }
-        })
+            })
     }
 
     pub(super) fn future_return_type(
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 5d8a6084f2e..f486a82ef95 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -715,7 +715,6 @@ fn test_debugging_options_tracking_hash() {
     tracked!(no_codegen, true);
     tracked!(no_generate_arange_section, true);
     tracked!(no_link, true);
-    tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
     tracked!(plt, Some(true));
@@ -724,6 +723,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(print_fuel, Some("abc".to_string()));
     tracked!(profile, true);
     tracked!(profile_emit, Some(PathBuf::from("abc")));
+    tracked!(profiler_runtime, None);
     tracked!(relax_elf_relocations, Some(true));
     tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index d73cfe35dc4..03a46efec3c 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -769,28 +769,32 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
-        if (self.sess.instrument_coverage()
-            || self.sess.opts.debugging_opts.profile
-            || self.sess.opts.cg.profile_generate.enabled())
-            && !self.sess.opts.debugging_opts.no_profiler_runtime
+        let profiler_runtime = &self.sess.opts.debugging_opts.profiler_runtime;
+
+        if !(profiler_runtime.is_some()
+            && (self.sess.instrument_coverage()
+                || self.sess.opts.debugging_opts.profile
+                || self.sess.opts.cg.profile_generate.enabled()))
         {
-            info!("loading profiler");
+            return;
+        }
 
-            if self.sess.contains_name(&krate.attrs, sym::no_core) {
-                self.sess.err(
-                    "`profiler_builtins` crate (required by compiler options) \
-                               is not compatible with crate attribute `#![no_core]`",
-                );
-            }
+        info!("loading profiler");
+
+        let name = Symbol::intern(profiler_runtime.as_ref().unwrap());
+        if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
+            self.sess.err(
+                "`profiler_builtins` crate (required by compiler options) \
+                        is not compatible with crate attribute `#![no_core]`",
+            );
+        }
 
-            let name = sym::profiler_builtins;
-            let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
-            let data = self.cstore.get_crate_data(cnum);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+        let data = self.cstore.get_crate_data(cnum);
 
-            // Sanity check the loaded crate to ensure it is indeed a profiler runtime
-            if !data.is_profiler_runtime() {
-                self.sess.err("the crate `profiler_builtins` is not a profiler runtime");
-            }
+        // Sanity check the loaded crate to ensure it is indeed a profiler runtime
+        if !data.is_profiler_runtime() {
+            self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
         }
     }
 
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 6e736095090..8570bf30f80 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -1100,7 +1100,9 @@ impl CrateError {
                         if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
                             err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
                         }
-                    } else if crate_name == sym::profiler_builtins {
+                    } else if Some(crate_name)
+                        == sess.opts.debugging_opts.profiler_runtime.as_deref().map(Symbol::intern)
+                    {
                         err.note(&"the compiler may have been built without the profiler runtime");
                     }
                     err.span_label(span, "can't find crate");
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 52cb1e1996e..48900fecd3e 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -252,6 +252,10 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
+    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
+        if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] }
+    }
+
     fn read_lazy_with_meta<T: ?Sized + LazyMeta>(
         &mut self,
         meta: T::Meta,
@@ -324,10 +328,6 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
         r
     }
 
-    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
-        if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] }
-    }
-
     fn decode_alloc_id(&mut self) -> Result<rustc_middle::mir::interpret::AllocId, Self::Error> {
         if let Some(alloc_decoding_session) = self.alloc_decoding_session {
             alloc_decoding_session.decode_alloc_id(self)
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 8476929eaec..aa54d1ae7b9 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
 // required that their size stay the same, but we don't want to change
 // it inadvertently. This assert just ensures we're aware of any change.
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-static_assert_size!(DepNode, 18);
+static_assert_size!(DepNode, 17);
 
 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 static_assert_size!(DepNode, 24);
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 7941800c7fa..cb2a355697d 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -518,4 +518,15 @@ impl InterpError<'_> {
             _ => false,
         }
     }
+
+    /// Should this error be reported as a hard error, preventing compilation, or a soft error,
+    /// causing a deny-by-default lint?
+    pub fn is_hard_err(&self) -> bool {
+        use InterpError::*;
+        match *self {
+            MachineStop(ref err) => err.is_hard_err(),
+            InterpError::UndefinedBehavior(_) => true,
+            _ => false,
+        }
+    }
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 7ae7eab6e5a..0daaec272fd 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -494,8 +494,6 @@ impl<'tcx> Body<'tcx> {
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum Safety {
     Safe,
-    /// Unsafe because of a PushUnsafeBlock
-    BuiltinUnsafe,
     /// Unsafe because of an unsafe fn
     FnUnsafe,
     /// Unsafe because of an `unsafe` block
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a6f9a7c96f0..dda407940e3 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -191,10 +191,6 @@ rustc_queries! {
         desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) }
     }
 
-    query projection_ty_from_predicates(key: (DefId, DefId)) -> Option<ty::ProjectionTy<'tcx>> {
-        desc { |tcx| "finding projection type inside predicates of `{}`", tcx.def_path_str(key.0) }
-    }
-
     query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
         desc { "looking up the native libraries of a linked crate" }
     }
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index a5069113702..2f107e7b96c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -97,12 +97,24 @@ pub struct Block {
     pub safety_mode: BlockSafety,
 }
 
+#[derive(Debug, HashStable)]
+pub struct Adt<'tcx> {
+    pub adt_def: &'tcx AdtDef,
+    pub variant_index: VariantIdx,
+    pub substs: SubstsRef<'tcx>,
+
+    /// Optional user-given substs: for something like `let x =
+    /// Bar::<T> { ... }`.
+    pub user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
+
+    pub fields: Box<[FieldExpr]>,
+    pub base: Option<FruInfo<'tcx>>,
+}
+
 #[derive(Copy, Clone, Debug, HashStable)]
 pub enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
-    PushUnsafe,
-    PopUnsafe,
 }
 
 #[derive(Debug, HashStable)]
@@ -145,7 +157,7 @@ pub enum StmtKind<'tcx> {
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Expr<'_>, 144);
+rustc_data_structures::static_assert_size!(Expr<'_>, 104);
 
 /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
 /// into instances of this `Expr` enum. This lowering can be done
@@ -304,18 +316,7 @@ pub enum ExprKind<'tcx> {
     Tuple {
         fields: Box<[ExprId]>,
     },
-    Adt {
-        adt_def: &'tcx AdtDef,
-        variant_index: VariantIdx,
-        substs: SubstsRef<'tcx>,
-
-        /// Optional user-given substs: for something like `let x =
-        /// Bar::<T> { ... }`.
-        user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
-
-        fields: Box<[FieldExpr]>,
-        base: Option<FruInfo<'tcx>>,
-    },
+    Adt(Box<Adt<'tcx>>),
     PlaceTypeAscription {
         source: ExprId,
         /// Type that the user gave to this expression
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index d7767dc39cb..5ec665e913c 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -15,7 +15,7 @@ use crate::mir::{
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::DefId;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::Span;
 use std::hash::Hash;
@@ -179,8 +179,6 @@ pub trait TyDecoder<'tcx>: Decoder {
     where
         F: FnOnce(&mut Self) -> R;
 
-    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
-
     fn positioned_at_shorthand(&self) -> bool {
         (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d13cbdd1228..73991436b7b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -53,6 +53,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
 use rustc_session::Session;
+use rustc_span::def_id::StableCrateId;
 use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -1264,6 +1265,11 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
+    #[inline]
+    pub fn stable_crate_id(self, cnum: CrateNum) -> StableCrateId {
+        self.def_path_hash(cnum.as_def_id()).stable_crate_id()
+    }
+
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
         // crate name and disambiguator since this code is called from debug!()
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 28a44b09de2..6b1ec1b0646 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -672,6 +672,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
             // SIMD vector types.
             ty::Adt(def, substs) if def.repr.simd() => {
+                if !def.is_struct() {
+                    // Should have yielded E0517 by now.
+                    tcx.sess.delay_span_bug(
+                        DUMMY_SP,
+                        "#[repr(simd)] was applied to an ADT that is not a struct",
+                    );
+                    return Err(LayoutError::Unknown(ty));
+                }
+
                 // Supported SIMD vectors are homogeneous ADTs with at least one field:
                 //
                 // * #[repr(simd)] struct S(T, T, T, T);
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index 5c42625306b..ebaef347f42 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Diagnostic;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_query_system::dep_graph::DepContext;
@@ -18,7 +18,7 @@ use rustc_serialize::{
     opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
     Decodable, Decoder, Encodable, Encoder,
 };
-use rustc_session::{CrateDisambiguator, Session};
+use rustc_session::Session;
 use rustc_span::hygiene::{
     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
     SyntaxContext, SyntaxContextData,
@@ -51,8 +51,7 @@ pub struct OnDiskCache<'sess> {
     // session.
     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
 
-    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
-    cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
+    cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>,
 
     source_map: &'sess SourceMap,
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
@@ -113,7 +112,6 @@ pub struct OnDiskCache<'sess> {
 #[derive(Encodable, Decodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
-    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     query_result_index: EncodedQueryResultIndex,
     diagnostics_index: EncodedQueryResultIndex,
     // The location of all allocations.
@@ -186,7 +184,6 @@ impl<'sess> OnDiskCache<'sess> {
             serialized_data: data,
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
-            prev_cnums: footer.prev_cnums,
             cnum_map: OnceCell::new(),
             source_map: sess.source_map(),
             current_diagnostics: Default::default(),
@@ -207,7 +204,6 @@ impl<'sess> OnDiskCache<'sess> {
             serialized_data: Vec::new(),
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
-            prev_cnums: vec![],
             cnum_map: OnceCell::new(),
             source_map,
             current_diagnostics: Default::default(),
@@ -327,16 +323,6 @@ impl<'sess> OnDiskCache<'sess> {
                 interpret_alloc_index
             };
 
-            let sorted_cnums = sorted_cnums_including_local_crate(tcx);
-            let prev_cnums: Vec<_> = sorted_cnums
-                .iter()
-                .map(|&cnum| {
-                    let crate_name = tcx.crate_name(cnum).to_string();
-                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
-                    (cnum.as_u32(), crate_name, crate_disambiguator)
-                })
-                .collect();
-
             let mut syntax_contexts = FxHashMap::default();
             let mut expn_ids = FxHashMap::default();
 
@@ -368,7 +354,6 @@ impl<'sess> OnDiskCache<'sess> {
                 TAG_FILE_FOOTER,
                 &Footer {
                     file_index_to_stable_id,
-                    prev_cnums,
                     query_result_index,
                     diagnostics_index,
                     interpret_alloc_index,
@@ -385,16 +370,7 @@ impl<'sess> OnDiskCache<'sess> {
             // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
             // of the footer must be the last thing in the data stream.
 
-            return Ok(());
-
-            fn sorted_cnums_including_local_crate(tcx: TyCtxt<'_>) -> Vec<CrateNum> {
-                let mut cnums = vec![LOCAL_CRATE];
-                cnums.extend_from_slice(tcx.crates());
-                cnums.sort_unstable();
-                // Just to be sure...
-                cnums.dedup();
-                cnums
-            }
+            Ok(())
         })
     }
 
@@ -429,12 +405,11 @@ impl<'sess> OnDiskCache<'sess> {
         self.foreign_def_path_hashes.get(hash).copied()
     }
 
-    fn try_remap_cnum(&self, tcx: TyCtxt<'_>, cnum: u32) -> Option<CrateNum> {
-        let cnum_map =
-            self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
-        debug!("try_remap_cnum({}): cnum_map={:?}", cnum, cnum_map);
+    fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> {
+        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
+        debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map);
 
-        cnum_map[CrateNum::from_u32(cnum)]
+        cnum_map.get(&stable_crate_id).copied()
     }
 
     pub(crate) fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
@@ -533,8 +508,7 @@ impl<'sess> OnDiskCache<'sess> {
     where
         T: Decodable<CacheDecoder<'a, 'tcx>>,
     {
-        let cnum_map =
-            self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
+        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
 
         let mut decoder = CacheDecoder {
             tcx,
@@ -555,31 +529,16 @@ impl<'sess> OnDiskCache<'sess> {
     // current-session-`CrateNum`. There might be `CrateNum`s from the previous
     // `Session` that don't occur in the current one. For these, the mapping
     // maps to None.
-    fn compute_cnum_map(
-        tcx: TyCtxt<'_>,
-        prev_cnums: &[(u32, String, CrateDisambiguator)],
-    ) -> IndexVec<CrateNum, Option<CrateNum>> {
+    fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> {
         tcx.dep_graph.with_ignore(|| {
-            let current_cnums = tcx
-                .all_crate_nums(())
+            tcx.all_crate_nums(())
                 .iter()
+                .chain(std::iter::once(&LOCAL_CRATE))
                 .map(|&cnum| {
-                    let crate_name = tcx.crate_name(cnum).to_string();
-                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
-                    ((crate_name, crate_disambiguator), cnum)
+                    let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
+                    (hash, cnum)
                 })
-                .collect::<FxHashMap<_, _>>();
-
-            let map_size = prev_cnums.iter().map(|&(cnum, ..)| cnum).max().unwrap_or(0) + 1;
-            let mut map = IndexVec::from_elem_n(None, map_size as usize);
-
-            for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
-                let key = (crate_name.clone(), crate_disambiguator);
-                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
-            }
-
-            map[LOCAL_CRATE] = Some(LOCAL_CRATE);
-            map
+                .collect()
         })
     }
 
@@ -612,7 +571,7 @@ impl<'sess> OnDiskCache<'sess> {
                 debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
                 // If the owning crate no longer exists, the corresponding definition definitely
                 // no longer exists.
-                let krate = self.try_remap_cnum(tcx, raw_def_id.krate)?;
+                let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
                 debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
                 // If our `DefPathHash` corresponded to a definition in the local crate,
                 // we should have either found it in `local_def_path_hash_to_def_id`, or
@@ -644,7 +603,7 @@ pub struct CacheDecoder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     opaque: opaque::Decoder<'a>,
     source_map: &'a SourceMap,
-    cnum_map: &'a IndexVec<CrateNum, Option<CrateNum>>,
+    cnum_map: &'a UnhashMap<StableCrateId, CrateNum>,
     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, StableSourceFileId>,
     alloc_decoding_session: AllocDecodingSession<'a>,
@@ -765,10 +724,6 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
         r
     }
 
-    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
-        self.cnum_map[cnum].unwrap_or_else(|| bug!("could not find new `CrateNum` for {:?}", cnum))
-    }
-
     fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
         let alloc_decoding_session = self.alloc_decoding_session;
         alloc_decoding_session.decode_alloc_id(self)
@@ -850,8 +805,9 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
-        let cnum = CrateNum::from_u32(u32::decode(d)?);
-        Ok(d.map_encoded_cnum_to_current(cnum))
+        let stable_id = StableCrateId::decode(d)?;
+        let cnum = d.cnum_map[&stable_id];
+        Ok(cnum)
     }
 }
 
@@ -1061,6 +1017,15 @@ where
     }
 }
 
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum
+where
+    E: 'a + OpaqueEncoder,
+{
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        s.tcx.stable_crate_id(*self).encode(s)
+    }
+}
+
 impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
 where
     E: 'a + OpaqueEncoder,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index 8b0761889b8..a0c9b43d5af 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -453,6 +453,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 Some(borrow_span),
+                None,
             );
         err.buffer(&mut self.errors_buffer);
     }
@@ -498,6 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         err
     }
@@ -718,6 +720,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             first_borrow_desc,
             None,
+            Some((issued_span, span)),
         );
 
         err
@@ -1076,6 +1079,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     &mut err,
                     "",
                     None,
+                    None,
                 );
             }
         } else {
@@ -1093,6 +1097,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 &mut err,
                 "",
                 None,
+                None,
             );
         }
 
@@ -1158,6 +1163,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         err.buffer(&mut self.errors_buffer);
@@ -1236,6 +1242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         let within = if borrow_spans.for_generator() { " by generator" } else { "" };
@@ -1614,6 +1621,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &mut err,
             "",
             None,
+            None,
         );
 
         self.explain_deref_coercion(loan, &mut err);
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index e9f1ecb9bbc..76de010d139 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -66,6 +66,7 @@ impl BorrowExplanation {
         err: &mut DiagnosticBuilder<'_>,
         borrow_desc: &str,
         borrow_span: Option<Span>,
+        multiple_borrow_span: Option<(Span, Span)>,
     ) {
         match *self {
             BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => {
@@ -192,14 +193,23 @@ impl BorrowExplanation {
 
                         if let Some(info) = &local_decl.is_block_tail {
                             if info.tail_result_is_ignored {
-                                err.span_suggestion_verbose(
-                                    info.span.shrink_to_hi(),
-                                    "consider adding semicolon after the expression so its \
-                                     temporaries are dropped sooner, before the local variables \
-                                     declared by the block are dropped",
-                                    ";".to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                // #85581: If the first mutable borrow's scope contains
+                                // the second borrow, this suggestion isn't helpful.
+                                if !multiple_borrow_span
+                                    .map(|(old, new)| {
+                                        old.to(info.span.shrink_to_hi()).contains(new)
+                                    })
+                                    .unwrap_or(false)
+                                {
+                                    err.span_suggestion_verbose(
+                                        info.span.shrink_to_hi(),
+                                        "consider adding semicolon after the expression so its \
+                                        temporaries are dropped sooner, before the local variables \
+                                        declared by the block are dropped",
+                                        ";".to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
                             } else {
                                 err.note(
                                     "the temporary is part of an expression at the end of a \
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
index 3ec24156f22..f2d69255d50 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
@@ -60,33 +60,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
-                let universal_substs =
-                    infcx.tcx.fold_regions(substs, &mut false, |region, _| match *region {
-                        ty::ReVar(vid) => {
-                            subst_regions.push(vid);
-                            self.definitions[vid].external_name.unwrap_or_else(|| {
-                                infcx.tcx.sess.delay_span_bug(
-                                    span,
-                                    "opaque type with non-universal region substs",
-                                );
-                                infcx.tcx.lifetimes.re_static
-                            })
-                        }
-                        // We don't fold regions in the predicates of opaque
-                        // types to `ReVar`s. This means that in a case like
-                        //
-                        // fn f<'a: 'a>() -> impl Iterator<Item = impl Sized>
-                        //
-                        // The inner opaque type has `'static` in its substs.
-                        ty::ReStatic => region,
-                        _ => {
-                            infcx.tcx.sess.delay_span_bug(
-                                span,
-                                &format!("unexpected concrete region in borrowck: {:?}", region),
-                            );
-                            region
-                        }
-                    });
+                let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
+                    let vid = self.universal_regions.to_region_vid(region);
+                    subst_regions.push(vid);
+                    self.definitions[vid].external_name.unwrap_or_else(|| {
+                        infcx
+                            .tcx
+                            .sess
+                            .delay_span_bug(span, "opaque type with non-universal region substs");
+                        infcx.tcx.lifetimes.re_static
+                    })
+                });
 
                 subst_regions.sort();
                 subst_regions.dedup();
diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_mir/src/const_eval/error.rs
index fc21047ab72..17e8ab2a4da 100644
--- a/compiler/rustc_mir/src/const_eval/error.rs
+++ b/compiler/rustc_mir/src/const_eval/error.rs
@@ -157,7 +157,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
         tcx: TyCtxtAt<'tcx>,
         message: &str,
         emit: impl FnOnce(DiagnosticBuilder<'_>),
-        mut lint_root: Option<hir::HirId>,
+        lint_root: Option<hir::HirId>,
     ) -> ErrorHandled {
         let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| {
             trace!("reporting const eval failure at {:?}", self.span);
@@ -194,12 +194,6 @@ impl<'tcx> ConstEvalErr<'tcx> {
             _ => {}
         };
 
-        // If we have a 'hard error', then set `lint_root` to `None` so that we don't
-        // emit a lint.
-        if matches!(&self.error, InterpError::MachineStop(err) if err.is_hard_err()) {
-            lint_root = None;
-        }
-
         let err_msg = self.error.to_string();
 
         // Regular case - emit a lint.
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs
index 460fea37461..536dbad4f76 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs
@@ -312,22 +312,17 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
             let err = ConstEvalErr::new(&ecx, error, None);
             // Some CTFE errors raise just a lint, not a hard error; see
             // <https://github.com/rust-lang/rust/issues/71800>.
-            let emit_as_lint = if let Some(def) = def.as_local() {
+            let is_hard_err = if let Some(def) = def.as_local() {
                 // (Associated) consts only emit a lint, since they might be unused.
-                matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
+                !matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
+                    // check if the inner InterpError is hard
+                    || err.error.is_hard_err()
             } else {
                 // use of broken constant from other crate: always an error
-                false
+                true
             };
-            if emit_as_lint {
-                let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
-                Err(err.report_as_lint(
-                    tcx.at(tcx.def_span(def.did)),
-                    "any use of this value will cause an error",
-                    hir_id,
-                    Some(err.span),
-                ))
-            } else {
+
+            if is_hard_err {
                 let msg = if is_static {
                     Cow::from("could not evaluate static initializer")
                 } else {
@@ -345,6 +340,14 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 };
 
                 Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), &msg))
+            } else {
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
+                Err(err.report_as_lint(
+                    tcx.at(tcx.def_span(def.did)),
+                    "any use of this value will cause an error",
+                    hir_id,
+                    Some(err.span),
+                ))
             }
         }
         Ok(mplace) => {
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index 103ddda1a1d..324a5257f5d 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -321,7 +321,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 }
                 false
             }
-            Safety::BuiltinUnsafe => true,
             Safety::ExplicitUnsafe(hir_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 681d63c6fc9..b56c247127c 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -528,14 +528,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         source_info: SourceInfo,
         message: &'static str,
         panic: AssertKind<impl std::fmt::Debug>,
-    ) -> Option<()> {
-        let lint_root = self.lint_root(source_info)?;
-        self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
-            let mut err = lint.build(message);
-            err.span_label(source_info.span, format!("{:?}", panic));
-            err.emit()
-        });
-        None
+    ) {
+        if let Some(lint_root) = self.lint_root(source_info) {
+            self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
+                let mut err = lint.build(message);
+                err.span_label(source_info.span, format!("{:?}", panic));
+                err.emit()
+            });
+        }
     }
 
     fn check_unary_op(
@@ -557,7 +557,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 source_info,
                 "this arithmetic operation will overflow",
                 AssertKind::OverflowNeg(val.to_const_int()),
-            )?;
+            );
+            return None;
         }
 
         Some(())
@@ -602,7 +603,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         },
                         r.to_const_int(),
                     ),
-                )?;
+                );
+                return None;
             }
         }
 
@@ -617,7 +619,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     source_info,
                     "this arithmetic operation will overflow",
                     AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
-                )?;
+                );
+                return None;
             }
         }
         Some(())
@@ -1202,12 +1205,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                         let mut eval_to_int = |op| {
                             // This can be `None` if the lhs wasn't const propagated and we just
                             // triggered the assert on the value of the rhs.
-                            match self.eval_operand(op, source_info) {
-                                Some(op) => DbgVal::Val(
-                                    self.ecx.read_immediate(&op).unwrap().to_const_int(),
-                                ),
-                                None => DbgVal::Underscore,
-                            }
+                            self.eval_operand(op, source_info).map_or(DbgVal::Underscore, |op| {
+                                DbgVal::Val(self.ecx.read_immediate(&op).unwrap().to_const_int())
+                            })
                         };
                         let msg = match msg {
                             AssertKind::DivisionByZero(op) => {
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs
index c4e1e184ac5..f8325a3646f 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_mir/src/util/pretty.rs
@@ -99,7 +99,10 @@ pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) ->
     });
     filters.split('|').any(|or_filter| {
         or_filter.split('&').all(|and_filter| {
-            and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
+            let and_filter_trimmed = and_filter.trim();
+            and_filter_trimmed == "all"
+                || pass_name.contains(and_filter_trimmed)
+                || node_path.contains(and_filter_trimmed)
         })
     })
 }
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 8426b24270d..4e1983aca94 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -74,8 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // First we build all the statements in the block.
         let mut let_scope_stack = Vec::with_capacity(8);
         let outer_source_scope = this.source_scope;
-        let outer_push_unsafe_count = this.push_unsafe_count;
-        let outer_unpushed_unsafe = this.unpushed_unsafe;
+        let outer_in_scope_unsafe = this.in_scope_unsafe;
         this.update_source_scope_for_safety_mode(span, safety_mode);
 
         let source_info = this.source_info(span);
@@ -206,8 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
         // Restore the original source scope.
         this.source_scope = outer_source_scope;
-        this.push_unsafe_count = outer_push_unsafe_count;
-        this.unpushed_unsafe = outer_unpushed_unsafe;
+        this.in_scope_unsafe = outer_in_scope_unsafe;
         block.unit()
     }
 
@@ -217,8 +215,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let new_unsafety = match safety_mode {
             BlockSafety::Safe => None,
             BlockSafety::ExplicitUnsafe(hir_id) => {
-                assert_eq!(self.push_unsafe_count, 0);
-                match self.unpushed_unsafe {
+                match self.in_scope_unsafe {
                     Safety::Safe => {}
                     // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
                     Safety::FnUnsafe
@@ -226,20 +223,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             != Level::Allow => {}
                     _ => return,
                 }
-                self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);
+                self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id);
                 Some(Safety::ExplicitUnsafe(hir_id))
             }
-            BlockSafety::PushUnsafe => {
-                self.push_unsafe_count += 1;
-                Some(Safety::BuiltinUnsafe)
-            }
-            BlockSafety::PopUnsafe => {
-                self.push_unsafe_count = self
-                    .push_unsafe_count
-                    .checked_sub(1)
-                    .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
-                if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
-            }
         };
 
         if let Some(unsafety) = new_unsafety {
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index f2b00f0f6ed..d7b3a85c15d 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -264,7 +264,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.push_assign(block, source_info, destination, address_of);
                 block.unit()
             }
-            ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => {
+            ExprKind::Adt(box Adt {
+                adt_def,
+                variant_index,
+                substs,
+                user_ty,
+                ref fields,
+                ref base,
+            }) => {
                 // See the notes for `ExprKind::Array` in `as_rvalue` and for
                 // `ExprKind::Borrow` above.
                 let is_union = adt_def.is_union();
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 10d6521e7de..f5f6da3ec0b 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -367,12 +367,8 @@ struct Builder<'a, 'tcx> {
     /// `{ STMTS; EXPR1 } + EXPR2`.
     block_context: BlockContext,
 
-    /// The current unsafe block in scope, even if it is hidden by
-    /// a `PushUnsafeBlock`.
-    unpushed_unsafe: Safety,
-
-    /// The number of `push_unsafe_block` levels in scope.
-    push_unsafe_count: usize,
+    /// The current unsafe block in scope
+    in_scope_unsafe: Safety,
 
     /// The vector of all scopes that we have created thus far;
     /// we track this for debuginfo later.
@@ -877,8 +873,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             guard_context: vec![],
-            push_unsafe_count: 0,
-            unpushed_unsafe: safety,
+            in_scope_unsafe: safety,
             local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
             canonical_user_type_annotations: IndexVec::new(),
             upvar_mutbls: vec![],
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 2d52577829c..e4ed5dece86 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -195,14 +195,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
                 self.requires_unsafe(expr.span, UseOfInlineAssembly);
             }
-            ExprKind::Adt {
+            ExprKind::Adt(box Adt {
                 adt_def,
                 variant_index: _,
                 substs: _,
                 user_ty: _,
                 fields: _,
                 base: _,
-            } => match self.tcx.layout_scalar_valid_range(adt_def.did) {
+            }) => match self.tcx.layout_scalar_valid_range(adt_def.did) {
                 (Bound::Unbounded, Bound::Unbounded) => {}
                 _ => self.requires_unsafe(expr.span, InitializingTypeWith),
             },
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 77235fe9ab3..4fe8cd8541a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -27,8 +27,6 @@ impl<'tcx> Cx<'tcx> {
             safety_mode: match block.rules {
                 hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
                 hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
-                hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe,
-                hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe,
             },
         }
     }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index aa4acfab5c8..da8cd66acb1 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -228,14 +228,14 @@ impl<'tcx> Cx<'tcx> {
                                 expr: self.mirror_expr(e),
                             })
                             .collect();
-                        ExprKind::Adt {
+                        ExprKind::Adt(Box::new(Adt {
                             adt_def,
                             substs,
                             variant_index: index,
                             fields: field_refs,
                             user_ty,
                             base: None,
-                        }
+                        }))
                     } else {
                         ExprKind::Call {
                             ty: self.typeck_results().node_type(fun.hir_id),
@@ -362,7 +362,7 @@ impl<'tcx> Cx<'tcx> {
                         let user_provided_types = self.typeck_results().user_provided_types();
                         let user_ty = user_provided_types.get(expr.hir_id).copied();
                         debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty);
-                        ExprKind::Adt {
+                        ExprKind::Adt(Box::new(Adt {
                             adt_def: adt,
                             variant_index: VariantIdx::new(0),
                             substs,
@@ -375,7 +375,7 @@ impl<'tcx> Cx<'tcx> {
                                     .copied()
                                     .collect(),
                             }),
-                        }
+                        }))
                     }
                     AdtKind::Enum => {
                         let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
@@ -388,14 +388,14 @@ impl<'tcx> Cx<'tcx> {
                                     self.typeck_results().user_provided_types();
                                 let user_ty = user_provided_types.get(expr.hir_id).copied();
                                 debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty);
-                                ExprKind::Adt {
+                                ExprKind::Adt(Box::new(Adt {
                                     adt_def: adt,
                                     variant_index: index,
                                     substs,
                                     user_ty,
                                     fields: self.field_refs(fields),
                                     base: None,
-                                }
+                                }))
                             }
                             _ => {
                                 span_bug!(expr.span, "unexpected res: {:?}", res);
@@ -906,14 +906,14 @@ impl<'tcx> Cx<'tcx> {
                 match ty.kind() {
                     // A unit struct/variant which is used as a value.
                     // We return a completely different ExprKind here to account for this special case.
-                    ty::Adt(adt_def, substs) => ExprKind::Adt {
+                    ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(Adt {
                         adt_def,
                         variant_index: adt_def.variant_index_with_ctor_id(def_id),
                         substs,
                         user_ty: user_provided_type,
                         fields: box [],
                         base: None,
-                    },
+                    })),
                     _ => bug!("unexpected ty: {:?}", ty),
                 }
             }
diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs
index 12c6a9c00b2..f611bb6eb43 100644
--- a/compiler/rustc_mir_build/src/thir/visit.rs
+++ b/compiler/rustc_mir_build/src/thir/visit.rs
@@ -1,4 +1,4 @@
-use rustc_middle::thir::*;
+use rustc_middle::thir::{self, *};
 use rustc_middle::ty::Const;
 
 pub trait Visitor<'a, 'tcx: 'a>: Sized {
@@ -98,7 +98,14 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                 visitor.visit_expr(&visitor.thir()[field]);
             }
         }
-        Adt { ref fields, ref base, adt_def: _, variant_index: _, substs: _, user_ty: _ } => {
+        Adt(box thir::Adt {
+            ref fields,
+            ref base,
+            adt_def: _,
+            variant_index: _,
+            substs: _,
+            user_ty: _,
+        }) => {
             for field in &**fields {
                 visitor.visit_expr(&visitor.thir()[field.expr]);
             }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c8789abc142..88ebf4aca23 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2116,7 +2116,7 @@ impl<'a> Parser<'a> {
                     let span = body.span;
                     return Ok((
                         ast::Arm {
-                            attrs,
+                            attrs: attrs.into(),
                             pat,
                             guard,
                             body,
@@ -2170,7 +2170,7 @@ impl<'a> Parser<'a> {
 
             Ok((
                 ast::Arm {
-                    attrs,
+                    attrs: attrs.into(),
                     pat,
                     guard,
                     body: expr,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 54e6ff6272c..2daa9e2485b 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> {
                     ident,
                     vis,
                     id: DUMMY_NODE_ID,
-                    attrs: variant_attrs,
+                    attrs: variant_attrs.into(),
                     data: struct_def,
                     disr_expr,
                     span: vlo.to(this.prev_token.span),
@@ -1286,7 +1286,7 @@ impl<'a> Parser<'a> {
                         ident: None,
                         id: DUMMY_NODE_ID,
                         ty,
-                        attrs,
+                        attrs: attrs.into(),
                         is_placeholder: false,
                     },
                     TrailingToken::MaybeComma,
@@ -1460,7 +1460,7 @@ impl<'a> Parser<'a> {
             vis,
             id: DUMMY_NODE_ID,
             ty,
-            attrs,
+            attrs: attrs.into(),
             is_placeholder: false,
         })
     }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index eca84c791fb..e85392cf0bd 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -525,8 +525,11 @@ impl CheckAttrVisitor<'tcx> {
             self.doc_attr_str_error(meta, "keyword");
             return false;
         }
-        match self.tcx.hir().expect_item(hir_id).kind {
-            ItemKind::Mod(ref module) => {
+        match self.tcx.hir().find(hir_id).and_then(|node| match node {
+            hir::Node::Item(item) => Some(&item.kind),
+            _ => None,
+        }) {
+            Some(ItemKind::Mod(ref module)) => {
                 if !module.item_ids.is_empty() {
                     self.tcx
                         .sess
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 1946bfd78cc..ebf59bb4cc6 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1160,8 +1160,6 @@ options! {
         "compile without linking"),
     no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
-    no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
-        "prevent automatic injection of the profiler_builtins crate"),
     normalize_docs: bool = (false, parse_bool, [TRACKED],
         "normalize associated items in rustdoc when generating documentation"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
@@ -1205,6 +1203,8 @@ options! {
     profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "file path to emit profiling data at runtime when using 'profile' \
         (default based on relative source path)"),
+    profiler_runtime: Option<String> = (Some(String::from("profiler_builtins")), parse_opt_string, [TRACKED],
+        "name of the profiler runtime crate to automatically inject, or None to disable"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
         "enable queries of the dependency graph for regression testing (default: no)"),
     query_stats: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a96d37c652d..862bde3f6a3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1062,6 +1062,7 @@ symbols! {
         rustdoc,
         rustfmt,
         rvalue_static_promotion,
+        s,
         sanitize,
         sanitizer_runtime,
         saturating_add,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0f2aaeb533a..437517989ab 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -769,6 +769,7 @@ supported_targets! {
     ("armv7-unknown-freebsd", armv7_unknown_freebsd),
     ("i686-unknown-freebsd", i686_unknown_freebsd),
     ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
+    ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd),
     ("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
 
     ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
new file mode 100644
index 00000000000..283e9f744cb
--- /dev/null
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -0,0 +1,16 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::freebsd_base::opts();
+    base.cpu = "ppc64le".to_string();
+    base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Target {
+        llvm_target: "powerpc64le-unknown-freebsd".to_string(),
+        pointer_width: 64,
+        data_layout: "e-m:e-i64:64-n32:64".to_string(),
+        arch: "powerpc64".to_string(),
+        options: TargetOptions { mcount: "_mcount".to_string(), ..base },
+    }
+}
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index ad7853b7cd0..d102896bfa6 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -174,13 +174,12 @@ impl Needs {
 pub struct UnsafetyState {
     pub def: hir::HirId,
     pub unsafety: hir::Unsafety,
-    pub unsafe_push_count: u32,
     from_fn: bool,
 }
 
 impl UnsafetyState {
     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
+        UnsafetyState { def, unsafety, from_fn: true }
     }
 
     pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
@@ -193,19 +192,11 @@ impl UnsafetyState {
             hir::Unsafety::Unsafe if self.from_fn => self,
 
             unsafety => {
-                let (unsafety, def, count) = match blk.rules {
-                    BlockCheckMode::PushUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap())
-                    }
-                    BlockCheckMode::PopUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap())
-                    }
-                    BlockCheckMode::UnsafeBlock(..) => {
-                        (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count)
-                    }
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
+                let (unsafety, def) = match blk.rules {
+                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
+                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
                 };
-                UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false }
+                UnsafetyState { def, unsafety, from_fn: false }
             }
         }
     }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index ee3ac3b62d9..248669a2c0c 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -77,7 +77,6 @@ pub fn provide(providers: &mut Providers) {
         generics_of,
         predicates_of,
         predicates_defined_on,
-        projection_ty_from_predicates,
         explicit_predicates_of,
         super_predicates_of,
         super_predicates_that_define_assoc_type,
@@ -180,8 +179,7 @@ crate fn placeholder_type_error(
     // Suggest, but only if it is not a function in const or static
     if suggest {
         let mut is_fn = false;
-        let mut is_const = false;
-        let mut is_static = false;
+        let mut is_const_or_static = false;
 
         if let Some(hir_ty) = hir_ty {
             if let hir::TyKind::BareFn(_) = hir_ty.kind {
@@ -191,19 +189,26 @@ crate fn placeholder_type_error(
                 let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id);
                 let parent_node = tcx.hir().get(parent_id);
 
-                if let hir::Node::Item(item) = parent_node {
-                    if let hir::ItemKind::Const(_, _) = item.kind {
-                        is_const = true;
-                    } else if let hir::ItemKind::Static(_, _, _) = item.kind {
-                        is_static = true;
-                    }
-                }
+                is_const_or_static = match parent_node {
+                    Node::Item(&hir::Item {
+                        kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
+                        ..
+                    })
+                    | Node::TraitItem(&hir::TraitItem {
+                        kind: hir::TraitItemKind::Const(..),
+                        ..
+                    })
+                    | Node::ImplItem(&hir::ImplItem {
+                        kind: hir::ImplItemKind::Const(..), ..
+                    }) => true,
+                    _ => false,
+                };
             }
         }
 
         // if function is wrapped around a const or static,
         // then don't show the suggestion
-        if !(is_fn && (is_const || is_static)) {
+        if !(is_fn && is_const_or_static) {
             err.multipart_suggestion(
                 "use type parameters instead",
                 sugg,
@@ -2352,29 +2357,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     }
 }
 
-fn projection_ty_from_predicates(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        // ty_def_id
-        DefId,
-        // def_id of `N` in `<T as Trait>::N`
-        DefId,
-    ),
-) -> Option<ty::ProjectionTy<'tcx>> {
-    let (ty_def_id, item_def_id) = key;
-    let mut projection_ty = None;
-    for (predicate, _) in tcx.predicates_of(ty_def_id).predicates {
-        if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder()
-        {
-            if item_def_id == projection_predicate.projection_ty.item_def_id {
-                projection_ty = Some(projection_predicate.projection_ty);
-                break;
-            }
-        }
-    }
-    projection_ty
-}
-
 /// Converts a specific `GenericBound` from the AST into a set of
 /// predicates that apply to the self type. A vector is returned
 /// because this can be anywhere from zero predicates (`T: ?Sized` adds no