Skip to content

rustdoc-json-types: Intern Types to deduplicate and flatten #142327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 34 additions & 16 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_middle::{bug, ty};
use rustc_span::{Pos, Symbol, kw};
use rustdoc_json_types::*;

use crate::clean::{self, ItemId};
use crate::clean;
use crate::formats::FormatRenderer;
use crate::formats::item_type::ItemType;
use crate::json::JsonRenderer;
Expand Down Expand Up @@ -107,7 +107,7 @@ impl JsonRenderer<'_> {
}
}

fn ids(&self, items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
fn ids(&self, items: impl IntoIterator<Item = clean::Item>) -> Vec<ItemId> {
items
.into_iter()
.filter(|x| !x.is_stripped() && !x.is_keyword())
Expand All @@ -118,7 +118,7 @@ impl JsonRenderer<'_> {
fn ids_keeping_stripped(
&self,
items: impl IntoIterator<Item = clean::Item>,
) -> Vec<Option<Id>> {
) -> Vec<Option<ItemId>> {
items
.into_iter()
.map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
Expand Down Expand Up @@ -470,7 +470,7 @@ impl FromClean<clean::WherePredicate> for WherePredicate {
EqPredicate { lhs, rhs } => WherePredicate::EqPredicate {
// The LHS currently has type `Type` but it should be a `QualifiedPath` since it may
// refer to an associated const. However, `EqPredicate` shouldn't exist in the first
// place: <https://github.com/rust-lang/rust/141368>.
// place: <https://github.com/rust-lang/rust/issues/141368>.
lhs: lhs.into_json(renderer),
rhs: rhs.into_json(renderer),
},
Expand Down Expand Up @@ -522,6 +522,12 @@ pub(crate) fn from_trait_bound_modifier(
}
}

impl FromClean<clean::Type> for TypeId {
fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self {
from_type(ty.into_json(renderer), renderer)
}
}

impl FromClean<clean::Type> for Type {
fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self {
use clean::Type::{
Expand All @@ -539,26 +545,24 @@ impl FromClean<clean::Type> for Type {
// FIXME: add dedicated variant to json Type?
SelfTy => Type::Generic("Self".to_owned()),
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_json(renderer))),
BareFunction(f) => Type::FunctionPointer((*f).into_json(renderer)),
Tuple(t) => Type::Tuple(t.into_json(renderer)),
Slice(t) => Type::Slice(Box::new((*t).into_json(renderer))),
Array(t, s) => {
Type::Array { type_: Box::new((*t).into_json(renderer)), len: s.to_string() }
}
Slice(t) => Type::Slice((*t).into_json(renderer)),
Array(t, s) => Type::Array { type_: (*t).into_json(renderer), len: s.to_string() },
clean::Type::Pat(t, p) => Type::Pat {
type_: Box::new((*t).into_json(renderer)),
type_: (*t).into_json(renderer),
__pat_unstable_do_not_use: p.to_string(),
},
ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)),
Infer => Type::Infer,
RawPointer(mutability, type_) => Type::RawPointer {
is_mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_json(renderer)),
type_: (*type_).into_json(renderer),
},
BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
lifetime: lifetime.map(convert_lifetime),
is_mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_json(renderer)),
type_: (*type_).into_json(renderer),
},
QPath(qpath) => (*qpath).into_json(renderer),
// FIXME(unsafe_binder): Implement rustdoc-json.
Expand All @@ -567,24 +571,34 @@ impl FromClean<clean::Type> for Type {
}
}

fn from_type(ty: Type, renderer: &JsonRenderer<'_>) -> TypeId {
renderer.types.borrow_mut().insert_full(ty).0
}

impl FromClean<clean::Path> for Path {
fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> Path {
Path {
path: path.whole_name(),
id: renderer.id_from_item_default(path.def_id().into()),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_json(renderer))),
args: path.segments.into_iter().next_back().map(|args| args.args.into_json(renderer)),
}
}
}

impl FromClean<clean::QPathData> for TypeId {
fn from_clean(qpath: clean::QPathData, renderer: &JsonRenderer<'_>) -> Self {
from_type(qpath.into_json(renderer), renderer)
}
}

impl FromClean<clean::QPathData> for Type {
fn from_clean(qpath: clean::QPathData, renderer: &JsonRenderer<'_>) -> Self {
let clean::QPathData { assoc, self_type, should_fully_qualify: _, trait_ } = qpath;

Self::QualifiedPath {
name: assoc.name.to_string(),
args: Box::new(assoc.args.into_json(renderer)),
self_type: Box::new(self_type.into_json(renderer)),
args: assoc.args.into_json(renderer),
self_type: self_type.into_json(renderer),
trait_: trait_.map(|trait_| trait_.into_json(renderer)),
}
}
Expand Down Expand Up @@ -768,7 +782,11 @@ impl FromClean<clean::Import> for Use {
Use {
source: import.source.path.whole_name(),
name,
id: import.source.did.map(ItemId::from).map(|i| renderer.id_from_item_default(i)),
id: import
.source
.did
.map(clean::ItemId::from)
.map(|i| renderer.id_from_item_default(i)),
is_glob,
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/librustdoc/json/ids.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Id handling for rustdoc-json.
//!
//! Manages the creation of [`rustdoc_json_types::Id`] and the
//! Manages the creation of [`rustdoc_json_types::ItemId`] and the
//! fact that these don't correspond exactly to [`DefId`], because
//! [`rustdoc_json_types::Item`] doesn't correspond exactly to what
//! other phases think of as an "item".
Expand All @@ -14,14 +14,14 @@ use rustdoc_json_types as types;
use super::JsonRenderer;
use crate::clean;

pub(super) type IdInterner = FxHashMap<FullItemId, types::Id>;
pub(super) type IdInterner = FxHashMap<FullItemId, types::ItemId>;

#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
/// An uninterned id.
///
/// Each one corresponds to exactly one of both:
/// 1. [`rustdoc_json_types::Item`].
/// 2. [`rustdoc_json_types::Id`] transitively (as each `Item` has an `Id`).
/// 2. [`rustdoc_json_types::ItemId`] transitively (as each `Item` has an `Id`).
///
/// It's *broadly* equivalent to a [`DefId`], but needs slightly more information
/// to fully disambiguate items, because sometimes we choose to split a single HIR
Expand Down Expand Up @@ -66,7 +66,7 @@ pub(super) struct FullItemId {
}

impl JsonRenderer<'_> {
pub(crate) fn id_from_item_default(&self, item_id: clean::ItemId) -> types::Id {
pub(crate) fn id_from_item_default(&self, item_id: clean::ItemId) -> types::ItemId {
self.id_from_item_inner(item_id, None, None)
}

Expand All @@ -75,7 +75,7 @@ impl JsonRenderer<'_> {
item_id: clean::ItemId,
name: Option<Symbol>,
imported_id: Option<DefId>,
) -> types::Id {
) -> types::ItemId {
let (def_id, extra_id) = match item_id {
clean::ItemId::DefId(did) => (did, imported_id),
clean::ItemId::Blanket { for_, impl_id } => (for_, Some(impl_id)),
Expand Down Expand Up @@ -107,10 +107,10 @@ impl JsonRenderer<'_> {
let len = interner.len();
*interner
.entry(key)
.or_insert_with(|| types::Id(len.try_into().expect("too many items in a crate")))
.or_insert_with(|| types::ItemId(len.try_into().expect("too many items in a crate")))
}

pub(crate) fn id_from_item(&self, item: &clean::Item) -> types::Id {
pub(crate) fn id_from_item(&self, item: &clean::Item) -> types::ItemId {
match item.kind {
clean::ItemKind::ImportItem(ref import) => {
let imported_id = import.source.did;
Expand Down
21 changes: 12 additions & 9 deletions src/librustdoc/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::io::{BufWriter, Write, stdout};
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
Expand All @@ -41,7 +41,8 @@ pub(crate) struct JsonRenderer<'tcx> {
tcx: TyCtxt<'tcx>,
/// A mapping of IDs that contains all local items for this crate which gets output as a top
/// level field of the JSON blob.
index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
index: RefCell<FxHashMap<types::ItemId, types::Item>>,
types: RefCell<FxIndexSet<types::Type>>,
/// The directory where the JSON blob should be written to.
///
/// If this is `None`, the blob will be printed to `stdout` instead.
Expand All @@ -56,7 +57,7 @@ impl<'tcx> JsonRenderer<'tcx> {
self.tcx.sess
}

fn get_trait_implementors(&mut self, id: DefId) -> Vec<types::Id> {
fn get_trait_implementors(&mut self, id: DefId) -> Vec<types::ItemId> {
Rc::clone(&self.cache)
.implementors
.get(&id)
Expand All @@ -73,7 +74,7 @@ impl<'tcx> JsonRenderer<'tcx> {
.unwrap_or_default()
}

fn get_impls(&mut self, id: DefId) -> Vec<types::Id> {
fn get_impls(&mut self, id: DefId) -> Vec<types::ItemId> {
Rc::clone(&self.cache)
.impls
.get(&id)
Expand Down Expand Up @@ -134,7 +135,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
let feature_stability: FxHashMap<&str, Stability> = sess
.target
.rust_target_features()
.into_iter()
.iter()
.copied()
.map(|(name, stability, _)| (name, stability))
.collect();
Expand All @@ -144,7 +145,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
target_features: sess
.target
.rust_target_features()
.into_iter()
.iter()
.copied()
.filter(|(_, stability, _)| {
// Describe only target features which the user can toggle
Expand All @@ -158,7 +159,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
_ => None,
},
implies_features: implied_features
.into_iter()
.iter()
.copied()
.filter(|name| {
// Imply only target features which the user can toggle
Expand Down Expand Up @@ -197,7 +198,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
Ok((
JsonRenderer {
tcx,
index: Rc::new(RefCell::new(FxHashMap::default())),
index: RefCell::new(FxHashMap::default()),
types: RefCell::new(FxIndexSet::default()),
out_dir: if options.output_to_stdout { None } else { Some(options.output) },
cache: Rc::new(cache),
imported_items,
Expand Down Expand Up @@ -299,7 +301,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
debug!("Done with crate");

let e = ExternalCrate { crate_num: LOCAL_CRATE };
let index = (*self.index).clone().into_inner();
let index = self.index.clone().into_inner();

// Note that tcx.rust_target_features is inappropriate here because rustdoc tries to run for
// multiple targets: https://github.com/rust-lang/rust/pull/137632
Expand All @@ -313,6 +315,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
crate_version: self.cache.crate_version.clone(),
includes_private: self.cache.document_private,
index,
types: self.types.borrow().iter().cloned().collect(),
paths: self
.cache
.paths
Expand Down
Loading
Loading