Skip to content

Commit dc10ccf

Browse files
Add checks for #[doc(keyword = "...")] and move them into rustc_passes
1 parent 5a22826 commit dc10ccf

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

compiler/rustc_passes/src/check_attr.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,24 +287,20 @@ impl CheckAttrVisitor<'tcx> {
287287
}
288288
}
289289

290-
fn doc_alias_str_error(&self, meta: &NestedMetaItem) {
290+
fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) {
291291
self.tcx
292292
.sess
293293
.struct_span_err(
294294
meta.span(),
295-
"doc alias attribute expects a string: #[doc(alias = \"0\")]",
295+
&format!("doc {0} attribute expects a string: #[doc({0} = \"a\")]", attr_name),
296296
)
297297
.emit();
298298
}
299299

300300
fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
301-
if !meta.is_value_str() {
302-
self.doc_alias_str_error(meta);
303-
return false;
304-
}
305301
let doc_alias = meta.value_str().map(|s| s.to_string()).unwrap_or_else(String::new);
306302
if doc_alias.is_empty() {
307-
self.doc_alias_str_error(meta);
303+
self.doc_attr_str_error(meta, "alias");
308304
return false;
309305
}
310306
if let Some(c) =
@@ -365,6 +361,49 @@ impl CheckAttrVisitor<'tcx> {
365361
true
366362
}
367363

364+
fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
365+
let doc_keyword = meta.value_str().map(|s| s.to_string()).unwrap_or_else(String::new);
366+
if doc_keyword.is_empty() {
367+
self.doc_attr_str_error(meta, "keyword");
368+
return false;
369+
}
370+
match self.tcx.hir().expect_item(hir_id).kind {
371+
ItemKind::Mod(ref module) => {
372+
if !module.item_ids.is_empty() {
373+
self.tcx
374+
.sess
375+
.struct_span_err(
376+
meta.span(),
377+
"`#[doc(keyword = \"...\")]` can only be used on empty modules",
378+
)
379+
.emit();
380+
return false;
381+
}
382+
}
383+
_ => {
384+
self.tcx
385+
.sess
386+
.struct_span_err(
387+
meta.span(),
388+
"`#[doc(keyword = \"...\")]` can only be used on modules",
389+
)
390+
.emit();
391+
return false;
392+
}
393+
}
394+
if !rustc_lexer::is_ident(&doc_keyword) {
395+
self.tcx
396+
.sess
397+
.struct_span_err(
398+
meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
399+
&format!("`{}` is not a valid identifier", doc_keyword),
400+
)
401+
.emit();
402+
return false;
403+
}
404+
true
405+
}
406+
368407
fn check_attr_crate_level(
369408
&self,
370409
meta: &NestedMetaItem,
@@ -384,6 +423,7 @@ impl CheckAttrVisitor<'tcx> {
384423
.emit();
385424
return false;
386425
}
426+
true
387427
}
388428

389429
fn check_doc_attrs(&self, attr: &Attribute, hir_id: HirId, target: Target) -> bool {
@@ -396,6 +436,12 @@ impl CheckAttrVisitor<'tcx> {
396436
{
397437
return false;
398438
}
439+
} else if meta.has_name(sym::keyword) {
440+
if !self.check_attr_crate_level(meta, hir_id, "keyword")
441+
|| !self.check_doc_keyword(meta, hir_id)
442+
{
443+
return false;
444+
}
399445
}
400446
}
401447
}

src/librustdoc/clean/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ impl Clean<ExternalCrate> for CrateNum {
162162
.collect()
163163
};
164164

165-
let get_span =
166-
|attr: &ast::NestedMetaItem| Some(attr.meta_item()?.name_value_literal()?.span);
167-
168165
let as_keyword = |res: Res| {
169166
if let Res::Def(DefKind::Mod, def_id) = res {
170167
let attrs = cx.tcx.get_attrs(def_id).clean(cx);

0 commit comments

Comments
 (0)