@@ -394,33 +394,50 @@ impl CheckAttrVisitor<'tcx> {
394394 . emit ( ) ;
395395 }
396396
397- fn check_doc_alias ( & self , meta : & NestedMetaItem , hir_id : HirId , target : Target ) -> bool {
398- let doc_alias = meta. value_str ( ) . map ( |s| s. to_string ( ) ) . unwrap_or_else ( String :: new) ;
397+ fn check_doc_alias_value (
398+ & self ,
399+ meta : & NestedMetaItem ,
400+ doc_alias : & str ,
401+ hir_id : HirId ,
402+ target : Target ,
403+ is_list : bool ,
404+ ) -> bool {
405+ let tcx = self . tcx ;
406+ let err_fn = move |span : Span , msg : & str | {
407+ tcx. sess . span_err (
408+ span,
409+ & format ! (
410+ "`#[doc(alias{})]` {}" ,
411+ if is_list { "(\" ...\" )" } else { " = \" ...\" " } ,
412+ msg,
413+ ) ,
414+ ) ;
415+ false
416+ } ;
399417 if doc_alias. is_empty ( ) {
400- self . doc_attr_str_error ( meta, "alias" ) ;
401- return false ;
418+ return err_fn (
419+ meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
420+ "attribute cannot have empty value" ,
421+ ) ;
402422 }
403423 if let Some ( c) =
404424 doc_alias. chars ( ) . find ( |& c| c == '"' || c == '\'' || ( c. is_whitespace ( ) && c != ' ' ) )
405425 {
406- self . tcx
407- . sess
408- . struct_span_err (
409- meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
410- & format ! ( "{:?} character isn't allowed in `#[doc(alias = \" ...\" )]`" , c) ,
411- )
412- . emit ( ) ;
426+ self . tcx . sess . span_err (
427+ meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
428+ & format ! (
429+ "{:?} character isn't allowed in `#[doc(alias{})]`" ,
430+ c,
431+ if is_list { "(\" ...\" )" } else { " = \" ...\" " } ,
432+ ) ,
433+ ) ;
413434 return false ;
414435 }
415436 if doc_alias. starts_with ( ' ' ) || doc_alias. ends_with ( ' ' ) {
416- self . tcx
417- . sess
418- . struct_span_err (
419- meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
420- "`#[doc(alias = \" ...\" )]` cannot start or end with ' '" ,
421- )
422- . emit ( ) ;
423- return false ;
437+ return err_fn (
438+ meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
439+ "cannot start or end with ' '" ,
440+ ) ;
424441 }
425442 if let Some ( err) = match target {
426443 Target :: Impl => Some ( "implementation block" ) ,
@@ -446,27 +463,63 @@ impl CheckAttrVisitor<'tcx> {
446463 }
447464 _ => None ,
448465 } {
449- self . tcx
450- . sess
451- . struct_span_err (
452- meta. span ( ) ,
453- & format ! ( "`#[doc(alias = \" ...\" )]` isn't allowed on {}" , err) ,
454- )
455- . emit ( ) ;
456- return false ;
466+ return err_fn ( meta. span ( ) , & format ! ( "isn't allowed on {}" , err) ) ;
457467 }
458468 let item_name = self . tcx . hir ( ) . name ( hir_id) ;
459469 if & * item_name. as_str ( ) == doc_alias {
470+ return err_fn ( meta. span ( ) , "is the same as the item's name" ) ;
471+ }
472+ true
473+ }
474+
475+ fn check_doc_alias ( & self , meta : & NestedMetaItem , hir_id : HirId , target : Target ) -> bool {
476+ if let Some ( values) = meta. meta_item_list ( ) {
477+ let mut errors = 0 ;
478+ for v in values {
479+ match v. literal ( ) {
480+ Some ( l) => match l. kind {
481+ LitKind :: Str ( s, _) => {
482+ if !self . check_doc_alias_value ( v, & s. as_str ( ) , hir_id, target, true ) {
483+ errors += 1 ;
484+ }
485+ }
486+ _ => {
487+ self . tcx
488+ . sess
489+ . struct_span_err (
490+ v. span ( ) ,
491+ "`#[doc(alias(\" a\" ))]` expects string literals" ,
492+ )
493+ . emit ( ) ;
494+ errors += 1 ;
495+ }
496+ } ,
497+ None => {
498+ self . tcx
499+ . sess
500+ . struct_span_err (
501+ v. span ( ) ,
502+ "`#[doc(alias(\" a\" ))]` expects string literals" ,
503+ )
504+ . emit ( ) ;
505+ errors += 1 ;
506+ }
507+ }
508+ }
509+ errors == 0
510+ } else if let Some ( doc_alias) = meta. value_str ( ) . map ( |s| s. to_string ( ) ) {
511+ self . check_doc_alias_value ( meta, & doc_alias, hir_id, target, false )
512+ } else {
460513 self . tcx
461514 . sess
462515 . struct_span_err (
463516 meta. span ( ) ,
464- & format ! ( "`#[doc(alias = \" ...\" )]` is the same as the item's name" ) ,
517+ "doc alias attribute expects a string `#[doc(alias = \" a\" )]` or a list of \
518+ strings `#[doc(alias(\" a\" , \" b\" ))]`",
465519 )
466520 . emit ( ) ;
467- return false ;
521+ false
468522 }
469- true
470523 }
471524
472525 fn check_doc_keyword ( & self , meta : & NestedMetaItem , hir_id : HirId ) -> bool {
0 commit comments