Avoid more clones in rustdoc JSON output.

By making `JsonRenderer::item` take `&clean::Item` instead of a
`clean::Item`. This required also changing `FromClean` and `IntoJson`
methods to take references, which required a lot of follow-on sigil
wrangling that is mostly tedious.
This commit is contained in:
Nicholas Nethercote 2025-06-10 22:29:36 +10:00
parent 195c985398
commit 79b3c08bdb
4 changed files with 133 additions and 125 deletions

View file

@ -56,7 +56,7 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
fn restore_module_data(&mut self, info: Self::ModuleData);
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
fn item(&mut self, item: &clean::Item) -> Result<(), Error>;
/// Renders a module (should not handle recursing into children).
fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error>;
@ -74,7 +74,7 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
cx: &mut T,
item: clean::Item,
item: &clean::Item,
prof: &SelfProfilerRef,
) -> Result<(), Error> {
if item.is_mod() && T::RUN_ON_MODULE {
@ -84,12 +84,12 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
cx.mod_item_in(&item)?;
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
item.inner.kind
let (clean::StrippedItem(box clean::ModuleItem(ref module))
| clean::ModuleItem(ref module)) = item.inner.kind
else {
unreachable!()
};
for it in module.items {
for it in module.items.iter() {
let info = cx.save_module_data();
run_format_inner(cx, it, prof)?;
cx.restore_module_data(info);
@ -101,7 +101,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
} else if let Some(item_name) = item.name
&& !item.is_extern_crate()
{
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(&item))?;
}
Ok(())
}
@ -125,7 +125,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
}
// Render the crate documentation
run_format_inner(&mut format_renderer, krate.module, prof)?;
run_format_inner(&mut format_renderer, &krate.module, prof)?;
prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
.run(|| format_renderer.after_krate())

View file

@ -830,7 +830,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
Ok(())
}
fn item(&mut self, item: clean::Item) -> Result<(), Error> {
fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
// Stripped modules survive the rustdoc passes (i.e., `strip-private`)
// if they contain impls for public types. These modules can also
// contain items such as publicly re-exported structures.

View file

@ -13,6 +13,7 @@ use rustc_metadata::rendered_const;
use rustc_middle::{bug, ty};
use rustc_span::{Pos, Symbol, kw};
use rustdoc_json_types::*;
use thin_vec::ThinVec;
use crate::clean::{self, ItemId};
use crate::formats::FormatRenderer;
@ -21,7 +22,7 @@ use crate::json::JsonRenderer;
use crate::passes::collect_intra_doc_links::UrlFragment;
impl JsonRenderer<'_> {
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
pub(super) fn convert_item(&self, item: &clean::Item) -> Option<Item> {
let deprecation = item.deprecation(self.tcx);
let links = self
.cache
@ -107,49 +108,54 @@ impl JsonRenderer<'_> {
}
}
fn ids(&self, items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
fn ids(&self, items: &[clean::Item]) -> Vec<Id> {
items
.into_iter()
.filter(|x| !x.is_stripped() && !x.is_keyword())
.iter()
.filter(|i| !i.is_stripped() && !i.is_keyword())
.map(|i| self.id_from_item(&i))
.collect()
}
fn ids_keeping_stripped(
&self,
items: impl IntoIterator<Item = clean::Item>,
) -> Vec<Option<Id>> {
fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
items
.into_iter()
.iter()
.map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
.collect()
}
}
pub(crate) trait FromClean<T> {
fn from_clean(f: T, renderer: &JsonRenderer<'_>) -> Self;
fn from_clean(f: &T, renderer: &JsonRenderer<'_>) -> Self;
}
pub(crate) trait IntoJson<T> {
fn into_json(self, renderer: &JsonRenderer<'_>) -> T;
fn into_json(&self, renderer: &JsonRenderer<'_>) -> T;
}
impl<T, U> IntoJson<U> for T
where
U: FromClean<T>,
{
fn into_json(self, renderer: &JsonRenderer<'_>) -> U {
fn into_json(&self, renderer: &JsonRenderer<'_>) -> U {
U::from_clean(self, renderer)
}
}
impl<I, T, U> FromClean<I> for Vec<U>
impl<T, U> FromClean<Vec<T>> for Vec<U>
where
I: IntoIterator<Item = T>,
U: FromClean<T>,
{
fn from_clean(f: I, renderer: &JsonRenderer<'_>) -> Vec<U> {
f.into_iter().map(|x| x.into_json(renderer)).collect()
fn from_clean(items: &Vec<T>, renderer: &JsonRenderer<'_>) -> Vec<U> {
items.iter().map(|i| i.into_json(renderer)).collect()
}
}
impl<T, U> FromClean<ThinVec<T>> for Vec<U>
where
U: FromClean<T>,
{
fn from_clean(items: &ThinVec<T>, renderer: &JsonRenderer<'_>) -> Vec<U> {
items.iter().map(|i| i.into_json(renderer)).collect()
}
}
@ -165,7 +171,7 @@ pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation {
}
impl FromClean<clean::GenericArgs> for GenericArgs {
fn from_clean(args: clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(args: &clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self {
use clean::GenericArgs::*;
match args {
AngleBracketed { args, constraints } => GenericArgs::AngleBracketed {
@ -174,7 +180,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
},
Parenthesized { inputs, output } => GenericArgs::Parenthesized {
inputs: inputs.into_json(renderer),
output: output.map(|a| (*a).into_json(renderer)),
output: output.as_ref().map(|a| a.as_ref().into_json(renderer)),
},
ReturnTypeNotation => GenericArgs::ReturnTypeNotation,
}
@ -182,7 +188,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs {
}
impl FromClean<clean::GenericArg> for GenericArg {
fn from_clean(arg: clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(arg: &clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self {
use clean::GenericArg::*;
match arg {
Lifetime(l) => GenericArg::Lifetime(convert_lifetime(l)),
@ -195,7 +201,7 @@ impl FromClean<clean::GenericArg> for GenericArg {
impl FromClean<clean::Constant> for Constant {
// FIXME(generic_const_items): Add support for generic const items.
fn from_clean(constant: clean::Constant, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(constant: &clean::Constant, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
let expr = constant.expr(tcx);
let value = constant.value(tcx);
@ -206,7 +212,7 @@ impl FromClean<clean::Constant> for Constant {
impl FromClean<clean::ConstantKind> for Constant {
// FIXME(generic_const_items): Add support for generic const items.
fn from_clean(constant: clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(constant: &clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
let expr = constant.expr(tcx);
let value = constant.value(tcx);
@ -216,7 +222,7 @@ impl FromClean<clean::ConstantKind> for Constant {
}
impl FromClean<clean::AssocItemConstraint> for AssocItemConstraint {
fn from_clean(constraint: clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(constraint: &clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self {
AssocItemConstraint {
name: constraint.assoc.name.to_string(),
args: constraint.assoc.args.into_json(renderer),
@ -226,7 +232,7 @@ impl FromClean<clean::AssocItemConstraint> for AssocItemConstraint {
}
impl FromClean<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
fn from_clean(kind: clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(kind: &clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self {
use clean::AssocItemConstraintKind::*;
match kind {
Equality { term } => AssocItemConstraintKind::Equality(term.into_json(renderer)),
@ -235,15 +241,15 @@ impl FromClean<clean::AssocItemConstraintKind> for AssocItemConstraintKind {
}
}
fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
fn from_clean_item(item: &clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
use clean::ItemKind::*;
let name = item.name;
let is_crate = item.is_crate();
let header = item.fn_header(renderer.tcx);
match item.inner.kind {
match &item.inner.kind {
ModuleItem(m) => {
ItemEnum::Module(Module { is_crate, items: renderer.ids(m.items), is_stripped: false })
ItemEnum::Module(Module { is_crate, items: renderer.ids(&m.items), is_stripped: false })
}
ImportItem(i) => ItemEnum::Use(i.into_json(renderer)),
StructItem(s) => ItemEnum::Struct(s.into_json(renderer)),
@ -251,27 +257,27 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)),
EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)),
VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)),
FunctionItem(f) => ItemEnum::Function(from_function(*f, true, header.unwrap(), renderer)),
FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), renderer)),
ForeignFunctionItem(f, _) => {
ItemEnum::Function(from_function(*f, false, header.unwrap(), renderer))
ItemEnum::Function(from_function(f, false, header.unwrap(), renderer))
}
TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)),
TraitItem(t) => ItemEnum::Trait(t.as_ref().into_json(renderer)),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)),
MethodItem(m, _) => ItemEnum::Function(from_function(*m, true, header.unwrap(), renderer)),
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
RequiredMethodItem(m) => {
ItemEnum::Function(from_function(*m, false, header.unwrap(), renderer))
ItemEnum::Function(from_function(m, false, header.unwrap(), renderer))
}
ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
ImplItem(i) => ItemEnum::Impl(i.as_ref().into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, &rustc_hir::Safety::Safe, renderer)),
ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
ForeignTypeItem => ItemEnum::ExternType,
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)),
TypeAliasItem(t) => ItemEnum::TypeAlias(t.as_ref().into_json(renderer)),
// FIXME(generic_const_items): Add support for generic free consts
ConstantItem(ci) => ItemEnum::Constant {
type_: ci.type_.into_json(renderer),
const_: ci.kind.into_json(renderer),
},
MacroItem(m) => ItemEnum::Macro(m.source),
MacroItem(m) => ItemEnum::Macro(m.source.clone()),
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_json(renderer)),
PrimitiveItem(p) => {
ItemEnum::Primitive(Primitive {
@ -281,7 +287,7 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
}
// FIXME(generic_const_items): Add support for generic associated consts.
RequiredAssocConstItem(_generics, ty) => {
ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None }
ItemEnum::AssocConst { type_: ty.as_ref().into_json(renderer), value: None }
}
// FIXME(generic_const_items): Add support for generic associated consts.
ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst {
@ -296,22 +302,22 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
AssocTypeItem(t, b) => ItemEnum::AssocType {
generics: t.generics.into_json(renderer),
bounds: b.into_json(renderer),
type_: Some(t.item_type.unwrap_or(t.type_).into_json(renderer)),
type_: Some(t.item_type.as_ref().unwrap_or(&t.type_).into_json(renderer)),
},
// `convert_item` early returns `None` for stripped items and keywords.
KeywordItem => unreachable!(),
StrippedItem(inner) => {
match *inner {
match inner.as_ref() {
ModuleItem(m) => ItemEnum::Module(Module {
is_crate,
items: renderer.ids(m.items),
items: renderer.ids(&m.items),
is_stripped: true,
}),
// `convert_item` early returns `None` for stripped items we're not including
_ => unreachable!(),
}
}
ExternCrateItem { ref src } => ItemEnum::ExternCrate {
ExternCrateItem { src } => ItemEnum::ExternCrate {
name: name.as_ref().unwrap().to_string(),
rename: src.map(|x| x.to_string()),
},
@ -319,17 +325,17 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
}
impl FromClean<clean::Struct> for Struct {
fn from_clean(struct_: clean::Struct, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(struct_: &clean::Struct, renderer: &JsonRenderer<'_>) -> Self {
let has_stripped_fields = struct_.has_stripped_entries();
let clean::Struct { ctor_kind, generics, fields } = struct_;
let kind = match ctor_kind {
Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)),
Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(&fields)),
Some(CtorKind::Const) => {
assert!(fields.is_empty());
StructKind::Unit
}
None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields },
None => StructKind::Plain { fields: renderer.ids(&fields), has_stripped_fields },
};
Struct {
@ -341,13 +347,13 @@ impl FromClean<clean::Struct> for Struct {
}
impl FromClean<clean::Union> for Union {
fn from_clean(union_: clean::Union, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(union_: &clean::Union, renderer: &JsonRenderer<'_>) -> Self {
let has_stripped_fields = union_.has_stripped_entries();
let clean::Union { generics, fields } = union_;
Union {
generics: generics.into_json(renderer),
has_stripped_fields,
fields: renderer.ids(fields),
fields: renderer.ids(&fields),
impls: Vec::new(), // Added in JsonRenderer::item
}
}
@ -377,12 +383,12 @@ fn convert_abi(a: ExternAbi) -> Abi {
}
}
fn convert_lifetime(l: clean::Lifetime) -> String {
fn convert_lifetime(l: &clean::Lifetime) -> String {
l.0.to_string()
}
impl FromClean<clean::Generics> for Generics {
fn from_clean(generics: clean::Generics, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(generics: &clean::Generics, renderer: &JsonRenderer<'_>) -> Self {
Generics {
params: generics.params.into_json(renderer),
where_predicates: generics.where_predicates.into_json(renderer),
@ -391,7 +397,7 @@ impl FromClean<clean::Generics> for Generics {
}
impl FromClean<clean::GenericParamDef> for GenericParamDef {
fn from_clean(generic_param: clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(generic_param: &clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self {
GenericParamDef {
name: generic_param.name.to_string(),
kind: generic_param.kind.into_json(renderer),
@ -400,7 +406,7 @@ impl FromClean<clean::GenericParamDef> for GenericParamDef {
}
impl FromClean<clean::GenericParamDefKind> for GenericParamDefKind {
fn from_clean(kind: clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(kind: &clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self {
use clean::GenericParamDefKind::*;
match kind {
Lifetime { outlives } => GenericParamDefKind::Lifetime {
@ -408,29 +414,29 @@ impl FromClean<clean::GenericParamDefKind> for GenericParamDefKind {
},
Type { bounds, default, synthetic } => GenericParamDefKind::Type {
bounds: bounds.into_json(renderer),
default: default.map(|x| (*x).into_json(renderer)),
is_synthetic: synthetic,
default: default.as_ref().map(|x| x.as_ref().into_json(renderer)),
is_synthetic: *synthetic,
},
Const { ty, default, synthetic: _ } => GenericParamDefKind::Const {
type_: (*ty).into_json(renderer),
default: default.map(|x| *x),
type_: ty.as_ref().into_json(renderer),
default: default.as_ref().map(|x| x.as_ref().clone()),
},
}
}
}
impl FromClean<clean::WherePredicate> for WherePredicate {
fn from_clean(predicate: clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(predicate: &clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self {
use clean::WherePredicate::*;
match predicate {
BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
type_: ty.into_json(renderer),
bounds: bounds.into_json(renderer),
generic_params: bound_params
.into_iter()
.iter()
.map(|x| {
let name = x.name.to_string();
let kind = match x.kind {
let kind = match &x.kind {
clean::GenericParamDefKind::Lifetime { outlives } => {
GenericParamDefKind::Lifetime {
outlives: outlives.iter().map(|lt| lt.0.to_string()).collect(),
@ -442,14 +448,16 @@ impl FromClean<clean::WherePredicate> for WherePredicate {
.into_iter()
.map(|bound| bound.into_json(renderer))
.collect(),
default: default.map(|ty| (*ty).into_json(renderer)),
is_synthetic: synthetic,
default: default
.as_ref()
.map(|ty| ty.as_ref().into_json(renderer)),
is_synthetic: *synthetic,
}
}
clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => {
GenericParamDefKind::Const {
type_: (*ty).into_json(renderer),
default: default.map(|d| *d),
type_: ty.as_ref().into_json(renderer),
default: default.as_ref().map(|d| d.as_ref().clone()),
}
}
};
@ -462,7 +470,7 @@ impl FromClean<clean::WherePredicate> for WherePredicate {
outlives: bounds
.iter()
.map(|bound| match bound {
clean::GenericBound::Outlives(lt) => convert_lifetime(*lt),
clean::GenericBound::Outlives(lt) => convert_lifetime(lt),
_ => bug!("found non-outlives-bound on lifetime predicate"),
})
.collect(),
@ -479,7 +487,7 @@ impl FromClean<clean::WherePredicate> for WherePredicate {
}
impl FromClean<clean::GenericBound> for GenericBound {
fn from_clean(bound: clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(bound: &clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self {
use clean::GenericBound::*;
match bound {
TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
@ -494,7 +502,7 @@ impl FromClean<clean::GenericBound> for GenericBound {
args.iter()
.map(|arg| match arg {
clean::PreciseCapturingArg::Lifetime(lt) => {
PreciseCapturingArg::Lifetime(convert_lifetime(*lt))
PreciseCapturingArg::Lifetime(convert_lifetime(lt))
}
clean::PreciseCapturingArg::Param(param) => {
PreciseCapturingArg::Param(param.to_string())
@ -507,7 +515,7 @@ impl FromClean<clean::GenericBound> for GenericBound {
}
pub(crate) fn from_trait_bound_modifier(
modifiers: rustc_hir::TraitBoundModifiers,
modifiers: &rustc_hir::TraitBoundModifiers,
) -> TraitBoundModifier {
use rustc_hir as hir;
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
@ -523,7 +531,7 @@ pub(crate) fn from_trait_bound_modifier(
}
impl FromClean<clean::Type> for Type {
fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(ty: &clean::Type, renderer: &JsonRenderer<'_>) -> Self {
use clean::Type::{
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
RawPointer, SelfTy, Slice, Tuple, UnsafeBinder,
@ -532,35 +540,35 @@ impl FromClean<clean::Type> for Type {
match ty {
clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)),
clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
lifetime: lt.map(convert_lifetime),
lifetime: lt.as_ref().map(convert_lifetime),
traits: bounds.into_json(renderer),
}),
Generic(s) => Type::Generic(s.to_string()),
// 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(Box::new(f.as_ref().into_json(renderer))),
Tuple(t) => Type::Tuple(t.into_json(renderer)),
Slice(t) => Type::Slice(Box::new((*t).into_json(renderer))),
Slice(t) => Type::Slice(Box::new(t.as_ref().into_json(renderer))),
Array(t, s) => {
Type::Array { type_: Box::new((*t).into_json(renderer)), len: s.to_string() }
Type::Array { type_: Box::new(t.as_ref().into_json(renderer)), len: s.to_string() }
}
clean::Type::Pat(t, p) => Type::Pat {
type_: Box::new((*t).into_json(renderer)),
type_: Box::new(t.as_ref().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)),
is_mutable: *mutability == ast::Mutability::Mut,
type_: Box::new(type_.as_ref().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)),
lifetime: lifetime.as_ref().map(convert_lifetime),
is_mutable: *mutability == ast::Mutability::Mut,
type_: Box::new(type_.as_ref().into_json(renderer)),
},
QPath(qpath) => (*qpath).into_json(renderer),
QPath(qpath) => qpath.as_ref().into_json(renderer),
// FIXME(unsafe_binder): Implement rustdoc-json.
UnsafeBinder(_) => todo!(),
}
@ -568,30 +576,30 @@ impl FromClean<clean::Type> for Type {
}
impl FromClean<clean::Path> for Path {
fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> 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.last().map(|args| Box::new(args.args.into_json(renderer))),
}
}
}
impl FromClean<clean::QPathData> for Type {
fn from_clean(qpath: clean::QPathData, renderer: &JsonRenderer<'_>) -> Self {
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)),
trait_: trait_.map(|trait_| trait_.into_json(renderer)),
trait_: trait_.as_ref().map(|trait_| trait_.into_json(renderer)),
}
}
}
impl FromClean<clean::Term> for Term {
fn from_clean(term: clean::Term, renderer: &JsonRenderer<'_>) -> Term {
fn from_clean(term: &clean::Term, renderer: &JsonRenderer<'_>) -> Term {
match term {
clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)),
clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)),
@ -600,14 +608,14 @@ impl FromClean<clean::Term> for Term {
}
impl FromClean<clean::BareFunctionDecl> for FunctionPointer {
fn from_clean(bare_decl: clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(bare_decl: &clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self {
let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl;
FunctionPointer {
header: FunctionHeader {
is_unsafe: safety.is_unsafe(),
is_const: false,
is_async: false,
abi: convert_abi(abi),
abi: convert_abi(*abi),
},
generic_params: generic_params.into_json(renderer),
sig: decl.into_json(renderer),
@ -616,7 +624,7 @@ impl FromClean<clean::BareFunctionDecl> for FunctionPointer {
}
impl FromClean<clean::FnDecl> for FunctionSignature {
fn from_clean(decl: clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(decl: &clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self {
let clean::FnDecl { inputs, output, c_variadic } = decl;
FunctionSignature {
inputs: inputs
@ -629,13 +637,13 @@ impl FromClean<clean::FnDecl> for FunctionSignature {
})
.collect(),
output: if output.is_unit() { None } else { Some(output.into_json(renderer)) },
is_c_variadic: c_variadic,
is_c_variadic: *c_variadic,
}
}
}
impl FromClean<clean::Trait> for Trait {
fn from_clean(trait_: clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(trait_: &clean::Trait, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
let is_auto = trait_.is_auto(tcx);
let is_unsafe = trait_.safety(tcx).is_unsafe();
@ -645,7 +653,7 @@ impl FromClean<clean::Trait> for Trait {
is_auto,
is_unsafe,
is_dyn_compatible,
items: renderer.ids(items),
items: renderer.ids(&items),
generics: generics.into_json(renderer),
bounds: bounds.into_json(renderer),
implementations: Vec::new(), // Added in JsonRenderer::item
@ -655,7 +663,7 @@ impl FromClean<clean::Trait> for Trait {
impl FromClean<clean::PolyTrait> for PolyTrait {
fn from_clean(
clean::PolyTrait { trait_, generic_params }: clean::PolyTrait,
clean::PolyTrait { trait_, generic_params }: &clean::PolyTrait,
renderer: &JsonRenderer<'_>,
) -> Self {
PolyTrait {
@ -666,14 +674,14 @@ impl FromClean<clean::PolyTrait> for PolyTrait {
}
impl FromClean<clean::Impl> for Impl {
fn from_clean(impl_: clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(impl_: &clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx);
let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
// FIXME: use something like ImplKind in JSON?
let (is_synthetic, blanket_impl) = match kind {
clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
clean::ImplKind::Auto => (true, None),
clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
clean::ImplKind::Blanket(ty) => (false, Some(ty)),
};
let is_negative = match polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
@ -686,18 +694,18 @@ impl FromClean<clean::Impl> for Impl {
.into_iter()
.map(|x| x.to_string())
.collect(),
trait_: trait_.map(|path| path.into_json(renderer)),
trait_: trait_.as_ref().map(|path| path.into_json(renderer)),
for_: for_.into_json(renderer),
items: renderer.ids(items),
items: renderer.ids(&items),
is_negative,
is_synthetic,
blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
blanket_impl: blanket_impl.map(|x| x.as_ref().into_json(renderer)),
}
}
}
pub(crate) fn from_function(
clean::Function { decl, generics }: clean::Function,
clean::Function { decl, generics }: &clean::Function,
has_body: bool,
header: rustc_hir::FnHeader,
renderer: &JsonRenderer<'_>,
@ -711,30 +719,30 @@ pub(crate) fn from_function(
}
impl FromClean<clean::Enum> for Enum {
fn from_clean(enum_: clean::Enum, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(enum_: &clean::Enum, renderer: &JsonRenderer<'_>) -> Self {
let has_stripped_variants = enum_.has_stripped_entries();
let clean::Enum { variants, generics } = enum_;
Enum {
generics: generics.into_json(renderer),
has_stripped_variants,
variants: renderer.ids(variants),
variants: renderer.ids(&variants.as_slice().raw),
impls: Vec::new(), // Added in JsonRenderer::item
}
}
}
impl FromClean<clean::Variant> for Variant {
fn from_clean(variant: clean::Variant, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(variant: &clean::Variant, renderer: &JsonRenderer<'_>) -> Self {
use clean::VariantKind::*;
let discriminant = variant.discriminant.map(|d| d.into_json(renderer));
let discriminant = variant.discriminant.as_ref().map(|d| d.into_json(renderer));
let kind = match variant.kind {
let kind = match &variant.kind {
CLike => VariantKind::Plain,
Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)),
Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(&fields)),
Struct(s) => VariantKind::Struct {
has_stripped_fields: s.has_stripped_entries(),
fields: renderer.ids(s.fields),
fields: renderer.ids(&s.fields),
},
};
@ -743,7 +751,7 @@ impl FromClean<clean::Variant> for Variant {
}
impl FromClean<clean::Discriminant> for Discriminant {
fn from_clean(disr: clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(disr: &clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self {
let tcx = renderer.tcx;
Discriminant {
// expr is only none if going through the inlining path, which gets
@ -756,7 +764,7 @@ impl FromClean<clean::Discriminant> for Discriminant {
}
impl FromClean<clean::Import> for Use {
fn from_clean(import: clean::Import, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(import: &clean::Import, renderer: &JsonRenderer<'_>) -> Self {
use clean::ImportKind::*;
let (name, is_glob) = match import.kind {
Simple(s) => (s.to_string(), false),
@ -775,7 +783,7 @@ impl FromClean<clean::Import> for Use {
}
impl FromClean<clean::ProcMacro> for ProcMacro {
fn from_clean(mac: clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(mac: &clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self {
ProcMacro {
kind: from_macro_kind(mac.kind),
helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
@ -792,21 +800,21 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind
}
}
impl FromClean<Box<clean::TypeAlias>> for TypeAlias {
fn from_clean(type_alias: Box<clean::TypeAlias>, renderer: &JsonRenderer<'_>) -> Self {
let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = *type_alias;
impl FromClean<clean::TypeAlias> for TypeAlias {
fn from_clean(type_alias: &clean::TypeAlias, renderer: &JsonRenderer<'_>) -> Self {
let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = type_alias;
TypeAlias { type_: type_.into_json(renderer), generics: generics.into_json(renderer) }
}
}
fn convert_static(
stat: clean::Static,
safety: rustc_hir::Safety,
stat: &clean::Static,
safety: &rustc_hir::Safety,
renderer: &JsonRenderer<'_>,
) -> Static {
let tcx = renderer.tcx;
Static {
type_: (*stat.type_).into_json(renderer),
type_: stat.type_.as_ref().into_json(renderer),
is_mutable: stat.mutability == ast::Mutability::Mut,
is_unsafe: safety.is_unsafe(),
expr: stat
@ -817,7 +825,7 @@ fn convert_static(
}
impl FromClean<clean::TraitAlias> for TraitAlias {
fn from_clean(alias: clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(alias: &clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self {
TraitAlias {
generics: alias.generics.into_json(renderer),
params: alias.bounds.into_json(renderer),
@ -826,7 +834,7 @@ impl FromClean<clean::TraitAlias> for TraitAlias {
}
impl FromClean<ItemType> for ItemKind {
fn from_clean(kind: ItemType, _renderer: &JsonRenderer<'_>) -> Self {
fn from_clean(kind: &ItemType, _renderer: &JsonRenderer<'_>) -> Self {
use ItemType::*;
match kind {
Module => ItemKind::Module,

View file

@ -64,7 +64,7 @@ impl<'tcx> JsonRenderer<'tcx> {
.iter()
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
self.item(item).unwrap();
self.id_from_item(item)
})
.collect()
@ -95,7 +95,7 @@ impl<'tcx> JsonRenderer<'tcx> {
}
if item.item_id.is_local() || is_primitive_impl {
self.item(item.clone()).unwrap();
self.item(item).unwrap();
Some(self.id_from_item(item))
} else {
None
@ -216,7 +216,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
/// Inserts an item into the index. This should be used rather than directly calling insert on
/// the hashmap because certain items (traits and types) need to have their mappings for trait
/// implementations filled out before they're inserted.
fn item(&mut self, item: clean::Item) -> Result<(), Error> {
fn item(&mut self, item: &clean::Item) -> Result<(), Error> {
let item_type = item.type_();
let item_name = item.name;
trace!("rendering {item_type} {item_name:?}");
@ -224,11 +224,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
// Flatten items that recursively store other items. We include orphaned items from
// stripped modules and etc that are otherwise reachable.
if let ItemKind::StrippedItem(inner) = &item.kind {
inner.inner_items().for_each(|i| self.item(i.clone()).unwrap());
inner.inner_items().for_each(|i| self.item(i).unwrap());
}
// Flatten items that recursively store other items
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
item.kind.inner_items().for_each(|i| self.item(i).unwrap());
let item_id = item.item_id;
if let Some(mut new_item) = self.convert_item(item) {