-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Description
Rustdoc currently creates a copy of the resolver to use for intra-doc links:
Lines 350 to 354 in d474075
crate fn create_resolver<'a>( | |
externs: config::Externs, | |
queries: &Queries<'a>, | |
sess: &Session, | |
) -> Rc<RefCell<interface::BoxedResolver>> { |
This is a Terrible, Horrible, No Good, Very Bad Idea. In particular, it causes rustdoc's copy of the resolver and the TyCtxt to disagree about what crates exist:
- ICE when documenting code with intra-doc-links with types with the same name but different crates #66159 (comment)
- Fix intra-doc links for cross-crate re-exports of default trait methods #75176
- Fix impl being removed excessively #82496 (comment)
It's also distorting rustc_resolve, since not all of the outputs make sense to clone in the first place: #65625 (comment)
We should refactor rustdoc somehow to allow getting rid of Resolver::clone_outputs
. @petrochenkov suggests moving anything that needs to touch the resolver before HIR lowering: #68427 (comment).
@petrochenkov what do you think about @eddyb's comment in #65625 (comment) ?
Why would cloning be needed? Is this that support for resolving things after rustc_resolve finishes?
In that case I'm not sure why we need to clone the outputs - is it to be able to keep the original resolver around?
Would it be possible for lower_to_hir
to stop stealing the resolver?
rust/compiler/rustc_interface/src/queries.rs
Line 227 in d474075
let resolver = peeked.1.steal(); |
Then rustdoc wouldn't need to clone it in the first place, it could just call queries.expansion().peek().1
whenever it needs access to the resolver.
See #68427 for previous discussion.
Implementation History
- Initial "early crate loader": rustdoc: Don't load all extern crates unconditionally #83738
- Don't require
clean::Item
s before resolving intra-doc links: rustdoc: Store intra-doc links in Cache instead of on items directly #83833 - Separate type-relative resolution from path resolution (at least somewhat): rustdoc: Cleanup handling of associated items for intra-doc links #83849
- Move early loader into
collect_intra_doc_links
: rustdoc: Move crate loader to collect_intra_doc_links::early #84101 - Move all path resolution from late to early module and add new field on DocContext for partially resolved links
- Change
preprocess_link
to also take into account the hacks forSelf::
andcrate
:// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly rust/src/librustdoc/passes/collect_intra_doc_links.rs
Lines 1124 to 1153 in ef52471
let resolved_self; // replace `Self` with suitable item's parent name let is_lone_self = path_str == "Self"; let is_lone_crate = path_str == "crate"; if path_str.starts_with("Self::") || is_lone_self { if let Some(ref name) = self_name { if is_lone_self { path_str = name; } else { resolved_self = format!("{}::{}", name, &path_str[6..]); path_str = &resolved_self; } } } else if path_str.starts_with("crate::") || is_lone_crate { use rustc_span::def_id::CRATE_DEF_INDEX; // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented. // But rustdoc wants it to mean the crate this item was originally present in. // To work around this, remove it and resolve relative to the crate root instead. // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root. // FIXME(#78696): This doesn't always work. if is_lone_crate { path_str = "self"; } else { resolved_self = format!("self::{}", &path_str["crate::".len()..]); path_str = &resolved_self; } module_id = DefId { krate, index: CRATE_DEF_INDEX }; }
- Change