@@ -64,7 +64,7 @@ use rustc::hir;
6464use rustc:: util:: nodemap:: { FnvHashMap , FnvHashSet } ;
6565use rustc_data_structures:: flock;
6666
67- use clean:: { self , Attributes , GetDefId } ;
67+ use clean:: { self , Attributes , GetDefId , SelfTy , Mutability } ;
6868use doctree;
6969use fold:: DocFolder ;
7070use html:: escape:: Escape ;
@@ -266,6 +266,7 @@ pub struct Cache {
266266 seen_mod : bool ,
267267 stripped_mod : bool ,
268268 deref_trait_did : Option < DefId > ,
269+ deref_mut_trait_did : Option < DefId > ,
269270
270271 // In rare case where a structure is defined in one module but implemented
271272 // in another, if the implementing module is parsed before defining module,
@@ -283,6 +284,7 @@ pub struct RenderInfo {
283284 pub external_paths : :: core:: ExternalPaths ,
284285 pub external_typarams : FnvHashMap < DefId , String > ,
285286 pub deref_trait_did : Option < DefId > ,
287+ pub deref_mut_trait_did : Option < DefId > ,
286288}
287289
288290/// Helper struct to render all source code to HTML pages
@@ -508,6 +510,7 @@ pub fn run(mut krate: clean::Crate,
508510 external_paths,
509511 external_typarams,
510512 deref_trait_did,
513+ deref_mut_trait_did,
511514 } = renderinfo;
512515
513516 let external_paths = external_paths. into_iter ( )
@@ -532,6 +535,7 @@ pub fn run(mut krate: clean::Crate,
532535 orphan_methods : Vec :: new ( ) ,
533536 traits : mem:: replace ( & mut krate. external_traits , FnvHashMap ( ) ) ,
534537 deref_trait_did : deref_trait_did,
538+ deref_mut_trait_did : deref_mut_trait_did,
535539 typarams : external_typarams,
536540 } ;
537541
@@ -2604,7 +2608,13 @@ impl<'a> AssocItemLink<'a> {
26042608
26052609enum AssocItemRender < ' a > {
26062610 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 } ,
26082618}
26092619
26102620fn render_assoc_items ( w : & mut fmt:: Formatter ,
@@ -2621,19 +2631,19 @@ fn render_assoc_items(w: &mut fmt::Formatter,
26212631 i. inner_impl ( ) . trait_ . is_none ( )
26222632 } ) ;
26232633 if !non_trait. is_empty ( ) {
2624- let render_header = match what {
2634+ let render_mode = match what {
26252635 AssocItemRender :: All => {
26262636 write ! ( w, "<h2 id='methods'>Methods</h2>" ) ?;
2627- true
2637+ RenderMode :: Normal
26282638 }
2629- AssocItemRender :: DerefFor { trait_, type_ } => {
2639+ AssocItemRender :: DerefFor { trait_, type_, deref_mut_ } => {
26302640 write ! ( w, "<h2 id='deref-methods'>Methods from \
26312641 {}<Target={}></h2>", trait_, type_) ?;
2632- false
2642+ RenderMode :: ForDeref { mut_ : deref_mut_ }
26332643 }
26342644 } ;
26352645 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 ,
26372647 containing_item. stable_since ( ) ) ?;
26382648 }
26392649 }
@@ -2645,29 +2655,34 @@ fn render_assoc_items(w: &mut fmt::Formatter,
26452655 t. inner_impl ( ) . trait_ . def_id ( ) == c. deref_trait_did
26462656 } ) ;
26472657 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) ?;
26492662 }
26502663 write ! ( w, "<h2 id='implementations'>Trait \
26512664 Implementations</h2>") ?;
26522665 for i in & traits {
26532666 let did = i. trait_did ( ) . unwrap ( ) ;
26542667 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 ( ) ) ?;
26562670 }
26572671 }
26582672 Ok ( ( ) )
26592673}
26602674
26612675fn 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 {
26632677 let deref_type = impl_. inner_impl ( ) . trait_ . as_ref ( ) . unwrap ( ) ;
26642678 let target = impl_. inner_impl ( ) . items . iter ( ) . filter_map ( |item| {
26652679 match item. inner {
26662680 clean:: TypedefItem ( ref t, true ) => Some ( & t. type_ ) ,
26672681 _ => None ,
26682682 }
26692683 } ) . 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 } ;
26712686 if let Some ( did) = target. def_id ( ) {
26722687 render_assoc_items ( w, cx, container_item, did, what)
26732688 } else {
@@ -2681,12 +2696,9 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
26812696 }
26822697}
26832698
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`
26872699fn 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 {
26902702 write ! ( w, "<h3 class='impl'><span class='in-band'><code>{}</code>" , i. inner_impl( ) ) ?;
26912703 write ! ( w, "</span><span class='out-of-band'>" ) ?;
26922704 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
27072719 }
27082720
27092721 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 ,
27112723 is_default_item : bool , outer_version : Option < & str > ,
27122724 trait_ : Option < & clean:: Trait > ) -> fmt:: Result {
27132725 let item_type = item_type ( item) ;
27142726 let name = item. name . as_ref ( ) . unwrap ( ) ;
27152727
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+ } ,
27202753 } ;
27212754
27222755 match item. inner {
27232756 clean:: MethodItem ( ..) | clean:: TyMethodItem ( ..) => {
27242757 // Only render when the method is not static or we allow static methods
2725- if !is_static || render_static {
2758+ if render_method_item {
27262759 let id = derive_id ( format ! ( "{}.{}" , item_type, name) ) ;
27272760 let ns_id = derive_id ( format ! ( "{}.{}" , name, item_type. name_space( ) ) ) ;
27282761 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
27702803 _ => panic ! ( "can't make docs for trait item with name {:?}" , item. name)
27712804 }
27722805
2773- if !is_static || render_static {
2806+ if render_method_item || render_mode == RenderMode :: Normal {
27742807 if !is_default_item {
27752808 if let Some ( t) = trait_ {
27762809 // 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
28032836
28042837 write ! ( w, "<div class='impl-items'>" ) ?;
28052838 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 ,
28072840 false , outer_version, trait_) ?;
28082841 }
28092842
28102843 fn render_default_items ( w : & mut fmt:: Formatter ,
28112844 cx : & Context ,
28122845 t : & clean:: Trait ,
28132846 i : & clean:: Impl ,
2814- render_static : bool ,
2847+ render_mode : RenderMode ,
28152848 outer_version : Option < & str > ) -> fmt:: Result {
28162849 for trait_item in & t. items {
28172850 let n = trait_item. name . clone ( ) ;
@@ -2821,7 +2854,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
28212854 let did = i. trait_ . as_ref ( ) . unwrap ( ) . def_id ( ) . unwrap ( ) ;
28222855 let assoc_link = AssocItemLink :: GotoSource ( did, & i. provided_trait_methods ) ;
28232856
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 ,
28252858 outer_version, None ) ?;
28262859 }
28272860 Ok ( ( ) )
@@ -2830,7 +2863,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
28302863 // If we've implemented a trait, then also emit documentation for all
28312864 // default items which weren't overridden in the implementation block.
28322865 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) ?;
28342867 }
28352868 write ! ( w, "</div>" ) ?;
28362869 Ok ( ( ) )
0 commit comments