@@ -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