@@ -19,6 +19,7 @@ use rustc_middle::ty;
19
19
use rustc_middle:: ty:: DefIdTree ;
20
20
use rustc_middle:: ty:: TyCtxt ;
21
21
use rustc_span:: def_id:: CRATE_DEF_INDEX ;
22
+ use rustc_span:: { sym, Symbol } ;
22
23
use rustc_target:: spec:: abi:: Abi ;
23
24
24
25
use crate :: clean:: {
@@ -29,6 +30,7 @@ use crate::formats::item_type::ItemType;
29
30
use crate :: html:: escape:: Escape ;
30
31
use crate :: html:: render:: Context ;
31
32
33
+ use super :: url_parts_builder:: estimate_item_path_byte_length;
32
34
use super :: url_parts_builder:: UrlPartsBuilder ;
33
35
34
36
crate trait Print {
@@ -502,11 +504,22 @@ crate enum HrefError {
502
504
NotInExternalCache ,
503
505
}
504
506
507
+ // Panics if `syms` is empty.
508
+ crate fn join_with_double_colon ( syms : & [ Symbol ] ) -> String {
509
+ let mut s = String :: with_capacity ( estimate_item_path_byte_length ( syms. len ( ) ) ) ;
510
+ s. push_str ( & syms[ 0 ] . as_str ( ) ) ;
511
+ for sym in & syms[ 1 ..] {
512
+ s. push_str ( "::" ) ;
513
+ s. push_str ( & sym. as_str ( ) ) ;
514
+ }
515
+ s
516
+ }
517
+
505
518
crate fn href_with_root_path (
506
519
did : DefId ,
507
520
cx : & Context < ' _ > ,
508
521
root_path : Option < & str > ,
509
- ) -> Result < ( String , ItemType , Vec < String > ) , HrefError > {
522
+ ) -> Result < ( String , ItemType , Vec < Symbol > ) , HrefError > {
510
523
let tcx = cx. tcx ( ) ;
511
524
let def_kind = tcx. def_kind ( did) ;
512
525
let did = match def_kind {
@@ -518,7 +531,7 @@ crate fn href_with_root_path(
518
531
} ;
519
532
let cache = cx. cache ( ) ;
520
533
let relative_to = & cx. current ;
521
- fn to_module_fqp ( shortty : ItemType , fqp : & [ String ] ) -> & [ String ] {
534
+ fn to_module_fqp ( shortty : ItemType , fqp : & [ Symbol ] ) -> & [ Symbol ] {
522
535
if shortty == ItemType :: Module { fqp } else { & fqp[ ..fqp. len ( ) - 1 ] }
523
536
}
524
537
@@ -533,9 +546,9 @@ crate fn href_with_root_path(
533
546
let mut is_remote = false ;
534
547
let ( fqp, shortty, mut url_parts) = match cache. paths . get ( & did) {
535
548
Some ( & ( ref fqp, shortty) ) => ( fqp, shortty, {
536
- let module_fqp = to_module_fqp ( shortty, fqp) ;
549
+ let module_fqp = to_module_fqp ( shortty, fqp. as_slice ( ) ) ;
537
550
debug ! ( ?fqp, ?shortty, ?module_fqp) ;
538
- href_relative_parts ( module_fqp, relative_to)
551
+ href_relative_parts ( module_fqp, relative_to) . collect ( )
539
552
} ) ,
540
553
None => {
541
554
if let Some ( & ( ref fqp, shortty) ) = cache. external_paths . get ( & did) {
@@ -548,10 +561,12 @@ crate fn href_with_root_path(
548
561
is_remote = true ;
549
562
let s = s. trim_end_matches ( '/' ) ;
550
563
let mut builder = UrlPartsBuilder :: singleton ( s) ;
551
- builder. extend ( module_fqp. iter ( ) . map ( String :: as_str ) ) ;
564
+ builder. extend ( module_fqp. iter ( ) . copied ( ) ) ;
552
565
builder
553
566
}
554
- ExternalLocation :: Local => href_relative_parts ( module_fqp, relative_to) ,
567
+ ExternalLocation :: Local => {
568
+ href_relative_parts ( module_fqp, relative_to) . collect ( )
569
+ }
555
570
ExternalLocation :: Unknown => return Err ( HrefError :: DocumentationNotBuilt ) ,
556
571
} ,
557
572
)
@@ -567,45 +582,50 @@ crate fn href_with_root_path(
567
582
}
568
583
}
569
584
debug ! ( ?url_parts) ;
570
- let last = & fqp. last ( ) . unwrap ( ) [ ..] ;
571
585
match shortty {
572
586
ItemType :: Module => {
573
587
url_parts. push ( "index.html" ) ;
574
588
}
575
589
_ => {
576
- let filename = format ! ( "{}.{}.html" , shortty. as_str( ) , last) ;
577
- url_parts. push ( & filename) ;
590
+ let prefix = shortty. as_str ( ) ;
591
+ let last = fqp. last ( ) . unwrap ( ) ;
592
+ url_parts. push_fmt ( format_args ! ( "{}.{}.html" , prefix, last) ) ;
578
593
}
579
594
}
580
595
Ok ( ( url_parts. finish ( ) , shortty, fqp. to_vec ( ) ) )
581
596
}
582
597
583
- crate fn href ( did : DefId , cx : & Context < ' _ > ) -> Result < ( String , ItemType , Vec < String > ) , HrefError > {
598
+ crate fn href ( did : DefId , cx : & Context < ' _ > ) -> Result < ( String , ItemType , Vec < Symbol > ) , HrefError > {
584
599
href_with_root_path ( did, cx, None )
585
600
}
586
601
587
602
/// Both paths should only be modules.
588
603
/// This is because modules get their own directories; that is, `std::vec` and `std::vec::Vec` will
589
604
/// both need `../iter/trait.Iterator.html` to get at the iterator trait.
590
- crate fn href_relative_parts ( fqp : & [ String ] , relative_to_fqp : & [ String ] ) -> UrlPartsBuilder {
605
+ crate fn href_relative_parts < ' fqp > (
606
+ fqp : & ' fqp [ Symbol ] ,
607
+ relative_to_fqp : & [ Symbol ] ,
608
+ ) -> Box < dyn Iterator < Item = Symbol > + ' fqp > {
591
609
for ( i, ( f, r) ) in fqp. iter ( ) . zip ( relative_to_fqp. iter ( ) ) . enumerate ( ) {
592
610
// e.g. linking to std::iter from std::vec (`dissimilar_part_count` will be 1)
593
611
if f != r {
594
612
let dissimilar_part_count = relative_to_fqp. len ( ) - i;
595
- let fqp_module = fqp[ i..fqp. len ( ) ] . iter ( ) . map ( String :: as_str) ;
596
- return iter:: repeat ( ".." ) . take ( dissimilar_part_count) . chain ( fqp_module) . collect ( ) ;
613
+ let fqp_module = & fqp[ i..fqp. len ( ) ] ;
614
+ return box iter:: repeat ( sym:: dotdot)
615
+ . take ( dissimilar_part_count)
616
+ . chain ( fqp_module. iter ( ) . copied ( ) ) ;
597
617
}
598
618
}
599
619
// e.g. linking to std::sync::atomic from std::sync
600
620
if relative_to_fqp. len ( ) < fqp. len ( ) {
601
- fqp[ relative_to_fqp. len ( ) ..fqp. len ( ) ] . iter ( ) . map ( String :: as_str ) . collect ( )
621
+ box fqp[ relative_to_fqp. len ( ) ..fqp. len ( ) ] . iter ( ) . copied ( )
602
622
// e.g. linking to std::sync from std::sync::atomic
603
623
} else if fqp. len ( ) < relative_to_fqp. len ( ) {
604
624
let dissimilar_part_count = relative_to_fqp. len ( ) - fqp. len ( ) ;
605
- iter:: repeat ( ".." ) . take ( dissimilar_part_count) . collect ( )
625
+ box iter:: repeat ( sym :: dotdot ) . take ( dissimilar_part_count)
606
626
// linking to the same module
607
627
} else {
608
- UrlPartsBuilder :: new ( )
628
+ box iter :: empty ( )
609
629
}
610
630
}
611
631
@@ -632,14 +652,14 @@ fn resolved_path<'cx>(
632
652
if let Ok ( ( _, _, fqp) ) = href ( did, cx) {
633
653
format ! (
634
654
"{}::{}" ,
635
- fqp[ ..fqp. len( ) - 1 ] . join ( "::" ) ,
636
- anchor( did, fqp. last( ) . unwrap( ) , cx)
655
+ join_with_double_colon ( & fqp[ ..fqp. len( ) - 1 ] ) ,
656
+ anchor( did, * fqp. last( ) . unwrap( ) , cx)
637
657
)
638
658
} else {
639
659
last. name . to_string ( )
640
660
}
641
661
} else {
642
- anchor ( did, last. name . as_str ( ) , cx) . to_string ( )
662
+ anchor ( did, last. name , cx) . to_string ( )
643
663
} ;
644
664
write ! ( w, "{}{}" , path, last. args. print( cx) ) ?;
645
665
}
@@ -668,30 +688,31 @@ fn primitive_link(
668
688
needs_termination = true ;
669
689
}
670
690
Some ( & def_id) => {
671
- let cname_sym;
672
691
let loc = match m. extern_locations [ & def_id. krate ] {
673
692
ExternalLocation :: Remote ( ref s) => {
674
- cname_sym = ExternalCrate { crate_num : def_id. krate } . name ( cx. tcx ( ) ) ;
675
- Some ( vec ! [ s. trim_end_matches( '/' ) , cname_sym. as_str( ) ] )
693
+ let cname_sym = ExternalCrate { crate_num : def_id. krate } . name ( cx. tcx ( ) ) ;
694
+ let builder: UrlPartsBuilder =
695
+ [ s. as_str ( ) . trim_end_matches ( '/' ) , cname_sym. as_str ( ) ]
696
+ . into_iter ( )
697
+ . collect ( ) ;
698
+ Some ( builder)
676
699
}
677
700
ExternalLocation :: Local => {
678
- cname_sym = ExternalCrate { crate_num : def_id. krate } . name ( cx. tcx ( ) ) ;
679
- Some ( if cx. current . first ( ) . map ( |x| & x [ .. ] ) == Some ( cname_sym. as_str ( ) ) {
680
- iter:: repeat ( ".." ) . take ( cx. current . len ( ) - 1 ) . collect ( )
701
+ let cname_sym = ExternalCrate { crate_num : def_id. krate } . name ( cx. tcx ( ) ) ;
702
+ Some ( if cx. current . first ( ) == Some ( & cname_sym) {
703
+ iter:: repeat ( sym :: dotdot ) . take ( cx. current . len ( ) - 1 ) . collect ( )
681
704
} else {
682
- let cname = iter:: once ( cname_sym. as_str ( ) ) ;
683
- iter:: repeat ( ".." ) . take ( cx. current . len ( ) ) . chain ( cname) . collect ( )
705
+ iter:: repeat ( sym:: dotdot)
706
+ . take ( cx. current . len ( ) )
707
+ . chain ( iter:: once ( cname_sym) )
708
+ . collect ( )
684
709
} )
685
710
}
686
711
ExternalLocation :: Unknown => None ,
687
712
} ;
688
- if let Some ( loc) = loc {
689
- write ! (
690
- f,
691
- "<a class=\" primitive\" href=\" {}/primitive.{}.html\" >" ,
692
- loc. join( "/" ) ,
693
- prim. as_sym( )
694
- ) ?;
713
+ if let Some ( mut loc) = loc {
714
+ loc. push_fmt ( format_args ! ( "primitive.{}.html" , prim. as_sym( ) ) ) ;
715
+ write ! ( f, "<a class=\" primitive\" href=\" {}\" >" , loc. finish( ) ) ?;
695
716
needs_termination = true ;
696
717
}
697
718
}
@@ -730,7 +751,7 @@ fn tybounds<'a, 'tcx: 'a>(
730
751
731
752
crate fn anchor < ' a , ' cx : ' a > (
732
753
did : DefId ,
733
- text : & ' a str ,
754
+ text : Symbol ,
734
755
cx : & ' cx Context < ' _ > ,
735
756
) -> impl fmt:: Display + ' a {
736
757
let parts = href ( did, cx) ;
@@ -742,8 +763,8 @@ crate fn anchor<'a, 'cx: 'a>(
742
763
short_ty,
743
764
url,
744
765
short_ty,
745
- fqp . join ( "::" ) ,
746
- text
766
+ join_with_double_colon ( & fqp ) ,
767
+ text. as_str ( )
747
768
)
748
769
} else {
749
770
write ! ( f, "{}" , text)
@@ -960,7 +981,7 @@ fn fmt_type<'cx>(
960
981
url = url,
961
982
shortty = ItemType :: AssocType ,
962
983
name = name,
963
- path = path . join ( "::" )
984
+ path = join_with_double_colon ( path ) ,
964
985
) ?;
965
986
}
966
987
_ => write ! ( f, "{}" , name) ?,
@@ -1270,7 +1291,7 @@ impl clean::Visibility {
1270
1291
debug ! ( "path={:?}" , path) ;
1271
1292
// modified from `resolved_path()` to work with `DefPathData`
1272
1293
let last_name = path. data . last ( ) . unwrap ( ) . data . get_opt_name ( ) . unwrap ( ) ;
1273
- let anchor = anchor ( vis_did, last_name. as_str ( ) , cx) . to_string ( ) ;
1294
+ let anchor = anchor ( vis_did, last_name, cx) . to_string ( ) ;
1274
1295
1275
1296
let mut s = "pub(in " . to_owned ( ) ;
1276
1297
for seg in & path. data [ ..path. data . len ( ) - 1 ] {
0 commit comments