Skip to content

Commit d308bee

Browse files
committed
add ?Dynsized support to rustic
1 parent 76ab610 commit d308bee

File tree

1 file changed

+77
-16
lines changed

1 file changed

+77
-16
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,33 @@ impl TyParamBound {
734734
}
735735
false
736736
}
737+
738+
fn maybe_dynsized(cx: &DocContext) -> TyParamBound {
739+
let did = cx.tcx.require_lang_item(lang_items::DynSizedTraitLangItem);
740+
let empty = cx.tcx.intern_substs(&[]);
741+
let path = external_path(cx, &cx.tcx.item_name(did),
742+
Some(did), false, vec![], empty);
743+
inline::record_extern_fqn(cx, did, TypeKind::Trait);
744+
TraitBound(PolyTrait {
745+
trait_: ResolvedPath {
746+
path,
747+
typarams: None,
748+
did,
749+
is_generic: false,
750+
},
751+
lifetimes: vec![]
752+
}, hir::TraitBoundModifier::Maybe)
753+
}
754+
755+
fn is_dynsized_bound(&self, cx: &DocContext) -> bool {
756+
use rustc::hir::TraitBoundModifier as TBM;
757+
if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
758+
if trait_.def_id() == cx.tcx.lang_items().dynsized_trait() {
759+
return true;
760+
}
761+
}
762+
false
763+
}
737764
}
738765

739766
impl Clean<TyParamBound> for hir::TyParamBound {
@@ -1089,36 +1116,47 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
10891116

10901117
let mut where_predicates = preds.predicates.to_vec().clean(cx);
10911118

1092-
// Type parameters and have a Sized bound by default unless removed with
1093-
// ?Sized. Scan through the predicates and mark any type parameter with
1094-
// a Sized bound, removing the bounds as we find them.
1119+
// Type parameters have a Sized bound by default unless removed with
1120+
// ?Sized or ?DynSized. Scan through the predicates and mark any type parameter with
1121+
// a Sized or DynSized bound, removing the bounds as we find them.
10951122
//
10961123
// Note that associated types also have a sized bound by default, but we
10971124
// don't actually know the set of associated types right here so that's
10981125
// handled in cleaning associated types
10991126
let mut sized_params = FxHashSet();
1127+
let mut dynsized_params = FxHashSet();
11001128
where_predicates.retain(|pred| {
11011129
match *pred {
11021130
WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
1103-
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
1104-
sized_params.insert(g.clone());
1105-
false
1106-
} else {
1107-
true
1131+
let mut retain = true;
1132+
for bound in bounds.iter() {
1133+
if bound.is_sized_bound(cx) {
1134+
sized_params.insert(g.clone());
1135+
retain = false;
1136+
} else if bound.is_dynsized_bound(cx) {
1137+
dynsized_params.insert(g.clone());
1138+
retain = false;
1139+
}
11081140
}
1141+
retain
11091142
}
11101143
_ => true,
11111144
}
11121145
});
11131146

1114-
// Run through the type parameters again and insert a ?Sized
1147+
// Run through the type parameters again and insert a ?Sized or ?DynSized
11151148
// unbound for any we didn't find to be Sized.
11161149
for tp in &stripped_typarams {
11171150
if !sized_params.contains(&tp.name) {
11181151
where_predicates.push(WP::BoundPredicate {
11191152
ty: Type::Generic(tp.name.clone()),
11201153
bounds: vec![TyParamBound::maybe_sized(cx)],
11211154
})
1155+
} else if !dynsized_params.contains(&tp.name) {
1156+
where_predicates.push(WP::BoundPredicate {
1157+
ty: Type::Generic(tp.name.clone()),
1158+
bounds: vec![TyParamBound::maybe_dynsized(cx)],
1159+
})
11221160
}
11231161
}
11241162

@@ -1532,14 +1570,37 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
15321570
vec![]
15331571
};
15341572

1535-
// Our Sized/?Sized bound didn't get handled when creating the generics
1573+
// Our Sized/?Sized/?DynSized bound didn't get handled when creating the generics
15361574
// because we didn't actually get our whole set of bounds until just now
1537-
// (some of them may have come from the trait). If we do have a sized
1538-
// bound, we remove it, and if we don't then we add the `?Sized` bound
1539-
// at the end.
1540-
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
1541-
Some(i) => { bounds.remove(i); }
1542-
None => bounds.push(TyParamBound::maybe_sized(cx)),
1575+
// (some of them may have come from the trait).
1576+
//
1577+
// We remove `Sized` and `DynSized` bounds, and then possibly add `?Sized`
1578+
// or `?DynSized`.
1579+
//
1580+
// It's theoretically possible to have a `Sized` bound without a `DynSized` bound.
1581+
// It means the same as having both, since `DynSized` is a supertrait of `Sized`
1582+
let mut has_sized_bound = false;
1583+
let mut has_dynsized_bound = false;
1584+
bounds.retain(|bound| {
1585+
if bound.is_sized_bound(cx) {
1586+
has_sized_bound = true;
1587+
false
1588+
} else if bound.is_dynsized_bound(cx) {
1589+
has_dynsized_bound = true;
1590+
false
1591+
} else {
1592+
true
1593+
}
1594+
});
1595+
if has_sized_bound {
1596+
// T
1597+
// don't push anything
1598+
} else if has_dynsized_bound {
1599+
// T: ?Sized
1600+
bounds.push(TyParamBound::maybe_sized(cx));
1601+
} else {
1602+
// T: ?DynSized
1603+
bounds.push(TyParamBound::maybe_dynsized(cx));
15431604
}
15441605

15451606
let ty = if self.defaultness.has_value() {

0 commit comments

Comments
 (0)