Remove rustc::existing_doc_keyword
lint.
`CheckAttrVisitor::check_doc_keyword` checks `#[doc(keyword = "..")]` attributes to ensure they are on an empty module, and that the value is a non-empty identifier. The `rustc::existing_doc_keyword` lint checks these attributes to ensure that the value is the name of a keyword. It's silly to have two different checking mechanisms for these attributes. This commit does the following. - Changes `check_doc_keyword` to check that the value is the name of a keyword (avoiding the need for the identifier check, which removes a dependency on `rustc_lexer`). - Removes the lint. - Updates tests accordingly. There is one hack: the `SelfTy` FIXME case used to used to be handled by disabling the lint, but now is handled with a special case in `is_doc_keyword`. That hack will go away if/when the FIXME is fixed. Co-Authored-By: Guillaume Gomez <guillaume1.gomez@gmail.com>
This commit is contained in:
parent
f10169c4ec
commit
121e87bf14
25 changed files with 61 additions and 118 deletions
|
@ -4273,7 +4273,6 @@ dependencies = [
|
||||||
"rustc_fluent_macro",
|
"rustc_fluent_macro",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_lexer",
|
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_privacy",
|
"rustc_privacy",
|
||||||
|
|
|
@ -536,9 +536,6 @@ lint_non_camel_case_type = {$sort} `{$name}` should have an upper camel case nam
|
||||||
.suggestion = convert the identifier to upper camel case
|
.suggestion = convert the identifier to upper camel case
|
||||||
.label = should have an UpperCamelCase name
|
.label = should have an UpperCamelCase name
|
||||||
|
|
||||||
lint_non_existent_doc_keyword = found non-existing keyword `{$keyword}` used in `#[doc(keyword = "...")]`
|
|
||||||
.help = only existing keywords are allowed in core/std
|
|
||||||
|
|
||||||
lint_non_fmt_panic = panic message is not a string literal
|
lint_non_fmt_panic = panic message is not a string literal
|
||||||
.note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
|
.note = this usage of `{$name}!()` is deprecated; it will be a hard error in Rust 2021
|
||||||
.more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
.more_info_note = for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
|
||||||
|
|
|
@ -12,11 +12,11 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||||
use rustc_span::symbol::{Symbol, kw, sym};
|
use rustc_span::symbol::sym;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::lints::{
|
use crate::lints::{
|
||||||
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
|
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand,
|
||||||
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
|
NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
|
||||||
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
|
SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrInherentUsage,
|
||||||
UntranslatableDiag,
|
UntranslatableDiag,
|
||||||
|
@ -375,46 +375,6 @@ impl EarlyLintPass for LintPassImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_tool_lint! {
|
|
||||||
/// The `existing_doc_keyword` lint detects use `#[doc()]` keywords
|
|
||||||
/// that don't exist, e.g. `#[doc(keyword = "..")]`.
|
|
||||||
pub rustc::EXISTING_DOC_KEYWORD,
|
|
||||||
Allow,
|
|
||||||
"Check that documented keywords in std and core actually exist",
|
|
||||||
report_in_external_macro: true
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint_pass!(ExistingDocKeyword => [EXISTING_DOC_KEYWORD]);
|
|
||||||
|
|
||||||
fn is_doc_keyword(s: Symbol) -> bool {
|
|
||||||
s <= kw::Union
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
|
|
||||||
fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
|
||||||
for attr in cx.tcx.hir().attrs(item.hir_id()) {
|
|
||||||
if !attr.has_name(sym::doc) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if let Some(list) = attr.meta_item_list() {
|
|
||||||
for nested in list {
|
|
||||||
if nested.has_name(sym::keyword) {
|
|
||||||
let keyword = nested
|
|
||||||
.value_str()
|
|
||||||
.expect("#[doc(keyword = \"...\")] expected a value!");
|
|
||||||
if is_doc_keyword(keyword) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cx.emit_span_lint(EXISTING_DOC_KEYWORD, attr.span, NonExistentDocKeyword {
|
|
||||||
keyword,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
/// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl
|
/// The `untranslatable_diagnostic` lint detects messages passed to functions with `impl
|
||||||
/// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings.
|
/// Into<{D,Subd}iagMessage` parameters without using translatable Fluent strings.
|
||||||
|
|
|
@ -600,8 +600,6 @@ fn register_internals(store: &mut LintStore) {
|
||||||
store.register_late_mod_pass(|_| Box::new(DefaultHashTypes));
|
store.register_late_mod_pass(|_| Box::new(DefaultHashTypes));
|
||||||
store.register_lints(&QueryStability::lint_vec());
|
store.register_lints(&QueryStability::lint_vec());
|
||||||
store.register_late_mod_pass(|_| Box::new(QueryStability));
|
store.register_late_mod_pass(|_| Box::new(QueryStability));
|
||||||
store.register_lints(&ExistingDocKeyword::lint_vec());
|
|
||||||
store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
|
|
||||||
store.register_lints(&TyTyKind::lint_vec());
|
store.register_lints(&TyTyKind::lint_vec());
|
||||||
store.register_late_mod_pass(|_| Box::new(TyTyKind));
|
store.register_late_mod_pass(|_| Box::new(TyTyKind));
|
||||||
store.register_lints(&TypeIr::lint_vec());
|
store.register_lints(&TypeIr::lint_vec());
|
||||||
|
@ -629,7 +627,6 @@ fn register_internals(store: &mut LintStore) {
|
||||||
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO),
|
||||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||||
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
|
LintId::of(NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT),
|
||||||
LintId::of(EXISTING_DOC_KEYWORD),
|
|
||||||
LintId::of(BAD_OPT_ACCESS),
|
LintId::of(BAD_OPT_ACCESS),
|
||||||
LintId::of(SPAN_USE_EQ_CTXT),
|
LintId::of(SPAN_USE_EQ_CTXT),
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -950,13 +950,6 @@ pub(crate) struct NonGlobImportTypeIrInherent {
|
||||||
#[help]
|
#[help]
|
||||||
pub(crate) struct LintPassByHand;
|
pub(crate) struct LintPassByHand;
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
|
||||||
#[diag(lint_non_existent_doc_keyword)]
|
|
||||||
#[help]
|
|
||||||
pub(crate) struct NonExistentDocKeyword {
|
|
||||||
pub keyword: Symbol,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(lint_diag_out_of_impl)]
|
#[diag(lint_diag_out_of_impl)]
|
||||||
pub(crate) struct DiagOutOfImpl;
|
pub(crate) struct DiagOutOfImpl;
|
||||||
|
|
|
@ -16,7 +16,6 @@ rustc_feature = { path = "../rustc_feature" }
|
||||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_index = { path = "../rustc_index" }
|
rustc_index = { path = "../rustc_index" }
|
||||||
rustc_lexer = { path = "../rustc_lexer" }
|
|
||||||
rustc_macros = { path = "../rustc_macros" }
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
rustc_privacy = { path = "../rustc_privacy" }
|
rustc_privacy = { path = "../rustc_privacy" }
|
||||||
|
|
|
@ -211,8 +211,9 @@ passes_doc_invalid =
|
||||||
passes_doc_keyword_empty_mod =
|
passes_doc_keyword_empty_mod =
|
||||||
`#[doc(keyword = "...")]` should be used on empty modules
|
`#[doc(keyword = "...")]` should be used on empty modules
|
||||||
|
|
||||||
passes_doc_keyword_invalid_ident =
|
passes_doc_keyword_not_keyword =
|
||||||
`{$doc_keyword}` is not a valid identifier
|
nonexistent keyword `{$keyword}` used in `#[doc(keyword = "...")]`
|
||||||
|
.help = only existing keywords are allowed in core/std
|
||||||
|
|
||||||
passes_doc_keyword_not_mod =
|
passes_doc_keyword_not_mod =
|
||||||
`#[doc(keyword = "...")]` should be used on modules
|
`#[doc(keyword = "...")]` should be used on modules
|
||||||
|
|
|
@ -914,6 +914,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) {
|
fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) {
|
||||||
|
fn is_doc_keyword(s: Symbol) -> bool {
|
||||||
|
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
|
||||||
|
// can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
|
||||||
|
// `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`.
|
||||||
|
s <= kw::Union || s == sym::SelfTy
|
||||||
|
}
|
||||||
|
|
||||||
let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
|
let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
|
||||||
if doc_keyword == kw::Empty {
|
if doc_keyword == kw::Empty {
|
||||||
self.doc_attr_str_error(meta, "keyword");
|
self.doc_attr_str_error(meta, "keyword");
|
||||||
|
@ -935,10 +942,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !rustc_lexer::is_ident(doc_keyword.as_str()) {
|
if !is_doc_keyword(doc_keyword) {
|
||||||
self.dcx().emit_err(errors::DocKeywordInvalidIdent {
|
self.dcx().emit_err(errors::DocKeywordNotKeyword {
|
||||||
span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
|
span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
|
||||||
doc_keyword,
|
keyword: doc_keyword,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,15 @@ pub(crate) struct DocKeywordEmptyMod {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(passes_doc_keyword_not_keyword)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct DocKeywordNotKeyword {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub keyword: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_doc_keyword_not_mod)]
|
#[diag(passes_doc_keyword_not_mod)]
|
||||||
pub(crate) struct DocKeywordNotMod {
|
pub(crate) struct DocKeywordNotMod {
|
||||||
|
@ -222,14 +231,6 @@ pub(crate) struct DocKeywordNotMod {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(passes_doc_keyword_invalid_ident)]
|
|
||||||
pub(crate) struct DocKeywordInvalidIdent {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
pub doc_keyword: Symbol,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_doc_fake_variadic_not_valid)]
|
#[diag(passes_doc_fake_variadic_not_valid)]
|
||||||
pub(crate) struct DocFakeVariadicNotValid {
|
pub(crate) struct DocFakeVariadicNotValid {
|
||||||
|
|
|
@ -306,6 +306,7 @@ symbols! {
|
||||||
RwLockWriteGuard,
|
RwLockWriteGuard,
|
||||||
Saturating,
|
Saturating,
|
||||||
SeekFrom,
|
SeekFrom,
|
||||||
|
SelfTy,
|
||||||
Send,
|
Send,
|
||||||
SeqCst,
|
SeqCst,
|
||||||
Sized,
|
Sized,
|
||||||
|
|
|
@ -1263,10 +1263,10 @@ mod return_keyword {}
|
||||||
/// [Reference]: ../reference/items/associated-items.html#methods
|
/// [Reference]: ../reference/items/associated-items.html#methods
|
||||||
mod self_keyword {}
|
mod self_keyword {}
|
||||||
|
|
||||||
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we can remove the
|
// FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we can replace
|
||||||
// three next lines and put back: `#[doc(keyword = "Self")]`.
|
// these two lines with `#[doc(keyword = "Self")]` and update `is_doc_keyword` in
|
||||||
|
// `CheckAttrVisitor`.
|
||||||
#[doc(alias = "Self")]
|
#[doc(alias = "Self")]
|
||||||
#[allow(rustc::existing_doc_keyword)]
|
|
||||||
#[doc(keyword = "SelfTy")]
|
#[doc(keyword = "SelfTy")]
|
||||||
//
|
//
|
||||||
/// The implementing type within a [`trait`] or [`impl`] block, or the current type within a type
|
/// The implementing type within a [`trait`] or [`impl`] block, or the current type within a type
|
||||||
|
|
|
@ -251,7 +251,6 @@
|
||||||
#![allow(explicit_outlives_requirements)]
|
#![allow(explicit_outlives_requirements)]
|
||||||
#![allow(unused_lifetimes)]
|
#![allow(unused_lifetimes)]
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
#![deny(rustc::existing_doc_keyword)]
|
|
||||||
#![deny(fuzzy_provenance_casts)]
|
#![deny(fuzzy_provenance_casts)]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
#![allow(rustdoc::redundant_explicit_links)]
|
#![allow(rustdoc::redundant_explicit_links)]
|
||||||
|
|
|
@ -207,7 +207,7 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
|
|
||||||
/// Some documentation about the keyword.
|
/// Some documentation about the keyword.
|
||||||
#[doc(keyword = "keyword")]
|
#[doc(keyword = "break")]
|
||||||
mod empty_mod {}
|
mod empty_mod {}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,8 @@ define-function: (
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo"
|
// Searching for the `for` keyword
|
||||||
|
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=fo"
|
||||||
|
|
||||||
// This is needed so that the text color is computed.
|
// This is needed so that the text color is computed.
|
||||||
show-text: true
|
show-text: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// Checks that the "keyword" results have the expected text alongside them.
|
// Checks that the "keyword" results have the expected text alongside them.
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
|
||||||
write-into: (".search-input", "CookieMonster")
|
write-into: (".search-input", "for")
|
||||||
// To be SURE that the search will be run.
|
// To be SURE that the search will be run.
|
||||||
press-key: 'Enter'
|
press-key: 'Enter'
|
||||||
// Waiting for the search results to appear...
|
// Waiting for the search results to appear...
|
||||||
wait-for: "#search-tabs"
|
wait-for: "#search-tabs"
|
||||||
assert-text: (".result-keyword .result-name", "keyword CookieMonster")
|
assert-text: (".result-keyword .result-name", "keyword for")
|
||||||
|
|
|
@ -78,7 +78,7 @@ call-function: ("check-colors", {
|
||||||
set-window-size: (851, 600)
|
set-window-size: (851, 600)
|
||||||
|
|
||||||
// Check the size and count in tabs
|
// Check the size and count in tabs
|
||||||
assert-text: ("#search-tabs > button:nth-child(1) > .count", " (25) ")
|
assert-text: ("#search-tabs > button:nth-child(1) > .count", " (26) ")
|
||||||
assert-text: ("#search-tabs > button:nth-child(2) > .count", " (6) ")
|
assert-text: ("#search-tabs > button:nth-child(2) > .count", " (6) ")
|
||||||
assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0) ")
|
assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0) ")
|
||||||
store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth})
|
store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth})
|
||||||
|
|
|
@ -156,7 +156,7 @@ pub enum AnEnum {
|
||||||
WithVariants { and: usize, sub: usize, variants: usize },
|
WithVariants { and: usize, sub: usize, variants: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(keyword = "CookieMonster")]
|
#[doc(keyword = "for")]
|
||||||
/// Some keyword.
|
/// Some keyword.
|
||||||
pub mod keyword {}
|
pub mod keyword {}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
/// this is a test!
|
/// this is a test!
|
||||||
pub mod foo {}
|
pub mod foo {}
|
||||||
|
|
||||||
//@ !has "$.index[*][?(@.name=='hello')]"
|
//@ !has "$.index[*][?(@.name=='break')]"
|
||||||
//@ !has "$.index[*][?(@.name=='bar')]"
|
//@ !has "$.index[*][?(@.name=='bar')]"
|
||||||
#[doc(keyword = "hello")]
|
#[doc(keyword = "break")]
|
||||||
/// hello
|
/// hello
|
||||||
mod bar {}
|
mod bar {}
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
/// this is a test!
|
/// this is a test!
|
||||||
pub mod foo {}
|
pub mod foo {}
|
||||||
|
|
||||||
//@ !has "$.index[*][?(@.name=='hello')]"
|
//@ !has "$.index[*][?(@.name=='break')]"
|
||||||
//@ has "$.index[*][?(@.name=='bar')]"
|
//@ has "$.index[*][?(@.name=='bar')]"
|
||||||
//@ is "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"hello\")]"]'
|
//@ is "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]'
|
||||||
//@ is "$.index[*][?(@.name=='bar')].docs" '"hello"'
|
//@ is "$.index[*][?(@.name=='bar')].docs" '"hello"'
|
||||||
#[doc(keyword = "hello")]
|
#[doc(keyword = "break")]
|
||||||
/// hello
|
/// hello
|
||||||
mod bar {}
|
mod bar {}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
error: `foo df` is not a valid identifier
|
error: nonexistent keyword `foo df` used in `#[doc(keyword = "...")]`
|
||||||
--> $DIR/invalid-keyword.rs:3:17
|
--> $DIR/invalid-keyword.rs:3:17
|
||||||
|
|
|
|
||||||
LL | #[doc(keyword = "foo df")]
|
LL | #[doc(keyword = "foo df")]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: only existing keywords are allowed in core/std
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
/// this is a test!
|
/// this is a test!
|
||||||
mod foo{}
|
mod foo{}
|
||||||
|
|
||||||
//@ has foo/keyword.foo.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
|
//@ has foo/keyword.break.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
|
||||||
#[doc(keyword = "foo")]
|
#[doc(keyword = "break")]
|
||||||
/// hello
|
/// hello
|
||||||
mod bar {}
|
mod bar {}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
//@ compile-flags: -Z unstable-options
|
|
||||||
|
|
||||||
#![feature(rustdoc_internals)]
|
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
|
|
||||||
#![deny(rustc::existing_doc_keyword)]
|
|
||||||
|
|
||||||
#[doc(keyword = "tadam")] //~ ERROR
|
|
||||||
mod tadam {}
|
|
|
@ -1,15 +0,0 @@
|
||||||
error: found non-existing keyword `tadam` used in `#[doc(keyword = "...")]`
|
|
||||||
--> $DIR/existing_doc_keyword.rs:9:1
|
|
||||||
|
|
|
||||||
LL | #[doc(keyword = "tadam")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: only existing keywords are allowed in core/std
|
|
||||||
note: the lint level is defined here
|
|
||||||
--> $DIR/existing_doc_keyword.rs:7:9
|
|
||||||
|
|
|
||||||
LL | #![deny(rustc::existing_doc_keyword)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(rustdoc_internals)]
|
#![feature(rustdoc_internals)]
|
||||||
|
|
||||||
#![doc(keyword = "hello")] //~ ERROR
|
#![doc(keyword = "hello")]
|
||||||
|
//~^ ERROR `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
|
||||||
#[doc(keyword = "hell")] //~ ERROR
|
#[doc(keyword = "hell")] //~ ERROR `#[doc(keyword = "...")]` should be used on empty modules
|
||||||
mod foo {
|
mod foo {
|
||||||
fn hell() {}
|
fn hell() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(keyword = "hall")] //~ ERROR
|
#[doc(keyword = "hall")] //~ ERROR `#[doc(keyword = "...")]` should be used on modules
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,3 +18,6 @@ trait Foo {
|
||||||
//~^ ERROR: `#[doc(keyword = "...")]` should be used on modules
|
//~^ ERROR: `#[doc(keyword = "...")]` should be used on modules
|
||||||
fn quux() {}
|
fn quux() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(keyword = "tadam")] //~ ERROR nonexistent keyword `tadam`
|
||||||
|
mod tadam {}
|
||||||
|
|
|
@ -10,6 +10,14 @@ error: `#[doc(keyword = "...")]` should be used on modules
|
||||||
LL | #[doc(keyword = "hall")]
|
LL | #[doc(keyword = "hall")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: nonexistent keyword `tadam` used in `#[doc(keyword = "...")]`
|
||||||
|
--> $DIR/doc_keyword.rs:22:17
|
||||||
|
|
|
||||||
|
LL | #[doc(keyword = "tadam")]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= help: only existing keywords are allowed in core/std
|
||||||
|
|
||||||
error: `#[doc(keyword = "...")]` should be used on modules
|
error: `#[doc(keyword = "...")]` should be used on modules
|
||||||
--> $DIR/doc_keyword.rs:17:11
|
--> $DIR/doc_keyword.rs:17:11
|
||||||
|
|
|
|
||||||
|
@ -22,5 +30,5 @@ error: `#![doc(keyword = "...")]` isn't allowed as a crate-level attribute
|
||||||
LL | #![doc(keyword = "hello")]
|
LL | #![doc(keyword = "hello")]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue