Skip to content

Commit 4ea2748

Browse files
committed
rustdoc: Introduce new DynTrait type for better representation of trait objects
1 parent 1f65f56 commit 4ea2748

File tree

9 files changed

+117
-116
lines changed

9 files changed

+117
-116
lines changed

src/librustdoc/clean/auto_trait.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
353353
let (poly_trait, output) =
354354
(data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
355355
let new_ty = match poly_trait.trait_ {
356-
Type::ResolvedPath {
357-
ref path,
358-
ref param_names,
359-
ref did,
360-
ref is_generic,
361-
} => {
356+
Type::ResolvedPath { ref path, ref did, ref is_generic } => {
362357
let mut new_path = path.clone();
363358
let last_segment =
364359
new_path.segments.pop().expect("segments were empty");
@@ -395,7 +390,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
395390

396391
Type::ResolvedPath {
397392
path: new_path,
398-
param_names: param_names.clone(),
399393
did: *did,
400394
is_generic: *is_generic,
401395
}
@@ -570,7 +564,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
570564
match **trait_ {
571565
Type::ResolvedPath {
572566
path: ref trait_path,
573-
ref param_names,
574567
ref did,
575568
ref is_generic,
576569
} => {
@@ -617,7 +610,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
617610
PolyTrait {
618611
trait_: Type::ResolvedPath {
619612
path: new_trait_path,
620-
param_names: param_names.clone(),
621613
did: *did,
622614
is_generic: *is_generic,
623615
},

src/librustdoc/clean/mod.rs

+26-58
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
180180

181181
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
182182

183-
ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false }
183+
ResolvedPath { path, did: trait_ref.def_id, is_generic: false }
184184
}
185185
}
186186

@@ -1378,30 +1378,9 @@ impl Clean<Type> for hir::Ty<'_> {
13781378
}
13791379
TyKind::Path(_) => clean_qpath(&self, cx),
13801380
TyKind::TraitObject(ref bounds, ref lifetime, _) => {
1381-
let cleaned = bounds[0].clean(cx);
1382-
match cleaned.trait_ {
1383-
ResolvedPath { path, param_names: None, did, is_generic, .. } => {
1384-
let mut bounds: Vec<self::GenericBound> = bounds[1..]
1385-
.iter()
1386-
.map(|bound| {
1387-
self::GenericBound::TraitBound(
1388-
bound.clean(cx),
1389-
hir::TraitBoundModifier::None,
1390-
)
1391-
})
1392-
.collect();
1393-
if !lifetime.is_elided() {
1394-
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
1395-
}
1396-
ResolvedPath {
1397-
path,
1398-
param_names: Some((bounds, cleaned.generic_params)),
1399-
did,
1400-
is_generic,
1401-
}
1402-
}
1403-
_ => Infer, // shouldn't happen
1404-
}
1381+
let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
1382+
let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
1383+
DynTrait(bounds, lifetime)
14051384
}
14061385
TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
14071386
TyKind::Infer | TyKind::Err => Infer,
@@ -1484,7 +1463,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
14841463
};
14851464
inline::record_extern_fqn(cx, did, kind);
14861465
let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
1487-
ResolvedPath { path, param_names: None, did, is_generic: false }
1466+
ResolvedPath { path, did, is_generic: false }
14881467
}
14891468
ty::Foreign(did) => {
14901469
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
@@ -1496,7 +1475,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
14961475
vec![],
14971476
InternalSubsts::empty(),
14981477
);
1499-
ResolvedPath { path, param_names: None, did, is_generic: false }
1478+
ResolvedPath { path, did, is_generic: false }
15001479
}
15011480
ty::Dynamic(ref obj, ref reg) => {
15021481
// HACK: pick the first `did` as the `did` of the trait object. Someone
@@ -1514,28 +1493,19 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
15141493

15151494
inline::record_extern_fqn(cx, did, ItemType::Trait);
15161495

1517-
let mut param_names = vec![];
1518-
if let Some(b) = reg.clean(cx) {
1519-
param_names.push(GenericBound::Outlives(b));
1520-
}
1496+
let lifetime = reg.clean(cx);
1497+
let mut bounds = vec![];
1498+
15211499
for did in dids {
15221500
let empty = cx.tcx.intern_substs(&[]);
15231501
let path =
15241502
external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
15251503
inline::record_extern_fqn(cx, did, ItemType::Trait);
1526-
let bound = GenericBound::TraitBound(
1527-
PolyTrait {
1528-
trait_: ResolvedPath {
1529-
path,
1530-
param_names: None,
1531-
did,
1532-
is_generic: false,
1533-
},
1534-
generic_params: Vec::new(),
1535-
},
1536-
hir::TraitBoundModifier::None,
1537-
);
1538-
param_names.push(bound);
1504+
let bound = PolyTrait {
1505+
trait_: ResolvedPath { path, did, is_generic: false },
1506+
generic_params: Vec::new(),
1507+
};
1508+
bounds.push(bound);
15391509
}
15401510

15411511
let mut bindings = vec![];
@@ -1548,12 +1518,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
15481518

15491519
let path =
15501520
external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
1551-
ResolvedPath {
1552-
path,
1553-
param_names: Some((param_names, vec![])),
1554-
did,
1555-
is_generic: false,
1556-
}
1521+
bounds.insert(
1522+
0,
1523+
PolyTrait {
1524+
trait_: ResolvedPath { path, did, is_generic: false },
1525+
generic_params: Vec::new(),
1526+
},
1527+
);
1528+
1529+
DynTrait(bounds, lifetime)
15571530
}
15581531
ty::Tuple(ref t) => {
15591532
Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
@@ -2257,14 +2230,9 @@ impl From<GenericBound> for SimpleBound {
22572230
match bound.clone() {
22582231
GenericBound::Outlives(l) => SimpleBound::Outlives(l),
22592232
GenericBound::TraitBound(t, mod_) => match t.trait_ {
2260-
Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
2261-
path.segments,
2262-
param_names.map_or_else(Vec::new, |(v, _)| {
2263-
v.iter().map(|p| SimpleBound::from(p.clone())).collect()
2264-
}),
2265-
t.generic_params,
2266-
mod_,
2267-
),
2233+
Type::ResolvedPath { path, .. } => {
2234+
SimpleBound::TraitBound(path.segments, Vec::new(), t.generic_params, mod_)
2235+
}
22682236
_ => panic!("Unexpected bound {:?}", bound),
22692237
},
22702238
}

src/librustdoc/clean/types.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,7 @@ impl GenericBound {
11411141
inline::record_extern_fqn(cx, did, ItemType::Trait);
11421142
GenericBound::TraitBound(
11431143
PolyTrait {
1144-
trait_: ResolvedPath { path, param_names: None, did, is_generic: false },
1144+
trait_: ResolvedPath { path, did, is_generic: false },
11451145
generic_params: Vec::new(),
11461146
},
11471147
hir::TraitBoundModifier::Maybe,
@@ -1407,13 +1407,12 @@ crate enum Type {
14071407
/// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
14081408
ResolvedPath {
14091409
path: Path,
1410-
/// If `param_names` is `Some`, this path is a trait object and the Vecs repsresent
1411-
/// `(generic bounds, generic parameters)`
1412-
param_names: Option<(Vec<GenericBound>, Vec<GenericParamDef>)>,
14131410
did: DefId,
14141411
/// `true` if is a `T::Name` path for associated types.
14151412
is_generic: bool,
14161413
},
1414+
/// `dyn for<'a> Trait<'a> + Send + 'static`
1415+
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
14171416
/// For parameterized types, so the consumer of the JSON don't go
14181417
/// looking for types which don't exist anywhere.
14191418
Generic(Symbol),
@@ -1600,6 +1599,7 @@ impl Type {
16001599
fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
16011600
let t: PrimitiveType = match *self {
16021601
ResolvedPath { did, .. } => return Some(did.into()),
1602+
DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache),
16031603
Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
16041604
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
16051605
BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),

src/librustdoc/clean/utils.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::clean::auto_trait::AutoTraitFinder;
22
use crate::clean::blanket_impl::BlanketImplFinder;
33
use crate::clean::{
44
inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
5-
Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
5+
Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
66
};
77
use crate::core::DocContext;
88
use crate::formats::item_type::ItemType;
@@ -163,8 +163,18 @@ pub(super) fn external_path(
163163

164164
crate fn strip_type(ty: Type) -> Type {
165165
match ty {
166-
Type::ResolvedPath { path, param_names, did, is_generic } => {
167-
Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic }
166+
Type::ResolvedPath { path, did, is_generic } => {
167+
Type::ResolvedPath { path: strip_path(&path), did, is_generic }
168+
}
169+
Type::DynTrait(mut bounds, lt) => {
170+
let first = bounds.remove(0);
171+
let stripped_trait = strip_type(first.trait_);
172+
173+
bounds.insert(
174+
0,
175+
PolyTrait { trait_: stripped_trait, generic_params: first.generic_params },
176+
);
177+
Type::DynTrait(bounds, lt)
168178
}
169179
Type::Tuple(inner_tys) => {
170180
Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
@@ -431,7 +441,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
431441
_ => false,
432442
};
433443
let did = register_res(cx, path.res);
434-
ResolvedPath { path, param_names: None, did, is_generic }
444+
ResolvedPath { path, did, is_generic }
435445
}
436446

437447
crate fn get_auto_trait_and_blanket_impls(

src/librustdoc/formats/cache.rs

+15
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
402402
self.cache.parent_stack.push(did);
403403
true
404404
}
405+
clean::DynTrait(ref bounds, _)
406+
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
407+
if let Some(did) = bounds[0].trait_.def_id() {
408+
self.cache.parent_stack.push(did);
409+
true
410+
} else {
411+
false
412+
}
413+
}
405414
ref t => {
406415
let prim_did = t
407416
.primitive_type()
@@ -432,6 +441,12 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
432441
| clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => {
433442
dids.insert(did);
434443
}
444+
clean::DynTrait(ref bounds, _)
445+
| clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => {
446+
if let Some(did) = bounds[0].trait_.def_id() {
447+
dids.insert(did);
448+
}
449+
}
435450
ref t => {
436451
let did = t
437452
.primitive_type()

src/librustdoc/html/format.rs

+23-37
Original file line numberDiff line numberDiff line change
@@ -646,18 +646,24 @@ fn primitive_link(
646646

647647
/// Helper to render type parameters
648648
fn tybounds<'a, 'tcx: 'a>(
649-
param_names: Option<&'a Vec<clean::GenericBound>>,
649+
bounds: &'a Vec<clean::PolyTrait>,
650+
lt: &'a Option<clean::Lifetime>,
650651
cx: &'a Context<'tcx>,
651652
) -> impl fmt::Display + 'a + Captures<'tcx> {
652-
display_fn(move |f| match param_names {
653-
Some(params) => {
654-
for param in params {
653+
display_fn(move |f| {
654+
for (i, bound) in bounds.iter().enumerate() {
655+
if i > 0 {
655656
write!(f, " + ")?;
656-
fmt::Display::fmt(&param.print(cx), f)?;
657657
}
658-
Ok(())
658+
659+
fmt::Display::fmt(&bound.print(cx), f)?;
659660
}
660-
None => Ok(()),
661+
662+
if let Some(lt) = lt {
663+
write!(f, " + ")?;
664+
fmt::Display::fmt(&lt.print(), f)?;
665+
}
666+
Ok(())
661667
})
662668
}
663669

@@ -694,32 +700,13 @@ fn fmt_type<'cx>(
694700

695701
match *t {
696702
clean::Generic(name) => write!(f, "{}", name),
697-
clean::ResolvedPath { did, ref param_names, ref path, is_generic } => {
698-
let generic_params = param_names.as_ref().map(|(_, x)| x);
699-
let param_names = param_names.as_ref().map(|(x, _)| x);
700-
701-
if let Some(generic_params) = generic_params {
702-
f.write_str("dyn ")?;
703-
704-
if !generic_params.is_empty() {
705-
if f.alternate() {
706-
write!(
707-
f,
708-
"for<{:#}> ",
709-
comma_sep(generic_params.iter().map(|g| g.print(cx)))
710-
)?;
711-
} else {
712-
write!(
713-
f,
714-
"for&lt;{}&gt; ",
715-
comma_sep(generic_params.iter().map(|g| g.print(cx)))
716-
)?;
717-
}
718-
}
719-
}
703+
clean::ResolvedPath { did, ref path, is_generic } => {
720704
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
721-
resolved_path(f, did, path, is_generic, use_absolute, cx)?;
722-
fmt::Display::fmt(&tybounds(param_names, cx), f)
705+
resolved_path(f, did, path, is_generic, use_absolute, cx)
706+
}
707+
clean::DynTrait(ref bounds, ref lt) => {
708+
f.write_str("dyn ")?;
709+
fmt::Display::fmt(&tybounds(bounds, lt, cx), f)
723710
}
724711
clean::Infer => write!(f, "_"),
725712
clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
@@ -854,7 +841,9 @@ fn fmt_type<'cx>(
854841
}
855842
}
856843
}
857-
clean::ResolvedPath { param_names: Some((ref v, _)), .. } if !v.is_empty() => {
844+
clean::DynTrait(ref bounds, ref trait_lt)
845+
if bounds.len() > 1 || trait_lt.is_some() =>
846+
{
858847
write!(f, "{}{}{}(", amp, lt, m)?;
859848
fmt_type(&ty, f, use_absolute, cx)?;
860849
write!(f, ")")
@@ -915,7 +904,7 @@ fn fmt_type<'cx>(
915904
// the ugliness comes from inlining across crates where
916905
// everything comes in as a fully resolved QPath (hard to
917906
// look at).
918-
box clean::ResolvedPath { did, ref param_names, .. } => {
907+
box clean::ResolvedPath { did, .. } => {
919908
match href(did.into(), cx) {
920909
Some((ref url, _, ref path)) if !f.alternate() => {
921910
write!(
@@ -930,9 +919,6 @@ fn fmt_type<'cx>(
930919
}
931920
_ => write!(f, "{}", name)?,
932921
}
933-
934-
// FIXME: `param_names` are not rendered, and this seems bad?
935-
drop(param_names);
936922
Ok(())
937923
}
938924
_ => write!(f, "{}", name),

src/librustdoc/html/render/cache.rs

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
233233
});
234234
Some(path_segment.name)
235235
}
236+
clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic),
236237
clean::Generic(s) if accept_generic => Some(s),
237238
clean::Primitive(ref p) => Some(p.as_sym()),
238239
clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic),

0 commit comments

Comments
 (0)