@@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
21
21
use rustc_hir:: PredicateOrigin ;
22
22
use rustc_hir_analysis:: hir_ty_to_ty;
23
23
use rustc_infer:: infer:: region_constraints:: { Constraint , RegionConstraintData } ;
24
+ use rustc_middle:: metadata:: Reexport ;
24
25
use rustc_middle:: middle:: resolve_bound_vars as rbv;
25
26
use rustc_middle:: ty:: fold:: TypeFolder ;
26
27
use rustc_middle:: ty:: InternalSubsts ;
@@ -2056,141 +2057,44 @@ fn clean_bare_fn_ty<'tcx>(
2056
2057
BareFunctionDecl { unsafety : bare_fn. unsafety , abi : bare_fn. abi , decl, generic_params }
2057
2058
}
2058
2059
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 ,
2098
2063
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 ( ) )
2149
2068
{
2150
- self . item = Some ( item ) ;
2069
+ return & child . reexport_chain ;
2151
2070
}
2152
2071
}
2072
+ & [ ]
2153
2073
}
2154
2074
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.
2159
2076
fn get_all_import_attributes < ' hir > (
2160
- mut item : & hir:: Item < ' hir > ,
2161
2077
cx : & mut DocContext < ' hir > ,
2078
+ import_def_id : LocalDefId ,
2162
2079
target_def_id : LocalDefId ,
2163
2080
is_inline : bool ,
2164
- mut prev_import : LocalDefId ,
2165
2081
) -> 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 ( ) ;
2167
2083
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) ;
2175
2089
if first {
2176
2090
// 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 ( ) ;
2181
2092
first = false ;
2182
2093
} 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 ) ) ;
2184
2095
}
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 ;
2192
2096
}
2193
- attributes
2097
+ attrs
2194
2098
}
2195
2099
2196
2100
fn filter_tokens_from_list (
@@ -2375,39 +2279,24 @@ fn clean_maybe_renamed_item<'tcx>(
2375
2279
_ => unreachable ! ( "not yet converted" ) ,
2376
2280
} ;
2377
2281
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 {
2381
2284
let is_inline = inline:: load_attrs ( cx, import_id. to_def_id ( ) )
2382
2285
. lists ( sym:: doc)
2383
2286
. get_word_attr ( sym:: inline)
2384
2287
. 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 ) ;
2400
2291
attrs
2401
2292
} else {
2402
2293
// 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 ( )
2404
2295
} ;
2405
2296
2406
2297
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 ) ;
2411
2300
2412
2301
let mut item =
2413
2302
Item :: from_def_id_and_attrs_and_parts ( def_id, Some ( name) , kind, Box :: new ( attrs) , cfg) ;
0 commit comments