about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-04-30 22:40:19 +0200
committerUrgau <urgau@numericable.fr>2024-05-01 16:57:20 +0200
commit712560cd0399bf36148ca8d185a2ed6e3cb2edb5 (patch)
treed91e0b79c122478543818eeb18eb778695d67f4f
parente27af2917b80487e9c0de00118fdcb9ccb1177f9 (diff)
downloadrust-712560cd0399bf36148ca8d185a2ed6e3cb2edb5.tar.gz
rust-712560cd0399bf36148ca8d185a2ed6e3cb2edb5.zip
Adjust `#[macro_export]`/doctest help suggestion for non_local_defs lint
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/lints.rs12
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs9
-rw-r--r--tests/rustdoc-ui/doctest/non_local_defs.rs10
-rw-r--r--tests/rustdoc-ui/doctest/non_local_defs.stderr14
-rw-r--r--tests/rustdoc-ui/doctest/non_local_defs.stdout6
6 files changed, 49 insertions, 4 deletions
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 82b90e1660a..676a7c21841 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -456,6 +456,8 @@ lint_non_local_definitions_macro_rules = non-local `macro_rules!` definition, th
             [one] `{$body_name}`
            *[other] `{$body_name}` and up {$depth} bodies
         }
+    .help_doctest =
+        remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`
     .non_local = a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
     .exception = one exception to the rule are anon-const (`const _: () = {"{"} ... {"}"}`) at top-level module
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 74a0a224dba..7efa5245baa 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1350,14 +1350,18 @@ pub enum NonLocalDefinitionsDiag {
         const_anon: Option<Span>,
     },
     #[diag(lint_non_local_definitions_macro_rules)]
-    #[help]
-    #[note(lint_non_local)]
-    #[note(lint_exception)]
-    #[note(lint_non_local_definitions_deprecation)]
     MacroRules {
         depth: u32,
         body_kind_descr: &'static str,
         body_name: String,
+        #[help]
+        help: Option<()>,
+        #[help(lint_help_doctest)]
+        doctest_help: Option<()>,
+        #[note(lint_non_local)]
+        #[note(lint_exception)]
+        #[note(lint_non_local_definitions_deprecation)]
+        notes: (),
         #[subdiagnostic]
         cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
     },
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 004c2c2e4f4..27bf9801829 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -232,6 +232,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
             ItemKind::Macro(_macro, MacroKind::Bang)
                 if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
             {
+                // determining we if are in a doctest context can't currently be determined
+                // by the code it-self (no specific attrs), but fortunatly rustdoc sets a
+                // perma-unstable env for libtest so we just re-use that env for now
+                let is_at_toplevel_doctest =
+                    self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok();
+
                 cx.emit_span_lint(
                     NON_LOCAL_DEFINITIONS,
                     item.span,
@@ -242,6 +248,9 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                             .map(|s| s.to_ident_string())
                             .unwrap_or_else(|| "<unnameable>".to_string()),
                         cargo_update: cargo_update(),
+                        help: (!is_at_toplevel_doctest).then_some(()),
+                        doctest_help: is_at_toplevel_doctest.then_some(()),
+                        notes: (),
                     },
                 )
             }
diff --git a/tests/rustdoc-ui/doctest/non_local_defs.rs b/tests/rustdoc-ui/doctest/non_local_defs.rs
new file mode 100644
index 00000000000..aa166c343b2
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/non_local_defs.rs
@@ -0,0 +1,10 @@
+//@ check-pass
+//@ compile-flags:--test --test-args --test-threads=1 --nocapture -Zunstable-options
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+//! ```
+//! #[macro_export]
+//! macro_rules! a_macro { () => {} }
+//! ```
diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr
new file mode 100644
index 00000000000..39a25de1aae
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr
@@ -0,0 +1,14 @@
+warning: non-local `macro_rules!` definition, they should be avoided as they go against expectation
+  --> $DIR/non_local_defs.rs:9:1
+   |
+LL | macro_rules! a_macro { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }`
+   = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute
+   = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module
+   = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363>
+   = note: `#[warn(non_local_definitions)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stdout b/tests/rustdoc-ui/doctest/non_local_defs.stdout
new file mode 100644
index 00000000000..bee195fcdd7
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/non_local_defs.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/non_local_defs.rs - (line 7) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+