@@ -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 }
0 commit comments