diff --git a/Cargo.lock b/Cargo.lock
index d7806b5daa63a..070d72bb0a9de 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4059,6 +4059,7 @@ dependencies = [
  "indexmap",
  "rustc_macros",
  "smallvec",
+ "tempfile",
  "thin-vec",
 ]
 
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 22de7549e9409..4389d2b60bc55 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -108,6 +108,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
         debug!(?region);
     }
 
+    #[instrument(skip(self), level = "debug")]
+    fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location) {
+        let old_ct = *ct;
+        *ct = self.renumber_regions(old_ct, || RegionCtxt::Location(location));
+
+        debug!(?ct);
+    }
+
     #[instrument(skip(self), level = "debug")]
     fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
         let literal = constant.literal;
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 438920e293db8..bd21f2c701f56 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1798,6 +1798,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             Rvalue::Repeat(operand, len) => {
                 self.check_operand(operand, location);
 
+                let array_ty = rvalue.ty(body.local_decls(), tcx);
+                self.prove_predicate(
+                    ty::PredicateKind::WellFormed(array_ty.into()),
+                    Locations::Single(location),
+                    ConstraintCategory::Boring,
+                );
+
                 // If the length cannot be evaluated we must assume that the length can be larger
                 // than 1.
                 // If the length is larger than 1, the repeat expression will need to copy the
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index b6d7484bccefd..2e3adc0866931 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -24,7 +24,7 @@ codegen_llvm_error_writing_def_file =
     Error writing .DEF file: {$error}
 
 codegen_llvm_error_calling_dlltool =
-    Error calling dlltool: {$error}
+    Error calling dlltool '{$dlltool_path}': {$error}
 
 codegen_llvm_dlltool_fail_import_library =
     Dlltool could not create import library: {$stdout}
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 12da21dc47772..a6416e9540cc0 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -198,7 +198,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
                 "arm" => ("arm", "--32"),
                 _ => panic!("unsupported arch {}", sess.target.arch),
             };
-            let result = std::process::Command::new(dlltool)
+            let result = std::process::Command::new(&dlltool)
                 .args([
                     "-d",
                     def_file_path.to_str().unwrap(),
@@ -218,9 +218,13 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
 
             match result {
                 Err(e) => {
-                    sess.emit_fatal(ErrorCallingDllTool { error: e });
+                    sess.emit_fatal(ErrorCallingDllTool {
+                        dlltool_path: dlltool.to_string_lossy(),
+                        error: e,
+                    });
                 }
-                Ok(output) if !output.status.success() => {
+                // dlltool returns '0' on failure, so check for error output instead.
+                Ok(output) if !output.stderr.is_empty() => {
                     sess.emit_fatal(DlltoolFailImportLibrary {
                         stdout: String::from_utf8_lossy(&output.stdout),
                         stderr: String::from_utf8_lossy(&output.stderr),
@@ -431,7 +435,7 @@ fn string_to_io_error(s: String) -> io::Error {
 
 fn find_binutils_dlltool(sess: &Session) -> OsString {
     assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
-    if let Some(dlltool_path) = &sess.opts.unstable_opts.dlltool {
+    if let Some(dlltool_path) = &sess.opts.cg.dlltool {
         return dlltool_path.clone().into_os_string();
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index bae88d942934c..672087de31555 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -67,7 +67,8 @@ pub(crate) struct ErrorWritingDEFFile {
 
 #[derive(Diagnostic)]
 #[diag(codegen_llvm_error_calling_dlltool)]
-pub(crate) struct ErrorCallingDllTool {
+pub(crate) struct ErrorCallingDllTool<'a> {
+    pub dlltool_path: Cow<'a, str>,
     pub error: std::io::Error,
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 5cc87d1e56cca..8dae5dab42972 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -592,15 +592,6 @@ fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 
 fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
     use rustc_ast::{LitIntType, LitKind, MetaItemLit};
-    if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
-        feature_err(
-            &tcx.sess.parse_sess,
-            sym::raw_dylib,
-            attr.span,
-            "`#[link_ordinal]` is unstable on x86",
-        )
-        .emit();
-    }
     let meta_item_list = attr.meta_item_list();
     let meta_item_list = meta_item_list.as_deref();
     let sole_meta_list = match meta_item_list {
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 26d55618b490a..c3cc17c255b46 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -31,7 +31,7 @@ use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::ty::query::{ExternProviders, Providers};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
+use rustc_serialize::opaque::{FileEncoder, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
@@ -39,6 +39,7 @@ use rustc_session::utils::NativeLibKind;
 use rustc_span::symbol::Symbol;
 use rustc_span::DebuggerVisualizerFile;
 use std::collections::BTreeSet;
+use std::io;
 use std::path::{Path, PathBuf};
 
 pub mod back;
@@ -215,8 +216,11 @@ const RLINK_MAGIC: &[u8] = b"rustlink";
 const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
 impl CodegenResults {
-    pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
-        let mut encoder = MemEncoder::new();
+    pub fn serialize_rlink(
+        rlink_file: &Path,
+        codegen_results: &CodegenResults,
+    ) -> Result<usize, io::Error> {
+        let mut encoder = FileEncoder::new(rlink_file)?;
         encoder.emit_raw_bytes(RLINK_MAGIC);
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 70d608a5ea428..5b2e4d15dfebe 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -280,6 +280,8 @@ declare_features! (
     (accepted, pub_restricted, "1.18.0", Some(32409), None),
     /// Allows use of the postfix `?` operator in expressions.
     (accepted, question_mark, "1.13.0", Some(31436), None),
+    /// Allows the use of raw-dylibs (RFC 2627).
+    (accepted, raw_dylib, "CURRENT_RUSTC_VERSION", Some(58713), None),
     /// Allows keywords to be escaped for use as identifiers.
     (accepted, raw_identifiers, "1.30.0", Some(48589), None),
     /// Allows relaxing the coherence rules such that
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 6201e5b619b87..80bf67ab5f682 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -483,8 +483,6 @@ declare_features! (
     (active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (active, proc_macro_hygiene, "1.30.0", Some(54727), None),
-    /// Allows the use of raw-dylibs (RFC 2627).
-    (active, raw_dylib, "1.65.0", Some(58713), None),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
     (active, raw_ref_op, "1.41.0", Some(64490), None),
     /// Allows using the `#[register_tool]` attribute.
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 778ef06d57e20..9ef6593160831 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1426,6 +1426,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.check_repeat_element_needs_copy_bound(element, count, element_ty);
 
+        self.register_wf_obligation(
+            tcx.mk_array_with_const_len(t, count).into(),
+            expr.span,
+            traits::WellFormed(None),
+        );
+
         tcx.mk_array_with_const_len(t, count)
     }
 
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 77fbbf64a0ad2..6483d51a0b9a9 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -368,9 +368,8 @@ impl Linker {
         }
 
         if sess.opts.unstable_opts.no_link {
-            let encoded = CodegenResults::serialize_rlink(&codegen_results);
             let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
-            std::fs::write(&rlink_file, encoded)
+            CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
                 .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
             return Ok(());
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 7b0b5102c2db6..89eecba378b9a 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -547,6 +547,7 @@ fn test_codegen_options_tracking_hash() {
     untracked!(ar, String::from("abc"));
     untracked!(codegen_units, Some(42));
     untracked!(default_linker_libraries, true);
+    untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
     untracked!(extra_filename, String::from("extra-filename"));
     untracked!(incremental, Some(String::from("abc")));
     // `link_arg` is omitted because it just forwards to `link_args`.
@@ -651,7 +652,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(assert_incr_state, Some(String::from("loaded")));
     untracked!(deduplicate_diagnostics, false);
     untracked!(dep_tasks, true);
-    untracked!(dlltool, Some(PathBuf::from("custom_dlltool.exe")));
     untracked!(dont_buffer_diagnostics, true);
     untracked!(dump_dep_graph, true);
     untracked!(dump_drop_tracking_cfg, Some("cfg.dot".to_string()));
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index b43dcf3e5a183..c83c47e722bf0 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -161,14 +161,6 @@ impl<'tcx> Collector<'tcx> {
                             "raw-dylib" => {
                                 if !sess.target.is_like_windows {
                                     sess.emit_err(errors::FrameworkOnlyWindows { span });
-                                } else if !features.raw_dylib && sess.target.arch == "x86" {
-                                    feature_err(
-                                        &sess.parse_sess,
-                                        sym::raw_dylib,
-                                        span,
-                                        "link kind `raw-dylib` is unstable on x86",
-                                    )
-                                    .emit();
                                 }
                                 NativeLibKind::RawDylib
                             }
@@ -251,16 +243,6 @@ impl<'tcx> Collector<'tcx> {
                                 continue;
                             }
                         };
-                        if !features.raw_dylib {
-                            let span = item.name_value_literal_span().unwrap();
-                            feature_err(
-                                &sess.parse_sess,
-                                sym::raw_dylib,
-                                span,
-                                "import name type is unstable",
-                            )
-                            .emit();
-                        }
                         import_name_type = Some((link_import_name_type, item.span()));
                     }
                     _ => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f5ffdd27cae3f..32f9e883fd6bb 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -837,11 +837,12 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::Impl { .. }
         | DefKind::Closure
         | DefKind::Generator => true,
-        DefKind::ForeignMod | DefKind::ImplTraitPlaceholder | DefKind::GlobalAsm => false,
+        DefKind::ForeignMod | DefKind::GlobalAsm => false,
     }
 }
 
@@ -1364,9 +1365,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         record!(self.tables.params_in_repr[def_id] <- params_in_repr);
 
         if adt_def.is_enum() {
-            let module_children = tcx.module_children_non_reexports(local_def_id);
+            let module_children = tcx.module_children_local(local_def_id);
             record_array!(self.tables.module_children_non_reexports[def_id] <-
-                module_children.iter().map(|def_id| def_id.local_def_index));
+                module_children.iter().map(|child| child.res.def_id().index));
         } else {
             // For non-enum, there is only one variant, and its def_id is the adt's.
             debug_assert_eq!(adt_def.variants().len(), 1);
@@ -1412,12 +1413,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             // Encode this here because we don't do it in encode_def_ids.
             record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
         } else {
-            let non_reexports = tcx.module_children_non_reexports(local_def_id);
+            let module_children = tcx.module_children_local(local_def_id);
+
             record_array!(self.tables.module_children_non_reexports[def_id] <-
-                non_reexports.iter().map(|def_id| def_id.local_def_index));
+                module_children.iter().filter(|child| child.reexport_chain.is_empty())
+                    .map(|child| child.res.def_id().index));
 
             record_defaulted_array!(self.tables.module_children_reexports[def_id] <-
-                tcx.module_children_reexports(local_def_id));
+                module_children.iter().filter(|child| !child.reexport_chain.is_empty()));
         }
     }
 
@@ -1676,9 +1679,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             hir::ItemKind::Trait(..) => {
                 record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
 
-                let module_children = tcx.module_children_non_reexports(item.owner_id.def_id);
+                let module_children = tcx.module_children_local(item.owner_id.def_id);
                 record_array!(self.tables.module_children_non_reexports[def_id] <-
-                    module_children.iter().map(|def_id| def_id.local_def_index));
+                    module_children.iter().map(|child| child.res.def_id().index));
 
                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
                 record_associated_item_def_ids(self, associated_item_def_ids);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index dd02463e16a07..84f6b7f934dc3 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -357,10 +357,16 @@ define_tables! {
     associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
     opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
     unused_generic_params: Table<DefIndex, UnusedGenericParams>,
+    // Reexported names are not associated with individual `DefId`s,
+    // e.g. a glob import can introduce a lot of names, all with the same `DefId`.
+    // That's why the encoded list needs to contain `ModChild` structures describing all the names
+    // individually instead of `DefId`s.
     module_children_reexports: Table<DefIndex, LazyArray<ModChild>>,
 
 - optional:
     attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
+    // For non-reexported names in a module every name is associated with a separate `DefId`,
+    // so we can take their names, visibilities etc from other encoded tables.
     module_children_non_reexports: Table<DefIndex, LazyArray<DefIndex>>,
     associated_item_or_field_def_ids: Table<DefIndex, LazyArray<DefIndex>>,
     opt_def_kind: Table<DefIndex, DefKind>,
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 0a9fcd898b93e..8e379e0baacdb 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -192,6 +192,15 @@ macro_rules! make_mir_visitor {
                 self.super_constant(constant, location);
             }
 
+            #[allow(rustc::pass_by_value)]
+            fn visit_ty_const(
+                &mut self,
+                ct: & $($mutability)? ty::Const<'tcx>,
+                location: Location,
+            ) {
+                self.super_ty_const(ct, location);
+            }
+
             fn visit_span(
                 &mut self,
                 span: $(& $mutability)? Span,
@@ -625,8 +634,9 @@ macro_rules! make_mir_visitor {
                         self.visit_operand(operand, location);
                     }
 
-                    Rvalue::Repeat(value, _) => {
+                    Rvalue::Repeat(value, ct) => {
                         self.visit_operand(value, location);
+                        self.visit_ty_const(ct, location);
                     }
 
                     Rvalue::ThreadLocalRef(_) => {}
@@ -878,12 +888,21 @@ macro_rules! make_mir_visitor {
                 self.visit_span($(& $mutability)? *span);
                 drop(user_ty); // no visit method for this
                 match literal {
-                    ConstantKind::Ty(_) => {}
+                    ConstantKind::Ty(ct) => self.visit_ty_const(ct, location),
                     ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
                     ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
                 }
             }
 
+            #[allow(rustc::pass_by_value)]
+            fn super_ty_const(
+                &mut self,
+                _ct: & $($mutability)? ty::Const<'tcx>,
+                _location: Location,
+            ) {
+
+            }
+
             fn super_span(&mut self, _span: $(& $mutability)? Span) {
             }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index a309eaf048d2a..bf78b379986d8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2414,26 +2414,17 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    /// Named module children from all items except `use` and `extern crate` imports.
-    ///
-    /// In addition to regular items this list also includes struct or variant constructors, and
+    /// Named module children from all kinds of items, including imports.
+    /// In addition to regular items this list also includes struct and variant constructors, and
     /// items inside `extern {}` blocks because all of them introduce names into parent module.
-    /// For non-reexported children every such name is associated with a separate `DefId`.
     ///
     /// Module here is understood in name resolution sense - it can be a `mod` item,
     /// or a crate root, or an enum, or a trait.
-    pub fn module_children_non_reexports(self, def_id: LocalDefId) -> &'tcx [LocalDefId] {
-        self.resolutions(()).module_children_non_reexports.get(&def_id).map_or(&[], |v| &v[..])
-    }
-
-    /// Named module children from `use` and `extern crate` imports.
     ///
-    /// Reexported names are not associated with individual `DefId`s,
-    /// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
-    /// That's why the list needs to contain `ModChild` structures describing all the names
-    /// individually instead of `DefId`s.
-    pub fn module_children_reexports(self, def_id: LocalDefId) -> &'tcx [ModChild] {
-        self.resolutions(()).module_children_reexports.get(&def_id).map_or(&[], |v| &v[..])
+    /// This is not a query, making it a query causes perf regressions
+    /// (probably due to hashing spans in `ModChild`ren).
+    pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
+        self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index db6b35026a8e7..8986defacc7ba 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -165,8 +165,7 @@ pub struct ResolverGlobalCtxt {
     pub effective_visibilities: EffectiveVisibilities,
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
-    pub module_children_non_reexports: LocalDefIdMap<Vec<LocalDefId>>,
-    pub module_children_reexports: LocalDefIdMap<Vec<ModChild>>,
+    pub module_children: LocalDefIdMap<Vec<ModChild>>,
     pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
     pub main_def: Option<MainDefinition>,
     pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index c607c7fd5f4a7..7e60870fef0ff 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -515,9 +515,11 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
             self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
         }
-        for export in self.tcx.module_children_reexports(module_def_id) {
-            if export.vis.is_accessible_from(defining_mod, self.tcx)
-                && let Res::Def(def_kind, def_id) = export.res
+        for child in self.tcx.module_children_local(module_def_id) {
+            // FIXME: Use module children for the logic above too.
+            if !child.reexport_chain.is_empty()
+                && child.vis.is_accessible_from(defining_mod, self.tcx)
+                && let Res::Def(def_kind, def_id) = child.res
                 && let Some(def_id) = def_id.as_local() {
                 let vis = self.tcx.local_visibility(def_id);
                 self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod);
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 2044798f4d01d..9e4429507b1c8 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1261,14 +1261,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         *module.globs.borrow_mut() = Vec::new();
 
         if let Some(def_id) = module.opt_def_id() {
-            let mut non_reexports = Vec::new();
-            let mut reexports = Vec::new();
+            let mut children = Vec::new();
 
             module.for_each_child(self, |this, ident, _, binding| {
                 let res = binding.res().expect_non_local();
-                if !binding.is_import() {
-                    non_reexports.push(res.def_id().expect_local());
-                } else if res != def::Res::Err && !binding.is_ambiguity() {
+                if res != def::Res::Err && !binding.is_ambiguity() {
                     let mut reexport_chain = SmallVec::new();
                     let mut next_binding = binding;
                     while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
@@ -1276,17 +1273,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         next_binding = binding;
                     }
 
-                    reexports.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
+                    children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
                 }
             });
 
-            // Should be fine because this code is only called for local modules.
-            let def_id = def_id.expect_local();
-            if !non_reexports.is_empty() {
-                self.module_children_non_reexports.insert(def_id, non_reexports);
-            }
-            if !reexports.is_empty() {
-                self.module_children_reexports.insert(def_id, reexports);
+            if !children.is_empty() {
+                // Should be fine because this code is only called for local modules.
+                self.module_children.insert(def_id.expect_local(), children);
             }
         }
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 125f5ce761174..e46463579fe45 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -909,8 +909,7 @@ pub struct Resolver<'a, 'tcx> {
 
     /// `CrateNum` resolutions of `extern crate` items.
     extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-    module_children_non_reexports: LocalDefIdMap<Vec<LocalDefId>>,
-    module_children_reexports: LocalDefIdMap<Vec<ModChild>>,
+    module_children: LocalDefIdMap<Vec<ModChild>>,
     trait_map: NodeMap<Vec<TraitCandidate>>,
 
     /// A map from nodes to anonymous modules.
@@ -1260,8 +1259,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             lifetimes_res_map: Default::default(),
             extra_lifetime_params_map: Default::default(),
             extern_crate_map: Default::default(),
-            module_children_non_reexports: Default::default(),
-            module_children_reexports: Default::default(),
+            module_children: Default::default(),
             trait_map: NodeMap::default(),
             underscore_disambiguator: 0,
             empty_module,
@@ -1399,8 +1397,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             has_pub_restricted,
             effective_visibilities,
             extern_crate_map,
-            module_children_non_reexports: self.module_children_non_reexports,
-            module_children_reexports: self.module_children_reexports,
+            module_children: self.module_children,
             glob_map,
             maybe_unused_trait_imports,
             main_def,
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index e4dbb8a637cea..6046780685ad8 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -10,3 +10,4 @@ thin-vec = "0.2.12"
 
 [dev-dependencies]
 rustc_macros = { path = "../rustc_macros" }
+tempfile = "3.2"
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 0f6e4b329b87e..a2ec318df6d83 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -12,118 +12,14 @@ use std::ptr;
 // Encoder
 // -----------------------------------------------------------------------------
 
-pub struct MemEncoder {
-    pub data: Vec<u8>,
-}
-
-impl MemEncoder {
-    pub fn new() -> MemEncoder {
-        MemEncoder { data: vec![] }
-    }
-
-    #[inline]
-    pub fn position(&self) -> usize {
-        self.data.len()
-    }
-
-    pub fn finish(self) -> Vec<u8> {
-        self.data
-    }
-}
-
-macro_rules! write_leb128 {
-    ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
-        const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
-        let old_len = $enc.data.len();
-
-        if MAX_ENCODED_LEN > $enc.data.capacity() - old_len {
-            $enc.data.reserve(MAX_ENCODED_LEN);
-        }
-
-        // SAFETY: The above check and `reserve` ensures that there is enough
-        // room to write the encoded value to the vector's internal buffer.
-        unsafe {
-            let buf = &mut *($enc.data.as_mut_ptr().add(old_len)
-                as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]);
-            let encoded = leb128::$fun(buf, $value);
-            $enc.data.set_len(old_len + encoded.len());
-        }
-    }};
-}
-
-impl Encoder for MemEncoder {
-    #[inline]
-    fn emit_usize(&mut self, v: usize) {
-        write_leb128!(self, v, usize, write_usize_leb128)
-    }
-
-    #[inline]
-    fn emit_u128(&mut self, v: u128) {
-        write_leb128!(self, v, u128, write_u128_leb128);
-    }
-
-    #[inline]
-    fn emit_u64(&mut self, v: u64) {
-        write_leb128!(self, v, u64, write_u64_leb128);
-    }
-
-    #[inline]
-    fn emit_u32(&mut self, v: u32) {
-        write_leb128!(self, v, u32, write_u32_leb128);
-    }
-
-    #[inline]
-    fn emit_u16(&mut self, v: u16) {
-        self.data.extend_from_slice(&v.to_le_bytes());
-    }
-
-    #[inline]
-    fn emit_u8(&mut self, v: u8) {
-        self.data.push(v);
-    }
-
-    #[inline]
-    fn emit_isize(&mut self, v: isize) {
-        write_leb128!(self, v, isize, write_isize_leb128)
-    }
-
-    #[inline]
-    fn emit_i128(&mut self, v: i128) {
-        write_leb128!(self, v, i128, write_i128_leb128)
-    }
-
-    #[inline]
-    fn emit_i64(&mut self, v: i64) {
-        write_leb128!(self, v, i64, write_i64_leb128)
-    }
-
-    #[inline]
-    fn emit_i32(&mut self, v: i32) {
-        write_leb128!(self, v, i32, write_i32_leb128)
-    }
-
-    #[inline]
-    fn emit_i16(&mut self, v: i16) {
-        self.data.extend_from_slice(&v.to_le_bytes());
-    }
-
-    #[inline]
-    fn emit_raw_bytes(&mut self, s: &[u8]) {
-        self.data.extend_from_slice(s);
-    }
-}
-
 pub type FileEncodeResult = Result<usize, io::Error>;
 
 /// `FileEncoder` encodes data to file via fixed-size buffer.
 ///
-/// When encoding large amounts of data to a file, using `FileEncoder` may be
-/// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
-/// `Vec` to file, as the latter uses as much memory as there is encoded data,
-/// while the former uses the fixed amount of memory allocated to the buffer.
-/// `FileEncoder` also has the advantage of not needing to reallocate as data
-/// is appended to it, but the disadvantage of requiring more error handling,
-/// which has some runtime overhead.
+/// There used to be a `MemEncoder` type that encoded all the data into a
+/// `Vec`. `FileEncoder` is better because its memory use is determined by the
+/// size of the buffer, rather than the full length of the encoded data, and
+/// because it doesn't need to reallocate memory along the way.
 pub struct FileEncoder {
     /// The input buffer. For adequate performance, we need more control over
     /// buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
@@ -645,13 +541,6 @@ impl<'a> Decoder for MemDecoder<'a> {
 
 // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
 // since the default implementations call `encode` on their slices internally.
-impl Encodable<MemEncoder> for [u8] {
-    fn encode(&self, e: &mut MemEncoder) {
-        Encoder::emit_usize(e, self.len());
-        e.emit_raw_bytes(self);
-    }
-}
-
 impl Encodable<FileEncoder> for [u8] {
     fn encode(&self, e: &mut FileEncoder) {
         Encoder::emit_usize(e, self.len());
@@ -675,16 +564,6 @@ impl IntEncodedWithFixedSize {
     pub const ENCODED_SIZE: usize = 8;
 }
 
-impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
-    #[inline]
-    fn encode(&self, e: &mut MemEncoder) {
-        let _start_pos = e.position();
-        e.emit_raw_bytes(&self.0.to_le_bytes());
-        let _end_pos = e.position();
-        debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
-    }
-}
-
 impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
     #[inline]
     fn encode(&self, e: &mut FileEncoder) {
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index 5e7dd18aa8408..861091688bb2d 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -1,9 +1,10 @@
 #![allow(rustc::internal)]
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
+use rustc_serialize::opaque::{MemDecoder, FileEncoder};
 use rustc_serialize::{Decodable, Encodable};
 use std::fmt::Debug;
+use std::fs;
 
 #[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 struct Struct {
@@ -27,18 +28,21 @@ struct Struct {
 }
 
 fn check_round_trip<
-    T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
+    T: Encodable<FileEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
 >(
     values: Vec<T>,
 ) {
-    let mut encoder = MemEncoder::new();
+    let tmpfile = tempfile::NamedTempFile::new().unwrap();
+    let tmpfile = tmpfile.path();
+
+    let mut encoder = FileEncoder::new(&tmpfile).unwrap();
     for value in &values {
         Encodable::encode(value, &mut encoder);
     }
+    encoder.finish().unwrap();
 
-    let data = encoder.finish();
+    let data = fs::read(&tmpfile).unwrap();
     let mut decoder = MemDecoder::new(&data[..], 0);
-
     for value in values {
         let decoded = Decodable::decode(&mut decoder);
         assert_eq!(value, decoded);
@@ -61,7 +65,7 @@ fn test_u8() {
 
 #[test]
 fn test_u16() {
-    for i in u16::MIN..u16::MAX {
+    for i in [u16::MIN, 111, 3333, 55555, u16::MAX] {
         check_round_trip(vec![1, 2, 3, i, i, i]);
     }
 }
@@ -92,7 +96,7 @@ fn test_i8() {
 
 #[test]
 fn test_i16() {
-    for i in i16::MIN..i16::MAX {
+    for i in [i16::MIN, -100, 0, 101, i16::MAX] {
         check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
     }
 }
@@ -251,3 +255,41 @@ fn test_tuples() {
     check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]);
     check_round_trip(vec![(String::new(), "some string".to_string())]);
 }
+
+#[test]
+fn test_unit_like_struct() {
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct UnitLikeStruct;
+
+    check_round_trip(vec![UnitLikeStruct]);
+}
+
+#[test]
+fn test_box() {
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct A {
+        foo: Box<[bool]>,
+    }
+
+    let obj = A { foo: Box::new([true, false]) };
+    check_round_trip(vec![obj]);
+}
+
+#[test]
+fn test_cell() {
+    use std::cell::{Cell, RefCell};
+
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct A {
+        baz: isize,
+    }
+
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct B {
+        foo: Cell<bool>,
+        bar: RefCell<A>,
+    }
+
+    let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
+    check_round_trip(vec![obj]);
+}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 775fad1a365c2..2a04292e789ff 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1235,6 +1235,8 @@ options! {
         line-tables-only, limited, or full; default: 0)"),
     default_linker_libraries: bool = (false, parse_bool, [UNTRACKED],
         "allow the linker to link its default libraries (default: no)"),
+    dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
+        "import library generation tool (ignored except when targeting windows-gnu)"),
     embed_bitcode: bool = (true, parse_bool, [TRACKED],
         "emit bitcode in rlibs (default: yes)"),
     extra_filename: String = (String::new(), parse_string, [UNTRACKED],
@@ -1391,8 +1393,6 @@ options! {
         (default: no)"),
     diagnostic_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
         "set the current output width for diagnostic truncation"),
-    dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
-        "import library generation tool (windows-gnu only)"),
     dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
         "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) \
         (default: no)"),
diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs
index 951d509ec9533..77f645883102c 100644
--- a/library/std/src/sys/common/thread_local/mod.rs
+++ b/library/std/src/sys/common/thread_local/mod.rs
@@ -1,5 +1,10 @@
 #![unstable(feature = "thread_local_internals", reason = "should not be necessary", issue = "none")]
 
+// There are three thread-local implementations: "static", "fast", "OS".
+// The "OS" thread local key type is accessed via platform-specific API calls and is slow, while the
+// "fast" key type is accessed via code generated via LLVM, where TLS keys are set up by the linker.
+// "static" is for single-threaded platforms where a global static is sufficient.
+
 cfg_if::cfg_if! {
     if #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] {
         #[doc(hidden)]
diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs
index d004897df281a..5d48ce1e03bc3 100644
--- a/library/std/src/sys/common/thread_local/os_local.rs
+++ b/library/std/src/sys/common/thread_local/os_local.rs
@@ -18,7 +18,7 @@ pub macro thread_local_inner {
         ) -> $crate::option::Option<&'static $t> {
             const INIT_EXPR: $t = $init;
 
-                        // On platforms without `#[thread_local]` we fall back to the
+            // On platforms without `#[thread_local]` we fall back to the
             // same implementation as below for os thread locals.
             #[inline]
             const fn __init() -> $t { INIT_EXPR }
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 9cdc17a287c96..f712c872708ac 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -193,22 +193,22 @@ pub use scoped::{scope, Scope, ScopedJoinHandle};
 #[macro_use]
 mod local;
 
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::local::{AccessError, LocalKey};
-
-// Provide the type used by the thread_local! macro to access TLS keys. This
-// needs to be kept in sync with the macro itself (in `local.rs`).
-// There are three types: "static", "fast", "OS". The "OS" thread local key
-// type is accessed via platform-specific API calls and is slow, while the "fast"
-// key type is accessed via code generated via LLVM, where TLS keys are set up
-// by the elf linker. "static" is for single-threaded platforms where a global
-// static is sufficient.
-
-// Implementation details used by the thread_local!{} macro.
-#[doc(hidden)]
-#[unstable(feature = "thread_local_internals", issue = "none")]
-pub mod local_impl {
-    pub use crate::sys::common::thread_local::{thread_local_inner, Key};
+cfg_if::cfg_if! {
+    if #[cfg(test)] {
+        // Avoid duplicating the global state assoicated with thread-locals between this crate and
+        // realstd. Miri relies on this.
+        pub use realstd::thread::{local_impl, AccessError, LocalKey};
+    } else {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub use self::local::{AccessError, LocalKey};
+
+        // Implementation details used by the thread_local!{} macro.
+        #[doc(hidden)]
+        #[unstable(feature = "thread_local_internals", issue = "none")]
+        pub mod local_impl {
+            pub use crate::sys::common::thread_local::{thread_local_inner, Key};
+        }
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index c1cf9b93fb356..3e82a381a1b2d 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -427,7 +427,6 @@ impl Config {
 
     fn download_toolchain(
         &self,
-        // FIXME(ozkanonur) use CompilerMetadata instead of `version: &str`
         version: &str,
         sysroot: &str,
         stamp_key: &str,
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index d7c6a884fc8fb..b7fa7243cc1c0 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -90,6 +90,14 @@ It takes one of the following values:
 For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
 the linker.
 
+## dlltool
+
+On `windows-gnu` targets, this flag controls which dlltool `rustc` invokes to
+generate import libraries when using the [`raw-dylib` link kind](../../reference/items/external-blocks.md#the-link-attribute).
+It takes a path to [the dlltool executable](https://sourceware.org/binutils/docs/binutils/dlltool.html).
+If this flag is not specified, a dlltool executable will be inferred based on
+the host environment and target.
+
 ## embed-bitcode
 
 This flag controls whether or not the compiler embeds LLVM bitcode into object
diff --git a/src/doc/unstable-book/src/language-features/raw-dylib.md b/src/doc/unstable-book/src/language-features/raw-dylib.md
deleted file mode 100644
index 5fd208ae7571c..0000000000000
--- a/src/doc/unstable-book/src/language-features/raw-dylib.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# `raw_dylib`
-
-The tracking issue for this feature is: [#58713]
-
-[#58713]: https://github.com/rust-lang/rust/issues/58713
-
-------------------------
-
-The `raw_dylib` feature allows you to link against the implementations of functions in an `extern`
-block without, on Windows, linking against an import library.
-
-```rust,ignore (partial-example)
-#![feature(raw_dylib)]
-
-#[link(name="library", kind="raw-dylib")]
-extern {
-    fn extern_function(x: i32);
-}
-
-fn main() {
-    unsafe {
-        extern_function(14);
-    }
-}
-```
-
-## Limitations
-
-This feature is unstable for the `x86` architecture, and stable for all other architectures.
-
-This feature is only supported on Windows.
-
-On the `x86` architecture, this feature supports only the `cdecl`, `stdcall`, `system`, `fastcall`, and
-`vectorcall` calling conventions.
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3f6a5d6d9017a..951f54e93663c 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -152,8 +152,9 @@ pub(crate) fn try_inline_glob(
             // reexported by the glob, e.g. because they are shadowed by something else.
             let reexports = cx
                 .tcx
-                .module_children_reexports(current_mod)
+                .module_children_local(current_mod)
                 .iter()
+                .filter(|child| !child.reexport_chain.is_empty())
                 .filter_map(|child| child.res.opt_def_id())
                 .collect();
             let mut items = build_module_items(cx, did, visited, inlined_names, Some(&reexports));
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1531e7fc7b91d..f9a46e33f9a8c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2089,9 +2089,9 @@ pub(crate) fn reexport_chain<'tcx>(
     import_def_id: LocalDefId,
     target_def_id: LocalDefId,
 ) -> &'tcx [Reexport] {
-    for child in tcx.module_children_reexports(tcx.local_parent(import_def_id)) {
+    for child in tcx.module_children_local(tcx.local_parent(import_def_id)) {
         if child.res.opt_def_id() == Some(target_def_id.to_def_id())
-            && child.reexport_chain[0].id() == Some(import_def_id.to_def_id())
+            && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id())
         {
             return &child.reexport_chain;
         }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 6fbb4508662c7..a7d5f497756b5 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1259,6 +1259,10 @@ a.tooltip:hover::after {
 	background-color: var(--search-error-code-background-color);
 }
 
+.search-corrections {
+	font-weight: normal;
+}
+
 #src-sidebar-toggle {
 	position: sticky;
 	top: 0;
diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js
index 4c81a0979c1a7..8b931f74e600a 100644
--- a/src/librustdoc/html/static/js/externs.js
+++ b/src/librustdoc/html/static/js/externs.js
@@ -9,6 +9,7 @@ function initSearch(searchIndex){}
 /**
  * @typedef {{
  *     name: string,
+ *     id: integer,
  *     fullPath: Array<string>,
  *     pathWithoutLast: Array<string>,
  *     pathLast: string,
@@ -36,6 +37,8 @@ let ParserState;
  *     args: Array<QueryElement>,
  *     returned: Array<QueryElement>,
  *     foundElems: number,
+ *     literalSearch: boolean,
+ *     corrections: Array<{from: string, to: integer}>,
  * }}
  */
 let ParsedQuery;
@@ -139,7 +142,7 @@ let FunctionSearchType;
 
 /**
  * @typedef {{
- *     name: (null|string),
+ *     id: (null|number),
  *     ty: (null|number),
  *     generics: Array<FunctionType>,
  * }}
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 3dc4f2149b8b9..62afe40bb3155 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -58,6 +58,7 @@ function printTab(nb) {
         }
         iter += 1;
     });
+    const isTypeSearch = (nb > 0 || iter === 1);
     iter = 0;
     onEachLazy(document.getElementById("results").childNodes, elem => {
         if (nb === iter) {
@@ -70,6 +71,13 @@ function printTab(nb) {
     });
     if (foundCurrentTab && foundCurrentResultSet) {
         searchState.currentTab = nb;
+        // Corrections only kick in on type-based searches.
+        const correctionsElem = document.getElementsByClassName("search-corrections");
+        if (isTypeSearch) {
+            removeClass(correctionsElem[0], "hidden");
+        } else {
+            addClass(correctionsElem[0], "hidden");
+        }
     } else if (nb !== 0) {
         printTab(0);
     }
@@ -191,6 +199,13 @@ function initSearch(rawSearchIndex) {
      */
     let searchIndex;
     let currentResults;
+    /**
+     * Map from normalized type names to integers. Used to make type search
+     * more efficient.
+     *
+     * @type {Map<string, integer>}
+     */
+    let typeNameIdMap;
     const ALIASES = new Map();
 
     function isWhitespace(c) {
@@ -358,6 +373,7 @@ function initSearch(rawSearchIndex) {
         parserState.typeFilter = null;
         return {
             name: name,
+            id: -1,
             fullPath: pathSegments,
             pathWithoutLast: pathSegments.slice(0, pathSegments.length - 1),
             pathLast: pathSegments[pathSegments.length - 1],
@@ -718,6 +734,7 @@ function initSearch(rawSearchIndex) {
             foundElems: 0,
             literalSearch: false,
             error: null,
+            correction: null,
         };
     }
 
@@ -873,7 +890,7 @@ function initSearch(rawSearchIndex) {
      *
      * @param {Array<Result>} results_in_args
      * @param {Array<Result>} results_returned
-     * @param {Array<Result>} results_in_args
+     * @param {Array<Result>} results_others
      * @param {ParsedQuery} parsedQuery
      *
      * @return {ResultsTable}
@@ -1091,48 +1108,50 @@ function initSearch(rawSearchIndex) {
          *
          * @param {Row} row                 - The object to check.
          * @param {QueryElement} elem       - The element from the parsed query.
-         * @param {integer} defaultDistance - This is the value to return in case there are no
-         *                                    generics.
          *
-         * @return {integer}           - Returns the best match (if any) or `maxEditDistance + 1`.
+         * @return {boolean}           - Returns true if a match, false otherwise.
          */
-        function checkGenerics(row, elem, defaultDistance, maxEditDistance) {
-            if (row.generics.length === 0) {
-                return elem.generics.length === 0 ? defaultDistance : maxEditDistance + 1;
-            } else if (row.generics.length > 0 && row.generics[0].name === null) {
-                return checkGenerics(row.generics[0], elem, defaultDistance, maxEditDistance);
-            }
-            // The names match, but we need to be sure that all generics kinda
-            // match as well.
+        function checkGenerics(row, elem) {
+            if (row.generics.length === 0 || elem.generics.length === 0) {
+                return false;
+            }
+            // This function is called if the names match, but we need to make
+            // sure that all generics match as well.
+            //
+            // This search engine implements order-agnostic unification. There
+            // should be no missing duplicates (generics have "bag semantics"),
+            // and the row is allowed to have extras.
             if (elem.generics.length > 0 && row.generics.length >= elem.generics.length) {
                 const elems = new Map();
-                for (const entry of row.generics) {
-                    if (entry.name === "") {
+                const addEntryToElems = function addEntryToElems(entry) {
+                    if (entry.id === -1) {
                         // Pure generic, needs to check into it.
-                        if (checkGenerics(entry, elem, maxEditDistance + 1, maxEditDistance)
-                            !== 0) {
-                            return maxEditDistance + 1;
+                        for (const inner_entry of entry.generics) {
+                            addEntryToElems(inner_entry);
                         }
-                        continue;
+                        return;
                     }
                     let currentEntryElems;
-                    if (elems.has(entry.name)) {
-                        currentEntryElems = elems.get(entry.name);
+                    if (elems.has(entry.id)) {
+                        currentEntryElems = elems.get(entry.id);
                     } else {
                         currentEntryElems = [];
-                        elems.set(entry.name, currentEntryElems);
+                        elems.set(entry.id, currentEntryElems);
                     }
                     currentEntryElems.push(entry);
+                };
+                for (const entry of row.generics) {
+                    addEntryToElems(entry);
                 }
                 // We need to find the type that matches the most to remove it in order
                 // to move forward.
                 const handleGeneric = generic => {
-                    if (!elems.has(generic.name)) {
+                    if (!elems.has(generic.id)) {
                         return false;
                     }
-                    const matchElems = elems.get(generic.name);
+                    const matchElems = elems.get(generic.id);
                     const matchIdx = matchElems.findIndex(tmp_elem => {
-                        if (checkGenerics(tmp_elem, generic, 0, maxEditDistance) !== 0) {
+                        if (generic.generics.length > 0 && !checkGenerics(tmp_elem, generic)) {
                             return false;
                         }
                         return typePassesFilter(generic.typeFilter, tmp_elem.ty);
@@ -1142,7 +1161,7 @@ function initSearch(rawSearchIndex) {
                     }
                     matchElems.splice(matchIdx, 1);
                     if (matchElems.length === 0) {
-                        elems.delete(generic.name);
+                        elems.delete(generic.id);
                     }
                     return true;
                 };
@@ -1152,17 +1171,17 @@ function initSearch(rawSearchIndex) {
                 // own type.
                 for (const generic of elem.generics) {
                     if (generic.typeFilter !== -1 && !handleGeneric(generic)) {
-                        return maxEditDistance + 1;
+                        return false;
                     }
                 }
                 for (const generic of elem.generics) {
                     if (generic.typeFilter === -1 && !handleGeneric(generic)) {
-                        return maxEditDistance + 1;
+                        return false;
                     }
                 }
-                return 0;
+                return true;
             }
-            return maxEditDistance + 1;
+            return false;
         }
 
         /**
@@ -1172,17 +1191,15 @@ function initSearch(rawSearchIndex) {
           * @param {Row} row
           * @param {QueryElement} elem    - The element from the parsed query.
           *
-          * @return {integer} - Returns an edit distance to the best match.
+          * @return {boolean} - Returns true if found, false otherwise.
           */
-        function checkIfInGenerics(row, elem, maxEditDistance) {
-            let dist = maxEditDistance + 1;
+        function checkIfInGenerics(row, elem) {
             for (const entry of row.generics) {
-                dist = Math.min(checkType(entry, elem, true, maxEditDistance), dist);
-                if (dist === 0) {
-                    break;
+                if (checkType(entry, elem)) {
+                    return true;
                 }
             }
-            return dist;
+            return false;
         }
 
         /**
@@ -1191,75 +1208,26 @@ function initSearch(rawSearchIndex) {
           *
           * @param {Row} row
           * @param {QueryElement} elem      - The element from the parsed query.
-          * @param {boolean} literalSearch
           *
-          * @return {integer} - Returns an edit distance to the best match. If there is
-          *                     no match, returns `maxEditDistance + 1`.
+          * @return {boolean} - Returns true if the type matches, false otherwise.
           */
-        function checkType(row, elem, literalSearch, maxEditDistance) {
-            if (row.name === null) {
+        function checkType(row, elem) {
+            if (row.id === -1) {
                 // This is a pure "generic" search, no need to run other checks.
-                if (row.generics.length > 0) {
-                    return checkIfInGenerics(row, elem, maxEditDistance);
-                }
-                return maxEditDistance + 1;
+                return row.generics.length > 0 ? checkIfInGenerics(row, elem) : false;
             }
 
-            let dist;
-            if (typePassesFilter(elem.typeFilter, row.ty)) {
-                dist = editDistance(row.name, elem.name, maxEditDistance);
-            } else {
-                dist = maxEditDistance + 1;
-            }
-            if (literalSearch) {
-                if (dist !== 0) {
-                    // The name didn't match, let's try to check if the generics do.
-                    if (elem.generics.length === 0) {
-                        const checkGeneric = row.generics.length > 0;
-                        if (checkGeneric && row.generics
-                            .findIndex(tmp_elem => tmp_elem.name === elem.name &&
-                                typePassesFilter(elem.typeFilter, tmp_elem.ty)) !== -1) {
-                            return 0;
-                        }
-                    }
-                    return maxEditDistance + 1;
-                } else if (elem.generics.length > 0) {
-                    return checkGenerics(row, elem, maxEditDistance + 1, maxEditDistance);
-                }
-                return 0;
-            } else if (row.generics.length > 0) {
-                if (elem.generics.length === 0) {
-                    if (dist === 0) {
-                        return 0;
-                    }
-                    // The name didn't match so we now check if the type we're looking for is inside
-                    // the generics!
-                    dist = Math.min(dist, checkIfInGenerics(row, elem, maxEditDistance));
-                    return dist;
-                } else if (dist > maxEditDistance) {
-                    // So our item's name doesn't match at all and has generics.
-                    //
-                    // Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
-                    // looking for "B<C>", we'll need to go down.
-                    return checkIfInGenerics(row, elem, maxEditDistance);
-                } else {
-                    // At this point, the name kinda match and we have generics to check, so
-                    // let's go!
-                    const tmp_dist = checkGenerics(row, elem, dist, maxEditDistance);
-                    if (tmp_dist > maxEditDistance) {
-                        return maxEditDistance + 1;
-                    }
-                    // We compute the median value of both checks and return it.
-                    return (tmp_dist + dist) / 2;
+            if (row.id === elem.id && typePassesFilter(elem.typeFilter, row.ty)) {
+                if (elem.generics.length > 0) {
+                    return checkGenerics(row, elem);
                 }
-            } else if (elem.generics.length > 0) {
-                // In this case, we were expecting generics but there isn't so we simply reject this
-                // one.
-                return maxEditDistance + 1;
+                return true;
             }
-            // No generics on our query or on the target type so we can return without doing
-            // anything else.
-            return dist;
+
+            // If the current item does not match, try [unboxing] the generic.
+            // [unboxing]:
+            //   https://ndmitchell.com/downloads/slides-hoogle_fast_type_searching-09_aug_2008.pdf
+            return checkIfInGenerics(row, elem);
         }
 
         /**
@@ -1267,17 +1235,11 @@ function initSearch(rawSearchIndex) {
          *
          * @param {Row} row
          * @param {QueryElement} elem    - The element from the parsed query.
-         * @param {integer} maxEditDistance
          * @param {Array<integer>} skipPositions - Do not return one of these positions.
          *
-         * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
-         *                                              If there is no match, returns
-         *                                              `maxEditDistance + 1` and position: -1.
+         * @return {integer} - Returns the position of the match, or -1 if none.
          */
-        function findArg(row, elem, maxEditDistance, skipPositions) {
-            let dist = maxEditDistance + 1;
-            let position = -1;
-
+        function findArg(row, elem, skipPositions) {
             if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
                 let i = 0;
                 for (const input of row.type.inputs) {
@@ -1285,24 +1247,13 @@ function initSearch(rawSearchIndex) {
                         i += 1;
                         continue;
                     }
-                    const typeDist = checkType(
-                        input,
-                        elem,
-                        parsedQuery.literalSearch,
-                        maxEditDistance
-                    );
-                    if (typeDist === 0) {
-                        return {dist: 0, position: i};
-                    }
-                    if (typeDist < dist) {
-                        dist = typeDist;
-                        position = i;
+                    if (checkType(input, elem)) {
+                        return i;
                     }
                     i += 1;
                 }
             }
-            dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
-            return {dist, position};
+            return -1;
         }
 
         /**
@@ -1310,43 +1261,25 @@ function initSearch(rawSearchIndex) {
          *
          * @param {Row} row
          * @param {QueryElement} elem   - The element from the parsed query.
-         * @param {integer} maxEditDistance
          * @param {Array<integer>} skipPositions - Do not return one of these positions.
          *
-         * @return {dist: integer, position: integer} - Returns an edit distance to the best match.
-         *                                              If there is no match, returns
-         *                                              `maxEditDistance + 1` and position: -1.
+         * @return {integer} - Returns the position of the matching item, or -1 if none.
          */
-        function checkReturned(row, elem, maxEditDistance, skipPositions) {
-            let dist = maxEditDistance + 1;
-            let position = -1;
-
+        function checkReturned(row, elem, skipPositions) {
             if (row && row.type && row.type.output.length > 0) {
-                const ret = row.type.output;
                 let i = 0;
-                for (const ret_ty of ret) {
+                for (const ret_ty of row.type.output) {
                     if (skipPositions.indexOf(i) !== -1) {
                         i += 1;
                         continue;
                     }
-                    const typeDist = checkType(
-                        ret_ty,
-                        elem,
-                        parsedQuery.literalSearch,
-                        maxEditDistance
-                    );
-                    if (typeDist === 0) {
-                        return {dist: 0, position: i};
-                    }
-                    if (typeDist < dist) {
-                        dist = typeDist;
-                        position = i;
+                    if (checkType(ret_ty, elem)) {
+                        return i;
                     }
                     i += 1;
                 }
             }
-            dist = parsedQuery.literalSearch ? maxEditDistance + 1 : dist;
-            return {dist, position};
+            return -1;
         }
 
         function checkPath(contains, ty, maxEditDistance) {
@@ -1543,17 +1476,20 @@ function initSearch(rawSearchIndex) {
             if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
                 return;
             }
-            let dist, index = -1, path_dist = 0;
+            let index = -1, path_dist = 0;
             const fullId = row.id;
             const searchWord = searchWords[pos];
 
-            const in_args = findArg(row, elem, maxEditDistance, []);
-            const returned = checkReturned(row, elem, maxEditDistance, []);
-
-            // path_dist is 0 because no parent path information is currently stored
-            // in the search index
-            addIntoResults(results_in_args, fullId, pos, -1, in_args.dist, 0, maxEditDistance);
-            addIntoResults(results_returned, fullId, pos, -1, returned.dist, 0, maxEditDistance);
+            const in_args = findArg(row, elem, []);
+            if (in_args !== -1) {
+                // path_dist is 0 because no parent path information is currently stored
+                // in the search index
+                addIntoResults(results_in_args, fullId, pos, -1, 0, 0, maxEditDistance);
+            }
+            const returned = checkReturned(row, elem, []);
+            if (returned !== -1) {
+                addIntoResults(results_returned, fullId, pos, -1, 0, 0, maxEditDistance);
+            }
 
             if (!typePassesFilter(elem.typeFilter, row.ty)) {
                 return;
@@ -1574,16 +1510,6 @@ function initSearch(rawSearchIndex) {
                 index = row_index;
             }
 
-            // No need to check anything else if it's a "pure" generics search.
-            if (elem.name.length === 0) {
-                if (row.type !== null) {
-                    dist = checkGenerics(row.type, elem, maxEditDistance + 1, maxEditDistance);
-                    // path_dist is 0 because we know it's empty
-                    addIntoResults(results_others, fullId, pos, index, dist, 0, maxEditDistance);
-                }
-                return;
-            }
-
             if (elem.fullPath.length > 1) {
                 path_dist = checkPath(elem.pathWithoutLast, row, maxEditDistance);
                 if (path_dist > maxEditDistance) {
@@ -1598,7 +1524,7 @@ function initSearch(rawSearchIndex) {
                 return;
             }
 
-            dist = editDistance(searchWord, elem.pathLast, maxEditDistance);
+            const dist = editDistance(searchWord, elem.pathLast, maxEditDistance);
 
             if (index === -1 && dist + path_dist > maxEditDistance) {
                 return;
@@ -1616,28 +1542,22 @@ function initSearch(rawSearchIndex) {
          * @param {integer} pos      - Position in the `searchIndex`.
          * @param {Object} results
          */
-        function handleArgs(row, pos, results, maxEditDistance) {
+        function handleArgs(row, pos, results) {
             if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
                 return;
             }
 
-            let totalDist = 0;
-            let nbDist = 0;
-
             // If the result is too "bad", we return false and it ends this search.
             function checkArgs(elems, callback) {
                 const skipPositions = [];
                 for (const elem of elems) {
                     // There is more than one parameter to the query so all checks should be "exact"
-                    const { dist, position } = callback(
+                    const position = callback(
                         row,
                         elem,
-                        maxEditDistance,
                         skipPositions
                     );
-                    if (dist <= 1) {
-                        nbDist += 1;
-                        totalDist += dist;
+                    if (position !== -1) {
                         skipPositions.push(position);
                     } else {
                         return false;
@@ -1652,11 +1572,7 @@ function initSearch(rawSearchIndex) {
                 return;
             }
 
-            if (nbDist === 0) {
-                return;
-            }
-            const dist = Math.round(totalDist / nbDist);
-            addIntoResults(results, row.id, pos, 0, dist, 0, maxEditDistance);
+            addIntoResults(results, row.id, pos, 0, 0, 0, Number.MAX_VALUE);
         }
 
         function innerRunQuery() {
@@ -1671,6 +1587,53 @@ function initSearch(rawSearchIndex) {
             }
             const maxEditDistance = Math.floor(queryLen / 3);
 
+            /**
+             * Convert names to ids in parsed query elements.
+             * This is not used for the "In Names" tab, but is used for the
+             * "In Params", "In Returns", and "In Function Signature" tabs.
+             *
+             * If there is no matching item, but a close-enough match, this
+             * function also that correction.
+             *
+             * See `buildTypeMapIndex` for more information.
+             *
+             * @param {QueryElement} elem
+             */
+            function convertNameToId(elem) {
+                if (typeNameIdMap.has(elem.name)) {
+                    elem.id = typeNameIdMap.get(elem.name);
+                } else if (!parsedQuery.literalSearch) {
+                    let match = -1;
+                    let matchDist = maxEditDistance + 1;
+                    let matchName = "";
+                    for (const [name, id] of typeNameIdMap) {
+                        const dist = editDistance(name, elem.name, maxEditDistance);
+                        if (dist <= matchDist && dist <= maxEditDistance) {
+                            if (dist === matchDist && matchName > name) {
+                                continue;
+                            }
+                            match = id;
+                            matchDist = dist;
+                            matchName = name;
+                        }
+                    }
+                    if (match !== -1) {
+                        parsedQuery.correction = matchName;
+                    }
+                    elem.id = match;
+                }
+                for (const elem2 of elem.generics) {
+                    convertNameToId(elem2);
+                }
+            }
+
+            for (const elem of parsedQuery.elems) {
+                convertNameToId(elem);
+            }
+            for (const elem of parsedQuery.returned) {
+                convertNameToId(elem);
+            }
+
             if (parsedQuery.foundElems === 1) {
                 if (parsedQuery.elems.length === 1) {
                     elem = parsedQuery.elems[0];
@@ -1695,22 +1658,23 @@ function initSearch(rawSearchIndex) {
                         in_returned = checkReturned(
                             row,
                             elem,
-                            maxEditDistance,
                             []
                         );
-                        addIntoResults(
-                            results_others,
-                            row.id,
-                            i,
-                            -1,
-                            in_returned.dist,
-                            maxEditDistance
-                        );
+                        if (in_returned !== -1) {
+                            addIntoResults(
+                                results_others,
+                                row.id,
+                                i,
+                                -1,
+                                0,
+                                Number.MAX_VALUE
+                            );
+                        }
                     }
                 }
             } else if (parsedQuery.foundElems > 0) {
                 for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
-                    handleArgs(searchIndex[i], i, results_others, maxEditDistance);
+                    handleArgs(searchIndex[i], i, results_others);
                 }
             }
         }
@@ -2030,6 +1994,16 @@ function initSearch(rawSearchIndex) {
             currentTab = 0;
         }
 
+        if (results.query.correction !== null) {
+            const orig = results.query.returned.length > 0
+                ? results.query.returned[0].name
+                : results.query.elems[0].name;
+            output += "<h3 class=\"search-corrections\">" +
+                `Type "${orig}" not found. ` +
+                "Showing results for closest type name " +
+                `"${results.query.correction}" instead.</h3>`;
+        }
+
         const resultsElem = document.createElement("div");
         resultsElem.id = "results";
         resultsElem.appendChild(ret_others[0]);
@@ -2108,6 +2082,34 @@ function initSearch(rawSearchIndex) {
             filterCrates);
     }
 
+    /**
+     * Add an item to the type Name->ID map, or, if one already exists, use it.
+     * Returns the number. If name is "" or null, return -1 (pure generic).
+     *
+     * This is effectively string interning, so that function matching can be
+     * done more quickly. Two types with the same name but different item kinds
+     * get the same ID.
+     *
+     * @param {Map<string, integer>} typeNameIdMap
+     * @param {string} name
+     *
+     * @returns {integer}
+     */
+    function buildTypeMapIndex(typeNameIdMap, name) {
+
+        if (name === "" || name === null) {
+            return -1;
+        }
+
+        if (typeNameIdMap.has(name)) {
+            return typeNameIdMap.get(name);
+        } else {
+            const id = typeNameIdMap.size;
+            typeNameIdMap.set(name, id);
+            return id;
+        }
+    }
+
     /**
      * Convert a list of RawFunctionType / ID to object-based FunctionType.
      *
@@ -2126,7 +2128,7 @@ function initSearch(rawSearchIndex) {
      *
      * @return {Array<FunctionSearchType>}
      */
-    function buildItemSearchTypeAll(types, lowercasePaths) {
+    function buildItemSearchTypeAll(types, lowercasePaths, typeNameIdMap) {
         const PATH_INDEX_DATA = 0;
         const GENERICS_DATA = 1;
         return types.map(type => {
@@ -2136,11 +2138,17 @@ function initSearch(rawSearchIndex) {
                 generics = [];
             } else {
                 pathIndex = type[PATH_INDEX_DATA];
-                generics = buildItemSearchTypeAll(type[GENERICS_DATA], lowercasePaths);
+                generics = buildItemSearchTypeAll(
+                    type[GENERICS_DATA],
+                    lowercasePaths,
+                    typeNameIdMap
+                );
             }
             return {
                 // `0` is used as a sentinel because it's fewer bytes than `null`
-                name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+                id: pathIndex === 0
+                    ? -1
+                    : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
                 ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
                 generics: generics,
             };
@@ -2159,10 +2167,11 @@ function initSearch(rawSearchIndex) {
      *
      * @param {RawFunctionSearchType} functionSearchType
      * @param {Array<{name: string, ty: number}>} lowercasePaths
+     * @param {Map<string, integer>}
      *
      * @return {null|FunctionSearchType}
      */
-    function buildFunctionSearchType(functionSearchType, lowercasePaths) {
+    function buildFunctionSearchType(functionSearchType, lowercasePaths, typeNameIdMap) {
         const INPUTS_DATA = 0;
         const OUTPUT_DATA = 1;
         // `0` is used as a sentinel because it's fewer bytes than `null`
@@ -2173,23 +2182,35 @@ function initSearch(rawSearchIndex) {
         if (typeof functionSearchType[INPUTS_DATA] === "number") {
             const pathIndex = functionSearchType[INPUTS_DATA];
             inputs = [{
-                name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+                id: pathIndex === 0
+                    ? -1
+                    : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
                 ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
                 generics: [],
             }];
         } else {
-            inputs = buildItemSearchTypeAll(functionSearchType[INPUTS_DATA], lowercasePaths);
+            inputs = buildItemSearchTypeAll(
+                functionSearchType[INPUTS_DATA],
+                lowercasePaths,
+                typeNameIdMap
+            );
         }
         if (functionSearchType.length > 1) {
             if (typeof functionSearchType[OUTPUT_DATA] === "number") {
                 const pathIndex = functionSearchType[OUTPUT_DATA];
                 output = [{
-                    name: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].name,
+                    id: pathIndex === 0
+                        ? -1
+                        : buildTypeMapIndex(typeNameIdMap, lowercasePaths[pathIndex - 1].name),
                     ty: pathIndex === 0 ? null : lowercasePaths[pathIndex - 1].ty,
                     generics: [],
                 }];
             } else {
-                output = buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA], lowercasePaths);
+                output = buildItemSearchTypeAll(
+                    functionSearchType[OUTPUT_DATA],
+                    lowercasePaths,
+                    typeNameIdMap
+                );
             }
         } else {
             output = [];
@@ -2202,9 +2223,12 @@ function initSearch(rawSearchIndex) {
     function buildIndex(rawSearchIndex) {
         searchIndex = [];
         /**
+         * List of normalized search words (ASCII lowercased, and undescores removed).
+         *
          * @type {Array<string>}
          */
         const searchWords = [];
+        typeNameIdMap = new Map();
         const charA = "A".charCodeAt(0);
         let currentIndex = 0;
         let id = 0;
@@ -2337,7 +2361,11 @@ function initSearch(rawSearchIndex) {
                     path: itemPaths.has(i) ? itemPaths.get(i) : lastPath,
                     desc: itemDescs[i],
                     parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
-                    type: buildFunctionSearchType(itemFunctionSearchTypes[i], lowercasePaths),
+                    type: buildFunctionSearchType(
+                        itemFunctionSearchTypes[i],
+                        lowercasePaths,
+                        typeNameIdMap
+                    ),
                     id: id,
                     normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
                     deprecated: deprecatedItems.has(i),
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index a6089680fae9d..841c7a78b2d4f 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -136,14 +136,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         // is declared but also a reexport of itself producing two exports of the same
         // macro in the same module.
         let mut inserted = FxHashSet::default();
-        for export in self.cx.tcx.module_children_reexports(CRATE_DEF_ID) {
-            if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+        for child in self.cx.tcx.module_children_local(CRATE_DEF_ID) {
+            if !child.reexport_chain.is_empty() &&
+                let Res::Def(DefKind::Macro(_), def_id) = child.res &&
                 let Some(local_def_id) = def_id.as_local() &&
                 self.cx.tcx.has_attr(def_id, sym::macro_export) &&
                 inserted.insert(def_id)
             {
-                    let item = self.cx.tcx.hir().expect_item(local_def_id);
-                    top_level_module.items.insert((local_def_id, Some(item.ident.name)), (item, None, None));
+                let item = self.cx.tcx.hir().expect_item(local_def_id);
+                top_level_module.items.insert((local_def_id, Some(item.ident.name)), (item, None, None));
             }
         }
 
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 81179480ed810..4a57c61406ce4 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -115,6 +115,11 @@ pub(super) fn handle_needs(
             condition: cache.x86_64_dlltool,
             ignore_reason: "ignored when dlltool for x86_64 is not present",
         },
+        Need {
+            name: "needs-dlltool",
+            condition: cache.dlltool,
+            ignore_reason: "ignored when dlltool for the current architecture is not present",
+        },
         Need {
             name: "needs-git-hash",
             condition: config.git_hash,
@@ -183,6 +188,7 @@ pub(super) struct CachedNeedsConditions {
     rust_lld: bool,
     i686_dlltool: bool,
     x86_64_dlltool: bool,
+    dlltool: bool,
 }
 
 impl CachedNeedsConditions {
@@ -190,6 +196,17 @@ impl CachedNeedsConditions {
         let path = std::env::var_os("PATH").expect("missing PATH environment variable");
         let path = std::env::split_paths(&path).collect::<Vec<_>>();
 
+        // On Windows, dlltool.exe is used for all architectures.
+        #[cfg(windows)]
+        let dlltool = path.iter().any(|dir| dir.join("dlltool.exe").is_file());
+
+        // For non-Windows, there are architecture specific dlltool binaries.
+        #[cfg(not(windows))]
+        let i686_dlltool = path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file());
+        #[cfg(not(windows))]
+        let x86_64_dlltool =
+            path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file());
+
         let target = &&*config.target;
         Self {
             sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(),
@@ -225,17 +242,26 @@ impl CachedNeedsConditions {
                 .join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
                 .exists(),
 
-            // On Windows, dlltool.exe is used for all architectures.
             #[cfg(windows)]
-            i686_dlltool: path.iter().any(|dir| dir.join("dlltool.exe").is_file()),
+            i686_dlltool: dlltool,
             #[cfg(windows)]
-            x86_64_dlltool: path.iter().any(|dir| dir.join("dlltool.exe").is_file()),
+            x86_64_dlltool: dlltool,
+            #[cfg(windows)]
+            dlltool,
 
             // For non-Windows, there are architecture specific dlltool binaries.
             #[cfg(not(windows))]
-            i686_dlltool: path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file()),
+            i686_dlltool,
+            #[cfg(not(windows))]
+            x86_64_dlltool,
             #[cfg(not(windows))]
-            x86_64_dlltool: path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file()),
+            dlltool: if config.matches_arch("x86") {
+                i686_dlltool
+            } else if config.matches_arch("x86_64") {
+                x86_64_dlltool
+            } else {
+                false
+            },
         }
     }
 }
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 6b9a9b66a7d9e..270704ebffde6 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -226,6 +226,24 @@ function runSearch(query, expected, doSearch, loadedFile, queryName) {
     return error_text;
 }
 
+function runCorrections(query, corrections, getCorrections, loadedFile) {
+    const qc = getCorrections(query, loadedFile.FILTER_CRATE);
+    const error_text = [];
+
+    if (corrections === null) {
+        if (qc !== null) {
+            error_text.push(`==> expected = null, found = ${qc}`);
+        }
+        return error_text;
+    }
+
+    if (qc !== corrections.toLowerCase()) {
+        error_text.push(`==> expected = ${corrections}, found = ${qc}`);
+    }
+
+    return error_text;
+}
+
 function checkResult(error_text, loadedFile, displaySuccess) {
     if (error_text.length === 0 && loadedFile.should_fail === true) {
         console.log("FAILED");
@@ -272,9 +290,10 @@ function runCheck(loadedFile, key, callback) {
     return 0;
 }
 
-function runChecks(testFile, doSearch, parseQuery) {
+function runChecks(testFile, doSearch, parseQuery, getCorrections) {
     let checkExpected = false;
     let checkParsed = false;
+    let checkCorrections = false;
     let testFileContent = readFile(testFile) + "exports.QUERY = QUERY;";
 
     if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
@@ -291,9 +310,13 @@ function runChecks(testFile, doSearch, parseQuery) {
         testFileContent += "exports.PARSED = PARSED;";
         checkParsed = true;
     }
-    if (!checkParsed && !checkExpected) {
+    if (testFileContent.indexOf("\nconst CORRECTIONS") !== -1) {
+        testFileContent += "exports.CORRECTIONS = CORRECTIONS;";
+        checkCorrections = true;
+    }
+    if (!checkParsed && !checkExpected && !checkCorrections) {
         console.log("FAILED");
-        console.log("==> At least `PARSED` or `EXPECTED` is needed!");
+        console.log("==> At least `PARSED`, `EXPECTED`, or `CORRECTIONS` is needed!");
         return 1;
     }
 
@@ -310,6 +333,11 @@ function runChecks(testFile, doSearch, parseQuery) {
             return runParser(query, expected, parseQuery, text);
         });
     }
+    if (checkCorrections) {
+        res += runCheck(loadedFile, "CORRECTIONS", (query, expected) => {
+            return runCorrections(query, expected, getCorrections, loadedFile);
+        });
+    }
     return res;
 }
 
@@ -318,9 +346,10 @@ function runChecks(testFile, doSearch, parseQuery) {
  *
  * @param {string} doc_folder      - Path to a folder generated by running rustdoc
  * @param {string} resource_suffix - Version number between filename and .js, e.g. "1.59.0"
- * @returns {Object}               - Object containing two keys: `doSearch`, which runs a search
- *   with the loaded index and returns a table of results; and `parseQuery`, which is the
- *   `parseQuery` function exported from the search module.
+ * @returns {Object}               - Object containing keys: `doSearch`, which runs a search
+ *   with the loaded index and returns a table of results; `parseQuery`, which is the
+ *   `parseQuery` function exported from the search module; and `getCorrections`, which runs
+ *   a search but returns type name corrections instead of results.
  */
 function loadSearchJS(doc_folder, resource_suffix) {
     const searchIndexJs = path.join(doc_folder, "search-index" + resource_suffix + ".js");
@@ -336,6 +365,12 @@ function loadSearchJS(doc_folder, resource_suffix) {
             return searchModule.execQuery(searchModule.parseQuery(queryStr), searchWords,
                 filterCrate, currentCrate);
         },
+        getCorrections: function(queryStr, filterCrate, currentCrate) {
+            const parsedQuery = searchModule.parseQuery(queryStr);
+            searchModule.execQuery(parsedQuery, searchWords,
+                filterCrate, currentCrate);
+            return parsedQuery.correction;
+        },
         parseQuery: searchModule.parseQuery,
     };
 }
@@ -417,11 +452,14 @@ function main(argv) {
     const doSearch = function(queryStr, filterCrate) {
         return parseAndSearch.doSearch(queryStr, filterCrate, opts["crate_name"]);
     };
+    const getCorrections = function(queryStr, filterCrate) {
+        return parseAndSearch.getCorrections(queryStr, filterCrate, opts["crate_name"]);
+    };
 
     if (opts["test_file"].length !== 0) {
         opts["test_file"].forEach(file => {
             process.stdout.write(`Testing ${file} ... `);
-            errors += runChecks(file, doSearch, parseAndSearch.parseQuery);
+            errors += runChecks(file, doSearch, parseAndSearch.parseQuery, getCorrections);
         });
     } else if (opts["test_folder"].length !== 0) {
         fs.readdirSync(opts["test_folder"]).forEach(file => {
@@ -430,7 +468,7 @@ function main(argv) {
             }
             process.stdout.write(`Testing ${file} ... `);
             errors += runChecks(path.join(opts["test_folder"], file), doSearch,
-                    parseAndSearch.parseQuery);
+                    parseAndSearch.parseQuery, getCorrections);
         });
     }
     return errors > 0 ? 1 : 0;
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/lib.rs b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs
index 22f222c12c39b..dcb5fee9ecc76 100644
--- a/tests/run-make/raw-dylib-alt-calling-convention/lib.rs
+++ b/tests/run-make/raw-dylib-alt-calling-convention/lib.rs
@@ -1,5 +1,4 @@
 #![feature(abi_vectorcall)]
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
 
 #[repr(C)]
 #[derive(Clone)]
diff --git a/tests/run-make/raw-dylib-c/lib.rs b/tests/run-make/raw-dylib-c/lib.rs
index 5fb1204037c93..f17125f308c20 100644
--- a/tests/run-make/raw-dylib-c/lib.rs
+++ b/tests/run-make/raw-dylib-c/lib.rs
@@ -1,5 +1,3 @@
-#![feature(raw_dylib)]
-
 #[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
 extern {
     fn extern_fn_1();
diff --git a/tests/run-make/raw-dylib-cross-compilation/lib.rs b/tests/run-make/raw-dylib-cross-compilation/lib.rs
index 51bf2ec6b6e11..3338ac0a0b50f 100644
--- a/tests/run-make/raw-dylib-cross-compilation/lib.rs
+++ b/tests/run-make/raw-dylib-cross-compilation/lib.rs
@@ -1,4 +1,3 @@
-#![feature(raw_dylib)]
 #![feature(no_core, lang_items)]
 #![no_std]
 #![no_core]
diff --git a/tests/run-make/raw-dylib-custom-dlltool/Makefile b/tests/run-make/raw-dylib-custom-dlltool/Makefile
new file mode 100644
index 0000000000000..f5d5360a3fbe8
--- /dev/null
+++ b/tests/run-make/raw-dylib-custom-dlltool/Makefile
@@ -0,0 +1,11 @@
+# Test using -Cdlltool to change where raw-dylib looks for the dlltool binary.
+
+# only-windows
+# only-gnu
+# needs-dlltool
+
+include ../tools.mk
+
+all:
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs -Cdlltool=$(CURDIR)/script.cmd
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
diff --git a/tests/run-make/raw-dylib-custom-dlltool/lib.rs b/tests/run-make/raw-dylib-custom-dlltool/lib.rs
new file mode 100644
index 0000000000000..2f3f497a00de1
--- /dev/null
+++ b/tests/run-make/raw-dylib-custom-dlltool/lib.rs
@@ -0,0 +1,10 @@
+#[link(name = "extern_1", kind = "raw-dylib")]
+extern {
+    fn extern_fn_1();
+}
+
+pub fn library_function() {
+    unsafe {
+        extern_fn_1();
+    }
+}
diff --git a/tests/run-make/raw-dylib-custom-dlltool/output.txt b/tests/run-make/raw-dylib-custom-dlltool/output.txt
new file mode 100644
index 0000000000000..6dd9466d26ddc
--- /dev/null
+++ b/tests/run-make/raw-dylib-custom-dlltool/output.txt
@@ -0,0 +1 @@
+Called dlltool via script.cmd
diff --git a/tests/run-make/raw-dylib-custom-dlltool/script.cmd b/tests/run-make/raw-dylib-custom-dlltool/script.cmd
new file mode 100644
index 0000000000000..95f85c61c67d2
--- /dev/null
+++ b/tests/run-make/raw-dylib-custom-dlltool/script.cmd
@@ -0,0 +1,2 @@
+echo Called dlltool via script.cmd> %TMPDIR%\output.txt
+dlltool.exe %*
diff --git a/tests/run-make/raw-dylib-import-name-type/driver.rs b/tests/run-make/raw-dylib-import-name-type/driver.rs
index 9a3cd9ebe1b4b..6c1c212f187b7 100644
--- a/tests/run-make/raw-dylib-import-name-type/driver.rs
+++ b/tests/run-make/raw-dylib-import-name-type/driver.rs
@@ -1,4 +1,3 @@
-#![feature(raw_dylib)]
 #![feature(abi_vectorcall)]
 
 #[link(name = "extern", kind = "raw-dylib", import_name_type = "undecorated")]
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs
index f72ded7d9f638..0c3125be6f596 100644
--- a/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs
@@ -1,5 +1,3 @@
-#![feature(raw_dylib)]
-
 extern crate raw_dylib_test;
 extern crate raw_dylib_test_wrapper;
 
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs
index 00c2c1c42d15f..4877cb80aea5e 100644
--- a/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs
@@ -1,5 +1,3 @@
-#![feature(raw_dylib)]
-
 #[link(name = "extern_1", kind = "raw-dylib")]
 extern {
     fn extern_fn_1();
diff --git a/tests/run-make/raw-dylib-link-ordinal/lib.rs b/tests/run-make/raw-dylib-link-ordinal/lib.rs
index bb25ac64c613b..1bbb45bbc7725 100644
--- a/tests/run-make/raw-dylib-link-ordinal/lib.rs
+++ b/tests/run-make/raw-dylib-link-ordinal/lib.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "exporter", kind = "raw-dylib")]
 extern {
     #[link_ordinal(13)]
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs b/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs
index b7921396a0f4d..74c5c7f8250b2 100644
--- a/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/lib.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "exporter", kind = "raw-dylib")]
 extern "stdcall" {
     #[link_ordinal(15)]
diff --git a/tests/rustdoc-gui/search-corrections.goml b/tests/rustdoc-gui/search-corrections.goml
new file mode 100644
index 0000000000000..5d1b83b35c5ee
--- /dev/null
+++ b/tests/rustdoc-gui/search-corrections.goml
@@ -0,0 +1,56 @@
+// ignore-tidy-linelength
+
+// Checks that the search tab result tell the user about corrections
+// First, try a search-by-name
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// Intentionally wrong spelling of "NotableStructWithLongName"
+write: (".search-input", "NotableStructWithLongNamr")
+// To be SURE that the search will be run.
+press-key: 'Enter'
+// Waiting for the search results to appear...
+wait-for: "#search-tabs"
+
+// Corrections aren't shown on the "In Names" tab.
+assert: "#search-tabs button.selected:first-child"
+assert-css: (".search-corrections", {
+    "display": "none"
+})
+
+// Corrections do get shown on the "In Parameters" tab.
+click: "#search-tabs button:nth-child(2)"
+assert: "#search-tabs button.selected:nth-child(2)"
+assert-css: (".search-corrections", {
+    "display": "block"
+})
+assert-text: (
+    ".search-corrections",
+    "Type \"notablestructwithlongnamr\" not found. Showing results for closest type name \"notablestructwithlongname\" instead."
+)
+
+// Corrections do get shown on the "In Return Type" tab.
+click: "#search-tabs button:nth-child(3)"
+assert: "#search-tabs button.selected:nth-child(3)"
+assert-css: (".search-corrections", {
+    "display": "block"
+})
+assert-text: (
+    ".search-corrections",
+    "Type \"notablestructwithlongnamr\" not found. Showing results for closest type name \"notablestructwithlongname\" instead."
+)
+
+// Now, explicit return values
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// Intentionally wrong spelling of "NotableStructWithLongName"
+write: (".search-input", "-> NotableStructWithLongNamr")
+// To be SURE that the search will be run.
+press-key: 'Enter'
+// Waiting for the search results to appear...
+wait-for: "#search-tabs"
+
+assert-css: (".search-corrections", {
+    "display": "block"
+})
+assert-text: (
+    ".search-corrections",
+    "Type \"notablestructwithlongnamr\" not found. Showing results for closest type name \"notablestructwithlongname\" instead."
+)
diff --git a/tests/rustdoc-js/generics-trait.js b/tests/rustdoc-js/generics-trait.js
index 7876622435b60..0e84751603ed6 100644
--- a/tests/rustdoc-js/generics-trait.js
+++ b/tests/rustdoc-js/generics-trait.js
@@ -1,9 +1,21 @@
+// exact-check
+
 const QUERY = [
     'Result<SomeTrait>',
+    'Result<SomeTraiz>',
+    'OtherThingxxxxxxxx',
+    'OtherThingxxxxxxxy',
+];
+
+const CORRECTIONS = [
+    null,
+    null,
+    null,
     'OtherThingxxxxxxxx',
 ];
 
 const EXPECTED = [
+    // Result<SomeTrait>
     {
         'in_args': [
             { 'path': 'generics_trait', 'name': 'beta' },
@@ -12,6 +24,21 @@ const EXPECTED = [
             { 'path': 'generics_trait', 'name': 'bet' },
         ],
     },
+    // Result<SomeTraiz>
+    {
+        'in_args': [],
+        'returned': [],
+    },
+    // OtherThingxxxxxxxx
+    {
+        'in_args': [
+            { 'path': 'generics_trait', 'name': 'alpha' },
+        ],
+        'returned': [
+            { 'path': 'generics_trait', 'name': 'alef' },
+        ],
+    },
+    // OtherThingxxxxxxxy
     {
         'in_args': [
             { 'path': 'generics_trait', 'name': 'alpha' },
diff --git a/tests/ui-fulldeps/deriving-encodable-decodable-box.rs b/tests/ui-fulldeps/deriving-encodable-decodable-box.rs
deleted file mode 100644
index 1c376f59e5174..0000000000000
--- a/tests/ui-fulldeps/deriving-encodable-decodable-box.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// run-pass
-
-#![allow(unused_imports)]
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-
-#[derive(Encodable, Decodable)]
-struct A {
-    foo: Box<[bool]>,
-}
-
-fn main() {
-    let obj = A { foo: Box::new([true, false]) };
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = A::decode(&mut decoder);
-
-    assert_eq!(obj.foo, obj2.foo);
-}
diff --git a/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
deleted file mode 100644
index 844d40f2ecd6a..0000000000000
--- a/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// run-pass
-
-#![allow(unused_imports)]
-// This briefly tests the capability of `Cell` and `RefCell` to implement the
-// `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]`
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
-
-#[derive(Encodable, Decodable)]
-struct A {
-    baz: isize,
-}
-
-#[derive(Encodable, Decodable)]
-struct B {
-    foo: Cell<bool>,
-    bar: RefCell<A>,
-}
-
-fn main() {
-    let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = B::decode(&mut decoder);
-
-    assert_eq!(obj.foo.get(), obj2.foo.get());
-    assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz);
-}
diff --git a/tests/ui-fulldeps/issue-14021.rs b/tests/ui-fulldeps/issue-14021.rs
deleted file mode 100644
index 309b5c4a03d57..0000000000000
--- a/tests/ui-fulldeps/issue-14021.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// run-pass
-
-#![allow(unused_mut)]
-#![allow(unused_imports)]
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-
-#[derive(Encodable, Decodable, PartialEq, Debug)]
-struct UnitLikeStruct;
-
-pub fn main() {
-    let obj = UnitLikeStruct;
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = UnitLikeStruct::decode(&mut decoder);
-
-    assert_eq!(obj, obj2);
-}
diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.rs b/tests/ui/const-generics/sneaky-array-repeat-expr.rs
index b147c246bdac8..cd1607608a6e9 100644
--- a/tests/ui/const-generics/sneaky-array-repeat-expr.rs
+++ b/tests/ui/const-generics/sneaky-array-repeat-expr.rs
@@ -10,6 +10,7 @@ impl<const N: usize> Trait<N> for () {
 pub const fn foo<const N: usize>() where (): Trait<N> {
     let bar = [(); <()>::Assoc];
     //~^ error: constant expression depends on a generic parameter
+    //~| error: constant expression depends on a generic parameter
 }
 
 trait Trait2<const N: usize> {
@@ -24,6 +25,7 @@ impl<const N: usize> Trait2<N> for () {
 pub const fn foo2<const N: usize>() where (): Trait2<N> {
     let bar2 = [(); <()>::Assoc2];
     //~^ error: constant expression depends on a generic parameter
+    //~| error: constant expression depends on a generic parameter
 }
 
 fn main() {
diff --git a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr
index 5c77375d39934..e532f27a10da9 100644
--- a/tests/ui/const-generics/sneaky-array-repeat-expr.stderr
+++ b/tests/ui/const-generics/sneaky-array-repeat-expr.stderr
@@ -7,12 +7,28 @@ LL |     let bar = [(); <()>::Assoc];
    = note: this may fail depending on what value the parameter takes
 
 error: constant expression depends on a generic parameter
-  --> $DIR/sneaky-array-repeat-expr.rs:25:21
+  --> $DIR/sneaky-array-repeat-expr.rs:11:15
+   |
+LL |     let bar = [(); <()>::Assoc];
+   |               ^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:26:21
    |
 LL |     let bar2 = [(); <()>::Assoc2];
    |                     ^^^^^^^^^^^^
    |
    = note: this may fail depending on what value the parameter takes
 
-error: aborting due to 2 previous errors
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:26:16
+   |
+LL |     let bar2 = [(); <()>::Assoc2];
+   |                ^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/consts/issue-50439.rs b/tests/ui/consts/issue-50439.rs
index 0be7c405473ca..d42347e136e1c 100644
--- a/tests/ui/consts/issue-50439.rs
+++ b/tests/ui/consts/issue-50439.rs
@@ -22,7 +22,9 @@ impl<T: Sized> PinDropInternal for Bears<T> {
     where
         Self: ReflectDrop,
     {
-        let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize]; //~ ERROR constant expression depends on a generic parameter
+        let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
+        //~^ ERROR constant expression depends on a generic parameter
+        //~| ERROR constant expression depends on a generic parameter
     }
 }
 
diff --git a/tests/ui/consts/issue-50439.stderr b/tests/ui/consts/issue-50439.stderr
index 3fbdf33b2d881..7a8cd45ecc7d1 100644
--- a/tests/ui/consts/issue-50439.stderr
+++ b/tests/ui/consts/issue-50439.stderr
@@ -6,5 +6,13 @@ LL |         let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usi
    |
    = note: this may fail depending on what value the parameter takes
 
-error: aborting due to previous error
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-50439.rs:25:17
+   |
+LL |         let _ = [(); 0 - !!(<Bears<T> as ReflectDrop>::REFLECT_DROP) as usize];
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs
deleted file mode 100644
index fc47a9061d3c0..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib-2.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// only-x86
-#[link(name = "foo")]
-extern "C" {
-    #[link_ordinal(42)]
-    //~^ ERROR: `#[link_ordinal]` is unstable on x86
-    fn foo();
-    #[link_ordinal(5)]
-    //~^ ERROR: `#[link_ordinal]` is unstable on x86
-    static mut imported_variable: i32;
-}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr
deleted file mode 100644
index 0e900760d245e..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib-2.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: `#[link_ordinal]` is unstable on x86
-  --> $DIR/feature-gate-raw-dylib-2.rs:4:5
-   |
-LL |     #[link_ordinal(42)]
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error[E0658]: `#[link_ordinal]` is unstable on x86
-  --> $DIR/feature-gate-raw-dylib-2.rs:7:5
-   |
-LL |     #[link_ordinal(5)]
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs
deleted file mode 100644
index 295f502d6a3e5..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// only-windows
-// only-x86
-#[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
-//~^ ERROR link kind `raw-dylib` is unstable on x86
-//~| ERROR import name type is unstable
-extern "C" {}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr
deleted file mode 100644
index d6b165b7610a5..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib-import-name-type.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: link kind `raw-dylib` is unstable on x86
-  --> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:29
-   |
-LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
-   |                             ^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error[E0658]: import name type is unstable
-  --> $DIR/feature-gate-raw-dylib-import-name-type.rs:3:61
-   |
-LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
-   |                                                             ^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib.rs b/tests/ui/feature-gates/feature-gate-raw-dylib.rs
deleted file mode 100644
index 291cca8fd2573..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// only-windows
-// only-x86
-#[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: link kind `raw-dylib` is unstable on x86
-extern "C" {}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib.stderr
deleted file mode 100644
index f02241e4908c0..0000000000000
--- a/tests/ui/feature-gates/feature-gate-raw-dylib.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: link kind `raw-dylib` is unstable on x86
-  --> $DIR/feature-gate-raw-dylib.rs:3:29
-   |
-LL | #[link(name = "foo", kind = "raw-dylib")]
-   |                             ^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
index ffeabe5c2edab..776006124dccf 100644
--- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
+++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
@@ -5,10 +5,10 @@
 use std::ops::Deref;
 
 pub trait Foo {
-    fn bar() -> impl Deref<Target = impl Sized>;
+    fn bar(self) -> impl Deref<Target = impl Sized>;
 }
 
 pub struct Foreign;
 impl Foo for Foreign {
-    fn bar() -> &'static () { &() }
+    fn bar(self) -> &'static () { &() }
 }
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs
new file mode 100644
index 0000000000000..ecb5e62c433a0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs
@@ -0,0 +1,8 @@
+// aux-build: rpitit.rs
+
+extern crate rpitit;
+
+fn main() {
+    let _: &dyn rpitit::Foo = todo!();
+    //~^ ERROR the trait `Foo` cannot be made into an object
+}
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
new file mode 100644
index 0000000000000..6eef392c05f01
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -0,0 +1,15 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/foreign-dyn-error.rs:6:12
+   |
+LL |     let _: &dyn rpitit::Foo = todo!();
+   |            ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/auxiliary/rpitit.rs:8:21
+   |
+LL |     fn bar(self) -> impl Deref<Target = impl Sized>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs
index f4972d948b246..98417b343a11e 100644
--- a/tests/ui/impl-trait/in-trait/foreign.rs
+++ b/tests/ui/impl-trait/in-trait/foreign.rs
@@ -5,17 +5,18 @@
 
 extern crate rpitit;
 
+use rpitit::{Foo, Foreign};
 use std::sync::Arc;
 
 // Implement an RPITIT from another crate.
 struct Local;
-impl rpitit::Foo for Local {
-    fn bar() -> Arc<String> { Arc::new(String::new()) }
+impl Foo for Local {
+    fn bar(self) -> Arc<String> { Arc::new(String::new()) }
 }
 
 fn main() {
     // Witness an RPITIT from another crate.
-    let &() = <rpitit::Foreign as rpitit::Foo>::bar();
+    let &() = Foreign.bar();
 
-    let x: Arc<String> = <Local as rpitit::Foo>::bar();
+    let x: Arc<String> = Local.bar();
 }
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index 351243c6727da..ec4fda322d04f 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -1,14 +1,12 @@
 #![feature(type_alias_impl_trait)]
 
 // edition:2021
-// unset-rustc-env:RUST_BACKTRACE
 // compile-flags:-Z treat-err-as-bug=1
-// error-pattern:stack backtrace:
+// error-pattern: aborting due to `-Z treat-err-as-bug=1`
 // failure-status:101
-// normalize-stderr-test "note: .*" -> ""
-// normalize-stderr-test "thread 'rustc' .*" -> ""
-// normalize-stderr-test " +[0-9]+:.*\n" -> ""
-// normalize-stderr-test " +at .*\n" -> ""
+// normalize-stderr-test ".*note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// rustc-env:RUST_BACKTRACE=0
 
 use std::future::Future;
 
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index f3a773837785e..facab390d1524 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -1,24 +1,12 @@
 error: unconstrained opaque type
-  --> $DIR/issue-86800.rs:33:34
+  --> $DIR/issue-86800.rs:31:34
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = 
-
-
-stack backtrace:
-
 error: the compiler unexpectedly panicked. this is a bug.
 
-
-
-
-
-
-
 query stack during panic:
 #0 [type_of] computing type of `TransactionFuture::{opaque#0}`
 #1 [check_mod_item_types] checking item types in top-level module
-#2 [analysis] running analysis passes on this crate
 end of query stack
diff --git a/tests/ui/panics/default-backtrace-ice.rs b/tests/ui/panics/default-backtrace-ice.rs
index fd86a3f9dfaff..483645ab90fa5 100644
--- a/tests/ui/panics/default-backtrace-ice.rs
+++ b/tests/ui/panics/default-backtrace-ice.rs
@@ -4,6 +4,14 @@
 // failure-status:101
 // normalize-stderr-test "note: .*" -> ""
 // normalize-stderr-test "thread 'rustc' .*" -> ""
-// normalize-stderr-test "  .*\n" -> ""
+// normalize-stderr-test " +\d+:.*__rust_begin_short_backtrace.*" -> "(begin_short_backtrace)"
+// normalize-stderr-test " +\d+:.*__rust_end_short_backtrace.*" -> "(end_short_backtrace)"
+// normalize-stderr-test " +\d+:.*\n" -> ""
+// normalize-stderr-test " +at .*\n" -> ""
+//
+// This test makes sure that full backtraces are used for ICEs when
+// RUST_BACKTRACE is not set. It does this by checking for the presence of
+// `__rust_{begin,end}_short_backtrace` markers, which only appear in full
+// backtraces. The rest of the backtrace is filtered out.
 
 fn main() { missing_ident; }
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index 4bd4780e25f6b..28fb91763d439 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -1,8 +1,13 @@
 error[E0425]: cannot find value `missing_ident` in this scope
+  --> $DIR/default-backtrace-ice.rs:17:13
+   |
 LL | fn main() { missing_ident; }
+   |             ^^^^^^^^^^^^^ not found in this scope
 
 
 stack backtrace:
+(end_short_backtrace)
+(begin_short_backtrace)
 
 error: the compiler unexpectedly panicked. this is a bug.
 
diff --git a/tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs
new file mode 100644
index 0000000000000..d7a418959bf51
--- /dev/null
+++ b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.rs
@@ -0,0 +1,19 @@
+// Tests that dlltool failing to generate an import library will raise an error.
+
+// only-gnu
+// only-windows
+// needs-dlltool
+// compile-flags: --crate-type lib --emit link
+// normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL"
+// normalize-stderr-test: "[^ ]*/foo.def" -> "$$DEF_FILE"
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+    // `@1` is an invalid name to export, as it usually indicates that something
+    // is being exported via ordinal.
+    #[link_name = "@1"]
+    fn f(x: i32);
+}
+
+pub fn lib_main() {
+    unsafe { f(42); }
+}
diff --git a/tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr
new file mode 100644
index 0000000000000..020ac6a2b670b
--- /dev/null
+++ b/tests/ui/rfc-2627-raw-dylib/dlltool-failed.stderr
@@ -0,0 +1,5 @@
+error: Dlltool could not create import library: 
+       $DLLTOOL: Syntax error in def file $DEF_FILE:1
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
index 22d57f8bedddc..7bc44d65be9e5 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.rs
@@ -1,7 +1,5 @@
 // only-windows
 // only-x86
-#![feature(raw_dylib)]
-
 #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
 //~^ ERROR import name type must be of the form `import_name_type = "string"`
 extern "C" { }
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
index 0e95fec29d257..fb70b987fc7d9 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr
@@ -1,5 +1,5 @@
 error: import name type must be of the form `import_name_type = "string"`
-  --> $DIR/import-name-type-invalid-format.rs:5:42
+  --> $DIR/import-name-type-invalid-format.rs:3:42
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
    |                                          ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs
index 7ccb0082fb976..b96f61a26da8b 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.rs
@@ -1,8 +1,6 @@
 // ignore-tidy-linelength
 // only-windows
 // only-x86
-#![feature(raw_dylib)]
-
 #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
 //~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute
 extern "C" { }
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr
index 7c0e0be911f73..9533061892fee 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-multiple.stderr
@@ -1,5 +1,5 @@
 error: multiple `import_name_type` arguments in a single `#[link]` attribute
-  --> $DIR/import-name-type-multiple.rs:6:74
+  --> $DIR/import-name-type-multiple.rs:4:74
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
    |                                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
index f728a578d3b8a..067e82a17fdc5 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.rs
@@ -1,7 +1,5 @@
 // only-windows
 // only-x86
-#![feature(raw_dylib)]
-
 #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
 //~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
 extern "C" { }
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
index 2b299f2fea316..2bce9758e997c 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr
@@ -1,5 +1,5 @@
 error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
-  --> $DIR/import-name-type-unknown-value.rs:5:42
+  --> $DIR/import-name-type-unknown-value.rs:3:42
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
index ae9207864a2ae..34e907bde839a 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs
@@ -1,7 +1,5 @@
 // only-windows
 // only-x86
-#![feature(raw_dylib)]
-
 #[link(name = "foo", import_name_type = "decorated")]
 //~^ ERROR import name type can only be used with link kind `raw-dylib`
 extern "C" { }
diff --git a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
index 5898cd875a1c8..75cadc471c437 100644
--- a/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr
@@ -1,11 +1,11 @@
 error: import name type can only be used with link kind `raw-dylib`
-  --> $DIR/import-name-type-unsupported-link-kind.rs:5:22
+  --> $DIR/import-name-type-unsupported-link-kind.rs:3:22
    |
 LL | #[link(name = "foo", import_name_type = "decorated")]
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: import name type can only be used with link kind `raw-dylib`
-  --> $DIR/import-name-type-unsupported-link-kind.rs:9:39
+  --> $DIR/import-name-type-unsupported-link-kind.rs:7:39
    |
 LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")]
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs
new file mode 100644
index 0000000000000..a07be9d92b4ed
--- /dev/null
+++ b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.rs
@@ -0,0 +1,13 @@
+// Tests that failing to run dlltool will raise an error.
+
+// only-gnu
+// only-windows
+// compile-flags: --crate-type lib --emit link -Cdlltool=does_not_exit.exe
+#[link(name = "foo", kind = "raw-dylib")]
+extern "C" {
+    fn f(x: i32);
+}
+
+pub fn lib_main() {
+    unsafe { f(42); }
+}
diff --git a/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr
new file mode 100644
index 0000000000000..3ae901e0dbc94
--- /dev/null
+++ b/tests/ui/rfc-2627-raw-dylib/invalid-dlltool.stderr
@@ -0,0 +1,4 @@
+error: Error calling dlltool 'does_not_exit.exe': program not found
+
+error: aborting due to previous error
+
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
index 1a128c87a0c30..b04c2facbcdf3 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name="foo")]
 extern "C" {
     #[link_name="foo"]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
index 481a06d2797d5..f1e54d37827c0 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr
@@ -1,11 +1,11 @@
 error: cannot use `#[link_name]` with `#[link_ordinal]`
-  --> $DIR/link-ordinal-and-name.rs:6:5
+  --> $DIR/link-ordinal-and-name.rs:4:5
    |
 LL |     #[link_ordinal(42)]
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: cannot use `#[link_name]` with `#[link_ordinal]`
-  --> $DIR/link-ordinal-and-name.rs:10:5
+  --> $DIR/link-ordinal-and-name.rs:8:5
    |
 LL |     #[link_ordinal(5)]
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
index 7c8da050cf624..9b7e8d70743b7 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo")]
 extern "C" {
     #[link_ordinal("JustMonika")]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
index 55cdcad75a4ad..6341e57a0be53 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr
@@ -1,5 +1,5 @@
 error: illegal ordinal format in `link_ordinal`
-  --> $DIR/link-ordinal-invalid-format.rs:5:5
+  --> $DIR/link-ordinal-invalid-format.rs:3:5
    |
 LL |     #[link_ordinal("JustMonika")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     #[link_ordinal("JustMonika")]
    = note: an unsuffixed integer value, e.g., `1`, is expected
 
 error: illegal ordinal format in `link_ordinal`
-  --> $DIR/link-ordinal-invalid-format.rs:8:5
+  --> $DIR/link-ordinal-invalid-format.rs:6:5
    |
 LL |     #[link_ordinal("JustMonika")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
index 9feed39411046..6b8cd49566dfe 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo")]
 extern "C" {
     #[link_ordinal()]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
index 853cdad8c1c54..1b04bb228e76a 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr
@@ -1,5 +1,5 @@
 error: incorrect number of arguments to `#[link_ordinal]`
-  --> $DIR/link-ordinal-missing-argument.rs:5:5
+  --> $DIR/link-ordinal-missing-argument.rs:3:5
    |
 LL |     #[link_ordinal()]
    |     ^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     #[link_ordinal()]
    = note: the attribute requires exactly one argument
 
 error: incorrect number of arguments to `#[link_ordinal]`
-  --> $DIR/link-ordinal-missing-argument.rs:8:5
+  --> $DIR/link-ordinal-missing-argument.rs:6:5
    |
 LL |     #[link_ordinal()]
    |     ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
index 631c363d4ba15..8842cb944045f 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.rs
@@ -1,6 +1,4 @@
 // only-windows
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo", kind = "raw-dylib")]
 extern "C" {
     #[link_ordinal(1)] //~ ERROR multiple `link_ordinal` attributes
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
index c0453d2bf0118..2e6cf3761c2f0 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-multiple.stderr
@@ -1,23 +1,23 @@
 error: multiple `link_ordinal` attributes
-  --> $DIR/link-ordinal-multiple.rs:6:5
+  --> $DIR/link-ordinal-multiple.rs:4:5
    |
 LL |     #[link_ordinal(1)]
    |     ^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/link-ordinal-multiple.rs:7:5
+  --> $DIR/link-ordinal-multiple.rs:5:5
    |
 LL |     #[link_ordinal(2)]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: multiple `link_ordinal` attributes
-  --> $DIR/link-ordinal-multiple.rs:9:5
+  --> $DIR/link-ordinal-multiple.rs:7:5
    |
 LL |     #[link_ordinal(1)]
    |     ^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/link-ordinal-multiple.rs:10:5
+  --> $DIR/link-ordinal-multiple.rs:8:5
    |
 LL |     #[link_ordinal(2)]
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
index 54e614164b3a5..f33a3d62e2688 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link_ordinal(123)]
 //~^ ERROR attribute should be applied to a foreign function or static
 struct Foo {}
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
index ec4104fbe5000..8f279508720ce 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr
@@ -1,17 +1,17 @@
 error: attribute should be applied to a foreign function or static
-  --> $DIR/link-ordinal-not-foreign-fn.rs:3:1
+  --> $DIR/link-ordinal-not-foreign-fn.rs:1:1
    |
 LL | #[link_ordinal(123)]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a foreign function or static
-  --> $DIR/link-ordinal-not-foreign-fn.rs:7:1
+  --> $DIR/link-ordinal-not-foreign-fn.rs:5:1
    |
 LL | #[link_ordinal(123)]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a foreign function or static
-  --> $DIR/link-ordinal-not-foreign-fn.rs:11:1
+  --> $DIR/link-ordinal-not-foreign-fn.rs:9:1
    |
 LL | #[link_ordinal(42)]
    | ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
index 46731581ebcb0..9d741630fc9da 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo")]
 extern "C" {
     #[link_ordinal(72436)]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
index fef6de6aedfe4..811145e77ee46 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr
@@ -1,5 +1,5 @@
 error: ordinal value in `link_ordinal` is too large: `72436`
-  --> $DIR/link-ordinal-too-large.rs:5:5
+  --> $DIR/link-ordinal-too-large.rs:3:5
    |
 LL |     #[link_ordinal(72436)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     #[link_ordinal(72436)]
    = note: the value may not exceed `u16::MAX`
 
 error: ordinal value in `link_ordinal` is too large: `72436`
-  --> $DIR/link-ordinal-too-large.rs:8:5
+  --> $DIR/link-ordinal-too-large.rs:6:5
    |
 LL |     #[link_ordinal(72436)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
index 71e0ac9f3ee4b..9988115fd8b0d 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo")]
 extern "C" {
     #[link_ordinal(3, 4)]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
index 7e0fcd845cbde..d5ce8aff34f20 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr
@@ -1,5 +1,5 @@
 error: incorrect number of arguments to `#[link_ordinal]`
-  --> $DIR/link-ordinal-too-many-arguments.rs:5:5
+  --> $DIR/link-ordinal-too-many-arguments.rs:3:5
    |
 LL |     #[link_ordinal(3, 4)]
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     #[link_ordinal(3, 4)]
    = note: the attribute requires exactly one argument
 
 error: incorrect number of arguments to `#[link_ordinal]`
-  --> $DIR/link-ordinal-too-many-arguments.rs:8:5
+  --> $DIR/link-ordinal-too-many-arguments.rs:6:5
    |
 LL |     #[link_ordinal(3, 4)]
    |     ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
index 329c93fc19637..14e915d602aaa 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
-
 #[link(name = "foo")]
 extern "C" {
     #[link_ordinal(3)]
diff --git a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
index 5fbffbda570af..200b8f6287465 100644
--- a/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr
@@ -1,11 +1,11 @@
 error: `#[link_ordinal]` is only supported if link kind is `raw-dylib`
-  --> $DIR/link-ordinal-unsupported-link-kind.rs:5:5
+  --> $DIR/link-ordinal-unsupported-link-kind.rs:3:5
    |
 LL |     #[link_ordinal(3)]
    |     ^^^^^^^^^^^^^^^^^^
 
 error: `#[link_ordinal]` is only supported if link kind is `raw-dylib`
-  --> $DIR/link-ordinal-unsupported-link-kind.rs:12:5
+  --> $DIR/link-ordinal-unsupported-link-kind.rs:10:5
    |
 LL |     #[link_ordinal(3)]
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs
index 6542faad26412..b4173f3b60bce 100644
--- a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs
+++ b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.rs
@@ -2,7 +2,6 @@
 // only-windows
 // compile-flags: --crate-type lib --emit link
 #![allow(clashing_extern_declarations)]
-#![feature(raw_dylib)]
 #[link(name = "foo", kind = "raw-dylib")]
 extern "C" {
     fn f(x: i32);
diff --git a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
index c6808bec7b5c5..5101084054882 100644
--- a/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/multiple-declarations.stderr
@@ -1,5 +1,5 @@
 error: multiple declarations of external function `f` from library `foo.dll` have different calling conventions
-  --> $DIR/multiple-declarations.rs:14:9
+  --> $DIR/multiple-declarations.rs:13:9
    |
 LL |         fn f(x: i32);
    |         ^^^^^^^^^^^^^
diff --git a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
index 4efffbd532e13..d4c6658a33024 100644
--- a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
+++ b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
@@ -1,6 +1,5 @@
 // ignore-windows
 // compile-flags: --crate-type lib
-#![cfg_attr(target_arch = "x86", feature(raw_dylib))]
 #[link(name = "foo", kind = "raw-dylib")]
 //~^ ERROR: link kind `raw-dylib` is only supported on Windows targets
 extern "C" {}
diff --git a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
index 14e791f1fb9a1..b635a09afba4e 100644
--- a/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
+++ b/tests/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
@@ -1,5 +1,5 @@
 error[E0455]: link kind `raw-dylib` is only supported on Windows targets
-  --> $DIR/raw-dylib-windows-only.rs:4:29
+  --> $DIR/raw-dylib-windows-only.rs:3:29
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
    |                             ^^^^^^^^^^^
diff --git a/tests/ui/typeck/repeat-expr-checks-wf.rs b/tests/ui/typeck/repeat-expr-checks-wf.rs
new file mode 100644
index 0000000000000..b8a2a0ceb5880
--- /dev/null
+++ b/tests/ui/typeck/repeat-expr-checks-wf.rs
@@ -0,0 +1,10 @@
+trait Foo {
+    const ASSOC: [u8];
+}
+
+fn bar<T: Foo>() {
+    let a = [T::ASSOC; 2];
+    //~^ ERROR: the size for values of type `[u8]` cannot be known at compilation time
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/repeat-expr-checks-wf.stderr b/tests/ui/typeck/repeat-expr-checks-wf.stderr
new file mode 100644
index 0000000000000..a821088a4b30e
--- /dev/null
+++ b/tests/ui/typeck/repeat-expr-checks-wf.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/repeat-expr-checks-wf.rs:6:13
+   |
+LL |     let a = [T::ASSOC; 2];
+   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: slice and array elements must have `Sized` type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index 89867b63d64f8..54c8b2060c526 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -475,10 +475,10 @@ cc = ["@rust-lang/style"]
 
 [mentions."Cargo.lock"]
 message = """
-These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
-This was probably unintentional and should be reverted before this PR is merged.
+These commits modify the `Cargo.lock` file. Unintentional changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
 
-If this was intentional then you can ignore this comment.
+If this was unintentional then you should revert the changes before this PR is merged.
+Otherwise, you can ignore this comment.
 """
 
 [mentions."src/tools/x"]
@@ -489,6 +489,14 @@ message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appro
 [mentions."src/bootstrap/defaults/config.codegen.toml"]
 message = "This PR changes src/bootstrap/defaults/config.codegen.toml. If appropriate, please also update `config.compiler.toml` so the defaults are in sync."
 
+[mentions."tests/ui/deriving/deriving-all-codegen.stdout"]
+message = "Changes to the code generated for builtin derived traits."
+cc = ["@nnethercote"]
+
+[mentions."tests/ui/stats/hir-stats.stderr"]
+message = "Changes to the size of AST and/or HIR nodes."
+cc = ["@nnethercote"]
+
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"