make generic projection types print correctly
This commit is contained in:
parent
ca6e06efba
commit
aefc0a223a
8 changed files with 107 additions and 41 deletions
|
@ -546,11 +546,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
WherePredicate::EqPredicate { lhs, rhs } => {
|
WherePredicate::EqPredicate { lhs, rhs } => {
|
||||||
match lhs {
|
match lhs {
|
||||||
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
|
Type::QPath { ref assoc, ref self_type, ref trait_, .. } => {
|
||||||
let ty = &*self_type;
|
let ty = &*self_type;
|
||||||
let mut new_trait = trait_.clone();
|
let mut new_trait = trait_.clone();
|
||||||
|
|
||||||
if self.is_fn_trait(trait_) && left_name == sym::Output {
|
if self.is_fn_trait(trait_) && assoc.name == sym::Output {
|
||||||
ty_to_fn
|
ty_to_fn
|
||||||
.entry(*ty.clone())
|
.entry(*ty.clone())
|
||||||
.and_modify(|e| {
|
.and_modify(|e| {
|
||||||
|
@ -571,7 +571,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
// to 'T: Iterator<Item=u8>'
|
// to 'T: Iterator<Item=u8>'
|
||||||
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
|
||||||
bindings.push(TypeBinding {
|
bindings.push(TypeBinding {
|
||||||
name: left_name,
|
assoc: *assoc.clone(),
|
||||||
kind: TypeBindingKind::Equality { term: rhs },
|
kind: TypeBindingKind::Equality { term: rhs },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,7 +636,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
||||||
|
|
||||||
g.where_predicates.retain(|pred| match pred {
|
g.where_predicates.retain(|pred| match pred {
|
||||||
clean::WherePredicate::BoundPredicate {
|
clean::WherePredicate::BoundPredicate {
|
||||||
ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, name: _, .. },
|
ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. },
|
||||||
bounds,
|
bounds,
|
||||||
..
|
..
|
||||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
} => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
|
||||||
|
|
|
@ -388,7 +388,7 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
||||||
let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
|
let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
|
||||||
let self_type = self.self_ty().clean(cx);
|
let self_type = self.self_ty().clean(cx);
|
||||||
Type::QPath {
|
Type::QPath {
|
||||||
name: cx.tcx.associated_item(self.item_def_id).name,
|
assoc: Box::new(projection_to_path_segment(*self, cx)),
|
||||||
self_def_id: self_type.def_id(&cx.cache),
|
self_def_id: self_type.def_id(&cx.cache),
|
||||||
self_type: box self_type,
|
self_type: box self_type,
|
||||||
trait_,
|
trait_,
|
||||||
|
@ -396,6 +396,27 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn projection_to_path_segment(ty: ty::ProjectionTy<'_>, cx: &mut DocContext<'_>) -> PathSegment {
|
||||||
|
let item = cx.tcx.associated_item(ty.item_def_id);
|
||||||
|
let generics = cx.tcx.generics_of(ty.item_def_id);
|
||||||
|
PathSegment {
|
||||||
|
name: item.name,
|
||||||
|
args: GenericArgs::AngleBracketed {
|
||||||
|
args: ty.substs[generics.parent_count..]
|
||||||
|
.iter()
|
||||||
|
.map(|ty| match ty.unpack() {
|
||||||
|
ty::subst::GenericArgKind::Lifetime(lt) => {
|
||||||
|
GenericArg::Lifetime(lt.clean(cx).unwrap())
|
||||||
|
}
|
||||||
|
ty::subst::GenericArgKind::Type(ty) => GenericArg::Type(ty.clean(cx)),
|
||||||
|
ty::subst::GenericArgKind::Const(c) => GenericArg::Const(Box::new(c.clean(cx))),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
bindings: Default::default(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clean<GenericParamDef> for ty::GenericParamDef {
|
impl Clean<GenericParamDef> for ty::GenericParamDef {
|
||||||
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
|
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
|
||||||
let (name, kind) = match self.kind {
|
let (name, kind) = match self.kind {
|
||||||
|
@ -601,8 +622,8 @@ fn clean_ty_generics(
|
||||||
})
|
})
|
||||||
.collect::<Vec<GenericParamDef>>();
|
.collect::<Vec<GenericParamDef>>();
|
||||||
|
|
||||||
// param index -> [(DefId of trait, associated type name, type)]
|
// param index -> [(DefId of trait, associated type name and generics, type)]
|
||||||
let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'_>)>>::default();
|
let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>)>>::default();
|
||||||
|
|
||||||
let where_predicates = preds
|
let where_predicates = preds
|
||||||
.predicates
|
.predicates
|
||||||
|
@ -648,8 +669,9 @@ fn clean_ty_generics(
|
||||||
|
|
||||||
let proj = projection
|
let proj = projection
|
||||||
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term));
|
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().term));
|
||||||
if let Some(((_, trait_did, name), rhs)) =
|
if let Some(((_, trait_did, name), rhs)) = proj
|
||||||
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
|
.as_ref()
|
||||||
|
.and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
|
||||||
{
|
{
|
||||||
// FIXME(...): Remove this unwrap()
|
// FIXME(...): Remove this unwrap()
|
||||||
impl_trait_proj.entry(param_idx).or_default().push((
|
impl_trait_proj.entry(param_idx).or_default().push((
|
||||||
|
@ -985,7 +1007,7 @@ impl Clean<Item> for hir::TraitItem<'_> {
|
||||||
TyMethodItem(t)
|
TyMethodItem(t)
|
||||||
}
|
}
|
||||||
hir::TraitItemKind::Type(bounds, ref default) => {
|
hir::TraitItemKind::Type(bounds, ref default) => {
|
||||||
let generics = self.generics.clean(cx);
|
let generics = enter_impl_trait(cx, |cx| self.generics.clean(cx));
|
||||||
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
|
let bounds = bounds.iter().filter_map(|x| x.clean(cx)).collect();
|
||||||
let default = default.map(|t| t.clean(cx));
|
let default = default.map(|t| t.clean(cx));
|
||||||
AssocTypeItem(Box::new(generics), bounds, default)
|
AssocTypeItem(Box::new(generics), bounds, default)
|
||||||
|
@ -1136,6 +1158,27 @@ impl Clean<Item> for ty::AssocItem {
|
||||||
ty::AssocKind::Type => {
|
ty::AssocKind::Type => {
|
||||||
let my_name = self.name;
|
let my_name = self.name;
|
||||||
|
|
||||||
|
fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
|
||||||
|
match (¶m.kind, arg) {
|
||||||
|
(GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
|
||||||
|
if *ty == param.name =>
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
(
|
||||||
|
GenericParamDefKind::Lifetime { .. },
|
||||||
|
GenericArg::Lifetime(Lifetime(lt)),
|
||||||
|
) if *lt == param.name => true,
|
||||||
|
(GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => {
|
||||||
|
match &c.kind {
|
||||||
|
ConstantKind::TyConst { expr } => expr == param.name.as_str(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let ty::TraitContainer(_) = self.container {
|
if let ty::TraitContainer(_) = self.container {
|
||||||
let bounds = tcx.explicit_item_bounds(self.def_id);
|
let bounds = tcx.explicit_item_bounds(self.def_id);
|
||||||
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
|
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
|
||||||
|
@ -1147,10 +1190,10 @@ impl Clean<Item> for ty::AssocItem {
|
||||||
.where_predicates
|
.where_predicates
|
||||||
.drain_filter(|pred| match *pred {
|
.drain_filter(|pred| match *pred {
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: QPath { name, ref self_type, ref trait_, .. },
|
ty: QPath { ref assoc, ref self_type, ref trait_, .. },
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if name != my_name {
|
if assoc.name != my_name {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if trait_.def_id() != self.container.id() {
|
if trait_.def_id() != self.container.id() {
|
||||||
|
@ -1267,7 +1310,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
|
||||||
};
|
};
|
||||||
register_res(cx, trait_.res);
|
register_res(cx, trait_.res);
|
||||||
Type::QPath {
|
Type::QPath {
|
||||||
name: p.segments.last().expect("segments were empty").ident.name,
|
assoc: Box::new(p.segments.last().expect("segments were empty").clean(cx)),
|
||||||
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
|
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
|
||||||
self_type: box qself.clean(cx),
|
self_type: box qself.clean(cx),
|
||||||
trait_,
|
trait_,
|
||||||
|
@ -1284,7 +1327,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
|
||||||
let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
|
let trait_ = hir::Path { span, res, segments: &[] }.clean(cx);
|
||||||
register_res(cx, trait_.res);
|
register_res(cx, trait_.res);
|
||||||
Type::QPath {
|
Type::QPath {
|
||||||
name: segment.ident.name,
|
assoc: Box::new(segment.clean(cx)),
|
||||||
self_def_id: res.opt_def_id(),
|
self_def_id: res.opt_def_id(),
|
||||||
self_type: box qself.clean(cx),
|
self_type: box qself.clean(cx),
|
||||||
trait_,
|
trait_,
|
||||||
|
@ -1557,7 +1600,16 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||||
let mut bindings = vec![];
|
let mut bindings = vec![];
|
||||||
for pb in obj.projection_bounds() {
|
for pb in obj.projection_bounds() {
|
||||||
bindings.push(TypeBinding {
|
bindings.push(TypeBinding {
|
||||||
name: cx.tcx.associated_item(pb.item_def_id()).name,
|
assoc: projection_to_path_segment(
|
||||||
|
pb.skip_binder()
|
||||||
|
.lift_to_tcx(cx.tcx)
|
||||||
|
.unwrap()
|
||||||
|
// HACK(compiler-errors): Doesn't actually matter what self
|
||||||
|
// type we put here, because we're only using the GAT's substs.
|
||||||
|
.with_self_ty(cx.tcx, cx.tcx.types.self_param)
|
||||||
|
.projection_ty,
|
||||||
|
cx,
|
||||||
|
),
|
||||||
kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
|
kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1623,10 +1675,10 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||||
== trait_ref.skip_binder()
|
== trait_ref.skip_binder()
|
||||||
{
|
{
|
||||||
Some(TypeBinding {
|
Some(TypeBinding {
|
||||||
name: cx
|
assoc: projection_to_path_segment(
|
||||||
.tcx
|
proj.projection_ty,
|
||||||
.associated_item(proj.projection_ty.item_def_id)
|
cx,
|
||||||
.name,
|
),
|
||||||
kind: TypeBindingKind::Equality {
|
kind: TypeBindingKind::Equality {
|
||||||
term: proj.term.clean(cx),
|
term: proj.term.clean(cx),
|
||||||
},
|
},
|
||||||
|
@ -2169,7 +2221,10 @@ fn clean_maybe_renamed_foreign_item(
|
||||||
|
|
||||||
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
|
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
|
||||||
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
|
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
|
||||||
TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
|
TypeBinding {
|
||||||
|
assoc: PathSegment { name: self.ident.name, args: self.gen_args.clean(cx) },
|
||||||
|
kind: self.kind.clean(cx),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ crate fn merge_bounds(
|
||||||
cx: &clean::DocContext<'_>,
|
cx: &clean::DocContext<'_>,
|
||||||
bounds: &mut Vec<clean::GenericBound>,
|
bounds: &mut Vec<clean::GenericBound>,
|
||||||
trait_did: DefId,
|
trait_did: DefId,
|
||||||
name: Symbol,
|
assoc: clean::PathSegment,
|
||||||
rhs: &clean::Term,
|
rhs: &clean::Term,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
!bounds.iter_mut().any(|b| {
|
!bounds.iter_mut().any(|b| {
|
||||||
|
@ -107,7 +107,7 @@ crate fn merge_bounds(
|
||||||
match last.args {
|
match last.args {
|
||||||
PP::AngleBracketed { ref mut bindings, .. } => {
|
PP::AngleBracketed { ref mut bindings, .. } => {
|
||||||
bindings.push(clean::TypeBinding {
|
bindings.push(clean::TypeBinding {
|
||||||
name,
|
assoc: assoc.clone(),
|
||||||
kind: clean::TypeBindingKind::Equality { term: rhs.clone() },
|
kind: clean::TypeBindingKind::Equality { term: rhs.clone() },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1397,7 +1397,7 @@ crate enum Type {
|
||||||
|
|
||||||
/// A qualified path to an associated item: `<Type as Trait>::Name`
|
/// A qualified path to an associated item: `<Type as Trait>::Name`
|
||||||
QPath {
|
QPath {
|
||||||
name: Symbol,
|
assoc: Box<PathSegment>,
|
||||||
self_type: Box<Type>,
|
self_type: Box<Type>,
|
||||||
/// FIXME: This is a hack that should be removed; see [this discussion][1].
|
/// FIXME: This is a hack that should be removed; see [this discussion][1].
|
||||||
///
|
///
|
||||||
|
@ -1415,7 +1415,7 @@ crate enum Type {
|
||||||
|
|
||||||
// `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `Type` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(Type, 72);
|
rustc_data_structures::static_assert_size!(Type, 80);
|
||||||
|
|
||||||
impl Type {
|
impl Type {
|
||||||
/// When comparing types for equality, it can help to ignore `&` wrapping.
|
/// When comparing types for equality, it can help to ignore `&` wrapping.
|
||||||
|
@ -1505,12 +1505,12 @@ impl Type {
|
||||||
self.primitive_type().is_some()
|
self.primitive_type().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
|
crate fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
|
||||||
let (self_, trait_, name) = match self {
|
let (self_, trait_, assoc) = match self {
|
||||||
QPath { self_type, trait_, name, .. } => (self_type, trait_, name),
|
QPath { self_type, trait_, assoc, .. } => (self_type, trait_, assoc),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some((&self_, trait_.def_id(), *name))
|
Some((&self_, trait_.def_id(), *assoc.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
|
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
|
||||||
|
@ -2018,7 +2018,7 @@ crate enum GenericArg {
|
||||||
// `GenericArg` can occur many times in a single `Path`, so make sure it
|
// `GenericArg` can occur many times in a single `Path`, so make sure it
|
||||||
// doesn't increase in size unexpectedly.
|
// doesn't increase in size unexpectedly.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(GenericArg, 80);
|
rustc_data_structures::static_assert_size!(GenericArg, 88);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
crate enum GenericArgs {
|
crate enum GenericArgs {
|
||||||
|
@ -2256,7 +2256,7 @@ crate struct ProcMacro {
|
||||||
/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
|
/// `A: Send + Sync` in `Foo<A: Send + Sync>`).
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
crate struct TypeBinding {
|
crate struct TypeBinding {
|
||||||
crate name: Symbol,
|
crate assoc: PathSegment,
|
||||||
crate kind: TypeBindingKind,
|
crate kind: TypeBindingKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -961,7 +961,7 @@ fn fmt_type<'cx>(
|
||||||
write!(f, "impl {}", print_generic_bounds(bounds, cx))
|
write!(f, "impl {}", print_generic_bounds(bounds, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean::QPath { ref name, ref self_type, ref trait_, ref self_def_id } => {
|
clean::QPath { ref assoc, ref self_type, ref trait_, ref self_def_id } => {
|
||||||
let should_show_cast = !trait_.segments.is_empty()
|
let should_show_cast = !trait_.segments.is_empty()
|
||||||
&& self_def_id
|
&& self_def_id
|
||||||
.zip(Some(trait_.def_id()))
|
.zip(Some(trait_.def_id()))
|
||||||
|
@ -994,14 +994,15 @@ fn fmt_type<'cx>(
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
|
"<a class=\"associatedtype\" href=\"{url}#{shortty}.{name}\" \
|
||||||
title=\"type {path}::{name}\">{name}</a>",
|
title=\"type {path}::{name}\">{name}</a>{args}",
|
||||||
url = url,
|
url = url,
|
||||||
shortty = ItemType::AssocType,
|
shortty = ItemType::AssocType,
|
||||||
name = name,
|
name = assoc.name,
|
||||||
path = join_with_double_colon(path),
|
path = join_with_double_colon(path),
|
||||||
|
args = assoc.args.print(cx),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
_ => write!(f, "{}", name)?,
|
_ => write!(f, "{}{:#}", assoc.name, assoc.args.print(cx))?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1457,7 +1458,12 @@ impl clean::TypeBinding {
|
||||||
cx: &'a Context<'tcx>,
|
cx: &'a Context<'tcx>,
|
||||||
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
) -> impl fmt::Display + 'a + Captures<'tcx> {
|
||||||
display_fn(move |f| {
|
display_fn(move |f| {
|
||||||
f.write_str(self.name.as_str())?;
|
f.write_str(self.assoc.name.as_str())?;
|
||||||
|
if f.alternate() {
|
||||||
|
write!(f, "{:#}", self.assoc.args.print(cx))?;
|
||||||
|
} else {
|
||||||
|
write!(f, "{}", self.assoc.args.print(cx))?;
|
||||||
|
}
|
||||||
match self.kind {
|
match self.kind {
|
||||||
clean::TypeBindingKind::Equality { ref term } => {
|
clean::TypeBindingKind::Equality { ref term } => {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
|
|
|
@ -154,7 +154,11 @@ impl FromWithTcx<clean::Constant> for Constant {
|
||||||
|
|
||||||
impl FromWithTcx<clean::TypeBinding> for TypeBinding {
|
impl FromWithTcx<clean::TypeBinding> for TypeBinding {
|
||||||
fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
|
||||||
TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) }
|
TypeBinding {
|
||||||
|
name: binding.assoc.name.to_string(),
|
||||||
|
args: binding.assoc.args.into_tcx(tcx),
|
||||||
|
binding: binding.kind.into_tcx(tcx),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,11 +449,12 @@ impl FromWithTcx<clean::Type> for Type {
|
||||||
mutable: mutability == ast::Mutability::Mut,
|
mutable: mutability == ast::Mutability::Mut,
|
||||||
type_: Box::new((*type_).into_tcx(tcx)),
|
type_: Box::new((*type_).into_tcx(tcx)),
|
||||||
},
|
},
|
||||||
QPath { name, self_type, trait_, .. } => {
|
QPath { assoc, self_type, trait_, .. } => {
|
||||||
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
|
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
|
||||||
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
|
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
|
||||||
Type::QualifiedPath {
|
Type::QualifiedPath {
|
||||||
name: name.to_string(),
|
name: assoc.name.to_string(),
|
||||||
|
args: Box::new(assoc.args.clone().into_tcx(tcx)),
|
||||||
self_type: Box::new((*self_type).into_tcx(tcx)),
|
self_type: Box::new((*self_type).into_tcx(tcx)),
|
||||||
trait_: Box::new(trait_),
|
trait_: Box::new(trait_),
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::path::PathBuf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// rustdoc format-version.
|
/// rustdoc format-version.
|
||||||
pub const FORMAT_VERSION: u32 = 11;
|
pub const FORMAT_VERSION: u32 = 12;
|
||||||
|
|
||||||
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
||||||
/// about the language items in the local crate, as well as info about external items to allow
|
/// about the language items in the local crate, as well as info about external items to allow
|
||||||
|
@ -145,6 +145,7 @@ pub struct Constant {
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct TypeBinding {
|
pub struct TypeBinding {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub args: GenericArgs,
|
||||||
pub binding: TypeBindingKind,
|
pub binding: TypeBindingKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +234,7 @@ pub enum ItemEnum {
|
||||||
default: Option<String>,
|
default: Option<String>,
|
||||||
},
|
},
|
||||||
AssocType {
|
AssocType {
|
||||||
/// generics and `where` clause
|
|
||||||
generics: Generics,
|
generics: Generics,
|
||||||
/// e.g. `: Sized`
|
|
||||||
bounds: Vec<GenericBound>,
|
bounds: Vec<GenericBound>,
|
||||||
/// e.g. `type X = usize;`
|
/// e.g. `type X = usize;`
|
||||||
default: Option<Type>,
|
default: Option<Type>,
|
||||||
|
@ -435,6 +434,7 @@ pub enum Type {
|
||||||
/// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
|
/// `<Type as Trait>::Name` or associated types like `T::Item` where `T: Iterator`
|
||||||
QualifiedPath {
|
QualifiedPath {
|
||||||
name: String,
|
name: String,
|
||||||
|
args: Box<GenericArgs>,
|
||||||
self_type: Box<Type>,
|
self_type: Box<Type>,
|
||||||
#[serde(rename = "trait")]
|
#[serde(rename = "trait")]
|
||||||
trait_: Box<Type>,
|
trait_: Box<Type>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue