@@ -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_impl_items : 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
@@ -2603,7 +2607,13 @@ impl<'a> AssocItemLink<'a> {
2603
2607
2604
2608
enum AssocItemRender < ' a > {
2605
2609
All ,
2606
- DerefFor { trait_ : & ' a clean:: Type , type_ : & ' a clean:: Type } ,
2610
+ DerefFor { trait_ : & ' a clean:: Type , type_ : & ' a clean:: Type , deref_mut_ : bool }
2611
+ }
2612
+
2613
+ #[ derive( Copy , Clone , PartialEq ) ]
2614
+ enum RenderMode {
2615
+ Normal ,
2616
+ ForDeref { mut_ : bool } ,
2607
2617
}
2608
2618
2609
2619
fn render_assoc_items ( w : & mut fmt:: Formatter ,
@@ -2620,19 +2630,19 @@ fn render_assoc_items(w: &mut fmt::Formatter,
2620
2630
i. inner_impl ( ) . trait_ . is_none ( )
2621
2631
} ) ;
2622
2632
if !non_trait. is_empty ( ) {
2623
- let render_header = match what {
2633
+ let render_mode = match what {
2624
2634
AssocItemRender :: All => {
2625
2635
write ! ( w, "<h2 id='methods'>Methods</h2>" ) ?;
2626
- true
2636
+ RenderMode :: Normal
2627
2637
}
2628
- AssocItemRender :: DerefFor { trait_, type_ } => {
2638
+ AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
2629
2639
write ! ( w, "<h2 id='deref-methods'>Methods from \
2630
2640
{}<Target={}></h2>", trait_, type_) ?;
2631
- false
2641
+ RenderMode :: ForDeref { mut_ : deref_mut_ }
2632
2642
}
2633
2643
} ;
2634
2644
for i in & non_trait {
2635
- render_impl ( w, cx, i, AssocItemLink :: Anchor ( None ) , render_header ,
2645
+ render_impl ( w, cx, i, AssocItemLink :: Anchor ( None ) , render_mode ,
2636
2646
containing_item. stable_since ( ) ) ?;
2637
2647
}
2638
2648
}
@@ -2644,29 +2654,34 @@ fn render_assoc_items(w: &mut fmt::Formatter,
2644
2654
t. inner_impl ( ) . trait_ . def_id ( ) == c. deref_trait_did
2645
2655
} ) ;
2646
2656
if let Some ( impl_) = deref_impl {
2647
- render_deref_methods ( w, cx, impl_, containing_item) ?;
2657
+ let has_deref_mut = traits. iter ( ) . find ( |t| {
2658
+ t. inner_impl ( ) . trait_ . def_id ( ) == c. deref_mut_trait_did
2659
+ } ) . is_some ( ) ;
2660
+ render_deref_methods ( w, cx, impl_, containing_item, has_deref_mut) ?;
2648
2661
}
2649
2662
write ! ( w, "<h2 id='implementations'>Trait \
2650
2663
Implementations</h2>") ?;
2651
2664
for i in & traits {
2652
2665
let did = i. trait_did ( ) . unwrap ( ) ;
2653
2666
let assoc_link = AssocItemLink :: GotoSource ( did, & i. inner_impl ( ) . provided_trait_methods ) ;
2654
- render_impl ( w, cx, i, assoc_link, true , containing_item. stable_since ( ) ) ?;
2667
+ render_impl ( w, cx, i, assoc_link,
2668
+ RenderMode :: Normal , containing_item. stable_since ( ) ) ?;
2655
2669
}
2656
2670
}
2657
2671
Ok ( ( ) )
2658
2672
}
2659
2673
2660
2674
fn render_deref_methods ( w : & mut fmt:: Formatter , cx : & Context , impl_ : & Impl ,
2661
- container_item : & clean:: Item ) -> fmt:: Result {
2675
+ container_item : & clean:: Item , deref_mut : bool ) -> fmt:: Result {
2662
2676
let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
2663
2677
let target = impl_. inner_impl ( ) . items . iter ( ) . filter_map ( |item| {
2664
2678
match item. inner {
2665
2679
clean:: TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
2666
2680
_ => None ,
2667
2681
}
2668
2682
} ) . next ( ) . expect ( "Expected associated type binding" ) ;
2669
- let what = AssocItemRender :: DerefFor { trait_ : deref_type, type_ : target } ;
2683
+ let what = AssocItemRender :: DerefFor { trait_ : deref_type, type_ : target,
2684
+ deref_mut_ : deref_mut } ;
2670
2685
if let Some ( did) = target. def_id ( ) {
2671
2686
render_assoc_items ( w, cx, container_item, did, what)
2672
2687
} else {
@@ -2680,12 +2695,9 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
2680
2695
}
2681
2696
}
2682
2697
2683
- // Render_header is false when we are rendering a `Deref` impl and true
2684
- // otherwise. If render_header is false, we will avoid rendering static
2685
- // methods, since they are not accessible for the type implementing `Deref`
2686
2698
fn render_impl ( w : & mut fmt:: Formatter , cx : & Context , i : & Impl , link : AssocItemLink ,
2687
- render_header : bool , outer_version : Option < & str > ) -> fmt:: Result {
2688
- if render_header {
2699
+ render_mode : RenderMode , outer_version : Option < & str > ) -> fmt:: Result {
2700
+ if render_mode == RenderMode :: Normal {
2689
2701
write ! ( w, "<h3 class='impl'><span class='in-band'><code>{}</code>" , i. inner_impl( ) ) ?;
2690
2702
write ! ( w, "</span><span class='out-of-band'>" ) ?;
2691
2703
let since = i. impl_item . stability . as_ref ( ) . map ( |s| & s. since [ ..] ) ;
@@ -2706,22 +2718,43 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2706
2718
}
2707
2719
2708
2720
fn doc_impl_item ( w : & mut fmt:: Formatter , cx : & Context , item : & clean:: Item ,
2709
- link : AssocItemLink , render_static : bool ,
2721
+ link : AssocItemLink , render_mode : RenderMode ,
2710
2722
is_default_item : bool , outer_version : Option < & str > ,
2711
2723
trait_ : Option < & clean:: Trait > ) -> fmt:: Result {
2712
2724
let item_type = item_type ( item) ;
2713
2725
let name = item. name . as_ref ( ) . unwrap ( ) ;
2714
2726
2715
- let is_static = match item. inner {
2716
- clean:: MethodItem ( ref method) => !method. decl . has_self ( ) ,
2717
- clean:: TyMethodItem ( ref method) => !method. decl . has_self ( ) ,
2718
- _ => false
2727
+ let render_method_item: bool = match render_mode {
2728
+ RenderMode :: Normal => true ,
2729
+ RenderMode :: ForDeref { mut_ : deref_mut_ } => {
2730
+ let self_type_opt = match item. inner {
2731
+ clean:: MethodItem ( ref method) => method. decl . self_type ( ) ,
2732
+ clean:: TyMethodItem ( ref method) => method. decl . self_type ( ) ,
2733
+ _ => None
2734
+ } ;
2735
+
2736
+ if let Some ( self_ty) = self_type_opt {
2737
+ let by_mut_ref = match self_ty {
2738
+ SelfTy :: SelfBorrowed ( _lifetime, mutability) => {
2739
+ mutability == Mutability :: Mutable
2740
+ } ,
2741
+ SelfTy :: SelfExplicit ( clean:: BorrowedRef { mutability, .. } ) => {
2742
+ mutability == Mutability :: Mutable
2743
+ } ,
2744
+ _ => false ,
2745
+ } ;
2746
+
2747
+ deref_mut_ || !by_mut_ref
2748
+ } else {
2749
+ false
2750
+ }
2751
+ } ,
2719
2752
} ;
2720
2753
2721
2754
match item. inner {
2722
2755
clean:: MethodItem ( ..) | clean:: TyMethodItem ( ..) => {
2723
2756
// Only render when the method is not static or we allow static methods
2724
- if !is_static || render_static {
2757
+ if render_method_item {
2725
2758
let id = derive_id ( format ! ( "{}.{}" , item_type, name) ) ;
2726
2759
let ns_id = derive_id ( format ! ( "{}.{}" , name, item_type. name_space( ) ) ) ;
2727
2760
write ! ( w, "<h4 id='{}' class='{}'>" , id, item_type) ?;
@@ -2769,7 +2802,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2769
2802
_ => panic ! ( "can't make docs for trait item with name {:?}" , item. name)
2770
2803
}
2771
2804
2772
- if !is_static || render_static {
2805
+ if render_method_item || render_mode == RenderMode :: Normal {
2773
2806
if !is_default_item {
2774
2807
if let Some ( t) = trait_ {
2775
2808
// The trait item may have been stripped so we might not
@@ -2802,15 +2835,15 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2802
2835
2803
2836
write ! ( w, "<div class='impl-items'>" ) ?;
2804
2837
for trait_item in & i. inner_impl ( ) . items {
2805
- doc_impl_item ( w, cx, trait_item, link, render_header ,
2838
+ doc_impl_item ( w, cx, trait_item, link, render_mode ,
2806
2839
false , outer_version, trait_) ?;
2807
2840
}
2808
2841
2809
2842
fn render_default_items ( w : & mut fmt:: Formatter ,
2810
2843
cx : & Context ,
2811
2844
t : & clean:: Trait ,
2812
2845
i : & clean:: Impl ,
2813
- render_static : bool ,
2846
+ render_mode : RenderMode ,
2814
2847
outer_version : Option < & str > ) -> fmt:: Result {
2815
2848
for trait_item in & t. items {
2816
2849
let n = trait_item. name . clone ( ) ;
@@ -2820,7 +2853,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2820
2853
let did = i. trait_ . as_ref ( ) . unwrap ( ) . def_id ( ) . unwrap ( ) ;
2821
2854
let assoc_link = AssocItemLink :: GotoSource ( did, & i. provided_trait_methods ) ;
2822
2855
2823
- doc_impl_item ( w, cx, trait_item, assoc_link, render_static , true ,
2856
+ doc_impl_item ( w, cx, trait_item, assoc_link, render_mode , true ,
2824
2857
outer_version, None ) ?;
2825
2858
}
2826
2859
Ok ( ( ) )
@@ -2829,7 +2862,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
2829
2862
// If we've implemented a trait, then also emit documentation for all
2830
2863
// default items which weren't overridden in the implementation block.
2831
2864
if let Some ( t) = trait_ {
2832
- render_default_items ( w, cx, t, & i. inner_impl ( ) , render_header , outer_version) ?;
2865
+ render_default_items ( w, cx, t, & i. inner_impl ( ) , render_mode , outer_version) ?;
2833
2866
}
2834
2867
write ! ( w, "</div>" ) ?;
2835
2868
Ok ( ( ) )
0 commit comments