about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-02-15 20:30:16 +0100
committerUrgau <urgau@numericable.fr>2024-02-17 13:59:46 +0100
commit85e3a2ee043f6404561a9fbed799c07d83f305ce (patch)
treec8d33f74a2451791332852ce013c36cf9350e87a
parenta8ae1175c7e8f96996b69d75ca6a18e58efb7814 (diff)
downloadrust-85e3a2ee043f6404561a9fbed799c07d83f305ce.tar.gz
rust-85e3a2ee043f6404561a9fbed799c07d83f305ce.zip
Add const-anon suggestion for non local impl
-rw-r--r--compiler/rustc_lint/messages.ftl1
-rw-r--r--compiler/rustc_lint/src/lints.rs8
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs16
-rw-r--r--tests/ui/lint/non_local_definitions.stderr3
4 files changed, 26 insertions, 2 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 4e0ba376b7d..ca3941c06f4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -421,6 +421,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, they should be av
         }
     .non_local = an `impl` definition is non-local if it is nested inside an item and neither the type nor the trait are at the same nesting level as the `impl` block
     .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module and anon-const at the same nesting as the trait or type
+    .const_anon = use a const-anon item to suppress this lint
 
 lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, they should be avoided as they go against expectation
     .help =
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 15f158961d0..1a56fa751c2 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1301,7 +1301,13 @@ pub enum NonLocalDefinitionsDiag {
     #[note(lint_non_local)]
     #[note(lint_exception)]
     #[note(lint_non_local_definitions_deprecation)]
-    Impl { depth: u32, body_kind_descr: &'static str, body_name: String },
+    Impl {
+        depth: u32,
+        body_kind_descr: &'static str,
+        body_name: String,
+        #[suggestion(lint_const_anon, code = "_", applicability = "machine-applicable")]
+        const_anon: Option<Span>,
+    },
     #[diag(lint_non_local_definitions_macro_rules)]
     #[help]
     #[note(lint_non_local)]
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 28bd49f36a0..bfd7b4a72f9 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,4 +1,4 @@
-use rustc_hir::{def::DefKind, Body, Item, ItemKind, Path, QPath, TyKind};
+use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
 use rustc_span::{def_id::DefId, sym, symbol::kw, MacroKind};
 
 use smallvec::{smallvec, SmallVec};
@@ -140,6 +140,19 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                 // If none of them have a local parent (LOGICAL NOR) this means that
                 // this impl definition is a non-local definition and so we lint on it.
                 if !(self_ty_has_local_parent || of_trait_has_local_parent) {
+                    let const_anon = if self.body_depth == 1
+                        && parent_def_kind == DefKind::Const
+                        && parent_opt_item_name != Some(kw::Underscore)
+                        && let Some(parent) = parent.as_local()
+                        && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent)
+                        && let ItemKind::Const(ty, _, _) = item.kind
+                        && let TyKind::Tup(&[]) = ty.kind
+                    {
+                        Some(item.ident.span)
+                    } else {
+                        None
+                    };
+
                     cx.emit_span_lint(
                         NON_LOCAL_DEFINITIONS,
                         item.span,
@@ -149,6 +162,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                             body_name: parent_opt_item_name
                                 .map(|s| s.to_ident_string())
                                 .unwrap_or_else(|| "<unnameable>".to_string()),
+                            const_anon,
                         },
                     )
                 }
diff --git a/tests/ui/lint/non_local_definitions.stderr b/tests/ui/lint/non_local_definitions.stderr
index f15457734bc..8403357b115 100644
--- a/tests/ui/lint/non_local_definitions.stderr
+++ b/tests/ui/lint/non_local_definitions.stderr
@@ -1,6 +1,9 @@
 warning: non-local `impl` definition, they should be avoided as they go against expectation
   --> $DIR/non_local_definitions.rs:32:5
    |
+LL | const Z: () = {
+   |       - help: use a const-anon item to suppress this lint: `_`
+...
 LL |     impl Uto for &Test {}
    |     ^^^^^^^^^^^^^^^^^^^^^
    |