about summary refs log tree commit diff
path: root/compiler/rustc_passes
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs28
-rw-r--r--compiler/rustc_passes/src/errors.rs187
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_passes/src/lib_features.rs8
-rw-r--r--compiler/rustc_passes/src/liveness.rs183
5 files changed, 247 insertions, 160 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5789531d2ff..f376da29bd9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -16,6 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
 use rustc_hir::{MethodKind, Target};
 use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::{
@@ -172,6 +173,9 @@ impl CheckAttrVisitor<'_> {
                 sym::no_implicit_prelude => {
                     self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
                 }
+                sym::rustc_object_lifetime_default => {
+                    self.check_object_lifetime_default(hir_id, span)
+                }
                 _ => {}
             }
 
@@ -410,6 +414,30 @@ impl CheckAttrVisitor<'_> {
         }
     }
 
+    /// Debugging aid for `object_lifetime_default` query.
+    fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) {
+        let tcx = self.tcx;
+        if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
+            let object_lifetime_default_reprs: String = generics
+                .params
+                .iter()
+                .filter_map(|p| {
+                    let param_id = tcx.hir().local_def_id(p.hir_id);
+                    let default = tcx.object_lifetime_default(param_id)?;
+                    Some(match default {
+                        ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
+                        ObjectLifetimeDefault::Static => "'static".to_owned(),
+                        ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
+                        ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
+                    })
+                })
+                .collect::<Vec<String>>()
+                .join(",");
+
+            tcx.sess.span_err(span, &object_lifetime_default_reprs);
+        }
+    }
+
     /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
     fn check_track_caller(
         &self,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index cd465380867..901f56ad96d 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,37 +3,37 @@ use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(LintDiagnostic)]
-#[lint(passes::outer_crate_level_attr)]
+#[diag(passes::outer_crate_level_attr)]
 pub struct OuterCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inner_crate_level_attr)]
+#[diag(passes::inner_crate_level_attr)]
 pub struct InnerCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr_with_macro)]
+#[diag(passes::ignored_attr_with_macro)]
 pub struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr)]
+#[diag(passes::ignored_attr)]
 pub struct IgnoredAttr<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_function_prototype)]
+#[diag(passes::inline_ignored_function_prototype)]
 pub struct IgnoredInlineAttrFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_constants)]
-#[warn_]
+#[diag(passes::inline_ignored_constants)]
+#[warning]
 #[note]
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -42,19 +42,19 @@ pub struct InlineNotFnOrClosure {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes::no_coverage_ignored_function_prototype)]
 pub struct IgnoredNoCoverageFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_propagate)]
+#[diag(passes::no_coverage_propagate)]
 pub struct IgnoredNoCoveragePropagate;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_fn_defn)]
+#[diag(passes::no_coverage_fn_defn)]
 pub struct IgnoredNoCoverageFnDefn;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_coverage_not_coverable, code = "E0788")]
+#[diag(passes::no_coverage_not_coverable, code = "E0788")]
 pub struct IgnoredNoCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -63,7 +63,7 @@ pub struct IgnoredNoCoverageNotCoverable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn)]
+#[diag(passes::should_be_applied_to_fn)]
 pub struct AttrShouldBeAppliedToFn {
     #[primary_span]
     pub attr_span: Span,
@@ -72,14 +72,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::naked_tracked_caller, code = "E0736")]
+#[diag(passes::naked_tracked_caller, code = "E0736")]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn, code = "E0739")]
+#[diag(passes::should_be_applied_to_fn, code = "E0739")]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -88,7 +88,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -97,7 +97,7 @@ pub struct NonExhaustiveWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_trait)]
+#[diag(passes::should_be_applied_to_trait)]
 pub struct AttrShouldBeAppliedToTrait {
     #[primary_span]
     pub attr_span: Span,
@@ -106,11 +106,11 @@ pub struct AttrShouldBeAppliedToTrait {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::target_feature_on_statement)]
+#[diag(passes::target_feature_on_statement)]
 pub struct TargetFeatureOnStatement;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_static)]
+#[diag(passes::should_be_applied_to_static)]
 pub struct AttrShouldBeAppliedToStatic {
     #[primary_span]
     pub attr_span: Span,
@@ -119,7 +119,7 @@ pub struct AttrShouldBeAppliedToStatic {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_expect_str)]
+#[diag(passes::doc_expect_str)]
 pub struct DocExpectStr<'a> {
     #[primary_span]
     pub attr_span: Span,
@@ -127,7 +127,7 @@ pub struct DocExpectStr<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_empty)]
+#[diag(passes::doc_alias_empty)]
 pub struct DocAliasEmpty<'a> {
     #[primary_span]
     pub span: Span,
@@ -135,7 +135,7 @@ pub struct DocAliasEmpty<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_char)]
+#[diag(passes::doc_alias_bad_char)]
 pub struct DocAliasBadChar<'a> {
     #[primary_span]
     pub span: Span,
@@ -144,7 +144,7 @@ pub struct DocAliasBadChar<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_start_end)]
+#[diag(passes::doc_alias_start_end)]
 pub struct DocAliasStartEnd<'a> {
     #[primary_span]
     pub span: Span,
@@ -152,7 +152,7 @@ pub struct DocAliasStartEnd<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_location)]
+#[diag(passes::doc_alias_bad_location)]
 pub struct DocAliasBadLocation<'a> {
     #[primary_span]
     pub span: Span,
@@ -161,7 +161,7 @@ pub struct DocAliasBadLocation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_an_alias)]
+#[diag(passes::doc_alias_not_an_alias)]
 pub struct DocAliasNotAnAlias<'a> {
     #[primary_span]
     pub span: Span,
@@ -169,42 +169,42 @@ pub struct DocAliasNotAnAlias<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_alias_duplicated)]
+#[diag(passes::doc_alias_duplicated)]
 pub struct DocAliasDuplicated {
     #[label]
     pub first_defn: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_string_literal)]
+#[diag(passes::doc_alias_not_string_literal)]
 pub struct DocAliasNotStringLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_malformed)]
+#[diag(passes::doc_alias_malformed)]
 pub struct DocAliasMalformed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_empty_mod)]
+#[diag(passes::doc_keyword_empty_mod)]
 pub struct DocKeywordEmptyMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_not_mod)]
+#[diag(passes::doc_keyword_not_mod)]
 pub struct DocKeywordNotMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_invalid_ident)]
+#[diag(passes::doc_keyword_invalid_ident)]
 pub struct DocKeywordInvalidIdent {
     #[primary_span]
     pub span: Span,
@@ -212,21 +212,21 @@ pub struct DocKeywordInvalidIdent {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_fake_variadic_not_valid)]
+#[diag(passes::doc_fake_variadic_not_valid)]
 pub struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_only_impl)]
+#[diag(passes::doc_keyword_only_impl)]
 pub struct DocKeywordOnlyImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_inline_conflict)]
+#[diag(passes::doc_inline_conflict)]
 #[help]
 pub struct DocKeywordConflict {
     #[primary_span]
@@ -234,7 +234,7 @@ pub struct DocKeywordConflict {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_inline_only_use)]
+#[diag(passes::doc_inline_only_use)]
 #[note]
 pub struct DocInlineOnlyUse {
     #[label]
@@ -244,7 +244,7 @@ pub struct DocInlineOnlyUse {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_attr_not_crate_level)]
+#[diag(passes::doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
     #[primary_span]
     pub span: Span,
@@ -252,27 +252,27 @@ pub struct DocAttrNotCrateLevel<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown)]
+#[diag(passes::doc_test_unknown)]
 pub struct DocTestUnknown {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_takes_list)]
+#[diag(passes::doc_test_takes_list)]
 pub struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_primitive)]
+#[diag(passes::doc_primitive)]
 pub struct DocPrimitive;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_any)]
+#[diag(passes::doc_test_unknown_any)]
 pub struct DocTestUnknownAny {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_spotlight)]
+#[diag(passes::doc_test_unknown_spotlight)]
 #[note]
 #[note(passes::no_op_note)]
 pub struct DocTestUnknownSpotlight {
@@ -282,7 +282,7 @@ pub struct DocTestUnknownSpotlight {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_include)]
+#[diag(passes::doc_test_unknown_include)]
 pub struct DocTestUnknownInclude {
     pub path: String,
     pub value: String,
@@ -292,11 +292,11 @@ pub struct DocTestUnknownInclude {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_invalid)]
+#[diag(passes::doc_invalid)]
 pub struct DocInvalid;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::pass_by_value)]
+#[diag(passes::pass_by_value)]
 pub struct PassByValue {
     #[primary_span]
     pub attr_span: Span,
@@ -305,7 +305,7 @@ pub struct PassByValue {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_incoherent_impl)]
+#[diag(passes::allow_incoherent_impl)]
 pub struct AllowIncoherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -314,7 +314,7 @@ pub struct AllowIncoherentImpl {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::has_incoherent_inherent_impl)]
+#[diag(passes::has_incoherent_inherent_impl)]
 pub struct HasIncoherentInherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -323,21 +323,21 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_async)]
+#[diag(passes::must_use_async)]
 pub struct MustUseAsync {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_no_effect)]
+#[diag(passes::must_use_no_effect)]
 pub struct MustUseNoEffect {
     pub article: &'static str,
     pub target: rustc_hir::Target,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::must_not_suspend)]
+#[diag(passes::must_not_suspend)]
 pub struct MustNotSuspend {
     #[primary_span]
     pub attr_span: Span,
@@ -346,24 +346,24 @@ pub struct MustNotSuspend {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::cold)]
-#[warn_]
+#[diag(passes::cold)]
+#[warning]
 pub struct Cold {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link)]
-#[warn_]
+#[diag(passes::link)]
+#[warning]
 pub struct Link {
     #[label]
     pub span: Option<Span>,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_name)]
-#[warn_]
+#[diag(passes::link_name)]
+#[warning]
 pub struct LinkName<'a> {
     #[help]
     pub attr_span: Option<Span>,
@@ -373,7 +373,7 @@ pub struct LinkName<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_link)]
+#[diag(passes::no_link)]
 pub struct NoLink {
     #[primary_span]
     pub attr_span: Span,
@@ -382,7 +382,7 @@ pub struct NoLink {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::export_name)]
+#[diag(passes::export_name)]
 pub struct ExportName {
     #[primary_span]
     pub attr_span: Span,
@@ -391,7 +391,7 @@ pub struct ExportName {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
 pub struct RustcLayoutScalarValidRangeNotStruct {
     #[primary_span]
     pub attr_span: Span,
@@ -400,14 +400,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_arg)]
+#[diag(passes::rustc_layout_scalar_valid_range_arg)]
 pub struct RustcLayoutScalarValidRangeArg {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_only)]
+#[diag(passes::rustc_legacy_const_generics_only)]
 pub struct RustcLegacyConstGenericsOnly {
     #[primary_span]
     pub attr_span: Span,
@@ -416,7 +416,7 @@ pub struct RustcLegacyConstGenericsOnly {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index)]
+#[diag(passes::rustc_legacy_const_generics_index)]
 pub struct RustcLegacyConstGenericsIndex {
     #[primary_span]
     pub attr_span: Span,
@@ -425,7 +425,7 @@ pub struct RustcLegacyConstGenericsIndex {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_exceed)]
+#[diag(passes::rustc_legacy_const_generics_index_exceed)]
 pub struct RustcLegacyConstGenericsIndexExceed {
     #[primary_span]
     #[label]
@@ -434,30 +434,30 @@ pub struct RustcLegacyConstGenericsIndexExceed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_negative)]
+#[diag(passes::rustc_legacy_const_generics_index_negative)]
 pub struct RustcLegacyConstGenericsIndexNegative {
     #[primary_span]
     pub invalid_args: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_dirty_clean)]
+#[diag(passes::rustc_dirty_clean)]
 pub struct RustcDirtyClean {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_section)]
-#[warn_]
+#[diag(passes::link_section)]
+#[warning]
 pub struct LinkSection {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle_foreign)]
-#[warn_]
+#[diag(passes::no_mangle_foreign)]
+#[warning]
 #[note]
 pub struct NoMangleForeign {
     #[label]
@@ -468,40 +468,40 @@ pub struct NoMangleForeign {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle)]
-#[warn_]
+#[diag(passes::no_mangle)]
+#[warning]
 pub struct NoMangle {
     #[label]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::repr_ident, code = "E0565")]
+#[diag(passes::repr_ident, code = "E0565")]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::repr_conflicting, code = "E0566")]
+#[diag(passes::repr_conflicting, code = "E0566")]
 pub struct ReprConflicting;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_static)]
+#[diag(passes::used_static)]
 pub struct UsedStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_compiler_linker)]
+#[diag(passes::used_compiler_linker)]
 pub struct UsedCompilerLinker {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_internal_unstable)]
+#[diag(passes::allow_internal_unstable)]
 pub struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -510,14 +510,14 @@ pub struct AllowInternalUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_placement)]
+#[diag(passes::debug_visualizer_placement)]
 pub struct DebugVisualizerPlacement {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_invalid)]
+#[diag(passes::debug_visualizer_invalid)]
 #[note(passes::note_1)]
 #[note(passes::note_2)]
 #[note(passes::note_3)]
@@ -527,7 +527,7 @@ pub struct DebugVisualizerInvalid {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_allow_const_fn_unstable)]
+#[diag(passes::rustc_allow_const_fn_unstable)]
 pub struct RustcAllowConstFnUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -536,7 +536,7 @@ pub struct RustcAllowConstFnUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_std_internal_symbol)]
+#[diag(passes::rustc_std_internal_symbol)]
 pub struct RustcStdInternalSymbol {
     #[primary_span]
     pub attr_span: Span,
@@ -545,42 +545,42 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::const_trait)]
+#[diag(passes::const_trait)]
 pub struct ConstTrait {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::link_ordinal)]
+#[diag(passes::link_ordinal)]
 pub struct LinkOrdinal {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::stability_promotable)]
+#[diag(passes::stability_promotable)]
 pub struct StabilityPromotable {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::deprecated)]
+#[diag(passes::deprecated)]
 pub struct Deprecated;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_use)]
+#[diag(passes::macro_use)]
 pub struct MacroUse {
     pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_export)]
+#[diag(passes::macro_export)]
 pub struct MacroExport;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::plugin_registrar)]
+#[diag(passes::plugin_registrar)]
 pub struct PluginRegistrar;
 
 #[derive(SessionSubdiagnostic)]
@@ -594,7 +594,7 @@ pub enum UnusedNote {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused)]
+#[diag(passes::unused)]
 pub struct Unused {
     #[suggestion(applicability = "machine-applicable")]
     pub attr_span: Span,
@@ -603,7 +603,7 @@ pub struct Unused {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -611,19 +611,18 @@ pub struct NonExportedMacroInvalidAttrs {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused_duplicate)]
+#[diag(passes::unused_duplicate)]
 pub struct UnusedDuplicate {
-    #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
     #[note]
     pub other: Span,
-    #[warn_]
+    #[warning]
     pub warning: Option<()>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::unused_multiple)]
+#[diag(passes::unused_multiple)]
 pub struct UnusedMultiple {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -634,7 +633,7 @@ pub struct UnusedMultiple {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_ty)]
+#[diag(passes::rustc_lint_opt_ty)]
 pub struct RustcLintOptTy {
     #[primary_span]
     pub attr_span: Span,
@@ -643,7 +642,7 @@ pub struct RustcLintOptTy {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_deny_field_access)]
+#[diag(passes::rustc_lint_opt_deny_field_access)]
 pub struct RustcLintOptDenyFieldAccess {
     #[primary_span]
     pub attr_span: Span,
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 4af041dac0d..7b2f83958af 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -7,6 +7,7 @@
 #![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(iter_intersperse)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 868887c66cd..70b6bfd1e58 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -54,6 +54,14 @@ impl<'tcx> LibFeatureCollector<'tcx> {
                         }
                     }
                 }
+                const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
+
+                if let Some(s) = since && s.as_str() == VERSION_PLACEHOLDER {
+                    let version = option_env!("CFG_VERSION").unwrap_or("<current>");
+                    let version = version.split(' ').next().unwrap();
+                    since = Some(Symbol::intern(&version));
+                }
+
                 if let Some(feature) = feature {
                     // This additional check for stability is to make sure we
                     // don't emit additional, irrelevant errors for malformed
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 7124b84bfef..5b79dd3d3ef 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -89,11 +89,10 @@ use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::*;
-use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::vec::IndexVec;
-use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
@@ -139,12 +138,54 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
     }
 }
 
-fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx));
+fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
+    let local_def_id = match def_id.as_local() {
+        None => return,
+        Some(def_id) => def_id,
+    };
+
+    // Don't run unused pass for #[derive()]
+    let parent = tcx.local_parent(local_def_id);
+    if let DefKind::Impl = tcx.def_kind(parent)
+        && tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
+    {
+        return;
+    }
+
+    // Don't run unused pass for #[naked]
+    if tcx.has_attr(def_id, sym::naked) {
+        return;
+    }
+
+    let mut maps = IrMaps::new(tcx);
+    let body_id = tcx.hir().body_owned_by(local_def_id);
+    let hir_id = tcx.hir().body_owner(body_id);
+    let body = tcx.hir().body(body_id);
+
+    if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+        for &var_hir_id in upvars.keys() {
+            let var_name = tcx.hir().name(var_hir_id);
+            maps.add_variable(Upvar(var_hir_id, var_name));
+        }
+    }
+
+    // gather up the various local variables, significant expressions,
+    // and so forth:
+    maps.visit_body(body);
+
+    // compute liveness
+    let mut lsets = Liveness::new(&mut maps, local_def_id);
+    let entry_ln = lsets.compute(&body, hir_id);
+    lsets.log_liveness(entry_ln, body_id.hir_id);
+
+    // check for various error conditions
+    lsets.visit_body(body);
+    lsets.warn_about_unused_upvars(entry_ln);
+    lsets.warn_about_unused_args(body, entry_ln);
 }
 
 pub fn provide(providers: &mut Providers) {
-    *providers = Providers { check_mod_liveness, ..*providers };
+    *providers = Providers { check_liveness, ..*providers };
 }
 
 // ______________________________________________________________________
@@ -188,6 +229,19 @@ enum VarKind {
     Upvar(HirId, Symbol),
 }
 
+struct CollectLitsVisitor<'tcx> {
+    lit_exprs: Vec<&'tcx hir::Expr<'tcx>>,
+}
+
+impl<'tcx> Visitor<'tcx> for CollectLitsVisitor<'tcx> {
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if let hir::ExprKind::Lit(_) = expr.kind {
+            self.lit_exprs.push(expr);
+        }
+        intravisit::walk_expr(self, expr);
+    }
+}
+
 struct IrMaps<'tcx> {
     tcx: TyCtxt<'tcx>,
     live_node_map: HirIdMap<LiveNode>,
@@ -316,56 +370,6 @@ impl<'tcx> IrMaps<'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
-    type NestedFilter = nested_filter::OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
-        debug!("visit_body {:?}", body.id());
-
-        // swap in a new set of IR maps for this body
-        let mut maps = IrMaps::new(self.tcx);
-        let hir_id = maps.tcx.hir().body_owner(body.id());
-        let local_def_id = maps.tcx.hir().local_def_id(hir_id);
-        let def_id = local_def_id.to_def_id();
-
-        // Don't run unused pass for #[derive()]
-        let parent = self.tcx.local_parent(local_def_id);
-        if let DefKind::Impl = self.tcx.def_kind(parent)
-            && self.tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
-        {
-            return;
-        }
-
-        // Don't run unused pass for #[naked]
-        if self.tcx.has_attr(def_id, sym::naked) {
-            return;
-        }
-
-        if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
-            for &var_hir_id in upvars.keys() {
-                let var_name = maps.tcx.hir().name(var_hir_id);
-                maps.add_variable(Upvar(var_hir_id, var_name));
-            }
-        }
-
-        // gather up the various local variables, significant expressions,
-        // and so forth:
-        intravisit::walk_body(&mut maps, body);
-
-        // compute liveness
-        let mut lsets = Liveness::new(&mut maps, local_def_id);
-        let entry_ln = lsets.compute(&body, hir_id);
-        lsets.log_liveness(entry_ln, body.id().hir_id);
-
-        // check for various error conditions
-        lsets.visit_body(body);
-        lsets.warn_about_unused_upvars(entry_ln);
-        lsets.warn_about_unused_args(body, entry_ln);
-    }
-
     fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
         self.add_from_pat(&local.pat);
         if local.els.is_some() {
@@ -1342,7 +1346,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
 impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
     fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
-        self.check_unused_vars_in_pat(&local.pat, None, |spans, hir_id, ln, var| {
+        self.check_unused_vars_in_pat(&local.pat, None, None, |spans, hir_id, ln, var| {
             if local.init.is_some() {
                 self.warn_about_dead_assign(spans, hir_id, ln, var);
             }
@@ -1357,7 +1361,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> {
     }
 
     fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
-        self.check_unused_vars_in_pat(&arm.pat, None, |_, _, _, _| {});
+        self.check_unused_vars_in_pat(&arm.pat, None, None, |_, _, _, _| {});
         intravisit::walk_arm(self, arm);
     }
 }
@@ -1396,7 +1400,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         }
 
         hir::ExprKind::Let(let_expr) => {
-            this.check_unused_vars_in_pat(let_expr.pat, None, |_, _, _, _| {});
+            this.check_unused_vars_in_pat(let_expr.pat, None, None, |_, _, _, _| {});
         }
 
         // no correctness conditions related to liveness
@@ -1517,13 +1521,18 @@ impl<'tcx> Liveness<'_, 'tcx> {
 
     fn warn_about_unused_args(&self, body: &hir::Body<'_>, entry_ln: LiveNode) {
         for p in body.params {
-            self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| {
-                if !self.live_on_entry(ln, var) {
-                    self.report_unused_assign(hir_id, spans, var, |name| {
-                        format!("value passed to `{}` is never read", name)
-                    });
-                }
-            });
+            self.check_unused_vars_in_pat(
+                &p.pat,
+                Some(entry_ln),
+                Some(body),
+                |spans, hir_id, ln, var| {
+                    if !self.live_on_entry(ln, var) {
+                        self.report_unused_assign(hir_id, spans, var, |name| {
+                            format!("value passed to `{}` is never read", name)
+                        });
+                    }
+                },
+            );
         }
     }
 
@@ -1531,6 +1540,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
         &self,
         pat: &hir::Pat<'_>,
         entry_ln: Option<LiveNode>,
+        opt_body: Option<&hir::Body<'_>>,
         on_used_on_entry: impl Fn(Vec<Span>, HirId, LiveNode, Variable),
     ) {
         // In an or-pattern, only consider the variable; any later patterns must have the same
@@ -1558,7 +1568,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
                     hir_ids_and_spans.into_iter().map(|(_, _, ident_span)| ident_span).collect();
                 on_used_on_entry(spans, id, ln, var);
             } else {
-                self.report_unused(hir_ids_and_spans, ln, var, can_remove);
+                self.report_unused(hir_ids_and_spans, ln, var, can_remove, pat, opt_body);
             }
         }
     }
@@ -1570,6 +1580,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
         ln: LiveNode,
         var: Variable,
         can_remove: bool,
+        pat: &hir::Pat<'_>,
+        opt_body: Option<&hir::Body<'_>>,
     ) {
         let first_hir_id = hir_ids_and_spans[0].0;
 
@@ -1673,6 +1685,9 @@ impl<'tcx> Liveness<'_, 'tcx> {
                             .collect::<Vec<_>>(),
                         |lint| {
                             let mut err = lint.build(&format!("unused variable: `{}`", name));
+                            if self.has_added_lit_match_name_span(&name, opt_body, &mut err) {
+                                err.span_label(pat.span, "unused variable");
+                            }
                             err.multipart_suggestion(
                                 "if this is intentional, prefix it with an underscore",
                                 non_shorthands,
@@ -1686,6 +1701,42 @@ impl<'tcx> Liveness<'_, 'tcx> {
         }
     }
 
+    fn has_added_lit_match_name_span(
+        &self,
+        name: &str,
+        opt_body: Option<&hir::Body<'_>>,
+        err: &mut rustc_errors::DiagnosticBuilder<'_, ()>,
+    ) -> bool {
+        let mut has_litstring = false;
+        let Some(opt_body) = opt_body else {return false;};
+        let mut visitor = CollectLitsVisitor { lit_exprs: vec![] };
+        intravisit::walk_body(&mut visitor, opt_body);
+        for lit_expr in visitor.lit_exprs {
+            let hir::ExprKind::Lit(litx) = &lit_expr.kind else { continue };
+            let rustc_ast::LitKind::Str(syb, _) = litx.node else{ continue; };
+            let name_str: &str = syb.as_str();
+            let mut name_pa = String::from("{");
+            name_pa.push_str(&name);
+            name_pa.push('}');
+            if name_str.contains(&name_pa) {
+                err.span_label(
+                    lit_expr.span,
+                    "you might have meant to use string interpolation in this string literal",
+                );
+                err.multipart_suggestion(
+                    "string interpolation only works in `format!` invocations",
+                    vec![
+                        (lit_expr.span.shrink_to_lo(), "format!(".to_string()),
+                        (lit_expr.span.shrink_to_hi(), ")".to_string()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+                has_litstring = true;
+            }
+        }
+        has_litstring
+    }
+
     fn warn_about_dead_assign(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) {
         if !self.live_on_exit(ln, var) {
             self.report_unused_assign(hir_id, spans, var, |name| {