77//! some of them support an alternate format that emits text, but that should
88//! not be used external to this module.
99
10- use std:: borrow:: Cow ;
1110use std:: cmp:: Ordering ;
1211use std:: fmt:: { self , Display , Write } ;
1312use std:: iter:: { self , once} ;
1413use std:: slice;
1514
16- use itertools:: Either ;
15+ use itertools:: { Either , Itertools } ;
1716use rustc_abi:: ExternAbi ;
1817use rustc_attr_data_structures:: { ConstStability , StabilityLevel , StableSince } ;
1918use rustc_data_structures:: fx:: FxHashSet ;
@@ -483,12 +482,12 @@ fn generate_item_def_id_path(
483482 let mut is_remote = false ;
484483
485484 let url_parts = url_parts ( cx. cache ( ) , def_id, module_fqp, & cx. current , & mut is_remote) ?;
486- let ( url_parts, shortty , fqp ) = make_href ( root_path, shortty, url_parts, & fqp, is_remote) ? ;
487- if def_id = = original_def_id {
488- return Ok ( ( url_parts , shortty , fqp ) ) ;
489- }
490- let kind = ItemType :: from_def_kind ( original_def_kind , Some ( def_kind ) ) ;
491- Ok ( ( format ! ( "{ url_parts}#{kind}.{}" , tcx . item_name ( original_def_id ) ) , shortty, fqp) )
485+ let mut url_parts = make_href ( root_path, shortty, url_parts, & fqp, is_remote) ;
486+ if def_id ! = original_def_id {
487+ let kind = ItemType :: from_def_kind ( original_def_kind , Some ( def_kind ) ) ;
488+ url_parts = format ! ( "{url_parts}#{kind}.{}" , tcx . item_name ( original_def_id ) )
489+ } ;
490+ Ok ( ( url_parts, shortty, fqp) )
492491}
493492
494493fn to_module_fqp ( shortty : ItemType , fqp : & [ Symbol ] ) -> & [ Symbol ] {
@@ -510,7 +509,7 @@ fn url_parts(
510509 builder. extend ( module_fqp. iter ( ) . copied ( ) ) ;
511510 Ok ( builder)
512511 }
513- ExternalLocation :: Local => Ok ( href_relative_parts ( module_fqp, relative_to) . collect ( ) ) ,
512+ ExternalLocation :: Local => Ok ( href_relative_parts ( module_fqp, relative_to) ) ,
514513 ExternalLocation :: Unknown => Err ( HrefError :: DocumentationNotBuilt ) ,
515514 }
516515}
@@ -521,7 +520,7 @@ fn make_href(
521520 mut url_parts : UrlPartsBuilder ,
522521 fqp : & [ Symbol ] ,
523522 is_remote : bool ,
524- ) -> Result < ( String , ItemType , Vec < Symbol > ) , HrefError > {
523+ ) -> String {
525524 if !is_remote && let Some ( root_path) = root_path {
526525 let root = root_path. trim_end_matches ( '/' ) ;
527526 url_parts. push_front ( root) ;
@@ -536,7 +535,7 @@ fn make_href(
536535 url_parts. push_fmt ( format_args ! ( "{shortty}.{last}.html" ) ) ;
537536 }
538537 }
539- Ok ( ( url_parts. finish ( ) , shortty , fqp . to_vec ( ) ) )
538+ url_parts. finish ( )
540539}
541540
542541pub ( crate ) fn href_with_root_path (
@@ -587,7 +586,7 @@ pub(crate) fn href_with_root_path(
587586 Some ( & ( ref fqp, shortty) ) => ( fqp, shortty, {
588587 let module_fqp = to_module_fqp ( shortty, fqp. as_slice ( ) ) ;
589588 debug ! ( ?fqp, ?shortty, ?module_fqp) ;
590- href_relative_parts ( module_fqp, relative_to) . collect ( )
589+ href_relative_parts ( module_fqp, relative_to)
591590 } ) ,
592591 None => {
593592 // Associated items are handled differently with "jump to def". The anchor is generated
@@ -606,7 +605,8 @@ pub(crate) fn href_with_root_path(
606605 }
607606 }
608607 } ;
609- make_href ( root_path, shortty, url_parts, fqp, is_remote)
608+ let url_parts = make_href ( root_path, shortty, url_parts, & fqp, is_remote) ;
609+ Ok ( ( url_parts, shortty, fqp. clone ( ) ) )
610610}
611611
612612pub ( crate ) fn href (
@@ -619,34 +619,30 @@ pub(crate) fn href(
619619/// Both paths should only be modules.
620620/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
621621/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
622- pub ( crate ) fn href_relative_parts < ' fqp > (
623- fqp : & ' fqp [ Symbol ] ,
624- relative_to_fqp : & [ Symbol ] ,
625- ) -> Box < dyn Iterator < Item = Symbol > + ' fqp > {
622+ pub ( crate ) fn href_relative_parts ( fqp : & [ Symbol ] , relative_to_fqp : & [ Symbol ] ) -> UrlPartsBuilder {
626623 for ( i, ( f, r) ) in fqp. iter ( ) . zip ( relative_to_fqp. iter ( ) ) . enumerate ( ) {
627624 // e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
628625 if f != r {
629626 let dissimilar_part_count = relative_to_fqp. len ( ) - i;
630627 let fqp_module = & fqp[ i..] ;
631- return Box :: new (
632- iter:: repeat_n ( sym:: dotdot, dissimilar_part_count)
633- . chain ( fqp_module. iter ( ) . copied ( ) ) ,
634- ) ;
628+ return iter:: repeat_n ( sym:: dotdot, dissimilar_part_count)
629+ . chain ( fqp_module. iter ( ) . copied ( ) )
630+ . collect ( ) ;
635631 }
636632 }
637633 match relative_to_fqp. len ( ) . cmp ( & fqp. len ( ) ) {
638634 Ordering :: Less => {
639635 // e.g. linking to std::sync::atomic from std::sync
640- Box :: new ( fqp[ relative_to_fqp. len ( ) ..fqp. len ( ) ] . iter ( ) . copied ( ) )
636+ fqp[ relative_to_fqp. len ( ) ..fqp. len ( ) ] . iter ( ) . copied ( ) . collect ( )
641637 }
642638 Ordering :: Greater => {
643639 // e.g. linking to std::sync from std::sync::atomic
644640 let dissimilar_part_count = relative_to_fqp. len ( ) - fqp. len ( ) ;
645- Box :: new ( iter:: repeat_n ( sym:: dotdot, dissimilar_part_count) )
641+ iter:: repeat_n ( sym:: dotdot, dissimilar_part_count) . collect ( )
646642 }
647643 Ordering :: Equal => {
648644 // linking to the same module
649- Box :: new ( iter :: empty ( ) )
645+ UrlPartsBuilder :: new ( )
650646 }
651647 }
652648}
@@ -708,13 +704,13 @@ fn resolved_path(
708704 f,
709705 "{path}::{anchor}" ,
710706 path = join_with_double_colon( & fqp[ ..fqp. len( ) - 1 ] ) ,
711- anchor = anchor ( did, * fqp. last( ) . unwrap( ) , cx)
707+ anchor = print_anchor ( did, * fqp. last( ) . unwrap( ) , cx)
712708 )
713709 } else {
714710 write ! ( f, "{}" , last. name)
715711 }
716712 } else {
717- write ! ( f, "{}" , anchor ( did, last. name, cx) )
713+ write ! ( f, "{}" , print_anchor ( did, last. name, cx) )
718714 }
719715 } ) ;
720716 write ! ( w, "{path}{args}" , args = last. args. print( cx) ) ?;
@@ -800,7 +796,7 @@ fn primitive_link_fragment(
800796 Ok ( ( ) )
801797}
802798
803- fn tybounds (
799+ fn print_tybounds (
804800 bounds : & [ clean:: PolyTrait ] ,
805801 lt : & Option < clean:: Lifetime > ,
806802 cx : & Context < ' _ > ,
@@ -832,7 +828,7 @@ fn print_higher_ranked_params_with_space(
832828 } )
833829}
834830
835- pub ( crate ) fn anchor ( did : DefId , text : Symbol , cx : & Context < ' _ > ) -> impl Display {
831+ pub ( crate ) fn print_anchor ( did : DefId , text : Symbol , cx : & Context < ' _ > ) -> impl Display {
836832 fmt:: from_fn ( move |f| {
837833 let parts = href ( did, cx) ;
838834 if let Ok ( ( url, short_ty, fqp) ) = parts {
@@ -866,7 +862,7 @@ fn fmt_type(
866862 }
867863 clean:: DynTrait ( bounds, lt) => {
868864 f. write_str ( "dyn " ) ?;
869- tybounds ( bounds, lt, cx) . fmt ( f)
865+ print_tybounds ( bounds, lt, cx) . fmt ( f)
870866 }
871867 clean:: Infer => write ! ( f, "_" ) ,
872868 clean:: Primitive ( clean:: PrimitiveType :: Never ) => {
@@ -1122,16 +1118,16 @@ impl clean::Impl {
11221118 write ! ( f, "!" ) ?;
11231119 }
11241120 if self . kind . is_fake_variadic ( )
1125- && let generics = ty. generics ( )
1126- && let & [ inner_type] = generics. as_ref ( ) . map_or ( & [ ] [ .. ] , |v| & v [ .. ] )
1121+ && let Some ( generics) = ty. generics ( )
1122+ && let Ok ( inner_type) = generics. exactly_one ( )
11271123 {
11281124 let last = ty. last ( ) ;
11291125 if f. alternate ( ) {
11301126 write ! ( f, "{}<" , last) ?;
11311127 self . print_type ( inner_type, f, use_absolute, cx) ?;
11321128 write ! ( f, ">" ) ?;
11331129 } else {
1134- write ! ( f, "{}<" , anchor ( ty. def_id( ) , last, cx) ) ?;
1130+ write ! ( f, "{}<" , print_anchor ( ty. def_id( ) , last, cx) ) ?;
11351131 self . print_type ( inner_type, f, use_absolute, cx) ?;
11361132 write ! ( f, ">" ) ?;
11371133 }
@@ -1202,11 +1198,10 @@ impl clean::Impl {
12021198 }
12031199 } else if let clean:: Type :: Path { path } = type_
12041200 && let Some ( generics) = path. generics ( )
1205- && generics . len ( ) == 1
1201+ && let Ok ( ty ) = generics . exactly_one ( )
12061202 && self . kind . is_fake_variadic ( )
12071203 {
1208- let ty = generics[ 0 ] ;
1209- let wrapper = anchor ( path. def_id ( ) , path. last ( ) , cx) ;
1204+ let wrapper = print_anchor ( path. def_id ( ) , path. last ( ) , cx) ;
12101205 if f. alternate ( ) {
12111206 write ! ( f, "{wrapper:#}<" ) ?;
12121207 } else {
@@ -1394,50 +1389,47 @@ impl clean::FnDecl {
13941389}
13951390
13961391pub ( crate ) fn visibility_print_with_space ( item : & clean:: Item , cx : & Context < ' _ > ) -> impl Display {
1397- use std:: fmt:: Write as _;
1398- let vis: Cow < ' static , str > = match item. visibility ( cx. tcx ( ) ) {
1399- None => "" . into ( ) ,
1400- Some ( ty:: Visibility :: Public ) => "pub " . into ( ) ,
1401- Some ( ty:: Visibility :: Restricted ( vis_did) ) => {
1402- // FIXME(camelid): This may not work correctly if `item_did` is a module.
1403- // However, rustdoc currently never displays a module's
1404- // visibility, so it shouldn't matter.
1405- let parent_module = find_nearest_parent_module ( cx. tcx ( ) , item. item_id . expect_def_id ( ) ) ;
1406-
1407- if vis_did. is_crate_root ( ) {
1408- "pub(crate) " . into ( )
1409- } else if parent_module == Some ( vis_did) {
1410- // `pub(in foo)` where `foo` is the parent module
1411- // is the same as no visibility modifier
1412- "" . into ( )
1413- } else if parent_module. and_then ( |parent| find_nearest_parent_module ( cx. tcx ( ) , parent) )
1414- == Some ( vis_did)
1415- {
1416- "pub(super) " . into ( )
1417- } else {
1418- let path = cx. tcx ( ) . def_path ( vis_did) ;
1419- debug ! ( "path={path:?}" ) ;
1420- // modified from `resolved_path()` to work with `DefPathData`
1421- let last_name = path. data . last ( ) . unwrap ( ) . data . get_opt_name ( ) . unwrap ( ) ;
1422- let anchor = anchor ( vis_did, last_name, cx) ;
1423-
1424- let mut s = "pub(in " . to_owned ( ) ;
1425- for seg in & path. data [ ..path. data . len ( ) - 1 ] {
1426- let _ = write ! ( s, "{}::" , seg. data. get_opt_name( ) . unwrap( ) ) ;
1427- }
1428- let _ = write ! ( s, "{anchor}) " ) ;
1429- s. into ( )
1430- }
1431- }
1432- } ;
1433-
1434- let is_doc_hidden = item. is_doc_hidden ( ) ;
14351392 fmt:: from_fn ( move |f| {
1436- if is_doc_hidden {
1393+ if item . is_doc_hidden ( ) {
14371394 f. write_str ( "#[doc(hidden)] " ) ?;
14381395 }
14391396
1440- f. write_str ( & vis)
1397+ match item. visibility ( cx. tcx ( ) ) {
1398+ None => { }
1399+ Some ( ty:: Visibility :: Public ) => f. write_str ( "pub " ) ?,
1400+ Some ( ty:: Visibility :: Restricted ( vis_did) ) => {
1401+ // FIXME(camelid): This may not work correctly if `item_did` is a module.
1402+ // However, rustdoc currently never displays a module's
1403+ // visibility, so it shouldn't matter.
1404+ let parent_module =
1405+ find_nearest_parent_module ( cx. tcx ( ) , item. item_id . expect_def_id ( ) ) ;
1406+
1407+ if vis_did. is_crate_root ( ) {
1408+ f. write_str ( "pub(crate) " ) ?;
1409+ } else if parent_module == Some ( vis_did) {
1410+ // `pub(in foo)` where `foo` is the parent module
1411+ // is the same as no visibility modifier; do nothing
1412+ } else if parent_module
1413+ . and_then ( |parent| find_nearest_parent_module ( cx. tcx ( ) , parent) )
1414+ == Some ( vis_did)
1415+ {
1416+ f. write_str ( "pub(super) " ) ?;
1417+ } else {
1418+ let path = cx. tcx ( ) . def_path ( vis_did) ;
1419+ debug ! ( "path={path:?}" ) ;
1420+ // modified from `resolved_path()` to work with `DefPathData`
1421+ let last_name = path. data . last ( ) . unwrap ( ) . data . get_opt_name ( ) . unwrap ( ) ;
1422+ let anchor = print_anchor ( vis_did, last_name, cx) ;
1423+
1424+ f. write_str ( "pub(in " ) ?;
1425+ for seg in & path. data [ ..path. data . len ( ) - 1 ] {
1426+ write ! ( f, "{}::" , seg. data. get_opt_name( ) . unwrap( ) ) ?;
1427+ }
1428+ write ! ( f, "{anchor}) " ) ?;
1429+ }
1430+ }
1431+ }
1432+ Ok ( ( ) )
14411433 } )
14421434}
14431435
0 commit comments