1
Fork 0

rustdoc: Clean up handling of lifetime bounds

Previously, rustdoc recorded lifetime bounds by rendering them into the
name of the lifetime parameter. Now, it leaves the name as the actual
name and instead records lifetime bounds in an `outlives` list, similar
to how type parameter bounds are recorded.
This commit is contained in:
Noah Lev 2021-09-01 16:20:14 -07:00
parent 50171c310c
commit 2a60229490
8 changed files with 51 additions and 35 deletions

View file

@ -331,9 +331,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
match br {
// We only care about named late bound regions, as we need to add them
// to the 'for<>' section
ty::BrNamed(_, name) => {
Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
}
ty::BrNamed(_, name) => Some(GenericParamDef {
name,
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
}),
_ => None,
}
})
@ -659,7 +660,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
bounds.insert(0, GenericBound::maybe_sized(self.cx));
}
}
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Lifetime { .. } => {}
GenericParamDefKind::Const { ref mut default, .. } => {
// We never want something like `impl<const N: usize = 10>`
default.take();

View file

@ -199,9 +199,10 @@ impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
.collect_referenced_late_bound_regions(&poly_trait_ref)
.into_iter()
.filter_map(|br| match br {
ty::BrNamed(_, name) => {
Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
}
ty::BrNamed(_, name) => Some(GenericParamDef {
name,
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
}),
_ => None,
})
.collect();
@ -412,7 +413,9 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
impl Clean<GenericParamDef> for ty::GenericParamDef {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
ty::GenericParamDefKind::Lifetime => {
(self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
let mut default = cx.tcx.type_of(self.def_id).clean(cx);
@ -462,21 +465,15 @@ impl Clean<GenericParamDef> for hir::GenericParam<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
hir::GenericParamKind::Lifetime { .. } => {
let name = if !self.bounds.is_empty() {
let mut bounds = self.bounds.iter().map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt,
let outlives = self
.bounds
.iter()
.map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt.clean(cx),
_ => panic!(),
});
let name = bounds.next().expect("no more bounds").name.ident();
let mut s = format!("{}: {}", self.name.ident(), name);
for bound in bounds {
s.push_str(&format!(" + {}", bound.name.ident()));
}
Symbol::intern(&s)
} else {
self.name.ident().name
};
(name, GenericParamDefKind::Lifetime)
})
.collect();
(self.name.ident().name, GenericParamDefKind::Lifetime { outlives })
}
hir::GenericParamKind::Type { ref default, synthetic } => (
self.name.ident().name,
@ -536,7 +533,7 @@ impl Clean<Generics> for hir::Generics<'_> {
.map(|param| {
let param: GenericParamDef = param.clean(cx);
match param.kind {
GenericParamDefKind::Lifetime => unreachable!(),
GenericParamDefKind::Lifetime { .. } => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
cx.impl_trait_bounds.insert(did.into(), bounds.clone());
}
@ -569,7 +566,7 @@ impl Clean<Generics> for hir::Generics<'_> {
{
for param in &mut generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Lifetime { .. } => {}
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
if &param.name == name {
mem::swap(bounds, ty_bounds);

View file

@ -1231,7 +1231,9 @@ impl WherePredicate {
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
crate enum GenericParamDefKind {
Lifetime,
Lifetime {
outlives: Vec<Lifetime>,
},
Type {
did: DefId,
bounds: Vec<GenericBound>,
@ -1257,7 +1259,7 @@ impl GenericParamDefKind {
match self {
GenericParamDefKind::Type { default, .. } => default.clone(),
GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
GenericParamDefKind::Lifetime => None,
GenericParamDefKind::Lifetime { .. } => None,
}
}
}
@ -1271,7 +1273,7 @@ crate struct GenericParamDef {
impl GenericParamDef {
crate fn is_synthetic_type_param(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
}
}

View file

@ -155,9 +155,23 @@ impl clean::GenericParamDef {
&'a self,
cx: &'a Context<'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, .. } => {
display_fn(move |f| match &self.kind {
clean::GenericParamDefKind::Lifetime { outlives } => {
write!(f, "{}", self.name)?;
if !outlives.is_empty() {
f.write_str(": ")?;
for (i, lt) in outlives.iter().enumerate() {
if i != 0 {
f.write_str(" + ")?;
}
write!(f, "{}", lt.print())?;
}
}
Ok(())
}
clean::GenericParamDefKind::Type { bounds, default, .. } => {
f.write_str(&*self.name.as_str())?;
if !bounds.is_empty() {
@ -178,7 +192,7 @@ impl clean::GenericParamDef {
Ok(())
}
clean::GenericParamDefKind::Const { ref ty, ref default, .. } => {
clean::GenericParamDefKind::Const { ty, default, .. } => {
if f.alternate() {
write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
} else {

View file

@ -326,7 +326,9 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
use clean::GenericParamDefKind::*;
match kind {
Lifetime => GenericParamDefKind::Lifetime,
Lifetime { outlives } => GenericParamDefKind::Lifetime {
outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
},
Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: default.map(|x| x.into_tcx(tcx)),

View file

@ -234,7 +234,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
)
})
.collect(),
format_version: 6,
format_version: 7,
};
let mut p = self.out_path.clone();
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());

View file

@ -323,7 +323,7 @@ pub struct GenericParamDef {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum GenericParamDefKind {
Lifetime,
Lifetime { outlives: Vec<String> },
Type { bounds: Vec<GenericBound>, default: Option<Type> },
Const { ty: Type, default: Option<String> },
}

View file

@ -1,7 +1,7 @@
// @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
// @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind" \"lifetime\"
// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
pub struct WithPrimitives<'a> {