diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0d32c14c3be9b..a4c1ee7a0f065 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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,23 +490,19 @@ 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 { +fn build_const(cx: &mut DocContext<'_>, def_id: 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)) - }), + type_: cx.tcx.type_of(def_id).clean(cx), + kind: clean::ConstantKind::Extern { def_id }, } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 84210276d35c4..80054469f9d6e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -398,9 +398,7 @@ impl Clean for hir::ConstArg { .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), + kind: ConstantKind::Anonymous { body: self.value.body }, } } } @@ -1135,7 +1133,7 @@ impl Clean 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(tcx, self.def_id)) } else { None }; @@ -1745,11 +1743,10 @@ impl<'tcx> Clean for Ty<'tcx> { impl<'tcx> Clean for ty::Const<'tcx> { fn clean(&self, cx: &mut DocContext<'_>) -> Constant { + // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { type_: self.ty.clean(cx), - expr: format!("{}", self), - value: None, - is_literal: false, + kind: ConstantKind::TyConst { expr: self.to_string() }, } } } @@ -1953,9 +1950,7 @@ impl Clean> for (&hir::Item<'_>, Option) { } ItemKind::Const(ty, body_id) => ConstantItem(Constant { 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), + kind: ConstantKind::Local { body: body_id, def_id }, }), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { bounds: ty.bounds.clean(cx), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 142121b734670..4132e187c72a1 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -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; @@ -1988,9 +1989,58 @@ crate struct Static { #[derive(Clone, PartialEq, Eq, Hash, Debug)] crate struct Constant { crate type_: Type, - crate expr: String, - crate value: Option, - crate is_literal: bool, + crate kind: ConstantKind, +} + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +crate enum ConstantKind { + /// This is the wrapper around `ty::Const` for a non-local constant. Because it doesn't have a + /// `BodyId`, we need to handle it on its own. + /// + /// Note that `ty::Const` includes generic parameters, and may not always be uniquely identified + /// by a DefId. So this field must be different from `Extern`. + TyConst { expr: String }, + /// A constant (expression) that's 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. + Anonymous { body: BodyId }, + /// A constant from a different crate. + Extern { def_id: DefId }, + /// `const FOO: u32 = ...;` + Local { def_id: DefId, body: BodyId }, +} + +impl Constant { + crate fn expr(&self, tcx: TyCtxt<'_>) -> String { + match self.kind { + ConstantKind::TyConst { ref expr } => expr.clone(), + ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), + ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { + print_const_expr(tcx, body) + } + } + } + + crate fn value(&self, tcx: TyCtxt<'_>) -> Option { + match self.kind { + ConstantKind::TyConst { .. } | ConstantKind::Anonymous { .. } => None, + ConstantKind::Extern { def_id } | ConstantKind::Local { def_id, .. } => { + print_evaluated_const(tcx, def_id) + } + } + } + + crate fn is_literal(&self, tcx: TyCtxt<'_>) -> bool { + match self.kind { + ConstantKind::TyConst { .. } => false, + ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| { + is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id)) + }), + ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { + is_literal_expr(tcx, body.hir_id) + } + } + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 582cbf69ed117..32bac53e8f51b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -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 { - 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 { + 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, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 60106f3b7ae12..a004ee5054ed6 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -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(items: impl Iterator) -> impl fmt::Display { display_fn(move |f| { for (i, item) in items.enumerate() { @@ -148,27 +123,32 @@ fn comma_sep(items: impl Iterator) -> 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, ": {}", print_generic_bounds(bounds, cache))?; + write!(f, ": {}", 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, " = {}", ty.print(cache))?; + write!(f, " = {}", 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 {}: {}", self.name, ty.print(cache)) + write!(f, "const {}: {}", 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::>(); @@ -212,109 +196,115 @@ 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, "<{}>", comma_sep(real_params.iter().map(|g| g.print(cache)))) + write!(f, "<{}>", 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 { - display_fn(move |f| { - let &WhereClause { gens, indent, end_newline } = self; - if gens.where_predicates.is_empty() { - return Ok(()); +/// * 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| { + if gens.where_predicates.is_empty() { + return Ok(()); + } + let mut clause = String::new(); + if f.alternate() { + clause.push_str(" where"); + } else { + if end_newline { + clause.push_str(" where"); + } else { + clause.push_str(" where"); } - let mut clause = String::new(); + } + for (i, pred) in gens.where_predicates.iter().enumerate() { if f.alternate() { - clause.push_str(" where"); + clause.push(' '); } else { - if end_newline { - clause.push_str(" where"); - } else { - clause.push_str(" where"); - } + clause.push_str("
"); } - for (i, pred) in gens.where_predicates.iter().enumerate() { - if f.alternate() { - clause.push(' '); - } else { - clause.push_str("
"); - } - match pred { - clean::WherePredicate::BoundPredicate { ty, bounds } => { - let bounds = bounds; - if f.alternate() { - clause.push_str(&format!( - "{:#}: {:#}", - ty.print(cache), - print_generic_bounds(bounds, cache) - )); - } else { - clause.push_str(&format!( - "{}: {}", - ty.print(cache), - print_generic_bounds(bounds, cache) - )); - } - } - clean::WherePredicate::RegionPredicate { lifetime, bounds } => { + match pred { + clean::WherePredicate::BoundPredicate { ty, bounds } => { + let bounds = bounds; + if f.alternate() { + clause.push_str(&format!( + "{:#}: {:#}", + ty.print(cache, tcx), + print_generic_bounds(bounds, cache, tcx) + )); + } else { clause.push_str(&format!( "{}: {}", - lifetime.print(), - bounds - .iter() - .map(|b| b.print(cache).to_string()) - .collect::>() - .join(" + ") + ty.print(cache, tcx), + print_generic_bounds(bounds, cache, tcx) )); } - clean::WherePredicate::EqPredicate { lhs, rhs } => { - if f.alternate() { - clause.push_str(&format!( - "{:#} == {:#}", - lhs.print(cache), - rhs.print(cache) - )); - } else { - clause.push_str(&format!( - "{} == {}", - lhs.print(cache), - rhs.print(cache) - )); - } + } + clean::WherePredicate::RegionPredicate { lifetime, bounds } => { + clause.push_str(&format!( + "{}: {}", + lifetime.print(), + bounds + .iter() + .map(|b| b.print(cache, tcx).to_string()) + .collect::>() + .join(" + ") + )); + } + clean::WherePredicate::EqPredicate { lhs, rhs } => { + if f.alternate() { + clause.push_str(&format!( + "{:#} == {:#}", + lhs.print(cache, tcx), + rhs.print(cache, tcx), + )); + } else { + clause.push_str(&format!( + "{} == {}", + lhs.print(cache, tcx), + rhs.print(cache, tcx), + )); } } + } - if i < gens.where_predicates.len() - 1 || end_newline { - clause.push(','); - } + if i < gens.where_predicates.len() - 1 || end_newline { + clause.push(','); } + } - if end_newline { - // add a space so stripping
tags and breaking spaces still renders properly - if f.alternate() { - clause.push(' '); - } else { - clause.push_str(" "); - } + if end_newline { + // add a space so stripping
tags and breaking spaces still renders properly + if f.alternate() { + clause.push(' '); + } else { + clause.push_str(" "); } + } - if !f.alternate() { - clause.push_str("
"); - let padding = " ".repeat(indent + 4); - clause = clause.replace("
", &format!("
{}", padding)); - clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); - if !end_newline { - clause.insert_str(0, "
"); - } + if !f.alternate() { + clause.push_str("
"); + let padding = " ".repeat(indent + 4); + clause = clause.replace("
", &format!("
{}", padding)); + clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); + if !end_newline { + clause.insert_str(0, "
"); } - write!(f, "{}", clause) - }) - } + } + 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<{}> ", - 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, " -> {}", ty.print(cache))?; + write!(f, " -> {}", 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( 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>, 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(¶m.print(cache), f)?; + fmt::Display::fmt(¶m.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, "<{} 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))? } }; 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, " -> {}", ty.print(cache)), + clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache, tcx)), + clean::Return(ty) => write!(f, " -> {}", 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,147 +1016,176 @@ 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; - let amp = if f.alternate() { "&" } else { "&" }; - let mut args = String::new(); - let mut args_plain = String::new(); - for (i, input) in decl.inputs.values.iter().enumerate() { - if i == 0 { - args.push_str("
"); - } + /// * `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. + ///
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)) + } - if let Some(selfty) = input.to_self() { - match selfty { - clean::SelfValue => { - args.push_str("self"); - args_plain.push_str("self"); - } - clean::SelfBorrowed(Some(ref lt), mtbl) => { - args.push_str(&format!( - "{}{} {}self", - amp, - lt.print(), - mtbl.print_with_space() - )); - args_plain.push_str(&format!( - "&{} {}self", - lt.print(), - mtbl.print_with_space() - )); - } - clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("{}{}self", amp, mtbl.print_with_space())); - args_plain.push_str(&format!("&{}self", mtbl.print_with_space())); - } - clean::SelfExplicit(ref typ) => { - if f.alternate() { - args.push_str(&format!("self: {:#}", typ.print(cache))); - } else { - args.push_str(&format!("self: {}", typ.print(cache))); - } - args_plain.push_str(&format!("self: {:#}", typ.print(cache))); - } + 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 { "&" }; + let mut args = String::new(); + let mut args_plain = String::new(); + for (i, input) in self.inputs.values.iter().enumerate() { + if i == 0 { + args.push_str("
"); + } + + if let Some(selfty) = input.to_self() { + match selfty { + clean::SelfValue => { + args.push_str("self"); + args_plain.push_str("self"); } - } else { - if i > 0 { - args.push_str("
"); - args_plain.push(' '); + clean::SelfBorrowed(Some(ref lt), mtbl) => { + args.push_str(&format!( + "{}{} {}self", + amp, + lt.print(), + mtbl.print_with_space() + )); + args_plain.push_str(&format!( + "&{} {}self", + lt.print(), + mtbl.print_with_space() + )); } - if !input.name.is_empty() { - args.push_str(&format!("{}: ", input.name)); - args_plain.push_str(&format!("{}: ", input.name)); + clean::SelfBorrowed(None, mtbl) => { + args.push_str(&format!("{}{}self", amp, mtbl.print_with_space())); + args_plain.push_str(&format!("&{}self", mtbl.print_with_space())); } - - if f.alternate() { - args.push_str(&format!("{:#}", input.type_.print(cache))); - } else { - args.push_str(&input.type_.print(cache).to_string()); + clean::SelfExplicit(ref typ) => { + if f.alternate() { + args.push_str(&format!("self: {:#}", typ.print(cache, tcx))); + } else { + args.push_str(&format!("self: {}", typ.print(cache, tcx))); + } + args_plain.push_str(&format!("self: {:#}", typ.print(cache, tcx))); } - args_plain.push_str(&format!("{:#}", input.type_.print(cache))); } - if i + 1 < decl.inputs.values.len() { - args.push(','); - args_plain.push(','); + } else { + if i > 0 { + args.push_str("
"); + args_plain.push(' '); + } + if !input.name.is_empty() { + args.push_str(&format!("{}: ", input.name)); + args_plain.push_str(&format!("{}: ", input.name)); } - } - - let mut args_plain = format!("({})", args_plain); - if decl.c_variadic { - args.push_str(",
..."); - args_plain.push_str(", ..."); + if f.alternate() { + args.push_str(&format!("{:#}", input.type_.print(cache, tcx))); + } else { + args.push_str(&input.type_.print(cache, tcx).to_string()); + } + args_plain.push_str(&format!("{:#}", input.type_.print(cache, tcx))); + } + if i + 1 < self.inputs.values.len() { + args.push(','); + args_plain.push(','); } + } - let output = if let hir::IsAsync::Async = asyncness { - Cow::Owned(decl.sugared_async_return_type()) - } else { - Cow::Borrowed(&decl.output) - }; + let mut args_plain = format!("({})", args_plain); - let arrow_plain = format!("{:#}", &output.print(cache)); - let arrow = if f.alternate() { - format!("{:#}", &output.print(cache)) - } else { - output.print(cache).to_string() - }; + if self.c_variadic { + args.push_str(",
..."); + args_plain.push_str(", ..."); + } - let declaration_len = header_len + args_plain.len() + arrow_plain.len(); - let output = if declaration_len > 80 { - let full_pad = format!("
{}", " ".repeat(indent + 4)); - let close_pad = format!("
{}", " ".repeat(indent)); - format!( - "({args}{close}){arrow}", - args = args.replace("
", &full_pad), - close = close_pad, - arrow = arrow - ) + 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 { - format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) - }; - + format!("{}", output.print(cache, tcx)) + } + } else { + arrow_plain = format!("{:#}", self.output.print(cache, tcx)); if f.alternate() { - write!(f, "{}", output.replace("
", "\n")) + arrow_plain.clone() } else { - write!(f, "{}", output) + format!("{}", self.output.print(cache, tcx)) } - }) + }; + + let declaration_len = header_len + args_plain.len() + arrow_plain.len(); + let output = if declaration_len > 80 { + let full_pad = format!("
{}", " ".repeat(indent + 4)); + let close_pad = format!("
{}", " ".repeat(indent)); + format!( + "({args}{close}){arrow}", + args = args.replace("
", &full_pad), + close = close_pad, + arrow = arrow + ) + } else { + format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) + }; + + if f.alternate() { + write!(f, "{}", output.replace("
", "\n")) + } 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, ": {}", print_generic_bounds(bounds, cache))?; + write!(f, ": {}", 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(<.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), }) } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 05d30187aa853..07bd26a4c5ebe 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -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}; @@ -855,10 +855,12 @@ fn render_impls( traits: &[&&Impl], containing_item: &clean::Item, ) { + let cache = cx.cache(); + let tcx = cx.tcx(); let mut impls = traits .iter() .map(|i| { - let did = i.trait_did_full(cx.cache()).unwrap(); + let did = i.trait_did_full(cache).unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; render_impl( @@ -868,8 +870,8 @@ fn render_impls( containing_item, assoc_link, RenderMode::Normal, - containing_item.stable_since(cx.tcx()).as_deref(), - containing_item.const_stable_since(cx.tcx()).as_deref(), + containing_item.stable_since(tcx).as_deref(), + containing_item.const_stable_since(tcx).as_deref(), true, None, false, @@ -911,14 +913,16 @@ fn assoc_const( extra: &str, cx: &Context<'_>, ) { + let cache = cx.cache(); + let tcx = cx.tcx(); write!( w, "{}{}const {}: {}", extra, - it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), - naive_assoc_href(it, link, cx.cache()), + it.visibility.print_with_space(tcx, it.def_id, cache), + naive_assoc_href(it, link, cache), it.name.as_ref().unwrap(), - ty.print(cx.cache()) + ty.print(cache, tcx) ); } @@ -930,6 +934,7 @@ fn assoc_type( link: AssocItemLink<'_>, extra: &str, cache: &Cache, + tcx: TyCtxt<'_>, ) { write!( w, @@ -939,10 +944,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)) } } @@ -992,6 +997,8 @@ fn render_assoc_item( parent: ItemType, cx: &Context<'_>, ) { + let cache = cx.cache(); + let tcx = cx.tcx(); let name = meth.name.as_ref().unwrap(); let anchor = format!("#{}.{}", meth.type_(), name); let href = match link { @@ -1006,18 +1013,17 @@ fn render_assoc_item( ItemType::TyMethod }; - href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) + href(did, cache).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; - let tcx = cx.tcx(); - let vis = meth.visibility.print_with_space(tcx, meth.def_id, cx.cache()).to_string(); + let vis = meth.visibility.print_with_space(tcx, meth.def_id, cache).to_string(); let constness = header.constness.print_with_space(); let asyncness = header.asyncness.print_with_space(); let unsafety = header.unsafety.print_with_space(); 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(cache, tcx)).len(); let mut header_len = "fn ".len() + vis.len() + constness.len() @@ -1049,11 +1055,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(cache, tcx), + decl = d.full_print(cache, tcx, header_len, indent, header.asyncness), + spotlight = spotlight_decl(&d, cache, tcx), + where_clause = print_where_clause(g, cache, tcx, indent, end_newline), ) } match *item.kind { @@ -1081,6 +1086,7 @@ fn render_assoc_item( link, if parent == ItemType::Trait { " " } else { "" }, cx.cache(), + cx.tcx(), ), _ => panic!("render_assoc_item called on non-associated-item"), } @@ -1155,6 +1161,8 @@ fn render_assoc_items( Some(v) => v, None => return, }; + let tcx = cx.tcx(); + let cache = cx.cache(); let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let render_mode = match what { @@ -1169,12 +1177,10 @@ 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(cache, tcx) ))); - debug!("Adding {} to deref id map", type_.print(cx.cache())); - cx.deref_id_map - .borrow_mut() - .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone()); + debug!("Adding {} to deref id map", type_.print(cache, tcx)); + cx.deref_id_map.borrow_mut().insert(type_.def_id_full(cache).unwrap(), id.clone()); write!( w, "

\ @@ -1182,8 +1188,8 @@ fn render_assoc_items( \

", id = id, - trait_ = trait_.print(cx.cache()), - type_ = type_.print(cx.cache()), + trait_ = trait_.print(cache, tcx), + type_ = type_.print(cache, tcx), ); RenderMode::ForDeref { mut_: deref_mut_ } } @@ -1196,8 +1202,8 @@ fn render_assoc_items( containing_item, AssocItemLink::Anchor(None), render_mode, - containing_item.stable_since(cx.tcx()).as_deref(), - containing_item.const_stable_since(cx.tcx()).as_deref(), + containing_item.stable_since(tcx).as_deref(), + containing_item.const_stable_since(tcx).as_deref(), true, None, false, @@ -1209,11 +1215,11 @@ fn render_assoc_items( if !traits.is_empty() { let deref_impl = traits .iter() - .find(|t| t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did); + .find(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did); if let Some(impl_) = deref_impl { - let has_deref_mut = traits.iter().any(|t| { - t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_mut_trait_did - }); + let has_deref_mut = traits + .iter() + .any(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_mut_trait_did); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } @@ -1335,7 +1341,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 +1357,16 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String { &mut out, "

Notable traits for {}

\ ", - 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, "{}", - 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 +1380,7 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String { AssocItemLink::GotoSource(t_did, &FxHashSet::default()), "", cache, + tcx, ); out.push_str(";
"); } @@ -1413,15 +1420,17 @@ fn render_impl( aliases: &[String], ) { let traits = &cx.cache.traits; - let trait_ = i.trait_did_full(cx.cache()).map(|did| &traits[&did]); + let tcx = cx.tcx(); + let cache = cx.cache(); + let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]); if render_mode == RenderMode::Normal { 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, cache, tcx) } else { - format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx.cache())))) + format!("impl-{}", small_url_encode(format!("{:#}", t.print(cache, tcx)))) } } None => "impl".to_string(), @@ -1433,7 +1442,7 @@ fn render_impl( }; if let Some(use_absolute) = use_absolute { write!(w, "

", id, aliases); - write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute)); + write!(w, "{}", i.inner_impl().print(cache, use_absolute, tcx)); if show_def_docs { for it in &i.inner_impl().items { if let clean::TypedefItem(ref tydef, _) = *it.kind { @@ -1445,7 +1454,8 @@ fn render_impl( Some(&tydef.type_), AssocItemLink::Anchor(None), "", - cx.cache(), + cache, + tcx, ); w.write_str(";"); } @@ -1458,14 +1468,14 @@ fn render_impl( "

{}", id, aliases, - i.inner_impl().print(cx.cache(), false) + i.inner_impl().print(cache, false, tcx) ); } write!(w, "", id); render_stability_since_raw( w, - i.impl_item.stable_since(cx.tcx()).as_deref(), - i.impl_item.const_stable_since(cx.tcx()).as_deref(), + i.impl_item.stable_since(tcx).as_deref(), + i.impl_item.const_stable_since(tcx).as_deref(), outer_version, outer_const_version, ); @@ -1511,6 +1521,7 @@ fn render_impl( ) { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); + let tcx = cx.tcx(); let render_method_item = match render_mode { RenderMode::Normal => true, @@ -1538,8 +1549,8 @@ fn render_impl( w.write_str(""); render_stability_since_raw( w, - item.stable_since(cx.tcx()).as_deref(), - item.const_stable_since(cx.tcx()).as_deref(), + item.stable_since(tcx).as_deref(), + item.const_stable_since(tcx).as_deref(), outer_version, outer_const_version, ); @@ -1558,6 +1569,7 @@ fn render_impl( link.anchor(&id), "", cx.cache(), + tcx, ); w.write_str("

"); } @@ -1568,8 +1580,8 @@ fn render_impl( w.write_str(""); render_stability_since_raw( w, - item.stable_since(cx.tcx()).as_deref(), - item.const_stable_since(cx.tcx()).as_deref(), + item.stable_since(tcx).as_deref(), + item.const_stable_since(tcx).as_deref(), outer_version, outer_const_version, ); @@ -1579,7 +1591,16 @@ fn render_impl( clean::AssocTypeItem(ref bounds, ref default) => { let id = cx.derive_id(format!("{}.{}", item_type, name)); write!(w, "

", 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(), + tcx, + ); w.write_str("

"); } clean::StrippedItem(..) => return, @@ -1882,6 +1903,8 @@ fn small_url_encode(s: String) -> String { fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { if let Some(v) = cx.cache.impls.get(&it.def_id) { let mut used_links = FxHashSet::default(); + let tcx = cx.tcx(); + let cache = cx.cache(); { let used_links_bor = &mut used_links; @@ -1911,7 +1934,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { if let Some(impl_) = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did) { sidebar_deref_methods(cx, out, impl_, v); } @@ -1922,9 +1945,9 @@ 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(cache, tcx)); let out = Escape(&i_display); - let encoded = small_url_encode(format!("{:#}", i.print(cx.cache()))); + let encoded = small_url_encode(format!("{:#}", i.print(cache, tcx))); let generated = format!( "{}{}", encoded, @@ -1988,6 +2011,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) { let c = cx.cache(); + let tcx = cx.tcx(); debug!("found Deref: {:?}", impl_); if let Some((target, real_target)) = @@ -2000,8 +2024,8 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V }) { debug!("found target, real_target: {:?} {:?}", target, real_target); - if let Some(did) = target.def_id_full(cx.cache()) { - if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) { + if let Some(did) = target.def_id_full(c) { + if let Some(type_did) = impl_.inner_impl().for_.def_id_full(c) { // `impl Deref for S` if did == type_did { // Avoid infinite cycles @@ -2012,9 +2036,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V let deref_mut = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .any(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_mut_trait_did); + .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did); let inner_impl = target - .def_id_full(cx.cache()) + .def_id_full(c) .or_else(|| { target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned()) }) @@ -2030,14 +2054,17 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V if !ret.is_empty() { let deref_id_map = cx.deref_id_map.borrow(); let id = deref_id_map - .get(&real_target.def_id_full(cx.cache()).unwrap()) + .get(&real_target.def_id_full(c).unwrap()) .expect("Deref section without derived id"); write!( out, "Methods from {}<Target={}>", 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(); @@ -2050,12 +2077,12 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V } // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id_full(cx.cache()) { + if let Some(target_did) = target.def_id_full(c) { if let Some(target_impls) = c.impls.get(&target_did) { if let Some(target_deref_impl) = target_impls .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did) { sidebar_deref_methods(cx, out, target_deref_impl, target_impls); } @@ -2094,17 +2121,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 @@ -2184,15 +2220,17 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean ); if let Some(implementors) = cx.cache.implementors.get(&it.def_id) { + let cache = cx.cache(); + let tcx = cx.tcx(); let mut res = implementors .iter() .filter(|i| { i.inner_impl() .for_ - .def_id_full(cx.cache()) + .def_id_full(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, cache, tcx)) .collect::>(); if !res.is_empty() { diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c3c4c4952b3b4..cc93e55fc676e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -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, "{}{}", 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("
");
@@ -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::>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>();
     let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>();
@@ -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 {}{}{} = {};
", 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};", 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_};", 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, "", 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(", ") } - 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(", "); } - 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
", 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(";"); } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 501d8e8e02e84..dc96755211622 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -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()), }) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 073209c2468a0..7516fc1eaa17a 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -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 { + fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self; +} + +crate trait IntoWithTcx { + fn into_tcx(self, tcx: TyCtxt<'_>) -> T; +} + +impl IntoWithTcx for T +where + U: FromWithTcx, +{ + 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 for GenericArgs { - fn from(args: clean::GenericArgs) -> Self { +impl FromWithTcx 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 for GenericArg { - fn from(arg: clean::GenericArg) -> Self { +impl FromWithTcx 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 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 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.type_.into_tcx(tcx), expr, value, is_literal } } } -impl From for TypeBinding { - fn from(binding: clean::TypeBinding) -> Self { - TypeBinding { name: binding.name.to_string(), binding: binding.kind.into() } +impl FromWithTcx 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 for TypeBindingKind { - fn from(kind: clean::TypeBindingKind) -> Self { +impl FromWithTcx 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) -> 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 for Module { - fn from(module: clean::Module) -> Self { +impl FromWithTcx for Module { + fn from_tcx(module: clean::Module, _tcx: TyCtxt<'_>) -> Self { Module { is_crate: module.is_crate, items: ids(module.items) } } } -impl From for Struct { - fn from(struct_: clean::Struct) -> Self { +impl FromWithTcx 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 for Struct { } } -impl From for Union { - fn from(struct_: clean::Union) -> Self { +impl FromWithTcx 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 { v } -impl From for Function { - fn from(function: clean::Function) -> Self { +impl FromWithTcx 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 for Generics { - fn from(generics: clean::Generics) -> Self { +impl FromWithTcx 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 for GenericParamDef { - fn from(generic_param: clean::GenericParamDef) -> Self { - GenericParamDef { name: generic_param.name.to_string(), kind: generic_param.kind.into() } +impl FromWithTcx 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 for GenericParamDefKind { - fn from(kind: clean::GenericParamDefKind) -> Self { +impl FromWithTcx 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 for WherePredicate { - fn from(predicate: clean::WherePredicate) -> Self { +impl FromWithTcx 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 for GenericBound { - fn from(bound: clean::GenericBound) -> Self { +impl FromWithTcx 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 for Type { - fn from(ty: clean::Type) -> Self { +impl FromWithTcx 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 for FunctionPointer { - fn from(bare_decl: clean::BareFunctionDecl) -> Self { +impl FromWithTcx 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 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 for FnDecl { - fn from(decl: clean::FnDecl) -> Self { +impl FromWithTcx 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 for FnDecl { } } -impl From for Trait { - fn from(trait_: clean::Trait) -> Self { +impl FromWithTcx 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 for Impl { - fn from(impl_: clean::Impl) -> Self { +impl FromWithTcx for Impl { + fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { let clean::Impl { unsafety, generics, @@ -436,37 +462,41 @@ impl From 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 for Enum { - fn from(enum_: clean::Enum) -> Self { +impl FromWithTcx 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 for Enum { } } -impl From for Struct { - fn from(struct_: clean::VariantStruct) -> Self { +impl FromWithTcx 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 for Struct { } } -impl From for Variant { - fn from(variant: clean::Variant) -> Self { +impl FromWithTcx 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 for Import { - fn from(import: clean::Import) -> Self { +impl FromWithTcx 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 for Import { } } -impl From for ProcMacro { - fn from(mac: clean::ProcMacro) -> Self { +impl FromWithTcx 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 for Typedef { - fn from(typedef: clean::Typedef) -> Self { +impl FromWithTcx 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 for OpaqueTy { - fn from(opaque: clean::OpaqueTy) -> Self { +impl FromWithTcx 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 { - Static { - type_: stat.type_.into(), - mutable: stat.mutability == ast::Mutability::Mut, - expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(), +impl FromWithTcx for Static { + fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { + Static { + 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 for TraitAlias { - fn from(alias: clean::TraitAlias) -> Self { +impl FromWithTcx 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 for ItemKind { - fn from(kind: ItemType) -> Self { +impl FromWithTcx for ItemKind { + fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self { use ItemType::*; match kind { Module => ItemKind::Module, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index a4cdad69865ff..6d18dbe67e405 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -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(), diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index a2f8eb3772efd..ad269413ac6c5 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -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 + ); } } _ => {