diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index f8a4e024605aa..9ad6e792c28ba 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -386,6 +386,12 @@ declare_lint! { "failures in resolving intra-doc link targets" } +declare_lint! { + pub MISSING_CRATE_LEVEL_DOCS, + Allow, + "detects crates with no crate-level documentation" +} + declare_lint! { pub MISSING_DOC_CODE_EXAMPLES, Allow, @@ -547,6 +553,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, IRREFUTABLE_LET_PATTERNS, INTRA_DOC_LINK_RESOLUTION_FAILURE, + MISSING_CRATE_LEVEL_DOCS, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, WHERE_CLAUSES_OBJECT_SAFETY, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index f0b9ad2852f51..fe3a9b6b3dcdd 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -249,6 +249,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let missing_docs = rustc_lint::builtin::MISSING_DOCS.name; let missing_doc_example = rustc_lint::builtin::MISSING_DOC_CODE_EXAMPLES.name; let private_doc_tests = rustc_lint::builtin::PRIVATE_DOC_TESTS.name; + let no_crate_level_docs = rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS.name; // In addition to those specific lints, we also need to whitelist those given through // command line, otherwise they'll get ignored and we don't want that. @@ -258,6 +259,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt missing_docs.to_owned(), missing_doc_example.to_owned(), private_doc_tests.to_owned(), + no_crate_level_docs.to_owned(), ]; whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); @@ -411,10 +413,28 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut krate = clean::krate(&mut ctxt); + if let Some(ref m) = krate.module { + if let None | Some("") = m.doc_value() { + let help = "The following guide may be of use:\n\ + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ + .html"; + tcx.struct_lint_node( + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS, + ctxt.as_local_hir_id(m.def_id).unwrap(), + |lint| { + let mut diag = lint.build( + "no documentation found for this crate's top-level module", + ); + diag.help(help); + diag.emit(); + }, + ); + } + } + fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) { let mut msg = diag.struct_warn(&format!( - "the `#![doc({})]` attribute is \ - considered deprecated", + "the `#![doc({})]` attribute is considered deprecated", name )); msg.warn( diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs new file mode 100644 index 0000000000000..152a7cd88bcb1 --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs @@ -0,0 +1,3 @@ +#![deny(missing_crate_level_docs)] + +pub fn foo() {} diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr new file mode 100644 index 0000000000000..6e7e2fb3eb73f --- /dev/null +++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr @@ -0,0 +1,12 @@ +error: no documentation found for this crate's top-level module + | +note: the lint level is defined here + --> $DIR/no-crate-level-doc-lint.rs:1:9 + | +LL | #![deny(missing_crate_level_docs)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: The following guide may be of use: + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html + +error: aborting due to previous error +