@@ -836,6 +836,62 @@ impl AttributesExt for Attributes {
836836 }
837837}
838838
839+ /// Given a def, returns its name and disambiguator
840+ /// for a value namespace
841+ ///
842+ /// Returns None for things which cannot be ambiguous since
843+ /// they exist in both namespaces (structs and modules)
844+ fn value_ns_kind ( def : Def , path_str : & str ) -> Option < ( & ' static str , String ) > {
845+ match def {
846+ // structs and mods exist in both namespaces. skip them
847+ Def :: StructCtor ( ..) | Def :: Mod ( ..) => None ,
848+ Def :: Variant ( ..) | Def :: VariantCtor ( ..)
849+ => Some ( ( "variant" , format ! ( "{}()" , path_str) ) ) ,
850+ Def :: Fn ( ..)
851+ => Some ( ( "function" , format ! ( "{}()" , path_str) ) ) ,
852+ Def :: Method ( ..)
853+ => Some ( ( "method" , format ! ( "{}()" , path_str) ) ) ,
854+ Def :: Const ( ..)
855+ => Some ( ( "const" , format ! ( "const@{}" , path_str) ) ) ,
856+ Def :: Static ( ..)
857+ => Some ( ( "static" , format ! ( "static@{}" , path_str) ) ) ,
858+ _ => Some ( ( "value" , format ! ( "value@{}" , path_str) ) ) ,
859+ }
860+ }
861+
862+ /// Given a def, returns its name, the article to be used, and a disambiguator
863+ /// for the type namespace
864+ fn type_ns_kind ( def : Def , path_str : & str ) -> ( & ' static str , & ' static str , String ) {
865+ let ( kind, article) = match def {
866+ // we can still have non-tuple structs
867+ Def :: Struct ( ..) => ( "struct" , "a" ) ,
868+ Def :: Enum ( ..) => ( "enum" , "an" ) ,
869+ Def :: Trait ( ..) => ( "trait" , "a" ) ,
870+ Def :: Union ( ..) => ( "union" , "a" ) ,
871+ _ => ( "type" , "a" ) ,
872+ } ;
873+ ( kind, article, format ! ( "{}@{}" , kind, path_str) )
874+ }
875+
876+ fn ambiguity_error ( cx : & DocContext , attrs : & Attributes ,
877+ path_str : & str ,
878+ article1 : & str , kind1 : & str , disambig1 : & str ,
879+ article2 : & str , kind2 : & str , disambig2 : & str ) {
880+ let sp = attrs. doc_strings . first ( )
881+ . map_or ( DUMMY_SP , |a| a. span ( ) ) ;
882+ cx. sess ( )
883+ . struct_span_err ( sp,
884+ & format ! ( "`{}` is both {} {} and {} {}" ,
885+ path_str, article1, kind1,
886+ article2, kind2) )
887+ . help ( & format ! ( "try `{0}` if you want to select the {1}, \
888+ or `{2}@{3}` if you want to \
889+ select the {2}",
890+ disambig1, kind1, disambig2,
891+ kind2) )
892+ . emit ( ) ;
893+ }
894+
839895enum PathKind {
840896 /// can be either value or type, not a macro
841897 Unknown ,
@@ -846,6 +902,7 @@ enum PathKind {
846902 /// types, traits, everything in the type namespace
847903 Type
848904}
905+
849906impl Clean < Attributes > for [ ast:: Attribute ] {
850907 fn clean ( & self , cx : & DocContext ) -> Attributes {
851908 let mut attrs = Attributes :: from_ast ( cx. sess ( ) . diagnostic ( ) , self ) ;
@@ -957,43 +1014,13 @@ impl Clean<Attributes> for [ast::Attribute] {
9571014 if let Ok ( path) = resolve ( false ) {
9581015 // if there is something in both namespaces
9591016 if let Ok ( value_path) = resolve ( true ) {
960- let kind = match value_path. def {
961- // structs and mods exist in both namespaces. skip them
962- Def :: StructCtor ( ..) | Def :: Mod ( ..) => None ,
963- Def :: Variant ( ..) | Def :: VariantCtor ( ..)
964- => Some ( ( "variant" , format ! ( "{}()" , path_str) ) ) ,
965- Def :: Fn ( ..)
966- => Some ( ( "function" , format ! ( "{}()" , path_str) ) ) ,
967- Def :: Method ( ..)
968- => Some ( ( "method" , format ! ( "{}()" , path_str) ) ) ,
969- Def :: Const ( ..)
970- => Some ( ( "const" , format ! ( "const@{}" , path_str) ) ) ,
971- Def :: Static ( ..)
972- => Some ( ( "static" , format ! ( "static@{}" , path_str) ) ) ,
973- _ => Some ( ( "value" , format ! ( "static@{}" , path_str) ) ) ,
974- } ;
975- if let Some ( ( value_kind, disambig) ) = kind {
976- let ( type_kind, article) = match path. def {
977- // we can still have non-tuple structs
978- Def :: Struct ( ..) => ( "struct" , "a" ) ,
979- Def :: Enum ( ..) => ( "enum" , "an" ) ,
980- Def :: Trait ( ..) => ( "trait" , "a" ) ,
981- Def :: Union ( ..) => ( "union" , "a" ) ,
982- _ => ( "type" , "a" ) ,
983- } ;
984- let sp = attrs. doc_strings . first ( )
985- . map_or ( DUMMY_SP , |a| a. span ( ) ) ;
986- cx. sess ( )
987- . struct_span_err ( sp,
988- & format ! ( "`{}` is both {} {} and a {}" ,
989- path_str, article, type_kind,
990- value_kind) )
991- . help ( & format ! ( "try `{0}` if you want to select the {1}, \
992- or `{2}@{3}` if you want to \
993- select the {2}",
994- disambig, value_kind, type_kind,
995- path_str) )
996- . emit ( ) ;
1017+ let kind = value_ns_kind ( value_path. def , path_str) ;
1018+ if let Some ( ( value_kind, value_disambig) ) = kind {
1019+ let ( type_kind, article, type_disambig)
1020+ = type_ns_kind ( path. def ) ;
1021+ ambiguity_error ( cx, & attrs,
1022+ article, type_kind, type_disambig,
1023+ "a" , value_kind, value_disambig) ;
9971024 continue ;
9981025 }
9991026 }
0 commit comments