@@ -64,7 +64,7 @@ use rustc::hir;
64
64
use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
65
65
use rustc_data_structures:: flock;
66
66
67
- use clean:: { self , Attributes , GetDefId } ;
67
+ use clean:: { self , Attributes , GetDefId , SelfTy , Mutability } ;
68
68
use doctree;
69
69
use fold:: DocFolder ;
70
70
use html:: escape:: Escape ;
@@ -266,6 +266,7 @@ pub struct Cache {
266
266
seen_mod : bool ,
267
267
stripped_mod : bool ,
268
268
deref_trait_did : Option < DefId > ,
269
+ deref_mut_trait_did : Option < DefId > ,
269
270
270
271
// In rare case where a structure is defined in one module but implemented
271
272
// in another, if the implementing module is parsed before defining module,
@@ -283,6 +284,7 @@ pub struct RenderInfo {
283
284
pub external_paths : :: core:: ExternalPaths ,
284
285
pub external_typarams : FnvHashMap < DefId , String > ,
285
286
pub deref_trait_did : Option < DefId > ,
287
+ pub deref_mut_trait_did : Option < DefId > ,
286
288
}
287
289
288
290
/// Helper struct to render all source code to HTML pages
@@ -508,6 +510,7 @@ pub fn run(mut krate: clean::Crate,
508
510
external_paths,
509
511
external_typarams,
510
512
deref_trait_did,
513
+ deref_mut_trait_did,
511
514
} = renderinfo;
512
515
513
516
let external_paths = external_paths. into_iter ( )
@@ -532,6 +535,7 @@ pub fn run(mut krate: clean::Crate,
532
535
orphan_methods : Vec :: new ( ) ,
533
536
traits : mem:: replace ( & mut krate. external_traits , FnvHashMap ( ) ) ,
534
537
deref_trait_did : deref_trait_did,
538
+ deref_mut_trait_did : deref_mut_trait_did,
535
539
typarams : external_typarams,
536
540
} ;
537
541
@@ -2604,7 +2608,13 @@ impl<'a> AssocItemLink<'a> {
2604
2608
2605
2609
enum AssocItemRender < ' a > {
2606
2610
All ,
2607
- DerefFor { trait_ : & ' a clean:: Type , type_ : & ' a clean:: Type } ,
2611
+ DerefFor { trait_ : & ' a clean:: Type , type_ : & ' a clean:: Type , deref_mut_ : bool }
2612
+ }
2613
+
2614
+ #[ derive( Copy , Clone , PartialEq ) ]
2615
+ enum RenderMode {
2616
+ Normal ,
2617
+ ForDeref { mut_ : bool } ,
2608
2618
}
2609
2619
2610
2620
fn render_assoc_items ( w : & mut fmt:: Formatter ,
@@ -2621,19 +2631,19 @@ fn render_assoc_items(w: &mut fmt::Formatter,
2621
2631
i. inner_impl ( ) . trait_ . is_none ( )
2622
2632
} ) ;
2623
2633
if !non_trait. is_empty ( ) {
2624
- let render_header = match what {
2634
+ let render_mode = match what {
2625
2635
AssocItemRender :: All => {
2626
2636
write ! ( w, "<h2 id='methods'>Methods</h2>" ) ?;
2627
- true
2637
+ RenderMode :: Normal
2628
2638
}
2629
- AssocItemRender :: DerefFor { trait_, type_ } => {
2639
+ AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
2630
2640
write ! ( w, "<h2 id='deref-methods'>Methods from \
2631
2641
{}<Target={}></h2>", trait_, type_) ?;
2632
- false
2642
+ RenderMode :: ForDeref { mut_ : deref_mut_ }
2633
2643
}
2634
2644
} ;
2635
2645
for i in & non_trait {
2636
- render_impl ( w, cx, i, AssocItemLink :: Anchor ( None ) , render_header ,
2646
+ render_impl ( w, cx, i, AssocItemLink :: Anchor ( None ) , render_mode ,
2637
2647
containing_item. stable_since ( ) ) ?;
2638
2648
}
2639
2649
}
@@ -2645,29 +2655,34 @@ fn render_assoc_items(w: &mut fmt::Formatter,
2645
2655
t. inner_impl ( ) . trait_ . def_id ( ) == c. deref_trait_did
2646
2656
} ) ;
2647
2657
if let Some ( impl_) = deref_impl {
2648
- render_deref_methods ( w, cx, impl_, containing_item) ?;
2658
+ let has_deref_mut = traits. iter ( ) . find ( |t| {
2659
+ t. inner_impl ( ) . trait_ . def_id ( ) == c. deref_mut_trait_did
2660
+ } ) . is_some ( ) ;
2661
+ render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut) ?;
2649
2662
}
2650
2663
write ! ( w, "<h2 id='implementations'>Trait \
2651
2664
Implementations</h2>") ?;
2652
2665
for i in & traits {
2653
2666
let did = i. trait_did ( ) . unwrap ( ) ;
2654
2667
let assoc_link = AssocItemLink :: GotoSource ( did, & i. inner_impl ( ) . provided_trait_methods ) ;
2655
- render_impl ( w, cx, i, assoc_link, true , containing_item. stable_since ( ) ) ?;
2668
+ render_impl ( w, cx, i, assoc_link,
2669
+ RenderMode :: Normal , containing_item. stable_since ( ) ) ?;
2656
2670
}
2657
2671
}
2658
2672
Ok ( ( ) )
2659
2673
}
2660
2674
2661
2675
fn render_deref_methods ( w : & mut fmt:: Formatter , cx : & Context , impl_ : & Impl ,
2662
- container_item : & clean:: Item ) -> fmt:: Result {
2676
+ container_item : & clean:: Item , deref_mut : bool ) -> fmt:: Result {
2663
2677
let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
2664
2678
let target = impl_. inner_impl ( ) . items . iter ( ) . filter_map ( |item| {
2665
2679
match item. inner {
2666
2680
clean:: TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
2667
2681
_ => None ,
2668
2682
}
2669
2683
} ) . next ( ) . expect ( "Expected associated type binding" ) ;
2670
- let what = AssocItemRender :: DerefFor { trait_ : deref_type, type_ : target } ;
2684
+ let what = AssocItemRender :: DerefFor { trait_ : deref_type, type_ : target,
2685
+ deref_mut_ : deref_mut } ;
2671
2686
if let Some ( did) = target. def_id ( ) {
2672
2687
render_assoc_items ( w, cx, container_item, did, what)
2673
2688
} else {
@@ -2681,12 +2696,9 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
2681
2696
}
2682
2697
}
2683
2698
2684
- // Render_header is false when we are rendering a `Deref` impl and true
2685
- // otherwise. If render_header is false, we will avoid rendering static
2686
- // methods, since they are not accessible for the type implementing `Deref`
2687
2699
fn render_impl ( w : & mut fmt:: Formatter , cx : & Context , i : & Impl , link : AssocItemLink ,
2688
- render_header : bool , outer_version : Option < & str > ) -> fmt:: Result {
2689
- if render_header {
2700
+ render_mode : RenderMode , outer_version : Option < & str > ) -> fmt:: Result {
2701
+ if render_mode == RenderMode :: Normal {
2690
2702
write ! ( w, "<h3 class='impl'><span class='in-band'><code>{}</code>" , i. inner_impl( ) ) ?;
2691
2703
write ! ( w, "</span><span class='out-of-band'>" ) ?;
2692
2704
let since = i. impl_item . stability . as_ref ( ) . map ( |s| & s. since [ ..] ) ;
@@ -2707,22 +2719,43 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2707
2719
}
2708
2720
2709
2721
fn doc_impl_item ( w : & mut fmt:: Formatter , cx : & Context , item : & clean:: Item ,
2710
- link : AssocItemLink , render_static : bool ,
2722
+ link : AssocItemLink , render_mode : RenderMode ,
2711
2723
is_default_item : bool , outer_version : Option < & str > ,
2712
2724
trait_ : Option < & clean:: Trait > ) -> fmt:: Result {
2713
2725
let item_type = item_type ( item) ;
2714
2726
let name = item. name . as_ref ( ) . unwrap ( ) ;
2715
2727
2716
- let is_static = match item. inner {
2717
- clean:: MethodItem ( ref method) => !method. decl . has_self ( ) ,
2718
- clean:: TyMethodItem ( ref method) => !method. decl . has_self ( ) ,
2719
- _ => false
2728
+ let render_method_item: bool = match render_mode {
2729
+ RenderMode :: Normal => true ,
2730
+ RenderMode :: ForDeref { mut_ : deref_mut_ } => {
2731
+ let self_type_opt = match item. inner {
2732
+ clean:: MethodItem ( ref method) => method. decl . self_type ( ) ,
2733
+ clean:: TyMethodItem ( ref method) => method. decl . self_type ( ) ,
2734
+ _ => None
2735
+ } ;
2736
+
2737
+ if let Some ( self_ty) = self_type_opt {
2738
+ let by_mut_ref = match self_ty {
2739
+ SelfTy :: SelfBorrowed ( _lifetime, mutability) => {
2740
+ mutability == Mutability :: Mutable
2741
+ } ,
2742
+ SelfTy :: SelfExplicit ( clean:: BorrowedRef { mutability, .. } ) => {
2743
+ mutability == Mutability :: Mutable
2744
+ } ,
2745
+ _ => false ,
2746
+ } ;
2747
+
2748
+ deref_mut_ || !by_mut_ref
2749
+ } else {
2750
+ false
2751
+ }
2752
+ } ,
2720
2753
} ;
2721
2754
2722
2755
match item. inner {
2723
2756
clean:: MethodItem ( ..) | clean:: TyMethodItem ( ..) => {
2724
2757
// Only render when the method is not static or we allow static methods
2725
- if !is_static || render_static {
2758
+ if render_method_item {
2726
2759
let id = derive_id ( format ! ( "{}.{}" , item_type, name) ) ;
2727
2760
let ns_id = derive_id ( format ! ( "{}.{}" , name, item_type. name_space( ) ) ) ;
2728
2761
write ! ( w, "<h4 id='{}' class='{}'>" , id, item_type) ?;
@@ -2770,7 +2803,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2770
2803
_ => panic ! ( "can't make docs for trait item with name {:?}" , item. name)
2771
2804
}
2772
2805
2773
- if !is_static || render_static {
2806
+ if render_method_item || render_mode == RenderMode :: Normal {
2774
2807
if !is_default_item {
2775
2808
if let Some ( t) = trait_ {
2776
2809
// The trait item may have been stripped so we might not
@@ -2803,15 +2836,15 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2803
2836
2804
2837
write ! ( w, "<div class='impl-items'>" ) ?;
2805
2838
for trait_item in & i. inner_impl ( ) . items {
2806
- doc_impl_item ( w, cx, trait_item, link, render_header ,
2839
+ doc_impl_item ( w, cx, trait_item, link, render_mode ,
2807
2840
false , outer_version, trait_) ?;
2808
2841
}
2809
2842
2810
2843
fn render_default_items ( w : & mut fmt:: Formatter ,
2811
2844
cx : & Context ,
2812
2845
t : & clean:: Trait ,
2813
2846
i : & clean:: Impl ,
2814
- render_static : bool ,
2847
+ render_mode : RenderMode ,
2815
2848
outer_version : Option < & str > ) -> fmt:: Result {
2816
2849
for trait_item in & t. items {
2817
2850
let n = trait_item. name . clone ( ) ;
@@ -2821,7 +2854,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2821
2854
let did = i. trait_ . as_ref ( ) . unwrap ( ) . def_id ( ) . unwrap ( ) ;
2822
2855
let assoc_link = AssocItemLink :: GotoSource ( did, & i. provided_trait_methods ) ;
2823
2856
2824
- doc_impl_item ( w, cx, trait_item, assoc_link, render_static , true ,
2857
+ doc_impl_item ( w, cx, trait_item, assoc_link, render_mode , true ,
2825
2858
outer_version, None ) ?;
2826
2859
}
2827
2860
Ok ( ( ) )
@@ -2830,7 +2863,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2830
2863
// If we've implemented a trait, then also emit documentation for all
2831
2864
// default items which weren't overridden in the implementation block.
2832
2865
if let Some ( t) = trait_ {
2833
- render_default_items ( w, cx, t, & i. inner_impl ( ) , render_header , outer_version) ?;
2866
+ render_default_items ( w, cx, t, & i. inner_impl ( ) , render_mode , outer_version) ?;
2834
2867
}
2835
2868
write ! ( w, "</div>" ) ?;
2836
2869
Ok ( ( ) )
0 commit comments