1
Fork 0

Rework rustdoc const type

This commit is contained in:
Guillaume Gomez 2021-03-07 18:09:35 +01:00
parent f5fe425c92
commit 0cde85523f
11 changed files with 812 additions and 615 deletions

View file

@ -9,7 +9,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_hir::Mutability;
use rustc_metadata::creader::LoadedMacro;
use rustc_middle::ty;
use rustc_middle::ty::{self, TyCtxt};
use rustc_mir::const_eval::is_min_const_fn;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
@ -490,24 +490,17 @@ fn build_module(
clean::Module { items, is_crate: false }
}
crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
crate fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
if let Some(did) = did.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did);
rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id)
let hir_id = tcx.hir().local_def_id_to_hir_id(did);
rustc_hir_pretty::id_to_string(&tcx.hir(), hir_id)
} else {
cx.tcx.rendered_const(did)
tcx.rendered_const(did)
}
}
fn build_const(cx: &mut DocContext<'_>, did: DefId) -> clean::Constant {
clean::Constant {
type_: cx.tcx.type_of(did).clean(cx),
expr: print_inlined_const(cx, did),
value: clean::utils::print_evaluated_const(cx, did),
is_literal: did.as_local().map_or(false, |did| {
clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did))
}),
}
clean::Constant::Inline { type_: cx.tcx.type_of(did).clean(cx), did }
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {

View file

@ -393,14 +393,12 @@ impl Clean<Lifetime> for hir::GenericParam<'_> {
impl Clean<Constant> for hir::ConstArg {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
Constant::Generic {
type_: cx
.tcx
.type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
.clean(cx),
expr: print_const_expr(cx.tcx, self.value.body),
value: None,
is_literal: is_literal_expr(cx, self.value.body.hir_id),
body: self.value.body,
}
}
}
@ -1135,7 +1133,7 @@ impl Clean<Item> for ty::AssocItem {
ty::AssocKind::Const => {
let ty = tcx.type_of(self.def_id);
let default = if self.defaultness.has_value() {
Some(inline::print_inlined_const(cx, self.def_id))
Some(inline::print_inlined_const(cx.tcx, self.def_id))
} else {
None
};
@ -1745,12 +1743,8 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: format!("{}", self),
value: None,
is_literal: false,
}
// FIXME: instead of storing `format!("{}", self)`, store `self` directly instead.
Constant::TyConst { type_: self.ty.clean(cx), expr: format!("{}", self) }
}
}
@ -1951,11 +1945,10 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
}
ItemKind::Const(ty, body_id) => ConstantItem(Constant {
ItemKind::Const(ty, body_id) => ConstantItem(Constant::Const {
type_: ty.clean(cx),
expr: print_const_expr(cx.tcx, body_id),
value: print_evaluated_const(cx, def_id),
is_literal: is_literal_expr(cx, body_id.hir_id),
body: body_id,
did: def_id,
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
bounds: ty.bounds.clean(cx),

View file

@ -32,8 +32,9 @@ use rustc_target::spec::abi::Abi;
use crate::clean::cfg::Cfg;
use crate::clean::external_path;
use crate::clean::inline;
use crate::clean::inline::{self, print_inlined_const};
use crate::clean::types::Type::{QPath, ResolvedPath};
use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const};
use crate::clean::Clean;
use crate::core::DocContext;
use crate::formats::cache::Cache;
@ -1986,11 +1987,64 @@ crate struct Static {
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
crate struct Constant {
crate type_: Type,
crate expr: String,
crate value: Option<String>,
crate is_literal: bool,
crate enum Constant {
/// Typed constant value.
TyConst { type_: Type, expr: String },
/// A constant (expression) thats not an item or associated item. These are usually found
/// nested inside types (e.g., array lengths) or expressions (e.g., repeat counts), and also
/// used to define explicit discriminant values for enum variants.
Generic { type_: Type, body: BodyId },
/// Inlined constant (from another crate).
Inline { type_: Type, did: DefId },
/// const FOO: u32 = ...;
Const { type_: Type, did: DefId, body: BodyId },
}
impl Constant {
crate fn expr(&self, tcx: TyCtxt<'_>) -> String {
match self {
Self::TyConst { expr, .. } => expr.clone(),
Self::Inline { did, .. } => print_inlined_const(tcx, *did),
Self::Const { body, .. } | Self::Generic { body, .. } => print_const_expr(tcx, *body),
}
}
crate fn value(&self, tcx: TyCtxt<'_>) -> Option<String> {
match self {
Self::TyConst { .. } | Self::Generic { .. } => None,
Self::Inline { did, .. } | Self::Const { did, .. } => print_evaluated_const(tcx, *did),
}
}
crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
match self {
Self::TyConst { .. } => false,
Self::Inline { did, .. } => did
.as_local()
.map_or(false, |did| is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(did))),
Self::Const { body, .. } | Self::Generic { body, .. } => {
is_literal_expr(tcx, body.hir_id)
}
}
}
crate fn type_(&self) -> &Type {
match *self {
Self::TyConst { ref type_, .. }
| Self::Inline { ref type_, .. }
| Self::Const { ref type_, .. }
| Self::Generic { ref type_, .. } => type_,
}
}
crate fn to_type(self) -> Type {
match self {
Self::TyConst { type_, .. }
| Self::Inline { type_, .. }
| Self::Const { type_, .. }
| Self::Generic { type_, .. } => type_,
}
}
}
#[derive(Clone, Debug)]

View file

@ -301,7 +301,7 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
} else {
inline::print_inlined_const(cx, def.did)
inline::print_inlined_const(cx.tcx, def.did)
};
if let Some(promoted) = promoted {
s.push_str(&format!("::{:?}", promoted))
@ -324,15 +324,15 @@ crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
}
}
crate fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
cx.tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = cx.tcx.type_of(def_id);
crate fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
let ty = tcx.type_of(def_id);
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(ConstValue::Scalar(_), _) => {
let const_ = ty::Const::from_value(cx.tcx, val, ty);
Some(print_const_with_custom_print_scalar(cx, const_))
let const_ = ty::Const::from_value(tcx, val, ty);
Some(print_const_with_custom_print_scalar(tcx, const_))
}
_ => None,
}
@ -349,7 +349,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
.collect()
}
fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
// Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`.
match (ct.val, ct.ty.kind()) {
@ -357,8 +357,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
}
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
let ty = cx.tcx.lift(ct.ty).unwrap();
let size = cx.tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let ty = tcx.lift(ct.ty).unwrap();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);
let sign_extended_data = size.sign_extend(data) as i128;
@ -372,8 +372,8 @@ fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const
}
}
crate fn is_literal_expr(cx: &DocContext<'_>, hir_id: hir::HirId) -> bool {
if let hir::Node::Expr(expr) = cx.tcx.hir().get(hir_id) {
crate fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
if let hir::Node::Expr(expr) = tcx.hir().get(hir_id) {
if let hir::ExprKind::Lit(_) = &expr.kind {
return true;
}
@ -411,7 +411,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
return Generic(kw::SelfUpper);
}
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, cx.tcx))));
}
Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
_ => false,

View file

@ -5,10 +5,10 @@
//! assume that HTML output is desired, although it may be possible to redesign
//! them in the future to instead emit any format desired.
use std::borrow::Cow;
use std::cell::Cell;
use std::fmt;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_middle::ty::TyCtxt;
@ -111,31 +111,6 @@ impl Buffer {
}
}
/// Wrapper struct for properly emitting a function or method declaration.
crate struct Function<'a> {
/// The declaration to emit.
crate decl: &'a clean::FnDecl,
/// The length of the function header and name. In other words, the number of characters in the
/// function declaration up to but not including the parentheses.
///
/// Used to determine line-wrapping.
crate header_len: usize,
/// The number of spaces to indent each successive line with, if line-wrapping is necessary.
crate indent: usize,
/// Whether the function is async or not.
crate asyncness: hir::IsAsync,
}
/// Wrapper struct for emitting a where-clause from Generics.
crate struct WhereClause<'a> {
/// The Generics from which to emit a where-clause.
crate gens: &'a clean::Generics,
/// The number of spaces to indent each line with.
crate indent: usize,
/// Whether the where-clause needs to add a comma and newline after the last bound.
crate end_newline: bool,
}
fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Display {
display_fn(move |f| {
for (i, item) in items.enumerate() {
@ -148,27 +123,32 @@ fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Displ
})
}
crate fn print_generic_bounds<'a>(
crate fn print_generic_bounds<'a, 'tcx: 'a>(
bounds: &'a [clean::GenericBound],
cache: &'a Cache,
) -> impl fmt::Display + 'a {
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
let mut bounds_dup = FxHashSet::default();
for (i, bound) in
bounds.iter().filter(|b| bounds_dup.insert(b.print(cache).to_string())).enumerate()
bounds.iter().filter(|b| bounds_dup.insert(b.print(cache, tcx).to_string())).enumerate()
{
if i > 0 {
f.write_str(" + ")?;
}
fmt::Display::fmt(&bound.print(cache), f)?;
fmt::Display::fmt(&bound.print(cache, tcx), f)?;
}
Ok(())
})
}
impl clean::GenericParamDef {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| match self.kind {
clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
@ -176,17 +156,17 @@ impl clean::GenericParamDef {
if !bounds.is_empty() {
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
write!(f, ": {:#}", print_generic_bounds(bounds, cache, tcx))?;
} else {
write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, tcx))?;
}
}
if let Some(ref ty) = default {
if f.alternate() {
write!(f, " = {:#}", ty.print(cache))?;
write!(f, " = {:#}", ty.print(cache, tcx))?;
} else {
write!(f, "&nbsp;=&nbsp;{}", ty.print(cache))?;
write!(f, "&nbsp;=&nbsp;{}", ty.print(cache, tcx))?;
}
}
@ -194,9 +174,9 @@ impl clean::GenericParamDef {
}
clean::GenericParamDefKind::Const { ref ty, .. } => {
if f.alternate() {
write!(f, "const {}: {:#}", self.name, ty.print(cache))
write!(f, "const {}: {:#}", self.name, ty.print(cache, tcx))
} else {
write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache))
write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache, tcx))
}
}
})
@ -204,7 +184,11 @@ impl clean::GenericParamDef {
}
impl clean::Generics {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
let real_params =
self.params.iter().filter(|p| !p.is_synthetic_type_param()).collect::<Vec<_>>();
@ -212,18 +196,25 @@ impl clean::Generics {
return Ok(());
}
if f.alternate() {
write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache))))
write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache, tcx))))
} else {
write!(f, "&lt;{}&gt;", comma_sep(real_params.iter().map(|g| g.print(cache))))
write!(f, "&lt;{}&gt;", comma_sep(real_params.iter().map(|g| g.print(cache, tcx))))
}
})
}
}
impl<'a> WhereClause<'a> {
crate fn print<'b>(&'b self, cache: &'b Cache) -> impl fmt::Display + 'b {
/// * The Generics from which to emit a where-clause.
/// * The number of spaces to indent each line with.
/// * Whether the where-clause needs to add a comma and newline after the last bound.
crate fn print_where_clause<'a, 'tcx: 'a>(
gens: &'a clean::Generics,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
indent: usize,
end_newline: bool,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
let &WhereClause { gens, indent, end_newline } = self;
if gens.where_predicates.is_empty() {
return Ok(());
}
@ -250,14 +241,14 @@ impl<'a> WhereClause<'a> {
if f.alternate() {
clause.push_str(&format!(
"{:#}: {:#}",
ty.print(cache),
print_generic_bounds(bounds, cache)
ty.print(cache, tcx),
print_generic_bounds(bounds, cache, tcx)
));
} else {
clause.push_str(&format!(
"{}: {}",
ty.print(cache),
print_generic_bounds(bounds, cache)
ty.print(cache, tcx),
print_generic_bounds(bounds, cache, tcx)
));
}
}
@ -267,7 +258,7 @@ impl<'a> WhereClause<'a> {
lifetime.print(),
bounds
.iter()
.map(|b| b.print(cache).to_string())
.map(|b| b.print(cache, tcx).to_string())
.collect::<Vec<_>>()
.join(" + ")
));
@ -276,14 +267,14 @@ impl<'a> WhereClause<'a> {
if f.alternate() {
clause.push_str(&format!(
"{:#} == {:#}",
lhs.print(cache),
rhs.print(cache)
lhs.print(cache, tcx),
rhs.print(cache, tcx),
));
} else {
clause.push_str(&format!(
"{} == {}",
lhs.print(cache),
rhs.print(cache)
lhs.print(cache, tcx),
rhs.print(cache, tcx),
));
}
}
@ -314,7 +305,6 @@ impl<'a> WhereClause<'a> {
}
write!(f, "{}", clause)
})
}
}
impl clean::Lifetime {
@ -324,46 +314,53 @@ impl clean::Lifetime {
}
impl clean::Constant {
crate fn print(&self) -> impl fmt::Display + '_ {
display_fn(move |f| {
if f.alternate() {
f.write_str(&self.expr)
} else {
write!(f, "{}", Escape(&self.expr))
}
})
crate fn print(&self, tcx: TyCtxt<'_>) -> impl fmt::Display + '_ {
let expr = self.expr(tcx);
display_fn(
move |f| {
if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) }
},
)
}
}
impl clean::PolyTrait {
fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
if !self.generic_params.is_empty() {
if f.alternate() {
write!(
f,
"for<{:#}> ",
comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
)?;
} else {
write!(
f,
"for&lt;{}&gt; ",
comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
)?;
}
}
if f.alternate() {
write!(f, "{:#}", self.trait_.print(cache))
write!(f, "{:#}", self.trait_.print(cache, tcx))
} else {
write!(f, "{}", self.trait_.print(cache))
write!(f, "{}", self.trait_.print(cache, tcx))
}
})
}
}
impl clean::GenericBound {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| match self {
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
clean::GenericBound::TraitBound(ty, modifier) => {
@ -373,9 +370,9 @@ impl clean::GenericBound {
hir::TraitBoundModifier::MaybeConst => "?const",
};
if f.alternate() {
write!(f, "{}{:#}", modifier_str, ty.print(cache))
write!(f, "{}{:#}", modifier_str, ty.print(cache, tcx))
} else {
write!(f, "{}{}", modifier_str, ty.print(cache))
write!(f, "{}{}", modifier_str, ty.print(cache, tcx))
}
}
})
@ -383,7 +380,11 @@ impl clean::GenericBound {
}
impl clean::GenericArgs {
fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
match self {
clean::GenericArgs::AngleBracketed { args, bindings } => {
@ -400,9 +401,9 @@ impl clean::GenericArgs {
}
comma = true;
if f.alternate() {
write!(f, "{:#}", arg.print(cache))?;
write!(f, "{:#}", arg.print(cache, tcx))?;
} else {
write!(f, "{}", arg.print(cache))?;
write!(f, "{}", arg.print(cache, tcx))?;
}
}
for binding in bindings {
@ -411,9 +412,9 @@ impl clean::GenericArgs {
}
comma = true;
if f.alternate() {
write!(f, "{:#}", binding.print(cache))?;
write!(f, "{:#}", binding.print(cache, tcx))?;
} else {
write!(f, "{}", binding.print(cache))?;
write!(f, "{}", binding.print(cache, tcx))?;
}
}
if f.alternate() {
@ -432,17 +433,17 @@ impl clean::GenericArgs {
}
comma = true;
if f.alternate() {
write!(f, "{:#}", ty.print(cache))?;
write!(f, "{:#}", ty.print(cache, tcx))?;
} else {
write!(f, "{}", ty.print(cache))?;
write!(f, "{}", ty.print(cache, tcx))?;
}
}
f.write_str(")")?;
if let Some(ref ty) = *output {
if f.alternate() {
write!(f, " -> {:#}", ty.print(cache))?;
write!(f, " -> {:#}", ty.print(cache, tcx))?;
} else {
write!(f, " -&gt; {}", ty.print(cache))?;
write!(f, " -&gt; {}", ty.print(cache, tcx))?;
}
}
}
@ -453,19 +454,27 @@ impl clean::GenericArgs {
}
impl clean::PathSegment {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
if f.alternate() {
write!(f, "{}{:#}", self.name, self.args.print(cache))
write!(f, "{}{:#}", self.name, self.args.print(cache, tcx))
} else {
write!(f, "{}{}", self.name, self.args.print(cache))
write!(f, "{}{}", self.name, self.args.print(cache, tcx))
}
})
}
}
impl clean::Path {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
if self.global {
f.write_str("::")?
@ -476,9 +485,9 @@ impl clean::Path {
f.write_str("::")?
}
if f.alternate() {
write!(f, "{:#}", seg.print(cache))?;
write!(f, "{:#}", seg.print(cache, tcx))?;
} else {
write!(f, "{}", seg.print(cache))?;
write!(f, "{}", seg.print(cache, tcx))?;
}
}
Ok(())
@ -528,13 +537,14 @@ crate fn href(did: DefId, cache: &Cache) -> Option<(String, ItemType, Vec<String
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(
fn resolved_path<'a, 'tcx: 'a>(
w: &mut fmt::Formatter<'_>,
did: DefId,
path: &clean::Path,
print_all: bool,
use_absolute: bool,
cache: &Cache,
tcx: TyCtxt<'tcx>,
) -> fmt::Result {
let last = path.segments.last().unwrap();
@ -544,7 +554,7 @@ fn resolved_path(
}
}
if w.alternate() {
write!(w, "{}{:#}", &last.name, last.args.print(cache))?;
write!(w, "{}{:#}", &last.name, last.args.print(cache, tcx))?;
} else {
let path = if use_absolute {
if let Some((_, _, fqp)) = href(did, cache) {
@ -559,7 +569,7 @@ fn resolved_path(
} else {
anchor(did, &*last.name.as_str(), cache).to_string()
};
write!(w, "{}{}", path, last.args.print(cache))?;
write!(w, "{}{}", path, last.args.print(cache, tcx))?;
}
Ok(())
}
@ -615,15 +625,16 @@ fn primitive_link(
}
/// Helper to render type parameters
fn tybounds<'a>(
fn tybounds<'a, 'tcx: 'a>(
param_names: &'a Option<Vec<clean::GenericBound>>,
cache: &'a Cache,
) -> impl fmt::Display + 'a {
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| match *param_names {
Some(ref params) => {
for param in params {
write!(f, " + ")?;
fmt::Display::fmt(&param.print(cache), f)?;
fmt::Display::fmt(&param.print(cache, tcx), f)?;
}
Ok(())
}
@ -654,6 +665,7 @@ fn fmt_type(
f: &mut fmt::Formatter<'_>,
use_absolute: bool,
cache: &Cache,
tcx: TyCtxt<'_>,
) -> fmt::Result {
debug!("fmt_type(t = {:?})", t);
@ -664,8 +676,8 @@ fn fmt_type(
f.write_str("dyn ")?;
}
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
resolved_path(f, did, path, is_generic, use_absolute, cache)?;
fmt::Display::fmt(&tybounds(param_names, cache), f)
resolved_path(f, did, path, is_generic, use_absolute, cache, tcx)?;
fmt::Display::fmt(&tybounds(param_names, cache, tcx), f)
}
clean::Infer => write!(f, "_"),
clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache),
@ -674,21 +686,21 @@ fn fmt_type(
write!(
f,
"{:#}{}{:#}fn{:#}",
decl.print_hrtb_with_space(cache),
decl.print_hrtb_with_space(cache, tcx),
decl.unsafety.print_with_space(),
print_abi_with_space(decl.abi),
decl.decl.print(cache)
decl.decl.print(cache, tcx),
)
} else {
write!(
f,
"{}{}{}",
decl.print_hrtb_with_space(cache),
decl.print_hrtb_with_space(cache, tcx),
decl.unsafety.print_with_space(),
print_abi_with_space(decl.abi)
)?;
primitive_link(f, PrimitiveType::Fn, "fn", cache)?;
write!(f, "{}", decl.decl.print(cache))
write!(f, "{}", decl.decl.print(cache, tcx))
}
}
clean::Tuple(ref typs) => {
@ -697,7 +709,7 @@ fn fmt_type(
&[ref one] => {
primitive_link(f, PrimitiveType::Tuple, "(", cache)?;
// Carry `f.alternate()` into this display w/o branching manually.
fmt::Display::fmt(&one.print(cache), f)?;
fmt::Display::fmt(&one.print(cache, tcx), f)?;
primitive_link(f, PrimitiveType::Tuple, ",)", cache)
}
many => {
@ -706,7 +718,7 @@ fn fmt_type(
if i != 0 {
write!(f, ", ")?;
}
fmt::Display::fmt(&item.print(cache), f)?;
fmt::Display::fmt(&item.print(cache, tcx), f)?;
}
primitive_link(f, PrimitiveType::Tuple, ")", cache)
}
@ -714,12 +726,12 @@ fn fmt_type(
}
clean::Slice(ref t) => {
primitive_link(f, PrimitiveType::Slice, "[", cache)?;
fmt::Display::fmt(&t.print(cache), f)?;
fmt::Display::fmt(&t.print(cache, tcx), f)?;
primitive_link(f, PrimitiveType::Slice, "]", cache)
}
clean::Array(ref t, ref n) => {
primitive_link(f, PrimitiveType::Array, "[", cache)?;
fmt::Display::fmt(&t.print(cache), f)?;
fmt::Display::fmt(&t.print(cache, tcx), f)?;
if f.alternate() {
primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache)
} else {
@ -738,14 +750,14 @@ fn fmt_type(
primitive_link(
f,
clean::PrimitiveType::RawPointer,
&format!("*{} {:#}", m, t.print(cache)),
&format!("*{} {:#}", m, t.print(cache, tcx)),
cache,
)
} else {
primitive_link(
f,
clean::PrimitiveType::RawPointer,
&format!("*{} {}", m, t.print(cache)),
&format!("*{} {}", m, t.print(cache, tcx)),
cache,
)
}
@ -757,7 +769,7 @@ fn fmt_type(
&format!("*{} ", m),
cache,
)?;
fmt::Display::fmt(&t.print(cache), f)
fmt::Display::fmt(&t.print(cache, tcx), f)
}
}
}
@ -777,14 +789,14 @@ fn fmt_type(
primitive_link(
f,
PrimitiveType::Slice,
&format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache)),
&format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache, tcx)),
cache,
)
} else {
primitive_link(
f,
PrimitiveType::Slice,
&format!("{}{}{}[{}]", amp, lt, m, bt.print(cache)),
&format!("{}{}{}[{}]", amp, lt, m, bt.print(cache, tcx)),
cache,
)
}
@ -797,9 +809,9 @@ fn fmt_type(
cache,
)?;
if f.alternate() {
write!(f, "{:#}", bt.print(cache))?;
write!(f, "{:#}", bt.print(cache, tcx))?;
} else {
write!(f, "{}", bt.print(cache))?;
write!(f, "{}", bt.print(cache, tcx))?;
}
primitive_link(f, PrimitiveType::Slice, "]", cache)
}
@ -807,7 +819,7 @@ fn fmt_type(
}
clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
write!(f, "{}{}{}(", amp, lt, m)?;
fmt_type(&ty, f, use_absolute, cache)?;
fmt_type(&ty, f, use_absolute, cache, tcx)?;
write!(f, ")")
}
clean::Generic(..) => {
@ -817,19 +829,19 @@ fn fmt_type(
&format!("{}{}{}", amp, lt, m),
cache,
)?;
fmt_type(&ty, f, use_absolute, cache)
fmt_type(&ty, f, use_absolute, cache, tcx)
}
_ => {
write!(f, "{}{}{}", amp, lt, m)?;
fmt_type(&ty, f, use_absolute, cache)
fmt_type(&ty, f, use_absolute, cache, tcx)
}
}
}
clean::ImplTrait(ref bounds) => {
if f.alternate() {
write!(f, "impl {:#}", print_generic_bounds(bounds, cache))
write!(f, "impl {:#}", print_generic_bounds(bounds, cache, tcx))
} else {
write!(f, "impl {}", print_generic_bounds(bounds, cache))
write!(f, "impl {}", print_generic_bounds(bounds, cache, tcx))
}
}
clean::QPath { ref name, ref self_type, ref trait_ } => {
@ -841,15 +853,25 @@ fn fmt_type(
};
if f.alternate() {
if should_show_cast {
write!(f, "<{:#} as {:#}>::", self_type.print(cache), trait_.print(cache))?
write!(
f,
"<{:#} as {:#}>::",
self_type.print(cache, tcx),
trait_.print(cache, tcx)
)?
} else {
write!(f, "{:#}::", self_type.print(cache))?
write!(f, "{:#}::", self_type.print(cache, tcx))?
}
} else {
if should_show_cast {
write!(f, "&lt;{} as {}&gt;::", self_type.print(cache), trait_.print(cache))?
write!(
f,
"&lt;{} as {}&gt;::",
self_type.print(cache, tcx),
trait_.print(cache, tcx)
)?
} else {
write!(f, "{}::", self_type.print(cache))?
write!(f, "{}::", self_type.print(cache, tcx))?
}
};
match *trait_ {
@ -890,52 +912,64 @@ fn fmt_type(
}
impl clean::Type {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
display_fn(move |f| fmt_type(self, f, false, cache))
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| fmt_type(self, f, false, cache, tcx))
}
}
impl clean::Impl {
crate fn print<'a>(&'a self, cache: &'a Cache, use_absolute: bool) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
use_absolute: bool,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
if f.alternate() {
write!(f, "impl{:#} ", self.generics.print(cache))?;
write!(f, "impl{:#} ", self.generics.print(cache, tcx))?;
} else {
write!(f, "impl{} ", self.generics.print(cache))?;
write!(f, "impl{} ", self.generics.print(cache, tcx))?;
}
if let Some(ref ty) = self.trait_ {
if self.negative_polarity {
write!(f, "!")?;
}
fmt::Display::fmt(&ty.print(cache), f)?;
fmt::Display::fmt(&ty.print(cache, tcx), f)?;
write!(f, " for ")?;
}
if let Some(ref ty) = self.blanket_impl {
fmt_type(ty, f, use_absolute, cache)?;
fmt_type(ty, f, use_absolute, cache, tcx)?;
} else {
fmt_type(&self.for_, f, use_absolute, cache)?;
fmt_type(&self.for_, f, use_absolute, cache, tcx)?;
}
let where_clause = WhereClause { gens: &self.generics, indent: 0, end_newline: true };
fmt::Display::fmt(&where_clause.print(cache), f)?;
fmt::Display::fmt(&print_where_clause(&self.generics, cache, tcx, 0, true), f)?;
Ok(())
})
}
}
impl clean::Arguments {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
for (i, input) in self.values.iter().enumerate() {
if !input.name.is_empty() {
write!(f, "{}: ", input.name)?;
}
if f.alternate() {
write!(f, "{:#}", input.type_.print(cache))?;
write!(f, "{:#}", input.type_.print(cache, tcx))?;
} else {
write!(f, "{}", input.type_.print(cache))?;
write!(f, "{}", input.type_.print(cache, tcx))?;
}
if i + 1 < self.values.len() {
write!(f, ", ")?;
@ -947,21 +981,33 @@ impl clean::Arguments {
}
impl clean::FnRetTy {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| match self {
clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()),
clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache)),
clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache)),
clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache, tcx)),
clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache, tcx)),
clean::DefaultReturn => Ok(()),
})
}
}
impl clean::BareFunctionDecl {
fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
fn print_hrtb_with_space<'a, 'tcx: 'a>(
&'a self,
cache: &'a Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
display_fn(move |f| {
if !self.generic_params.is_empty() {
write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache))))
write!(
f,
"for<{}> ",
comma_sep(self.generic_params.iter().map(|g| g.print(cache, tcx)))
)
} else {
Ok(())
}
@ -970,38 +1016,63 @@ impl clean::BareFunctionDecl {
}
impl clean::FnDecl {
crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| {
let ellipsis = if self.c_variadic { ", ..." } else { "" };
if f.alternate() {
write!(
f,
"({args:#}{ellipsis}){arrow:#}",
args = self.inputs.print(cache),
args = self.inputs.print(cache, tcx),
ellipsis = ellipsis,
arrow = self.output.print(cache)
arrow = self.output.print(cache, tcx)
)
} else {
write!(
f,
"({args}{ellipsis}){arrow}",
args = self.inputs.print(cache),
args = self.inputs.print(cache, tcx),
ellipsis = ellipsis,
arrow = self.output.print(cache)
arrow = self.output.print(cache, tcx)
)
}
})
}
}
impl Function<'_> {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
display_fn(move |f| {
let &Function { decl, header_len, indent, asyncness } = self;
/// * `header_len`: The length of the function header and name. In other words, the number of
/// characters in the function declaration up to but not including the parentheses.
/// <br>Used to determine line-wrapping.
/// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
/// necessary.
/// * `asyncness`: Whether the function is async or not.
crate fn full_print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
header_len: usize,
indent: usize,
asyncness: hir::IsAsync,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| self.inner_full_print(cache, tcx, header_len, indent, asyncness, f))
}
fn inner_full_print(
&self,
cache: &Cache,
tcx: TyCtxt<'_>,
header_len: usize,
indent: usize,
asyncness: hir::IsAsync,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
let amp = if f.alternate() { "&" } else { "&amp;" };
let mut args = String::new();
let mut args_plain = String::new();
for (i, input) in decl.inputs.values.iter().enumerate() {
for (i, input) in self.inputs.values.iter().enumerate() {
if i == 0 {
args.push_str("<br>");
}
@ -1031,11 +1102,11 @@ impl Function<'_> {
}
clean::SelfExplicit(ref typ) => {
if f.alternate() {
args.push_str(&format!("self: {:#}", typ.print(cache)));
args.push_str(&format!("self: {:#}", typ.print(cache, tcx)));
} else {
args.push_str(&format!("self: {}", typ.print(cache)));
args.push_str(&format!("self: {}", typ.print(cache, tcx)));
}
args_plain.push_str(&format!("self: {:#}", typ.print(cache)));
args_plain.push_str(&format!("self: {:#}", typ.print(cache, tcx)));
}
}
} else {
@ -1049,13 +1120,13 @@ impl Function<'_> {
}
if f.alternate() {
args.push_str(&format!("{:#}", input.type_.print(cache)));
args.push_str(&format!("{:#}", input.type_.print(cache, tcx)));
} else {
args.push_str(&input.type_.print(cache).to_string());
args.push_str(&input.type_.print(cache, tcx).to_string());
}
args_plain.push_str(&format!("{:#}", input.type_.print(cache)));
args_plain.push_str(&format!("{:#}", input.type_.print(cache, tcx)));
}
if i + 1 < decl.inputs.values.len() {
if i + 1 < self.inputs.values.len() {
args.push(',');
args_plain.push(',');
}
@ -1063,22 +1134,27 @@ impl Function<'_> {
let mut args_plain = format!("({})", args_plain);
if decl.c_variadic {
if self.c_variadic {
args.push_str(",<br> ...");
args_plain.push_str(", ...");
}
let output = if let hir::IsAsync::Async = asyncness {
Cow::Owned(decl.sugared_async_return_type())
let arrow_plain;
let arrow = if let hir::IsAsync::Async = asyncness {
let output = self.sugared_async_return_type();
arrow_plain = format!("{:#}", output.print(cache, tcx));
if f.alternate() {
arrow_plain.clone()
} else {
Cow::Borrowed(&decl.output)
};
let arrow_plain = format!("{:#}", &output.print(cache));
let arrow = if f.alternate() {
format!("{:#}", &output.print(cache))
format!("{}", output.print(cache, tcx))
}
} else {
output.print(cache).to_string()
arrow_plain = format!("{:#}", self.output.print(cache, tcx));
if f.alternate() {
arrow_plain.clone()
} else {
format!("{}", self.output.print(cache, tcx))
}
};
let declaration_len = header_len + args_plain.len() + arrow_plain.len();
@ -1100,17 +1176,16 @@ impl Function<'_> {
} else {
write!(f, "{}", output)
}
})
}
}
impl clean::Visibility {
crate fn print_with_space<'tcx>(
crate fn print_with_space<'a, 'tcx: 'a>(
self,
tcx: TyCtxt<'tcx>,
item_did: DefId,
cache: &Cache,
) -> impl fmt::Display + 'tcx {
cache: &'a Cache,
) -> impl fmt::Display + 'a + Captures<'tcx> {
use rustc_span::symbol::kw;
let to_print = match self {
@ -1202,20 +1277,24 @@ impl PrintWithSpace for hir::Mutability {
}
impl clean::Import {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| match self.kind {
clean::ImportKind::Simple(name) => {
if name == self.source.path.last() {
write!(f, "use {};", self.source.print(cache))
write!(f, "use {};", self.source.print(cache, tcx))
} else {
write!(f, "use {} as {};", self.source.print(cache), name)
write!(f, "use {} as {};", self.source.print(cache, tcx), name)
}
}
clean::ImportKind::Glob => {
if self.source.path.segments.is_empty() {
write!(f, "use *;")
} else {
write!(f, "use {}::*;", self.source.print(cache))
write!(f, "use {}::*;", self.source.print(cache, tcx))
}
}
})
@ -1223,9 +1302,13 @@ impl clean::Import {
}
impl clean::ImportSource {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| match self.did {
Some(did) => resolved_path(f, did, &self.path, true, false, cache),
Some(did) => resolved_path(f, did, &self.path, true, false, cache, tcx),
_ => {
for seg in &self.path.segments[..self.path.segments.len() - 1] {
write!(f, "{}::", seg.name)?;
@ -1243,23 +1326,27 @@ impl clean::ImportSource {
}
impl clean::TypeBinding {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| {
f.write_str(&*self.name.as_str())?;
match self.kind {
clean::TypeBindingKind::Equality { ref ty } => {
if f.alternate() {
write!(f, " = {:#}", ty.print(cache))?;
write!(f, " = {:#}", ty.print(cache, tcx))?;
} else {
write!(f, " = {}", ty.print(cache))?;
write!(f, " = {}", ty.print(cache, tcx))?;
}
}
clean::TypeBindingKind::Constraint { ref bounds } => {
if !bounds.is_empty() {
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
write!(f, ": {:#}", print_generic_bounds(bounds, cache, tcx))?;
} else {
write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, tcx))?;
}
}
}
@ -1284,11 +1371,15 @@ crate fn print_default_space<'a>(v: bool) -> &'a str {
}
impl clean::GenericArg {
crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
crate fn print<'b, 'a: 'b, 'tcx: 'a>(
&'a self,
cache: &'b Cache,
tcx: TyCtxt<'tcx>,
) -> impl fmt::Display + 'b + Captures<'tcx> {
display_fn(move |f| match self {
clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(&lt.print(), f),
clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache), f),
clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f),
clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache, tcx), f),
clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(tcx), f),
})
}
}

View file

@ -67,8 +67,8 @@ use crate::formats::item_type::ItemType;
use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode};
use crate::html::escape::Escape;
use crate::html::format::{
href, print_abi_with_space, print_default_space, print_generic_bounds, Buffer, Function,
PrintWithSpace, WhereClause,
href, print_abi_with_space, print_default_space, print_generic_bounds, print_where_clause,
Buffer, PrintWithSpace,
};
use crate::html::layout;
use crate::html::markdown::{self, ErrorCodes, Markdown, MarkdownHtml, MarkdownSummaryLine};
@ -918,7 +918,7 @@ fn assoc_const(
it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
naive_assoc_href(it, link, cx.cache()),
it.name.as_ref().unwrap(),
ty.print(cx.cache())
ty.print(cx.cache(), cx.tcx())
);
}
@ -930,6 +930,7 @@ fn assoc_type(
link: AssocItemLink<'_>,
extra: &str,
cache: &Cache,
tcx: TyCtxt<'_>,
) {
write!(
w,
@ -939,10 +940,10 @@ fn assoc_type(
it.name.as_ref().unwrap()
);
if !bounds.is_empty() {
write!(w, ": {}", print_generic_bounds(bounds, cache))
write!(w, ": {}", print_generic_bounds(bounds, cache, tcx))
}
if let Some(default) = default {
write!(w, " = {}", default.print(cache))
write!(w, " = {}", default.print(cache, tcx))
}
}
@ -1017,7 +1018,7 @@ fn render_assoc_item(
let defaultness = print_default_space(meth.is_default());
let abi = print_abi_with_space(header.abi).to_string();
// NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
let generics_len = format!("{:#}", g.print(cx.cache())).len();
let generics_len = format!("{:#}", g.print(cx.cache(), tcx)).len();
let mut header_len = "fn ".len()
+ vis.len()
+ constness.len()
@ -1049,11 +1050,10 @@ fn render_assoc_item(
abi,
href = href,
name = name,
generics = g.print(cx.cache()),
decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }
.print(cx.cache()),
spotlight = spotlight_decl(&d, cx.cache()),
where_clause = WhereClause { gens: g, indent, end_newline }.print(cx.cache())
generics = g.print(cx.cache(), cx.tcx()),
decl = d.full_print(cx.cache(), cx.tcx(), header_len, indent, header.asyncness),
spotlight = spotlight_decl(&d, cx.cache(), cx.tcx()),
where_clause = print_where_clause(g, cx.cache(), cx.tcx(), indent, end_newline),
)
}
match *item.kind {
@ -1081,6 +1081,7 @@ fn render_assoc_item(
link,
if parent == ItemType::Trait { " " } else { "" },
cx.cache(),
cx.tcx(),
),
_ => panic!("render_assoc_item called on non-associated-item"),
}
@ -1169,9 +1170,9 @@ fn render_assoc_items(
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
let id = cx.derive_id(small_url_encode(format!(
"deref-methods-{:#}",
type_.print(cx.cache())
type_.print(cx.cache(), cx.tcx())
)));
debug!("Adding {} to deref id map", type_.print(cx.cache()));
debug!("Adding {} to deref id map", type_.print(cx.cache(), cx.tcx()));
cx.deref_id_map
.borrow_mut()
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@ -1182,8 +1183,8 @@ fn render_assoc_items(
<a href=\"#{id}\" class=\"anchor\"></a>\
</h2>",
id = id,
trait_ = trait_.print(cx.cache()),
type_ = type_.print(cx.cache()),
trait_ = trait_.print(cx.cache(), cx.tcx()),
type_ = type_.print(cx.cache(), cx.tcx()),
);
RenderMode::ForDeref { mut_: deref_mut_ }
}
@ -1335,7 +1336,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo
}
}
fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache, tcx: TyCtxt<'_>) -> String {
let mut out = Buffer::html();
let mut trait_ = String::new();
@ -1351,16 +1352,16 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
&mut out,
"<h3 class=\"notable\">Notable traits for {}</h3>\
<code class=\"content\">",
impl_.for_.print(cache)
impl_.for_.print(cache, tcx)
);
trait_.push_str(&impl_.for_.print(cache).to_string());
trait_.push_str(&impl_.for_.print(cache, tcx).to_string());
}
//use the "where" class here to make it small
write!(
&mut out,
"<span class=\"where fmt-newline\">{}</span>",
impl_.print(cache, false)
impl_.print(cache, false, tcx)
);
let t_did = impl_.trait_.def_id_full(cache).unwrap();
for it in &impl_.items {
@ -1374,6 +1375,7 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
"",
cache,
tcx,
);
out.push_str(";</span>");
}
@ -1419,9 +1421,12 @@ fn render_impl(
let id = cx.derive_id(match i.inner_impl().trait_ {
Some(ref t) => {
if is_on_foreign_type {
get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache())
get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache(), cx.tcx())
} else {
format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx.cache()))))
format!(
"impl-{}",
small_url_encode(format!("{:#}", t.print(cx.cache(), cx.tcx())))
)
}
}
None => "impl".to_string(),
@ -1433,7 +1438,7 @@ fn render_impl(
};
if let Some(use_absolute) = use_absolute {
write!(w, "<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">", id, aliases);
write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute));
write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute, cx.tcx()));
if show_def_docs {
for it in &i.inner_impl().items {
if let clean::TypedefItem(ref tydef, _) = *it.kind {
@ -1446,6 +1451,7 @@ fn render_impl(
AssocItemLink::Anchor(None),
"",
cx.cache(),
cx.tcx(),
);
w.write_str(";</span>");
}
@ -1458,7 +1464,7 @@ fn render_impl(
"<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">{}</code>",
id,
aliases,
i.inner_impl().print(cx.cache(), false)
i.inner_impl().print(cx.cache(), false, cx.tcx())
);
}
write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
@ -1558,6 +1564,7 @@ fn render_impl(
link.anchor(&id),
"",
cx.cache(),
cx.tcx(),
);
w.write_str("</code></h4>");
}
@ -1579,7 +1586,16 @@ fn render_impl(
clean::AssocTypeItem(ref bounds, ref default) => {
let id = cx.derive_id(format!("{}.{}", item_type, name));
write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, extra_class);
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "", cx.cache());
assoc_type(
w,
item,
bounds,
default.as_ref(),
link.anchor(&id),
"",
cx.cache(),
cx.tcx(),
);
w.write_str("</code></h4>");
}
clean::StrippedItem(..) => return,
@ -1922,9 +1938,10 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
.iter()
.filter_map(|it| {
if let Some(ref i) = it.inner_impl().trait_ {
let i_display = format!("{:#}", i.print(cx.cache()));
let i_display = format!("{:#}", i.print(cx.cache(), cx.tcx()));
let out = Escape(&i_display);
let encoded = small_url_encode(format!("{:#}", i.print(cx.cache())));
let encoded =
small_url_encode(format!("{:#}", i.print(cx.cache(), cx.tcx())));
let generated = format!(
"<a href=\"#impl-{}\">{}{}</a>",
encoded,
@ -1988,6 +2005,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec<Impl>) {
let c = cx.cache();
let tcx = cx.tcx();
debug!("found Deref: {:?}", impl_);
if let Some((target, real_target)) =
@ -2036,8 +2054,11 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
out,
"<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
id,
Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(c))),
Escape(&format!("{:#}", real_target.print(c))),
Escape(&format!(
"{:#}",
impl_.inner_impl().trait_.as_ref().unwrap().print(c, tcx)
)),
Escape(&format!("{:#}", real_target.print(c, tcx))),
);
// We want links' order to be reproducible so we don't use unstable sort.
ret.sort();
@ -2094,17 +2115,26 @@ fn get_id_for_impl_on_foreign_type(
for_: &clean::Type,
trait_: &clean::Type,
cache: &Cache,
tcx: TyCtxt<'_>,
) -> String {
small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cache), for_.print(cache)))
small_url_encode(format!(
"impl-{:#}-for-{:#}",
trait_.print(cache, tcx),
for_.print(cache, tcx)
))
}
fn extract_for_impl_name(item: &clean::Item, cache: &Cache) -> Option<(String, String)> {
fn extract_for_impl_name(
item: &clean::Item,
cache: &Cache,
tcx: TyCtxt<'_>,
) -> Option<(String, String)> {
match *item.kind {
clean::ItemKind::ImplItem(ref i) => {
if let Some(ref trait_) = i.trait_ {
Some((
format!("{:#}", i.for_.print(cache)),
get_id_for_impl_on_foreign_type(&i.for_, trait_, cache),
format!("{:#}", i.for_.print(cache, tcx)),
get_id_for_impl_on_foreign_type(&i.for_, trait_, cache, tcx),
))
} else {
None
@ -2192,7 +2222,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
.def_id_full(cx.cache())
.map_or(false, |d| !cx.cache.paths.contains_key(&d))
})
.filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache()))
.filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache(), cx.tcx()))
.collect::<Vec<_>>();
if !res.is_empty() {

View file

@ -19,7 +19,7 @@ use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode};
use crate::html::escape::Escape;
use crate::html::format::{print_abi_with_space, Buffer, Function, PrintWithSpace, WhereClause};
use crate::html::format::{print_abi_with_space, print_where_clause, Buffer, PrintWithSpace};
use crate::html::highlight;
use crate::html::markdown::MarkdownSummaryLine;
@ -266,7 +266,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
w,
"<tr><td><code>{}{}</code></td></tr>",
myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()),
import.print(cx.cache())
import.print(cx.cache(), cx.tcx()),
);
}
@ -372,7 +372,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
f.header.unsafety.print_with_space(),
print_abi_with_space(f.header.abi),
it.name.as_ref().unwrap(),
f.generics.print(cx.cache())
f.generics.print(cx.cache(), cx.tcx())
)
.len();
w.write_str("<pre class=\"rust fn\">");
@ -387,18 +387,16 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
unsafety = f.header.unsafety.print_with_space(),
abi = print_abi_with_space(f.header.abi),
name = it.name.as_ref().unwrap(),
generics = f.generics.print(cx.cache()),
where_clause =
WhereClause { gens: &f.generics, indent: 0, end_newline: true }.print(cx.cache()),
decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
.print(cx.cache()),
spotlight = spotlight_decl(&f.decl, cx.cache()),
generics = f.generics.print(cx.cache(), cx.tcx()),
where_clause = print_where_clause(&f.generics, cx.cache(), cx.tcx(), 0, true),
decl = f.decl.full_print(cx.cache(), cx.tcx(), header_len, 0, f.header.asyncness),
spotlight = spotlight_decl(&f.decl, cx.cache(), cx.tcx()),
);
document(w, cx, it, None)
}
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
let bounds = bounds(&t.bounds, false, cx.cache());
let bounds = bounds(&t.bounds, false, cx.cache(), cx.tcx());
let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
let required = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
@ -415,13 +413,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
t.unsafety.print_with_space(),
if t.is_auto { "auto " } else { "" },
it.name.as_ref().unwrap(),
t.generics.print(cx.cache()),
t.generics.print(cx.cache(), cx.tcx()),
bounds
);
if !t.generics.where_predicates.is_empty() {
let where_ = WhereClause { gens: &t.generics, indent: 0, end_newline: true };
write!(w, "{}", where_.print(cx.cache()));
write!(w, "{}", print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true));
} else {
w.write_str(" ");
}
@ -594,8 +591,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
local.iter().partition(|i| i.inner_impl().synthetic);
synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache()));
concrete.sort_by(|a, b| compare_impl(a, b, cx.cache()));
synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.tcx()));
concrete.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.tcx()));
if !foreign.is_empty() {
write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
@ -700,9 +697,9 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
w,
"trait {}{}{} = {};</pre>",
it.name.as_ref().unwrap(),
t.generics.print(cx.cache()),
WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
bounds(&t.bounds, true, cx.cache())
t.generics.print(cx.cache(), cx.tcx()),
print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
bounds(&t.bounds, true, cx.cache(), cx.tcx())
);
document(w, cx, it, None);
@ -721,10 +718,9 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
w,
"type {}{}{where_clause} = impl {bounds};</pre>",
it.name.as_ref().unwrap(),
t.generics.print(cx.cache()),
where_clause =
WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
bounds = bounds(&t.bounds, false, cx.cache())
t.generics.print(cx.cache(), cx.tcx()),
where_clause = print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
bounds = bounds(&t.bounds, false, cx.cache(), cx.tcx()),
);
document(w, cx, it, None);
@ -743,10 +739,9 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
w,
"type {}{}{where_clause} = {type_};</pre>",
it.name.as_ref().unwrap(),
t.generics.print(cx.cache()),
where_clause =
WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
type_ = t.type_.print(cx.cache())
t.generics.print(cx.cache(), cx.tcx()),
where_clause = print_where_clause(&t.generics, cx.cache(), cx.tcx(), 0, true),
type_ = t.type_.print(cx.cache(), cx.tcx()),
);
document(w, cx, it, None);
@ -793,7 +788,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
id = id,
name = name,
shortty = ItemType::StructField,
ty = ty.print(cx.cache())
ty = ty.print(cx.cache(), cx.tcx()),
);
if let Some(stability_class) = field.stability_class(cx.tcx()) {
write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
@ -813,8 +808,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
"{}enum {}{}{}",
it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
it.name.as_ref().unwrap(),
e.generics.print(cx.cache()),
WhereClause { gens: &e.generics, indent: 0, end_newline: true }.print(cx.cache())
e.generics.print(cx.cache(), cx.tcx()),
print_where_clause(&e.generics, cx.cache(), cx.tcx(), 0, true),
);
if e.variants.is_empty() && !e.variants_stripped {
w.write_str(" {}");
@ -832,7 +827,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
if i > 0 {
w.write_str(",&nbsp;")
}
write!(w, "{}", ty.print(cx.cache()));
write!(w, "{}", ty.print(cx.cache(), cx.tcx()));
}
w.write_str(")");
}
@ -879,7 +874,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
if i > 0 {
w.write_str(",&nbsp;");
}
write!(w, "{}", ty.print(cx.cache()));
write!(w, "{}", ty.print(cx.cache(), cx.tcx()));
}
w.write_str(")");
}
@ -916,7 +911,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
</span>",
id = id,
f = field.name.as_ref().unwrap(),
t = ty.print(cx.cache())
t = ty.print(cx.cache(), cx.tcx())
);
document(w, cx, field, Some(variant));
}
@ -987,19 +982,22 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
"{vis}const {name}: {typ}",
vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
name = it.name.as_ref().unwrap(),
typ = c.type_.print(cx.cache()),
typ = c.type_().print(cx.cache(), cx.tcx()),
);
if c.value.is_some() || c.is_literal {
write!(w, " = {expr};", expr = Escape(&c.expr));
let value = c.value(cx.tcx());
let is_literal = c.is_literal(cx.tcx());
let expr = c.expr(cx.tcx());
if value.is_some() || is_literal {
write!(w, " = {expr};", expr = Escape(&expr));
} else {
w.write_str(";");
}
if let Some(value) = &c.value {
if !c.is_literal {
if !is_literal {
if let Some(value) = &value {
let value_lowercase = value.to_lowercase();
let expr_lowercase = c.expr.to_lowercase();
let expr_lowercase = expr.to_lowercase();
if value_lowercase != expr_lowercase
&& value_lowercase.trim_end_matches("i32") != expr_lowercase
@ -1054,7 +1052,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
item_type = ItemType::StructField,
id = id,
name = field.name.as_ref().unwrap(),
ty = ty.print(cx.cache())
ty = ty.print(cx.cache(), cx.tcx())
);
document(w, cx, field, Some(it));
}
@ -1072,7 +1070,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
mutability = s.mutability.print_with_space(),
name = it.name.as_ref().unwrap(),
typ = s.type_.print(cx.cache())
typ = s.type_.print(cx.cache(), cx.tcx())
);
document(w, cx, it, None)
}
@ -1147,7 +1145,12 @@ pub(super) fn item_path(ty: ItemType, name: &str) -> String {
}
}
fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) -> String {
fn bounds(
t_bounds: &[clean::GenericBound],
trait_alias: bool,
cache: &Cache,
tcx: TyCtxt<'_>,
) -> String {
let mut bounds = String::new();
if !t_bounds.is_empty() {
if !trait_alias {
@ -1157,7 +1160,7 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) ->
if i > 0 {
bounds.push_str(" + ");
}
bounds.push_str(&p.print(cache).to_string());
bounds.push_str(&p.print(cache, tcx).to_string());
}
}
bounds
@ -1187,9 +1190,14 @@ fn render_stability_since(
)
}
fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cache: &Cache) -> Ordering {
let lhs = format!("{}", lhs.inner_impl().print(cache, false));
let rhs = format!("{}", rhs.inner_impl().print(cache, false));
fn compare_impl<'a, 'b>(
lhs: &'a &&Impl,
rhs: &'b &&Impl,
cache: &Cache,
tcx: TyCtxt<'_>,
) -> Ordering {
let lhs = format!("{}", lhs.inner_impl().print(cache, false, tcx));
let rhs = format!("{}", rhs.inner_impl().print(cache, false, tcx));
// lhs and rhs are formatted as HTML, which may be unnecessary
compare_names(&lhs, &rhs)
@ -1247,8 +1255,8 @@ fn render_union(
it.name.as_ref().unwrap()
);
if let Some(g) = g {
write!(w, "{}", g.print(cx.cache()));
write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache()));
write!(w, "{}", g.print(cx.cache(), cx.tcx()));
write!(w, "{}", print_where_clause(&g, cx.cache(), cx.tcx(), 0, true));
}
write!(w, " {{\n{}", tab);
@ -1259,7 +1267,7 @@ fn render_union(
" {}{}: {},\n{}",
field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
field.name.as_ref().unwrap(),
ty.print(cx.cache()),
ty.print(cx.cache(), cx.tcx()),
tab
);
}
@ -1289,16 +1297,12 @@ fn render_struct(
it.name.as_ref().unwrap()
);
if let Some(g) = g {
write!(w, "{}", g.print(cx.cache()))
write!(w, "{}", g.print(cx.cache(), cx.tcx()))
}
match ty {
CtorKind::Fictive => {
if let Some(g) = g {
write!(
w,
"{}",
WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache())
)
write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, true),)
}
let mut has_visible_fields = false;
w.write_str(" {");
@ -1310,7 +1314,7 @@ fn render_struct(
tab,
field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
field.name.as_ref().unwrap(),
ty.print(cx.cache())
ty.print(cx.cache(), cx.tcx()),
);
has_visible_fields = true;
}
@ -1341,7 +1345,7 @@ fn render_struct(
w,
"{}{}",
field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
ty.print(cx.cache())
ty.print(cx.cache(), cx.tcx()),
)
}
_ => unreachable!(),
@ -1349,22 +1353,14 @@ fn render_struct(
}
w.write_str(")");
if let Some(g) = g {
write!(
w,
"{}",
WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
)
write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, false),)
}
w.write_str(";");
}
CtorKind::Const => {
// Needed for PhantomData.
if let Some(g) = g {
write!(
w,
"{}",
WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
)
write!(w, "{}", print_where_clause(g, cx.cache(), cx.tcx(), 0, false),)
}
w.write_str(";");
}

View file

@ -430,7 +430,7 @@ pub(super) fn write_shared(
None
} else {
Some(Implementor {
text: imp.inner_impl().print(cx.cache(), false).to_string(),
text: imp.inner_impl().print(cx.cache(), false, cx.tcx()).to_string(),
synthetic: imp.inner_impl().synthetic,
types: collect_paths_for_type(imp.inner_impl().for_.clone(), cx.cache()),
})

View file

@ -27,7 +27,7 @@ impl JsonRenderer<'_> {
let clean::Item { span, name, attrs, kind, visibility, def_id } = item;
let inner = match *kind {
clean::StrippedItem(_) => return None,
x => from_clean_item_kind(x, self.tcx, &name),
kind => from_clean_item_kind(kind, self.tcx, &name),
};
Some(Item {
id: from_def_id(def_id),
@ -87,59 +87,78 @@ impl JsonRenderer<'_> {
}
}
crate trait FromWithTcx<T> {
fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self;
}
crate trait IntoWithTcx<T> {
fn into_tcx(self, tcx: TyCtxt<'_>) -> T;
}
impl<T, U> IntoWithTcx<U> for T
where
U: FromWithTcx<T>,
{
fn into_tcx(self, tcx: TyCtxt<'_>) -> U {
U::from_tcx(self, tcx)
}
}
crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
#[rustfmt::skip]
let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
}
impl From<clean::GenericArgs> for GenericArgs {
fn from(args: clean::GenericArgs) -> Self {
impl FromWithTcx<clean::GenericArgs> for GenericArgs {
fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
use clean::GenericArgs::*;
match args {
AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
args: args.into_iter().map(Into::into).collect(),
bindings: bindings.into_iter().map(Into::into).collect(),
args: args.into_iter().map(|a| a.into_tcx(tcx)).collect(),
bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(),
},
Parenthesized { inputs, output } => GenericArgs::Parenthesized {
inputs: inputs.into_iter().map(Into::into).collect(),
output: output.map(Into::into),
inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(),
output: output.map(|a| a.into_tcx(tcx)),
},
}
}
}
impl From<clean::GenericArg> for GenericArg {
fn from(arg: clean::GenericArg) -> Self {
impl FromWithTcx<clean::GenericArg> for GenericArg {
fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
use clean::GenericArg::*;
match arg {
Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
Type(t) => GenericArg::Type(t.into()),
Const(c) => GenericArg::Const(c.into()),
Type(t) => GenericArg::Type(t.into_tcx(tcx)),
Const(c) => GenericArg::Const(c.into_tcx(tcx)),
}
}
}
impl From<clean::Constant> for Constant {
fn from(constant: clean::Constant) -> Self {
let clean::Constant { type_, expr, value, is_literal } = constant;
Constant { type_: type_.into(), expr, value, is_literal }
impl FromWithTcx<clean::Constant> for Constant {
fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self {
let expr = constant.expr(tcx);
let value = constant.value(tcx);
let is_literal = constant.is_literal(tcx);
Constant { type_: constant.to_type().into_tcx(tcx), expr, value, is_literal }
}
}
impl From<clean::TypeBinding> for TypeBinding {
fn from(binding: clean::TypeBinding) -> Self {
TypeBinding { name: binding.name.to_string(), binding: binding.kind.into() }
impl FromWithTcx<clean::TypeBinding> for TypeBinding {
fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) }
}
}
impl From<clean::TypeBindingKind> for TypeBindingKind {
fn from(kind: clean::TypeBindingKind) -> Self {
impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
use clean::TypeBindingKind::*;
match kind {
Equality { ty } => TypeBindingKind::Equality(ty.into()),
Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)),
Constraint { bounds } => {
TypeBindingKind::Constraint(bounds.into_iter().map(Into::into).collect())
TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
}
}
}
@ -152,32 +171,32 @@ crate fn from_def_id(did: DefId) -> Id {
fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum {
use clean::ItemKind::*;
match item {
ModuleItem(m) => ItemEnum::Module(m.into()),
ImportItem(i) => ItemEnum::Import(i.into()),
StructItem(s) => ItemEnum::Struct(s.into()),
UnionItem(u) => ItemEnum::Union(u.into()),
StructFieldItem(f) => ItemEnum::StructField(f.into()),
EnumItem(e) => ItemEnum::Enum(e.into()),
VariantItem(v) => ItemEnum::Variant(v.into()),
FunctionItem(f) => ItemEnum::Function(f.into()),
ForeignFunctionItem(f) => ItemEnum::Function(f.into()),
TraitItem(t) => ItemEnum::Trait(t.into()),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into()),
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true)),
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false)),
ImplItem(i) => ItemEnum::Impl(i.into()),
StaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
ForeignStaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
ModuleItem(m) => ItemEnum::Module(m.into_tcx(tcx)),
ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
FunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
ForeignFunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, tcx)),
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, tcx)),
ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
ForeignTypeItem => ItemEnum::ForeignType,
TypedefItem(t, _) => ItemEnum::Typedef(t.into()),
OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into()),
ConstantItem(c) => ItemEnum::Constant(c.into()),
TypedefItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
MacroItem(m) => ItemEnum::Macro(m.source),
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into()),
AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into(), default: s },
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into_tcx(tcx), default: s },
AssocTypeItem(g, t) => ItemEnum::AssocType {
bounds: g.into_iter().map(Into::into).collect(),
default: t.map(Into::into),
bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: t.map(|x| x.into_tcx(tcx)),
},
StrippedItem(inner) => from_clean_item_kind(*inner, tcx, name),
PrimitiveItem(_) | KeywordItem(_) => {
@ -190,18 +209,18 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Sy
}
}
impl From<clean::Module> for Module {
fn from(module: clean::Module) -> Self {
impl FromWithTcx<clean::Module> for Module {
fn from_tcx(module: clean::Module, _tcx: TyCtxt<'_>) -> Self {
Module { is_crate: module.is_crate, items: ids(module.items) }
}
}
impl From<clean::Struct> for Struct {
fn from(struct_: clean::Struct) -> Self {
impl FromWithTcx<clean::Struct> for Struct {
fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
Struct {
struct_type: from_ctor_kind(struct_type),
generics: generics.into(),
generics: generics.into_tcx(tcx),
fields_stripped,
fields: ids(fields),
impls: Vec::new(), // Added in JsonRenderer::item
@ -209,11 +228,11 @@ impl From<clean::Struct> for Struct {
}
}
impl From<clean::Union> for Union {
fn from(struct_: clean::Union) -> Self {
impl FromWithTcx<clean::Union> for Union {
fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self {
let clean::Union { generics, fields, fields_stripped } = struct_;
Union {
generics: generics.into(),
generics: generics.into_tcx(tcx),
fields_stripped,
fields: ids(fields),
impls: Vec::new(), // Added in JsonRenderer::item
@ -247,74 +266,81 @@ crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
v
}
impl From<clean::Function> for Function {
fn from(function: clean::Function) -> Self {
impl FromWithTcx<clean::Function> for Function {
fn from_tcx(function: clean::Function, tcx: TyCtxt<'_>) -> Self {
let clean::Function { decl, generics, header } = function;
Function {
decl: decl.into(),
generics: generics.into(),
decl: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
header: from_fn_header(&header),
abi: header.abi.to_string(),
}
}
}
impl From<clean::Generics> for Generics {
fn from(generics: clean::Generics) -> Self {
impl FromWithTcx<clean::Generics> for Generics {
fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
Generics {
params: generics.params.into_iter().map(Into::into).collect(),
where_predicates: generics.where_predicates.into_iter().map(Into::into).collect(),
params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
where_predicates: generics
.where_predicates
.into_iter()
.map(|x| x.into_tcx(tcx))
.collect(),
}
}
}
impl From<clean::GenericParamDef> for GenericParamDef {
fn from(generic_param: clean::GenericParamDef) -> Self {
GenericParamDef { name: generic_param.name.to_string(), kind: generic_param.kind.into() }
impl FromWithTcx<clean::GenericParamDef> for GenericParamDef {
fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self {
GenericParamDef {
name: generic_param.name.to_string(),
kind: generic_param.kind.into_tcx(tcx),
}
}
}
impl From<clean::GenericParamDefKind> for GenericParamDefKind {
fn from(kind: clean::GenericParamDefKind) -> Self {
impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
use clean::GenericParamDefKind::*;
match kind {
Lifetime => GenericParamDefKind::Lifetime,
Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
bounds: bounds.into_iter().map(Into::into).collect(),
default: default.map(Into::into),
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: default.map(|x| x.into_tcx(tcx)),
},
Const { did: _, ty } => GenericParamDefKind::Const(ty.into()),
Const { did: _, ty } => GenericParamDefKind::Const(ty.into_tcx(tcx)),
}
}
}
impl From<clean::WherePredicate> for WherePredicate {
fn from(predicate: clean::WherePredicate) -> Self {
impl FromWithTcx<clean::WherePredicate> for WherePredicate {
fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
use clean::WherePredicate::*;
match predicate {
BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate {
ty: ty.into(),
bounds: bounds.into_iter().map(Into::into).collect(),
ty: ty.into_tcx(tcx),
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
},
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
lifetime: lifetime.0.to_string(),
bounds: bounds.into_iter().map(Into::into).collect(),
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
},
EqPredicate { lhs, rhs } => {
WherePredicate::EqPredicate { lhs: lhs.into(), rhs: rhs.into() }
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
}
}
}
}
impl From<clean::GenericBound> for GenericBound {
fn from(bound: clean::GenericBound) -> Self {
impl FromWithTcx<clean::GenericBound> for GenericBound {
fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
use clean::GenericBound::*;
match bound {
TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
GenericBound::TraitBound {
trait_: trait_.into(),
generic_params: generic_params.into_iter().map(Into::into).collect(),
trait_: trait_.into_tcx(tcx),
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
modifier: from_trait_bound_modifier(modifier),
}
}
@ -332,47 +358,47 @@ crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> T
}
}
impl From<clean::Type> for Type {
fn from(ty: clean::Type) -> Self {
impl FromWithTcx<clean::Type> for Type {
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
use clean::Type::*;
match ty {
ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath {
name: path.whole_name(),
id: from_def_id(did),
args: path.segments.last().map(|args| Box::new(args.clone().args.into())),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
param_names: param_names
.map(|v| v.into_iter().map(Into::into).collect())
.map(|v| v.into_iter().map(|x| x.into_tcx(tcx)).collect())
.unwrap_or_default(),
},
Generic(s) => Type::Generic(s.to_string()),
Primitive(p) => Type::Primitive(p.as_str().to_string()),
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into())),
Tuple(t) => Type::Tuple(t.into_iter().map(Into::into).collect()),
Slice(t) => Type::Slice(Box::new((*t).into())),
Array(t, s) => Type::Array { type_: Box::new((*t).into()), len: s },
ImplTrait(g) => Type::ImplTrait(g.into_iter().map(Into::into).collect()),
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()),
Never => Type::Never,
Infer => Type::Infer,
RawPointer(mutability, type_) => Type::RawPointer {
mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into()),
type_: Box::new((*type_).into_tcx(tcx)),
},
BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
lifetime: lifetime.map(|l| l.0.to_string()),
mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into()),
type_: Box::new((*type_).into_tcx(tcx)),
},
QPath { name, self_type, trait_ } => Type::QualifiedPath {
name: name.to_string(),
self_type: Box::new((*self_type).into()),
trait_: Box::new((*trait_).into()),
self_type: Box::new((*self_type).into_tcx(tcx)),
trait_: Box::new((*trait_).into_tcx(tcx)),
},
}
}
}
impl From<clean::BareFunctionDecl> for FunctionPointer {
fn from(bare_decl: clean::BareFunctionDecl) -> Self {
impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
FunctionPointer {
header: if let rustc_hir::Unsafety::Unsafe = unsafety {
@ -382,24 +408,24 @@ impl From<clean::BareFunctionDecl> for FunctionPointer {
} else {
HashSet::new()
},
generic_params: generic_params.into_iter().map(Into::into).collect(),
decl: decl.into(),
generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
decl: decl.into_tcx(tcx),
abi: abi.to_string(),
}
}
}
impl From<clean::FnDecl> for FnDecl {
fn from(decl: clean::FnDecl) -> Self {
impl FromWithTcx<clean::FnDecl> for FnDecl {
fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
let clean::FnDecl { inputs, output, c_variadic, attrs: _ } = decl;
FnDecl {
inputs: inputs
.values
.into_iter()
.map(|arg| (arg.name.to_string(), arg.type_.into()))
.map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
.collect(),
output: match output {
clean::FnRetTy::Return(t) => Some(t.into()),
clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)),
clean::FnRetTy::DefaultReturn => None,
},
c_variadic,
@ -407,22 +433,22 @@ impl From<clean::FnDecl> for FnDecl {
}
}
impl From<clean::Trait> for Trait {
fn from(trait_: clean::Trait) -> Self {
impl FromWithTcx<clean::Trait> for Trait {
fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
Trait {
is_auto,
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
items: ids(items),
generics: generics.into(),
bounds: bounds.into_iter().map(Into::into).collect(),
generics: generics.into_tcx(tcx),
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
implementors: Vec::new(), // Added in JsonRenderer::item
}
}
}
impl From<clean::Impl> for Impl {
fn from(impl_: clean::Impl) -> Self {
impl FromWithTcx<clean::Impl> for Impl {
fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
let clean::Impl {
unsafety,
generics,
@ -436,37 +462,41 @@ impl From<clean::Impl> for Impl {
} = impl_;
Impl {
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
generics: generics.into(),
generics: generics.into_tcx(tcx),
provided_trait_methods: provided_trait_methods
.into_iter()
.map(|x| x.to_string())
.collect(),
trait_: trait_.map(Into::into),
for_: for_.into(),
trait_: trait_.map(|x| x.into_tcx(tcx)),
for_: for_.into_tcx(tcx),
items: ids(items),
negative: negative_polarity,
synthetic,
blanket_impl: blanket_impl.map(Into::into),
blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
}
}
}
crate fn from_function_method(function: clean::Function, has_body: bool) -> Method {
crate fn from_function_method(
function: clean::Function,
has_body: bool,
tcx: TyCtxt<'_>,
) -> Method {
let clean::Function { header, decl, generics } = function;
Method {
decl: decl.into(),
generics: generics.into(),
decl: decl.into_tcx(tcx),
generics: generics.into_tcx(tcx),
header: from_fn_header(&header),
abi: header.abi.to_string(),
has_body,
}
}
impl From<clean::Enum> for Enum {
fn from(enum_: clean::Enum) -> Self {
impl FromWithTcx<clean::Enum> for Enum {
fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
let clean::Enum { variants, generics, variants_stripped } = enum_;
Enum {
generics: generics.into(),
generics: generics.into_tcx(tcx),
variants_stripped,
variants: ids(variants),
impls: Vec::new(), // Added in JsonRenderer::item
@ -474,8 +504,8 @@ impl From<clean::Enum> for Enum {
}
}
impl From<clean::VariantStruct> for Struct {
fn from(struct_: clean::VariantStruct) -> Self {
impl FromWithTcx<clean::VariantStruct> for Struct {
fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self {
let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
Struct {
struct_type: from_ctor_kind(struct_type),
@ -487,19 +517,19 @@ impl From<clean::VariantStruct> for Struct {
}
}
impl From<clean::Variant> for Variant {
fn from(variant: clean::Variant) -> Self {
impl FromWithTcx<clean::Variant> for Variant {
fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
use clean::Variant::*;
match variant {
CLike => Variant::Plain,
Tuple(t) => Variant::Tuple(t.into_iter().map(Into::into).collect()),
Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
Struct(s) => Variant::Struct(ids(s.fields)),
}
}
}
impl From<clean::Import> for Import {
fn from(import: clean::Import) -> Self {
impl FromWithTcx<clean::Import> for Import {
fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self {
use clean::ImportKind::*;
match import.kind {
Simple(s) => Import {
@ -518,8 +548,8 @@ impl From<clean::Import> for Import {
}
}
impl From<clean::ProcMacro> for ProcMacro {
fn from(mac: clean::ProcMacro) -> Self {
impl FromWithTcx<clean::ProcMacro> for ProcMacro {
fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self {
ProcMacro {
kind: from_macro_kind(mac.kind),
helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
@ -536,41 +566,43 @@ crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
}
}
impl From<clean::Typedef> for Typedef {
fn from(typedef: clean::Typedef) -> Self {
impl FromWithTcx<clean::Typedef> for Typedef {
fn from_tcx(typedef: clean::Typedef, tcx: TyCtxt<'_>) -> Self {
let clean::Typedef { type_, generics, item_type: _ } = typedef;
Typedef { type_: type_.into(), generics: generics.into() }
Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) }
}
}
impl From<clean::OpaqueTy> for OpaqueTy {
fn from(opaque: clean::OpaqueTy) -> Self {
impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
OpaqueTy {
bounds: opaque.bounds.into_iter().map(Into::into).collect(),
generics: opaque.generics.into(),
bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
generics: opaque.generics.into_tcx(tcx),
}
}
}
fn from_clean_static(stat: clean::Static, tcx: TyCtxt<'_>) -> Static {
impl FromWithTcx<clean::Static> for Static {
fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
Static {
type_: stat.type_.into(),
type_: stat.type_.into_tcx(tcx),
mutable: stat.mutability == ast::Mutability::Mut,
expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
}
}
}
impl From<clean::TraitAlias> for TraitAlias {
fn from(alias: clean::TraitAlias) -> Self {
impl FromWithTcx<clean::TraitAlias> for TraitAlias {
fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
TraitAlias {
generics: alias.generics.into(),
params: alias.bounds.into_iter().map(Into::into).collect(),
generics: alias.generics.into_tcx(tcx),
params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
}
}
}
impl From<ItemType> for ItemKind {
fn from(kind: ItemType) -> Self {
impl FromWithTcx<ItemType> for ItemKind {
fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
use ItemType::*;
match kind {
Module => ItemKind::Module,

View file

@ -24,7 +24,7 @@ use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
use crate::json::conversions::from_def_id;
use crate::json::conversions::{from_def_id, IntoWithTcx};
#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
@ -108,7 +108,7 @@ impl JsonRenderer<'tcx> {
.last()
.map(Clone::clone),
visibility: types::Visibility::Public,
inner: types::ItemEnum::Trait(trait_item.clone().into()),
inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
span: None,
docs: Default::default(),
links: Default::default(),
@ -225,7 +225,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
.map(|(k, (path, kind))| {
(
from_def_id(k),
types::ItemSummary { crate_id: k.krate.as_u32(), path, kind: kind.into() },
types::ItemSummary {
crate_id: k.krate.as_u32(),
path,
kind: kind.into_tcx(self.tcx),
},
)
})
.collect(),

View file

@ -216,8 +216,8 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
if let Some(ref tr) = impl_.trait_ {
debug!(
"impl {:#} for {:#} in {}",
tr.print(&self.ctx.cache),
impl_.for_.print(&self.ctx.cache),
tr.print(&self.ctx.cache, self.ctx.tcx),
impl_.for_.print(&self.ctx.cache, self.ctx.tcx),
filename,
);
@ -228,7 +228,11 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
// inherent impls *can* be documented, and those docs show up, but in most
// cases it doesn't make sense, as all methods on a type are in one single
// impl block
debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename);
debug!(
"impl {:#} in {}",
impl_.for_.print(&self.ctx.cache, self.ctx.tcx),
filename
);
}
}
_ => {