2020-06-24 08:16:21 -05:00
|
|
|
use std::mem;
|
|
|
|
|
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
|
|
|
|
use rustc_middle::middle::privacy::AccessLevels;
|
2021-01-28 16:07:24 +01:00
|
|
|
use rustc_middle::ty::TyCtxt;
|
2021-01-28 17:05:22 +01:00
|
|
|
use rustc_span::symbol::sym;
|
2020-06-24 08:16:21 -05:00
|
|
|
|
2021-07-10 22:25:36 -04:00
|
|
|
use crate::clean::{self, GetDefId, ItemId, PrimitiveType};
|
Give precedence to `html_root_url` over `--extern-html-root-url` by default, but add a way to opt-in to the previous behavior
## What is an HTML root url?
It tells rustdoc where it should link when documentation for a crate is
not available locally; for example, when a crate is a dependency of a
crate documented with `cargo doc --no-deps`.
## What is the difference between `html_root_url` and `--extern-html-root-url`?
Both of these tell rustdoc what the HTML root should be set to.
`doc(html_root_url)` is set by the crate author, while
`--extern-html-root-url` is set by the person documenting the crate.
These are often different. For example, docs.rs uses
`--extern-html-root-url https://docs.rs/crate-name/version` to ensure
all crates have documentation, even if `html_root_url` is not set.
Conversely, crates such as Rocket set `doc(html_root_url =
"https://api.rocket.rs")`, because they prefer users to view the
documentation on their own site.
Crates also set `html_root_url` to ensure they have
documentation when building locally when offline. This is unfortunate to
require, because it's more work from the library author. It also makes
it impossible to distinguish between crates that want to be viewed on a
different site (e.g. Rocket) and crates that just want documentation to
be visible offline at all (e.g. Tokio). I have authored a separate
change to the API guidelines to no longer recommend doing this:
https://github.com/rust-lang/api-guidelines/pull/230.
## Why change the default?
In the past, docs.rs has been the main user of `--extern-html-root-url`.
However, it's useful for other projects as well. In particular, Cargo
wants to pass it by default when running `--no-deps`
(https://github.com/rust-lang/cargo/issues/8296).
Unfortunately, for these other use cases, the priority order is
inverted. They want to give *precedence* to the URL the crate picks, and
only fall back to the `--extern-html-root` if no `html_root_url` is
present. That allows passing `--extern-html-root` unconditionally,
without having to parse the source code to see what attributes are
present.
For docs.rs, however, we still want to keep the old behavior, so that
all links on docs.rs stay on the site.
2021-03-04 15:03:22 -05:00
|
|
|
use crate::config::RenderOptions;
|
2020-06-24 08:16:21 -05:00
|
|
|
use crate::fold::DocFolder;
|
|
|
|
use crate::formats::item_type::ItemType;
|
|
|
|
use crate::formats::Impl;
|
2020-10-04 20:42:34 -07:00
|
|
|
use crate::html::markdown::short_markdown_summary;
|
2021-04-26 21:08:14 +02:00
|
|
|
use crate::html::render::cache::{get_index_search_type, ExternalLocation};
|
2020-06-24 08:16:21 -05:00
|
|
|
use crate::html::render::IndexItem;
|
|
|
|
|
2020-10-04 20:42:34 -07:00
|
|
|
/// This cache is used to store information about the [`clean::Crate`] being
|
2020-06-24 08:16:21 -05:00
|
|
|
/// rendered in order to provide more useful documentation. This contains
|
|
|
|
/// information like all implementors of a trait, all traits a type implements,
|
|
|
|
/// documentation for all known traits, etc.
|
|
|
|
///
|
|
|
|
/// This structure purposefully does not implement `Clone` because it's intended
|
|
|
|
/// to be a fairly large and expensive structure to clone. Instead this adheres
|
2021-08-22 16:20:58 +02:00
|
|
|
/// to `Send` so it may be stored in an `Arc` instance and shared among the various
|
2020-06-24 08:16:21 -05:00
|
|
|
/// rendering threads.
|
|
|
|
#[derive(Default)]
|
2020-11-14 17:59:58 -05:00
|
|
|
crate struct Cache {
|
2020-06-24 08:16:21 -05:00
|
|
|
/// Maps a type ID to all known implementations for that type. This is only
|
|
|
|
/// recognized for intra-crate `ResolvedPath` types, and is used to print
|
|
|
|
/// out extra documentation on the page of an enum/struct.
|
|
|
|
///
|
|
|
|
/// The values of the map are a list of implementations and documentation
|
|
|
|
/// found on that implementation.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate impls: FxHashMap<DefId, Vec<Impl>>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Maintains a mapping of local crate `DefId`s to the fully qualified name
|
|
|
|
/// and "short type description" of that node. This is used when generating
|
|
|
|
/// URLs when a type is being linked to. External paths are not located in
|
|
|
|
/// this map because the `External` type itself has all the information
|
|
|
|
/// necessary.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Similar to `paths`, but only holds external paths. This is only used for
|
|
|
|
/// generating explicit hyperlinks to other crates.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate external_paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Maps local `DefId`s of exported types to fully qualified paths.
|
|
|
|
/// Unlike 'paths', this mapping ignores any renames that occur
|
|
|
|
/// due to 'use' statements.
|
|
|
|
///
|
|
|
|
/// This map is used when writing out the special 'implementors'
|
|
|
|
/// javascript file. By using the exact path that the type
|
|
|
|
/// is declared with, we ensure that each path will be identical
|
|
|
|
/// to the path used if the corresponding type is inlined. By
|
|
|
|
/// doing this, we can detect duplicate impls on a trait page, and only display
|
|
|
|
/// the impl for the inlined type.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate exact_paths: FxHashMap<DefId, Vec<String>>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// This map contains information about all known traits of this crate.
|
|
|
|
/// Implementations of a crate should inherit the documentation of the
|
|
|
|
/// parent trait if no extra documentation is specified, and default methods
|
|
|
|
/// should show up in documentation about trait implementations.
|
2021-02-12 14:33:32 +01:00
|
|
|
crate traits: FxHashMap<DefId, clean::TraitWithExtraInfo>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// When rendering traits, it's often useful to be able to list all
|
|
|
|
/// implementors of the trait, and this mapping is exactly, that: a mapping
|
|
|
|
/// of trait ids to the list of known implementors of the trait
|
2021-05-08 10:04:03 +02:00
|
|
|
crate implementors: FxHashMap<DefId, Vec<Impl>>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Cache of where external crate documentation can be found.
|
2021-04-29 19:14:29 +02:00
|
|
|
crate extern_locations: FxHashMap<CrateNum, ExternalLocation>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Cache of where documentation for primitives can be found.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
// Note that external items for which `doc(hidden)` applies to are shown as
|
|
|
|
// non-reachable while local items aren't. This is because we're reusing
|
|
|
|
// the access levels from the privacy check pass.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate access_levels: AccessLevels<DefId>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// The version of the crate being documented, if given from the `--crate-version` flag.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate crate_version: Option<String>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
/// Whether to document private items.
|
|
|
|
/// This is stored in `Cache` so it doesn't need to be passed through all rustdoc functions.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate document_private: bool,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
2021-03-09 19:55:35 -08:00
|
|
|
/// Crates marked with [`#[doc(masked)]`][doc_masked].
|
|
|
|
///
|
|
|
|
/// [doc_masked]: https://doc.rust-lang.org/nightly/unstable-book/language-features/doc-masked.html
|
|
|
|
crate masked_crates: FxHashSet<CrateNum>,
|
|
|
|
|
2020-06-24 08:16:21 -05:00
|
|
|
// Private fields only used when initially crawling a crate to build a cache
|
|
|
|
stack: Vec<String>,
|
|
|
|
parent_stack: Vec<DefId>,
|
|
|
|
parent_is_trait_impl: bool,
|
|
|
|
stripped_mod: bool,
|
|
|
|
|
2020-11-14 17:59:58 -05:00
|
|
|
crate search_index: Vec<IndexItem>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
// In rare case where a structure is defined in one module but implemented
|
|
|
|
// in another, if the implementing module is parsed before defining module,
|
|
|
|
// then the fully qualified name of the structure isn't presented in `paths`
|
|
|
|
// yet when its implementation methods are being indexed. Caches such methods
|
|
|
|
// and their parent id here and indexes them at the end of crate parsing.
|
2020-11-14 17:59:58 -05:00
|
|
|
crate orphan_impl_items: Vec<(DefId, clean::Item)>,
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
// Similarly to `orphan_impl_items`, sometimes trait impls are picked up
|
|
|
|
// even though the trait itself is not exported. This can happen if a trait
|
|
|
|
// was defined in function/expression scope, since the impl will be picked
|
|
|
|
// up by `collect-trait-impls` but the trait won't be scraped out in the HIR
|
2021-04-01 13:26:29 -07:00
|
|
|
// crawl. In order to prevent crashes when looking for notable traits or
|
2020-06-24 08:16:21 -05:00
|
|
|
// when gathering trait documentation on a type, hold impls here while
|
|
|
|
// folding and add them to the cache later on if we find the trait.
|
|
|
|
orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
|
2021-04-03 22:15:24 -04:00
|
|
|
|
|
|
|
/// All intra-doc links resolved so far.
|
|
|
|
///
|
|
|
|
/// Links are indexed by the DefId of the item they document.
|
2021-07-03 17:21:39 +02:00
|
|
|
crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
2021-01-28 16:07:24 +01:00
|
|
|
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
|
|
|
|
struct CacheBuilder<'a, 'tcx> {
|
|
|
|
cache: &'a mut Cache,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
}
|
|
|
|
|
2020-06-24 08:16:21 -05:00
|
|
|
impl Cache {
|
2021-02-12 00:03:24 -05:00
|
|
|
crate fn new(access_levels: AccessLevels<DefId>, document_private: bool) -> Self {
|
|
|
|
Cache { access_levels, document_private, ..Cache::default() }
|
2021-02-11 21:29:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
|
|
|
|
/// in `krate` due to the data being moved into the `Cache`.
|
|
|
|
crate fn populate(
|
|
|
|
&mut self,
|
|
|
|
mut krate: clean::Crate,
|
|
|
|
tcx: TyCtxt<'_>,
|
Give precedence to `html_root_url` over `--extern-html-root-url` by default, but add a way to opt-in to the previous behavior
## What is an HTML root url?
It tells rustdoc where it should link when documentation for a crate is
not available locally; for example, when a crate is a dependency of a
crate documented with `cargo doc --no-deps`.
## What is the difference between `html_root_url` and `--extern-html-root-url`?
Both of these tell rustdoc what the HTML root should be set to.
`doc(html_root_url)` is set by the crate author, while
`--extern-html-root-url` is set by the person documenting the crate.
These are often different. For example, docs.rs uses
`--extern-html-root-url https://docs.rs/crate-name/version` to ensure
all crates have documentation, even if `html_root_url` is not set.
Conversely, crates such as Rocket set `doc(html_root_url =
"https://api.rocket.rs")`, because they prefer users to view the
documentation on their own site.
Crates also set `html_root_url` to ensure they have
documentation when building locally when offline. This is unfortunate to
require, because it's more work from the library author. It also makes
it impossible to distinguish between crates that want to be viewed on a
different site (e.g. Rocket) and crates that just want documentation to
be visible offline at all (e.g. Tokio). I have authored a separate
change to the API guidelines to no longer recommend doing this:
https://github.com/rust-lang/api-guidelines/pull/230.
## Why change the default?
In the past, docs.rs has been the main user of `--extern-html-root-url`.
However, it's useful for other projects as well. In particular, Cargo
wants to pass it by default when running `--no-deps`
(https://github.com/rust-lang/cargo/issues/8296).
Unfortunately, for these other use cases, the priority order is
inverted. They want to give *precedence* to the URL the crate picks, and
only fall back to the `--extern-html-root` if no `html_root_url` is
present. That allows passing `--extern-html-root` unconditionally,
without having to parse the source code to see what attributes are
present.
For docs.rs, however, we still want to keep the old behavior, so that
all links on docs.rs stay on the site.
2021-03-04 15:03:22 -05:00
|
|
|
render_options: &RenderOptions,
|
2021-02-11 21:29:22 -05:00
|
|
|
) -> clean::Crate {
|
2021-02-12 00:03:24 -05:00
|
|
|
// Crawl the crate to build various caches used for the output
|
2021-02-11 21:29:22 -05:00
|
|
|
debug!(?self.crate_version);
|
|
|
|
self.traits = krate.external_traits.take();
|
Give precedence to `html_root_url` over `--extern-html-root-url` by default, but add a way to opt-in to the previous behavior
## What is an HTML root url?
It tells rustdoc where it should link when documentation for a crate is
not available locally; for example, when a crate is a dependency of a
crate documented with `cargo doc --no-deps`.
## What is the difference between `html_root_url` and `--extern-html-root-url`?
Both of these tell rustdoc what the HTML root should be set to.
`doc(html_root_url)` is set by the crate author, while
`--extern-html-root-url` is set by the person documenting the crate.
These are often different. For example, docs.rs uses
`--extern-html-root-url https://docs.rs/crate-name/version` to ensure
all crates have documentation, even if `html_root_url` is not set.
Conversely, crates such as Rocket set `doc(html_root_url =
"https://api.rocket.rs")`, because they prefer users to view the
documentation on their own site.
Crates also set `html_root_url` to ensure they have
documentation when building locally when offline. This is unfortunate to
require, because it's more work from the library author. It also makes
it impossible to distinguish between crates that want to be viewed on a
different site (e.g. Rocket) and crates that just want documentation to
be visible offline at all (e.g. Tokio). I have authored a separate
change to the API guidelines to no longer recommend doing this:
https://github.com/rust-lang/api-guidelines/pull/230.
## Why change the default?
In the past, docs.rs has been the main user of `--extern-html-root-url`.
However, it's useful for other projects as well. In particular, Cargo
wants to pass it by default when running `--no-deps`
(https://github.com/rust-lang/cargo/issues/8296).
Unfortunately, for these other use cases, the priority order is
inverted. They want to give *precedence* to the URL the crate picks, and
only fall back to the `--extern-html-root` if no `html_root_url` is
present. That allows passing `--extern-html-root` unconditionally,
without having to parse the source code to see what attributes are
present.
For docs.rs, however, we still want to keep the old behavior, so that
all links on docs.rs stay on the site.
2021-03-04 15:03:22 -05:00
|
|
|
let RenderOptions { extern_html_root_takes_precedence, output: dst, .. } = render_options;
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
// Cache where all our extern crates are located
|
2020-06-26 09:14:45 -05:00
|
|
|
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
|
2021-07-05 12:35:02 -04:00
|
|
|
for &e in &krate.externs {
|
2021-04-22 19:02:09 -04:00
|
|
|
let name = e.name(tcx);
|
Give precedence to `html_root_url` over `--extern-html-root-url` by default, but add a way to opt-in to the previous behavior
## What is an HTML root url?
It tells rustdoc where it should link when documentation for a crate is
not available locally; for example, when a crate is a dependency of a
crate documented with `cargo doc --no-deps`.
## What is the difference between `html_root_url` and `--extern-html-root-url`?
Both of these tell rustdoc what the HTML root should be set to.
`doc(html_root_url)` is set by the crate author, while
`--extern-html-root-url` is set by the person documenting the crate.
These are often different. For example, docs.rs uses
`--extern-html-root-url https://docs.rs/crate-name/version` to ensure
all crates have documentation, even if `html_root_url` is not set.
Conversely, crates such as Rocket set `doc(html_root_url =
"https://api.rocket.rs")`, because they prefer users to view the
documentation on their own site.
Crates also set `html_root_url` to ensure they have
documentation when building locally when offline. This is unfortunate to
require, because it's more work from the library author. It also makes
it impossible to distinguish between crates that want to be viewed on a
different site (e.g. Rocket) and crates that just want documentation to
be visible offline at all (e.g. Tokio). I have authored a separate
change to the API guidelines to no longer recommend doing this:
https://github.com/rust-lang/api-guidelines/pull/230.
## Why change the default?
In the past, docs.rs has been the main user of `--extern-html-root-url`.
However, it's useful for other projects as well. In particular, Cargo
wants to pass it by default when running `--no-deps`
(https://github.com/rust-lang/cargo/issues/8296).
Unfortunately, for these other use cases, the priority order is
inverted. They want to give *precedence* to the URL the crate picks, and
only fall back to the `--extern-html-root` if no `html_root_url` is
present. That allows passing `--extern-html-root` unconditionally,
without having to parse the source code to see what attributes are
present.
For docs.rs, however, we still want to keep the old behavior, so that
all links on docs.rs stay on the site.
2021-03-04 15:03:22 -05:00
|
|
|
let extern_url =
|
|
|
|
render_options.extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
|
|
|
|
let location = e.location(extern_url, *extern_html_root_takes_precedence, dst, tcx);
|
|
|
|
self.extern_locations.insert(e.crate_num, location);
|
2021-07-05 12:35:02 -04:00
|
|
|
self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
2021-07-10 22:25:36 -04:00
|
|
|
// FIXME: avoid this clone (requires implementing Default manually)
|
|
|
|
self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone();
|
|
|
|
for (prim, &def_id) in &self.primitive_locations {
|
|
|
|
let crate_name = tcx.crate_name(def_id.krate);
|
|
|
|
// Recall that we only allow primitive modules to be at the root-level of the crate.
|
|
|
|
// If that restriction is ever lifted, this will have to include the relative paths instead.
|
|
|
|
self.external_paths.insert(
|
|
|
|
def_id,
|
|
|
|
(vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive),
|
|
|
|
);
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
2021-06-24 12:53:35 -07:00
|
|
|
krate = CacheBuilder { tcx, cache: self }.fold_crate(krate);
|
2020-06-24 08:16:21 -05:00
|
|
|
|
2021-02-11 21:29:22 -05:00
|
|
|
for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) {
|
|
|
|
if self.traits.contains_key(&trait_did) {
|
2020-06-24 08:16:21 -05:00
|
|
|
for did in dids {
|
2021-02-11 21:29:22 -05:00
|
|
|
self.impls.entry(did).or_default().push(impl_.clone());
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 21:29:22 -05:00
|
|
|
krate
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-28 16:07:24 +01:00
|
|
|
impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
|
2020-06-24 08:16:21 -05:00
|
|
|
fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
|
|
|
|
if item.def_id.is_local() {
|
|
|
|
debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a stripped module,
|
|
|
|
// we don't want it or its children in the search index.
|
2020-12-13 11:32:57 -05:00
|
|
|
let orig_stripped_mod = match *item.kind {
|
2020-06-24 08:16:21 -05:00
|
|
|
clean::StrippedItem(box clean::ModuleItem(..)) => {
|
2021-01-28 16:07:24 +01:00
|
|
|
mem::replace(&mut self.cache.stripped_mod, true)
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
2021-01-28 16:07:24 +01:00
|
|
|
_ => self.cache.stripped_mod,
|
2020-06-24 08:16:21 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// If the impl is from a masked crate or references something from a
|
|
|
|
// masked crate then remove it completely.
|
2020-12-13 11:32:57 -05:00
|
|
|
if let clean::ImplItem(ref i) = *item.kind {
|
2021-04-29 21:36:54 +02:00
|
|
|
if self.cache.masked_crates.contains(&item.def_id.krate())
|
2021-01-28 16:07:24 +01:00
|
|
|
|| i.trait_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate))
|
|
|
|
|| i.for_.def_id().map_or(false, |d| self.cache.masked_crates.contains(&d.krate))
|
2020-06-24 08:16:21 -05:00
|
|
|
{
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Propagate a trait method's documentation to all implementors of the
|
|
|
|
// trait.
|
2020-12-13 11:32:57 -05:00
|
|
|
if let clean::TraitItem(ref t) = *item.kind {
|
2021-06-26 17:10:52 +02:00
|
|
|
self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
|
2021-04-29 21:36:54 +02:00
|
|
|
clean::TraitWithExtraInfo {
|
|
|
|
trait_: t.clone(),
|
|
|
|
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
|
|
|
|
}
|
2021-01-28 17:05:22 +01:00
|
|
|
});
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Collect all the implementors of traits.
|
2020-12-13 11:32:57 -05:00
|
|
|
if let clean::ImplItem(ref i) = *item.kind {
|
2021-01-15 15:36:15 +01:00
|
|
|
if let Some(did) = i.trait_.def_id() {
|
2020-06-24 08:16:21 -05:00
|
|
|
if i.blanket_impl.is_none() {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache
|
|
|
|
.implementors
|
2021-08-03 07:24:31 +02:00
|
|
|
.entry(did)
|
2020-06-24 08:16:21 -05:00
|
|
|
.or_default()
|
|
|
|
.push(Impl { impl_item: item.clone() });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Index this method for searching later on.
|
|
|
|
if let Some(ref s) = item.name {
|
2020-12-13 11:32:57 -05:00
|
|
|
let (parent, is_inherent_impl_item) = match *item.kind {
|
2020-06-24 08:16:21 -05:00
|
|
|
clean::StrippedItem(..) => ((None, None), false),
|
|
|
|
clean::AssocConstItem(..) | clean::TypedefItem(_, true)
|
2021-01-28 16:07:24 +01:00
|
|
|
if self.cache.parent_is_trait_impl =>
|
2020-06-24 08:16:21 -05:00
|
|
|
{
|
|
|
|
// skip associated items in trait impls
|
|
|
|
((None, None), false)
|
|
|
|
}
|
|
|
|
clean::AssocTypeItem(..)
|
|
|
|
| clean::TyMethodItem(..)
|
|
|
|
| clean::StructFieldItem(..)
|
|
|
|
| clean::VariantItem(..) => (
|
|
|
|
(
|
2021-01-28 16:07:24 +01:00
|
|
|
Some(*self.cache.parent_stack.last().expect("parent_stack is empty")),
|
|
|
|
Some(&self.cache.stack[..self.cache.stack.len() - 1]),
|
2020-06-24 08:16:21 -05:00
|
|
|
),
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
clean::MethodItem(..) | clean::AssocConstItem(..) => {
|
2021-01-28 16:07:24 +01:00
|
|
|
if self.cache.parent_stack.is_empty() {
|
2020-06-24 08:16:21 -05:00
|
|
|
((None, None), false)
|
|
|
|
} else {
|
2021-01-28 16:07:24 +01:00
|
|
|
let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
|
2020-06-24 08:16:21 -05:00
|
|
|
let did = *last;
|
2021-01-28 16:07:24 +01:00
|
|
|
let path = match self.cache.paths.get(&did) {
|
2020-06-24 08:16:21 -05:00
|
|
|
// The current stack not necessarily has correlation
|
|
|
|
// for where the type was defined. On the other
|
|
|
|
// hand, `paths` always has the right
|
|
|
|
// information if present.
|
|
|
|
Some(&(
|
|
|
|
ref fqp,
|
|
|
|
ItemType::Trait
|
|
|
|
| ItemType::Struct
|
|
|
|
| ItemType::Union
|
|
|
|
| ItemType::Enum,
|
|
|
|
)) => Some(&fqp[..fqp.len() - 1]),
|
2021-01-28 16:07:24 +01:00
|
|
|
Some(..) => Some(&*self.cache.stack),
|
2020-06-24 08:16:21 -05:00
|
|
|
None => None,
|
|
|
|
};
|
|
|
|
((Some(*last), path), true)
|
|
|
|
}
|
|
|
|
}
|
2021-01-28 16:07:24 +01:00
|
|
|
_ => ((None, Some(&*self.cache.stack)), false),
|
2020-06-24 08:16:21 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
match parent {
|
2021-01-28 16:07:24 +01:00
|
|
|
(parent, Some(path)) if is_inherent_impl_item || !self.cache.stripped_mod => {
|
2020-06-24 08:16:21 -05:00
|
|
|
debug_assert!(!item.is_stripped());
|
|
|
|
|
|
|
|
// A crate has a module at its root, containing all items,
|
|
|
|
// which should not be indexed. The crate-item itself is
|
|
|
|
// inserted later on when serializing the search-index.
|
2021-06-27 09:28:17 +02:00
|
|
|
if item.def_id.index().map_or(false, |idx| idx != CRATE_DEF_INDEX) {
|
2021-06-18 15:29:45 -07:00
|
|
|
let desc = item.doc_value().map_or_else(String::new, |x| {
|
|
|
|
short_markdown_summary(&x.as_str(), &item.link_names(&self.cache))
|
|
|
|
});
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.search_index.push(IndexItem {
|
2020-06-24 08:16:21 -05:00
|
|
|
ty: item.type_(),
|
|
|
|
name: s.to_string(),
|
|
|
|
path: path.join("::"),
|
2021-06-18 15:29:45 -07:00
|
|
|
desc,
|
2021-05-08 10:04:03 +02:00
|
|
|
parent,
|
2020-06-24 08:16:21 -05:00
|
|
|
parent_idx: None,
|
2021-06-24 12:53:35 -07:00
|
|
|
search_type: get_index_search_type(&item, self.tcx),
|
2021-04-03 19:08:14 -07:00
|
|
|
aliases: item.attrs.get_doc_aliases(),
|
2020-06-24 08:16:21 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Some(parent), None) if is_inherent_impl_item => {
|
|
|
|
// We have a parent, but we don't know where they're
|
|
|
|
// defined yet. Wait for later to index this item.
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.orphan_impl_items.push((parent, item.clone()));
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep track of the fully qualified path for this item.
|
|
|
|
let pushed = match item.name {
|
2020-12-14 23:23:58 -05:00
|
|
|
Some(n) if !n.is_empty() => {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.stack.push(n.to_string());
|
2020-06-24 08:16:21 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
_ => false,
|
|
|
|
};
|
|
|
|
|
2020-12-13 11:32:57 -05:00
|
|
|
match *item.kind {
|
2020-06-24 08:16:21 -05:00
|
|
|
clean::StructItem(..)
|
|
|
|
| clean::EnumItem(..)
|
|
|
|
| clean::TypedefItem(..)
|
|
|
|
| clean::TraitItem(..)
|
2021-05-01 21:39:59 -07:00
|
|
|
| clean::TraitAliasItem(..)
|
2020-06-24 08:16:21 -05:00
|
|
|
| clean::FunctionItem(..)
|
|
|
|
| clean::ModuleItem(..)
|
|
|
|
| clean::ForeignFunctionItem(..)
|
|
|
|
| clean::ForeignStaticItem(..)
|
|
|
|
| clean::ConstantItem(..)
|
|
|
|
| clean::StaticItem(..)
|
|
|
|
| clean::UnionItem(..)
|
|
|
|
| clean::ForeignTypeItem
|
|
|
|
| clean::MacroItem(..)
|
|
|
|
| clean::ProcMacroItem(..)
|
2021-05-01 21:39:59 -07:00
|
|
|
| clean::VariantItem(..) => {
|
|
|
|
if !self.cache.stripped_mod {
|
|
|
|
// Re-exported items mean that the same id can show up twice
|
|
|
|
// in the rustdoc ast that we're looking at. We know,
|
|
|
|
// however, that a re-exported item doesn't show up in the
|
|
|
|
// `public_items` map, so we can skip inserting into the
|
|
|
|
// paths map if there was already an entry present and we're
|
|
|
|
// not a public item.
|
2021-06-26 17:10:52 +02:00
|
|
|
if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
|
|
|
|
|| self.cache.access_levels.is_public(item.def_id.expect_def_id())
|
2021-05-01 21:39:59 -07:00
|
|
|
{
|
2021-04-29 21:36:54 +02:00
|
|
|
self.cache.paths.insert(
|
2021-06-26 17:10:52 +02:00
|
|
|
item.def_id.expect_def_id(),
|
2021-04-29 21:36:54 +02:00
|
|
|
(self.cache.stack.clone(), item.type_()),
|
|
|
|
);
|
2021-05-01 21:39:59 -07:00
|
|
|
}
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clean::PrimitiveItem(..) => {
|
2021-04-29 21:36:54 +02:00
|
|
|
self.cache
|
|
|
|
.paths
|
2021-06-26 17:10:52 +02:00
|
|
|
.insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
2021-05-01 21:39:59 -07:00
|
|
|
clean::ExternCrateItem { .. }
|
|
|
|
| clean::ImportItem(..)
|
|
|
|
| clean::OpaqueTyItem(..)
|
|
|
|
| clean::ImplItem(..)
|
|
|
|
| clean::TyMethodItem(..)
|
|
|
|
| clean::MethodItem(..)
|
|
|
|
| clean::StructFieldItem(..)
|
|
|
|
| clean::AssocConstItem(..)
|
|
|
|
| clean::AssocTypeItem(..)
|
|
|
|
| clean::StrippedItem(..)
|
|
|
|
| clean::KeywordItem(..) => {
|
|
|
|
// FIXME: Do these need handling?
|
|
|
|
// The person writing this comment doesn't know.
|
|
|
|
// So would rather leave them to an expert,
|
|
|
|
// as at least the list is better than `_ => {}`.
|
|
|
|
}
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Maintain the parent stack
|
2021-01-28 16:07:24 +01:00
|
|
|
let orig_parent_is_trait_impl = self.cache.parent_is_trait_impl;
|
2020-12-13 11:32:57 -05:00
|
|
|
let parent_pushed = match *item.kind {
|
2020-06-24 08:16:21 -05:00
|
|
|
clean::TraitItem(..)
|
|
|
|
| clean::EnumItem(..)
|
|
|
|
| clean::ForeignTypeItem
|
|
|
|
| clean::StructItem(..)
|
|
|
|
| clean::UnionItem(..)
|
|
|
|
| clean::VariantItem(..) => {
|
2021-06-26 17:10:52 +02:00
|
|
|
self.cache.parent_stack.push(item.def_id.expect_def_id());
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.parent_is_trait_impl = false;
|
2020-06-24 08:16:21 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
clean::ImplItem(ref i) => {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.parent_is_trait_impl = i.trait_.is_some();
|
2020-06-24 08:16:21 -05:00
|
|
|
match i.for_ {
|
|
|
|
clean::ResolvedPath { did, .. } => {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.parent_stack.push(did);
|
2020-06-24 08:16:21 -05:00
|
|
|
true
|
|
|
|
}
|
2021-06-18 21:47:42 +02:00
|
|
|
clean::DynTrait(ref bounds, _)
|
|
|
|
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
|
|
|
|
if let Some(did) = bounds[0].trait_.def_id() {
|
|
|
|
self.cache.parent_stack.push(did);
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2020-06-24 08:16:21 -05:00
|
|
|
ref t => {
|
|
|
|
let prim_did = t
|
|
|
|
.primitive_type()
|
2021-01-28 16:07:24 +01:00
|
|
|
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
|
2020-06-24 08:16:21 -05:00
|
|
|
match prim_did {
|
|
|
|
Some(did) => {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.parent_stack.push(did);
|
2020-06-24 08:16:21 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => false,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Once we've recursively found all the generics, hoard off all the
|
|
|
|
// implementations elsewhere.
|
2020-11-22 12:57:55 -05:00
|
|
|
let item = self.fold_item_recur(item);
|
2020-12-13 11:32:57 -05:00
|
|
|
let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item {
|
2020-11-22 12:57:55 -05:00
|
|
|
// Figure out the id of this impl. This may map to a
|
|
|
|
// primitive rather than always to a struct/enum.
|
|
|
|
// Note: matching twice to restrict the lifetime of the `i` borrow.
|
|
|
|
let mut dids = FxHashSet::default();
|
2020-12-13 11:32:57 -05:00
|
|
|
match i.for_ {
|
|
|
|
clean::ResolvedPath { did, .. }
|
|
|
|
| clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => {
|
|
|
|
dids.insert(did);
|
|
|
|
}
|
2021-06-18 21:47:42 +02:00
|
|
|
clean::DynTrait(ref bounds, _)
|
|
|
|
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
|
|
|
|
if let Some(did) = bounds[0].trait_.def_id() {
|
|
|
|
dids.insert(did);
|
|
|
|
}
|
|
|
|
}
|
2020-12-13 11:32:57 -05:00
|
|
|
ref t => {
|
2021-01-28 16:07:24 +01:00
|
|
|
let did = t
|
|
|
|
.primitive_type()
|
|
|
|
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
|
2020-06-24 08:16:21 -05:00
|
|
|
|
2020-12-13 11:32:57 -05:00
|
|
|
if let Some(did) = did {
|
|
|
|
dids.insert(did);
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
2020-11-22 12:57:55 -05:00
|
|
|
}
|
2020-12-13 11:32:57 -05:00
|
|
|
}
|
2020-06-24 08:16:21 -05:00
|
|
|
|
2020-12-13 11:32:57 -05:00
|
|
|
if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
|
|
|
|
for bound in generics {
|
2021-01-15 15:36:15 +01:00
|
|
|
if let Some(did) = bound.def_id() {
|
2020-12-13 11:32:57 -05:00
|
|
|
dids.insert(did);
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
}
|
2020-12-13 11:32:57 -05:00
|
|
|
}
|
2020-11-22 12:57:55 -05:00
|
|
|
let impl_item = Impl { impl_item: item };
|
2021-01-28 16:07:24 +01:00
|
|
|
if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
|
2020-11-22 12:57:55 -05:00
|
|
|
for did in dids {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
|
2020-11-22 12:57:55 -05:00
|
|
|
}
|
|
|
|
} else {
|
2021-01-15 15:36:15 +01:00
|
|
|
let trait_did = impl_item.trait_did().expect("no trait did");
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.orphan_trait_impls.push((trait_did, dids, impl_item));
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
2020-11-22 12:57:55 -05:00
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(item)
|
|
|
|
};
|
2020-06-24 08:16:21 -05:00
|
|
|
|
|
|
|
if pushed {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.stack.pop().expect("stack already empty");
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
|
|
|
if parent_pushed {
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.parent_stack.pop().expect("parent stack already empty");
|
2020-06-24 08:16:21 -05:00
|
|
|
}
|
2021-01-28 16:07:24 +01:00
|
|
|
self.cache.stripped_mod = orig_stripped_mod;
|
|
|
|
self.cache.parent_is_trait_impl = orig_parent_is_trait_impl;
|
2020-06-24 08:16:21 -05:00
|
|
|
ret
|
|
|
|
}
|
|
|
|
}
|