mirror of https://github.com/rust-lang/rust.git
rustdoc: Render `for<'_>` lifetimes in front of where bound
This commit is contained in:
parent
312b894cc1
commit
e0162a8a56
|
@ -414,7 +414,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
let mut bounds_vec = bounds.into_iter().collect();
|
let mut bounds_vec = bounds.into_iter().collect();
|
||||||
self.sort_where_bounds(&mut bounds_vec);
|
self.sort_where_bounds(&mut bounds_vec);
|
||||||
|
|
||||||
Some(WherePredicate::BoundPredicate { ty, bounds: bounds_vec })
|
Some(WherePredicate::BoundPredicate {
|
||||||
|
ty,
|
||||||
|
bounds: bounds_vec,
|
||||||
|
bound_params: Vec::new(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.chain(
|
.chain(
|
||||||
lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map(
|
lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map(
|
||||||
|
@ -492,7 +496,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
let p = p.unwrap();
|
let p = p.unwrap();
|
||||||
match p {
|
match p {
|
||||||
WherePredicate::BoundPredicate { ty, mut bounds } => {
|
WherePredicate::BoundPredicate { ty, mut bounds, .. } => {
|
||||||
// Writing a projection trait bound of the form
|
// Writing a projection trait bound of the form
|
||||||
// <T as Trait>::Name : ?Sized
|
// <T as Trait>::Name : ?Sized
|
||||||
// is illegal, because ?Sized bounds can only
|
// is illegal, because ?Sized bounds can only
|
||||||
|
|
|
@ -566,9 +566,11 @@ fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::Item
|
||||||
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
||||||
for pred in &mut g.where_predicates {
|
for pred in &mut g.where_predicates {
|
||||||
match *pred {
|
match *pred {
|
||||||
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref mut bounds }
|
clean::WherePredicate::BoundPredicate {
|
||||||
if *s == kw::SelfUpper =>
|
ty: clean::Generic(ref s),
|
||||||
{
|
ref mut bounds,
|
||||||
|
..
|
||||||
|
} if *s == kw::SelfUpper => {
|
||||||
bounds.retain(|bound| match *bound {
|
bounds.retain(|bound| match *bound {
|
||||||
clean::GenericBound::TraitBound(
|
clean::GenericBound::TraitBound(
|
||||||
clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
|
clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
|
||||||
|
@ -591,6 +593,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
ref bounds,
|
ref bounds,
|
||||||
|
..
|
||||||
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
|
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
|
||||||
_ => true,
|
_ => true,
|
||||||
});
|
});
|
||||||
|
@ -605,7 +608,7 @@ fn separate_supertrait_bounds(
|
||||||
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
) -> (clean::Generics, Vec<clean::GenericBound>) {
|
||||||
let mut ty_bounds = Vec::new();
|
let mut ty_bounds = Vec::new();
|
||||||
g.where_predicates.retain(|pred| match *pred {
|
g.where_predicates.retain(|pred| match *pred {
|
||||||
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds }
|
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
|
||||||
if *s == kw::SelfUpper =>
|
if *s == kw::SelfUpper =>
|
||||||
{
|
{
|
||||||
ty_bounds.extend(bounds.iter().cloned());
|
ty_bounds.extend(bounds.iter().cloned());
|
||||||
|
|
|
@ -330,6 +330,7 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
|
||||||
hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
|
hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
|
||||||
ty: wbp.bounded_ty.clean(cx),
|
ty: wbp.bounded_ty.clean(cx),
|
||||||
bounds: wbp.bounds.clean(cx),
|
bounds: wbp.bounds.clean(cx),
|
||||||
|
bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
|
||||||
},
|
},
|
||||||
|
|
||||||
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
|
||||||
|
@ -370,6 +371,7 @@ impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
|
ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
|
||||||
bounds: vec![poly_trait_ref.clean(cx)],
|
bounds: vec![poly_trait_ref.clean(cx)],
|
||||||
|
bound_params: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,6 +404,7 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
|
||||||
Some(WherePredicate::BoundPredicate {
|
Some(WherePredicate::BoundPredicate {
|
||||||
ty: ty.clean(cx),
|
ty: ty.clean(cx),
|
||||||
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
|
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
|
||||||
|
bound_params: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -567,7 +570,9 @@ impl Clean<Generics> for hir::Generics<'_> {
|
||||||
// to where predicates when such cases occur.
|
// to where predicates when such cases occur.
|
||||||
for where_pred in &mut generics.where_predicates {
|
for where_pred in &mut generics.where_predicates {
|
||||||
match *where_pred {
|
match *where_pred {
|
||||||
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
|
WherePredicate::BoundPredicate {
|
||||||
|
ty: Generic(ref name), ref mut bounds, ..
|
||||||
|
} => {
|
||||||
if bounds.is_empty() {
|
if bounds.is_empty() {
|
||||||
for param in &mut generics.params {
|
for param in &mut generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
|
@ -721,7 +726,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
|
||||||
// handled in cleaning associated types
|
// handled in cleaning associated types
|
||||||
let mut sized_params = FxHashSet::default();
|
let mut sized_params = FxHashSet::default();
|
||||||
where_predicates.retain(|pred| match *pred {
|
where_predicates.retain(|pred| match *pred {
|
||||||
WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
|
WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
|
||||||
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
|
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
|
||||||
sized_params.insert(*g);
|
sized_params.insert(*g);
|
||||||
false
|
false
|
||||||
|
@ -741,6 +746,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
|
||||||
where_predicates.push(WP::BoundPredicate {
|
where_predicates.push(WP::BoundPredicate {
|
||||||
ty: Type::Generic(tp.name),
|
ty: Type::Generic(tp.name),
|
||||||
bounds: vec![GenericBound::maybe_sized(cx)],
|
bounds: vec![GenericBound::maybe_sized(cx)],
|
||||||
|
bound_params: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1117,6 +1123,7 @@ impl Clean<Item> for ty::AssocItem {
|
||||||
WherePredicate::BoundPredicate {
|
WherePredicate::BoundPredicate {
|
||||||
ty: QPath { ref name, ref self_type, ref trait_, .. },
|
ty: QPath { ref name, ref self_type, ref trait_, .. },
|
||||||
ref bounds,
|
ref bounds,
|
||||||
|
..
|
||||||
} => (name, self_type, trait_, bounds),
|
} => (name, self_type, trait_, bounds),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,16 +24,20 @@ use crate::core::DocContext;
|
||||||
|
|
||||||
crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
|
crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
|
||||||
// First, partition the where clause into its separate components
|
// First, partition the where clause into its separate components
|
||||||
let mut params: BTreeMap<_, Vec<_>> = BTreeMap::new();
|
let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new();
|
||||||
let mut lifetimes = Vec::new();
|
let mut lifetimes = Vec::new();
|
||||||
let mut equalities = Vec::new();
|
let mut equalities = Vec::new();
|
||||||
let mut tybounds = Vec::new();
|
let mut tybounds = Vec::new();
|
||||||
|
|
||||||
for clause in clauses {
|
for clause in clauses {
|
||||||
match clause {
|
match clause {
|
||||||
WP::BoundPredicate { ty, bounds } => match ty {
|
WP::BoundPredicate { ty, bounds, bound_params } => match ty {
|
||||||
clean::Generic(s) => params.entry(s).or_default().extend(bounds),
|
clean::Generic(s) => {
|
||||||
t => tybounds.push((t, bounds)),
|
let (b, p) = params.entry(s).or_default();
|
||||||
|
b.extend(bounds);
|
||||||
|
p.extend(bound_params);
|
||||||
|
}
|
||||||
|
t => tybounds.push((t, (bounds, bound_params))),
|
||||||
},
|
},
|
||||||
WP::RegionPredicate { lifetime, bounds } => {
|
WP::RegionPredicate { lifetime, bounds } => {
|
||||||
lifetimes.push((lifetime, bounds));
|
lifetimes.push((lifetime, bounds));
|
||||||
|
@ -54,7 +58,7 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
|
||||||
clean::Generic(s) => s,
|
clean::Generic(s) => s,
|
||||||
_ => return true,
|
_ => return true,
|
||||||
};
|
};
|
||||||
let bounds = match params.get_mut(generic) {
|
let (bounds, _) = match params.get_mut(generic) {
|
||||||
Some(bound) => bound,
|
Some(bound) => bound,
|
||||||
None => return true,
|
None => return true,
|
||||||
};
|
};
|
||||||
|
@ -67,10 +71,16 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
|
||||||
clauses.extend(
|
clauses.extend(
|
||||||
lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
|
lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
|
||||||
);
|
);
|
||||||
clauses.extend(
|
clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
|
||||||
params.into_iter().map(|(k, v)| WP::BoundPredicate { ty: clean::Generic(k), bounds: v }),
|
ty: clean::Generic(k),
|
||||||
);
|
bounds,
|
||||||
clauses.extend(tybounds.into_iter().map(|(ty, bounds)| WP::BoundPredicate { ty, bounds }));
|
bound_params: params,
|
||||||
|
}));
|
||||||
|
clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
|
||||||
|
ty,
|
||||||
|
bounds,
|
||||||
|
bound_params,
|
||||||
|
}));
|
||||||
clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
|
clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
|
||||||
clauses
|
clauses
|
||||||
}
|
}
|
||||||
|
|
|
@ -1193,7 +1193,7 @@ impl Lifetime {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
crate enum WherePredicate {
|
crate enum WherePredicate {
|
||||||
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
|
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
|
||||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
|
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
|
||||||
EqPredicate { lhs: Type, rhs: Type },
|
EqPredicate { lhs: Type, rhs: Type },
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,17 +249,33 @@ crate fn print_where_clause<'a, 'tcx: 'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match pred {
|
match pred {
|
||||||
clean::WherePredicate::BoundPredicate { ty, bounds } => {
|
clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
|
||||||
let bounds = bounds;
|
let bounds = bounds;
|
||||||
|
let for_prefix = match bound_params.len() {
|
||||||
|
0 => String::new(),
|
||||||
|
_ if f.alternate() => {
|
||||||
|
format!(
|
||||||
|
"for<{:#}> ",
|
||||||
|
comma_sep(bound_params.iter().map(|lt| lt.print()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => format!(
|
||||||
|
"for<{}> ",
|
||||||
|
comma_sep(bound_params.iter().map(|lt| lt.print()))
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
clause.push_str(&format!(
|
clause.push_str(&format!(
|
||||||
"{:#}: {:#}",
|
"{}{:#}: {:#}",
|
||||||
|
for_prefix,
|
||||||
ty.print(cx),
|
ty.print(cx),
|
||||||
print_generic_bounds(bounds, cx)
|
print_generic_bounds(bounds, cx)
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
clause.push_str(&format!(
|
clause.push_str(&format!(
|
||||||
"{}: {}",
|
"{}{}: {}",
|
||||||
|
for_prefix,
|
||||||
ty.print(cx),
|
ty.print(cx),
|
||||||
print_generic_bounds(bounds, cx)
|
print_generic_bounds(bounds, cx)
|
||||||
));
|
));
|
||||||
|
|
|
@ -328,9 +328,10 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
||||||
fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
|
fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
|
||||||
use clean::WherePredicate::*;
|
use clean::WherePredicate::*;
|
||||||
match predicate {
|
match predicate {
|
||||||
BoundPredicate { ty, bounds } => WherePredicate::BoundPredicate {
|
BoundPredicate { ty, bounds, .. } => WherePredicate::BoundPredicate {
|
||||||
ty: ty.into_tcx(tcx),
|
ty: ty.into_tcx(tcx),
|
||||||
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
|
||||||
|
// FIXME: add `bound_params` to rustdoc-json-params?
|
||||||
},
|
},
|
||||||
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
|
RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
|
||||||
lifetime: lifetime.0.to_string(),
|
lifetime: lifetime.0.to_string(),
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
trait A<'x> {}
|
||||||
|
|
||||||
|
// @has foo/fn.test1.html
|
||||||
|
// @has - '//pre' "pub fn test1<T>() where for<'a> &'a T: Iterator,"
|
||||||
|
pub fn test1<T>()
|
||||||
|
where
|
||||||
|
for<'a> &'a T: Iterator,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has foo/fn.test2.html
|
||||||
|
// @has - '//pre' "pub fn test2<T>() where for<'a, 'b> &'a T: A<'b>,"
|
||||||
|
pub fn test2<T>()
|
||||||
|
where
|
||||||
|
for<'a, 'b> &'a T: A<'b>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has foo/fn.test3.html
|
||||||
|
// @has - '//pre' "pub fn test3<F>() where F: for<'a, 'b> Fn(&'a u8, &'b u8),"
|
||||||
|
pub fn test3<F>()
|
||||||
|
where
|
||||||
|
F: for<'a, 'b> Fn(&'a u8, &'b u8),
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has foo/struct.Foo.html
|
||||||
|
pub struct Foo<'a> {
|
||||||
|
_x: &'a u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Foo<'a> {
|
||||||
|
// @has - '//code' "pub fn bar<T>() where T: A<'a>,"
|
||||||
|
pub fn bar<T>()
|
||||||
|
where
|
||||||
|
T: A<'a>,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue