about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs6
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs6
-rw-r--r--compiler/rustc_attr/src/builtin.rs25
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs30
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs2
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/mod.rs48
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_data_structures/src/tiny_list.rs2
-rw-r--r--compiler/rustc_errors/src/emitter.rs39
-rw-r--r--compiler/rustc_errors/src/lib.rs44
-rw-r--r--compiler/rustc_expand/src/base.rs11
-rw-r--r--compiler/rustc_expand/src/config.rs69
-rw-r--r--compiler/rustc_expand/src/expand.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs161
-rw-r--r--compiler/rustc_hir/src/hir.rs4
-rw-r--r--compiler/rustc_hir/src/intravisit.rs2
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs4
-rw-r--r--compiler/rustc_incremental/src/assert_module_sources.rs39
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs2
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs2
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_interface/src/util.rs6
-rw-r--r--compiler/rustc_lexer/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs23
-rw-r--r--compiler/rustc_lint/src/levels.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs6
-rw-r--r--compiler/rustc_lint/src/unused.rs63
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs25
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/blocks.rs2
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs2
-rw-r--r--compiler/rustc_middle/src/middle/region.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs14
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/select.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs6
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs10
-rw-r--r--compiler/rustc_middle/src/ty/util.rs2
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs4
-rw-r--r--compiler/rustc_mir/src/borrow_check/mod.rs10
-rw-r--r--compiler/rustc_mir/src/borrow_check/universal_regions.rs2
-rw-r--r--compiler/rustc_mir/src/dataflow/framework/engine.rs2
-rw-r--r--compiler/rustc_mir/src/dataflow/mod.rs4
-rw-r--r--compiler/rustc_mir/src/interpret/operand.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/validity.rs2
-rw-r--r--compiler/rustc_mir/src/monomorphize/partitioning/default.rs2
-rw-r--r--compiler/rustc_mir/src/monomorphize/polymorphize.rs6
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs2
-rw-r--r--compiler/rustc_mir/src/transform/coverage/counters.rs2
-rw-r--r--compiler/rustc_mir/src/transform/coverage/mod.rs2
-rw-r--r--compiler/rustc_mir/src/transform/rustc_peek.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs44
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs6
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs12
-rw-r--r--compiler/rustc_passes/Cargo.toml2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs166
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs9
-rw-r--r--compiler/rustc_passes/src/lang_items.rs3
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/lib_features.rs4
-rw-r--r--compiler/rustc_passes/src/liveness.rs103
-rw-r--r--compiler/rustc_passes/src/stability.rs3
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs3
-rw-r--r--compiler/rustc_plugin_impl/src/load.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs8
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs52
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs10
-rw-r--r--compiler/rustc_resolve/src/lib.rs25
-rw-r--r--compiler/rustc_serialize/src/json.rs4
-rw-r--r--compiler/rustc_serialize/src/serialize.rs2
-rw-r--r--compiler/rustc_session/src/config.rs28
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs38
-rw-r--r--compiler/rustc_span/src/source_map.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs4
-rw-r--r--compiler/rustc_target/src/asm/mod.rs2
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs6
-rw-r--r--compiler/rustc_target/src/spec/armv7_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/i386_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs2
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs4
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs2
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs4
-rw-r--r--compiler/rustc_typeck/src/check/closure.rs2
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs1
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs103
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs2
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs23
-rw-r--r--compiler/rustc_typeck/src/check/fallback.rs6
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs1
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs3
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs2
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs2
-rw-r--r--compiler/rustc_typeck/src/collect.rs58
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs5
-rw-r--r--compiler/rustc_typeck/src/lib.rs4
-rw-r--r--compiler/rustc_typeck/src/outlives/implicit_infer.rs2
-rw-r--r--library/alloc/src/alloc.rs2
-rw-r--r--library/alloc/src/collections/binary_heap.rs2
-rw-r--r--library/core/src/array/iter.rs2
-rw-r--r--library/core/src/char/methods.rs2
-rw-r--r--library/core/src/fmt/mod.rs42
-rw-r--r--library/core/src/intrinsics.rs2
-rw-r--r--library/core/src/iter/adapters/zip.rs2
-rw-r--r--library/core/src/iter/traits/marker.rs2
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/macros/mod.rs1
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/num/dec2flt/lemire.rs2
-rw-r--r--library/core/src/panicking.rs10
-rw-r--r--library/core/src/ptr/mod.rs6
-rw-r--r--library/proc_macro/src/lib.rs2
-rw-r--r--library/std/src/collections/hash/map.rs6
-rw-r--r--library/std/src/ffi/c_str.rs6
-rw-r--r--library/std/src/ffi/mod.rs2
-rw-r--r--library/std/src/ffi/os_str.rs8
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/keyword_docs.rs2
-rw-r--r--library/std/src/net/addr.rs4
-rw-r--r--library/std/src/net/ip.rs6
-rw-r--r--library/std/src/os/unix/net/ancillary.rs4
-rw-r--r--library/std/src/os/windows/ffi.rs2
-rw-r--r--library/std/src/sys/windows/stdio.rs2
-rw-r--r--library/std/src/sys_common/remutex/tests.rs4
-rw-r--r--library/std/src/sys_common/wtf8.rs2
-rw-r--r--library/std/src/time/monotonic.rs2
-rw-r--r--src/doc/rustc/src/lints/levels.md39
-rw-r--r--src/doc/unstable-book/src/compiler-flags/force-warn.md21
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/static/js/search.js2
-rw-r--r--src/librustdoc/lib.rs17
-rw-r--r--src/test/debuginfo/rc_arc.rs4
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs2
-rw-r--r--src/test/mir-opt/dest-prop/copy_propagation_arg.rs2
-rw-r--r--src/test/pretty/dollar-crate.pp10
-rw-r--r--src/test/pretty/issue-4264.pp56
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt6
-rw-r--r--src/test/run-make/unstable-flag-required/Makefile1
-rw-r--r--src/test/run-make/unstable-flag-required/force-warn.stderr2
-rw-r--r--src/test/rustdoc-ui/coverage/allow_missing_docs.rs2
-rw-r--r--src/test/ui-fulldeps/internal-lints/pass_ty_by_ref_self.rs2
-rw-r--r--src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-53249.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-69307.rs2
-rw-r--r--src/test/ui/attributes/key-value-expansion.stderr16
-rw-r--r--src/test/ui/attributes/register-attr-tool-unused.rs2
-rw-r--r--src/test/ui/attributes/register-attr-tool-unused.stderr18
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue_88118.rs15
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs2
-rw-r--r--src/test/ui/closures/issue-87814-1.rs8
-rw-r--r--src/test/ui/closures/issue-87814-2.rs11
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs4
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr4
-rw-r--r--src/test/ui/const-generics/defaults/default-annotation.rs1
-rw-r--r--src/test/ui/consts/cast-discriminant-zst-enum.rs2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs223
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr969
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-2.rs20
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs18
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr16
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-specialization.rs25
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-specialization.stderr26
-rw-r--r--src/test/ui/generic-associated-types/issue-87429.rs15
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.rs2
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs2
-rw-r--r--src/test/ui/invalid/invalid-plugin-attr.rs3
-rw-r--r--src/test/ui/invalid/invalid-plugin-attr.stderr10
-rw-r--r--src/test/ui/issues/issue-11692-2.stderr2
-rw-r--r--src/test/ui/lint/cli-lint-override.rs2
-rw-r--r--src/test/ui/lint/cli-unknown-force-warn.rs2
-rw-r--r--src/test/ui/lint/cli-unknown-force-warn.stderr6
-rw-r--r--src/test/ui/lint/dead-code/issue-85071-2.rs22
-rw-r--r--src/test/ui/lint/dead-code/issue-85071-2.stderr34
-rw-r--r--src/test/ui/lint/dead-code/issue-85071.rs19
-rw-r--r--src/test/ui/lint/dead-code/issue-85071.stderr34
-rw-r--r--src/test/ui/lint/force-warn/allow-warnings.rs2
-rw-r--r--src/test/ui/lint/force-warn/allowed-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/cap-lints-allow.rs2
-rw-r--r--src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/deny-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allow-warnings.rs2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs2
-rw-r--r--src/test/ui/lint/lint-misplaced-attr.rs6
-rw-r--r--src/test/ui/lint/lint-misplaced-attr.stderr18
-rw-r--r--src/test/ui/lint/lint-nonstandard-style-unicode-1.rs2
-rw-r--r--src/test/ui/lint/unused/unused-attr-macro-rules.rs7
-rw-r--r--src/test/ui/lint/unused/unused-attr-macro-rules.stderr12
-rw-r--r--src/test/ui/lint/unused/unused-attr.rs49
-rw-r--r--src/test/ui/lint/unused/unused-attr.stderr98
-rw-r--r--src/test/ui/macros/issue-88206.rs66
-rw-r--r--src/test/ui/macros/issue-88206.stderr114
-rw-r--r--src/test/ui/macros/issue-88228.rs1
-rw-r--r--src/test/ui/macros/issue-88228.stderr4
-rw-r--r--src/test/ui/macros/macro-path-prelude-fail-3.stderr2
-rw-r--r--src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs2
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.stderr10
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/enum.rs2
-rw-r--r--src/test/ui/traits/reservation-impl/non-lattice-ok.rs4
-rw-r--r--src/test/ui/union/union-nonzero.rs2
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr8
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs3
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr8
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_eq.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs35
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs2
-rw-r--r--src/tools/rustdoc-gui/tester.js28
-rw-r--r--src/tools/rustfmt/src/macros.rs2
-rw-r--r--src/tools/rustfmt/src/string.rs2
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/tidy/src/style.rs2
280 files changed, 2156 insertions, 1870 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9e0624c57ae..e4612d8a954 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4115,10 +4115,12 @@ dependencies = [
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_feature",
  "rustc_hir",
  "rustc_index",
  "rustc_lexer",
  "rustc_middle",
+ "rustc_parse",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 15f46ef5d7f..710a592e258 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -495,7 +495,7 @@ impl Token {
         self.lifetime().is_some()
     }
 
-    /// Returns `true` if the token is a identifier whose name is the given
+    /// Returns `true` if the token is an identifier whose name is the given
     /// string slice.
     pub fn is_ident_named(&self, name: Symbol) -> bool {
         self.ident().map_or(false, |(ident, _)| ident.name == name)
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d41b3b81466..7b018875571 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1265,7 +1265,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                     ty,
                                 );
 
-                                // Construct a AnonConst where the expr is the "ty"'s path.
+                                // Construct an AnonConst where the expr is the "ty"'s path.
 
                                 let parent_def_id = self.current_hir_id_owner.0;
                                 let node_id = self.resolver.next_node_id();
@@ -2281,7 +2281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     synthetic: param
                         .attrs
                         .iter()
-                        .filter(|attr| self.sess.check_name(attr, sym::rustc_synthetic))
+                        .filter(|attr| attr.has_name(sym::rustc_synthetic))
                         .map(|_| hir::SyntheticTyParamKind::FromAttr)
                         .next(),
                 };
@@ -2690,7 +2690,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
-    /// return a "error lifetime".
+    /// return an "error lifetime".
     fn new_error_lifetime(&mut self, id: Option<NodeId>, span: Span) -> hir::Lifetime {
         let (id, msg, label) = match id {
             Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"),
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index feece517ceb..0be26b6f8e9 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -268,7 +268,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             gate_feature_fn!(self, has_feature, attr.span, name, descr);
         }
         // Check unstable flavors of the `#[doc]` attribute.
-        if self.sess.check_name(attr, sym::doc) {
+        if attr.has_name(sym::doc) {
             for nested_meta in attr.meta_item_list().unwrap_or_default() {
                 macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
                     $(if nested_meta.has_name(sym::$name) {
@@ -287,7 +287,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         }
 
         // Check for unstable modifiers on `#[link(..)]` attribute
-        if self.sess.check_name(attr, sym::link) {
+        if attr.has_name(sym::link) {
             for nested_meta in attr.meta_item_list().unwrap_or_default() {
                 if nested_meta.has_name(sym::modifiers) {
                     gate_feature_post!(
@@ -709,7 +709,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
 
     if !sess.opts.unstable_features.is_nightly_build() {
         let lang_features = &sess.features_untracked().declared_lang_features;
-        for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) {
+        for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
             let mut err = struct_span_err!(
                 sess.parse_sess.span_diagnostic,
                 attr.span,
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index a50fc698850..0ab452fb42d 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -166,8 +166,6 @@ where
             continue; // not a stability level
         }
 
-        sess.mark_attr_used(attr);
-
         let meta = attr.meta();
 
         if attr.has_name(sym::rustc_promotable) {
@@ -636,8 +634,7 @@ where
     let diagnostic = &sess.parse_sess.span_diagnostic;
 
     'outer: for attr in attrs_iter {
-        if !(sess.check_name(attr, sym::deprecated) || sess.check_name(attr, sym::rustc_deprecated))
-        {
+        if !(attr.has_name(sym::deprecated) || attr.has_name(sym::rustc_deprecated)) {
             continue;
         }
 
@@ -700,17 +697,17 @@ where
                                     continue 'outer;
                                 }
                             }
-                            sym::note if sess.check_name(attr, sym::deprecated) => {
+                            sym::note if attr.has_name(sym::deprecated) => {
                                 if !get(mi, &mut note) {
                                     continue 'outer;
                                 }
                             }
-                            sym::reason if sess.check_name(attr, sym::rustc_deprecated) => {
+                            sym::reason if attr.has_name(sym::rustc_deprecated) => {
                                 if !get(mi, &mut note) {
                                     continue 'outer;
                                 }
                             }
-                            sym::suggestion if sess.check_name(attr, sym::rustc_deprecated) => {
+                            sym::suggestion if attr.has_name(sym::rustc_deprecated) => {
                                 if !get(mi, &mut suggestion) {
                                     continue 'outer;
                                 }
@@ -721,7 +718,7 @@ where
                                     meta.span(),
                                     AttrError::UnknownMetaItem(
                                         pprust::path_to_string(&mi.path),
-                                        if sess.check_name(attr, sym::deprecated) {
+                                        if attr.has_name(sym::deprecated) {
                                             &["since", "note"]
                                         } else {
                                             &["since", "reason", "suggestion"]
@@ -747,11 +744,11 @@ where
             }
         }
 
-        if suggestion.is_some() && sess.check_name(attr, sym::deprecated) {
+        if suggestion.is_some() && attr.has_name(sym::deprecated) {
             unreachable!("only allowed on rustc_deprecated")
         }
 
-        if sess.check_name(attr, sym::rustc_deprecated) {
+        if attr.has_name(sym::rustc_deprecated) {
             if since.is_none() {
                 handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
                 continue;
@@ -763,9 +760,7 @@ where
             }
         }
 
-        sess.mark_attr_used(&attr);
-
-        let is_since_rustc_version = sess.check_name(attr, sym::rustc_deprecated);
+        let is_since_rustc_version = attr.has_name(sym::rustc_deprecated);
         depr = Some((Deprecation { since, note, suggestion, is_since_rustc_version }, attr.span));
     }
 
@@ -816,7 +811,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
     let diagnostic = &sess.parse_sess.span_diagnostic;
     if attr.has_name(sym::repr) {
         if let Some(items) = attr.meta_item_list() {
-            sess.mark_attr_used(attr);
             for item in items {
                 let mut recognised = false;
                 if item.is_word() {
@@ -1015,14 +1009,13 @@ pub enum TransparencyError {
 }
 
 pub fn find_transparency(
-    sess: &Session,
     attrs: &[Attribute],
     macro_rules: bool,
 ) -> (Transparency, Option<TransparencyError>) {
     let mut transparency = None;
     let mut error = None;
     for attr in attrs {
-        if sess.check_name(attr, sym::rustc_macro_transparency) {
+        if attr.has_name(sym::rustc_macro_transparency) {
             if let Some((_, old_span)) = transparency {
                 error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
                 break;
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 61af4979e70..59f933d422d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -677,8 +677,6 @@ impl<'a> TraitDef<'a> {
         let self_type = cx.ty_path(path);
 
         let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
-        // Just mark it now since we know that it'll end up used downstream
-        cx.sess.mark_attr_used(&attr);
         let opt_trait_ref = Some(trait_ref);
         let unused_qual = {
             let word = rustc_ast::attr::mk_nested_word_item(Ident::new(
@@ -1700,7 +1698,7 @@ where
 /// One or more fields: call the base case function on the first value (which depends on
 /// `use_fold`), and use that as the base case. Then perform `cs_fold` on the remainder of the
 /// fields.
-/// When the `substructure` is a `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f`
+/// When the `substructure` is an `EnumNonMatchingCollapsed`, the result of `enum_nonmatch_f`
 /// is returned. Statics may not be folded over.
 /// See `cs_op` in `partial_ord.rs` for a model example.
 pub fn cs_fold1<F, B>(
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 00f2f37146d..1dbf7728421 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -3,8 +3,8 @@ use Position::*;
 
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, BlockCheckMode, UnsafeSource};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
 use rustc_expand::base::{self, *};
@@ -838,12 +838,15 @@ impl<'a, 'b> Context<'a, 'b> {
         //
         // But the nested match expression is proved to perform not as well
         // as series of let's; the first approach does.
-        let pat = self.ecx.pat_tuple(self.macsp, pats);
-        let arm = self.ecx.arm(self.macsp, pat, args_array);
-        let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
-        let result = self.ecx.expr_match(self.macsp, head, vec![arm]);
+        let args_match = {
+            let pat = self.ecx.pat_tuple(self.macsp, pats);
+            let arm = self.ecx.arm(self.macsp, pat, args_array);
+            let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
+            self.ecx.expr_match(self.macsp, head, vec![arm])
+        };
 
-        let args_slice = self.ecx.expr_addr_of(self.macsp, result);
+        let ident = Ident::from_str_and_span("args", self.macsp);
+        let args_slice = self.ecx.expr_ident(self.macsp, ident);
 
         // Now create the fmt::Arguments struct with all our locals we created.
         let (fn_name, fn_args) = if self.all_pieces_simple {
@@ -857,7 +860,20 @@ impl<'a, 'b> Context<'a, 'b> {
         };
 
         let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
-        self.ecx.expr_call_global(self.macsp, path, fn_args)
+        let arguments = self.ecx.expr_call_global(self.macsp, path, fn_args);
+        let body = self.ecx.expr_block(P(ast::Block {
+            stmts: vec![self.ecx.stmt_expr(arguments)],
+            id: ast::DUMMY_NODE_ID,
+            rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
+            span: self.macsp,
+            tokens: None,
+        }));
+
+        let ident = Ident::from_str_and_span("args", self.macsp);
+        let binding_mode = ast::BindingMode::ByRef(ast::Mutability::Not);
+        let pat = self.ecx.pat_ident_binding_mode(self.macsp, ident, binding_mode);
+        let arm = self.ecx.arm(self.macsp, pat, body);
+        self.ecx.expr_match(self.macsp, args_match, vec![arm])
     }
 
     fn format_arg(
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index f83329ecba8..7971c1fff42 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -260,11 +260,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
             return;
         }
 
-        if self.sess.check_name(attr, sym::proc_macro_derive) {
+        if attr.has_name(sym::proc_macro_derive) {
             self.collect_custom_derive(item, attr);
-        } else if self.sess.check_name(attr, sym::proc_macro_attribute) {
+        } else if attr.has_name(sym::proc_macro_attribute) {
             self.collect_attr_proc_macro(item);
-        } else if self.sess.check_name(attr, sym::proc_macro) {
+        } else if attr.has_name(sym::proc_macro) {
             self.collect_bang_proc_macro(item);
         };
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index be24b60294b..d791677cb8e 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -188,8 +188,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
                     let attrs = attrs
                         .into_iter()
                         .filter(|attr| {
-                            !self.sess.check_name(attr, sym::rustc_main)
-                                && !self.sess.check_name(attr, sym::start)
+                            !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start)
                         })
                         .chain(iter::once(allow_dead_code))
                         .collect();
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 2139f9776b7..07e1b55afe5 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -558,7 +558,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
         if self.sess().target.arch == "amdgpu" {
-            // amdgpu/LLVM does something weird and thinks a i64 value is
+            // amdgpu/LLVM does something weird and thinks an i64 value is
             // split into a v2i32, halving the bitwidth LLVM expects,
             // tripping an assertion. So, for now, just disable this
             // optimization.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index fe2ed21c1e3..e30c49295ba 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -137,9 +137,9 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                         match scalar.value {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
-                                    // `va_arg` should not be called on a integer type
+                                    // `va_arg` should not be called on an integer type
                                     // less than 4 bytes in length. If it is, promote
-                                    // the integer to a `i32` and truncate the result
+                                    // the integer to an `i32` and truncate the result
                                     // back to the smaller type.
                                     let promoted_result = emit_va_arg(self, args[0], tcx.types.i32);
                                     self.trunc(promoted_result, llret_ty)
@@ -1031,7 +1031,7 @@ fn generic_simd_intrinsic(
         // vector mask and returns an unsigned integer containing the most
         // significant bit (MSB) of each lane.
 
-        // If the vector has less than 8 lanes, an u8 is returned with zeroed
+        // If the vector has less than 8 lanes, a u8 is returned with zeroed
         // trailing bits.
         let expected_int_bits = in_len.max(8);
         match ret_ty.kind() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 7e432d27402..65869483025 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -901,7 +901,7 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     //
     // Performance note: Unordered comparison can be lowered to a "flipped"
     // comparison and a negation, and the negation can be merged into the
-    // select. Therefore, it not necessarily any more expensive than a
+    // select. Therefore, it not necessarily any more expensive than an
     // ordered ("normal") comparison. Whether these optimizations will be
     // performed is ultimately up to the backend, but at least x86 does
     // perform them.
diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs
index ad4b79de236..5b27a407ad4 100644
--- a/compiler/rustc_data_structures/src/owning_ref/mod.rs
+++ b/compiler/rustc_data_structures/src/owning_ref/mod.rs
@@ -321,7 +321,7 @@ pub unsafe trait IntoErasedSendSync<'a> {
 /////////////////////////////////////////////////////////////////////////////
 
 impl<O, T: ?Sized> OwningRef<O, T> {
-    /// Creates a new owning reference from a owner
+    /// Creates a new owning reference from an owner
     /// initialized to the direct dereference of it.
     ///
     /// # Example
@@ -368,7 +368,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
     /// fn main() {
     ///     let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref = owning_ref.map(|array| &array[2]);
     ///     assert_eq!(*owning_ref, 3);
@@ -396,7 +396,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
     /// fn main() {
     ///     let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref = owning_ref.try_map(|array| {
     ///         if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
@@ -430,7 +430,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
     /// in an additional `Box<O>`.
     ///
     /// This can be used to safely erase the owner of any `OwningRef<O, T>`
-    /// to a `OwningRef<Box<Erased>, T>`.
+    /// to an `OwningRef<Box<Erased>, T>`.
     pub fn map_owner_box(self) -> OwningRef<Box<O>, T> {
         OwningRef { reference: self.reference, owner: Box::new(self.owner) }
     }
@@ -511,7 +511,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
 }
 
 impl<O, T: ?Sized> OwningRefMut<O, T> {
-    /// Creates a new owning reference from a owner
+    /// Creates a new owning reference from an owner
     /// initialized to the direct dereference of it.
     ///
     /// # Example
@@ -558,7 +558,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// fn main() {
     ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref = owning_ref_mut.map(|array| &array[2]);
     ///     assert_eq!(*owning_ref, 3);
@@ -586,7 +586,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// fn main() {
     ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]);
     ///     assert_eq!(*owning_ref_mut, 3);
@@ -614,7 +614,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// fn main() {
     ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref = owning_ref_mut.try_map(|array| {
     ///         if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
@@ -644,7 +644,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// fn main() {
     ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
     ///
-    ///     // create a owning reference that points at the
+    ///     // create an owning reference that points at the
     ///     // third element of the array.
     ///     let owning_ref_mut = owning_ref_mut.try_map_mut(|array| {
     ///         if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) }
@@ -678,7 +678,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
     /// in an additional `Box<O>`.
     ///
     /// This can be used to safely erase the owner of any `OwningRefMut<O, T>`
-    /// to a `OwningRefMut<Box<Erased>, T>`.
+    /// to an `OwningRefMut<Box<Erased>, T>`.
     pub fn map_owner_box(self) -> OwningRefMut<Box<O>, T> {
         OwningRefMut { reference: self.reference, owner: Box::new(self.owner) }
     }
@@ -970,7 +970,7 @@ where
     }
 }
 
-// ^ FIXME: Is a Into impl for calling into_inner() possible as well?
+// ^ FIXME: Is an Into impl for calling into_inner() possible as well?
 
 impl<O, T: ?Sized> Debug for OwningRef<O, T>
 where
@@ -1139,27 +1139,27 @@ impl<T: 'static> ToHandleMut for RefCell<T> {
 // about which handle creation to use (i.e., read() vs try_read()) as well as
 // what to do with error results.
 
-/// Typedef of a owning reference that uses a `Box` as the owner.
+/// Typedef of an owning reference that uses a `Box` as the owner.
 pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
-/// Typedef of a owning reference that uses a `Vec` as the owner.
+/// Typedef of an owning reference that uses a `Vec` as the owner.
 pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
-/// Typedef of a owning reference that uses a `String` as the owner.
+/// Typedef of an owning reference that uses a `String` as the owner.
 pub type StringRef = OwningRef<String, str>;
 
-/// Typedef of a owning reference that uses a `Rc` as the owner.
+/// Typedef of an owning reference that uses a `Rc` as the owner.
 pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
-/// Typedef of a owning reference that uses a `Arc` as the owner.
+/// Typedef of an owning reference that uses an `Arc` as the owner.
 pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
 
-/// Typedef of a owning reference that uses a `Ref` as the owner.
+/// Typedef of an owning reference that uses a `Ref` as the owner.
 pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RefMut` as the owner.
+/// Typedef of an owning reference that uses a `RefMut` as the owner.
 pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
-/// Typedef of a owning reference that uses a `MutexGuard` as the owner.
+/// Typedef of an owning reference that uses a `MutexGuard` as the owner.
 pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RwLockReadGuard` as the owner.
+/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
 pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
-/// Typedef of a owning reference that uses a `RwLockWriteGuard` as the owner.
+/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
 pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
 
 /// Typedef of a mutable owning reference that uses a `Box` as the owner.
@@ -1219,11 +1219,11 @@ unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> {
     }
 }
 
-/// Typedef of a owning reference that uses an erased `Box` as the owner.
+/// Typedef of an owning reference that uses an erased `Box` as the owner.
 pub type ErasedBoxRef<U> = OwningRef<Box<dyn Erased>, U>;
-/// Typedef of a owning reference that uses an erased `Rc` as the owner.
+/// Typedef of an owning reference that uses an erased `Rc` as the owner.
 pub type ErasedRcRef<U> = OwningRef<Rc<dyn Erased>, U>;
-/// Typedef of a owning reference that uses an erased `Arc` as the owner.
+/// Typedef of an owning reference that uses an erased `Arc` as the owner.
 pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>;
 
 /// Typedef of a mutable owning reference that uses an erased `Box` as the owner.
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index ef101c56ab5..0bbd0eda0c6 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -220,7 +220,7 @@ impl SelfProfilerRef {
         VerboseTimingGuard::start(message, self.generic_activity(event_label))
     }
 
-    /// Start profiling a extra verbose generic activity. Profiling continues until the
+    /// Start profiling an extra verbose generic activity. Profiling continues until the
     /// VerboseTimingGuard returned from this call is dropped. In addition to recording
     /// a measureme event, "extra verbose" generic activities also print a timing entry to
     /// stdout if the compiler is invoked with -Ztime-passes.
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 722ce6b6367..f99ca53ab25 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -14,7 +14,7 @@
 //!
 //! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise.
 //!
-//! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync
+//! `rustc_erase_owner!` erases an OwningRef owner into Erased or Erased + Send + Sync
 //! depending on the value of cfg!(parallel_compiler).
 
 use crate::owning_ref::{Erased, OwningRef};
diff --git a/compiler/rustc_data_structures/src/tiny_list.rs b/compiler/rustc_data_structures/src/tiny_list.rs
index f88bcc29481..9b07f86846e 100644
--- a/compiler/rustc_data_structures/src/tiny_list.rs
+++ b/compiler/rustc_data_structures/src/tiny_list.rs
@@ -5,7 +5,7 @@
 //!
 //! - If you have a list that rarely stores more than one element, then this
 //!   data-structure can store the element without allocating and only uses as
-//!   much space as a `Option<(T, usize)>`. If T can double as the `Option`
+//!   much space as an `Option<(T, usize)>`. If T can double as the `Option`
 //!   discriminant, it will even only be as large as `T, usize`.
 //!
 //! If you expect to store more than 1 element in the common case, steer clear
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 07c864c93a1..25777f4133b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1623,7 +1623,7 @@ impl EmitterWriter {
             let line_start = sm.lookup_char_pos(parts[0].span.lo()).line;
             draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
             let mut lines = complete.lines();
-            for (line_pos, (line, parts)) in
+            for (line_pos, (line, highlight_parts)) in
                 lines.by_ref().zip(highlights).take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate()
             {
                 // Print the span column to avoid confusion
@@ -1658,7 +1658,7 @@ impl EmitterWriter {
                     );
                     buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
                 } else if is_multiline {
-                    match &parts[..] {
+                    match &highlight_parts[..] {
                         [SubstitutionHighlight { start: 0, end }] if *end == line.len() => {
                             buffer.puts(row_num, max_line_num_len + 1, "+ ", Style::Addition);
                         }
@@ -1676,16 +1676,24 @@ impl EmitterWriter {
                 // print the suggestion
                 buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
 
-                if is_multiline {
-                    for SubstitutionHighlight { start, end } in parts {
-                        buffer.set_style_range(
-                            row_num,
-                            max_line_num_len + 3 + start,
-                            max_line_num_len + 3 + end,
-                            Style::Addition,
-                            true,
-                        );
-                    }
+                // Colorize addition/replacements with green.
+                for &SubstitutionHighlight { start, end } in highlight_parts {
+                    // Account for tabs when highlighting (#87972).
+                    let tabs: usize = line
+                        .chars()
+                        .take(start)
+                        .map(|ch| match ch {
+                            '\t' => 3,
+                            _ => 0,
+                        })
+                        .sum();
+                    buffer.set_style_range(
+                        row_num,
+                        max_line_num_len + 3 + start + tabs,
+                        max_line_num_len + 3 + end + tabs,
+                        Style::Addition,
+                        true,
+                    );
                 }
                 row_num += 1;
             }
@@ -1723,13 +1731,6 @@ impl EmitterWriter {
                     assert!(underline_start >= 0 && underline_end >= 0);
                     let padding: usize = max_line_num_len + 3;
                     for p in underline_start..underline_end {
-                        // Colorize addition/replacements with green.
-                        buffer.set_style(
-                            row_num - 1,
-                            (padding as isize + p) as usize,
-                            Style::Addition,
-                            true,
-                        );
                         if !show_diff {
                             // If this is a replacement, underline with `^`, if this is an addition
                             // underline with `+`.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index ec29d8016dd..a48d4fe8bb5 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -283,6 +283,9 @@ impl CodeSuggestion {
                 let mut buf = String::new();
 
                 let mut line_highlight = vec![];
+                // We need to keep track of the difference between the existing code and the added
+                // or deleted code in order to point at the correct column *after* substitution.
+                let mut acc = 0;
                 for part in &substitution.parts {
                     let cur_lo = sm.lookup_char_pos(part.span.lo());
                     if prev_hi.line == cur_lo.line {
@@ -290,9 +293,11 @@ impl CodeSuggestion {
                             push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
                         while count > 0 {
                             highlights.push(std::mem::take(&mut line_highlight));
+                            acc = 0;
                             count -= 1;
                         }
                     } else {
+                        acc = 0;
                         highlights.push(std::mem::take(&mut line_highlight));
                         let mut count = push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
                         while count > 0 {
@@ -316,18 +321,43 @@ impl CodeSuggestion {
                         }
                     }
                     // Add a whole line highlight per line in the snippet.
+                    let len: isize = part
+                        .snippet
+                        .split('\n')
+                        .next()
+                        .unwrap_or(&part.snippet)
+                        .chars()
+                        .map(|c| match c {
+                            '\t' => 4,
+                            _ => 1,
+                        })
+                        .sum();
                     line_highlight.push(SubstitutionHighlight {
-                        start: cur_lo.col.0,
-                        end: cur_lo.col.0
-                            + part.snippet.split('\n').next().unwrap_or(&part.snippet).len(),
+                        start: (cur_lo.col.0 as isize + acc) as usize,
+                        end: (cur_lo.col.0 as isize + acc + len) as usize,
                     });
+                    buf.push_str(&part.snippet);
+                    let cur_hi = sm.lookup_char_pos(part.span.hi());
+                    if prev_hi.line == cur_lo.line {
+                        // Account for the difference between the width of the current code and the
+                        // snippet being suggested, so that the *later* suggestions are correctly
+                        // aligned on the screen.
+                        acc += len as isize - (cur_hi.col.0 - cur_lo.col.0) as isize;
+                    }
+                    prev_hi = cur_hi;
+                    prev_line = sf.get_line(prev_hi.line - 1);
                     for line in part.snippet.split('\n').skip(1) {
+                        acc = 0;
                         highlights.push(std::mem::take(&mut line_highlight));
-                        line_highlight.push(SubstitutionHighlight { start: 0, end: line.len() });
+                        let end: usize = line
+                            .chars()
+                            .map(|c| match c {
+                                '\t' => 4,
+                                _ => 1,
+                            })
+                            .sum();
+                        line_highlight.push(SubstitutionHighlight { start: 0, end });
                     }
-                    buf.push_str(&part.snippet);
-                    prev_hi = sm.lookup_char_pos(part.span.hi());
-                    prev_line = sf.get_line(prev_hi.line - 1);
                 }
                 highlights.push(std::mem::take(&mut line_highlight));
                 let only_capitalization = is_case_difference(sm, &buf, bounding_span);
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 3ed99eab95c..a4b7bdd9155 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -654,10 +654,7 @@ pub enum SyntaxExtensionKind {
     /// A trivial attribute "macro" that does nothing,
     /// only keeps the attribute and marks it as inert,
     /// thus making it ineligible for further expansion.
-    NonMacroAttr {
-        /// Suppresses the `unused_attributes` lint for this attribute.
-        mark_used: bool,
-    },
+    NonMacroAttr,
 
     /// A token-based derive macro.
     Derive(
@@ -706,7 +703,7 @@ impl SyntaxExtension {
             SyntaxExtensionKind::Bang(..) | SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang,
             SyntaxExtensionKind::Attr(..)
             | SyntaxExtensionKind::LegacyAttr(..)
-            | SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr,
+            | SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
             SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
                 MacroKind::Derive
             }
@@ -812,8 +809,8 @@ impl SyntaxExtension {
         SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition)
     }
 
-    pub fn non_macro_attr(mark_used: bool, edition: Edition) -> SyntaxExtension {
-        SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
+    pub fn non_macro_attr(edition: Edition) -> SyntaxExtension {
+        SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
     }
 
     pub fn expn_data(
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index f9140609c0f..e09893f7f38 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -5,7 +5,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind};
 use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
 use rustc_ast::tokenstream::{DelimSpan, Spacing};
 use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
-use rustc_ast::{self as ast, AstLike, AttrItem, AttrStyle, Attribute, MetaItem};
+use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::map_in_place::MapInPlace;
@@ -14,7 +14,7 @@ use rustc_feature::{Feature, Features, State as FeatureState};
 use rustc_feature::{
     ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
 };
-use rustc_parse::{parse_in, validate_attr};
+use rustc_parse::validate_attr;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::edition::{Edition, ALL_EDITIONS};
@@ -75,7 +75,7 @@ fn get_features(
     // Process the edition umbrella feature-gates first, to ensure
     // `edition_enabled_features` is completed before it's queried.
     for attr in krate_attrs {
-        if !sess.check_name(attr, sym::feature) {
+        if !attr.has_name(sym::feature) {
             continue;
         }
 
@@ -108,7 +108,7 @@ fn get_features(
     }
 
     for attr in krate_attrs {
-        if !sess.check_name(attr, sym::feature) {
+        if !attr.has_name(sym::feature) {
             continue;
         }
 
@@ -237,11 +237,6 @@ macro_rules! configure {
     };
 }
 
-const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
-const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
-    <https://doc.rust-lang.org/reference/conditional-compilation.html\
-    #the-cfg_attr-attribute>";
-
 impl<'a> StripUnconfigured<'a> {
     pub fn configure<T: AstLike>(&mut self, mut node: T) -> Option<T> {
         self.process_cfg_attrs(&mut node);
@@ -349,19 +344,17 @@ impl<'a> StripUnconfigured<'a> {
             return vec![attr];
         }
 
-        let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
-            None => return vec![],
-            Some(r) => r,
-        };
+        let (cfg_predicate, expanded_attrs) =
+            match rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) {
+                None => return vec![],
+                Some(r) => r,
+            };
 
         // Lint on zero attributes in source.
         if expanded_attrs.is_empty() {
             return vec![attr];
         }
 
-        // At this point we know the attribute is considered used.
-        self.sess.mark_attr_used(&attr);
-
         if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) {
             return vec![];
         }
@@ -415,46 +408,10 @@ impl<'a> StripUnconfigured<'a> {
             .collect()
     }
 
-    fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
-        match attr.get_normal_item().args {
-            ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
-                let msg = "wrong `cfg_attr` delimiters";
-                validate_attr::check_meta_bad_delim(&self.sess.parse_sess, dspan, delim, msg);
-                match parse_in(&self.sess.parse_sess, tts.clone(), "`cfg_attr` input", |p| {
-                    p.parse_cfg_attr()
-                }) {
-                    Ok(r) => return Some(r),
-                    Err(mut e) => {
-                        e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
-                            .note(CFG_ATTR_NOTE_REF)
-                            .emit();
-                    }
-                }
-            }
-            _ => self.error_malformed_cfg_attr_missing(attr.span),
-        }
-        None
-    }
-
-    fn error_malformed_cfg_attr_missing(&self, span: Span) {
-        self.sess
-            .parse_sess
-            .span_diagnostic
-            .struct_span_err(span, "malformed `cfg_attr` attribute input")
-            .span_suggestion(
-                span,
-                "missing condition and attribute",
-                CFG_ATTR_GRAMMAR_HELP.to_string(),
-                Applicability::HasPlaceholders,
-            )
-            .note(CFG_ATTR_NOTE_REF)
-            .emit();
-    }
-
     /// Determines if a node with the given attributes should be included in this configuration.
     fn in_cfg(&self, attrs: &[Attribute]) -> bool {
         attrs.iter().all(|attr| {
-            if !is_cfg(self.sess, attr) {
+            if !is_cfg(attr) {
                 return true;
             }
             let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
@@ -500,7 +457,7 @@ impl<'a> StripUnconfigured<'a> {
         //
         // N.B., this is intentionally not part of the visit_expr() function
         //     in order for filter_map_expr() to be able to avoid this check
-        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(self.sess, a)) {
+        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
             let msg = "removing an expression is not supported in this position";
             self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
         }
@@ -536,6 +493,6 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta
     }
 }
 
-fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
-    sess.check_name(attr, sym::cfg)
+fn is_cfg(attr: &Attribute) -> bool {
+    attr.has_name(sym::cfg)
 }
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 09beda33483..16e086e32f6 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -753,11 +753,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         }
                     }
                 }
-                SyntaxExtensionKind::NonMacroAttr { mark_used } => {
+                SyntaxExtensionKind::NonMacroAttr => {
                     self.cx.expanded_inert_attrs.mark(&attr);
-                    if *mark_used {
-                        self.cx.sess.mark_attr_used(&attr);
-                    }
                     item.visit_attrs(|attrs| attrs.insert(pos, attr));
                     fragment_kind.expect_from_annotatables(iter::once(item))
                 }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 9aee86c9e57..e0c62388fe0 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -535,7 +535,7 @@ pub fn compile_declarative_macro(
 
     valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses);
 
-    let (transparency, transparency_error) = attr::find_transparency(sess, &def.attrs, macro_rules);
+    let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
     match transparency_error {
         Some(TransparencyError::UnknownTransparency(value, span)) => {
             diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 5729384c0da..e2aa54a59b2 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -52,11 +52,6 @@ pub enum AttributeType {
     /// by the compiler before the unused_attribute check
     Normal,
 
-    /// Builtin attribute that may not be consumed by the compiler
-    /// before the unused_attribute check. These attributes
-    /// will be ignored by the unused_attribute lint
-    AssumedUsed,
-
     /// Builtin attribute that is only allowed at the crate level
     CrateLevel,
 }
@@ -186,7 +181,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"),
     ),
     // FIXME(Centril): This can be used on stable but shouldn't.
-    ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")),
+    ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name")),
 
     // Macros:
     ungated!(automatically_derived, Normal, template!(Word)),
@@ -206,7 +201,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
     ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
     ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
-    ungated!(must_use, AssumedUsed, template!(Word, NameValueStr: "reason")),
+    ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")),
     // FIXME(#14407)
     ungated!(
         deprecated, Normal,
@@ -224,16 +219,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     // ABI, linking, symbols, and FFI
     ungated!(
-        link, AssumedUsed,
+        link, Normal,
         template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#),
     ),
-    ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")),
-    ungated!(no_link, AssumedUsed, template!(Word)),
-    ungated!(repr, AssumedUsed, template!(List: "C")),
-    ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")),
-    ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")),
-    ungated!(no_mangle, AssumedUsed, template!(Word)),
-    ungated!(used, AssumedUsed, template!(Word)),
+    ungated!(link_name, Normal, template!(NameValueStr: "name")),
+    ungated!(no_link, Normal, template!(Word)),
+    ungated!(repr, Normal, template!(List: "C")),
+    ungated!(export_name, Normal, template!(NameValueStr: "name")),
+    ungated!(link_section, Normal, template!(NameValueStr: "name")),
+    ungated!(no_mangle, Normal, template!(Word)),
+    ungated!(used, Normal, template!(Word)),
 
     // Limits:
     ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")),
@@ -257,36 +252,36 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(path, Normal, template!(NameValueStr: "file")),
     ungated!(no_std, CrateLevel, template!(Word)),
     ungated!(no_implicit_prelude, Normal, template!(Word)),
-    ungated!(non_exhaustive, AssumedUsed, template!(Word)),
+    ungated!(non_exhaustive, Normal, template!(Word)),
 
     // Runtime
-    ungated!(windows_subsystem, AssumedUsed, template!(NameValueStr: "windows|console")),
+    ungated!(windows_subsystem, Normal, template!(NameValueStr: "windows|console")),
     ungated!(panic_handler, Normal, template!(Word)), // RFC 2070
 
     // Code generation:
-    ungated!(inline, AssumedUsed, template!(Word, List: "always|never")),
-    ungated!(cold, AssumedUsed, template!(Word)),
-    ungated!(no_builtins, AssumedUsed, template!(Word)),
-    ungated!(target_feature, AssumedUsed, template!(List: r#"enable = "name""#)),
-    ungated!(track_caller, AssumedUsed, template!(Word)),
+    ungated!(inline, Normal, template!(Word, List: "always|never")),
+    ungated!(cold, Normal, template!(Word)),
+    ungated!(no_builtins, Normal, template!(Word)),
+    ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)),
+    ungated!(track_caller, Normal, template!(Word)),
     gated!(
-        no_sanitize, AssumedUsed,
+        no_sanitize, Normal,
         template!(List: "address, memory, thread"),
         experimental!(no_sanitize)
     ),
-    gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)),
+    gated!(no_coverage, Normal, template!(Word), experimental!(no_coverage)),
 
     // FIXME: #14408 assume docs are used since rustdoc looks at them.
-    ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")),
+    ungated!(doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string")),
 
     // ==========================================================================
     // Unstable attributes:
     // ==========================================================================
 
     // Linking:
-    gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)),
+    gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)),
     gated!(
-        link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib,
+        link_ordinal, Normal, template!(List: "ordinal"), raw_dylib,
         experimental!(link_ordinal)
     ),
 
@@ -311,23 +306,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "custom test frameworks are an unstable feature",
     ),
     // RFC #1268
-    gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)),
+    gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)),
     gated!(
-        thread_local, AssumedUsed, template!(Word),
+        thread_local, Normal, template!(Word),
         "`#[thread_local]` is an experimental feature, and does not currently handle destructors",
     ),
     gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)),
     // RFC 2412
     gated!(
-        optimize, AssumedUsed, template!(List: "size|speed"), optimize_attribute,
+        optimize, Normal, template!(List: "size|speed"), optimize_attribute,
         experimental!(optimize),
     ),
     // RFC 2867
-    gated!(instruction_set, AssumedUsed, template!(List: "set"), isa_attribute, experimental!(instruction_set)),
+    gated!(instruction_set, Normal, template!(List: "set"), isa_attribute, experimental!(instruction_set)),
 
-    gated!(ffi_returns_twice, AssumedUsed, template!(Word), experimental!(ffi_returns_twice)),
-    gated!(ffi_pure, AssumedUsed, template!(Word), experimental!(ffi_pure)),
-    gated!(ffi_const, AssumedUsed, template!(Word), experimental!(ffi_const)),
+    gated!(ffi_returns_twice, Normal, template!(Word), experimental!(ffi_returns_twice)),
+    gated!(ffi_pure, Normal, template!(Word), experimental!(ffi_pure)),
+    gated!(ffi_const, Normal, template!(Word), experimental!(ffi_const)),
     gated!(
         register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),
         experimental!(register_attr),
@@ -337,10 +332,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         experimental!(register_tool),
     ),
 
-    gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)),
+    gated!(cmse_nonsecure_entry, Normal, template!(Word), experimental!(cmse_nonsecure_entry)),
     // RFC 2632
     gated!(
-        default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl,
+        default_method_body_is_const, Normal, template!(Word), const_trait_impl,
         "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
         as `const`, which may be removed or renamed in the future."
     ),
@@ -353,26 +348,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // FIXME(#14407) -- only looked at on-demand so we can't
     // guarantee they'll have already been checked.
     ungated!(
-        rustc_deprecated, AssumedUsed,
+        rustc_deprecated, Normal,
         template!(List: r#"since = "version", reason = "...""#)
     ),
     // FIXME(#14407)
-    ungated!(stable, AssumedUsed, template!(List: r#"feature = "name", since = "version""#)),
+    ungated!(stable, Normal, template!(List: r#"feature = "name", since = "version""#)),
     // FIXME(#14407)
     ungated!(
-        unstable, AssumedUsed,
+        unstable, Normal,
         template!(List: r#"feature = "name", reason = "...", issue = "N""#),
     ),
     // FIXME(#14407)
-    ungated!(rustc_const_unstable, AssumedUsed, template!(List: r#"feature = "name""#)),
+    ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#)),
     // FIXME(#14407)
-    ungated!(rustc_const_stable, AssumedUsed, template!(List: r#"feature = "name""#)),
+    ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#)),
     gated!(
-        allow_internal_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."),
+        allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
         "allow_internal_unstable side-steps feature gating and stability checks",
     ),
     gated!(
-        rustc_allow_const_fn_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."),
+        rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
         "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
     ),
     gated!(
@@ -384,7 +379,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes: Type system related:
     // ==========================================================================
 
-    gated!(fundamental, AssumedUsed, template!(Word), experimental!(fundamental)),
+    gated!(fundamental, Normal, template!(Word), experimental!(fundamental)),
     gated!(
         may_dangle, Normal, template!(Word), dropck_eyepatch,
         "`may_dangle` has unstable semantics and may be removed in the future",
@@ -394,26 +389,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes: Runtime related:
     // ==========================================================================
 
-    rustc_attr!(rustc_allocator, AssumedUsed, template!(Word), IMPL_DETAIL),
-    rustc_attr!(rustc_allocator_nounwind, AssumedUsed, template!(Word), IMPL_DETAIL),
+    rustc_attr!(rustc_allocator, Normal, template!(Word), IMPL_DETAIL),
+    rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), IMPL_DETAIL),
     gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)),
     gated!(
-        default_lib_allocator, AssumedUsed, template!(Word), allocator_internals,
+        default_lib_allocator, Normal, template!(Word), allocator_internals,
         experimental!(default_lib_allocator),
     ),
     gated!(
         needs_allocator, Normal, template!(Word), allocator_internals,
         experimental!(needs_allocator),
     ),
-    gated!(panic_runtime, AssumedUsed, template!(Word), experimental!(panic_runtime)),
-    gated!(needs_panic_runtime, AssumedUsed, template!(Word), experimental!(needs_panic_runtime)),
+    gated!(panic_runtime, Normal, template!(Word), experimental!(panic_runtime)),
+    gated!(needs_panic_runtime, Normal, template!(Word), experimental!(needs_panic_runtime)),
     gated!(
-        compiler_builtins, AssumedUsed, template!(Word),
+        compiler_builtins, Normal, template!(Word),
         "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
-        profiler_runtime, AssumedUsed, template!(Word),
+        profiler_runtime, Normal, template!(Word),
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
     ),
@@ -423,23 +418,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
 
     gated!(
-        linkage, AssumedUsed, template!(NameValueStr: "external|internal|..."),
+        linkage, Normal, template!(NameValueStr: "external|internal|..."),
         "the `linkage` attribute is experimental and not portable across platforms",
     ),
-    rustc_attr!(rustc_std_internal_symbol, AssumedUsed, template!(Word), INTERNAL_UNSTABLE),
+    rustc_attr!(rustc_std_internal_symbol, Normal, template!(Word), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Macro related:
     // ==========================================================================
 
     rustc_attr!(
-        rustc_builtin_macro, AssumedUsed,
+        rustc_builtin_macro, Normal,
         template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"),
         IMPL_DETAIL,
     ),
     rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE),
     rustc_attr!(
-        rustc_macro_transparency, AssumedUsed,
+        rustc_macro_transparency, Normal,
         template!(NameValueStr: "transparent|semitransparent|opaque"),
         "used internally for testing macro hygiene",
     ),
@@ -449,7 +444,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
 
     rustc_attr!(
-        rustc_on_unimplemented, AssumedUsed,
+        rustc_on_unimplemented, Normal,
         template!(
             List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
             NameValueStr: "message"
@@ -457,31 +452,31 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         INTERNAL_UNSTABLE
     ),
     // Enumerates "identity-like" conversion methods to suggest on type mismatch.
-    rustc_attr!(rustc_conversion_suggestion, AssumedUsed, template!(Word), INTERNAL_UNSTABLE),
+    rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Const related:
     // ==========================================================================
 
-    rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL),
-    rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE),
+    rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL),
+    rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Layout related:
     // ==========================================================================
 
     rustc_attr!(
-        rustc_layout_scalar_valid_range_start, AssumedUsed, template!(List: "value"),
+        rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"),
         "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
         niche optimizations in libcore and will never be stable",
     ),
     rustc_attr!(
-        rustc_layout_scalar_valid_range_end, AssumedUsed, template!(List: "value"),
+        rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"),
         "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
         niche optimizations in libcore and will never be stable",
     ),
     rustc_attr!(
-        rustc_nonnull_optimization_guaranteed, AssumedUsed, template!(Word),
+        rustc_nonnull_optimization_guaranteed, Normal, template!(Word),
         "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
         niche optimizations in libcore and will never be stable",
     ),
@@ -506,7 +501,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     gated!(
         // Used in resolve:
-        prelude_import, AssumedUsed, template!(Word),
+        prelude_import, Normal, template!(Word),
         "`#[prelude_import]` is for use by rustc only",
     ),
     gated!(
@@ -514,7 +509,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         "unboxed_closures are still evolving",
     ),
     rustc_attr!(
-        rustc_inherit_overflow_checks, AssumedUsed, template!(Word),
+        rustc_inherit_overflow_checks, Normal, template!(Word),
         "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
         overflow checking behavior of several libcore functions that are inlined \
         across crates and will never be stable",
@@ -556,41 +551,41 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
     rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
     rustc_attr!(
-        TEST, rustc_error, AssumedUsed,
+        TEST, rustc_error, Normal,
         template!(Word, List: "delay_span_bug_from_inside_query")
     ),
-    rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_evaluate_where_clauses, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")),
-    rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")),
+    rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode")),
+    rustc_attr!(TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode")),
     rustc_attr!(
-        TEST, rustc_clean, AssumedUsed,
+        TEST, rustc_clean, Normal,
         template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
     ),
     rustc_attr!(
-        TEST, rustc_partition_reused, AssumedUsed,
+        TEST, rustc_partition_reused, Normal,
         template!(List: r#"cfg = "...", module = "...""#),
     ),
     rustc_attr!(
-        TEST, rustc_partition_codegened, AssumedUsed,
+        TEST, rustc_partition_codegened, Normal,
         template!(List: r#"cfg = "...", module = "...""#),
     ),
     rustc_attr!(
-        TEST, rustc_expected_cgu_reuse, AssumedUsed,
+        TEST, rustc_expected_cgu_reuse, Normal,
         template!(List: r#"cfg = "...", module = "...", kind = "...""#),
     ),
-    rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")),
-    rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)),
-    rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)),
+    rustc_attr!(TEST, rustc_synthetic, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ...")),
+    rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)),
     gated!(
-        omit_gdb_pretty_printer_section, AssumedUsed, template!(Word),
+        omit_gdb_pretty_printer_section, Normal, template!(Word),
         "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
     ),
 ];
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 4e233ed1457..888d1c1832b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -974,7 +974,7 @@ pub enum PatKind<'hir> {
     /// Invariant: `pats.len() >= 2`.
     Or(&'hir [Pat<'hir>]),
 
-    /// A path pattern for an unit struct/variant or a (maybe-associated) constant.
+    /// A path pattern for a unit struct/variant or a (maybe-associated) constant.
     Path(QPath<'hir>),
 
     /// A tuple pattern (e.g., `(a, b)`).
@@ -2323,7 +2323,7 @@ pub enum TyKind<'hir> {
     ///
     /// Type parameters may be stored in each `PathSegment`.
     Path(QPath<'hir>),
-    /// A opaque type definition itself. This is currently only used for the
+    /// An opaque type definition itself. This is currently only used for the
     /// `opaque type Foo: Trait` item that `impl Trait` in desugars to.
     ///
     /// The generic argument list contains the lifetimes (and in the future
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 1cbe3b12c82..7f153867596 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -313,7 +313,7 @@ pub trait Visitor<'v>: Sized {
     }
 
     /// When invoking `visit_all_item_likes()`, you need to supply an
-    /// item-like visitor. This method converts a "intra-visit"
+    /// item-like visitor. This method converts an "intra-visit"
     /// visitor into an item-like visitor that walks the entire tree.
     /// If you use this, you probably don't want to process the
     /// contents of nested item-like things, since the outer loop will
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index b5680beae14..0a558eb0555 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -123,7 +123,7 @@ impl IfThisChanged<'tcx> {
         let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) {
+            if attr.has_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
                     None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner),
@@ -138,7 +138,7 @@ impl IfThisChanged<'tcx> {
                     },
                 };
                 self.if_this_changed.push((attr.span, def_id.to_def_id(), dep_node));
-            } else if self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need) {
+            } else if attr.has_name(sym::rustc_then_this_would_need) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
                     Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs
index 8220eb6c657..a5f3e4553ce 100644
--- a/compiler/rustc_incremental/src/assert_module_sources.rs
+++ b/compiler/rustc_incremental/src/assert_module_sources.rs
@@ -57,27 +57,26 @@ struct AssertModuleSource<'tcx> {
 
 impl AssertModuleSource<'tcx> {
     fn check_attr(&self, attr: &ast::Attribute) {
-        let (expected_reuse, comp_kind) =
-            if self.tcx.sess.check_name(attr, sym::rustc_partition_reused) {
-                (CguReuse::PreLto, ComparisonKind::AtLeast)
-            } else if self.tcx.sess.check_name(attr, sym::rustc_partition_codegened) {
-                (CguReuse::No, ComparisonKind::Exact)
-            } else if self.tcx.sess.check_name(attr, sym::rustc_expected_cgu_reuse) {
-                match self.field(attr, sym::kind) {
-                    sym::no => (CguReuse::No, ComparisonKind::Exact),
-                    sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact),
-                    sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
-                    sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
-                    other => {
-                        self.tcx.sess.span_fatal(
-                            attr.span,
-                            &format!("unknown cgu-reuse-kind `{}` specified", other),
-                        );
-                    }
+        let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
+            (CguReuse::PreLto, ComparisonKind::AtLeast)
+        } else if attr.has_name(sym::rustc_partition_codegened) {
+            (CguReuse::No, ComparisonKind::Exact)
+        } else if attr.has_name(sym::rustc_expected_cgu_reuse) {
+            match self.field(attr, sym::kind) {
+                sym::no => (CguReuse::No, ComparisonKind::Exact),
+                sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact),
+                sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
+                sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
+                other => {
+                    self.tcx.sess.span_fatal(
+                        attr.span,
+                        &format!("unknown cgu-reuse-kind `{}` specified", other),
+                    );
                 }
-            } else {
-                return;
-            };
+            }
+        } else {
+            return;
+        };
 
         if !self.tcx.sess.opts.debugging_opts.query_dep_graph {
             self.tcx.sess.span_fatal(
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 9abd4eae914..c4dc0fbadc8 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -159,7 +159,7 @@ pub struct DirtyCleanVisitor<'tcx> {
 impl DirtyCleanVisitor<'tcx> {
     /// Possibly "deserialize" the attribute into a clean/dirty assertion
     fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> {
-        if !self.tcx.sess.check_name(attr, sym::rustc_clean) {
+        if !attr.has_name(sym::rustc_clean) {
             // skip: not rustc_clean/dirty
             return None;
         }
@@ -427,7 +427,7 @@ pub struct FindAllAttrs<'tcx> {
 
 impl FindAllAttrs<'tcx> {
     fn is_active_attr(&mut self, attr: &Attribute) -> bool {
-        if self.tcx.sess.check_name(attr, sym::rustc_clean) && check_config(self.tcx, attr) {
+        if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) {
             return true;
         }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 3d48d4c2fca..4830158c15a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1697,7 +1697,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
 
         // In some (most?) cases cause.body_id points to actual body, but in some cases
-        // it's a actual definition. According to the comments (e.g. in
+        // it's an actual definition. According to the comments (e.g. in
         // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
         // is relied upon by some other code. This might (or might not) need cleanup.
         let body_owner_def_id =
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 261c3471a98..042e6159aff 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -307,7 +307,7 @@ where
     /// relations between `'0` and `'a`).
     ///
     /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
-    /// -- in other words, it is always a (unresolved) inference
+    /// -- in other words, it is always an (unresolved) inference
     /// variable `vid` and a type `ty` that are being related, but the
     /// vid may appear either as the "a" type or the "b" type,
     /// depending on where it appears in the tuple. The trait
@@ -389,7 +389,7 @@ where
     }
 }
 
-/// When we instantiate a inference variable with a value in
+/// When we instantiate an inference variable with a value in
 /// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
 /// but the ordering may vary (depending on whether the inference
 /// variable was found on the `a` or `b` sides). Therefore, this trait
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 5adbfd469a4..af31ab0923d 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -186,7 +186,7 @@ pub enum GenericKind<'tcx> {
 ///        ('a: min) || ('b: min)
 ///     }
 ///
-/// This is described with a `AnyRegion('a, 'b)` node.
+/// This is described with an `AnyRegion('a, 'b)` node.
 #[derive(Debug, Clone)]
 pub enum VerifyBound<'tcx> {
     /// Given a kind K and a bound B, expands to a function like the
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 5ad2519a93c..89db8f464b4 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -96,7 +96,7 @@ impl Default for InferCtxtUndoLogs<'_> {
 }
 
 /// The UndoLogs trait defines how we undo a particular kind of action (of type T). We can undo any
-/// action that is convertable into a UndoLog (per the From impls above).
+/// action that is convertable into an UndoLog (per the From impls above).
 impl<'tcx, T> UndoLogs<T> for InferCtxtUndoLogs<'tcx>
 where
     UndoLog<'tcx>: From<T>,
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index d5c17ede214..b450c398946 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -28,7 +28,7 @@ pub use self::project::{
 pub use rustc_middle::traits::*;
 
 /// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
-/// which the "impl_source" must be found. The process of finding a "impl_source" is
+/// which the "impl_source" must be found. The process of finding an "impl_source" is
 /// called "resolving" the `Obligation`. This process consists of
 /// either identifying an `impl` (e.g., `impl Eq for i32`) that
 /// satisfies the obligation, or else finding a bound that is in
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 8a0964e6b9f..2f540395b2d 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -266,7 +266,7 @@ impl<'tcx> Queries<'tcx> {
         };
 
         let attrs = &*tcx.get_attrs(def_id);
-        let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error));
+        let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error));
         for attr in attrs {
             match attr.meta_item_list() {
                 // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`.
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 8b41a0ff176..6b64614363f 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -488,13 +488,13 @@ pub fn get_codegen_sysroot(
 }
 
 pub(crate) fn check_attr_crate_type(
-    sess: &Session,
+    _sess: &Session,
     attrs: &[ast::Attribute],
     lint_buffer: &mut LintBuffer,
 ) {
     // Unconditionally collect crate types from attributes to make them used
     for a in attrs.iter() {
-        if sess.check_name(a, sym::crate_type) {
+        if a.has_name(sym::crate_type) {
             if let Some(n) = a.value_str() {
                 if categorize_crate_type(n).is_some() {
                     return;
@@ -552,7 +552,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
     let attr_types: Vec<CrateType> = attrs
         .iter()
         .filter_map(|a| {
-            if session.check_name(a, sym::crate_type) {
+            if a.has_name(sym::crate_type) {
                 match a.value_str() {
                     Some(s) => categorize_crate_type(s),
                     _ => None,
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index b5e6d256a99..b64a891cb25 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -489,7 +489,7 @@ impl Cursor<'_> {
         // Start is already eaten, eat the rest of identifier.
         self.eat_while(is_id_continue);
         // Known prefixes must have been handled earlier. So if
-        // we see a prefix here, it is definitely a unknown prefix.
+        // we see a prefix here, it is definitely an unknown prefix.
         match self.first() {
             '#' | '"' | '\'' => UnknownPrefix,
             _ => Ident,
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5a72db7752d..afa2cfca188 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -46,7 +46,6 @@ use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
 use rustc_session::lint::FutureIncompatibilityReason;
-use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -344,7 +343,7 @@ impl UnsafeCode {
 
 impl EarlyLintPass for UnsafeCode {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
-        if cx.sess().check_name(attr, sym::allow_internal_unsafe) {
+        if attr.has_name(sym::allow_internal_unsafe) {
             self.report_unsafe(cx, attr.span, |lint| {
                 lint.build(
                     "`allow_internal_unsafe` allows defining \
@@ -492,12 +491,12 @@ pub struct MissingDoc {
 
 impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
 
-fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool {
+fn has_doc(attr: &ast::Attribute) -> bool {
     if attr.is_doc_comment() {
         return true;
     }
 
-    if !sess.check_name(attr, sym::doc) {
+    if !attr.has_name(sym::doc) {
         return false;
     }
 
@@ -554,7 +553,7 @@ impl MissingDoc {
         }
 
         let attrs = cx.tcx.get_attrs(def_id.to_def_id());
-        let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
+        let has_doc = attrs.iter().any(has_doc);
         if !has_doc {
             cx.struct_span_lint(
                 MISSING_DOCS,
@@ -568,10 +567,10 @@ impl MissingDoc {
 }
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
-    fn enter_lint_attrs(&mut self, cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
+    fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden()
             || attrs.iter().any(|attr| {
-                cx.sess().check_name(attr, sym::doc)
+                attr.has_name(sym::doc)
                     && match attr.meta_item_list() {
                         None => false,
                         Some(l) => attr::list_contains_name(&l, sym::hidden),
@@ -595,7 +594,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
             }
 
             let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
-            let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
+            let has_doc = attrs.iter().any(has_doc);
             if !has_doc {
                 cx.struct_span_lint(
                     MISSING_DOCS,
@@ -999,7 +998,7 @@ impl EarlyLintPass for DeprecatedAttr {
                 return;
             }
         }
-        if cx.sess().check_name(attr, sym::no_start) || cx.sess().check_name(attr, sym::crate_id) {
+        if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
             let path_str = pprust::path_to_string(&attr.get_normal_item().path);
             let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str);
             lint_deprecated_attr(cx, attr, &msg, None);
@@ -1028,7 +1027,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
 
         let span = sugared_span.take().unwrap_or(attr.span);
 
-        if is_doc_comment || cx.sess().check_name(attr, sym::doc) {
+        if is_doc_comment || attr.has_name(sym::doc) {
             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
                 let mut err = lint.build("unused doc comment");
                 err.span_label(
@@ -1301,7 +1300,7 @@ declare_lint_pass!(
 
 impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
     fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
-        if cx.sess().check_name(attr, sym::feature) {
+        if attr.has_name(sym::feature) {
             if let Some(items) = attr.meta_item_list() {
                 for item in items {
                     cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
@@ -2771,7 +2770,7 @@ impl ClashingExternDeclarations {
                     overridden_link_name,
                     tcx.get_attrs(fi.def_id.to_def_id())
                         .iter()
-                        .find(|at| tcx.sess.check_name(at, sym::link_name))
+                        .find(|at| at.has_name(sym::link_name))
                         .unwrap()
                         .span,
                 )
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index bca3023664a..e6cbfa0c9e2 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -236,8 +236,6 @@ impl<'s> LintLevelsBuilder<'s> {
                 Some(lvl) => lvl,
             };
 
-            self.sess.mark_attr_used(attr);
-
             let mut metas = unwrap_or!(attr.meta_item_list(), continue);
 
             if metas.is_empty() {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 0ffcd0154de..c4008e77bab 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -151,8 +151,6 @@ macro_rules! late_lint_passes {
                 // FIXME: Look into regression when this is used as a module lint
                 // May Depend on constants elsewhere
                 UnusedBrokenConst: UnusedBrokenConst,
-                // Uses attr::is_used which is untracked, can't be an incremental module pass.
-                UnusedAttributes: UnusedAttributes::new(),
                 // Needs to run after UnusedAttributes as it marks all `feature` attributes as used.
                 UnstableFeatures: UnstableFeatures,
                 // Tracks state across modules
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 7f71923c91a..03344973bb3 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -118,7 +118,7 @@ fn to_camel_case(s: &str) -> String {
         })
         .fold((String::new(), None), |(acc, prev): (String, Option<String>), next| {
             // separate two components with an underscore if their boundary cannot
-            // be distinguished using a uppercase/lowercase case distinction
+            // be distinguished using an uppercase/lowercase case distinction
             let join = if let Some(prev) = prev {
                 let l = prev.chars().last().unwrap();
                 let f = next.chars().next().unwrap();
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 34d342e6694..ef8aee8f64e 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -669,9 +669,7 @@ enum FfiResult<'tcx> {
 }
 
 crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool {
-    tcx.get_attrs(def.did)
-        .iter()
-        .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed))
+    tcx.get_attrs(def.did).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed))
 }
 
 /// `repr(transparent)` structs can have a single non-ZST field, this function returns that
@@ -1171,7 +1169,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     ty::Projection(..) => {
                         let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
 
-                        // If `ty` is a opaque type directly then `super_visit_with` won't invoke
+                        // If `ty` is an opaque type directly then `super_visit_with` won't invoke
                         // this function again.
                         if ty.has_opaque_types() {
                             self.visit_ty(ty)
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index f59ad0ac82d..be137884b4b 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -4,21 +4,16 @@ use rustc_ast as ast;
 use rustc_ast::util::parser;
 use rustc_ast::{ExprKind, StmtKind};
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, Applicability};
-use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
-use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
-use tracing::debug;
-
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
     /// `#[must_use]`.
@@ -308,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             descr_post_path: &str,
         ) -> bool {
             for attr in cx.tcx.get_attrs(def_id).iter() {
-                if cx.sess().check_name(attr, sym::must_use) {
+                if attr.has_name(sym::must_use) {
                     cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
                         let msg = format!(
                             "unused {}`{}`{} that must be used",
@@ -382,62 +377,6 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAttributes {
-    builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
-}
-
-impl UnusedAttributes {
-    pub fn new() -> Self {
-        UnusedAttributes { builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP }
-    }
-}
-
-impl_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
-
-impl<'tcx> LateLintPass<'tcx> for UnusedAttributes {
-    fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
-        debug!("checking attribute: {:?}", attr);
-
-        if attr.is_doc_comment() {
-            return;
-        }
-
-        let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name));
-
-        if let Some(&&(name, ty, ..)) = attr_info {
-            if let AttributeType::AssumedUsed = ty {
-                debug!("{:?} is AssumedUsed", name);
-                return;
-            }
-        }
-
-        if !cx.sess().is_attr_used(attr) {
-            debug!("emitting warning for: {:?}", attr);
-            cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| {
-                // Mark as used to avoid duplicate warnings.
-                cx.sess().mark_attr_used(attr);
-                lint.build("unused attribute").emit()
-            });
-            // Is it a builtin attribute that must be used at the crate level?
-            if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) {
-                cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| {
-                    let msg = match attr.style {
-                        ast::AttrStyle::Outer => {
-                            "crate-level attribute should be an inner attribute: add an exclamation \
-                             mark: `#![foo]`"
-                        }
-                        ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
-                    };
-                    lint.build(msg).emit()
-                });
-            }
-        } else {
-            debug!("Attr was used: {:?}", attr);
-        }
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum UnusedDelimsCtx {
     FunctionArg,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 467ec73663b..a1c507b4c84 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3042,6 +3042,7 @@ declare_lint_pass! {
         RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
         UNSUPPORTED_CALLING_CONVENTIONS,
         BREAK_WITH_LABEL_AND_LOOP,
+        UNUSED_ATTRIBUTES,
     ]
 }
 
@@ -3070,16 +3071,19 @@ declare_lint! {
 
 declare_lint! {
     /// The `rust_2021_incompatible_closure_captures` lint detects variables that aren't completely
-    /// captured in Rust 2021 and affect the Drop order of at least one path starting at this variable.
-    /// It can also detect when a variable implements a trait, but one of its field does not and
-    /// the field is captured by a closure and used with the assumption that said field implements
+    /// captured in Rust 2021, such that the `Drop` order of their fields may differ between
+    /// Rust 2018 and 2021.
+    ///
+    /// It can also detect when a variable implements a trait like `Send`, but one of its fields does not,
+    /// and the field is captured by a closure and used with the assumption that said field implements
     /// the same trait as the root variable.
     ///
     /// ### Example of drop reorder
     ///
     /// ```rust,compile_fail
-    /// # #![deny(rust_2021_incompatible_closure_captures)]
+    /// #![deny(rust_2021_incompatible_closure_captures)]
     /// # #![allow(unused)]
+    ///
     /// struct FancyInteger(i32);
     ///
     /// impl Drop for FancyInteger {
@@ -3133,8 +3137,8 @@ declare_lint! {
     /// ### Explanation
     ///
     /// In the above example, only `fptr.0` is captured in Rust 2021.
-    /// The field is of type *mut i32 which doesn't implement Send, making the code invalid as the
-    /// field cannot be sent between thread safely.
+    /// The field is of type `*mut i32`, which doesn't implement `Send`,
+    /// making the code invalid as the field cannot be sent between threads safely.
     pub RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
     Allow,
     "detects closures affected by Rust 2021 changes",
@@ -3254,6 +3258,7 @@ declare_lint! {
     ///
     /// ```rust,compile_fail
     /// #![deny(rust_2021_incompatible_or_patterns)]
+    ///
     /// macro_rules! match_any {
     ///     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
     ///         match $expr {
@@ -3275,7 +3280,7 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// In Rust 2021, the pat matcher will match new patterns, which include the | character.
+    /// In Rust 2021, the `pat` matcher will match additional patterns, which include the `|` character.
     pub RUST_2021_INCOMPATIBLE_OR_PATTERNS,
     Allow,
     "detects usage of old versions of or-patterns",
@@ -3320,8 +3325,8 @@ declare_lint! {
     /// In Rust 2021, one of the important introductions is the [prelude changes], which add
     /// `TryFrom`, `TryInto`, and `FromIterator` into the standard library's prelude. Since this
     /// results in an ambiguity as to which method/function to call when an existing `try_into`
-    ///  method is called via dot-call syntax or a `try_from`/`from_iter` associated function
-    ///  is called directly on a type.
+    /// method is called via dot-call syntax or a `try_from`/`from_iter` associated function
+    /// is called directly on a type.
     ///
     /// [prelude changes]: https://blog.rust-lang.org/inside-rust/2021/03/04/planning-rust-2021.html#prelude-changes
     pub RUST_2021_PRELUDE_COLLISIONS,
@@ -3371,7 +3376,7 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `unsupported_calling_conventions` lint is output whenever there is an use of the
+    /// The `unsupported_calling_conventions` lint is output whenever there is a use of the
     /// `stdcall`, `fastcall`, `thiscall`, `vectorcall` calling conventions (or their unwind
     /// variants) on targets that cannot meaningfully be supported for the requested target.
     ///
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 804b86cd864..5f0d8c46f20 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -44,8 +44,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
 
         // Process all of the #[link(..)]-style arguments
         let sess = &self.tcx.sess;
-        for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link))
-        {
+        for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
             let items = match m.meta_item_list() {
                 Some(item) => item,
                 None => continue,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 8bdd4313de4..4e591b28f60 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -62,7 +62,7 @@ crate struct CrateMetadata {
     // --- Some data pre-decoded from the metadata blob, usually for performance ---
     /// Properties of the whole crate.
     /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
-    /// lifetime is only used behind `Lazy`, and therefore acts like an
+    /// lifetime is only used behind `Lazy`, and therefore acts like a
     /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
     /// is being used to decode those values.
     root: CrateRoot<'static>,
diff --git a/compiler/rustc_middle/src/hir/map/blocks.rs b/compiler/rustc_middle/src/hir/map/blocks.rs
index 706c7900949..8efec8ef567 100644
--- a/compiler/rustc_middle/src/hir/map/blocks.rs
+++ b/compiler/rustc_middle/src/hir/map/blocks.rs
@@ -63,7 +63,7 @@ impl MaybeFnLike for hir::Expr<'_> {
     }
 }
 
-/// Carries either an FnLikeNode or a Expr, as these are the two
+/// Carries either an FnLikeNode or an Expr, as these are the two
 /// constructs that correspond to "code" (as in, something from which
 /// we can construct a control-flow graph).
 #[derive(Copy, Clone)]
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 7ea4902f4bc..20dcb670cd6 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -48,7 +48,7 @@ pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
 
 fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
     for attr in krate_attrs {
-        if !sess.check_name(attr, name) {
+        if !attr.has_name(name) {
             continue;
         }
 
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index ffa26b9f299..6c92c65a6dd 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -151,7 +151,7 @@ rustc_index::newtype_index! {
 static_assert_size!(ScopeData, 4);
 
 impl Scope {
-    /// Returns a item-local ID associated with this scope.
+    /// Returns an item-local ID associated with this scope.
     ///
     /// N.B., likely to be replaced as API is refined; e.g., pnkfelix
     /// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 4826c96000c..5d17bb9b15f 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -46,7 +46,7 @@ static_assert_size!(InterpErrorInfo<'_>, 8);
 /// Packages the kind of error we got from the const code interpreter
 /// up with a Rust-level backtrace of where the error occurred.
 /// These should always be constructed by calling `.into()` on
-/// a `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*`
+/// an `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*`
 /// macros for this.
 #[derive(Debug)]
 pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 62b71b10d5a..cc31d8c2c18 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -17,7 +17,7 @@ use super::{
 /// Represents the result of const evaluation via the `eval_to_allocation` query.
 #[derive(Copy, Clone, HashStable, TyEncodable, TyDecodable, Debug, Hash, Eq, PartialEq)]
 pub struct ConstAlloc<'tcx> {
-    // the value lives here, at offset 0, and that allocation definitely is a `AllocKind::Memory`
+    // the value lives here, at offset 0, and that allocation definitely is an `AllocKind::Memory`
     // (so you can use `AllocMap::unwrap_memory`).
     pub alloc_id: AllocId,
     pub ty: Ty<'tcx>,
@@ -113,7 +113,7 @@ impl<'tcx> ConstValue<'tcx> {
 }
 
 /// A `Scalar` represents an immediate, primitive value existing outside of a
-/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 16 bytes in
+/// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in
 /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
 /// of a simple value or a pointer into another `Allocation`
 ///
@@ -376,27 +376,27 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
         self.to_bits(sz)
     }
 
-    /// Converts the scalar to produce an `u8`. Fails if the scalar is a pointer.
+    /// Converts the scalar to produce a `u8`. Fails if the scalar is a pointer.
     pub fn to_u8(self) -> InterpResult<'static, u8> {
         self.to_unsigned_with_bit_width(8).map(|v| u8::try_from(v).unwrap())
     }
 
-    /// Converts the scalar to produce an `u16`. Fails if the scalar is a pointer.
+    /// Converts the scalar to produce a `u16`. Fails if the scalar is a pointer.
     pub fn to_u16(self) -> InterpResult<'static, u16> {
         self.to_unsigned_with_bit_width(16).map(|v| u16::try_from(v).unwrap())
     }
 
-    /// Converts the scalar to produce an `u32`. Fails if the scalar is a pointer.
+    /// Converts the scalar to produce a `u32`. Fails if the scalar is a pointer.
     pub fn to_u32(self) -> InterpResult<'static, u32> {
         self.to_unsigned_with_bit_width(32).map(|v| u32::try_from(v).unwrap())
     }
 
-    /// Converts the scalar to produce an `u64`. Fails if the scalar is a pointer.
+    /// Converts the scalar to produce a `u64`. Fails if the scalar is a pointer.
     pub fn to_u64(self) -> InterpResult<'static, u64> {
         self.to_unsigned_with_bit_width(64).map(|v| u64::try_from(v).unwrap())
     }
 
-    /// Converts the scalar to produce an `u128`. Fails if the scalar is a pointer.
+    /// Converts the scalar to produce a `u128`. Fails if the scalar is a pointer.
     pub fn to_u128(self) -> InterpResult<'static, u128> {
         self.to_unsigned_with_bit_width(128)
     }
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 6e819145976..74d303cee5d 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -265,7 +265,7 @@ impl BorrowKind {
             BorrowKind::Shared => hir::Mutability::Not,
 
             // We have no type corresponding to a unique imm borrow, so
-            // use `&mut`. It gives all the capabilities of an `&uniq`
+            // use `&mut`. It gives all the capabilities of a `&uniq`
             // and hence is a safe "over approximation".
             BorrowKind::Unique => hir::Mutability::Mut,
 
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 5516a045c1d..45ea3e3d9f3 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1202,7 +1202,7 @@ pub enum NonUseContext {
     StorageDead,
     /// User type annotation assertions for NLL.
     AscribeUserTy,
-    /// The data of an user variable, for debug info.
+    /// The data of a user variable, for debug info.
     VarDebugInfo,
 }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 85b1274da10..68de7f29193 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -648,7 +648,7 @@ rustc_queries! {
         }
     }
 
-    /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error.
+    /// HACK: when evaluated, this reports an "unsafe derive on repr(packed)" error.
     ///
     /// Unsafety checking is executed for each method separately, but we only want
     /// to emit this error once per derive. As there are some impls with multiple
@@ -1733,7 +1733,7 @@ rustc_queries! {
     }
 
     /// Performs an HIR-based well-formed check on the item with the given `HirId`. If
-    /// we get an `Umimplemented` error that matches the provided `Predicate`, return
+    /// we get an `Unimplemented` error that matches the provided `Predicate`, return
     /// the cause of the newly created obligation.
     ///
     /// This is only used by error-reporting code to get a better cause (in particular, a better
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 469da858ccf..457e80c1663 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -509,7 +509,7 @@ pub enum ImplSource<'tcx, N> {
     TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>),
 
     /// ImplSource automatically generated for a closure. The `DefId` is the ID
-    /// of the closure expression. This is a `ImplSource::UserDefined` in spirit, but the
+    /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the
     /// impl is generated by the compiler and does not appear in the source.
     Closure(ImplSourceClosureData<'tcx, N>),
 
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 3b7c201f3ee..62996bf4cbe 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -111,7 +111,7 @@ pub enum SelectionCandidate<'tcx> {
     ProjectionCandidate(usize),
 
     /// Implementation of a `Fn`-family trait by one of the anonymous types
-    /// generated for a `||` expression.
+    /// generated for an `||` expression.
     ClosureCandidate,
 
     /// Implementation of a `Generator` trait by one of the anonymous types
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 95159ea46ae..27927bcca72 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -209,7 +209,7 @@ impl<'tcx> AdtDef {
         self.flags.contains(AdtFlags::IS_UNION)
     }
 
-    /// Returns `true` if this is a enum.
+    /// Returns `true` if this is an enum.
     #[inline]
     pub fn is_enum(&self) -> bool {
         self.flags.contains(AdtFlags::IS_ENUM)
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index dd6ca9bd8c8..4eacb3c4176 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -434,7 +434,7 @@ impl BorrowKind {
             ImmBorrow => hir::Mutability::Not,
 
             // We have no type corresponding to a unique imm borrow, so
-            // use `&mut`. It gives all the capabilities of an `&uniq`
+            // use `&mut`. It gives all the capabilities of a `&uniq`
             // and hence is a safe "over approximation".
             UniqueImmBorrow => hir::Mutability::Mut,
         }
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index fb13614e4b3..36db258e92d 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -209,7 +209,7 @@ where
 impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
     #[allow(rustc::usage_of_ty_tykind)]
     fn decode(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> {
-        // Handle shorthands first, if we have an usize > 0x80.
+        // Handle shorthands first, if we have a usize > 0x80.
         if decoder.positioned_at_shorthand() {
             let pos = decoder.read_usize()?;
             assert!(pos >= SHORTHAND_OFFSET);
@@ -228,7 +228,7 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
 impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
     fn decode(decoder: &mut D) -> Result<ty::Binder<'tcx, ty::PredicateKind<'tcx>>, D::Error> {
         let bound_vars = Decodable::decode(decoder)?;
-        // Handle shorthands first, if we have an usize > 0x80.
+        // Handle shorthands first, if we have a usize > 0x80.
         Ok(ty::Binder::bind_with_vars(
             if decoder.positioned_at_shorthand() {
                 let pos = decoder.read_usize()?;
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 106b443ee3c..89542a1ebab 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1136,7 +1136,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
         let attrs = self.get_attrs(def_id);
         let get = |name| {
-            let attr = match attrs.iter().find(|a| self.sess.check_name(a, name)) {
+            let attr = match attrs.iter().find(|a| a.has_name(name)) {
                 Some(attr) => attr,
                 None => return Bound::Unbounded,
             };
@@ -1792,7 +1792,7 @@ pub mod tls {
         if context == 0 {
             f(None)
         } else {
-            // We could get a `ImplicitCtxt` pointer from another thread.
+            // We could get an `ImplicitCtxt` pointer from another thread.
             // Ensure that `ImplicitCtxt` is `Sync`.
             sync::assert_sync::<ImplicitCtxt<'_, '_>>();
 
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 119cb135046..77d82ee6eae 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -9,7 +9,7 @@ use crate::ty::{DefId, SubstsRef};
 
 mod def_id_forest;
 
-// The methods in this module calculate `DefIdForest`s of modules in which a
+// The methods in this module calculate `DefIdForest`s of modules in which an
 // `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
 //
 // # Example
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 3caca313ffd..80c99872dd7 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2571,14 +2571,14 @@ where
     /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
     ///
     /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance`
-    /// instead, where the instance is a `InstanceDef::Virtual`.
+    /// instead, where the instance is an `InstanceDef::Virtual`.
     fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
 
     /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
     /// direct calls to an `fn`.
     ///
     /// NB: that includes virtual calls, which are represented by "direct calls"
-    /// to a `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+    /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
     fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
 
     fn new_internal(
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 9fcf35b7320..62e093581b8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -865,7 +865,7 @@ impl<'tcx> Predicate<'tcx> {
 
 /// Represents the bounds declared on a particular set of type
 /// parameters. Should eventually be generalized into a flag list of
-/// where-clauses. You can obtain a `InstantiatedPredicates` list from a
+/// where-clauses. You can obtain an `InstantiatedPredicates` list from a
 /// `GenericPredicates` by using the `instantiate` method. Note that this method
 /// reflects an important semantic invariant of `InstantiatedPredicates`: while
 /// the `GenericPredicates` are expressed in terms of the bound type
@@ -1371,7 +1371,7 @@ bitflags! {
     }
 }
 
-/// Definition of a variant -- a struct's fields or a enum variant.
+/// Definition of a variant -- a struct's fields or an enum variant.
 #[derive(Debug, HashStable)]
 pub struct VariantDef {
     /// `DefId` that identifies the variant itself.
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index a1edb8071c4..8e0a2d4a28d 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -239,7 +239,7 @@ static_assert_size!(TyKind<'_>, 32);
 ///   implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait
 ///   specified above.
 /// - U is a type parameter representing the types of its upvars, tupled up
-///   (borrowed, if appropriate; that is, if an U field represents a by-ref upvar,
+///   (borrowed, if appropriate; that is, if a U field represents a by-ref upvar,
 ///    and the up-var has the type `Foo`, then that field of U will be `&Foo`).
 ///
 /// So, for example, given this function:
@@ -1323,7 +1323,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
 /// These are regions that are stored behind a binder and must be substituted
 /// with some concrete region before being used. There are two kind of
 /// bound regions: early-bound, which are bound in an item's `Generics`,
-/// and are substituted by a `InternalSubsts`, and late-bound, which are part of
+/// and are substituted by an `InternalSubsts`, and late-bound, which are part of
 /// higher-ranked types (e.g., `for<'a> fn(&'a ())`), and are substituted by
 /// the likes of `liberate_late_bound_regions`. The distinction exists
 /// because higher-ranked lifetimes aren't supported in all places. See [1][2].
@@ -1471,7 +1471,7 @@ pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'t
 impl<'tcx> ExistentialProjection<'tcx> {
     /// Extracts the underlying existential trait reference from this projection.
     /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
-    /// then this function would return a `exists T. T: Iterator` existential trait
+    /// then this function would return an `exists T. T: Iterator` existential trait
     /// reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
         let def_id = tcx.associated_item(self.item_def_id).container.id();
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 9b8d22d8eaf..84ec2e76c0b 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -22,7 +22,7 @@ use std::ops::ControlFlow;
 
 /// An entity in the Rust type system, which can be one of
 /// several kinds (types, lifetimes, and consts).
-/// To reduce memory usage, a `GenericArg` is a interned pointer,
+/// To reduce memory usage, a `GenericArg` is an interned pointer,
 /// with the lowest 2 bits being reserved for a tag to
 /// indicate the type (`Ty`, `Region`, or `Const`) it points to.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -204,12 +204,12 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
         GeneratorSubsts { substs: self }
     }
 
-    /// Creates a `InternalSubsts` that maps each generic parameter to itself.
+    /// Creates an `InternalSubsts` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
         Self::for_item(tcx, def_id, |param, _| tcx.mk_param_from_def(param))
     }
 
-    /// Creates a `InternalSubsts` for generic parameter definitions,
+    /// Creates an `InternalSubsts` for generic parameter definitions,
     /// by calling closures to obtain each kind.
     /// The closures get to observe the `InternalSubsts` as they're
     /// being built, which can be used to correctly
@@ -234,7 +234,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
         })
     }
 
-    fn fill_item<F>(
+    pub fn fill_item<F>(
         substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         tcx: TyCtxt<'tcx>,
         defs: &ty::Generics,
@@ -249,7 +249,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
         Self::fill_single(substs, defs, mk_kind)
     }
 
-    fn fill_single<F>(
+    pub fn fill_single<F>(
         substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         defs: &ty::Generics,
         mk_kind: &mut F,
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 9ba85e58018..a78206034f0 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -681,7 +681,7 @@ impl<'tcx> ty::TyS<'tcx> {
     }
 
     /// Checks whether values of this type `T` implement the `Freeze`
-    /// trait -- frozen types are those that do not contain a
+    /// trait -- frozen types are those that do not contain an
     /// `UnsafeCell` anywhere. This is a language concept used to
     /// distinguish "true immutability", which is relevant to
     /// optimization as well as the rules around static values. Note
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index a3ea1700634..6561fe37c1c 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -825,7 +825,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // We're going to want to traverse the first borrowed place to see if we can find
                 // field access to a union. If we find that, then we will keep the place of the
                 // union being accessed and the field that was being accessed so we can check the
-                // second borrowed place for the same union and a access to a different field.
+                // second borrowed place for the same union and an access to a different field.
                 for (place_base, elem) in first_borrowed_place.iter_projections().rev() {
                     match elem {
                         ProjectionElem::Field(field, _) if union_ty(place_base).is_some() => {
@@ -838,7 +838,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             })
             .and_then(|(target_base, target_field)| {
                 // With the place of a union and a field access into it, we traverse the second
-                // borrowed place and look for a access to a different field of the same union.
+                // borrowed place and look for an access to a different field of the same union.
                 for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
                     if let ProjectionElem::Field(field, _) = elem {
                         if let Some(union_ty) = union_ty(place_base) {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index 76de010d139..f40a2db330a 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -606,7 +606,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// Checks if a borrowed value was captured by a trait object. We do this by
     /// looking forward in the MIR from the reserve location and checking if we see
-    /// a unsized cast to a trait object on our data.
+    /// an unsized cast to a trait object on our data.
     fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
         // Start at the reserve location, find the place that we want to see cast to a trait object.
         let location = borrow.reserve_location;
@@ -666,7 +666,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             }
                             _ => {}
                         },
-                        // If we see a unsized cast, then if it is our data we should check
+                        // If we see an unsized cast, then if it is our data we should check
                         // whether it is being cast to a trait object.
                         Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, ty) => {
                             match operand {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
index 5932cb9e775..7be3f541487 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
                 // If the place is immutable then:
                 //
-                // - Either we deref a immutable ref to get to our final place.
+                // - Either we deref an immutable ref to get to our final place.
                 //    - We don't capture derefs of raw ptrs
                 // - Or the final place is immut because the root variable of the capture
                 //   isn't marked mut and we should suggest that to the user.
@@ -601,7 +601,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
                 let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
                 let root_hir_id = upvar_id.var_path.hir_id;
-                // we have a origin for this closure kind starting at this root variable so it's safe to unwrap here
+                // we have an origin for this closure kind starting at this root variable so it's safe to unwrap here
                 let captured_places = tables.closure_min_captures[id].get(&root_hir_id).unwrap();
 
                 let origin_projection = closure_kind_origin
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index fe9df41db45..cbb8f064bb8 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -423,7 +423,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         diag
     }
 
-    /// Reports a error specifically for when data is escaping a closure.
+    /// Reports an error specifically for when data is escaping a closure.
     ///
     /// ```text
     /// error: borrowed data escapes outside of function
@@ -566,7 +566,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         diag
     }
 
-    /// Adds a suggestion to errors where a `impl Trait` is returned.
+    /// Adds a suggestion to errors where an `impl Trait` is returned.
     ///
     /// ```text
     /// help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 9f7decad969..1dcb0676562 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -1241,7 +1241,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        // Special case: you can assign a immutable local variable
+        // Special case: you can assign an immutable local variable
         // (e.g., `x = ...`) so long as it has never been initialized
         // before (at this point in the flow).
         if let Some(local) = place_span.0.as_local() {
@@ -1702,7 +1702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // initialization state of `a.b` is all we need to inspect to
         // know if `a.b.c` is valid (and from that we infer that the
         // dereference and `.d` access is also valid, since we assume
-        // `a.b.c` is assigned a reference to a initialized and
+        // `a.b.c` is assigned a reference to an initialized and
         // well-formed record structure.)
 
         // Therefore, if we seek out the *closest* prefix for which we
@@ -1889,7 +1889,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
                 // assigning to (P->variant) is okay if assigning to `P` is okay
                 //
-                // FIXME: is this true even if P is a adt with a dtor?
+                // FIXME: is this true even if P is an adt with a dtor?
                 { }
 
                 // assigning to (*P) requires P to be initialized
@@ -2003,8 +2003,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
 
             if let Some((prefix, mpi)) = shortest_uninit_seen {
-                // Check for a reassignment into a uninitialized field of a union (for example,
-                // after a move out). In this case, do not report a error here. There is an
+                // Check for a reassignment into an uninitialized field of a union (for example,
+                // after a move out). In this case, do not report an error here. There is an
                 // exception, if this is the first assignment into the union (that is, there is
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
index c2ac1e289ce..3c9b4272b36 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
@@ -169,7 +169,7 @@ struct UniversalRegionIndices<'tcx> {
     /// used because trait matching and type-checking will feed us
     /// region constraints that reference those regions and we need to
     /// be able to map them our internal `RegionVid`. This is
-    /// basically equivalent to a `InternalSubsts`, except that it also
+    /// basically equivalent to an `InternalSubsts`, except that it also
     /// contains an entry for `ReStatic` -- it might be nice to just
     /// use a substs, and then handle `ReStatic` another way.
     indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs
index 3f9f558223b..7ff7c860591 100644
--- a/compiler/rustc_mir/src/dataflow/framework/engine.rs
+++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs
@@ -338,7 +338,7 @@ impl RustcMirAttrs {
 
         let rustc_mir_attrs = attrs
             .iter()
-            .filter(|attr| tcx.sess.check_name(attr, sym::rustc_mir))
+            .filter(|attr| attr.has_name(sym::rustc_mir))
             .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
 
         for attr in rustc_mir_attrs {
diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs
index 4ca757cf269..8a426cc1015 100644
--- a/compiler/rustc_mir/src/dataflow/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/mod.rs
@@ -30,12 +30,12 @@ pub struct MoveDataParamEnv<'tcx> {
 }
 
 pub(crate) fn has_rustc_mir_with(
-    sess: &Session,
+    _sess: &Session,
     attrs: &[ast::Attribute],
     name: Symbol,
 ) -> Option<MetaItem> {
     for attr in attrs {
-        if sess.check_name(attr, sym::rustc_mir) {
+        if attr.has_name(sym::rustc_mir) {
             let items = attr.meta_item_list();
             for item in items.iter().flat_map(|l| l.iter()) {
                 match item.meta_item() {
diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs
index baef2a5a52c..81f78621d14 100644
--- a/compiler/rustc_mir/src/interpret/operand.rs
+++ b/compiler/rustc_mir/src/interpret/operand.rs
@@ -295,7 +295,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// we can find the data.
     /// Note that for a given layout, this operation will either always fail or always
     /// succeed!  Whether it succeeds depends on whether the layout can be represented
-    /// in a `Immediate`, not on which data is stored there currently.
+    /// in an `Immediate`, not on which data is stored there currently.
     pub(crate) fn try_read_immediate(
         &self,
         src: &OpTy<'tcx, M::PointerTag>,
diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_mir/src/interpret/validity.rs
index 0c7f89c1a36..b0cd6405eb9 100644
--- a/compiler/rustc_mir/src/interpret/validity.rs
+++ b/compiler/rustc_mir/src/interpret/validity.rs
@@ -857,7 +857,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 // types above, in `visit_primitive`.
                 // In run-time mode, we accept pointers in here.  This is actually more
                 // permissive than a per-element check would be, e.g., we accept
-                // an &[u8] that contains a pointer even though bytewise checking would
+                // a &[u8] that contains a pointer even though bytewise checking would
                 // reject it.  However, that's good: We don't inherently want
                 // to reject those pointers, we just do not have the machinery to
                 // talk about parts of a pointer.
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
index 541c825416c..a559a6ce415 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
+++ b/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
@@ -455,7 +455,7 @@ fn mono_item_visibility(
         def_id
     } else {
         return if export_generics && is_generic {
-            // If it is a upstream monomorphization and we export generics, we must make
+            // If it is an upstream monomorphization and we export generics, we must make
             // it available to downstream crates.
             *can_be_internalized = false;
             default_visibility(tcx, def_id, true)
diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
index 30e758c7fdf..fea1adfa3d5 100644
--- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs
+++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs
@@ -204,11 +204,7 @@ fn emit_unused_generic_params_error<'tcx>(
     unused_parameters: &FiniteBitSet<u32>,
 ) {
     let base_def_id = tcx.closure_base_def_id(def_id);
-    if !tcx
-        .get_attrs(base_def_id)
-        .iter()
-        .any(|a| tcx.sess.check_name(a, sym::rustc_polymorphize_error))
-    {
+    if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) {
         return;
     }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index ddca22aebd2..8923d989b29 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -86,7 +86,7 @@ impl NonConstOp for FnCallNonConst {
     }
 }
 
-/// A call to a `#[unstable]` const fn or `#[rustc_const_unstable]` function.
+/// A call to an `#[unstable]` const fn or `#[rustc_const_unstable]` function.
 ///
 /// Contains the name of the feature that would allow the use of this function.
 #[derive(Debug)]
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index e02e41d6206..4578f04c034 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -145,7 +145,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
 
         // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
         // constants, instead of just checking for const-folding succeeding.
-        // That would require an uniform one-def no-mutation analysis
+        // That would require a uniform one-def no-mutation analysis
         // and RPO (or recursing when needing the value of a local).
         let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx);
         optimization_finder.visit_body(body);
diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir/src/transform/coverage/counters.rs
index 272a7bf9617..6726b669ff2 100644
--- a/compiler/rustc_mir/src/transform/coverage/counters.rs
+++ b/compiler/rustc_mir/src/transform/coverage/counters.rs
@@ -100,7 +100,7 @@ impl CoverageCounters {
         CounterValueReference::from(next)
     }
 
-    /// Expression IDs start from u32::MAX and go down because a Expression can reference
+    /// Expression IDs start from u32::MAX and go down because an Expression can reference
     /// (add or subtract counts) of both Counter regions and Expression regions. The counter
     /// expression operand IDs must be unique across both types.
     fn next_expression(&mut self) -> InjectedExpressionId {
diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir/src/transform/coverage/mod.rs
index 406a8832d26..f7fbea6ad53 100644
--- a/compiler/rustc_mir/src/transform/coverage/mod.rs
+++ b/compiler/rustc_mir/src/transform/coverage/mod.rs
@@ -334,7 +334,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
     /// process (via `take_counter()`).
     ///
     /// Any other counter associated with a `BasicCoverageBlock`, or its incoming edge, but not
-    /// associated with a `CoverageSpan`, should only exist if the counter is a `Expression`
+    /// associated with a `CoverageSpan`, should only exist if the counter is an `Expression`
     /// dependency (one of the expression operands). Collect them, and inject the additional
     /// counters into the MIR, without a reportable coverage span.
     fn inject_indirect_counters(
diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir/src/transform/rustc_peek.rs
index a6b8f20f6d4..f4a1b0ddba5 100644
--- a/compiler/rustc_mir/src/transform/rustc_peek.rs
+++ b/compiler/rustc_mir/src/transform/rustc_peek.rs
@@ -88,11 +88,11 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
 /// For each such call, determines what the dataflow bit-state is for
 /// the L-value corresponding to `expr`; if the bit-state is a 1, then
 /// that call to `rustc_peek` is ignored by the sanity check. If the
-/// bit-state is a 0, then this pass emits a error message saying
+/// bit-state is a 0, then this pass emits an error message saying
 /// "rustc_peek: bit not set".
 ///
 /// The intention is that one can write unit tests for dataflow by
-/// putting code into an UI test and using `rustc_peek` to
+/// putting code into a UI test and using `rustc_peek` to
 /// make observations about the results of dataflow static analyses.
 ///
 /// (If there are any calls to `rustc_peek` that do not match the
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index b2e03f13479..21c5a64f823 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -61,7 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     unpack!(this.expr_into_dest(destination, else_blk, &this.thir[else_opt]))
                 } else {
                     // Body of the `if` expression without an `else` clause must return `()`, thus
-                    // we implicitly generate a `else {}` if it is not specified.
+                    // we implicitly generate an `else {}` if it is not specified.
                     let correct_si = this.source_info(expr_span.shrink_to_hi());
                     this.cfg.push_assign_unit(else_blk, correct_si, destination, this.tcx);
                     else_blk
@@ -208,7 +208,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                     this.diverge_from(loop_block);
 
-                    // The “return” value of the loop body must always be an unit. We therefore
+                    // The “return” value of the loop body must always be a unit. We therefore
                     // introduce a unit temporary as the destination for the loop body.
                     let tmp = this.get_unit_temp();
                     // Execute the body, branching back to the test.
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 6e16ee94c50..a36af024ad8 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1936,7 +1936,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // }
             // ```
             //
-            // would yield a `arm_block` something like:
+            // would yield an `arm_block` something like:
             //
             // ```
             // StorageLive(_4);        // _4 is `x`
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 988cc625422..bfebe860971 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -700,7 +700,7 @@ fn construct_const<'a, 'tcx>(
     builder.finish()
 }
 
-/// Construct MIR for a item that has had errors in type checking.
+/// Construct MIR for an item that has had errors in type checking.
 ///
 /// This is required because we may still want to run MIR passes on an item
 /// with type errors, but normal MIR construction can't handle that in general.
@@ -885,7 +885,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let tcx_hir = tcx.hir();
         let hir_typeck_results = self.typeck_results;
 
-        // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
+        // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
         // indexed closure and we stored in a map called closure_min_captures in TypeckResults
         // with the closure's DefId. Here, we run through that vec of UpvarIds for
         // the given closure and use the necessary information to create upvar
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 6bbf1faf483..f1d882e1ddd 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -788,7 +788,7 @@ impl<'tcx> Cx<'tcx> {
                 self.user_substs_applied_to_ty_of_hir_id(hir_id)
             }
 
-            // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
+            // `Self` is used in expression as a tuple struct constructor or a unit struct constructor
             Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id),
 
             _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 5d4eb75155a..344006e9fb4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -762,7 +762,7 @@ impl<'p, 'tcx> SubPatSet<'p, 'tcx> {
                     for i in 0..*alt_count {
                         let sub_set = subpats.get(&i).unwrap_or(&SubPatSet::Empty);
                         if sub_set.is_empty() {
-                            // Found a unreachable subpattern.
+                            // Found an unreachable subpattern.
                             spans.push(expanded[i].span);
                         } else {
                             fill_spans(sub_set, spans);
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 611d72e61d0..07f972c2fa8 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -13,9 +13,10 @@ use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
 use rustc_ast::AstLike;
 use rustc_ast::Attribute;
+use rustc_ast::{AttrItem, MetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Diagnostic, FatalError, Level, PResult};
+use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::{FileName, SourceFile, Span};
 
@@ -324,3 +325,44 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
     let filename = FileName::macro_expansion_source_code(&source);
     parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
 }
+
+pub fn parse_cfg_attr(
+    attr: &Attribute,
+    parse_sess: &ParseSess,
+) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
+    match attr.get_normal_item().args {
+        ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
+            let msg = "wrong `cfg_attr` delimiters";
+            crate::validate_attr::check_meta_bad_delim(parse_sess, dspan, delim, msg);
+            match parse_in(parse_sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
+                Ok(r) => return Some(r),
+                Err(mut e) => {
+                    e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
+                        .note(CFG_ATTR_NOTE_REF)
+                        .emit();
+                }
+            }
+        }
+        _ => error_malformed_cfg_attr_missing(attr.span, parse_sess),
+    }
+    None
+}
+
+const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
+const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
+    <https://doc.rust-lang.org/reference/conditional-compilation.html\
+    #the-cfg_attr-attribute>";
+
+fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) {
+    parse_sess
+        .span_diagnostic
+        .struct_span_err(span, "malformed `cfg_attr` attribute input")
+        .span_suggestion(
+            span,
+            "missing condition and attribute",
+            CFG_ATTR_GRAMMAR_HELP.to_string(),
+            Applicability::HasPlaceholders,
+        )
+        .note(CFG_ATTR_NOTE_REF)
+        .emit();
+}
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index e1d0b84f419..9f06bdcc135 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -301,7 +301,7 @@ impl<'a> Parser<'a> {
         // If we 'broke' the last token (e.g. breaking a '>>' token to two '>' tokens),
         // then extend the range of captured tokens to include it, since the parser
         // was not actually bumped past it. When the `LazyTokenStream` gets converted
-        // into a `AttrAnnotatedTokenStream`, we will create the proper token.
+        // into an `AttrAnnotatedTokenStream`, we will create the proper token.
         if self.token_cursor.break_last_token {
             assert_eq!(
                 trailing,
@@ -320,7 +320,7 @@ impl<'a> Parser<'a> {
         } else {
             // Grab any replace ranges that occur *inside* the current AST node.
             // We will perform the actual replacement when we convert the `LazyTokenStream`
-            // to a `AttrAnnotatedTokenStream`
+            // to an `AttrAnnotatedTokenStream`
             let start_calls: u32 = cursor_snapshot_next_calls.try_into().unwrap();
             self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end]
                 .iter()
@@ -486,7 +486,7 @@ fn make_token_stream(
         if let AttrAnnotatedTokenTree::Token(last_token) = last_token {
             let unglued_first = last_token.kind.break_two_token_op().unwrap().0;
 
-            // A 'unglued' token is always two ASCII characters
+            // An 'unglued' token is always two ASCII characters
             let mut first_span = last_token.span.shrink_to_lo();
             first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 6259eff5a1a..326c8f81ffb 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> {
         // added to the return value after the fact.
         //
         // Therefore, prevent sub-parser from parsing
-        // attributes by giving them a empty "already-parsed" list.
+        // attributes by giving them an empty "already-parsed" list.
         let attrs = AttrVec::new();
 
         // Note: when adding new syntax here, don't forget to adjust `TokenKind::can_begin_expr()`.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 51d4e007b59..4c3c140d171 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -152,7 +152,7 @@ pub struct Parser<'a> {
 /// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]`
 /// In this case, we use a `ReplaceRange` to replace the entire inner AST node
 /// with `FlatToken::AttrTarget`, allowing us to perform eager cfg-expansion
-/// on a `AttrAnnotatedTokenStream`
+/// on an `AttrAnnotatedTokenStream`
 ///
 /// 2. When we parse an inner attribute while collecting tokens. We
 /// remove inner attributes from the token stream entirely, and
@@ -165,7 +165,7 @@ pub type ReplaceRange = (Range<u32>, Vec<(FlatToken, Spacing)>);
 
 /// Controls how we capture tokens. Capturing can be expensive,
 /// so we try to avoid performing capturing in cases where
-/// we will never need a `AttrAnnotatedTokenStream`
+/// we will never need an `AttrAnnotatedTokenStream`
 #[derive(Copy, Clone)]
 pub enum Capturing {
     /// We aren't performing any capturing - this is the default mode.
@@ -1362,10 +1362,10 @@ pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &Pa
     }
 }
 
-/// A helper struct used when building a `AttrAnnotatedTokenStream` from
+/// A helper struct used when building an `AttrAnnotatedTokenStream` from
 /// a `LazyTokenStream`. Both delimiter and non-delimited tokens
 /// are stored as `FlatToken::Token`. A vector of `FlatToken`s
-/// is then 'parsed' to build up a `AttrAnnotatedTokenStream` with nested
+/// is then 'parsed' to build up an `AttrAnnotatedTokenStream` with nested
 /// `AttrAnnotatedTokenTree::Delimited` tokens
 #[derive(Debug, Clone)]
 pub enum FlatToken {
@@ -1375,10 +1375,10 @@ pub enum FlatToken {
     /// Holds the `AttributesData` for an AST node. The
     /// `AttributesData` is inserted directly into the
     /// constructed `AttrAnnotatedTokenStream` as
-    /// a `AttrAnnotatedTokenTree::Attributes`
+    /// an `AttrAnnotatedTokenTree::Attributes`
     AttrTarget(AttributesData),
     /// A special 'empty' token that is ignored during the conversion
-    /// to a `AttrAnnotatedTokenStream`. This is used to simplify the
+    /// to an `AttrAnnotatedTokenStream`. This is used to simplify the
     /// handling of replace ranges.
     Empty,
 }
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 5e49df841d7..bf1e52cd9a8 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -11,6 +11,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
+rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_target = { path = "../rustc_target" }
 rustc_ast = { path = "../rustc_ast" }
@@ -18,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_feature = { path = "../rustc_feature" }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 3fea75954b9..d0ddad1c1a3 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,8 +8,10 @@ use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
-use rustc_ast::{AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
+use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
+use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -66,9 +68,10 @@ impl CheckAttrVisitor<'tcx> {
     ) {
         let mut is_valid = true;
         let mut specified_inline = None;
+        let mut seen = FxHashSet::default();
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            is_valid &= match attr.name_or_empty() {
+            let attr_is_valid = match attr.name_or_empty() {
                 sym::inline => self.check_inline(hir_id, attr, span, target),
                 sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
                 sym::marker => self.check_marker(hir_id, attr, span, target),
@@ -101,14 +104,72 @@ impl CheckAttrVisitor<'tcx> {
                 sym::default_method_body_is_const => {
                     self.check_default_method_body_is_const(attr, span, target)
                 }
+                sym::rustc_const_unstable
+                | sym::rustc_const_stable
+                | sym::unstable
+                | sym::stable
+                | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
                 _ => true,
             };
+            is_valid &= attr_is_valid;
+
             // lint-only checks
             match attr.name_or_empty() {
                 sym::cold => self.check_cold(hir_id, attr, span, target),
                 sym::link_name => self.check_link_name(hir_id, attr, span, target),
                 sym::link_section => self.check_link_section(hir_id, attr, span, target),
                 sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
+                sym::deprecated | sym::rustc_deprecated => {
+                    self.check_deprecated(hir_id, attr, span, target)
+                }
+                sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
+                sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
+                sym::cfg_attr => self.check_cfg_attr(hir_id, attr),
+                sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
+                sym::macro_export => self.check_macro_export(hir_id, attr, target),
+                sym::ignore | sym::should_panic | sym::proc_macro_derive => {
+                    self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
+                }
+                sym::automatically_derived => {
+                    self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
+                }
+                sym::no_implicit_prelude => {
+                    self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
+                }
+                _ => {}
+            }
+
+            if hir_id != CRATE_HIR_ID {
+                if let Some((_, AttributeType::CrateLevel, ..)) =
+                    attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
+                {
+                    self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                        let msg = match attr.style {
+                            ast::AttrStyle::Outer => {
+                                "crate-level attribute should be an inner attribute: add an exclamation \
+                                 mark: `#![foo]`"
+                            }
+                            ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
+                        };
+                        lint.build(msg).emit()
+                    });
+                }
+            }
+
+            // Duplicate attributes
+            match attr.name_or_empty() {
+                name @ sym::macro_use => {
+                    let args = attr.meta_item_list().unwrap_or_else(Vec::new);
+                    let args: Vec<_> = args.iter().map(|arg| arg.name_or_empty()).collect();
+                    if !seen.insert((name, args)) {
+                        self.tcx.struct_span_lint_hir(
+                            UNUSED_ATTRIBUTES,
+                            hir_id,
+                            attr.span,
+                            |lint| lint.build("unused attribute").emit(),
+                        );
+                    }
+                }
                 _ => {}
             }
         }
@@ -211,6 +272,37 @@ impl CheckAttrVisitor<'tcx> {
         }
     }
 
+    fn check_generic_attr(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        target: Target,
+        allowed_targets: &[Target],
+    ) {
+        if !allowed_targets.iter().any(|t| t == &target) {
+            let name = attr.name_or_empty();
+            let mut i = allowed_targets.iter();
+            // Pluralize
+            let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
+            let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
+                if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
+                    b.push_str(", and ");
+                } else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
+                    b.push_str(" and ");
+                } else {
+                    b.push_str(", ");
+                }
+                // Pluralize
+                b.push_str(&(allowed_target.to_string() + "s"));
+                b
+            });
+            self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
+                    .emit();
+            });
+        }
+    }
+
     /// Checks if `#[naked]` is applied to a function definition.
     fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
         match target {
@@ -1555,6 +1647,72 @@ impl CheckAttrVisitor<'tcx> {
             }
         }
     }
+
+    fn check_stability_promotable(&self, attr: &Attribute, _span: &Span, target: Target) -> bool {
+        match target {
+            Target::Expression => {
+                self.tcx
+                    .sess
+                    .struct_span_err(attr.span, "attribute cannot be applied to an expression")
+                    .emit();
+                false
+            }
+            _ => true,
+        }
+    }
+
+    fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: &Span, target: Target) {
+        match target {
+            Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
+                self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                    lint.build("attribute is ignored here").emit();
+                });
+            }
+            _ => {}
+        }
+    }
+
+    fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
+        let name = attr.name_or_empty();
+        match target {
+            Target::ExternCrate | Target::Mod => {}
+            _ => {
+                self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                    lint.build(&format!(
+                        "`#[{name}]` only has an effect on `extern crate` and modules"
+                    ))
+                    .emit();
+                });
+            }
+        }
+    }
+
+    fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
+        if target != Target::MacroDef {
+            self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                lint.build(&format!("`#[macro_export]` only has an effect on macro definitions"))
+                    .emit();
+            });
+        }
+    }
+
+    fn check_cfg_attr(&self, hir_id: HirId, attr: &Attribute) {
+        if let Some((_, attrs)) = rustc_parse::parse_cfg_attr(&attr, &self.tcx.sess.parse_sess) {
+            if attrs.is_empty() {
+                self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                    lint.build("`#[cfg_attr]` does not expand to any attributes").emit();
+                });
+            }
+        }
+    }
+
+    fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) {
+        if target != Target::Fn {
+            self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                lint.build("`#[plugin_registrar]` only has an effect on functions").emit();
+            });
+        }
+    }
 }
 
 impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
@@ -1675,7 +1833,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 
     for attr in attrs {
         for attr_to_check in ATTRS_TO_CHECK {
-            if tcx.sess.check_name(attr, *attr_to_check) {
+            if attr.has_name(*attr_to_check) {
                 tcx.sess
                     .struct_span_err(
                         attr.span,
@@ -1692,7 +1850,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
 
 fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
     for attr in attrs {
-        if tcx.sess.check_name(attr, sym::inline) {
+        if attr.has_name(sym::inline) {
             struct_span_err!(
                 tcx.sess,
                 attr.span,
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 3cf1d0cdd94..e43abda7133 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -15,7 +15,6 @@ use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::Session;
 use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_span::symbol::{sym, Symbol};
 
@@ -51,7 +50,7 @@ impl<'tcx> DiagnosticItemCollector<'tcx> {
     fn observe_item(&mut self, def_id: LocalDefId) {
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let attrs = self.tcx.hir().attrs(hir_id);
-        if let Some(name) = extract(&self.tcx.sess, attrs) {
+        if let Some(name) = extract(attrs) {
             // insert into our table
             collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
         }
@@ -91,10 +90,10 @@ fn collect_item(
     }
 }
 
-/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
-fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> {
+/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.p
+fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
     attrs.iter().find_map(|attr| {
-        if sess.check_name(attr, sym::rustc_diagnostic_item) { attr.value_str() } else { None }
+        if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
     })
 }
 
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 3a88d1932a8..62f9bcfdc47 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -13,6 +13,7 @@ use crate::weak_lang_items;
 use rustc_middle::middle::cstore::ExternCrate;
 use rustc_middle::ty::TyCtxt;
 
+use rustc_ast::Attribute;
 use rustc_errors::{pluralize, struct_span_err};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -57,7 +58,7 @@ impl LanguageItemCollector<'tcx> {
 
     fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
         let attrs = self.tcx.hir().attrs(hir_id);
-        let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
+        let check_name = |attr: &Attribute, sym| attr.has_name(sym);
         if let Some((value, span)) = extract(check_name, &attrs) {
             match ITEM_REFS.get(&value).cloned() {
                 // Known lang item with attribute on correct target.
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 18c1d647060..43a3a3062e7 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -27,7 +27,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
             | ItemKind::Struct(..)
             | ItemKind::Union(..) => {
                 for attr in self.tcx.get_attrs(item.def_id.to_def_id()).iter() {
-                    if self.tcx.sess.check_name(attr, sym::rustc_layout) {
+                    if attr.has_name(sym::rustc_layout) {
                         self.dump_layout_of(item.def_id, item, attr);
                     }
                 }
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index cadb8d23580..f583a5d58d5 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
+#![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(nll)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 363a6417f99..605b52f1891 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -33,9 +33,7 @@ impl LibFeatureCollector<'tcx> {
 
         // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`,
         // `#[rustc_const_unstable (..)]`).
-        if let Some(stab_attr) =
-            stab_attrs.iter().find(|stab_attr| self.tcx.sess.check_name(attr, **stab_attr))
-        {
+        if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
             let meta_item = attr.meta();
             if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta_item {
                 let mut feature = None;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 87c14d9c395..72889bc49d0 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -95,7 +95,7 @@ use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::vec::IndexVec;
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -123,8 +123,8 @@ rustc_index::newtype_index! {
 #[derive(Copy, Clone, PartialEq, Debug)]
 enum LiveNodeKind {
     UpvarNode(Span),
-    ExprNode(Span),
-    VarDefNode(Span),
+    ExprNode(Span, HirId),
+    VarDefNode(Span, HirId),
     ClosureNode,
     ExitNode,
 }
@@ -133,8 +133,8 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
     let sm = tcx.sess.source_map();
     match lnk {
         UpvarNode(s) => format!("Upvar node [{}]", sm.span_to_diagnostic_string(s)),
-        ExprNode(s) => format!("Expr node [{}]", sm.span_to_diagnostic_string(s)),
-        VarDefNode(s) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)),
+        ExprNode(s, _) => format!("Expr node [{}]", sm.span_to_diagnostic_string(s)),
+        VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)),
         ClosureNode => "Closure node".to_owned(),
         ExitNode => "Exit node".to_owned(),
     }
@@ -297,7 +297,7 @@ impl IrMaps<'tcx> {
         }
 
         pat.each_binding(|_, hir_id, _, ident| {
-            self.add_live_node_for_node(hir_id, VarDefNode(ident.span));
+            self.add_live_node_for_node(hir_id, VarDefNode(ident.span, hir_id));
             self.add_variable(Local(LocalInfo {
                 id: hir_id,
                 name: ident.name,
@@ -396,14 +396,14 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
                 debug!("expr {}: path that leads to {:?}", expr.hir_id, path.res);
                 if let Res::Local(_var_hir_id) = path.res {
-                    self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+                    self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
                 }
                 intravisit::walk_expr(self, expr);
             }
             hir::ExprKind::Closure(..) => {
                 // Interesting control flow (for loops can contain labeled
                 // breaks or continues)
-                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
 
                 // Make a live_node for each mentioned variable, with the span
                 // being the location that the variable is used.  This results
@@ -429,11 +429,11 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
 
             // live nodes required for interesting control flow:
             hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
-                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
                 intravisit::walk_expr(self, expr);
             }
             hir::ExprKind::Binary(op, ..) if op.node.is_lazy() => {
-                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+                self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
                 intravisit::walk_expr(self, expr);
             }
 
@@ -982,32 +982,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             }
 
             hir::ExprKind::Call(ref f, ref args) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(
-                    m,
-                    self.typeck_results.expr_ty(expr),
-                    self.param_env,
-                ) {
-                    self.exit_ln
-                } else {
-                    succ
-                };
+                let succ = self.check_is_ty_uninhabited(expr, succ);
                 let succ = self.propagate_through_exprs(args, succ);
                 self.propagate_through_expr(&f, succ)
             }
 
             hir::ExprKind::MethodCall(.., ref args, _) => {
-                let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
-                let succ = if self.ir.tcx.is_ty_uninhabited_from(
-                    m,
-                    self.typeck_results.expr_ty(expr),
-                    self.param_env,
-                ) {
-                    self.exit_ln
-                } else {
-                    succ
-                };
-
+                let succ = self.check_is_ty_uninhabited(expr, succ);
                 self.propagate_through_exprs(args, succ)
             }
 
@@ -1265,6 +1246,66 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
         ln
     }
+
+    fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
+        let ty = self.typeck_results.expr_ty(expr);
+        let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
+        if self.ir.tcx.is_ty_uninhabited_from(m, ty, self.param_env) {
+            match self.ir.lnks[succ] {
+                LiveNodeKind::ExprNode(succ_span, succ_id) => {
+                    self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "expression");
+                }
+                LiveNodeKind::VarDefNode(succ_span, succ_id) => {
+                    self.warn_about_unreachable(expr.span, ty, succ_span, succ_id, "definition");
+                }
+                _ => {}
+            };
+            self.exit_ln
+        } else {
+            succ
+        }
+    }
+
+    fn warn_about_unreachable(
+        &mut self,
+        orig_span: Span,
+        orig_ty: Ty<'tcx>,
+        expr_span: Span,
+        expr_id: HirId,
+        descr: &str,
+    ) {
+        if !orig_ty.is_never() {
+            // Unreachable code warnings are already emitted during type checking.
+            // However, during type checking, full type information is being
+            // calculated but not yet available, so the check for diverging
+            // expressions due to uninhabited result types is pretty crude and
+            // only checks whether ty.is_never(). Here, we have full type
+            // information available and can issue warnings for less obviously
+            // uninhabited types (e.g. empty enums). The check above is used so
+            // that we do not emit the same warning twice if the uninhabited type
+            // is indeed `!`.
+
+            self.ir.tcx.struct_span_lint_hir(
+                lint::builtin::UNREACHABLE_CODE,
+                expr_id,
+                expr_span,
+                |lint| {
+                    let msg = format!("unreachable {}", descr);
+                    lint.build(&msg)
+                        .span_label(expr_span, &msg)
+                        .span_label(orig_span, "any code following this expression is unreachable")
+                        .span_note(
+                            orig_span,
+                            &format!(
+                                "this expression has type `{}`, which is uninhabited",
+                                orig_ty
+                            ),
+                        )
+                        .emit();
+                },
+            );
+        }
+    }
 }
 
 // _______________________________________________________________________
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 484040de0fb..b64dcb0bbf0 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -148,7 +148,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         }
 
         if self.tcx.features().staged_api {
-            if let Some(a) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
+            if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) {
                 self.tcx
                     .sess
                     .struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
@@ -350,7 +350,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         for attr in attrs {
             let name = attr.name_or_empty();
             if unstable_attrs.contains(&name) {
-                self.tcx.sess.mark_attr_used(attr);
                 struct_span_err!(
                     self.tcx.sess,
                     attr.span,
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 629513c7cfe..3a662a9bab2 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -1,5 +1,6 @@
 //! Validity checking for weak lang items
 
+use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
@@ -96,7 +97,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
-        let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
+        let check_name = |attr: &Attribute, sym| attr.has_name(sym);
         let attrs = self.tcx.hir().attrs(i.hir_id());
         if let Some((lang_item, _)) = lang_items::extract(check_name, attrs) {
             self.register(lang_item, i.span);
diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs
index 5da02e3a489..51cf85f794b 100644
--- a/compiler/rustc_plugin_impl/src/load.rs
+++ b/compiler/rustc_plugin_impl/src/load.rs
@@ -32,7 +32,7 @@ pub fn load_plugins(
     let mut plugins = Vec::new();
 
     for attr in &krate.attrs {
-        if !sess.check_name(attr, sym::plugin) {
+        if !attr.has_name(sym::plugin) {
             continue;
         }
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index a683cb05e16..d84175724cc 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -575,7 +575,7 @@ impl EmbargoVisitor<'tcx> {
         }
     }
 
-    /// Given the path segments of a `ItemKind::Use`, then we need
+    /// Given the path segments of an `ItemKind::Use`, then we need
     /// to update the visibility of the intermediate use so that it isn't linted
     /// by `unreachable_pub`.
     ///
@@ -885,9 +885,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
         // Non-opaque macros cannot make other items more accessible than they already are.
         let attrs = self.tcx.hir().attrs(md.hir_id());
-        if attr::find_transparency(&self.tcx.sess, &attrs, md.ast.macro_rules).0
-            != Transparency::Opaque
-        {
+        if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque {
             // `#[macro_export]`-ed `macro_rules!` are `Public` since they
             // ignore their containing path to always appear at the crate root.
             if md.ast.macro_rules {
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 178d727418d..2ee483d850e 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -195,7 +195,7 @@ impl<'a> Resolver<'a> {
     crate fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
         match res {
             Res::Def(DefKind::Macro(..), def_id) => Some(self.get_macro_by_def_id(def_id)),
-            Res::NonMacroAttr(attr_kind) => Some(self.non_macro_attr(attr_kind.is_used())),
+            Res::NonMacroAttr(_) => Some(self.non_macro_attr.clone()),
             _ => None,
         }
     }
@@ -1059,7 +1059,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         let mut import_all = None;
         let mut single_imports = Vec::new();
         for attr in &item.attrs {
-            if self.r.session.check_name(attr, sym::macro_use) {
+            if attr.has_name(sym::macro_use) {
                 if self.parent_scope.module.parent.is_some() {
                     struct_span_err!(
                         self.r.session,
@@ -1165,7 +1165,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     /// Returns `true` if this attribute list contains `macro_use`.
     fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
         for attr in attrs {
-            if self.r.session.check_name(attr, sym::macro_escape) {
+            if attr.has_name(sym::macro_escape) {
                 let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`";
                 let mut err = self.r.session.struct_span_warn(attr.span, msg);
                 if let ast::AttrStyle::Inner = attr.style {
@@ -1173,7 +1173,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 } else {
                     err.emit();
                 }
-            } else if !self.r.session.check_name(attr, sym::macro_use) {
+            } else if !attr.has_name(sym::macro_use) {
                 continue;
             }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 3cf04268756..ca2c22854c4 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -956,9 +956,61 @@ impl<'a> Resolver<'a> {
         if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
             err.span_note(ident.span, &msg);
+            return;
         }
         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
             err.help("have you added the `#[macro_use]` on the module/import?");
+            return;
+        }
+        for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
+            if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
+                ident,
+                ScopeSet::All(ns, false),
+                &parent_scope,
+                false,
+                false,
+                ident.span,
+            ) {
+                let desc = match binding.res() {
+                    Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
+                        "a function-like macro".to_string()
+                    }
+                    Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
+                        format!("an attribute: `#[{}]`", ident)
+                    }
+                    Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
+                        format!("a derive macro: `#[derive({})]`", ident)
+                    }
+                    Res::ToolMod => {
+                        // Don't confuse the user with tool modules.
+                        continue;
+                    }
+                    Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
+                        "only a trait, without a derive macro".to_string()
+                    }
+                    res => format!(
+                        "{} {}, not {} {}",
+                        res.article(),
+                        res.descr(),
+                        macro_kind.article(),
+                        macro_kind.descr_expected(),
+                    ),
+                };
+                if let crate::NameBindingKind::Import { import, .. } = binding.kind {
+                    if !import.span.is_dummy() {
+                        err.span_note(
+                            import.span,
+                            &format!("`{}` is imported here, but it is {}", ident, desc),
+                        );
+                        // Silence the 'unused import' warning we might get,
+                        // since this diagnostic already covers that import.
+                        self.record_use(ident, binding, false);
+                        return;
+                    }
+                }
+                err.note(&format!("`{}` is in scope, but it is {}", ident, desc));
+                return;
+            }
         }
     }
 
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index a602a58e517..9d923599db7 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1826,7 +1826,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         err.emit();
     }
 
-    // FIXME(const_generics): This patches over a ICE caused by non-'static lifetimes in const
+    // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
     // generics. We are disallowing this until we can decide on how we want to handle non-'static
     // lifetimes in const generics. See issue #74052 for discussion.
     crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) {
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index d79fd910b7e..882d15cf892 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -2057,9 +2057,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                             if let Some(def_id) = parent_def_id.as_local() {
                                 let parent_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 // lifetimes in `derive` expansions don't count (Issue #53738)
-                                if self.tcx.hir().attrs(parent_hir_id).iter().any(|attr| {
-                                    self.tcx.sess.check_name(attr, sym::automatically_derived)
-                                }) {
+                                if self
+                                    .tcx
+                                    .hir()
+                                    .attrs(parent_hir_id)
+                                    .iter()
+                                    .any(|attr| attr.has_name(sym::automatically_derived))
+                                {
                                     continue;
                                 }
                             }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 465007507da..e308ea1a1be 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -668,7 +668,7 @@ enum NameBindingKind<'a> {
 }
 
 impl<'a> NameBindingKind<'a> {
-    /// Is this a name binding of a import?
+    /// Is this a name binding of an import?
     fn is_import(&self) -> bool {
         matches!(*self, NameBindingKind::Import { .. })
     }
@@ -968,7 +968,7 @@ pub struct Resolver<'a> {
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
     dummy_ext_bang: Lrc<SyntaxExtension>,
     dummy_ext_derive: Lrc<SyntaxExtension>,
-    non_macro_attrs: [Lrc<SyntaxExtension>; 2],
+    non_macro_attr: Lrc<SyntaxExtension>,
     local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
     ast_transform_scopes: FxHashMap<LocalExpnId, Module<'a>>,
     unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
@@ -1293,8 +1293,6 @@ impl<'a> Resolver<'a> {
             macros::registered_attrs_and_tools(session, &krate.attrs);
 
         let features = session.features_untracked();
-        let non_macro_attr =
-            |mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
 
         let mut resolver = Resolver {
             session,
@@ -1361,7 +1359,7 @@ impl<'a> Resolver<'a> {
             macro_map: FxHashMap::default(),
             dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
             dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
-            non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
+            non_macro_attr: Lrc::new(SyntaxExtension::non_macro_attr(session.edition())),
             invocation_parent_scopes: Default::default(),
             output_macro_rules_scopes: Default::default(),
             helper_attrs: Default::default(),
@@ -1476,15 +1474,11 @@ impl<'a> Resolver<'a> {
         self.crate_loader.cstore()
     }
 
-    fn non_macro_attr(&self, mark_used: bool) -> Lrc<SyntaxExtension> {
-        self.non_macro_attrs[mark_used as usize].clone()
-    }
-
     fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
         match macro_kind {
             MacroKind::Bang => self.dummy_ext_bang.clone(),
             MacroKind::Derive => self.dummy_ext_derive.clone(),
-            MacroKind::Attr => self.non_macro_attr(true),
+            MacroKind::Attr => self.non_macro_attr.clone(),
         }
     }
 
@@ -3065,7 +3059,7 @@ impl<'a> Resolver<'a> {
             self.extern_prelude.get(&ident).map_or(true, |entry| entry.introduced_by_item);
         // Only suggest removing an import if both bindings are to the same def, if both spans
         // aren't dummy spans. Further, if both bindings are imports, then the ident must have
-        // been introduced by a item.
+        // been introduced by an item.
         let should_remove_import = duplicate
             && !has_dummy_span
             && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
@@ -3160,7 +3154,7 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    /// This function adds a suggestion to remove a unnecessary binding from an import that is
+    /// This function adds a suggestion to remove an unnecessary binding from an import that is
     /// nested. In the following example, this function will be invoked to remove the `a` binding
     /// in the second use statement:
     ///
@@ -3212,7 +3206,7 @@ impl<'a> Resolver<'a> {
                     Applicability::MaybeIncorrect,
                 );
             } else {
-                // Remove the entire line if we cannot extend the span back, this indicates a
+                // Remove the entire line if we cannot extend the span back, this indicates an
                 // `issue_52891::{self}` case.
                 err.span_suggestion(
                     import.use_span_with_attributes,
@@ -3381,9 +3375,8 @@ impl<'a> Resolver<'a> {
 
                 let parse_attrs = || {
                     let attrs = self.cstore().item_attrs(def_id, self.session);
-                    let attr = attrs
-                        .iter()
-                        .find(|a| self.session.check_name(a, sym::rustc_legacy_const_generics))?;
+                    let attr =
+                        attrs.iter().find(|a| a.has_name(sym::rustc_legacy_const_generics))?;
                     let mut ret = vec![];
                     for meta in attr.meta_item_list()? {
                         match meta.literal()?.kind {
diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs
index 4d213207fb6..e5369b4bbfd 100644
--- a/compiler/rustc_serialize/src/json.rs
+++ b/compiler/rustc_serialize/src/json.rs
@@ -1202,7 +1202,7 @@ impl Json {
         matches!(*self, Json::I64(_) | Json::U64(_) | Json::F64(_))
     }
 
-    /// Returns `true` if the Json value is a `i64`.
+    /// Returns `true` if the Json value is an `i64`.
     pub fn is_i64(&self) -> bool {
         matches!(*self, Json::I64(_))
     }
@@ -1217,7 +1217,7 @@ impl Json {
         matches!(*self, Json::F64(_))
     }
 
-    /// If the Json value is a number, returns or cast it to a `i64`;
+    /// If the Json value is a number, returns or cast it to an `i64`;
     /// returns `None` otherwise.
     pub fn as_i64(&self) -> Option<i64> {
         match *self {
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 4d9aaaecec8..ecc8dae0480 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -644,7 +644,7 @@ impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
 }
 
 // FIXME: #15036
-// Should use `try_borrow`, returning a
+// Should use `try_borrow`, returning an
 // `encoder.error("attempting to Encode borrowed RefCell")`
 // from `encode` when `try_borrow` returns `None`.
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 123f47b430a..fdedb7e6a4a 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1089,10 +1089,11 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         ),
         opt::flag_s("", "test", "Build a test harness"),
         opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
-        opt::multi_s("W", "warn", "Set lint warnings", "OPT"),
-        opt::multi_s("A", "allow", "Set lint allowed", "OPT"),
-        opt::multi_s("D", "deny", "Set lint denied", "OPT"),
-        opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
+        opt::multi_s("A", "allow", "Set lint allowed", "LINT"),
+        opt::multi_s("W", "warn", "Set lint warnings", "LINT"),
+        opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"),
+        opt::multi_s("D", "deny", "Set lint denied", "LINT"),
+        opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"),
         opt::multi_s(
             "",
             "cap-lints",
@@ -1101,13 +1102,6 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
              level",
             "LEVEL",
         ),
-        opt::multi_s(
-            "",
-            "force-warn",
-            "Specifiy lints that should warn even if \
-             they are allowed somewhere else",
-            "LINT",
-        ),
         opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
         opt::flag_s("V", "version", "Print version info and exit"),
         opt::flag_s("v", "verbose", "Use verbose output"),
@@ -1163,19 +1157,10 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
-    debugging_opts: &DebuggingOptions,
 ) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
-    if !debugging_opts.unstable_options && matches.opt_present("force-warn") {
-        early_error(
-            error_format,
-            "the `-Z unstable-options` flag must also be passed to enable \
-            the flag `--force-warn=lints`",
-        );
-    }
-
     for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] {
         for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
             if lint_name == "help" {
@@ -1965,8 +1950,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
-    let (lint_opts, describe_lints, lint_cap) =
-        get_cmd_lint_options(matches, error_format, &debugging_opts);
+    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 481520122d2..f36fc29e974 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1287,7 +1287,7 @@ options! {
     thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "enable ThinLTO when possible"),
     thir_unsafeck: bool = (false, parse_bool, [TRACKED],
-        "use the work-in-progress THIR unsafety checker. NOTE: this is unsound (default: no)"),
+        "use the THIR unsafety checker (default: no)"),
     /// We default to 1 here since we want to behave like
     /// a sequential compiler for now. This'll likely be adjusted
     /// in the future. Note that -Zthreads=0 is the way to get
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 5b163603d5f..d49ba861785 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -213,8 +213,6 @@ pub struct Session {
     /// Set of enabled features for the current target.
     pub target_features: FxHashSet<Symbol>,
 
-    used_attrs: Lock<MarkedAttrs>,
-
     /// `Span`s for `if` conditions that we have suggested turning into `if let`.
     pub if_let_suggestions: Lock<FxHashSet<Span>>,
 }
@@ -1066,39 +1064,14 @@ impl Session {
             == config::InstrumentCoverage::ExceptUnusedFunctions
     }
 
-    pub fn mark_attr_used(&self, attr: &Attribute) {
-        self.used_attrs.lock().mark(attr)
-    }
-
-    pub fn is_attr_used(&self, attr: &Attribute) -> bool {
-        self.used_attrs.lock().is_marked(attr)
-    }
-
-    /// Returns `true` if the attribute's path matches the argument. If it
-    /// matches, then the attribute is marked as used.
-    ///
-    /// This method should only be used by rustc, other tools can use
-    /// `Attribute::has_name` instead, because only rustc is supposed to report
-    /// the `unused_attributes` lint. (`MetaItem` and `NestedMetaItem` are
-    /// produced by lowering an `Attribute` and don't have identity, so they
-    /// only have the `has_name` method, and you need to mark the original
-    /// `Attribute` as used when necessary.)
-    pub fn check_name(&self, attr: &Attribute, name: Symbol) -> bool {
-        let matches = attr.has_name(name);
-        if matches {
-            self.mark_attr_used(attr);
-        }
-        matches
-    }
-
     pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
         [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
             .iter()
-            .any(|kind| self.check_name(attr, *kind))
+            .any(|kind| attr.has_name(*kind))
     }
 
     pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool {
-        attrs.iter().any(|item| self.check_name(item, name))
+        attrs.iter().any(|item| item.has_name(name))
     }
 
     pub fn find_by_name<'a>(
@@ -1106,7 +1079,7 @@ impl Session {
         attrs: &'a [Attribute],
         name: Symbol,
     ) -> Option<&'a Attribute> {
-        attrs.iter().find(|attr| self.check_name(attr, name))
+        attrs.iter().find(|attr| attr.has_name(name))
     }
 
     pub fn filter_by_name<'a>(
@@ -1114,7 +1087,7 @@ impl Session {
         attrs: &'a [Attribute],
         name: Symbol,
     ) -> impl Iterator<Item = &'a Attribute> {
-        attrs.iter().filter(move |attr| self.check_name(attr, name))
+        attrs.iter().filter(move |attr| attr.has_name(name))
     }
 
     pub fn first_attr_value_str_by_name(
@@ -1122,7 +1095,7 @@ impl Session {
         attrs: &[Attribute],
         name: Symbol,
     ) -> Option<Symbol> {
-        attrs.iter().find(|at| self.check_name(at, name)).and_then(|at| at.value_str())
+        attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
     }
 }
 
@@ -1359,7 +1332,6 @@ pub fn build_session(
         miri_unleashed_features: Lock::new(Default::default()),
         asm_arch,
         target_features: FxHashSet::default(),
-        used_attrs: Lock::new(MarkedAttrs::new()),
         if_let_suggestions: Default::default(),
     };
 
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 77a3ad931d5..f700397fcdf 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -100,7 +100,7 @@ pub trait FileLoader {
     /// Query the existence of a file.
     fn file_exists(&self, path: &Path) -> bool;
 
-    /// Read the contents of an UTF-8 file into memory.
+    /// Read the contents of a UTF-8 file into memory.
     fn read_file(&self, path: &Path) -> io::Result<String>;
 }
 
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index bfe9c4d6de3..183df96f316 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -35,7 +35,7 @@ impl SymbolNamesTest<'tcx> {
     fn process_attrs(&mut self, def_id: LocalDefId) {
         let tcx = self.tcx;
         for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
-            if tcx.sess.check_name(attr, SYMBOL_NAME) {
+            if attr.has_name(SYMBOL_NAME) {
                 let def_id = def_id.to_def_id();
                 let instance = Instance::new(
                     def_id,
@@ -47,7 +47,7 @@ impl SymbolNamesTest<'tcx> {
                     tcx.sess.span_err(attr.span, &format!("demangling({})", demangling));
                     tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling));
                 }
-            } else if tcx.sess.check_name(attr, DEF_PATH) {
+            } else if attr.has_name(DEF_PATH) {
                 let path = with_no_trimmed_paths(|| tcx.def_path_str(def_id.to_def_id()));
                 tcx.sess.span_err(attr.span, &format!("def-path({})", path));
             }
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 9ebf8235e20..bb24f7bb135 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -469,7 +469,7 @@ impl InlineAsmRegClass {
         }
     }
 
-    /// Returns a list of supported types for this register class, each with a
+    /// Returns a list of supported types for this register class, each with an
     /// options target feature required to use this type.
     pub fn supported_types(
         self,
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index cff0b3651e1..5d75f6ab39c 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -92,6 +92,12 @@ fn ios_deployment_target() -> (u32, u32) {
 }
 
 pub fn ios_llvm_target(arch: &str) -> String {
+    // Modern iOS tooling extracts information about deployment target
+    // from LC_BUILD_VERSION. This load command will only be emitted when
+    // we build with a version specific `llvm_target`, with the version
+    // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode
+    // to pick it up (since std and core are still built with the fallback
+    // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
     let (major, minor) = ios_deployment_target();
     format!("{}-apple-ios{}.{}.0", arch, major, minor)
 }
diff --git a/compiler/rustc_target/src/spec/armv7_apple_ios.rs b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
index 2f228688f43..1f90c78f14a 100644
--- a/compiler/rustc_target/src/spec/armv7_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/armv7_apple_ios.rs
@@ -3,7 +3,7 @@ use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_llvm_target("armv7"),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".to_string(),
         arch: "arm".to_string(),
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
index f5d7be4537b..4419dfe92f4 100644
--- a/compiler/rustc_target/src/spec/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -4,7 +4,7 @@ use crate::spec::{StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     let base = opts("ios", Arch::I386);
     Target {
-        llvm_target: "i386-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_sim_llvm_target("i386"),
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
index adb87718589..6e20bd23f17 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -4,7 +4,7 @@ use crate::spec::{StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     let base = opts("ios", Arch::X86_64);
     Target {
-        llvm_target: "x86_64-apple-ios".to_string(),
+        llvm_target: super::apple_base::ios_sim_llvm_target("x86_64"),
         pointer_width: 64,
         data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .to_string(),
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index e6686b8cc70..c5a6e301deb 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -77,7 +77,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ///     ?0: Iterator<Item = ?1>
     ///     ?1: Debug
     ///
-    /// Moreover, it returns a `OpaqueTypeMap` that would map `?0` to
+    /// Moreover, it returns an `OpaqueTypeMap` that would map `?0` to
     /// info about the `impl Iterator<..>` type and `?1` to info about
     /// the `impl Debug` type.
     ///
@@ -886,7 +886,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                     // }
                     // ```
                     //
-                    // Here, the return type of `foo` references a
+                    // Here, the return type of `foo` references an
                     // `Opaque` indeed, but not one whose value is
                     // presently being inferred. You can get into a
                     // similar situation with closure return types
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 45853a66efc..f06f0e32f41 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -12,7 +12,7 @@ use rustc_errors::ErrorReported;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, TyCtxt};
 
-/// Attempts to resolve an obligation to a `ImplSource`. The result is
+/// Attempts to resolve an obligation to an `ImplSource`. The result is
 /// a shallow `ImplSource` resolution, meaning that we do not
 /// (necessarily) resolve all nested obligations on the impl. Note
 /// that type check should guarantee to us that all nested
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 2c09c551b65..90b6ee5f5a6 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2009,7 +2009,7 @@ pub enum ArgKind {
     Arg(String, String),
 
     /// An argument of tuple type. For a "found" argument, the span is
-    /// the location in the source of the pattern. For a "expected"
+    /// the location in the source of the pattern. For an "expected"
     /// argument, it will be None. The vector is a list of (name, ty)
     /// strings for the components of the tuple.
     Tuple(Option<Span>, Vec<(String, String)>),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 003642ff259..40841a6e32d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1365,7 +1365,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // When a future does not implement a trait because of a captured type in one of the
         // generators somewhere in the call stack, then the result is a chain of obligations.
         //
-        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
+        // Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
         // future is passed as an argument to a function C which requires a `Send` type, then the
         // chain looks something like this:
         //
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index f75f7b887a5..19e3c1afb9f 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -62,7 +62,7 @@ enum ProjectionTyCandidate<'tcx> {
     /// Bounds specified on an object type
     Object(ty::PolyProjectionPredicate<'tcx>),
 
-    /// From a "impl" (or a "pseudo-impl" returned by select)
+    /// From an "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
 }
 
@@ -1011,7 +1011,7 @@ fn prune_cache_value_obligations<'a, 'tcx>(
 /// Note that we used to return `Error` here, but that was quite
 /// dubious -- the premise was that an error would *eventually* be
 /// reported, when the obligation was processed. But in general once
-/// you see a `Error` you are supposed to be able to assume that an
+/// you see an `Error` you are supposed to be able to assume that an
 /// error *has been* reported, so that you can take whatever heuristic
 /// paths you want to take. To make things worse, it was possible for
 /// cycles to arise, where you basically had a setup like `<MyType<$0>
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 3863dd61cef..03087e3353a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -24,7 +24,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
     ) -> Fallible<CanonicalizedQueryResponse<'tcx, Self::QueryResponse>> {
         // FIXME this `unchecked_map` is only necessary because the
         // query is defined as taking a `ParamEnvAnd<Ty>`; it should
-        // take a `ImpliedOutlivesBounds` instead
+        // take an `ImpliedOutlivesBounds` instead
         let canonicalized = canonicalized.unchecked_map(|ParamEnvAnd { param_env, value }| {
             let ImpliedOutlivesBounds { ty } = value;
             param_env.and(ty)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 0f2f5357eb7..ba62ce1d531 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -257,7 +257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         ImplSourceBuiltinData { nested: obligations }
     }
 
-    /// This handles the case where a `auto trait Foo` impl is being used.
+    /// This handles the case where an `auto trait Foo` impl is being used.
     /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
     ///
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 4b563a87a15..88aca794a6b 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -149,7 +149,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
     let penv = tcx.param_env(impl1_def_id);
     let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
 
-    // Create a infcx, taking the predicates of impl1 as assumptions:
+    // Create an infcx, taking the predicates of impl1 as assumptions:
     tcx.infer_ctxt().enter(|infcx| {
         // Normalize the trait reference. The WF rules ought to ensure
         // that this always succeeds.
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 8c97e606c56..1d457d6761f 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -718,7 +718,7 @@ impl<'tcx> chalk_ir::UnificationDatabase<RustInterner<'tcx>> for RustIrDatabase<
     }
 }
 
-/// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked
+/// Creates an `InternalSubsts` that maps each generic parameter to a higher-ranked
 /// var bound at index `0`. For types, we use a `BoundVar` index equal to
 /// the type parameter index. For regions, we use the `BoundRegionKind::BrNamed`
 /// variant (which has a `DefId`).
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index b0d644ae028..8332e738411 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -185,7 +185,7 @@ fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
 ///     - a type parameter or projection whose Sizedness can't be known
 ///     - a tuple of type parameters or projections, if there are multiple
 ///       such.
-///     - a Error, if a type contained itself. The representability
+///     - an Error, if a type contained itself. The representability
 ///       check should catch this case.
 fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
     let def = tcx.adt_def(def_id);
@@ -253,7 +253,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
     // report these errors right here; this doesn't actually feel
     // right to me, because constructing the environment feels like a
-    // kind of a "idempotent" action, but I'm not sure where would be
+    // kind of an "idempotent" action, but I'm not sure where would be
     // a better place. In practice, we construct environments for
     // every fn once during type checking, and we'll abort if there
     // are any errors at that point, so after type checking you can be
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 3f72a431bd1..7d7d69b4079 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2350,7 +2350,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             hir::TyKind::Infer => {
                 // Infer also appears as the type of arguments or return
-                // values in a ExprKind::Closure, or as
+                // values in an ExprKind::Closure, or as
                 // the type of local variables. Both of these cases are
                 // handled specially and will not descend into this routine.
                 self.ty_infer(None, ast_ty.span)
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 87fd8f1e03b..01227cad334 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -14,6 +14,7 @@ use rustc_trait_selection::traits::{
 };
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    #[instrument(skip(self), level = "debug")]
     pub fn check_match(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
@@ -26,6 +27,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let acrb = arms_contain_ref_bindings(arms);
         let scrutinee_ty = self.demand_scrutinee_type(scrut, acrb, arms.is_empty());
+        debug!(?scrutinee_ty);
 
         // If there are no arms, that is a diverging match; a special case.
         if arms.is_empty() {
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 181972e3e7b..14550690e63 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -51,6 +51,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
+#[derive(Debug)]
 pub struct CastCheck<'tcx> {
     expr: &'tcx hir::Expr<'tcx>,
     expr_ty: Ty<'tcx>,
@@ -603,12 +604,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         });
     }
 
+    #[instrument(skip(fcx), level = "debug")]
     pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
         self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
 
-        debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
-
         if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) {
             self.report_cast_to_unsized_type(fcx);
         } else if self.expr_ty.references_error() || self.cast_ty.references_error() {
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs
index e4b615e4ade..65ba1c08b62 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_typeck/src/check/closure.rs
@@ -617,7 +617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Invoked when we are translating the generator that results
     /// from desugaring an `async fn`. Returns the "sugared" return
     /// type of the `async fn` -- that is, the return type that the
-    /// user specified. The "desugared" return type is a `impl
+    /// user specified. The "desugared" return type is an `impl
     /// Future<Output = T>`, so we do this by searching through the
     /// obligations to extract the `T`.
     fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 0b4df8e6d3c..17a81486048 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -1328,6 +1328,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
     /// The inner coercion "engine". If `expression` is `None`, this
     /// is a forced-unit case, and hence `expression_ty` must be
     /// `Nil`.
+    #[instrument(skip(self, fcx, augment_error, label_expression_as_expected), level = "debug")]
     crate fn coerce_inner<'a>(
         &mut self,
         fcx: &FnCtxt<'a, 'tcx>,
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 8d5bf98be99..c384e0dcb2c 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -1225,6 +1225,7 @@ fn compare_type_predicate_entailment<'tcx>(
 /// For default associated types the normalization is not possible (the value
 /// from the impl could be overridden). We also can't normalize generic
 /// associated types (yet) because they contain bound parameters.
+#[tracing::instrument(level = "debug", skip(tcx))]
 pub fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
@@ -1238,10 +1239,83 @@ pub fn check_type_bounds<'tcx>(
     //     type Bar<C> =...
     // }
     //
-    // - `impl_substs` would be `[A, B, C]`
-    // - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from
-    //    the *trait* with the generic associated type parameters.
-    let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
+    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
+    // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+    // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
+    //    the *trait* with the generic associated type parameters (as bound vars).
+    //
+    // A note regarding the use of bound vars here:
+    // Imagine as an example
+    // ```
+    // trait Family {
+    //     type Member<C: Eq>;
+    // }
+    //
+    // impl Family for VecFamily {
+    //     type Member<C: Eq> = i32;
+    // }
+    // ```
+    // Here, we would generate
+    // ```notrust
+    // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
+    // ```
+    // when we really would like to generate
+    // ```notrust
+    // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
+    // ```
+    // But, this is probably fine, because although the first clause can be used with types C that
+    // do not implement Eq, for it to cause some kind of problem, there would have to be a
+    // VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type
+    // Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
+    // elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
+    // the trait (notably, that X: Eq and T: Family).
+    let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
+    let mut substs = smallvec::SmallVec::with_capacity(defs.count());
+    if let Some(def_id) = defs.parent {
+        let parent_defs = tcx.generics_of(def_id);
+        InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
+            tcx.mk_param_from_def(param)
+        });
+    }
+    let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
+        smallvec::SmallVec::with_capacity(defs.count());
+    InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
+        GenericParamDefKind::Type { .. } => {
+            let kind = ty::BoundTyKind::Param(param.name);
+            let bound_var = ty::BoundVariableKind::Ty(kind);
+            bound_vars.push(bound_var);
+            tcx.mk_ty(ty::Bound(
+                ty::INNERMOST,
+                ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+            ))
+            .into()
+        }
+        GenericParamDefKind::Lifetime => {
+            let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+            let bound_var = ty::BoundVariableKind::Region(kind);
+            bound_vars.push(bound_var);
+            tcx.mk_region(ty::ReLateBound(
+                ty::INNERMOST,
+                ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+            ))
+            .into()
+        }
+        GenericParamDefKind::Const { .. } => {
+            let bound_var = ty::BoundVariableKind::Const;
+            bound_vars.push(bound_var);
+            tcx.mk_const(ty::Const {
+                ty: tcx.type_of(param.def_id),
+                val: ty::ConstKind::Bound(
+                    ty::INNERMOST,
+                    ty::BoundVar::from_usize(bound_vars.len() - 1),
+                ),
+            })
+            .into()
+        }
+    });
+    let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+    let impl_ty_substs = tcx.intern_substs(&substs);
+
     let rebased_substs =
         impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
     let impl_ty_value = tcx.type_of(impl_ty.def_id);
@@ -1270,18 +1344,26 @@ pub fn check_type_bounds<'tcx>(
                 // impl<T> X for T where T: X { type Y = <T as X>::Y; }
             }
             _ => predicates.push(
-                ty::Binder::dummy(ty::ProjectionPredicate {
-                    projection_ty: ty::ProjectionTy {
-                        item_def_id: trait_ty.def_id,
-                        substs: rebased_substs,
+                ty::Binder::bind_with_vars(
+                    ty::ProjectionPredicate {
+                        projection_ty: ty::ProjectionTy {
+                            item_def_id: trait_ty.def_id,
+                            substs: rebased_substs,
+                        },
+                        ty: impl_ty_value,
                     },
-                    ty: impl_ty_value,
-                })
+                    bound_vars,
+                )
                 .to_predicate(tcx),
             ),
         };
         ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
     };
+    debug!(?normalize_param_env);
+
+    let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
+    let rebased_substs =
+        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
         let constness = impl_ty
@@ -1308,6 +1390,7 @@ pub fn check_type_bounds<'tcx>(
             .explicit_item_bounds(trait_ty.def_id)
             .iter()
             .map(|&(bound, span)| {
+                debug!(?bound);
                 let concrete_ty_bound = bound.subst(tcx, rebased_substs);
                 debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
 
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index a4a54bac870..808685d7fa9 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -257,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     //
                     // FIXME? Other potential candidate methods: `as_ref` and
                     // `as_mut`?
-                    .any(|a| self.sess().check_name(a, sym::rustc_conversion_suggestion))
+                    .any(|a| a.has_name(sym::rustc_conversion_suggestion))
         });
 
         methods
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 9cbd3f7bb33..eaf24552355 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -156,12 +156,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Note that inspecting a type's structure *directly* may expose the fact
     /// that there are actually multiple representations for `Error`, so avoid
     /// that when err needs to be handled differently.
+    #[instrument(skip(self), level = "debug")]
     pub(super) fn check_expr_with_expectation(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        debug!(">> type-checking: expected={:?}, expr={:?} ", expected, expr);
+        if self.tcx().sess.verbose() {
+            // make this code only run with -Zverbose because it is probably slow
+            if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                if !lint_str.contains("\n") {
+                    debug!("expr text: {}", lint_str);
+                } else {
+                    let mut lines = lint_str.lines();
+                    if let Some(line0) = lines.next() {
+                        let remaining_lines = lines.count();
+                        debug!("expr text: {}", line0);
+                        debug!("expr text: ...(and {} more lines)", remaining_lines);
+                    }
+                }
+            }
+        }
 
         // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
         // without the final expr (e.g. `try { return; }`). We don't want to generate an
@@ -1039,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let t_cast = self.to_ty_saving_user_provided_ty(t);
         let t_cast = self.resolve_vars_if_possible(t_cast);
         let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
-        let t_cast = self.resolve_vars_if_possible(t_cast);
+        let t_expr = self.resolve_vars_if_possible(t_expr);
 
         // Eagerly check for some obvious errors.
         if t_expr.references_error() || t_cast.references_error() {
@@ -1049,6 +1064,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
             match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
                 Ok(cast_check) => {
+                    debug!(
+                        "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
+                        t_cast, t_expr, cast_check,
+                    );
                     deferred_cast_checks.push(cast_check);
                     t_cast
                 }
diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_typeck/src/check/fallback.rs
index 69a8970ae09..8f6cdc7bb12 100644
--- a/compiler/rustc_typeck/src/check/fallback.rs
+++ b/compiler/rustc_typeck/src/check/fallback.rs
@@ -3,7 +3,9 @@ use rustc_infer::infer::type_variable::Diverging;
 use rustc_middle::ty::{self, Ty};
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
-    pub(super) fn type_inference_fallback(&self) {
+    /// Performs type inference fallback, returning true if any fallback
+    /// occurs.
+    pub(super) fn type_inference_fallback(&self) -> bool {
         // All type checking constraints were added, try to fallback unsolved variables.
         self.select_obligations_where_possible(false, |_| {});
         let mut fallback_has_occurred = false;
@@ -50,6 +52,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
 
         // See if we can make any more progress.
         self.select_obligations_where_possible(fallback_has_occurred, |_| {});
+
+        fallback_has_occurred
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index bb80f0879a4..f9b7bb8ea99 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -743,7 +743,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // possibly be referring to the current closure,
                     // because we haven't produced the `Closure` for
                     // this closure yet; this is exactly why the other
-                    // code is looking for a self type of a unresolved
+                    // code is looking for a self type of an unresolved
                     // inference variable.
                     ty::PredicateKind::ClosureKind(..) => None,
                     ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 9952413353f..b624e07374e 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -29,6 +29,7 @@ use std::slice;
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn check_casts(&self) {
         let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
+        debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
         for cast in deferred_cast_checks.drain(..) {
             cast.check(self);
         }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
index a466a04bd98..16f3de58078 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
@@ -96,7 +96,7 @@ pub struct FnCtxt<'a, 'tcx> {
     ///   `foo(return)`; we warn on the `foo()` expression. (We then
     ///   update the flag to `WarnedAlways` to suppress duplicate
     ///   reports.) Similarly, if we traverse to a fresh statement (or
-    ///   tail expression) from a `Always` setting, we will issue a
+    ///   tail expression) from an `Always` setting, we will issue a
     ///   warning. This corresponds to something like `{return;
     ///   foo();}` or `{return; 22}`, where we would warn on the
     ///   `foo()` or `22`.
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 2a196644dac..a88b1c7af5a 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -446,11 +446,12 @@ fn typeck_with_fallback<'tcx>(
             fcx
         };
 
-        fcx.type_inference_fallback();
+        let fallback_has_occurred = fcx.type_inference_fallback();
 
         // Even though coercion casts provide type hints, we check casts after fallback for
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
         fcx.check_casts();
+        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
 
         // Closure and generator analysis may run after fallback
         // because they don't constrain other type variables.
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 34176623ebc..fc7f55e24b2 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -1456,7 +1456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // an immut-ref after on top of this.
                 ty::Ref(.., hir::Mutability::Mut) => is_mutbl = hir::Mutability::Mut,
 
-                // The place isn't mutable once we dereference a immutable reference.
+                // The place isn't mutable once we dereference an immutable reference.
                 ty::Ref(.., hir::Mutability::Not) => return hir::Mutability::Not,
 
                 // Dereferencing a box doesn't change mutability
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index 7e5cc771b31..95d3bb11723 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -155,7 +155,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         }
 
         // If the extern crate isn't in the extern prelude,
-        // there is no way it can be written as an `use`.
+        // there is no way it can be written as a `use`.
         let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
         if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
             continue;
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 9fbf5ab8533..1c6fd5983cb 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -21,6 +21,7 @@ use crate::constrained_generic_params as cgp;
 use crate::errors;
 use crate::middle::resolve_lifetime as rl;
 use rustc_ast as ast;
+use rustc_ast::Attribute;
 use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
@@ -2769,11 +2770,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     let mut link_ordinal_span = None;
     let mut no_sanitize_span = None;
     for attr in attrs.iter() {
-        if tcx.sess.check_name(attr, sym::cold) {
+        if attr.has_name(sym::cold) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
-        } else if tcx.sess.check_name(attr, sym::rustc_allocator) {
+        } else if attr.has_name(sym::rustc_allocator) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
-        } else if tcx.sess.check_name(attr, sym::ffi_returns_twice) {
+        } else if attr.has_name(sym::ffi_returns_twice) {
             if tcx.is_foreign_item(id) {
                 codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
             } else {
@@ -2786,9 +2787,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 )
                 .emit();
             }
-        } else if tcx.sess.check_name(attr, sym::ffi_pure) {
+        } else if attr.has_name(sym::ffi_pure) {
             if tcx.is_foreign_item(id) {
-                if attrs.iter().any(|a| tcx.sess.check_name(a, sym::ffi_const)) {
+                if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
                     // `#[ffi_const]` functions cannot be `#[ffi_pure]`
                     struct_span_err!(
                         tcx.sess,
@@ -2810,7 +2811,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 )
                 .emit();
             }
-        } else if tcx.sess.check_name(attr, sym::ffi_const) {
+        } else if attr.has_name(sym::ffi_const) {
             if tcx.is_foreign_item(id) {
                 codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
             } else {
@@ -2823,19 +2824,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 )
                 .emit();
             }
-        } else if tcx.sess.check_name(attr, sym::rustc_allocator_nounwind) {
+        } else if attr.has_name(sym::rustc_allocator_nounwind) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
-        } else if tcx.sess.check_name(attr, sym::naked) {
+        } else if attr.has_name(sym::naked) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
-        } else if tcx.sess.check_name(attr, sym::no_mangle) {
+        } else if attr.has_name(sym::no_mangle) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
-        } else if tcx.sess.check_name(attr, sym::no_coverage) {
+        } else if attr.has_name(sym::no_coverage) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
-        } else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) {
+        } else if attr.has_name(sym::rustc_std_internal_symbol) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
-        } else if tcx.sess.check_name(attr, sym::used) {
+        } else if attr.has_name(sym::used) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
-        } else if tcx.sess.check_name(attr, sym::cmse_nonsecure_entry) {
+        } else if attr.has_name(sym::cmse_nonsecure_entry) {
             if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
                 struct_span_err!(
                     tcx.sess,
@@ -2850,15 +2851,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     .emit();
             }
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
-        } else if tcx.sess.check_name(attr, sym::thread_local) {
+        } else if attr.has_name(sym::thread_local) {
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
-        } else if tcx.sess.check_name(attr, sym::track_caller) {
+        } else if attr.has_name(sym::track_caller) {
             if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
                 struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
                     .emit();
             }
             codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
-        } else if tcx.sess.check_name(attr, sym::export_name) {
+        } else if attr.has_name(sym::export_name) {
             if let Some(s) = attr.value_str() {
                 if s.as_str().contains('\0') {
                     // `#[export_name = ...]` will be converted to a null-terminated string,
@@ -2873,7 +2874,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 }
                 codegen_fn_attrs.export_name = Some(s);
             }
-        } else if tcx.sess.check_name(attr, sym::target_feature) {
+        } else if attr.has_name(sym::target_feature) {
             if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal {
                 if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
                     // The `#[target_feature]` attribute is allowed on
@@ -2913,11 +2914,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 &supported_target_features,
                 &mut codegen_fn_attrs.target_features,
             );
-        } else if tcx.sess.check_name(attr, sym::linkage) {
+        } else if attr.has_name(sym::linkage) {
             if let Some(val) = attr.value_str() {
                 codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
             }
-        } else if tcx.sess.check_name(attr, sym::link_section) {
+        } else if attr.has_name(sym::link_section) {
             if let Some(val) = attr.value_str() {
                 if val.as_str().bytes().any(|b| b == 0) {
                     let msg = format!(
@@ -2930,14 +2931,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     codegen_fn_attrs.link_section = Some(val);
                 }
             }
-        } else if tcx.sess.check_name(attr, sym::link_name) {
+        } else if attr.has_name(sym::link_name) {
             codegen_fn_attrs.link_name = attr.value_str();
-        } else if tcx.sess.check_name(attr, sym::link_ordinal) {
+        } else if attr.has_name(sym::link_ordinal) {
             link_ordinal_span = Some(attr.span);
             if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
                 codegen_fn_attrs.link_ordinal = ordinal;
             }
-        } else if tcx.sess.check_name(attr, sym::no_sanitize) {
+        } else if attr.has_name(sym::no_sanitize) {
             no_sanitize_span = Some(attr.span);
             if let Some(list) = attr.meta_item_list() {
                 for item in list.iter() {
@@ -2957,7 +2958,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     }
                 }
             }
-        } else if tcx.sess.check_name(attr, sym::instruction_set) {
+        } else if attr.has_name(sym::instruction_set) {
             codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) {
                 Some(MetaItemKind::List(ref items)) => match items.as_slice() {
                     [NestedMetaItem::MetaItem(set)] => {
@@ -3026,7 +3027,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     None
                 }
             };
-        } else if tcx.sess.check_name(attr, sym::repr) {
+        } else if attr.has_name(sym::repr) {
             codegen_fn_attrs.alignment = match attr.meta_item_list() {
                 Some(items) => match items.as_slice() {
                     [item] => match item.name_value_literal() {
@@ -3064,12 +3065,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
             return ia;
         }
         match attr.meta().map(|i| i.kind) {
-            Some(MetaItemKind::Word) => {
-                tcx.sess.mark_attr_used(attr);
-                InlineAttr::Hint
-            }
+            Some(MetaItemKind::Word) => InlineAttr::Hint,
             Some(MetaItemKind::List(ref items)) => {
-                tcx.sess.mark_attr_used(attr);
                 inline_span = Some(attr.span);
                 if items.len() != 1 {
                     struct_span_err!(
@@ -3112,7 +3109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                 ia
             }
             Some(MetaItemKind::List(ref items)) => {
-                tcx.sess.mark_attr_used(attr);
                 inline_span = Some(attr.span);
                 if items.len() != 1 {
                     err(attr.span, "expected one argument");
@@ -3181,7 +3177,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     if tcx.is_weak_lang_item(id) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
     }
-    let check_name = |attr, sym| tcx.sess.check_name(attr, sym);
+    let check_name = |attr: &Attribute, sym| attr.has_name(sym);
     if let Some(name) = weak_lang_items::link_name(check_name, &attrs) {
         codegen_fn_attrs.export_name = Some(name);
         codegen_fn_attrs.link_name = Some(name);
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs
index b0c95939bb7..cd00d181ed0 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_typeck/src/expr_use_visitor.rs
@@ -120,9 +120,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     pub fn consume_body(&mut self, body: &hir::Body<'_>) {
-        debug!("consume_body(body={:?})", body);
-
         for param in body.params {
             let param_ty = return_if_err!(self.mc.pat_ty_adjusted(&param.pat));
             debug!("consume_body: param_ty = {:?}", param_ty);
@@ -819,7 +818,7 @@ fn copy_or_move<'a, 'tcx>(
 }
 
 // - If a place is used in a `ByValue` context then move it if it's not a `Copy` type.
-// - If the place that is a `Copy` type consider it a `ImmBorrow`.
+// - If the place that is a `Copy` type consider it an `ImmBorrow`.
 fn delegate_consume<'a, 'tcx>(
     mc: &mc::MemCategorizationContext<'a, 'tcx>,
     delegate: &mut (dyn Delegate<'tcx> + 'a),
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 9ed2a965dbe..61631f3b14b 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -291,7 +291,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
     }
 
     for attr in tcx.get_attrs(main_def_id) {
-        if tcx.sess.check_name(attr, sym::track_caller) {
+        if attr.has_name(sym::track_caller) {
             tcx.sess
                 .struct_span_err(
                     attr.span,
@@ -405,7 +405,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
 
                     let attrs = tcx.hir().attrs(start_id);
                     for attr in attrs {
-                        if tcx.sess.check_name(attr, sym::track_caller) {
+                        if attr.has_name(sym::track_caller) {
                             tcx.sess
                                 .struct_span_err(
                                     attr.span,
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
index 6e6ecf6a22b..ccf0fb72738 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs
@@ -297,7 +297,7 @@ pub fn check_explicit_predicates<'tcx>(
         // to apply the substs, and not filter this predicate, we might then falsely
         // conclude that e.g., `X: 'x` was a reasonable inferred requirement.
         //
-        // Another similar case is where we have a inferred
+        // Another similar case is where we have an inferred
         // requirement like `<Self as Trait>::Foo: 'b`. We presently
         // ignore such requirements as well (cc #54467)-- though
         // conceivably it might be better if we could extract the `Foo
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index a10a027ffda..3ed3c2382ca 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -387,7 +387,7 @@ pub mod __alloc_error_handler {
         panic!("memory allocation of {} bytes failed", size)
     }
 
-    // if there is a `#[alloc_error_handler]`
+    // if there is an `#[alloc_error_handler]`
     #[rustc_std_internal_symbol]
     pub unsafe extern "C" fn __rg_oom(size: usize, align: usize) -> ! {
         let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index fb340734e0b..28e4f8bba05 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -46,7 +46,7 @@
 //!     }
 //! }
 //!
-//! // Each node is represented as an `usize`, for a shorter implementation.
+//! // Each node is represented as a `usize`, for a shorter implementation.
 //! struct Edge {
 //!     node: usize,
 //!     cost: usize,
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index f6616399610..77c52e51abb 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -45,7 +45,7 @@ impl<T, const N: usize> IntoIter<T, N> {
     /// use std::array;
     ///
     /// for value in array::IntoIter::new([1, 2, 3, 4, 5]) {
-    ///     // The type of `value` is a `i32` here, instead of `&i32`
+    ///     // The type of `value` is an `i32` here, instead of `&i32`
     ///     let _: i32 = value;
     /// }
     /// ```
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index e5af22c8fbb..0dadbdd1bd0 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -958,7 +958,7 @@ impl char {
     /// Returns an iterator that yields the uppercase mapping of this `char` as one or more
     /// `char`s.
     ///
-    /// If this `char` does not have a uppercase mapping, the iterator yields the same `char`.
+    /// If this `char` does not have an uppercase mapping, the iterator yields the same `char`.
     ///
     /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character
     /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 6ad10990840..1d75ac3d254 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -4,7 +4,6 @@
 
 use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
 use crate::char::EscapeDebugExtArgs;
-use crate::iter;
 use crate::marker::PhantomData;
 use crate::mem;
 use crate::num::fmt as numfmt;
@@ -334,11 +333,29 @@ enum FlagV1 {
 impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
+    #[cfg(not(bootstrap))]
+    #[doc(hidden)]
+    #[inline]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
+    #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
+    pub const unsafe fn new_v1(
+        pieces: &'a [&'static str],
+        args: &'a [ArgumentV1<'a>],
+    ) -> Arguments<'a> {
+        if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
+            panic!("invalid args");
+        }
+        Arguments { pieces, fmt: None, args }
+    }
+    #[cfg(bootstrap)]
     #[doc(hidden)]
     #[inline]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
     #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
     pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
+        if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
+            panic!("invalid args");
+        }
         Arguments { pieces, fmt: None, args }
     }
 
@@ -348,6 +365,19 @@ impl<'a> Arguments<'a> {
     /// `CountIsParam` or `CountIsNextParam` has to point to an argument
     /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
+    #[cfg(not(bootstrap))]
+    #[doc(hidden)]
+    #[inline]
+    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
+    #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
+    pub const unsafe fn new_v1_formatted(
+        pieces: &'a [&'static str],
+        args: &'a [ArgumentV1<'a>],
+        fmt: &'a [rt::v1::Argument],
+    ) -> Arguments<'a> {
+        Arguments { pieces, fmt: Some(fmt), args }
+    }
+    #[cfg(bootstrap)]
     #[doc(hidden)]
     #[inline]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -1110,7 +1140,10 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
     match args.fmt {
         None => {
             // We can use default formatting parameters for all arguments.
-            for (arg, piece) in iter::zip(args.args, args.pieces) {
+            for (i, arg) in args.args.iter().enumerate() {
+                // SAFETY: args.args and args.pieces come from the same Arguments,
+                // which guarantees the indexes are always within bounds.
+                let piece = unsafe { args.pieces.get_unchecked(i) };
                 if !piece.is_empty() {
                     formatter.buf.write_str(*piece)?;
                 }
@@ -1121,7 +1154,10 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
         Some(fmt) => {
             // Every spec has a corresponding argument that is preceded by
             // a string piece.
-            for (arg, piece) in iter::zip(fmt, args.pieces) {
+            for (i, arg) in fmt.iter().enumerate() {
+                // SAFETY: fmt and args.pieces come from the same Arguments,
+                // which guarantees the indexes are always within bounds.
+                let piece = unsafe { args.pieces.get_unchecked(i) };
                 if !piece.is_empty() {
                     formatter.buf.write_str(*piece)?;
                 }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 272b1e3a1d7..9278dbb5498 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1013,7 +1013,7 @@ extern "rust-intrinsic" {
     /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
     /// ```
     ///
-    /// Turning an `&str` into an `&[u8]`:
+    /// Turning an `&str` into a `&[u8]`:
     ///
     /// ```
     /// // this is not a good way to do this.
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index c7e69e922c1..17697fa0e04 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -563,7 +563,7 @@ where
 }
 
 unsafe trait SpecTrustedRandomAccess: Iterator {
-    /// If `Self: TrustedRandomAccess`, it must be safe to call a
+    /// If `Self: TrustedRandomAccess`, it must be safe to call
     /// `Iterator::__iterator_get_unchecked(self, index)`.
     unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
 }
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index ebf37f97bc6..844459d77cd 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -25,7 +25,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}
 /// (lower bound is equal to upper bound), or the upper bound is [`None`].
 /// The upper bound must only be [`None`] if the actual iterator length is
 /// larger than [`usize::MAX`]. In that case, the lower bound must be
-/// [`usize::MAX`], resulting in a [`Iterator::size_hint()`] of
+/// [`usize::MAX`], resulting in an [`Iterator::size_hint()`] of
 /// `(usize::MAX, None)`.
 ///
 /// The iterator must produce exactly the number of elements it reported
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 4ab7cc24a0d..a4e57fd6a6d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -111,6 +111,7 @@
 //
 // Language features:
 #![feature(abi_unadjusted)]
+#![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
 #![feature(asm)]
 #![feature(associated_type_bounds)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 476f37699ee..a3a074ac131 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -828,6 +828,7 @@ pub(crate) mod builtin {
     /// assert_eq!(s, format!("hello {}", "world"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[allow_internal_unsafe]
     #[allow_internal_unstable(fmt_internals)]
     #[rustc_builtin_macro]
     #[macro_export]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index d6eb535fd2e..84fd1a532c1 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -660,7 +660,7 @@ pub unsafe fn zeroed<T>() -> T {
 #[rustc_diagnostic_item = "mem_uninitialized"]
 #[track_caller]
 pub unsafe fn uninitialized<T>() -> T {
-    // SAFETY: the caller must guarantee that an unitialized value is valid for `T`.
+    // SAFETY: the caller must guarantee that an uninitialized value is valid for `T`.
     unsafe {
         intrinsics::assert_uninit_valid::<T>();
         MaybeUninit::uninit().assume_init()
diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs
index 9b7efc3d556..75405f47154 100644
--- a/library/core/src/num/dec2flt/lemire.rs
+++ b/library/core/src/num/dec2flt/lemire.rs
@@ -9,7 +9,7 @@ use crate::num::dec2flt::table::{
 /// Compute a float using an extended-precision representation.
 ///
 /// Fast conversion of a the significant digits and decimal exponent
-/// a float to a extended representation with a binary float. This
+/// a float to an extended representation with a binary float. This
 /// algorithm will accurately parse the vast majority of cases,
 /// and uses a 128-bit representation (with a fallback 192-bit
 /// representation).
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 2ec6b4d15ff..85728551f53 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -47,7 +47,15 @@ pub fn panic(expr: &'static str) -> ! {
     // truncation and padding (even though none is used here). Using
     // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
-    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
+    panic_fmt(
+        #[cfg(bootstrap)]
+        fmt::Arguments::new_v1(&[expr], &[]),
+        #[cfg(not(bootstrap))]
+        // SAFETY: Arguments::new_v1 is safe with exactly one str and zero args
+        unsafe {
+            fmt::Arguments::new_v1(&[expr], &[])
+        },
+    );
 }
 
 #[inline]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 47fad15e333..02c9dadc086 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -767,7 +767,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
 ///
 /// # Examples
 ///
-/// Read an usize value from a byte buffer:
+/// Read a usize value from a byte buffer:
 ///
 /// ```
 /// use std::mem;
@@ -960,7 +960,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
 ///
 /// # Examples
 ///
-/// Write an usize value to a byte buffer:
+/// Write a usize value to a byte buffer:
 ///
 /// ```
 /// use std::mem;
@@ -1232,7 +1232,7 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
     let smoda = stride & a_minus_one;
     // SAFETY: a is power-of-two hence non-zero. stride == 0 case is handled above.
     let gcdpow = unsafe { intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a)) };
-    // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in an usize.
+    // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in a usize.
     let gcd = unsafe { unchecked_shl(1usize, gcdpow) };
 
     // SAFETY: gcd is always greater or equal to 1.
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index f25e257bf31..243922b18b5 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -262,7 +262,7 @@ pub mod token_stream {
 }
 
 /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
-/// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
+/// For example, `quote!(a + b)` will produce an expression, that, when evaluated, constructs
 /// the `TokenStream` `[Ident("a"), Punct('+', Alone), Ident("b")]`.
 ///
 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 4238c1db8b8..36077a42b48 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1247,7 +1247,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
 }
 
 impl<'a, K, V> IterMut<'a, K, V> {
-    /// Returns a iterator of references over the remaining items.
+    /// Returns an iterator of references over the remaining items.
     #[inline]
     pub(super) fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.rustc_iter() }
@@ -1276,7 +1276,7 @@ pub struct IntoIter<K, V> {
 }
 
 impl<K, V> IntoIter<K, V> {
-    /// Returns a iterator of references over the remaining items.
+    /// Returns an iterator of references over the remaining items.
     #[inline]
     pub(super) fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.rustc_iter() }
@@ -1379,7 +1379,7 @@ pub struct Drain<'a, K: 'a, V: 'a> {
 }
 
 impl<'a, K, V> Drain<'a, K, V> {
-    /// Returns a iterator of references over the remaining items.
+    /// Returns an iterator of references over the remaining items.
     #[inline]
     pub(super) fn iter(&self) -> Iter<'_, K, V> {
         Iter { base: self.base.rustc_iter() }
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index be7e099b73a..0d082648591 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -46,7 +46,7 @@ use crate::sys_common::memchr;
 ///
 /// # Extracting a raw pointer to the whole C string
 ///
-/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
+/// `CString` implements an [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
 /// trait. This method will give you a `*const c_char` which you can
 /// feed directly to extern functions that expect a nul-terminated
 /// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
@@ -730,7 +730,7 @@ impl CString {
     /// );
     /// ```
     ///
-    /// A incorrectly formatted [`Vec`] will produce an error.
+    /// An incorrectly formatted [`Vec`] will produce an error.
     ///
     /// ```
     /// #![feature(cstring_from_vec_with_nul)]
@@ -939,7 +939,7 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Arc<CStr> {
-    /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
+    /// Converts a [`CString`] into an [`Arc`]`<CStr>` without copying or allocating.
     #[inline]
     fn from(s: CString) -> Arc<CStr> {
         let arc: Arc<[u8]> = Arc::from(s.into_inner());
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs
index 0b7dc256db8..fe4e3af91ad 100644
--- a/library/std/src/ffi/mod.rs
+++ b/library/std/src/ffi/mod.rs
@@ -94,7 +94,7 @@
 //!
 //! * [`OsStr`] represents a borrowed reference to a string in a
 //! format that can be passed to the operating system. It can be
-//! converted into an UTF-8 Rust string slice in a similar way to
+//! converted into a UTF-8 Rust string slice in a similar way to
 //! [`OsString`].
 //!
 //! # Conversions
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 8f4cd6c691c..f05295f89af 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -359,7 +359,7 @@ impl OsString {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for OsString {
-    /// Converts a [`String`] into a [`OsString`].
+    /// Converts a [`String`] into an [`OsString`].
     ///
     /// This conversion does not allocate or copy memory.
     #[inline]
@@ -880,7 +880,7 @@ impl From<Box<OsStr>> for OsString {
 
 #[stable(feature = "box_from_os_string", since = "1.20.0")]
 impl From<OsString> for Box<OsStr> {
-    /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
+    /// Converts an [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
     #[inline]
     fn from(s: OsString) -> Box<OsStr> {
         s.into_boxed_os_str()
@@ -897,7 +897,7 @@ impl Clone for Box<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
-    /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
+    /// Converts an [`OsString`] into an [`Arc`]`<OsStr>` without copying or allocating.
     #[inline]
     fn from(s: OsString) -> Arc<OsStr> {
         let arc = s.inner.into_arc();
@@ -916,7 +916,7 @@ impl From<&OsStr> for Arc<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
-    /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
+    /// Converts an [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index fa073d080c6..28254fea0d3 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1150,7 +1150,7 @@ impl<'a> DerefMut for IoSliceMut<'a> {
 
 /// A buffer type used with `Write::write_vectored`.
 ///
-/// It is semantically a wrapper around an `&[u8]`, but is guaranteed to be
+/// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be
 /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
 /// Windows.
 #[stable(feature = "iovec", since = "1.36.0")]
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 605bd33a4bf..749a441d182 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -2289,7 +2289,7 @@ mod dyn_keyword {}
 /// }
 ///
 /// let mut u = IntOrFloat { f: 1.0 };
-/// // Reading the fields of an union is always unsafe
+/// // Reading the fields of a union is always unsafe
 /// assert_eq!(unsafe { u.i }, 1065353216);
 /// // Updating through any of the field will modify all of them
 /// u.i = 1073741824;
diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs
index d3569710c2b..43d930677fa 100644
--- a/library/std/src/net/addr.rs
+++ b/library/std/src/net/addr.rs
@@ -561,8 +561,8 @@ impl From<SocketAddrV6> for SocketAddr {
 impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
     /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
     ///
-    /// This conversion creates a [`SocketAddr::V4`] for a [`IpAddr::V4`]
-    /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
+    /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
+    /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
     ///
     /// `u16` is treated as port of the newly created [`SocketAddr`].
     fn from(pieces: (I, u16)) -> SocketAddr {
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index ac92cfe19cd..4165a7beaa8 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -380,7 +380,7 @@ impl IpAddr {
         matches!(self, IpAddr::V6(_))
     }
 
-    /// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped IPv6 addresses, otherwise it
+    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
     /// return `self` as-is.
     ///
     /// # Examples
@@ -1621,8 +1621,8 @@ impl Ipv6Addr {
         }
     }
 
-    /// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped addresses, otherwise it
-    /// returns self wrapped in a `IpAddr::V6`.
+    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
+    /// returns self wrapped in an `IpAddr::V6`.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs
index cd429d14269..1f9d42812ec 100644
--- a/library/std/src/os/unix/net/ancillary.rs
+++ b/library/std/src/os/unix/net/ancillary.rs
@@ -279,7 +279,7 @@ pub enum AncillaryData<'a> {
 }
 
 impl<'a> AncillaryData<'a> {
-    /// Create a `AncillaryData::ScmRights` variant.
+    /// Create an `AncillaryData::ScmRights` variant.
     ///
     /// # Safety
     ///
@@ -291,7 +291,7 @@ impl<'a> AncillaryData<'a> {
         AncillaryData::ScmRights(scm_rights)
     }
 
-    /// Create a `AncillaryData::ScmCredentials` variant.
+    /// Create an `AncillaryData::ScmCredentials` variant.
     ///
     /// # Safety
     ///
diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs
index c89b9ff1efa..8d29fa7d66f 100644
--- a/library/std/src/os/windows/ffi.rs
+++ b/library/std/src/os/windows/ffi.rs
@@ -30,7 +30,7 @@
 //! [`OsString`] is the Rust wrapper for owned strings in the
 //! preferred representation of the operating system. On Windows,
 //! this struct gets augmented with an implementation of the
-//! [`OsStringExt`] trait, which has a [`OsStringExt::from_wide`] method. This
+//! [`OsStringExt`] trait, which has an [`OsStringExt::from_wide`] method. This
 //! lets you create an [`OsString`] from a `&[u16]` slice; presumably
 //! you get such a slice out of a `WCHAR` Windows API.
 //!
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index 1cf0e9f0cf1..6f2618c63b5 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -162,7 +162,7 @@ impl io::Read for Stdin {
         }
 
         let mut utf16_buf = [0u16; MAX_BUFFER_SIZE / 2];
-        // In the worst case, an UTF-8 string can take 3 bytes for every `u16` of an UTF-16. So
+        // In the worst case, a UTF-8 string can take 3 bytes for every `u16` of a UTF-16. So
         // we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets
         // lost.
         let amount = cmp::min(buf.len() / 3, utf16_buf.len());
diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sys_common/remutex/tests.rs
index 88453ded2f9..64873b850d3 100644
--- a/library/std/src/sys_common/remutex/tests.rs
+++ b/library/std/src/sys_common/remutex/tests.rs
@@ -30,7 +30,7 @@ fn smoke() {
 #[test]
 fn is_mutex() {
     let m = unsafe {
-        // FIXME: Simplify this if Arc gets a Arc::get_pin_mut.
+        // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
         let mut m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
         Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
         Pin::new_unchecked(m)
@@ -52,7 +52,7 @@ fn is_mutex() {
 #[test]
 fn trylock_works() {
     let m = unsafe {
-        // FIXME: Simplify this if Arc gets a Arc::get_pin_mut.
+        // FIXME: Simplify this if Arc gets an Arc::get_pin_mut.
         let mut m = Arc::new(ReentrantMutex::new(()));
         Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
         Pin::new_unchecked(m)
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 1bd3cfd2200..9508bd7da59 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -785,7 +785,7 @@ pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
 /// Copied from core::str::raw::slice_unchecked
 #[inline]
 pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
-    // memory layout of an &[u8] and &Wtf8 are the same
+    // memory layout of a &[u8] and &Wtf8 are the same
     Wtf8::from_bytes_unchecked(slice::from_raw_parts(s.bytes.as_ptr().add(begin), end - begin))
 }
 
diff --git a/library/std/src/time/monotonic.rs b/library/std/src/time/monotonic.rs
index 27fee6acff3..fa96b7abff6 100644
--- a/library/std/src/time/monotonic.rs
+++ b/library/std/src/time/monotonic.rs
@@ -84,7 +84,7 @@ pub mod inner {
     pub(super) fn monotonize(raw: time::Instant) -> time::Instant {
         let delta = raw.checked_sub_instant(&ZERO).unwrap();
         // Split into seconds and nanos since Duration doesn't have a
-        // constructor that takes an u128
+        // constructor that takes a u128
         let secs = delta.as_secs() as u128;
         let nanos = delta.subsec_nanos() as u128;
         let timestamp: u128 = secs << 64 | nanos;
diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md
index 3e616f226ed..7bd46fafadf 100644
--- a/src/doc/rustc/src/lints/levels.md
+++ b/src/doc/rustc/src/lints/levels.md
@@ -1,11 +1,12 @@
 # Lint levels
 
-In `rustc`, lints are divided into four *levels*:
+In `rustc`, lints are divided into five *levels*:
 
 1. allow
 2. warn
-3. deny
-4. forbid
+3. force-warn
+4. deny
+5. forbid
 
 Each lint has a default level (explained in the lint listing later in this
 chapter), and the compiler has a default warning level. First, let's explain
@@ -57,6 +58,14 @@ warning: unused variable: `x`
   = note: to avoid this warning, consider using `_x` instead
 ```
 
+## force-warn
+
+'force-warn' is a special lint level. It's the same as 'warn' in that a lint
+at this level will produce a warning, but unlike the 'warn' level, the
+'force-warn' level cannot be overridden. If a lint is set to 'force-warn', it
+is guaranteed to warn: no more, no less. This is true even if the overall lint
+level is capped via cap-lints.
+
 ## deny
 
 A 'deny' lint produces an error if you violate it. For example, this code
@@ -87,11 +96,12 @@ This lint level gives you that.
 
 ## forbid
 
-'forbid' is a special lint level that's stronger than 'deny'. It's the same
-as 'deny' in that a lint at this level will produce an error, but unlike the
-'deny' level, the 'forbid' level can not be overridden to be anything lower
-than an error.  However, lint levels may still be capped with `--cap-lints`
-(see below) so `rustc --cap-lints warn` will make lints set to 'forbid' just
+'forbid' is a special lint level that fills the same role for 'deny' that
+'force-warn' does for 'warn'. It's the same as 'deny' in that a lint at this
+level will produce an error, but unlike the 'deny' level, the 'forbid' level
+can not be overridden to be anything lower than an error.  However, lint
+levels may still be capped with `--cap-lints` (see below) so `rustc --cap-
+lints warn` will make lints set to 'forbid' just
 warn.
 
 ## Configuring warning levels
@@ -113,8 +123,8 @@ certain lint levels. We'll talk about that last.
 
 ### Via compiler flag
 
-The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
-into allowed, warning, deny, or forbid levels, like this:
+The `-A`, `-W`, `--force-warn` `-D`, and `-F` flags let you turn one or more lints
+into allowed, warning, force-warn, deny, or forbid levels, like this:
 
 ```bash
 $ rustc lib.rs --crate-type=lib -W missing-docs
@@ -158,7 +168,7 @@ You can also pass each flag more than once for changing multiple lints:
 $ rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
 ```
 
-And of course, you can mix these four flags together:
+And of course, you can mix these five flags together:
 
 ```bash
 $ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
@@ -176,6 +186,10 @@ You can make use of this behavior by overriding the level of one specific lint o
 $ rustc lib.rs --crate-type=lib -D unused -A unused-variables
 ```
 
+Since `force-warn` and `forbid` cannot be overridden, setting
+one of them will prevent any later level for the same lint from
+taking effect.
+
 ### Via an attribute
 
 You can also modify the lint level with a crate-wide attribute:
@@ -207,7 +221,8 @@ warning: missing documentation for a function
   | ^^^^^^^^^^^^
 ```
 
-All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
+`warn`, `allow`, `deny`, and `forbid` all work this way. There is
+no way to set a lint to `force-warn` using an attribute.
 
 You can also pass in multiple lints per attribute:
 
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warn.md b/src/doc/unstable-book/src/compiler-flags/force-warn.md
deleted file mode 100644
index 052de0f379e..00000000000
--- a/src/doc/unstable-book/src/compiler-flags/force-warn.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# `force-warn`
-
-The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
-
-------------------------
-
-This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warn` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
-
-## Example
-
-```rust,ignore (partial-example)
-#![allow(dead_code)]
-
-fn dead_function() {}
-// This would normally not produce a warning even though the
-// function is not used, because dead code is being allowed
-
-fn main() {}
-```
-
-We can force a warning to be produced by providing `--force-warn dead_code` to rustc.
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index eef6985ea30..97930f10699 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -671,8 +671,7 @@ impl Options {
             return Err(1);
         }
 
-        let (lint_opts, describe_lints, lint_cap) =
-            get_cmd_lint_options(matches, error_format, &debugging_opts);
+        let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
         Ok(Options {
             input,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index d45f277a0a8..1830909d944 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -22,7 +22,7 @@ use crate::html::render::IndexItem;
 ///
 /// This structure purposefully does not implement `Clone` because it's intended
 /// to be a fairly large and expensive structure to clone. Instead this adheres
-/// to `Send` so it may be stored in a `Arc` instance and shared among the various
+/// to `Send` so it may be stored in an `Arc` instance and shared among the various
 /// rendering threads.
 #[derive(Default)]
 crate struct Cache {
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 76e7295bce3..5eb545f7582 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1331,7 +1331,7 @@ window.initSearch = function(rawSearchIndex) {
             // an array of [(Number) item type,
             //              (String) name]
             var paths = rawSearchIndex[crate].p;
-            // a array of [(String) alias name
+            // an array of [(String) alias name
             //             [Number] index to items]
             var aliases = rawSearchIndex[crate].a;
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 34fe808dae2..4eae813aff7 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -503,10 +503,11 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("disable-minification", |o| {
             o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
         }),
-        stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")),
-        stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")),
-        stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "OPT")),
-        stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "OPT")),
+        stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")),
+        stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")),
+        stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")),
+        stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "LINT")),
+        stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "LINT")),
         stable("cap-lints", |o| {
             o.optmulti(
                 "",
@@ -517,14 +518,6 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
-        unstable("force-warn", |o| {
-            o.optopt(
-                "",
-                "force-warn",
-                "Lints that will warn even if allowed somewhere else",
-                "LINTS",
-            )
-        }),
         unstable("index-page", |o| {
             o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
         }),
diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs
index 55cddf7c6c6..144a746062d 100644
--- a/src/test/debuginfo/rc_arc.rs
+++ b/src/test/debuginfo/rc_arc.rs
@@ -75,5 +75,7 @@ fn main() {
     let a1 = Arc::clone(&a);
     let w2 = Arc::downgrade(&a);
 
-    print!(""); // #break
+    zzz(); // #break
 }
+
+fn zzz() { () }
diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
index 1214e37f982..fc53acf75cb 100644
--- a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
+++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs
@@ -8,7 +8,7 @@
 // functions and the modules are enclosed in `[]`)
 //
 // In our specific instance, the earlier compilations were inlining the call
-// to`B` into `A`; thus `A` ended up with a external reference to the symbol `D`
+// to`B` into `A`; thus `A` ended up with an external reference to the symbol `D`
 // in its object code, to be resolved at subsequent link time. The LTO import
 // information provided by LLVM for those runs reflected that information: it
 // explicitly says during those runs, `B` definition and `D` declaration were
diff --git a/src/test/mir-opt/dest-prop/copy_propagation_arg.rs b/src/test/mir-opt/dest-prop/copy_propagation_arg.rs
index 41796247789..a5fb0f640b2 100644
--- a/src/test/mir-opt/dest-prop/copy_propagation_arg.rs
+++ b/src/test/mir-opt/dest-prop/copy_propagation_arg.rs
@@ -7,7 +7,7 @@ fn dummy(x: u8) -> u8 {
 
 // EMIT_MIR copy_propagation_arg.foo.DestinationPropagation.diff
 fn foo(mut x: u8) {
-    // calling `dummy` to make an use of `x` that copyprop cannot eliminate
+    // calling `dummy` to make a use of `x` that copyprop cannot eliminate
     x = dummy(x); // this will assign a local to `x`
 }
 
diff --git a/src/test/pretty/dollar-crate.pp b/src/test/pretty/dollar-crate.pp
index f4be3c1c63a..4eccba06b13 100644
--- a/src/test/pretty/dollar-crate.pp
+++ b/src/test/pretty/dollar-crate.pp
@@ -10,9 +10,11 @@ extern crate std;
 
 fn main() {
     {
-        ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
-                                                         &match () {
-                                                              () => [],
-                                                          }));
+        ::std::io::_print(match match () { () => [], } {
+                              ref args => unsafe {
+                                  ::core::fmt::Arguments::new_v1(&["rust\n"],
+                                                                 args)
+                              }
+                          });
     };
 }
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 199aee05622..a21ea520121 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -32,29 +32,39 @@ pub fn bar() ({
                   ({
                        let res =
                            ((::alloc::fmt::format as
-                                for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1
-                                                                                   as
-                                                                                   fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
-                                                                                                                                                                as
-                                                                                                                                                                &str)]
-                                                                                                                                                              as
-                                                                                                                                                              [&str; 1])
-                                                                                                                                                            as
-                                                                                                                                                            &[&str; 1]),
-                                                                                                                                                        (&(match (()
-                                                                                                                                                                     as
-                                                                                                                                                                     ())
-                                                                                                                                                               {
-                                                                                                                                                               ()
-                                                                                                                                                               =>
-                                                                                                                                                               ([]
-                                                                                                                                                                   as
-                                                                                                                                                                   [ArgumentV1; 0]),
-                                                                                                                                                           }
-                                                                                                                                                              as
-                                                                                                                                                              [ArgumentV1; 0])
-                                                                                                                                                            as
-                                                                                                                                                            &[ArgumentV1; 0]))
+                                for<'r> fn(Arguments<'r>) -> String {format})((match (match (()
+                                                                                                as
+                                                                                                ())
+                                                                                          {
+                                                                                          ()
+                                                                                          =>
+                                                                                          ([]
+                                                                                              as
+                                                                                              [ArgumentV1; 0]),
+                                                                                      }
+                                                                                         as
+                                                                                         [ArgumentV1; 0])
+                                                                                   {
+                                                                                   ref args
+                                                                                   =>
+                                                                                   unsafe
+                                                                                   {
+                                                                                       ((::core::fmt::Arguments::new_v1
+                                                                                            as
+                                                                                            unsafe fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
+                                                                                                                                                                                as
+                                                                                                                                                                                &str)]
+                                                                                                                                                                              as
+                                                                                                                                                                              [&str; 1])
+                                                                                                                                                                            as
+                                                                                                                                                                            &[&str; 1]),
+                                                                                                                                                                        (args
+                                                                                                                                                                            as
+                                                                                                                                                                            &[ArgumentV1; 0]))
+                                                                                           as
+                                                                                           Arguments)
+                                                                                   }
+                                                                               }
                                                                                   as
                                                                                   Arguments))
                                as String);
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt
index f24f7c69404..b35f3f54de9 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -31,15 +31,15 @@
    24|      1|    println!("{:?}", Foo(1));
    25|      1|
    26|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
-                                             ^0                 ^0                      ^0
+                                             ^0       ^0        ^0                      ^0
    27|      1|    assert_ne!(
    28|       |        Foo(0)
    29|       |        ,
    30|       |        Foo(5)
    31|       |        ,
    32|      0|        "{}"
-   33|      0|        ,
-   34|      0|        if
+   33|       |        ,
+   34|       |        if
    35|      0|        is_true
    36|       |        {
    37|      0|            "true message"
diff --git a/src/test/run-make/unstable-flag-required/Makefile b/src/test/run-make/unstable-flag-required/Makefile
index a9aad54162f..b8769d5f690 100644
--- a/src/test/run-make/unstable-flag-required/Makefile
+++ b/src/test/run-make/unstable-flag-required/Makefile
@@ -2,4 +2,3 @@
 
 all:
 	$(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
-	$(RUSTC) --force-warn dead_code x.rs 2>&1 | diff - force-warn.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warn.stderr b/src/test/run-make/unstable-flag-required/force-warn.stderr
deleted file mode 100644
index 1b70dc83bdb..00000000000
--- a/src/test/run-make/unstable-flag-required/force-warn.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warn=lints`
-
diff --git a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
index c077be31b20..c771c09da88 100644
--- a/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
+++ b/src/test/rustdoc-ui/coverage/allow_missing_docs.rs
@@ -8,7 +8,7 @@ pub mod mod_foo {
     pub struct Bar;
 }
 
-/// This is a struct with a `#[allow(missing_docs)]`
+/// This is a struct with an `#[allow(missing_docs)]`
 pub struct AllowTheMissingDocs {
     #[allow(missing_docs)]
     pub empty_str: String,
diff --git a/src/test/ui-fulldeps/internal-lints/pass_ty_by_ref_self.rs b/src/test/ui-fulldeps/internal-lints/pass_ty_by_ref_self.rs
index 25f6490aa35..48b140d9174 100644
--- a/src/test/ui-fulldeps/internal-lints/pass_ty_by_ref_self.rs
+++ b/src/test/ui-fulldeps/internal-lints/pass_ty_by_ref_self.rs
@@ -1,6 +1,6 @@
 // compile-flags: -Z unstable-options
 // NOTE: This test doesn't actually require `fulldeps`
-// so we could instead use it as an `ui` test.
+// so we could instead use it as a `ui` test.
 //
 // Considering that all other `internal-lints` are tested here
 // this seems like the cleaner solution though.
diff --git a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
index 4ec43708584..edfecb91036 100644
--- a/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
+++ b/src/test/ui/async-await/drop-order/drop-order-for-temporary-in-tail-return-expr.rs
@@ -10,7 +10,7 @@
 // Test the drop order for parameters relative to local variables and
 // temporaries created in the tail return expression of the function
 // body. In particular, check that this drop order is the same between
-// a `async fn` and an ordinary `fn`. See #64512.
+// an `async fn` and an ordinary `fn`. See #64512.
 
 extern crate arc_wake;
 
diff --git a/src/test/ui/async-await/issues/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs
index e9079bfdd85..3a33af2d2ee 100644
--- a/src/test/ui/async-await/issues/issue-53249.rs
+++ b/src/test/ui/async-await/issues/issue-53249.rs
@@ -8,7 +8,7 @@ use std::future::Future;
 use std::marker::Unpin;
 use std::pin::Pin;
 
-// This is a regression test for a ICE/unbounded recursion issue relating to async-await.
+// This is a regression test for an ICE/unbounded recursion issue relating to async-await.
 
 #[derive(Debug)]
 #[must_use = "futures do nothing unless polled"]
diff --git a/src/test/ui/async-await/issues/issue-69307.rs b/src/test/ui/async-await/issues/issue-69307.rs
index 4dae96ec8a6..59309a7f288 100644
--- a/src/test/ui/async-await/issues/issue-69307.rs
+++ b/src/test/ui/async-await/issues/issue-69307.rs
@@ -1,6 +1,6 @@
 // Regression test for #69307
 //
-// Having a `async { .. foo.await .. }` block appear inside of a `+=`
+// Having an `async { .. foo.await .. }` block appear inside of a `+=`
 // expression was causing an ICE due to a failure to save/restore
 // state in the AST numbering pass when entering a nested body.
 //
diff --git a/src/test/ui/attributes/key-value-expansion.stderr b/src/test/ui/attributes/key-value-expansion.stderr
index 31e93ef54f2..03ca515265c 100644
--- a/src/test/ui/attributes/key-value-expansion.stderr
+++ b/src/test/ui/attributes/key-value-expansion.stderr
@@ -17,12 +17,16 @@ LL | bug!();
 
 error: unexpected token: `{
     let res =
-        ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
-                                                            &match (&"u8",) {
-                                                                 (arg0,) =>
-                                                                 [::core::fmt::ArgumentV1::new(arg0,
-                                                                                               ::core::fmt::Display::fmt)],
-                                                             }));
+        ::alloc::fmt::format(match match (&"u8",) {
+                                       (arg0,) =>
+                                       [::core::fmt::ArgumentV1::new(arg0,
+                                                                     ::core::fmt::Display::fmt)],
+                                   } {
+                                 ref args => unsafe {
+                                     ::core::fmt::Arguments::new_v1(&[""],
+                                                                    args)
+                                 }
+                             });
     res
 }.as_str()`
   --> $DIR/key-value-expansion.rs:48:23
diff --git a/src/test/ui/attributes/register-attr-tool-unused.rs b/src/test/ui/attributes/register-attr-tool-unused.rs
index 546e372f5e3..68061465653 100644
--- a/src/test/ui/attributes/register-attr-tool-unused.rs
+++ b/src/test/ui/attributes/register-attr-tool-unused.rs
@@ -4,7 +4,5 @@
 #![feature(register_tool)]
 
 #[register_attr(attr)] //~ ERROR crate-level attribute should be an inner attribute
-                       //~| ERROR unused attribute
 #[register_tool(tool)] //~ ERROR crate-level attribute should be an inner attribute
-                       //~| ERROR unused attribute
 fn main() {}
diff --git a/src/test/ui/attributes/register-attr-tool-unused.stderr b/src/test/ui/attributes/register-attr-tool-unused.stderr
index 85a4fa4a748..8d2e1b6bc28 100644
--- a/src/test/ui/attributes/register-attr-tool-unused.stderr
+++ b/src/test/ui/attributes/register-attr-tool-unused.stderr
@@ -1,4 +1,4 @@
-error: unused attribute
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
   --> $DIR/register-attr-tool-unused.rs:6:1
    |
 LL | #[register_attr(attr)]
@@ -12,22 +12,10 @@ LL | #![deny(unused)]
    = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
 
 error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/register-attr-tool-unused.rs:6:1
-   |
-LL | #[register_attr(attr)]
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/register-attr-tool-unused.rs:8:1
-   |
-LL | #[register_tool(tool)]
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/register-attr-tool-unused.rs:8:1
+  --> $DIR/register-attr-tool-unused.rs:7:1
    |
 LL | #[register_tool(tool)]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/closures/2229_closure_analysis/issue_88118.rs b/src/test/ui/closures/2229_closure_analysis/issue_88118.rs
new file mode 100644
index 00000000000..453b7e04a36
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/issue_88118.rs
@@ -0,0 +1,15 @@
+// Regression test for #88118. Used to ICE.
+//
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(capture_disjoint_fields)]
+
+fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
+    Box::new(move |value| {
+        (|_| handler.clone()())(value);
+        None
+    }) as Box<dyn Fn(i32) -> Option<i32>>;
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed
index 982407e2e25..c82bc369f43 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed
@@ -3,7 +3,7 @@
 #![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
-// Test cases for types that implement a insignificant drop (stlib defined)
+// Test cases for types that implement an insignificant drop (stlib defined)
 
 // `t` needs Drop because one of its elements needs drop,
 // therefore precise capture might affect drop ordering
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs
index 1ac034959cb..57ab15ae8f2 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs
@@ -3,7 +3,7 @@
 #![deny(rust_2021_incompatible_closure_captures)]
 //~^ NOTE: the lint level is defined here
 
-// Test cases for types that implement a insignificant drop (stlib defined)
+// Test cases for types that implement an insignificant drop (stlib defined)
 
 // `t` needs Drop because one of its elements needs drop,
 // therefore precise capture might affect drop ordering
diff --git a/src/test/ui/closures/issue-87814-1.rs b/src/test/ui/closures/issue-87814-1.rs
new file mode 100644
index 00000000000..5cf01ddf5d7
--- /dev/null
+++ b/src/test/ui/closures/issue-87814-1.rs
@@ -0,0 +1,8 @@
+// check-pass
+fn main() {
+    let mut schema_all = vec![];
+    (0..42).for_each(|_x| match Err(()) as Result<(), _> {
+        Ok(()) => schema_all.push(()),
+        Err(_) => (),
+    });
+}
diff --git a/src/test/ui/closures/issue-87814-2.rs b/src/test/ui/closures/issue-87814-2.rs
new file mode 100644
index 00000000000..7a5facdac58
--- /dev/null
+++ b/src/test/ui/closures/issue-87814-2.rs
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(try_reserve)]
+
+fn main() {
+    let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);
+
+    let _c = || match schema_all.0.try_reserve(1) as Result<(), _> {
+        Ok(()) => (),
+        Err(_) => (),
+    };
+}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs
index 4c96d6e7ca1..2600ec7c444 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs
@@ -4,10 +4,10 @@
 
 #![deny(unused)]
 
-#[cfg_attr(FALSE,)] //~ ERROR unused attribute
+#[cfg_attr(FALSE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes
 fn _f() {}
 
-#[cfg_attr(TRUE,)] //~ ERROR unused attribute
+#[cfg_attr(TRUE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes
 fn _g() {}
 
 fn main() {}
diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr
index 67cb6530e38..87b69881353 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr
@@ -1,4 +1,4 @@
-error: unused attribute
+error: `#[cfg_attr]` does not expand to any attributes
   --> $DIR/cfg-attr-empty-is-unused.rs:7:1
    |
 LL | #[cfg_attr(FALSE,)]
@@ -11,7 +11,7 @@ LL | #![deny(unused)]
    |         ^^^^^^
    = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
 
-error: unused attribute
+error: `#[cfg_attr]` does not expand to any attributes
   --> $DIR/cfg-attr-empty-is-unused.rs:10:1
    |
 LL | #[cfg_attr(TRUE,)]
diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs
index 3febb7cffbf..8eb8f368b12 100644
--- a/src/test/ui/const-generics/defaults/default-annotation.rs
+++ b/src/test/ui/const-generics/defaults/default-annotation.rs
@@ -13,7 +13,6 @@ pub struct ConstDefaultUnstable<const N: usize = 3>;
 
 #[stable(feature = "const_default_unstable", since="none")]
 pub struct ConstDefaultStable<const N: usize = {
-    #[stable(feature = "const_default_unstable_val", since="none")]
     3
 }>;
 
diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index 66b76627c02..e59ae297da1 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,5 +1,5 @@
 // run-pass
-// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32.
+// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to an i32.
 #![feature(bench_black_box)]
 use std::hint::black_box;
 
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index b30ab446d7a..97fa775967d 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -49,14 +49,14 @@
 #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs)
 // skipping testing of cfg
 // skipping testing of cfg_attr
-#![should_panic] //~ WARN unused attribute
-#![ignore] //~ WARN unused attribute
+#![should_panic] //~ WARN `#[should_panic]` only has an effect
+#![ignore] //~ WARN `#[ignore]` only has an effect on functions
 #![no_implicit_prelude]
 #![reexport_test_harness_main = "2900"]
 // see gated-link-args.rs
 // see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700"
 // (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600")
-#![proc_macro_derive()] //~ WARN unused attribute
+#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect
 #![doc = "2400"]
 #![cold] //~ WARN attribute should be applied to a function
 //~^ WARN
@@ -182,35 +182,35 @@ mod macro_use {
     mod inner { #![macro_use] }
 
     #[macro_use] fn f() { }
-    //~^ WARN unused attribute
+    //~^ `#[macro_use]` only has an effect
 
     #[macro_use] struct S;
-    //~^ WARN unused attribute
+    //~^ `#[macro_use]` only has an effect
 
     #[macro_use] type T = S;
-    //~^ WARN unused attribute
+    //~^ `#[macro_use]` only has an effect
 
     #[macro_use] impl S { }
-    //~^ WARN unused attribute
+    //~^ `#[macro_use]` only has an effect
 }
 
 #[macro_export]
-//~^ WARN unused attribute
+//~^ WARN `#[macro_export]` only has an effect on macro definitions
 mod macro_export {
     mod inner { #![macro_export] }
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_export]` only has an effect on macro definitions
 
     #[macro_export] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_export]` only has an effect on macro definitions
 
     #[macro_export] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_export]` only has an effect on macro definitions
 
     #[macro_export] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_export]` only has an effect on macro definitions
 
     #[macro_export] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_export]` only has an effect on macro definitions
 }
 
 // At time of unit test authorship, if compiling without `--test` then
@@ -263,35 +263,34 @@ mod path {
     mod inner { #![path="3800"] }
 
     #[path = "3800"] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[path]` only has an effect
 
     #[path = "3800"]  struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[path]` only has an effect
 
     #[path = "3800"] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[path]` only has an effect
 
     #[path = "3800"] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[path]` only has an effect
 }
 
 #[automatically_derived]
-//~^ WARN unused attribute
+//~^ WARN `#[automatically_derived]` only has an effect
 mod automatically_derived {
     mod inner { #![automatically_derived] }
-    //~^ WARN unused attribute
+    //~^ WARN `#[automatically_derived]
 
     #[automatically_derived] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[automatically_derived]
 
     #[automatically_derived] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[automatically_derived]
 
     #[automatically_derived] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[automatically_derived]
 
     #[automatically_derived] impl S { }
-    //~^ WARN unused attribute
 }
 
 #[no_mangle]
@@ -335,79 +334,75 @@ mod no_mangle {
 }
 
 #[should_panic]
-//~^ WARN unused attribute
+//~^ WARN `#[should_panic]` only has an effect on
 mod should_panic {
     mod inner { #![should_panic] }
-    //~^ WARN unused attribute
+    //~^ WARN `#[should_panic]` only has an effect on
 
     #[should_panic] fn f() { }
-    //~^ WARN unused attribute
 
     #[should_panic] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[should_panic]` only has an effect on
 
     #[should_panic] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[should_panic]` only has an effect on
 
     #[should_panic] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[should_panic]` only has an effect on
 }
 
 #[ignore]
-//~^ WARN unused attribute
+//~^ WARN `#[ignore]` only has an effect on functions
 mod ignore {
     mod inner { #![ignore] }
-    //~^ WARN unused attribute
+    //~^ WARN `#[ignore]` only has an effect on functions
 
     #[ignore] fn f() { }
-    //~^ WARN unused attribute
 
     #[ignore] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[ignore]` only has an effect on functions
 
     #[ignore] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[ignore]` only has an effect on functions
 
     #[ignore] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[ignore]` only has an effect on functions
 }
 
 #[no_implicit_prelude]
-//~^ WARN unused attribute
 mod no_implicit_prelude {
     mod inner { #![no_implicit_prelude] }
-    //~^ WARN unused attribute
 
     #[no_implicit_prelude] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[no_implicit_prelude]` only has an effect
 
     #[no_implicit_prelude] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[no_implicit_prelude]` only has an effect
 
     #[no_implicit_prelude] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[no_implicit_prelude]` only has an effect
 
     #[no_implicit_prelude] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[no_implicit_prelude]` only has an effect
 }
 
 #[reexport_test_harness_main = "2900"]
-//~^ WARN unused attribute
+//~^ WARN crate-level attribute should be
 mod reexport_test_harness_main {
     mod inner { #![reexport_test_harness_main="2900"] }
-    //~^ WARN unused attribute
+    //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN crate-level attribute should be
 }
 
 // Cannot feed "2700" to `#[macro_escape]` without signaling an error.
@@ -419,41 +414,35 @@ mod macro_escape {
     //~| HELP try an outer attribute: `#[macro_use]`
 
     #[macro_escape] fn f() { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_escape]` only has an effect
 
     #[macro_escape] struct S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_escape]` only has an effect
 
     #[macro_escape] type T = S;
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_escape]` only has an effect
 
     #[macro_escape] impl S { }
-    //~^ WARN unused attribute
+    //~^ WARN `#[macro_escape]` only has an effect
 }
 
 #[no_std]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod no_std {
     mod inner { #![no_std] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[no_std] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_std] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_std] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_std] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 // At time of authorship, #[proc_macro_derive = "2500"] signals error
@@ -633,104 +622,80 @@ mod windows_subsystem {
 // BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
 
 #[crate_name = "0900"]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod crate_name {
     mod inner { #![crate_name="0900"] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[crate_name = "0900"] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_name = "0900"] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_name = "0900"] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_name = "0900"] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 #[crate_type = "0800"]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod crate_type {
     mod inner { #![crate_type="0800"] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[crate_type = "0800"] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_type = "0800"] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_type = "0800"] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[crate_type = "0800"] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 #[feature(x0600)]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod feature {
     mod inner { #![feature(x0600)] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[feature(x0600)] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[feature(x0600)] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[feature(x0600)] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[feature(x0600)] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 
 #[no_main]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod no_main_1 {
     mod inner { #![no_main] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[no_main] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_main] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_main] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[no_main] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 #[no_builtins]
@@ -747,53 +712,41 @@ mod no_builtins {
 }
 
 #[recursion_limit="0200"]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod recursion_limit {
     mod inner { #![recursion_limit="0200"] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[recursion_limit="0200"] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[recursion_limit="0200"] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[recursion_limit="0200"] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[recursion_limit="0200"] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 #[type_length_limit="0100"]
-//~^ WARN unused attribute
-//~| WARN crate-level attribute should be an inner attribute
+//~^ WARN crate-level attribute should be an inner attribute
 mod type_length_limit {
     mod inner { #![type_length_limit="0100"] }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be in the root module
+//~^ WARN crate-level attribute should be in the root module
 
     #[type_length_limit="0100"] fn f() { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[type_length_limit="0100"] struct S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[type_length_limit="0100"] type T = S;
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 
     #[type_length_limit="0100"] impl S { }
-    //~^ WARN unused attribute
-    //~| WARN crate-level attribute should be an inner attribute
+    //~^ WARN crate-level attribute should be an inner attribute
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index b0fc71c8a62..214584f47e9 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -173,7 +173,7 @@ LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -181,7 +181,7 @@ LL |     mod inner { #![macro_escape] }
    = help: try an outer attribute: `#[macro_use]`
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
@@ -200,8 +200,26 @@ warning: use of deprecated attribute `no_start`: no longer used.
 LL | #![no_start]
    | ^^^^^^^^^^^^ help: remove this attribute
 
+warning: `#[macro_export]` only has an effect on macro definitions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:1
+   |
+LL | #[macro_export]
+   | ^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:39:9
+   |
+LL | #![warn(unused_attributes, unknown_lints)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: `#[automatically_derived]` only has an effect on items
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:1
+   |
+LL | #[automatically_derived]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
 warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:297:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:1
    |
 LL |   #[no_mangle]
    |   ^^^^^^^^^^^^
@@ -215,15 +233,34 @@ LL | |     }
 LL | | }
    | |_- not a free function, impl method or static
    |
-note: the lint level is defined here
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:39:9
-   |
-LL | #![warn(unused_attributes, unknown_lints)]
-   |         ^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:1
+   |
+LL | #[should_panic]
+   | ^^^^^^^^^^^^^^^
+
+warning: `#[ignore]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:1
+   |
+LL | #[ignore]
+   | ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:1
+   |
+LL | #[reexport_test_harness_main = "2900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:1
+   |
+LL | #[no_std]
+   | ^^^^^^^^^
+
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:1
    |
 LL |   #[cold]
    |   ^^^^^^^
@@ -240,7 +277,7 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:1
    |
 LL |   #[link_name = "1900"]
    |   ^^^^^^^^^^^^^^^^^^^^^
@@ -257,7 +294,7 @@ LL | | }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:1
    |
 LL |   #[link_section = "1800"]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -273,1015 +310,697 @@ LL | | }
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
-   |
-LL | #![cold]
-   | ^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:1
    |
-LL | #![link_name = "1900"]
+LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
-   |
-LL | #![link_section = "1800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:302:17
-   |
-LL |     mod inner { #![no_mangle] }
-   |     ------------^^^^^^^^^^^^^-- not a free function, impl method or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:309:5
-   |
-LL |     #[no_mangle] struct S;
-   |     ^^^^^^^^^^^^ --------- not a free function, impl method or static
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[crate_type = "0800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:5
-   |
-LL |     #[no_mangle] type T = S;
-   |     ^^^^^^^^^^^^ ----------- not a free function, impl method or static
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:662:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[feature(x0600)]
+   | ^^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:5
-   |
-LL |     #[no_mangle] impl S { }
-   |     ^^^^^^^^^^^^ ---------- not a free function, impl method or static
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[no_main]
+   | ^^^^^^^^^^
 
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:325:9
-   |
-LL |         #[no_mangle] fn foo();
-   |         ^^^^^^^^^^^^ --------- not a free function, impl method or static
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:714:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[recursion_limit="0200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a free function, impl method or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:9
-   |
-LL |         #[no_mangle] fn bar() {}
-   |         ^^^^^^^^^^^^ ----------- not a free function, impl method or static
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[type_length_limit="0100"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:17
-   |
-LL |     mod inner { #![cold] }
-   |     ------------^^^^^^^^-- not a function
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #![should_panic]
+   | ^^^^^^^^^^^^^^^^
 
-warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
-   |
-LL |     #[cold] struct S;
-   |     ^^^^^^^ --------- not a function
+warning: `#[ignore]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #![ignore]
+   | ^^^^^^^^^^
 
-warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:5
-   |
-LL |     #[cold] type T = S;
-   |     ^^^^^^^ ----------- not a function
+warning: `#[proc_macro_derive]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #![proc_macro_derive()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attribute should be applied to a function
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
-   |
-LL |     #[cold] impl S { }
-   |     ^^^^^^^ ---------- not a function
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:5
-   |
-LL |     #[link_name = "1900"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     extern "C" { }
-   |     -------------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-help: try `#[link(name = "1900")]` instead
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:5
-   |
-LL |     #[link_name = "1900"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:17
-   |
-LL |     mod inner { #![link_name="1900"] }
-   |     ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:5
-   |
-LL |     #[link_name = "1900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
-   |
-LL |     #[link_name = "1900"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1
    |
-LL |     #[link_name = "1900"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static
+LL | #![cold]
+   | ^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a foreign function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5
-   |
-LL |     #[link_name = "1900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:17
-   |
-LL |     mod inner { #![link_section="1800"] }
-   |     ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:557:5
-   |
-LL |     #[link_section = "1800"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-
-warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:562:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
    |
-LL |     #[link_section = "1800"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static
+LL | #![link_name = "1900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to a function or static
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1
    |
-LL |     #[link_section = "1800"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
+LL | #![link_section = "1800"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:89:12
-   |
-LL | #![feature(rust1)]
-   |            ^^^^^
-   |
-   = note: `#[warn(stable_features)]` on by default
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:1
-   |
-LL | #![should_panic]
-   | ^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
-   |
-LL | #![ignore]
-   | ^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
-   |
-LL | #![proc_macro_derive()]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
+warning: `#[macro_use]` only has an effect on `extern crate` and modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:5
    |
 LL |     #[macro_use] fn f() { }
    |     ^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_use]` only has an effect on `extern crate` and modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:187:5
    |
 LL |     #[macro_use] struct S;
    |     ^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_use]` only has an effect on `extern crate` and modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:5
    |
 LL |     #[macro_use] type T = S;
    |     ^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_use]` only has an effect on `extern crate` and modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5
    |
 LL |     #[macro_use] impl S { }
    |     ^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:1
-   |
-LL | #[macro_export]
-   | ^^^^^^^^^^^^^^^
-
-warning: unused attribute
+warning: `#[macro_export]` only has an effect on macro definitions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:200:17
    |
 LL |     mod inner { #![macro_export] }
    |                 ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_export]` only has an effect on macro definitions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5
    |
 LL |     #[macro_export] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_export]` only has an effect on macro definitions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:206:5
    |
 LL |     #[macro_export] struct S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_export]` only has an effect on macro definitions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5
    |
 LL |     #[macro_export] type T = S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[macro_export]` only has an effect on macro definitions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5
    |
 LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[path]` only has an effect on modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:5
    |
 LL |     #[path = "3800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[path]` only has an effect on modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:5
    |
 LL |     #[path = "3800"]  struct S;
    |     ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[path]` only has an effect on modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
    |
 LL |     #[path = "3800"] type T = S;
    |     ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[path]` only has an effect on modules
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
    |
 LL |     #[path = "3800"] impl S { }
    |     ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:1
-   |
-LL | #[automatically_derived]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
+warning: `#[automatically_derived]` only has an effect on items
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:17
    |
 LL |     mod inner { #![automatically_derived] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[automatically_derived]` only has an effect on items
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:5
    |
 LL |     #[automatically_derived] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[automatically_derived]` only has an effect on items
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:5
    |
 LL |     #[automatically_derived] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[automatically_derived]` only has an effect on items
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:5
    |
 LL |     #[automatically_derived] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:293:5
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:17
    |
-LL |     #[automatically_derived] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![no_mangle] }
+   |     ------------^^^^^^^^^^^^^-- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:1
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:308:5
    |
-LL | #[should_panic]
-   | ^^^^^^^^^^^^^^^
+LL |     #[no_mangle] struct S;
+   |     ^^^^^^^^^^^^ --------- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:340:17
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:5
    |
-LL |     mod inner { #![should_panic] }
-   |                 ^^^^^^^^^^^^^^^^
+LL |     #[no_mangle] type T = S;
+   |     ^^^^^^^^^^^^ ----------- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:343:5
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:5
    |
-LL |     #[should_panic] fn f() { }
-   |     ^^^^^^^^^^^^^^^
+LL |     #[no_mangle] impl S { }
+   |     ^^^^^^^^^^^^ ---------- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:9
+   |
+LL |         #[no_mangle] fn foo();
+   |         ^^^^^^^^^^^^ --------- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:9
+   |
+LL |         #[no_mangle] fn bar() {}
+   |         ^^^^^^^^^^^^ ----------- not a free function, impl method or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:17
+   |
+LL |     mod inner { #![should_panic] }
+   |                 ^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:346:5
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5
    |
 LL |     #[should_panic] struct S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:5
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5
    |
 LL |     #[should_panic] type T = S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5
+warning: `#[should_panic]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5
    |
 LL |     #[should_panic] impl S { }
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:356:1
-   |
-LL | #[ignore]
-   | ^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:359:17
+warning: `#[ignore]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:17
    |
 LL |     mod inner { #![ignore] }
    |                 ^^^^^^^^^^
 
-warning: unused attribute
+warning: `#[ignore]` only has an effect on functions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:362:5
    |
-LL |     #[ignore] fn f() { }
-   |     ^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5
-   |
 LL |     #[ignore] struct S;
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5
+warning: `#[ignore]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:5
    |
 LL |     #[ignore] type T = S;
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
+warning: `#[ignore]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:5
    |
 LL |     #[ignore] impl S { }
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:1
-   |
-LL | #[no_implicit_prelude]
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:378:17
-   |
-LL |     mod inner { #![no_implicit_prelude] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:381:5
+warning: `#[no_implicit_prelude]` only has an effect on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5
    |
 LL |     #[no_implicit_prelude] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:5
+warning: `#[no_implicit_prelude]` only has an effect on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5
    |
 LL |     #[no_implicit_prelude] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:5
+warning: `#[no_implicit_prelude]` only has an effect on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:382:5
    |
 LL |     #[no_implicit_prelude] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+warning: `#[no_implicit_prelude]` only has an effect on modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:385:5
    |
 LL |     #[no_implicit_prelude] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:394:1
-   |
-LL | #[reexport_test_harness_main = "2900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:17
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:421:5
+warning: `#[macro_escape]` only has an effect on `extern crate` and modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:5
+warning: `#[macro_escape]` only has an effect on `extern crate` and modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:5
+warning: `#[macro_escape]` only has an effect on `extern crate` and modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+warning: `#[macro_escape]` only has an effect on `extern crate` and modules
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:434:1
-   |
-LL | #[no_std]
-   | ^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:434:1
-   |
-LL | #[no_std]
-   | ^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:17
-   |
-LL |     mod inner { #![no_std] }
-   |                 ^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
-   |
-LL |     #[no_std] fn f() { }
-   |     ^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5
-   |
-LL |     #[no_std] struct S;
-   |     ^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:5
-   |
-LL |     #[no_std] type T = S;
-   |     ^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5
-   |
-LL |     #[no_std] impl S { }
-   |     ^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:1
+warning: attribute should be applied to a function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:17
    |
-LL | #[crate_name = "0900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:1
+LL |     mod inner { #![cold] }
+   |     ------------^^^^^^^^-- not a function
    |
-LL | #[crate_name = "0900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:17
+warning: attribute should be applied to a function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:5
    |
-LL |     mod inner { #![crate_name="0900"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^
+LL |     #[cold] struct S;
+   |     ^^^^^^^ --------- not a function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:17
+warning: attribute should be applied to a function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
    |
-LL |     mod inner { #![crate_name="0900"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^
+LL |     #[cold] type T = S;
+   |     ^^^^^^^ ----------- not a function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5
+warning: attribute should be applied to a function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5
    |
-LL |     #[crate_name = "0900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[cold] impl S { }
+   |     ^^^^^^^ ---------- not a function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5
    |
-LL |     #[crate_name = "0900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_name = "1900"]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     extern "C" { }
+   |     -------------- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+help: try `#[link(name = "1900")]` instead
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5
+   |
+LL |     #[link_name = "1900"]
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:17
    |
-LL |     #[crate_name = "0900"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![link_name="1900"] }
+   |     ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5
    |
-LL |     #[crate_name = "0900"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_name = "1900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:517:5
    |
-LL |     #[crate_name = "0900"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_name = "1900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
    |
-LL |     #[crate_name = "0900"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_name = "1900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5
+warning: attribute should be applied to a foreign function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
    |
-LL |     #[crate_name = "0900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_name = "1900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5
+warning: attribute should be applied to a function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:17
    |
-LL |     #[crate_name = "0900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![link_section="1800"] }
+   |     ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:1
+warning: attribute should be applied to a function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:546:5
    |
-LL | #[crate_type = "0800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_section = "1800"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:1
+warning: attribute should be applied to a function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5
    |
-LL | #[crate_type = "0800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_section = "1800"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:17
+warning: attribute should be applied to a function or static
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:5
    |
-LL |     mod inner { #![crate_type="0800"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^
+LL |     #[link_section = "1800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:664:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:17
    |
-LL |     mod inner { #![crate_type="0800"] }
+LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
    |
-LL |     #[crate_type = "0800"] fn f() { }
+LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:5
    |
-LL |     #[crate_type = "0800"] fn f() { }
+LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
    |
-LL |     #[crate_type = "0800"] struct S;
+LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:639:5
    |
-LL |     #[crate_type = "0800"] struct S;
+LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5
+warning: crate-level attribute should be in the root module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:17
    |
-LL |     #[crate_type = "0800"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![crate_type="0800"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:5
    |
-LL |     #[crate_type = "0800"] type T = S;
+LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
    |
-LL |     #[crate_type = "0800"] impl S { }
+LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:5
    |
-LL |     #[crate_type = "0800"] impl S { }
+LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
-   |
-LL | #[feature(x0600)]
-   | ^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:658:5
    |
-LL | #[feature(x0600)]
-   | ^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:17
-   |
-LL |     mod inner { #![feature(x0600)] }
-   |                 ^^^^^^^^^^^^^^^^^^
+LL |     #[crate_type = "0800"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:689:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
-   |
-LL |     #[feature(x0600)] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
-   |
-LL |     #[feature(x0600)] struct S;
-   |     ^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
-   |
-LL |     #[feature(x0600)] type T = S;
-   |     ^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5
-   |
-LL |     #[feature(x0600)] impl S { }
-   |     ^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:677:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:1
-   |
-LL | #[no_main]
-   | ^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:1
-   |
-LL | #[no_main]
-   | ^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:17
-   |
-LL |     mod inner { #![no_main] }
-   |                 ^^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
-   |
-LL |     #[no_main] fn f() { }
-   |     ^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
-   |
-LL |     #[no_main] struct S;
-   |     ^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
-   |
-LL |     #[no_main] type T = S;
-   |     ^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5
-   |
-LL |     #[no_main] impl S { }
-   |     ^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:1
-   |
-LL | #[recursion_limit="0200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:1
-   |
-LL | #[recursion_limit="0200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:17
-   |
-LL |     mod inner { #![recursion_limit="0200"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5
-   |
-LL |     #[recursion_limit="0200"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5
-   |
-LL |     #[recursion_limit="0200"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
-   |
-LL |     #[recursion_limit="0200"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
-   |
-LL |     #[recursion_limit="0200"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:1
-   |
-LL | #[type_length_limit="0100"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:1
-   |
-LL | #[type_length_limit="0100"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:17
-   |
-LL |     mod inner { #![type_length_limit="0100"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
-   |
-LL |     #[type_length_limit="0100"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:739:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
-   |
-LL |     #[type_length_limit="0100"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
-   |
-LL |     #[type_length_limit="0100"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5
+warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:89:12
    |
-LL |     #[type_length_limit="0100"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![feature(rust1)]
+   |            ^^^^^
+   |
+   = note: `#[warn(stable_features)]` on by default
 
-warning: 195 warnings emitted
+warning: 148 warnings emitted
 
diff --git a/src/test/ui/generic-associated-types/issue-87429-2.rs b/src/test/ui/generic-associated-types/issue-87429-2.rs
new file mode 100644
index 00000000000..d35bb098abd
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429-2.rs
@@ -0,0 +1,20 @@
+// Derived from `issue-87429`. A test that ensures that using bound vars in the
+// predicates in the param env when checking that an associated type satisfies
+// its bounds does not cause us to not be able to use the bounds on the parameters.
+
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a, C: Eq>: for<'b> MyBound<'b, C>;
+}
+
+trait MyBound<'a, C> { }
+impl<'a, C: Eq> MyBound<'a, C> for i32 { }
+
+impl Family for () {
+    type Member<'a, C: Eq> = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs
new file mode 100644
index 00000000000..9ee07c2f1e1
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs
@@ -0,0 +1,18 @@
+// check-fail
+
+#![feature(associated_type_defaults)]
+#![feature(generic_associated_types)]
+
+trait Family {
+    // Fine, i32: PartialEq<i32>
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = i32;
+}
+
+struct Foo;
+trait Family2 {
+    // Not fine, not Foo: PartialEq<Foo>
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+    //~^ ERROR can't compare
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr
new file mode 100644
index 00000000000..01cb0bfc72c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr
@@ -0,0 +1,16 @@
+error[E0277]: can't compare `Foo` with `Foo`
+  --> $DIR/issue-87429-associated-type-default.rs:14:5
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo`
+   |
+   = help: the trait `PartialEq` is not implemented for `Foo`
+note: required by a bound in `Family2::Member`
+  --> $DIR/issue-87429-associated-type-default.rs:14:22
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.rs b/src/test/ui/generic-associated-types/issue-87429-specialization.rs
new file mode 100644
index 00000000000..b365e07feb2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429-specialization.rs
@@ -0,0 +1,25 @@
+// check-fail
+
+#![feature(specialization)]
+//~^ WARN incomplete
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+}
+
+struct I32Family;
+
+impl Family for I32Family {
+    default type Member<'a> = i32;
+}
+
+struct Foo;
+struct FooFamily;
+
+impl Family for FooFamily {
+    default type Member<'a> = Foo;
+    //~^ ERROR can't compare
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
new file mode 100644
index 00000000000..87bd35f5878
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
@@ -0,0 +1,26 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-87429-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+error[E0277]: can't compare `Foo` with `Foo`
+  --> $DIR/issue-87429-specialization.rs:21:5
+   |
+LL |     default type Member<'a> = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo`
+   |
+   = help: the trait `PartialEq` is not implemented for `Foo`
+note: required by a bound in `Family::Member`
+  --> $DIR/issue-87429-specialization.rs:8:22
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-87429.rs b/src/test/ui/generic-associated-types/issue-87429.rs
new file mode 100644
index 00000000000..f905348ae32
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-87429.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+}
+
+struct I32;
+
+impl Family for I32 {
+    type Member<'a> = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
index 828331cb950..56780237618 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
@@ -1,4 +1,4 @@
-// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
 //
 // In particular, we test this pattern in trait solving, where it is not connected
 // to any part of the source code.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
index b1b7ec6bcf1..9b9e4496a87 100644
--- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
@@ -1,4 +1,4 @@
-// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+// Test an `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
 //
 // In particular, we test this pattern in trait solving, where it is not connected
 // to any part of the source code.
diff --git a/src/test/ui/invalid/invalid-plugin-attr.rs b/src/test/ui/invalid/invalid-plugin-attr.rs
index 3ba7389d5db..3080af24500 100644
--- a/src/test/ui/invalid/invalid-plugin-attr.rs
+++ b/src/test/ui/invalid/invalid-plugin-attr.rs
@@ -1,8 +1,7 @@
 #![deny(unused_attributes)]
 #![feature(plugin)]
 
-#[plugin(bla)]  //~ ERROR unused attribute
-                //~^ ERROR should be an inner attribute
+#[plugin(bla)] //~ ERROR should be an inner attribute
 //~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated
 
 fn main() {}
diff --git a/src/test/ui/invalid/invalid-plugin-attr.stderr b/src/test/ui/invalid/invalid-plugin-attr.stderr
index c822d908ddd..d3882d33fc4 100644
--- a/src/test/ui/invalid/invalid-plugin-attr.stderr
+++ b/src/test/ui/invalid/invalid-plugin-attr.stderr
@@ -6,7 +6,7 @@ LL | #[plugin(bla)]
    |
    = note: `#[warn(deprecated)]` on by default
 
-error: unused attribute
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
   --> $DIR/invalid-plugin-attr.rs:4:1
    |
 LL | #[plugin(bla)]
@@ -18,11 +18,5 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/invalid-plugin-attr.rs:4:1
-   |
-LL | #[plugin(bla)]
-   | ^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr
index f021943da32..84746ca2c88 100644
--- a/src/test/ui/issues/issue-11692-2.stderr
+++ b/src/test/ui/issues/issue-11692-2.stderr
@@ -3,6 +3,8 @@ error: cannot find macro `test` in this scope
    |
 LL |     concat!(test!());
    |             ^^^^
+   |
+   = note: `test` is in scope, but it is an attribute: `#[test]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/cli-lint-override.rs b/src/test/ui/lint/cli-lint-override.rs
index a0a96d01be3..7d762b05c97 100644
--- a/src/test/ui/lint/cli-lint-override.rs
+++ b/src/test/ui/lint/cli-lint-override.rs
@@ -5,7 +5,7 @@
 //
 //[warn_deny] compile-flags: --warn missing_abi --deny missing_abi
 //[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi
-//[force_warn_deny] compile-flags: -Z unstable-options --force-warn missing_abi --allow missing_abi
+//[force_warn_deny] compile-flags: --force-warn missing_abi --allow missing_abi
 //[force_warn_deny] check-pass
 
 
diff --git a/src/test/ui/lint/cli-unknown-force-warn.rs b/src/test/ui/lint/cli-unknown-force-warn.rs
index 55544cc7378..f3dea87a6b6 100644
--- a/src/test/ui/lint/cli-unknown-force-warn.rs
+++ b/src/test/ui/lint/cli-unknown-force-warn.rs
@@ -1,7 +1,7 @@
 // Checks that rustc correctly errors when passed an invalid lint with
 // `--force-warn`. This is a regression test for issue #86958.
 //
-// compile-flags: -Z unstable-options --force-warn foo-qux
+// compile-flags: --force-warn foo-qux
 // error-pattern: unknown lint: `foo_qux`
 
 fn main() {}
diff --git a/src/test/ui/lint/cli-unknown-force-warn.stderr b/src/test/ui/lint/cli-unknown-force-warn.stderr
index 4367c3b4500..9ce9f405aee 100644
--- a/src/test/ui/lint/cli-unknown-force-warn.stderr
+++ b/src/test/ui/lint/cli-unknown-force-warn.stderr
@@ -6,10 +6,6 @@ error[E0602]: unknown lint: `foo_qux`
    |
    = note: requested on the command line with `--force-warn foo_qux`
 
-error[E0602]: unknown lint: `foo_qux`
-   |
-   = note: requested on the command line with `--force-warn foo_qux`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
diff --git a/src/test/ui/lint/dead-code/issue-85071-2.rs b/src/test/ui/lint/dead-code/issue-85071-2.rs
new file mode 100644
index 00000000000..f0639931c84
--- /dev/null
+++ b/src/test/ui/lint/dead-code/issue-85071-2.rs
@@ -0,0 +1,22 @@
+// A slight variation of issue-85071.rs. Here, a method is called instead
+// of a function, and the warning is about an unreachable definition
+// instead of an unreachable expression.
+
+// check-pass
+
+#![warn(unused_variables,unreachable_code)]
+
+enum Foo {}
+
+struct S;
+impl S {
+    fn f(&self) -> Foo {todo!()}
+}
+
+fn main() {
+    let s = S;
+    let x = s.f();
+    //~^ WARNING: unused variable: `x`
+    let _y = x;
+    //~^ WARNING: unreachable definition
+}
diff --git a/src/test/ui/lint/dead-code/issue-85071-2.stderr b/src/test/ui/lint/dead-code/issue-85071-2.stderr
new file mode 100644
index 00000000000..86fbd1d75e8
--- /dev/null
+++ b/src/test/ui/lint/dead-code/issue-85071-2.stderr
@@ -0,0 +1,34 @@
+warning: unreachable definition
+  --> $DIR/issue-85071-2.rs:20:9
+   |
+LL |     let x = s.f();
+   |             ----- any code following this expression is unreachable
+LL |
+LL |     let _y = x;
+   |         ^^ unreachable definition
+   |
+note: the lint level is defined here
+  --> $DIR/issue-85071-2.rs:7:26
+   |
+LL | #![warn(unused_variables,unreachable_code)]
+   |                          ^^^^^^^^^^^^^^^^
+note: this expression has type `Foo`, which is uninhabited
+  --> $DIR/issue-85071-2.rs:18:13
+   |
+LL |     let x = s.f();
+   |             ^^^^^
+
+warning: unused variable: `x`
+  --> $DIR/issue-85071-2.rs:18:9
+   |
+LL |     let x = s.f();
+   |         ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+note: the lint level is defined here
+  --> $DIR/issue-85071-2.rs:7:9
+   |
+LL | #![warn(unused_variables,unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/lint/dead-code/issue-85071.rs b/src/test/ui/lint/dead-code/issue-85071.rs
new file mode 100644
index 00000000000..d6969321cad
--- /dev/null
+++ b/src/test/ui/lint/dead-code/issue-85071.rs
@@ -0,0 +1,19 @@
+// Checks that an unreachable code warning is emitted when an expression is
+// preceded by an expression with an uninhabited type. Previously, the
+// variable liveness analysis was "smarter" than the reachability analysis
+// in this regard, which led to confusing "unused variable" warnings
+// without an accompanying explanatory "unreachable expression" warning.
+
+// check-pass
+
+#![warn(unused_variables,unreachable_code)]
+
+enum Foo {}
+fn f() -> Foo {todo!()}
+
+fn main() {
+    let x = f();
+    //~^ WARNING: unused variable: `x`
+    let _ = x;
+    //~^ WARNING: unreachable expression
+}
diff --git a/src/test/ui/lint/dead-code/issue-85071.stderr b/src/test/ui/lint/dead-code/issue-85071.stderr
new file mode 100644
index 00000000000..49555fdaa35
--- /dev/null
+++ b/src/test/ui/lint/dead-code/issue-85071.stderr
@@ -0,0 +1,34 @@
+warning: unreachable expression
+  --> $DIR/issue-85071.rs:17:13
+   |
+LL |     let x = f();
+   |             --- any code following this expression is unreachable
+LL |
+LL |     let _ = x;
+   |             ^ unreachable expression
+   |
+note: the lint level is defined here
+  --> $DIR/issue-85071.rs:9:26
+   |
+LL | #![warn(unused_variables,unreachable_code)]
+   |                          ^^^^^^^^^^^^^^^^
+note: this expression has type `Foo`, which is uninhabited
+  --> $DIR/issue-85071.rs:15:13
+   |
+LL |     let x = f();
+   |             ^^^
+
+warning: unused variable: `x`
+  --> $DIR/issue-85071.rs:15:9
+   |
+LL |     let x = f();
+   |         ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+note: the lint level is defined here
+  --> $DIR/issue-85071.rs:9:9
+   |
+LL | #![warn(unused_variables,unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/lint/force-warn/allow-warnings.rs b/src/test/ui/lint/force-warn/allow-warnings.rs
index 6ee5ba67932..adcefc7ec78 100644
--- a/src/test/ui/lint/force-warn/allow-warnings.rs
+++ b/src/test/ui/lint/force-warn/allow-warnings.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite allowing all warnings in module
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 #![allow(warnings)]
diff --git a/src/test/ui/lint/force-warn/allowed-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-by-default-lint.rs
index fd0b886d84d..b24ab822d93 100644
--- a/src/test/ui/lint/force-warn/allowed-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-by-default-lint.rs
@@ -1,5 +1,5 @@
 // --force-warn $LINT causes $LINT (which is allow-by-default) to warn
-// compile-flags: --force-warn elided_lifetimes_in_paths -Zunstable-options
+// compile-flags: --force-warn elided_lifetimes_in_paths
 // check-pass
 
 struct Foo<'a> {
diff --git a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
index 82a584ac972..08e75a775d0 100644
--- a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn const_err -Zunstable-options
+// compile-flags: --force-warn const_err
 // check-pass
 
 #![allow(const_err)]
diff --git a/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs
index 86ab12668a3..9b1edba41aa 100644
--- a/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite $LINT_GROUP (which contains $LINT) being allowed
-// compile-flags: --force-warn bare_trait_objects -Zunstable-options
+// compile-flags: --force-warn bare_trait_objects
 // check-pass
 
 #![allow(rust_2018_idioms)]
diff --git a/src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs
index 7204782a324..4ac29ff7d99 100644
--- a/src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 #![allow(dead_code)]
diff --git a/src/test/ui/lint/force-warn/cap-lints-allow.rs b/src/test/ui/lint/force-warn/cap-lints-allow.rs
index de3a1bd8dd7..9609ea99431 100644
--- a/src/test/ui/lint/force-warn/cap-lints-allow.rs
+++ b/src/test/ui/lint/force-warn/cap-lints-allow.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT casuses $LINT to warn despite --cap-lints
 // set to allow
-// compile-flags: --cap-lints allow  --force-warn bare_trait_objects -Zunstable-options
+// compile-flags: --cap-lints allow  --force-warn bare_trait_objects
 // check-pass
 
 pub trait SomeTrait {}
diff --git a/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs
index 70fb90dc199..e65f156bfdc 100644
--- a/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT to warn despite $LINT being
 // allowed in module and cap-lints set to warn
-// compile-flags: --cap-lints warn  --force-warn rust-2021-compatibility -Zunstable-options
+// compile-flags: --cap-lints warn  --force-warn rust-2021-compatibility
 // check-pass
 #![allow(ellipsis_inclusive_range_patterns)]
 
diff --git a/src/test/ui/lint/force-warn/deny-by-default-lint.rs b/src/test/ui/lint/force-warn/deny-by-default-lint.rs
index b0a15cc2fba..e371029032f 100644
--- a/src/test/ui/lint/force-warn/deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/deny-by-default-lint.rs
@@ -1,5 +1,5 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
-// compile-flags: --force-warn const_err -Zunstable-options
+// compile-flags: --force-warn const_err
 // check-pass
 
 const C: i32 = 1 / 0;
diff --git a/src/test/ui/lint/force-warn/lint-group-allow-warnings.rs b/src/test/ui/lint/force-warn/lint-group-allow-warnings.rs
index e5dcd9a7ea1..4b95f4d2dfb 100644
--- a/src/test/ui/lint/force-warn/lint-group-allow-warnings.rs
+++ b/src/test/ui/lint/force-warn/lint-group-allow-warnings.rs
@@ -1,7 +1,7 @@
 // --force-warn $LINT_GROUP causes $LINT in $LINT_GROUP to warn
 // despite all warnings being allowed in module
 // warn-by-default lint to warn
-// compile-flags: --force-warn nonstandard_style -Zunstable-options
+// compile-flags: --force-warn nonstandard_style
 // check-pass
 
 #![allow(warnings)]
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs
index dc13b2b2474..99cad614c25 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT to warn despite
 // $LINT_GROUP being allowed in module
-// compile-flags: --force-warn rust_2018_idioms -Zunstable-options
+// compile-flags: --force-warn rust_2018_idioms
 // check-pass
 
 #![allow(rust_2018_idioms)]
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs
index b7f79b3d4aa..f0aacd77340 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn rust-2018-idioms -Zunstable-options
+// compile-flags: --force-warn rust-2018-idioms
 // check-pass
 
 #![allow(bare_trait_objects)]
diff --git a/src/test/ui/lint/lint-misplaced-attr.rs b/src/test/ui/lint/lint-misplaced-attr.rs
index e5ad7a53e0c..d06917ea3f8 100644
--- a/src/test/ui/lint/lint-misplaced-attr.rs
+++ b/src/test/ui/lint/lint-misplaced-attr.rs
@@ -4,9 +4,7 @@
 #![deny(unused_attributes)]
 
 mod a {
-    #![crate_type = "bin"] //~ ERROR unused attribute
-                           //~^ ERROR should be in the root module
+    #![crate_type = "bin"] //~ ERROR should be in the root module
 }
 
-#[crate_type = "bin"] fn main() {} //~ ERROR unused attribute
-                                   //~^ ERROR should be an inner
+#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner
diff --git a/src/test/ui/lint/lint-misplaced-attr.stderr b/src/test/ui/lint/lint-misplaced-attr.stderr
index 3a7ca2f83ae..abaf4620e6f 100644
--- a/src/test/ui/lint/lint-misplaced-attr.stderr
+++ b/src/test/ui/lint/lint-misplaced-attr.stderr
@@ -1,4 +1,4 @@
-error: unused attribute
+error: crate-level attribute should be in the root module
   --> $DIR/lint-misplaced-attr.rs:7:5
    |
 LL |     #![crate_type = "bin"]
@@ -10,23 +10,11 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: crate-level attribute should be in the root module
-  --> $DIR/lint-misplaced-attr.rs:7:5
-   |
-LL |     #![crate_type = "bin"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/lint-misplaced-attr.rs:11:1
-   |
-LL | #[crate_type = "bin"] fn main() {}
-   | ^^^^^^^^^^^^^^^^^^^^^
-
 error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/lint-misplaced-attr.rs:11:1
+  --> $DIR/lint-misplaced-attr.rs:10:1
    |
 LL | #[crate_type = "bin"] fn main() {}
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
index 527d0ea9432..7c45c099304 100644
--- a/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode-1.rs
@@ -30,7 +30,7 @@ struct 对__否;
 struct ヒ__χ;
 //~^ ERROR type `ヒ__χ` should have an upper camel case name
 
-// also cannot have lowercase letter next to a underscore.
+// also cannot have lowercase letter next to an underscore.
 // so this triggers the lint:
 
 struct Hello_你好;
diff --git a/src/test/ui/lint/unused/unused-attr-macro-rules.rs b/src/test/ui/lint/unused/unused-attr-macro-rules.rs
index 396137a11d0..c0fc280ab1a 100644
--- a/src/test/ui/lint/unused/unused-attr-macro-rules.rs
+++ b/src/test/ui/lint/unused/unused-attr-macro-rules.rs
@@ -4,10 +4,9 @@
 
 // A sample of various built-in attributes.
 #[macro_export]
-#[macro_use] //~ ERROR unused attribute
-#[path="foo"] //~ ERROR unused attribute
-#[recursion_limit="1"] //~ ERROR unused attribute
-                       //~| ERROR crate-level attribute should be an inner attribute
+#[macro_use] //~ ERROR `#[macro_use]` only has an effect
+#[path="foo"] //~ ERROR #[path]` only has an effect
+#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute
 macro_rules! foo {
     () => {};
 }
diff --git a/src/test/ui/lint/unused/unused-attr-macro-rules.stderr b/src/test/ui/lint/unused/unused-attr-macro-rules.stderr
index 4606be01ac0..e3ca90d9acd 100644
--- a/src/test/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/src/test/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -1,4 +1,4 @@
-error: unused attribute
+error: `#[macro_use]` only has an effect on `extern crate` and modules
   --> $DIR/unused-attr-macro-rules.rs:7:1
    |
 LL | #[macro_use]
@@ -10,23 +10,17 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: unused attribute
+error: `#[path]` only has an effect on modules
   --> $DIR/unused-attr-macro-rules.rs:8:1
    |
 LL | #[path="foo"]
    | ^^^^^^^^^^^^^
 
-error: unused attribute
-  --> $DIR/unused-attr-macro-rules.rs:9:1
-   |
-LL | #[recursion_limit="1"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
-
 error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
   --> $DIR/unused-attr-macro-rules.rs:9:1
    |
 LL | #[recursion_limit="1"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/unused/unused-attr.rs b/src/test/ui/lint/unused/unused-attr.rs
deleted file mode 100644
index cb8ac0e6a05..00000000000
--- a/src/test/ui/lint/unused/unused-attr.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#![deny(unused_attributes)]
-#![feature(rustc_attrs)]
-
-#![rustc_dummy] //~ ERROR unused attribute
-
-#[rustc_dummy] //~ ERROR unused attribute
-extern crate core;
-
-#[rustc_dummy] //~ ERROR unused attribute
-use std::collections;
-
-#[rustc_dummy] //~ ERROR unused attribute
-extern "C" {
-    #[rustc_dummy] //~ ERROR unused attribute
-    fn foo();
-}
-
-#[rustc_dummy] //~ ERROR unused attribute
-mod foo {
-    #[rustc_dummy] //~ ERROR unused attribute
-    pub enum Foo {
-        #[rustc_dummy] //~ ERROR unused attribute
-        Bar,
-    }
-}
-
-#[rustc_dummy] //~ ERROR unused attribute
-fn bar(f: foo::Foo) {
-    match f {
-        #[rustc_dummy] //~ ERROR unused attribute
-        foo::Foo::Bar => {}
-    }
-}
-
-#[rustc_dummy] //~ ERROR unused attribute
-struct Foo {
-    #[rustc_dummy] //~ ERROR unused attribute
-    a: isize
-}
-
-#[rustc_dummy] //~ ERROR unused attribute
-trait Baz {
-    #[rustc_dummy] //~ ERROR unused attribute
-    fn blah(&self);
-    #[rustc_dummy] //~ ERROR unused attribute
-    fn blah2(&self) {}
-}
-
-fn main() {}
diff --git a/src/test/ui/lint/unused/unused-attr.stderr b/src/test/ui/lint/unused/unused-attr.stderr
deleted file mode 100644
index 707521b7802..00000000000
--- a/src/test/ui/lint/unused/unused-attr.stderr
+++ /dev/null
@@ -1,98 +0,0 @@
-error: unused attribute
-  --> $DIR/unused-attr.rs:4:1
-   |
-LL | #![rustc_dummy]
-   | ^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/unused-attr.rs:1:9
-   |
-LL | #![deny(unused_attributes)]
-   |         ^^^^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:6:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:9:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:12:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:14:5
-   |
-LL |     #[rustc_dummy]
-   |     ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:18:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:20:5
-   |
-LL |     #[rustc_dummy]
-   |     ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:22:9
-   |
-LL |         #[rustc_dummy]
-   |         ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:27:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:30:9
-   |
-LL |         #[rustc_dummy]
-   |         ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:35:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:37:5
-   |
-LL |     #[rustc_dummy]
-   |     ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:41:1
-   |
-LL | #[rustc_dummy]
-   | ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:43:5
-   |
-LL |     #[rustc_dummy]
-   |     ^^^^^^^^^^^^^^
-
-error: unused attribute
-  --> $DIR/unused-attr.rs:45:5
-   |
-LL |     #[rustc_dummy]
-   |     ^^^^^^^^^^^^^^
-
-error: aborting due to 15 previous errors
-
diff --git a/src/test/ui/macros/issue-88206.rs b/src/test/ui/macros/issue-88206.rs
new file mode 100644
index 00000000000..14e2f66068b
--- /dev/null
+++ b/src/test/ui/macros/issue-88206.rs
@@ -0,0 +1,66 @@
+// compile-flags: -Z deduplicate-diagnostics=yes
+
+#![warn(unused_imports)]
+
+use std::str::*;
+//~^ NOTE `from_utf8` is imported here, but it is a function
+//~| NOTE `from_utf8_mut` is imported here, but it is a function
+//~| NOTE `from_utf8_unchecked` is imported here, but it is a function
+
+mod hey {
+    pub trait Serialize {}
+    pub trait Deserialize {}
+
+    pub struct X(i32);
+}
+
+use hey::{Serialize, Deserialize, X};
+//~^ NOTE `Serialize` is imported here, but it is only a trait, without a derive macro
+//~| NOTE `Deserialize` is imported here, but it is a trait
+//~| NOTE `X` is imported here, but it is a struct
+
+#[derive(Serialize)]
+//~^ ERROR cannot find derive macro `Serialize`
+struct A;
+
+#[derive(from_utf8_mut)]
+//~^ ERROR cannot find derive macro `from_utf8_mut`
+struct B;
+
+#[derive(println)]
+//~^ ERROR cannot find derive macro `println`
+//~| NOTE `println` is in scope, but it is a function-like macro
+struct C;
+
+#[Deserialize]
+//~^ ERROR cannot find attribute `Deserialize`
+struct D;
+
+#[from_utf8_unchecked]
+//~^ ERROR cannot find attribute `from_utf8_unchecked`
+struct E;
+
+#[println]
+//~^ ERROR cannot find attribute `println`
+//~| NOTE `println` is in scope, but it is a function-like macro
+struct F;
+
+fn main() {
+    from_utf8!();
+    //~^ ERROR cannot find macro `from_utf8`
+
+    Box!();
+    //~^ ERROR cannot find macro `Box`
+    //~| NOTE `Box` is in scope, but it is a struct
+
+    Copy!();
+    //~^ ERROR cannot find macro `Copy`
+    //~| NOTE `Copy` is in scope, but it is a derive macro
+
+    test!();
+    //~^ ERROR cannot find macro `test`
+    //~| NOTE `test` is in scope, but it is an attribute
+
+    X!();
+    //~^ ERROR cannot find macro `X`
+}
diff --git a/src/test/ui/macros/issue-88206.stderr b/src/test/ui/macros/issue-88206.stderr
new file mode 100644
index 00000000000..f7f5b564880
--- /dev/null
+++ b/src/test/ui/macros/issue-88206.stderr
@@ -0,0 +1,114 @@
+error: cannot find macro `X` in this scope
+  --> $DIR/issue-88206.rs:64:5
+   |
+LL |     X!();
+   |     ^
+   |
+note: `X` is imported here, but it is a struct, not a macro
+  --> $DIR/issue-88206.rs:17:35
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |                                   ^
+
+error: cannot find macro `test` in this scope
+  --> $DIR/issue-88206.rs:60:5
+   |
+LL |     test!();
+   |     ^^^^
+   |
+   = note: `test` is in scope, but it is an attribute: `#[test]`
+
+error: cannot find macro `Copy` in this scope
+  --> $DIR/issue-88206.rs:56:5
+   |
+LL |     Copy!();
+   |     ^^^^
+   |
+   = note: `Copy` is in scope, but it is a derive macro: `#[derive(Copy)]`
+
+error: cannot find macro `Box` in this scope
+  --> $DIR/issue-88206.rs:52:5
+   |
+LL |     Box!();
+   |     ^^^
+   |
+   = note: `Box` is in scope, but it is a struct, not a macro
+
+error: cannot find macro `from_utf8` in this scope
+  --> $DIR/issue-88206.rs:49:5
+   |
+LL |     from_utf8!();
+   |     ^^^^^^^^^
+   |
+note: `from_utf8` is imported here, but it is a function, not a macro
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find attribute `println` in this scope
+  --> $DIR/issue-88206.rs:43:3
+   |
+LL | #[println]
+   |   ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
+
+error: cannot find attribute `from_utf8_unchecked` in this scope
+  --> $DIR/issue-88206.rs:39:3
+   |
+LL | #[from_utf8_unchecked]
+   |   ^^^^^^^^^^^^^^^^^^^
+   |
+note: `from_utf8_unchecked` is imported here, but it is a function, not an attribute
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find attribute `Deserialize` in this scope
+  --> $DIR/issue-88206.rs:35:3
+   |
+LL | #[Deserialize]
+   |   ^^^^^^^^^^^
+   |
+note: `Deserialize` is imported here, but it is a trait, not an attribute
+  --> $DIR/issue-88206.rs:17:22
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |                      ^^^^^^^^^^^
+
+error: cannot find derive macro `println` in this scope
+  --> $DIR/issue-88206.rs:30:10
+   |
+LL | #[derive(println)]
+   |          ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
+
+error: cannot find derive macro `from_utf8_mut` in this scope
+  --> $DIR/issue-88206.rs:26:10
+   |
+LL | #[derive(from_utf8_mut)]
+   |          ^^^^^^^^^^^^^
+   |
+note: `from_utf8_mut` is imported here, but it is a function, not a derive macro
+  --> $DIR/issue-88206.rs:5:5
+   |
+LL | use std::str::*;
+   |     ^^^^^^^^^^^
+
+error: cannot find derive macro `Serialize` in this scope
+  --> $DIR/issue-88206.rs:22:10
+   |
+LL | #[derive(Serialize)]
+   |          ^^^^^^^^^
+   |
+note: `Serialize` is imported here, but it is only a trait, without a derive macro
+  --> $DIR/issue-88206.rs:17:11
+   |
+LL | use hey::{Serialize, Deserialize, X};
+   |           ^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/macros/issue-88228.rs b/src/test/ui/macros/issue-88228.rs
index 615b865e9f1..cbdef5f0d40 100644
--- a/src/test/ui/macros/issue-88228.rs
+++ b/src/test/ui/macros/issue-88228.rs
@@ -13,6 +13,7 @@ struct A;
 
 #[derive(println)]
 //~^ ERROR cannot find derive macro `println`
+//~|`println` is in scope, but it is a function-like macro
 struct B;
 
 fn main() {
diff --git a/src/test/ui/macros/issue-88228.stderr b/src/test/ui/macros/issue-88228.stderr
index b164e39064c..62afa67a783 100644
--- a/src/test/ui/macros/issue-88228.stderr
+++ b/src/test/ui/macros/issue-88228.stderr
@@ -1,5 +1,5 @@
 error: cannot find macro `bla` in this scope
-  --> $DIR/issue-88228.rs:19:5
+  --> $DIR/issue-88228.rs:20:5
    |
 LL |     bla!();
    |     ^^^
@@ -12,6 +12,8 @@ error: cannot find derive macro `println` in this scope
    |
 LL | #[derive(println)]
    |          ^^^^^^^
+   |
+   = note: `println` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `Bla` in this scope
   --> $DIR/issue-88228.rs:9:10
diff --git a/src/test/ui/macros/macro-path-prelude-fail-3.stderr b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
index 1abb501ec80..70900a6bc81 100644
--- a/src/test/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/src/test/ui/macros/macro-path-prelude-fail-3.stderr
@@ -8,6 +8,8 @@ LL |     inline!();
    |
 LL |     macro_rules! line {
    |     ----------------- similarly named macro `line` defined here
+   |
+   = note: `inline` is in scope, but it is an attribute: `#[inline]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
index 1983e13db0a..ebea6d3d9d1 100644
--- a/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
+++ b/src/test/ui/nll/issue-21232-partial-init-and-erroneous-use.rs
@@ -1,4 +1,4 @@
-// This test enumerates various cases of interest where a ADT or tuple is
+// This test enumerates various cases of interest where an ADT or tuple is
 // partially initialized and then used in some way that is wrong *even*
 // after rust-lang/rust#54987 is implemented.
 //
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index a617319faea..633a6c6a0d3 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -93,30 +93,40 @@ error: cannot find macro `my_macro_attr` in this scope
    |
 LL |     my_macro_attr!();
    |     ^^^^^^^^^^^^^
+   |
+   = note: `my_macro_attr` is in scope, but it is an attribute: `#[my_macro_attr]`
 
 error: cannot find macro `MyTrait` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:33:5
    |
 LL |     MyTrait!();
    |     ^^^^^^^
+   |
+   = note: `MyTrait` is in scope, but it is a derive macro: `#[derive(MyTrait)]`
 
 error: cannot find attribute `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:38:3
    |
 LL | #[my_macro]
    |   ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:48:10
    |
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: cannot find derive macro `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:48:10
    |
 LL | #[derive(my_macro)]
    |          ^^^^^^^^
+   |
+   = note: `my_macro` is in scope, but it is a function-like macro
 
 error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
index 73e0b98296b..9d2855f5c61 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/enum.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs
@@ -30,7 +30,7 @@ fn main() {
     match enum_unit {
         NonExhaustiveEnum::Unit => 1,
         NonExhaustiveEnum::Tuple(_) => 2,
-        // This particular arm tests that a enum marked as non-exhaustive
+        // This particular arm tests that an enum marked as non-exhaustive
         // will not error if its variants are matched exhaustively.
         NonExhaustiveEnum::Struct { field } => field,
         _ => 0 // no error with wildcard
diff --git a/src/test/ui/traits/reservation-impl/non-lattice-ok.rs b/src/test/ui/traits/reservation-impl/non-lattice-ok.rs
index b894577c1f7..a71051243c8 100644
--- a/src/test/ui/traits/reservation-impl/non-lattice-ok.rs
+++ b/src/test/ui/traits/reservation-impl/non-lattice-ok.rs
@@ -5,7 +5,7 @@
 
 // Why did we ever want to do this?
 //
-// We want to eventually add a `impl<T> From<!> for T` impl. That impl conflicts
+// We want to eventually add an `impl<T> From<!> for T` impl. That impl conflicts
 // with existing impls - at least the `impl<T> From<T> for T` impl. There are
 // 2 ways we thought of for dealing with that conflict:
 //
@@ -23,7 +23,7 @@
 // actually cause any ambiguity.
 //
 // Now it turned out lattice specialization doesn't work it, because an
-// `impl<T> From<T> for Smaht<T>` would require a `impl From<!> for Smaht<!>`,
+// `impl<T> From<T> for Smaht<T>` would require an `impl From<!> for Smaht<!>`,
 // breaking backwards-compatibility in a fairly painful way. So if we want to
 // go with a known approach, we should go with a "marker trait overlap"-style
 // approach.
diff --git a/src/test/ui/union/union-nonzero.rs b/src/test/ui/union/union-nonzero.rs
index d29e7a97180..3f4f7ea1c10 100644
--- a/src/test/ui/union/union-nonzero.rs
+++ b/src/test/ui/union/union-nonzero.rs
@@ -13,7 +13,7 @@
 // optimizations to types containing unions even if they're theoretically possible. (discussion:
 // https://github.com/rust-lang/rust/issues/36394)
 //
-// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a
+// Notably this nails down part of the behavior that `MaybeUninit` assumes: that an
 // `Option<MaybeUninit<&u8>>` does not take advantage of non-zero optimization, and thus is a safe
 // construct.
 
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
index 29bd84cd0db..62199e5a2ec 100644
--- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary `unsafe` block
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5
+   |
+LL |     unsafe { println!("foo"); }
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
index e9c7efb9e8b..c1a32764039 100644
--- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
@@ -8,4 +8,7 @@ fn main() {
     let _ = async {
         unsafe { async {}.await; } //~ ERROR unnecessary `unsafe`
     };
+
+    // `format_args!` expands with a compiler-generated unsafe block
+    unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
 }
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
index 29bd84cd0db..62199e5a2ec 100644
--- a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
@@ -10,5 +10,11 @@ note: the lint level is defined here
 LL | #![deny(unused_unsafe)]
    |         ^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unnecessary `unsafe` block
+  --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5
+   |
+LL |     unsafe { println!("foo"); }
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index b4cf1971d78..4dd0ffe77ea 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -164,7 +164,7 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
         if !differing_macro_contexts(lhs.span, rhs.span) && !lhs.span.from_expansion();
         // span between BinOp LHS and RHS
         let binop_span = lhs.span.between(rhs.span);
-        // if RHS is a UnOp
+        // if RHS is an UnOp
         if let ExprKind::Unary(op, ref un_rhs) = rhs.kind;
         // from UnOp operator to UnOp operand
         let unop_operand_span = rhs.span.until(un_rhs.span);
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 2525b14e1c5..2296842e86f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -268,7 +268,7 @@ impl std::ops::Sub<&MinifyingSugg<'static>> for MinifyingSugg<'static> {
     }
 }
 
-/// a wrapper around `MinifyingSugg`, which carries a operator like currying
+/// a wrapper around `MinifyingSugg`, which carries an operator like currying
 /// so that the suggested code become more efficient (e.g. `foo + -bar` `foo - bar`).
 struct Offset {
     value: MinifyingSugg<'static>,
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index aa3067876eb..3f9110295fc 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -122,7 +122,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     // Ignore types whose layout is unknown since `is_freeze` reports every generic types as `!Freeze`,
     // making it indistinguishable from `UnsafeCell`. i.e. it isn't a tool to prove a type is
     // 'unfrozen'. However, this code causes a false negative in which
-    // a type contains a layout-unknown type, but also a unsafe cell like `const CELL: Cell<T>`.
+    // a type contains a layout-unknown type, but also an unsafe cell like `const CELL: Cell<T>`.
     // Yet, it's better than `ty.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_PROJECTION)`
     // since it works when a pointer indirection involves (`Cell<*const T>`).
     // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
@@ -266,7 +266,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                 // in other words, lint consts whose value *could* be unfrozen, not definitely is.
                 // This feels inconsistent with how the lint treats generic types,
                 // which avoids linting types which potentially become unfrozen.
-                // One could check whether a unfrozen type have a *frozen variant*
+                // One could check whether an unfrozen type have a *frozen variant*
                 // (like `body_id_opt.map_or_else(|| !has_frozen_variant(...), ...)`),
                 // and do the same as the case of generic types at impl items.
                 // Note that it isn't sufficient to check if it has an enum
@@ -293,7 +293,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
                 }) => {
                     if_chain! {
                         // Lint a trait impl item only when the definition is a generic type,
-                        // assuming a assoc const is not meant to be a interior mutable type.
+                        // assuming an assoc const is not meant to be an interior mutable type.
                         if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
                         if let Some(of_assoc_item) = specialization_graph::Node::Trait(of_trait_def_id)
                             .item(cx.tcx, impl_item.ident, AssocKind::Const, of_trait_def_id);
diff --git a/src/tools/clippy/clippy_lints/src/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/ptr_eq.rs
index d6d7049fb61..3258c9fb3fe 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_eq.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_eq.rs
@@ -74,7 +74,7 @@ impl LateLintPass<'_> for PtrEq {
     }
 }
 
-// If the given expression is a cast to an usize, return the lhs of the cast
+// If the given expression is a cast to a usize, return the lhs of the cast
 // E.g., `foo as *const _ as usize` returns `foo as *const _`.
 fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize {
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 0114a2f97a2..4fa361fedaf 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -51,7 +51,7 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     /// Will add unnecessary pair of parentheses when the
-    /// expression is not wrapped in a pair but starts with a opening parenthesis
+    /// expression is not wrapped in a pair but starts with an opening parenthesis
     /// and ends with a closing one.
     /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index b28a37cabd4..b9e317a3cfd 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -74,7 +74,7 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for bindings that shadow other bindings already in
-    /// scope, either without a initialization or with one that does not even use
+    /// scope, either without an initialization or with one that does not even use
     /// the original value.
     ///
     /// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index a28b1d78f7d..c192f9094a8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -198,7 +198,7 @@ define_Conf! {
     (enum_variant_name_threshold: u64 = 3),
     /// Lint: LARGE_ENUM_VARIANT.
     ///
-    /// The maximum size of a enum's variant to avoid box suggestion
+    /// The maximum size of an enum's variant to avoid box suggestion
     (enum_variant_size_threshold: u64 = 200),
     /// Lint: VERBOSE_BIT_MASK.
     ///
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 15c27d1a996..9ba1381da65 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -329,7 +329,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
         vec.iter().map(|elem| self.expr(elem)).collect::<Option<_>>()
     }
 
-    /// Lookup a possibly constant expression from a `ExprKind::Path`.
+    /// Lookup a possibly constant expression from an `ExprKind::Path`.
     fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<Constant> {
         let res = self.typeck_results.qpath_res(qpath, id);
         match res {
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 957ec35be6f..c06b894a738 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -469,12 +469,28 @@ impl FormatArgsExpn<'tcx> {
             if let ExpnKind::Macro(_, name) = expr.span.ctxt().outer_expn_data().kind;
             let name = name.as_str();
             if name.ends_with("format_args") || name.ends_with("format_args_nl");
-            if let ExprKind::Call(_, args) = expr.kind;
-            if let Some((strs_ref, args, fmt_expr)) = match args {
+
+            if let ExprKind::Match(inner_match, [arm], _) = expr.kind;
+
+            // `match match`, if you will
+            if let ExprKind::Match(args, [inner_arm], _) = inner_match.kind;
+            if let ExprKind::Tup(value_args) = args.kind;
+            if let Some(value_args) = value_args
+                .iter()
+                .map(|e| match e.kind {
+                    ExprKind::AddrOf(_, _, e) => Some(e),
+                    _ => None,
+                })
+                .collect();
+            if let ExprKind::Array(args) = inner_arm.body.kind;
+
+            if let ExprKind::Block(Block { stmts: [], expr: Some(expr), .. }, _) = arm.body.kind;
+            if let ExprKind::Call(_, call_args) = expr.kind;
+            if let Some((strs_ref, fmt_expr)) = match call_args {
                 // Arguments::new_v1
-                [strs_ref, args] => Some((strs_ref, args, None)),
+                [strs_ref, _] => Some((strs_ref, None)),
                 // Arguments::new_v1_formatted
-                [strs_ref, args, fmt_expr] => Some((strs_ref, args, Some(fmt_expr))),
+                [strs_ref, _, fmt_expr] => Some((strs_ref, Some(fmt_expr))),
                 _ => None,
             };
             if let ExprKind::AddrOf(BorrowKind::Ref, _, strs_arr) = strs_ref.kind;
@@ -490,17 +506,6 @@ impl FormatArgsExpn<'tcx> {
                     None
                 })
                 .collect();
-            if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args.kind;
-            if let ExprKind::Match(args, [arm], _) = args.kind;
-            if let ExprKind::Tup(value_args) = args.kind;
-            if let Some(value_args) = value_args
-                .iter()
-                .map(|e| match e.kind {
-                    ExprKind::AddrOf(_, _, e) => Some(e),
-                    _ => None,
-                })
-                .collect();
-            if let ExprKind::Array(args) = arm.body.kind;
             then {
                 Some(FormatArgsExpn {
                     format_string_span: strs_ref.span,
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 2777e5bd0c4..32a73984674 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -587,7 +587,7 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
 /// For example, if `e` represents the `v[0].a.b[x]`
 /// this method will return a tuple, composed of a `Vec`
 /// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
-/// and a `Expr` for root of them, `v`
+/// and an `Expr` for root of them, `v`
 fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
     let mut result = vec![];
     let root = loop {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 3b494e1fc85..65d93e8f86e 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -434,7 +434,7 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static>
         matches!(op, AssocOp::ShiftLeft | AssocOp::ShiftRight)
     }
 
-    /// Returns `true` if the operator is a arithmetic operator
+    /// Returns `true` if the operator is an arithmetic operator
     /// (i.e., `+`, `-`, `*`, `/`, `%`).
     fn is_arith(op: AssocOp) -> bool {
         matches!(
diff --git a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
index 535147ccc64..256a336db82 100644
--- a/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
+++ b/src/tools/clippy/tests/ui/declare_interior_mutable_const/traits.rs
@@ -117,7 +117,7 @@ impl SelfType for AtomicUsize {
     const WRAPPED_SELF: Option<Self> = Some(AtomicUsize::new(21)); //~ ERROR interior mutable
 }
 
-// Even though a constant contains a generic type, if it also have a interior mutable type,
+// Even though a constant contains a generic type, if it also have an interior mutable type,
 // it should be linted at the definition site.
 trait BothOfCellAndGeneric<T> {
     // this is a false negative in the current implementation.
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index dee1d315b3d..f291918225f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1733,7 +1733,7 @@ impl<'test> TestCx<'test> {
     }
 
     /// For each `aux-build: foo/bar` annotation, we check to find the
-    /// file in a `auxiliary` directory relative to the test itself.
+    /// file in an `auxiliary` directory relative to the test itself.
     fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths {
         let test_ab = self
             .testpaths
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index e697e1f86a9..d34dcc0f094 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -3,6 +3,7 @@
 // ```
 // npm install browser-ui-test
 // ```
+
 const fs = require("fs");
 const path = require("path");
 const os = require('os');
@@ -172,12 +173,14 @@ async function main(argv) {
     files.sort();
 
     console.log(`Running ${files.length} rustdoc-gui tests...`);
+
     if (opts["jobs"] < 1) {
         process.setMaxListeners(files.length + 1);
     } else {
-        process.setMaxListeners(opts["jobs"]);
+        process.setMaxListeners(opts["jobs"] + 1);
     }
-    let tests = [];
+
+    const tests_queue = [];
     let results = {
         successful: [],
         failed: [],
@@ -187,8 +190,7 @@ async function main(argv) {
     for (let i = 0; i < files.length; ++i) {
         const file_name = files[i];
         const testPath = path.join(opts["tests_folder"], file_name);
-        tests.push(
-            runTest(testPath, options)
+        const callback = runTest(testPath, options)
             .then(out => {
                 const [output, nb_failures] = out;
                 results[nb_failures === 0 ? "successful" : "failed"].push({
@@ -196,10 +198,10 @@ async function main(argv) {
                     output: output,
                 });
                 if (nb_failures > 0) {
-                    status_bar.erroneous()
+                    status_bar.erroneous();
                     failed = true;
                 } else {
-                    status_bar.successful()
+                    status_bar.successful();
                 }
             })
             .catch(err => {
@@ -210,13 +212,19 @@ async function main(argv) {
                 status_bar.erroneous();
                 failed = true;
             })
-        );
+            .finally(() => {
+                // We now remove the promise from the tests_queue.
+                tests_queue.splice(tests_queue.indexOf(callback), 1);
+            });
+        tests_queue.push(callback);
         if (no_headless) {
-            await tests[i];
+            await tests_queue[i];
+        } else if (opts["jobs"] > 0 && tests_queue.length >= opts["jobs"]) {
+            await Promise.race(tests_queue);
         }
     }
-    if (!no_headless) {
-        await Promise.all(tests);
+    if (!no_headless && tests_queue.length > 0) {
+        await Promise.all(tests_queue);
     }
     status_bar.finish();
 
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index c8ee590b6cc..a9bc89544d8 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -401,7 +401,7 @@ fn rewrite_macro_inner(
                 handle_vec_semi(context, shape, arg_vec, macro_name, style)
             } else {
                 // If we are rewriting `vec!` macro or other special macros,
-                // then we can rewrite this as an usual array literal.
+                // then we can rewrite this as a usual array literal.
                 // Otherwise, we must preserve the original existence of trailing comma.
                 let macro_name = &macro_name.as_str();
                 let mut force_trailing_comma = if trailing_comma {
diff --git a/src/tools/rustfmt/src/string.rs b/src/tools/rustfmt/src/string.rs
index 0cb9d817ca2..64ae15672df 100644
--- a/src/tools/rustfmt/src/string.rs
+++ b/src/tools/rustfmt/src/string.rs
@@ -153,7 +153,7 @@ pub(crate) fn rewrite_string<'a>(
     wrap_str(result, fmt.config.max_width(), fmt.shape)
 }
 
-/// Returns the index to the end of the URL if the split at index of the given string includes an
+/// Returns the index to the end of the URL if the split at index of the given string includes a
 /// URL or alike. Otherwise, returns `None`.
 fn detect_url(s: &[&str], index: usize) -> Option<usize> {
     let start = match s[..=index].iter().rposition(|g| is_whitespace(g)) {
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 3f251bf7c16..770693d165b 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -36,7 +36,7 @@ pub(crate) struct SnippetProvider {
     big_snippet: Lrc<String>,
     /// A position of the start of `big_snippet`, used as an offset.
     start_pos: usize,
-    /// A end position of the file that this snippet lives.
+    /// An end position of the file that this snippet lives.
     end_pos: usize,
 }
 
diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
index 50d5cfa87c4..4c71a2c6ab9 100644
--- a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
@@ -2,7 +2,7 @@
 //!
 //! The features are detected using the `detect_features` function below.
 //! This function uses the CPUID instruction to read the feature flags from the
-//! CPU and encodes them in an `usize` where each bit position represents
+//! CPU and encodes them in a `usize` where each bit position represents
 //! whether a feature is available (bit is set) or unavaiable (bit is cleared).
 //!
 //! The enum `Feature` is used to map bit positions to feature names, and the
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
index 9219a4a577f..b985dd8caa1 100644
--- a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
@@ -2,7 +2,7 @@
 //!
 //! The features are detected using the `detect_features` function below.
 //! This function uses the CPUID instruction to read the feature flags from the
-//! CPU and encodes them in an `usize` where each bit position represents
+//! CPU and encodes them in a `usize` where each bit position represents
 //! whether a feature is available (bit is set) or unavaiable (bit is cleared).
 //!
 //! The enum `Feature` is used to map bit positions to feature names, and the
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index d8d3dc3ddb1..022a3dfde82 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -66,7 +66,7 @@ enum LIUState {
     EXP_END,
 }
 
-/// Returns `true` if `line` appears to be a line comment containing an URL,
+/// Returns `true` if `line` appears to be a line comment containing a URL,
 /// possibly with a Markdown link label in front, and nothing else.
 /// The Markdown link label, if present, may not contain whitespace.
 /// Lines of this form are allowed to be overlength, because Markdown