Skip to content

Commit 7c34f1a

Browse files
committed
Make MissingDoc a module lint.
1 parent 53e5fd6 commit 7c34f1a

File tree

9 files changed

+84
-120
lines changed

9 files changed

+84
-120
lines changed

compiler/rustc_interface/src/passes.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -846,9 +846,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
846846
},
847847
{
848848
sess.time("lint_checking", || {
849-
rustc_lint::check_crate(tcx, || {
850-
rustc_lint::BuiltinCombinedLateLintPass::new()
851-
});
849+
rustc_lint::check_crate(tcx);
852850
});
853851
},
854852
{

compiler/rustc_lint/src/builtin.rs

+1-34
Original file line numberDiff line numberDiff line change
@@ -457,10 +457,7 @@ declare_lint! {
457457
report_in_external_macro
458458
}
459459

460-
pub struct MissingDoc {
461-
/// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes.
462-
doc_hidden_stack: Vec<bool>,
463-
}
460+
pub struct MissingDoc;
464461

465462
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
466463

@@ -489,14 +486,6 @@ fn has_doc(attr: &ast::Attribute) -> bool {
489486
}
490487

491488
impl MissingDoc {
492-
pub fn new() -> MissingDoc {
493-
MissingDoc { doc_hidden_stack: vec![false] }
494-
}
495-
496-
fn doc_hidden(&self) -> bool {
497-
*self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
498-
}
499-
500489
fn check_missing_docs_attrs(
501490
&self,
502491
cx: &LateContext<'_>,
@@ -510,11 +499,6 @@ impl MissingDoc {
510499
return;
511500
}
512501

513-
// `#[doc(hidden)]` disables missing_docs check.
514-
if self.doc_hidden() {
515-
return;
516-
}
517-
518502
// Only check publicly-visible items, using the result from the privacy pass.
519503
// It's an option so the crate root can also use this function (it doesn't
520504
// have a `NodeId`).
@@ -537,23 +521,6 @@ impl MissingDoc {
537521
}
538522

539523
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
540-
#[inline]
541-
fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
542-
let doc_hidden = self.doc_hidden()
543-
|| attrs.iter().any(|attr| {
544-
attr.has_name(sym::doc)
545-
&& match attr.meta_item_list() {
546-
None => false,
547-
Some(l) => attr::list_contains_name(&l, sym::hidden),
548-
}
549-
});
550-
self.doc_hidden_stack.push(doc_hidden);
551-
}
552-
553-
fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) {
554-
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
555-
}
556-
557524
fn check_crate(&mut self, cx: &LateContext<'_>) {
558525
self.check_missing_docs_attrs(cx, CRATE_DEF_ID, "the", "crate");
559526
}

compiler/rustc_lint/src/late.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
1818
use rustc_ast as ast;
1919
use rustc_data_structures::stack::ensure_sufficient_stack;
20-
use rustc_data_structures::sync::{join, DynSend};
20+
use rustc_data_structures::sync::join;
2121
use rustc_hir as hir;
2222
use rustc_hir::def_id::LocalDefId;
2323
use rustc_hir::intravisit as hir_visit;
@@ -336,7 +336,7 @@ macro_rules! impl_late_lint_pass {
336336

337337
crate::late_lint_methods!(impl_late_lint_pass, []);
338338

339-
pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
339+
pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
340340
tcx: TyCtxt<'tcx>,
341341
module_def_id: LocalDefId,
342342
builtin_lints: T,
@@ -376,17 +376,32 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
376376
let mut cx = LateContextAndPass { context, pass };
377377

378378
let (module, _span, hir_id) = tcx.hir().get_module(module_def_id);
379+
380+
// There is no module lint that will have the crate itself as an item, so check it here.
381+
if hir_id == hir::CRATE_HIR_ID {
382+
lint_callback!(cx, check_crate,);
383+
}
384+
379385
cx.process_mod(module, hir_id);
380386

381387
// Visit the crate attributes
382388
if hir_id == hir::CRATE_HIR_ID {
383389
for attr in tcx.hir().attrs(hir::CRATE_HIR_ID).iter() {
384390
cx.visit_attribute(attr)
385391
}
392+
lint_callback!(cx, check_crate_post,);
386393
}
387394
}
388395

389-
fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
396+
fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
397+
// Note: `passes` is often empty.
398+
let mut passes: Vec<_> =
399+
unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
400+
401+
if passes.is_empty() {
402+
return;
403+
}
404+
390405
let context = LateContext {
391406
tcx,
392407
enclosing_body: None,
@@ -399,18 +414,8 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti
399414
only_module: false,
400415
};
401416

402-
// Note: `passes` is often empty. In that case, it's faster to run
403-
// `builtin_lints` directly rather than bundling it up into the
404-
// `RuntimeCombinedLateLintPass`.
405-
let mut passes: Vec<_> =
406-
unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
407-
if passes.is_empty() {
408-
late_lint_crate_inner(tcx, context, builtin_lints);
409-
} else {
410-
passes.push(Box::new(builtin_lints));
411-
let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
412-
late_lint_crate_inner(tcx, context, pass);
413-
}
417+
let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
418+
late_lint_crate_inner(tcx, context, pass);
414419
}
415420

416421
fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
@@ -432,15 +437,12 @@ fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>(
432437
}
433438

434439
/// Performs lint checking on a crate.
435-
pub fn check_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(
436-
tcx: TyCtxt<'tcx>,
437-
builtin_lints: impl FnOnce() -> T + Send + DynSend,
438-
) {
440+
pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
439441
join(
440442
|| {
441443
tcx.sess.time("crate_lints", || {
442444
// Run whole crate non-incremental lints
443-
late_lint_crate(tcx, builtin_lints());
445+
late_lint_crate(tcx);
444446
});
445447
},
446448
|| {

compiler/rustc_lint/src/levels.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::{
2+
builtin::MISSING_DOCS,
23
context::{CheckLintNameResult, LintStore},
34
fluent_generated as fluent,
45
late::unerased_lint_store,
@@ -667,6 +668,16 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
667668
continue;
668669
}
669670

671+
// `#[doc(hidden)]` disables missing_docs check.
672+
if attr.has_name(sym::doc)
673+
&& attr
674+
.meta_item_list()
675+
.map_or(false, |l| ast::attr::list_contains_name(&l, sym::hidden))
676+
{
677+
self.insert(LintId::of(MISSING_DOCS), (Level::Allow, LintLevelSource::Default));
678+
continue;
679+
}
680+
670681
let level = match Level::from_attr(attr) {
671682
None => continue,
672683
// This is the only lint level with a `LintExpectationId` that can be created from an attribute

compiler/rustc_lint/src/lib.rs

+4-17
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,11 @@ use types::*;
126126
use unused::*;
127127

128128
/// Useful for other parts of the compiler / Clippy.
129-
pub use builtin::SoftLints;
129+
pub use builtin::{MissingDoc, SoftLints};
130130
pub use context::{CheckLintNameResult, FindLintError, LintStore};
131131
pub use context::{EarlyContext, LateContext, LintContext};
132132
pub use early::{check_ast_node, EarlyCheckNode};
133-
pub use late::{check_crate, unerased_lint_store};
133+
pub use late::{check_crate, late_lint_mod, unerased_lint_store};
134134
pub use passes::{EarlyLintPass, LateLintPass};
135135
pub use rustc_session::lint::Level::{self, *};
136136
pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
@@ -146,7 +146,7 @@ pub fn provide(providers: &mut Providers) {
146146
}
147147

148148
fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
149-
late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
149+
late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
150150
}
151151

152152
early_lint_methods!(
@@ -184,19 +184,6 @@ early_lint_methods!(
184184
]
185185
);
186186

187-
// FIXME: Make a separate lint type which does not require typeck tables.
188-
189-
late_lint_methods!(
190-
declare_combined_late_lint_pass,
191-
[
192-
pub BuiltinCombinedLateLintPass,
193-
[
194-
// Tracks attributes of parents
195-
MissingDoc: MissingDoc::new(),
196-
]
197-
]
198-
);
199-
200187
late_lint_methods!(
201188
declare_combined_late_lint_pass,
202189
[
@@ -250,6 +237,7 @@ late_lint_methods!(
250237
MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
251238
MapUnitFn: MapUnitFn,
252239
MissingDebugImplementations: MissingDebugImplementations,
240+
MissingDoc: MissingDoc,
253241
]
254242
]
255243
);
@@ -278,7 +266,6 @@ fn register_builtins(store: &mut LintStore) {
278266
store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
279267
store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
280268
store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
281-
store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
282269
store.register_lints(&foreign_modules::get_lints());
283270

284271
add_lint_group!(

src/librustdoc/core.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
1010
use rustc_hir::intravisit::{self, Visitor};
1111
use rustc_hir::{HirId, Path};
1212
use rustc_interface::interface;
13+
use rustc_lint::{late_lint_mod, MissingDoc};
1314
use rustc_middle::hir::nested_filter;
1415
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
1516
use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
@@ -269,7 +270,7 @@ pub(crate) fn create_config(
269270
register_lints: Some(Box::new(crate::lint::register_lints)),
270271
override_queries: Some(|_sess, providers, _external_providers| {
271272
// Most lints will require typechecking, so just don't run them.
272-
providers.lint_mod = |_, _| {};
273+
providers.lint_mod = |tcx, module_def_id| late_lint_mod(tcx, module_def_id, MissingDoc);
273274
// hack so that `used_trait_imports` won't try to call typeck
274275
providers.used_trait_imports = |_, _| {
275276
static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
@@ -323,9 +324,7 @@ pub(crate) fn run_global_ctxt(
323324
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
324325
});
325326
tcx.sess.abort_if_errors();
326-
tcx.sess.time("missing_docs", || {
327-
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
328-
});
327+
tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx));
329328
tcx.sess.time("check_mod_attrs", || {
330329
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
331330
});

tests/ui/lint/lint-attr-everywhere-late.stderr

+18-18
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ note: the lint level is defined here
3434
LL | #![deny(missing_docs)]
3535
| ^^^^^^^^^^^^
3636

37-
error: missing documentation for a function
38-
--> $DIR/lint-attr-everywhere-late.rs:47:5
39-
|
40-
LL | pub fn missing_inner() {}
41-
| ^^^^^^^^^^^^^^^^^^^^^^
42-
4337
error: missing documentation for an associated function
4438
--> $DIR/lint-attr-everywhere-late.rs:54:5
4539
|
@@ -142,18 +136,6 @@ note: the lint level is defined here
142136
LL | #[deny(missing_docs)]
143137
| ^^^^^^^^^^^^
144138

145-
error: missing documentation for a variant
146-
--> $DIR/lint-attr-everywhere-late.rs:112:5
147-
|
148-
LL | Variant1,
149-
| ^^^^^^^^
150-
|
151-
note: the lint level is defined here
152-
--> $DIR/lint-attr-everywhere-late.rs:111:12
153-
|
154-
LL | #[deny(missing_docs)]
155-
| ^^^^^^^^^^^^
156-
157139
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
158140
--> $DIR/lint-attr-everywhere-late.rs:93:38
159141
|
@@ -196,6 +178,18 @@ note: the lint level is defined here
196178
LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
197179
| ^^^^^^^^^^^^^^^^^^^^
198180

181+
error: missing documentation for a variant
182+
--> $DIR/lint-attr-everywhere-late.rs:112:5
183+
|
184+
LL | Variant1,
185+
| ^^^^^^^^
186+
|
187+
note: the lint level is defined here
188+
--> $DIR/lint-attr-everywhere-late.rs:111:12
189+
|
190+
LL | #[deny(missing_docs)]
191+
| ^^^^^^^^^^^^
192+
199193
error: variable `PARAM` should have a snake case name
200194
--> $DIR/lint-attr-everywhere-late.rs:131:37
201195
|
@@ -402,6 +396,12 @@ note: the lint level is defined here
402396
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
403397
| ^^^^^^^^^^^^^^^^^^^^^^^^^
404398

399+
error: missing documentation for a function
400+
--> $DIR/lint-attr-everywhere-late.rs:47:5
401+
|
402+
LL | pub fn missing_inner() {}
403+
| ^^^^^^^^^^^^^^^^^^^^^^
404+
405405
error: `clashing1` redeclared with a different signature
406406
--> $DIR/lint-attr-everywhere-late.rs:123:5
407407
|

tests/ui/lint/lint-missing-doc.stderr

+18-18
Original file line numberDiff line numberDiff line change
@@ -112,24 +112,6 @@ error: missing documentation for a static
112112
LL | pub static BAR4: u32 = 0;
113113
| ^^^^^^^^^^^^^^^^^^^^
114114

115-
error: missing documentation for a function
116-
--> $DIR/lint-missing-doc.rs:174:5
117-
|
118-
LL | pub fn undocumented1() {}
119-
| ^^^^^^^^^^^^^^^^^^^^^^
120-
121-
error: missing documentation for a function
122-
--> $DIR/lint-missing-doc.rs:175:5
123-
|
124-
LL | pub fn undocumented2() {}
125-
| ^^^^^^^^^^^^^^^^^^^^^^
126-
127-
error: missing documentation for a function
128-
--> $DIR/lint-missing-doc.rs:181:9
129-
|
130-
LL | pub fn also_undocumented1() {}
131-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
132-
133115
error: missing documentation for a function
134116
--> $DIR/lint-missing-doc.rs:196:5
135117
|
@@ -154,5 +136,23 @@ error: missing documentation for a trait alias
154136
LL | pub trait T = Sync;
155137
| ^^^^^^^^^^^
156138

139+
error: missing documentation for a function
140+
--> $DIR/lint-missing-doc.rs:174:5
141+
|
142+
LL | pub fn undocumented1() {}
143+
| ^^^^^^^^^^^^^^^^^^^^^^
144+
145+
error: missing documentation for a function
146+
--> $DIR/lint-missing-doc.rs:175:5
147+
|
148+
LL | pub fn undocumented2() {}
149+
| ^^^^^^^^^^^^^^^^^^^^^^
150+
151+
error: missing documentation for a function
152+
--> $DIR/lint-missing-doc.rs:181:9
153+
|
154+
LL | pub fn also_undocumented1() {}
155+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
156+
157157
error: aborting due to 25 previous errors
158158

0 commit comments

Comments
 (0)