@@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
2121use rustc_hir:: PredicateOrigin ;
2222use rustc_hir_analysis:: hir_ty_to_ty;
2323use rustc_infer:: infer:: region_constraints:: { Constraint , RegionConstraintData } ;
24+ use rustc_middle:: metadata:: Reexport ;
2425use rustc_middle:: middle:: resolve_bound_vars as rbv;
2526use rustc_middle:: ty:: fold:: TypeFolder ;
2627use rustc_middle:: ty:: InternalSubsts ;
@@ -2056,141 +2057,44 @@ fn clean_bare_fn_ty<'tcx>(
20562057 BareFunctionDecl { unsafety : bare_fn. unsafety , abi : bare_fn. abi , decl, generic_params }
20572058}
20582059
2059- /// Get DefId of of an item's user-visible parent.
2060- ///
2061- /// "User-visible" should account for re-exporting and inlining, which is why this function isn't
2062- /// just `tcx.parent(def_id)`. If the provided `path` has more than one path element, the `DefId`
2063- /// of the second-to-last will be given.
2064- ///
2065- /// ```text
2066- /// use crate::foo::Bar;
2067- /// ^^^ DefId of this item will be returned
2068- /// ```
2069- ///
2070- /// If the provided path has only one item, `tcx.parent(def_id)` will be returned instead.
2071- fn get_path_parent_def_id (
2072- tcx : TyCtxt < ' _ > ,
2073- def_id : DefId ,
2074- path : & hir:: UsePath < ' _ > ,
2075- ) -> Option < DefId > {
2076- if let [ .., parent_segment, _] = & path. segments {
2077- match parent_segment. res {
2078- hir:: def:: Res :: Def ( _, parent_def_id) => Some ( parent_def_id) ,
2079- _ if parent_segment. ident . name == kw:: Crate => {
2080- // In case the "parent" is the crate, it'll give `Res::Err` so we need to
2081- // circumvent it this way.
2082- Some ( tcx. parent ( def_id) )
2083- }
2084- _ => None ,
2085- }
2086- } else {
2087- // If the path doesn't have a parent, then the parent is the current module.
2088- Some ( tcx. parent ( def_id) )
2089- }
2090- }
2091-
2092- /// This visitor is used to find an HIR Item based on its `use` path. This doesn't use the ordinary
2093- /// name resolver because it does not walk all the way through a chain of re-exports.
2094- pub ( crate ) struct OneLevelVisitor < ' hir > {
2095- map : rustc_middle:: hir:: map:: Map < ' hir > ,
2096- pub ( crate ) item : Option < & ' hir hir:: Item < ' hir > > ,
2097- looking_for : Ident ,
2060+ pub ( crate ) fn reexport_chain < ' tcx > (
2061+ tcx : TyCtxt < ' tcx > ,
2062+ import_def_id : LocalDefId ,
20982063 target_def_id : LocalDefId ,
2099- }
2100-
2101- impl < ' hir > OneLevelVisitor < ' hir > {
2102- pub ( crate ) fn new ( map : rustc_middle:: hir:: map:: Map < ' hir > , target_def_id : LocalDefId ) -> Self {
2103- Self { map, item : None , looking_for : Ident :: empty ( ) , target_def_id }
2104- }
2105-
2106- pub ( crate ) fn find_target (
2107- & mut self ,
2108- tcx : TyCtxt < ' _ > ,
2109- def_id : DefId ,
2110- path : & hir:: UsePath < ' _ > ,
2111- ) -> Option < & ' hir hir:: Item < ' hir > > {
2112- let parent_def_id = get_path_parent_def_id ( tcx, def_id, path) ?;
2113- let parent = self . map . get_if_local ( parent_def_id) ?;
2114-
2115- // We get the `Ident` we will be looking for into `item`.
2116- self . looking_for = path. segments [ path. segments . len ( ) - 1 ] . ident ;
2117- // We reset the `item`.
2118- self . item = None ;
2119-
2120- match parent {
2121- hir:: Node :: Item ( parent_item) => {
2122- hir:: intravisit:: walk_item ( self , parent_item) ;
2123- }
2124- hir:: Node :: Crate ( m) => {
2125- hir:: intravisit:: walk_mod (
2126- self ,
2127- m,
2128- tcx. local_def_id_to_hir_id ( parent_def_id. as_local ( ) . unwrap ( ) ) ,
2129- ) ;
2130- }
2131- _ => return None ,
2132- }
2133- self . item
2134- }
2135- }
2136-
2137- impl < ' hir > hir:: intravisit:: Visitor < ' hir > for OneLevelVisitor < ' hir > {
2138- type NestedFilter = rustc_middle:: hir:: nested_filter:: All ;
2139-
2140- fn nested_visit_map ( & mut self ) -> Self :: Map {
2141- self . map
2142- }
2143-
2144- fn visit_item ( & mut self , item : & ' hir hir:: Item < ' hir > ) {
2145- if self . item . is_none ( )
2146- && item. ident == self . looking_for
2147- && ( matches ! ( item. kind, hir:: ItemKind :: Use ( _, _) )
2148- || item. owner_id . def_id == self . target_def_id )
2064+ ) -> & ' tcx [ Reexport ] {
2065+ for child in tcx. module_reexports ( tcx. local_parent ( import_def_id) ) . unwrap_or_default ( ) {
2066+ if child. res . opt_def_id ( ) == Some ( target_def_id. to_def_id ( ) )
2067+ && child. reexport_chain [ 0 ] . id ( ) == Some ( import_def_id. to_def_id ( ) )
21492068 {
2150- self . item = Some ( item ) ;
2069+ return & child . reexport_chain ;
21512070 }
21522071 }
2072+ & [ ]
21532073}
21542074
2155- /// Because a `Use` item directly links to the imported item, we need to manually go through each
2156- /// import one by one. To do so, we go to the parent item and look for the `Ident` into it. Then,
2157- /// if we found the "end item" (the imported one), we stop there because we don't need its
2158- /// documentation. Otherwise, we repeat the same operation until we find the "end item".
2075+ /// Collect attributes from the whole import chain.
21592076fn get_all_import_attributes < ' hir > (
2160- mut item : & hir:: Item < ' hir > ,
21612077 cx : & mut DocContext < ' hir > ,
2078+ import_def_id : LocalDefId ,
21622079 target_def_id : LocalDefId ,
21632080 is_inline : bool ,
2164- mut prev_import : LocalDefId ,
21652081) -> Vec < ( Cow < ' hir , ast:: Attribute > , Option < DefId > ) > {
2166- let mut attributes : Vec < ( Cow < ' hir , ast :: Attribute > , Option < DefId > ) > = Vec :: new ( ) ;
2082+ let mut attrs = Vec :: new ( ) ;
21672083 let mut first = true ;
2168- let hir_map = cx. tcx . hir ( ) ;
2169- let mut visitor = OneLevelVisitor :: new ( hir_map, target_def_id) ;
2170- let mut visited = FxHashSet :: default ( ) ;
2171-
2172- // If the item is an import and has at least a path with two parts, we go into it.
2173- while let hir:: ItemKind :: Use ( path, _) = item. kind && visited. insert ( item. hir_id ( ) ) {
2174- let import_parent = cx. tcx . opt_local_parent ( prev_import) . map ( |def_id| def_id. to_def_id ( ) ) ;
2084+ for def_id in reexport_chain ( cx. tcx , import_def_id, target_def_id)
2085+ . iter ( )
2086+ . flat_map ( |reexport| reexport. id ( ) )
2087+ {
2088+ let import_attrs = inline:: load_attrs ( cx, def_id) ;
21752089 if first {
21762090 // This is the "original" reexport so we get all its attributes without filtering them.
2177- attributes = hir_map. attrs ( item. hir_id ( ) )
2178- . iter ( )
2179- . map ( |attr| ( Cow :: Borrowed ( attr) , import_parent) )
2180- . collect :: < Vec < _ > > ( ) ;
2091+ attrs = import_attrs. iter ( ) . map ( |attr| ( Cow :: Borrowed ( attr) , Some ( def_id) ) ) . collect ( ) ;
21812092 first = false ;
21822093 } else {
2183- add_without_unwanted_attributes ( & mut attributes , hir_map . attrs ( item . hir_id ( ) ) , is_inline, import_parent ) ;
2094+ add_without_unwanted_attributes ( & mut attrs , import_attrs , is_inline, Some ( def_id ) ) ;
21842095 }
2185-
2186- if let Some ( i) = visitor. find_target ( cx. tcx , item. owner_id . def_id . to_def_id ( ) , path) {
2187- item = i;
2188- } else {
2189- break ;
2190- }
2191- prev_import = item. owner_id . def_id ;
21922096 }
2193- attributes
2097+ attrs
21942098}
21952099
21962100fn filter_tokens_from_list (
@@ -2375,39 +2279,24 @@ fn clean_maybe_renamed_item<'tcx>(
23752279 _ => unreachable ! ( "not yet converted" ) ,
23762280 } ;
23772281
2378- let attrs = if let Some ( import_id) = import_id &&
2379- let Some ( hir:: Node :: Item ( use_node) ) = cx. tcx . hir ( ) . find_by_def_id ( import_id)
2380- {
2282+ let target_attrs = inline:: load_attrs ( cx, def_id) ;
2283+ let attrs = if let Some ( import_id) = import_id {
23812284 let is_inline = inline:: load_attrs ( cx, import_id. to_def_id ( ) )
23822285 . lists ( sym:: doc)
23832286 . get_word_attr ( sym:: inline)
23842287 . is_some ( ) ;
2385- // Then we get all the various imports' attributes.
2386- let mut attrs = get_all_import_attributes (
2387- use_node,
2388- cx,
2389- item. owner_id . def_id ,
2390- is_inline,
2391- import_id,
2392- ) ;
2393-
2394- add_without_unwanted_attributes (
2395- & mut attrs,
2396- inline:: load_attrs ( cx, def_id) ,
2397- is_inline,
2398- None
2399- ) ;
2288+ let mut attrs =
2289+ get_all_import_attributes ( cx, import_id, item. owner_id . def_id , is_inline) ;
2290+ add_without_unwanted_attributes ( & mut attrs, target_attrs, is_inline, None ) ;
24002291 attrs
24012292 } else {
24022293 // We only keep the item's attributes.
2403- inline :: load_attrs ( cx , def_id ) . iter ( ) . map ( |attr| ( Cow :: Borrowed ( attr) , None ) ) . collect :: < Vec < _ > > ( )
2294+ target_attrs . iter ( ) . map ( |attr| ( Cow :: Borrowed ( attr) , None ) ) . collect ( )
24042295 } ;
24052296
24062297 let cfg = attrs. cfg ( cx. tcx , & cx. cache . hidden_cfg ) ;
2407- let attrs = Attributes :: from_ast_iter ( attrs. iter ( ) . map ( |( attr, did) | match attr {
2408- Cow :: Borrowed ( attr) => ( * attr, * did) ,
2409- Cow :: Owned ( attr) => ( attr, * did)
2410- } ) , false ) ;
2298+ let attrs =
2299+ Attributes :: from_ast_iter ( attrs. iter ( ) . map ( |( attr, did) | ( & * * attr, * did) ) , false ) ;
24112300
24122301 let mut item =
24132302 Item :: from_def_id_and_attrs_and_parts ( def_id, Some ( name) , kind, Box :: new ( attrs) , cfg) ;
0 commit comments