about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-07-15 16:43:45 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-08-04 16:09:14 +0000
commit7c34f1a8d8bf45b7c0e4197f642d757b4e01ce01 (patch)
tree300cbc2cda643859fbd3feee62e6e15c753270e7
parent53e5fd6a61b42eb4a401a8d0de58eb6f6b39b9d4 (diff)
downloadrust-7c34f1a8d8bf45b7c0e4197f642d757b4e01ce01.tar.gz
rust-7c34f1a8d8bf45b7c0e4197f642d757b4e01ce01.zip
Make MissingDoc a module lint.
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/builtin.rs35
-rw-r--r--compiler/rustc_lint/src/late.rs42
-rw-r--r--compiler/rustc_lint/src/levels.rs11
-rw-r--r--compiler/rustc_lint/src/lib.rs21
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--tests/ui/lint/lint-attr-everywhere-late.stderr36
-rw-r--r--tests/ui/lint/lint-missing-doc.stderr36
-rw-r--r--tests/ui/lint/missing-doc-private-macro.stderr12
9 files changed, 84 insertions, 120 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 7355136aae5..a34fdf4ecc9 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -846,9 +846,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                     },
                     {
                         sess.time("lint_checking", || {
-                            rustc_lint::check_crate(tcx, || {
-                                rustc_lint::BuiltinCombinedLateLintPass::new()
-                            });
+                            rustc_lint::check_crate(tcx);
                         });
                     },
                     {
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 3dfe84dcccc..310e542e5a5 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -457,10 +457,7 @@ declare_lint! {
     report_in_external_macro
 }
 
-pub struct MissingDoc {
-    /// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes.
-    doc_hidden_stack: Vec<bool>,
-}
+pub struct MissingDoc;
 
 impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
 
@@ -489,14 +486,6 @@ fn has_doc(attr: &ast::Attribute) -> bool {
 }
 
 impl MissingDoc {
-    pub fn new() -> MissingDoc {
-        MissingDoc { doc_hidden_stack: vec![false] }
-    }
-
-    fn doc_hidden(&self) -> bool {
-        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
-    }
-
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_>,
@@ -510,11 +499,6 @@ impl MissingDoc {
             return;
         }
 
-        // `#[doc(hidden)]` disables missing_docs check.
-        if self.doc_hidden() {
-            return;
-        }
-
         // Only check publicly-visible items, using the result from the privacy pass.
         // It's an option so the crate root can also use this function (it doesn't
         // have a `NodeId`).
@@ -537,23 +521,6 @@ impl MissingDoc {
 }
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
-    #[inline]
-    fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
-        let doc_hidden = self.doc_hidden()
-            || attrs.iter().any(|attr| {
-                attr.has_name(sym::doc)
-                    && match attr.meta_item_list() {
-                        None => false,
-                        Some(l) => attr::list_contains_name(&l, sym::hidden),
-                    }
-            });
-        self.doc_hidden_stack.push(doc_hidden);
-    }
-
-    fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) {
-        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
-    }
-
     fn check_crate(&mut self, cx: &LateContext<'_>) {
         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, "the", "crate");
     }
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index fb12ded71d6..3331dbad4a9 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -17,7 +17,7 @@
 use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
 use rustc_ast as ast;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_data_structures::sync::{join, DynSend};
+use rustc_data_structures::sync::join;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit as hir_visit;
@@ -336,7 +336,7 @@ macro_rules! impl_late_lint_pass {
 
 crate::late_lint_methods!(impl_late_lint_pass, []);
 
-pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
+pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     tcx: TyCtxt<'tcx>,
     module_def_id: LocalDefId,
     builtin_lints: T,
@@ -376,6 +376,12 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
     let mut cx = LateContextAndPass { context, pass };
 
     let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
+
+    // There is no module lint that will have the crate itself as an item, so check it here.
+    if hir_id == hir::CRATE_HIR_ID {
+        lint_callback!(cx, check_crate,);
+    }
+
     cx.process_mod(module, hir_id);
 
     // Visit the crate attributes
@@ -383,10 +389,19 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
         for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
             cx.visit_attribute(attr)
         }
+        lint_callback!(cx, check_crate_post,);
     }
 }
 
-fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
+fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+    // Note: `passes` is often empty.
+    let mut passes: Vec<_> =
+        unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
+
+    if passes.is_empty() {
+        return;
+    }
+
     let context = LateContext {
         tcx,
         enclosing_body: None,
@@ -399,18 +414,8 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
         only_module: false,
     };
 
-    // Note: `passes` is often empty. In that case, it's faster to run
-    // `builtin_lints` directly rather than bundling it up into the
-    // `RuntimeCombinedLateLintPass`.
-    let mut passes: Vec<_> =
-        unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
-    if passes.is_empty() {
-        late_lint_crate_inner(tcx, context, builtin_lints);
-    } else {
-        passes.push(Box::new(builtin_lints));
-        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
-        late_lint_crate_inner(tcx, context, pass);
-    }
+    let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+    late_lint_crate_inner(tcx, context, pass);
 }
 
 fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
@@ -432,15 +437,12 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
 }
 
 /// Performs lint checking on a crate.
-pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
-    tcx: TyCtxt<'tcx>,
-    builtin_lints: impl FnOnce() -> T + Send + DynSend,
-) {
+pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
     join(
         || {
             tcx.sess.time("crate_lints", || {
                 // Run whole crate non-incremental lints
-                late_lint_crate(tcx, builtin_lints());
+                late_lint_crate(tcx);
             });
         },
         || {
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index fb407be1f02..18b178d8882 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,4 +1,5 @@
 use crate::{
+    builtin::MISSING_DOCS,
     context::{CheckLintNameResult, LintStore},
     fluent_generated as fluent,
     late::unerased_lint_store,
@@ -667,6 +668,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                 continue;
             }
 
+            // `#[doc(hidden)]` disables missing_docs check.
+            if attr.has_name(sym::doc)
+                && attr
+                    .meta_item_list()
+                    .map_or(false, |l| ast::attr::list_contains_name(&l, sym::hidden))
+            {
+                self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default));
+                continue;
+            }
+
             let level = match Level::from_attr(attr) {
                 None => continue,
                 // This is the only lint level with a `LintExpectationId` that can be created from an attribute
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 8ae0c9ba3fe..67823a2dcc2 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -126,11 +126,11 @@ use types::*;
 use unused::*;
 
 /// Useful for other parts of the compiler / Clippy.
-pub use builtin::SoftLints;
+pub use builtin::{MissingDoc, SoftLints};
 pub use context::{CheckLintNameResult, FindLintError, LintStore};
 pub use context::{EarlyContext, LateContext, LintContext};
 pub use early::{check_ast_node, EarlyCheckNode};
-pub use late::{check_crate, unerased_lint_store};
+pub use late::{check_crate, late_lint_mod, unerased_lint_store};
 pub use passes::{EarlyLintPass, LateLintPass};
 pub use rustc_session::lint::Level::{self, *};
 pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
@@ -146,7 +146,7 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
+    late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
 }
 
 early_lint_methods!(
@@ -184,19 +184,6 @@ early_lint_methods!(
     ]
 );
 
-// FIXME: Make a separate lint type which does not require typeck tables.
-
-late_lint_methods!(
-    declare_combined_late_lint_pass,
-    [
-        pub BuiltinCombinedLateLintPass,
-        [
-            // Tracks attributes of parents
-            MissingDoc: MissingDoc::new(),
-        ]
-    ]
-);
-
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
@@ -250,6 +237,7 @@ late_lint_methods!(
             MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
             MapUnitFn: MapUnitFn,
             MissingDebugImplementations: MissingDebugImplementations,
+            MissingDoc: MissingDoc,
         ]
     ]
 );
@@ -278,7 +266,6 @@ fn register_builtins(store: &mut LintStore) {
     store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
     store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
     store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
-    store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
     store.register_lints(&foreign_modules::get_lints());
 
     add_lint_group!(
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 6f791aec3f2..ceee6274ea5 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, Path};
 use rustc_interface::interface;
+use rustc_lint::{late_lint_mod, MissingDoc};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
@@ -269,7 +270,7 @@ pub(crate) fn create_config(
         register_lints: Some(Box::new(crate::lint::register_lints)),
         override_queries: Some(|_sess, providers, _external_providers| {
             // Most lints will require typechecking, so just don't run them.
-            providers.lint_mod = |_, _| {};
+            providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc);
             // hack so that `used_trait_imports` won't try to call typeck
             providers.used_trait_imports = |_, _| {
                 static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
@@ -323,9 +324,7 @@ pub(crate) fn run_global_ctxt(
         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
     });
     tcx.sess.abort_if_errors();
-    tcx.sess.time("missing_docs", || {
-        rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
-    });
+    tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
     tcx.sess.time("check_mod_attrs", || {
         tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
     });
diff --git a/tests/ui/lint/lint-attr-everywhere-late.stderr b/tests/ui/lint/lint-attr-everywhere-late.stderr
index be4368c5cc3..7fe078068fe 100644
--- a/tests/ui/lint/lint-attr-everywhere-late.stderr
+++ b/tests/ui/lint/lint-attr-everywhere-late.stderr
@@ -34,12 +34,6 @@ note: the lint level is defined here
 LL |     #![deny(missing_docs)]
    |             ^^^^^^^^^^^^
 
-error: missing documentation for a function
-  --> $DIR/lint-attr-everywhere-late.rs:47:5
-   |
-LL |     pub fn missing_inner() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
 error: missing documentation for an associated function
   --> $DIR/lint-attr-everywhere-late.rs:54:5
    |
@@ -142,18 +136,6 @@ note: the lint level is defined here
 LL |     #[deny(missing_docs)]
    |            ^^^^^^^^^^^^
 
-error: missing documentation for a variant
-  --> $DIR/lint-attr-everywhere-late.rs:112:5
-   |
-LL |     Variant1,
-   |     ^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/lint-attr-everywhere-late.rs:111:12
-   |
-LL |     #[deny(missing_docs)]
-   |            ^^^^^^^^^^^^
-
 error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
   --> $DIR/lint-attr-everywhere-late.rs:93:38
    |
@@ -196,6 +178,18 @@ note: the lint level is defined here
 LL |     #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
    |            ^^^^^^^^^^^^^^^^^^^^
 
+error: missing documentation for a variant
+  --> $DIR/lint-attr-everywhere-late.rs:112:5
+   |
+LL |     Variant1,
+   |     ^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-attr-everywhere-late.rs:111:12
+   |
+LL |     #[deny(missing_docs)]
+   |            ^^^^^^^^^^^^
+
 error: variable `PARAM` should have a snake case name
   --> $DIR/lint-attr-everywhere-late.rs:131:37
    |
@@ -402,6 +396,12 @@ note: the lint level is defined here
 LL |     TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: missing documentation for a function
+  --> $DIR/lint-attr-everywhere-late.rs:47:5
+   |
+LL |     pub fn missing_inner() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
 error: `clashing1` redeclared with a different signature
   --> $DIR/lint-attr-everywhere-late.rs:123:5
    |
diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr
index adcc21c44b2..4e9ee4f2769 100644
--- a/tests/ui/lint/lint-missing-doc.stderr
+++ b/tests/ui/lint/lint-missing-doc.stderr
@@ -113,24 +113,6 @@ LL | pub static BAR4: u32 = 0;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
-  --> $DIR/lint-missing-doc.rs:174:5
-   |
-LL |     pub fn undocumented1() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: missing documentation for a function
-  --> $DIR/lint-missing-doc.rs:175:5
-   |
-LL |     pub fn undocumented2() {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: missing documentation for a function
-  --> $DIR/lint-missing-doc.rs:181:9
-   |
-LL |         pub fn also_undocumented1() {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: missing documentation for a function
   --> $DIR/lint-missing-doc.rs:196:5
    |
 LL |     pub fn extern_fn_undocumented(f: f32) -> f32;
@@ -154,5 +136,23 @@ error: missing documentation for a trait alias
 LL | pub trait T = Sync;
    | ^^^^^^^^^^^
 
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:174:5
+   |
+LL |     pub fn undocumented1() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:175:5
+   |
+LL |     pub fn undocumented2() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/lint-missing-doc.rs:181:9
+   |
+LL |         pub fn also_undocumented1() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to 25 previous errors
 
diff --git a/tests/ui/lint/missing-doc-private-macro.stderr b/tests/ui/lint/missing-doc-private-macro.stderr
index 979b007d0ec..18c8ad2de6b 100644
--- a/tests/ui/lint/missing-doc-private-macro.stderr
+++ b/tests/ui/lint/missing-doc-private-macro.stderr
@@ -1,8 +1,8 @@
 error: missing documentation for a macro
-  --> $DIR/missing-doc-private-macro.rs:31:5
+  --> $DIR/missing-doc-private-macro.rs:37:1
    |
-LL |     macro_rules! exported_to_top_level {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub macro top_level_pub_macro {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/missing-doc-private-macro.rs:5:9
@@ -11,10 +11,10 @@ LL | #![deny(missing_docs)]
    |         ^^^^^^^^^^^^
 
 error: missing documentation for a macro
-  --> $DIR/missing-doc-private-macro.rs:37:1
+  --> $DIR/missing-doc-private-macro.rs:31:5
    |
-LL | pub macro top_level_pub_macro {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     macro_rules! exported_to_top_level {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors