about summary refs log tree commit diff
path: root/compiler/rustc_lint/src
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-06-13 17:08:04 +0200
committerUrgau <urgau@numericable.fr>2024-06-15 13:00:53 +0200
commitab0e72781f6bccb1c033a7c79edaebc6124ac2b5 (patch)
treea176a3c5b4b9e841aec86dd970bae414d20ecf6a /compiler/rustc_lint/src
parent8217b412a235407243f2516ebc859e7b3af8345a (diff)
downloadrust-ab0e72781f6bccb1c033a7c79edaebc6124ac2b5.tar.gz
rust-ab0e72781f6bccb1c033a7c79edaebc6124ac2b5.zip
Suggest standalone doctest for non-local impl defs
Diffstat (limited to 'compiler/rustc_lint/src')
-rw-r--r--compiler/rustc_lint/src/lints.rs5
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs84
2 files changed, 51 insertions, 38 deletions
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index b377da31a58..6cc0a81aa4f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1358,6 +1358,7 @@ pub enum NonLocalDefinitionsDiag {
         cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
         const_anon: Option<Option<Span>>,
         move_to: Option<(Span, Vec<Span>)>,
+        doctest: bool,
         may_remove: Option<(Span, String)>,
         has_trait: bool,
         self_ty_str: String,
@@ -1383,6 +1384,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                 cargo_update,
                 const_anon,
                 move_to,
+                doctest,
                 may_remove,
                 has_trait,
                 self_ty_str,
@@ -1411,6 +1413,9 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                     }
                     diag.span_help(ms, fluent::lint_non_local_definitions_impl_move_help);
                 }
+                if doctest {
+                    diag.help(fluent::lint_doctest);
+                }
 
                 if let Some((span, part)) = may_remove {
                     diag.arg("may_remove_part", part);
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index d7ffc34d824..423862dcdba 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -111,6 +111,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
             }
         };
 
+        // determining if we are in a doctest context can't currently be determined
+        // by the code itself (there are no specific attributes), but fortunately rustdoc
+        // sets a perma-unstable env var for libtest so we just reuse that for now
+        let is_at_toplevel_doctest =
+            || self.body_depth == 2 && std::env::var("UNSTABLE_RUSTDOC_TEST_PATH").is_ok();
+
         match item.kind {
             ItemKind::Impl(impl_) => {
                 // The RFC states:
@@ -191,29 +197,6 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                     None
                 };
 
-                let mut collector = PathCollector { paths: Vec::new() };
-                collector.visit_ty(&impl_.self_ty);
-                if let Some(of_trait) = &impl_.of_trait {
-                    collector.visit_trait_ref(of_trait);
-                }
-                collector.visit_generics(&impl_.generics);
-
-                let mut may_move: Vec<Span> = collector
-                    .paths
-                    .into_iter()
-                    .filter_map(|path| {
-                        if let Some(did) = path.res.opt_def_id()
-                            && did_has_local_parent(did, cx.tcx, parent, parent_parent)
-                        {
-                            Some(cx.tcx.def_span(did))
-                        } else {
-                            None
-                        }
-                    })
-                    .collect();
-                may_move.sort();
-                may_move.dedup();
-
                 let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. })
                     .then_some(span_for_const_anon_suggestion);
 
@@ -248,14 +231,44 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                 } else {
                     None
                 };
-                let move_to = if may_move.is_empty() {
-                    ms.push_span_label(
-                        cx.tcx.def_span(parent),
-                        fluent::lint_non_local_definitions_impl_move_help,
-                    );
-                    None
+
+                let (doctest, move_to) = if is_at_toplevel_doctest() {
+                    (true, None)
                 } else {
-                    Some((cx.tcx.def_span(parent), may_move))
+                    let mut collector = PathCollector { paths: Vec::new() };
+                    collector.visit_ty(&impl_.self_ty);
+                    if let Some(of_trait) = &impl_.of_trait {
+                        collector.visit_trait_ref(of_trait);
+                    }
+                    collector.visit_generics(&impl_.generics);
+
+                    let mut may_move: Vec<Span> = collector
+                        .paths
+                        .into_iter()
+                        .filter_map(|path| {
+                            if let Some(did) = path.res.opt_def_id()
+                                && did_has_local_parent(did, cx.tcx, parent, parent_parent)
+                            {
+                                Some(cx.tcx.def_span(did))
+                            } else {
+                                None
+                            }
+                        })
+                        .collect();
+                    may_move.sort();
+                    may_move.dedup();
+
+                    let move_to = if may_move.is_empty() {
+                        ms.push_span_label(
+                            cx.tcx.def_span(parent),
+                            fluent::lint_non_local_definitions_impl_move_help,
+                        );
+                        None
+                    } else {
+                        Some((cx.tcx.def_span(parent), may_move))
+                    };
+
+                    (false, move_to)
                 };
 
                 cx.emit_span_lint(
@@ -272,6 +285,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                         self_ty_str,
                         of_trait_str,
                         move_to,
+                        doctest,
                         may_remove,
                         has_trait: impl_.of_trait.is_some(),
                     },
@@ -280,12 +294,6 @@ 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,
@@ -296,8 +304,8 @@ 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(()),
+                        help: (!is_at_toplevel_doctest()).then_some(()),
+                        doctest_help: is_at_toplevel_doctest().then_some(()),
                     },
                 )
             }