@@ -2065,23 +2065,81 @@ fn clean_bare_fn_ty<'tcx>(
2065
2065
BareFunctionDecl { unsafety : bare_fn. unsafety , abi : bare_fn. abi , decl, generic_params }
2066
2066
}
2067
2067
2068
- /// This visitor is used to go through only the "top level" of a item and not enter any sub
2069
- /// item while looking for a given `Ident` which is stored into `item` if found.
2070
- struct OneLevelVisitor < ' hir > {
2068
+ /// Get DefId of of an item's user-visible parent.
2069
+ ///
2070
+ /// "User-visible" should account for re-exporting and inlining, which is why this function isn't
2071
+ /// just `tcx.parent(def_id)`. If the provided `path` has more than one path element, the `DefId`
2072
+ /// of the second-to-last will be given.
2073
+ ///
2074
+ /// ```text
2075
+ /// use crate::foo::Bar;
2076
+ /// ^^^ DefId of this item will be returned
2077
+ /// ```
2078
+ ///
2079
+ /// If the provided path has only one item, `tcx.parent(def_id)` will be returned instead.
2080
+ fn get_path_parent_def_id (
2081
+ tcx : TyCtxt < ' _ > ,
2082
+ def_id : DefId ,
2083
+ path : & hir:: UsePath < ' _ > ,
2084
+ ) -> Option < DefId > {
2085
+ if let [ .., parent_segment, _] = & path. segments {
2086
+ match parent_segment. res {
2087
+ hir:: def:: Res :: Def ( _, parent_def_id) => Some ( parent_def_id) ,
2088
+ _ if parent_segment. ident . name == kw:: Crate => {
2089
+ // In case the "parent" is the crate, it'll give `Res::Err` so we need to
2090
+ // circumvent it this way.
2091
+ Some ( tcx. parent ( def_id) )
2092
+ }
2093
+ _ => None ,
2094
+ }
2095
+ } else {
2096
+ // If the path doesn't have a parent, then the parent is the current module.
2097
+ Some ( tcx. parent ( def_id) )
2098
+ }
2099
+ }
2100
+
2101
+ /// This visitor is used to find an HIR Item based on its `use` path. This doesn't use the ordinary
2102
+ /// name resolver because it does not walk all the way through a chain of re-exports.
2103
+ pub ( crate ) struct OneLevelVisitor < ' hir > {
2071
2104
map : rustc_middle:: hir:: map:: Map < ' hir > ,
2072
- item : Option < & ' hir hir:: Item < ' hir > > ,
2105
+ pub ( crate ) item : Option < & ' hir hir:: Item < ' hir > > ,
2073
2106
looking_for : Ident ,
2074
2107
target_def_id : LocalDefId ,
2075
2108
}
2076
2109
2077
2110
impl < ' hir > OneLevelVisitor < ' hir > {
2078
- fn new ( map : rustc_middle:: hir:: map:: Map < ' hir > , target_def_id : LocalDefId ) -> Self {
2111
+ pub ( crate ) fn new ( map : rustc_middle:: hir:: map:: Map < ' hir > , target_def_id : LocalDefId ) -> Self {
2079
2112
Self { map, item : None , looking_for : Ident :: empty ( ) , target_def_id }
2080
2113
}
2081
2114
2082
- fn reset ( & mut self , looking_for : Ident ) {
2083
- self . looking_for = looking_for;
2115
+ pub ( crate ) fn find_target (
2116
+ & mut self ,
2117
+ tcx : TyCtxt < ' _ > ,
2118
+ def_id : DefId ,
2119
+ path : & hir:: UsePath < ' _ > ,
2120
+ ) -> Option < & ' hir hir:: Item < ' hir > > {
2121
+ let parent_def_id = get_path_parent_def_id ( tcx, def_id, path) ?;
2122
+ let parent = self . map . get_if_local ( parent_def_id) ?;
2123
+
2124
+ // We get the `Ident` we will be looking for into `item`.
2125
+ self . looking_for = path. segments [ path. segments . len ( ) - 1 ] . ident ;
2126
+ // We reset the `item`.
2084
2127
self . item = None ;
2128
+
2129
+ match parent {
2130
+ hir:: Node :: Item ( parent_item) => {
2131
+ hir:: intravisit:: walk_item ( self , parent_item) ;
2132
+ }
2133
+ hir:: Node :: Crate ( m) => {
2134
+ hir:: intravisit:: walk_mod (
2135
+ self ,
2136
+ m,
2137
+ tcx. local_def_id_to_hir_id ( parent_def_id. as_local ( ) . unwrap ( ) ) ,
2138
+ ) ;
2139
+ }
2140
+ _ => return None ,
2141
+ }
2142
+ self . item
2085
2143
}
2086
2144
}
2087
2145
@@ -2129,41 +2187,7 @@ fn get_all_import_attributes<'hir>(
2129
2187
add_without_unwanted_attributes ( attributes, hir_map. attrs ( item. hir_id ( ) ) , is_inline) ;
2130
2188
}
2131
2189
2132
- let def_id = if let [ .., parent_segment, _] = & path. segments {
2133
- match parent_segment. res {
2134
- hir:: def:: Res :: Def ( _, def_id) => def_id,
2135
- _ if parent_segment. ident . name == kw:: Crate => {
2136
- // In case the "parent" is the crate, it'll give `Res::Err` so we need to
2137
- // circumvent it this way.
2138
- tcx. parent ( item. owner_id . def_id . to_def_id ( ) )
2139
- }
2140
- _ => break ,
2141
- }
2142
- } else {
2143
- // If the path doesn't have a parent, then the parent is the current module.
2144
- tcx. parent ( item. owner_id . def_id . to_def_id ( ) )
2145
- } ;
2146
-
2147
- let Some ( parent) = hir_map. get_if_local ( def_id) else { break } ;
2148
-
2149
- // We get the `Ident` we will be looking for into `item`.
2150
- let looking_for = path. segments [ path. segments . len ( ) - 1 ] . ident ;
2151
- visitor. reset ( looking_for) ;
2152
-
2153
- match parent {
2154
- hir:: Node :: Item ( parent_item) => {
2155
- hir:: intravisit:: walk_item ( & mut visitor, parent_item) ;
2156
- }
2157
- hir:: Node :: Crate ( m) => {
2158
- hir:: intravisit:: walk_mod (
2159
- & mut visitor,
2160
- m,
2161
- tcx. local_def_id_to_hir_id ( def_id. as_local ( ) . unwrap ( ) ) ,
2162
- ) ;
2163
- }
2164
- _ => break ,
2165
- }
2166
- if let Some ( i) = visitor. item {
2190
+ if let Some ( i) = visitor. find_target ( tcx, item. owner_id . def_id . to_def_id ( ) , path) {
2167
2191
item = i;
2168
2192
} else {
2169
2193
break ;
0 commit comments