@@ -26,6 +26,7 @@ use rustc::middle::stability;
2626use rustc_front:: hir;
2727
2828use core;
29+ use clean:: { Clean , Attributes } ;
2930use doctree:: * ;
3031
3132// looks to me like the first two of these are actually
@@ -182,15 +183,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
182183 please_inline : bool ) -> Option < hir:: ViewPath_ > {
183184 match path {
184185 hir:: ViewPathSimple ( dst, base) => {
185- if self . resolve_id ( id, Some ( dst) , false , om, please_inline) {
186+ if self . maybe_inline_local ( id, Some ( dst) , false , om, please_inline) {
186187 None
187188 } else {
188189 Some ( hir:: ViewPathSimple ( dst, base) )
189190 }
190191 }
191192 hir:: ViewPathList ( p, paths) => {
192193 let mine = paths. into_iter ( ) . filter ( |path| {
193- !self . resolve_id ( path. node . id ( ) , None , false , om,
194+ !self . maybe_inline_local ( path. node . id ( ) , None , false , om,
194195 please_inline)
195196 } ) . collect :: < hir:: HirVec < hir:: PathListItem > > ( ) ;
196197
@@ -201,9 +202,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
201202 }
202203 }
203204
204- // these are feature gated anyway
205205 hir:: ViewPathGlob ( base) => {
206- if self . resolve_id ( id, None , true , om, please_inline) {
206+ if self . maybe_inline_local ( id, None , true , om, please_inline) {
207207 None
208208 } else {
209209 Some ( hir:: ViewPathGlob ( base) )
@@ -213,8 +213,32 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
213213
214214 }
215215
216- fn resolve_id ( & mut self , id : ast:: NodeId , renamed : Option < ast:: Name > ,
216+ /// Tries to resolve the target of a `pub use` statement and inlines the
217+ /// target if it is defined locally and would not be documented otherwise,
218+ /// or when it is specifically requested with `please_inline`.
219+ /// (the latter is the case when the import is marked `doc(inline)`)
220+ ///
221+ /// Cross-crate inlining occurs later on during crate cleaning
222+ /// and follows different rules.
223+ ///
224+ /// Returns true if the target has been inlined.
225+ fn maybe_inline_local ( & mut self , id : ast:: NodeId , renamed : Option < ast:: Name > ,
217226 glob : bool , om : & mut Module , please_inline : bool ) -> bool {
227+
228+ fn inherits_doc_hidden ( cx : & core:: DocContext , mut node : ast:: NodeId ) -> bool {
229+ while let Some ( id) = cx. map . get_enclosing_scope ( node) {
230+ node = id;
231+ let attrs = cx. map . attrs ( node) . clean ( cx) ;
232+ if attrs. list_def ( "doc" ) . has_word ( "hidden" ) {
233+ return true ;
234+ }
235+ if node == ast:: CRATE_NODE_ID {
236+ break ;
237+ }
238+ }
239+ false
240+ }
241+
218242 let tcx = match self . cx . tcx_opt ( ) {
219243 Some ( tcx) => tcx,
220244 None => return false
@@ -226,9 +250,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
226250 let analysis = match self . analysis {
227251 Some ( analysis) => analysis, None => return false
228252 } ;
229- if !please_inline && analysis. access_levels . is_public ( def) {
253+
254+ let is_private = !analysis. access_levels . is_public ( def) ;
255+ let is_hidden = inherits_doc_hidden ( self . cx , def_node_id) ;
256+
257+ // Only inline if requested or if the item would otherwise be stripped
258+ if !please_inline && !is_private && !is_hidden {
230259 return false
231260 }
261+
232262 if !self . view_item_stack . insert ( def_node_id) { return false }
233263
234264 let ret = match tcx. map . get ( def_node_id) {
@@ -276,10 +306,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
276306 let node = if item. vis == hir:: Public {
277307 let please_inline = item. attrs . iter ( ) . any ( |item| {
278308 match item. meta_item_list ( ) {
279- Some ( list) => {
309+ Some ( list) if & item . name ( ) [ .. ] == "doc" => {
280310 list. iter ( ) . any ( |i| & i. name ( ) [ ..] == "inline" )
281311 }
282- None => false ,
312+ _ => false ,
283313 }
284314 } ) ;
285315 match self . visit_view_path ( node, om, item. id , please_inline) {
0 commit comments