Skip to content

Commit 40e3fcf

Browse files
authored
Rollup merge of #112920 - fmease:rustdoc-fix-112904, r=GuillaumeGomez
rustdoc: render generic params & where-clauses of cross-crate assoc tys in impls We used to only ever render generic parameters & where-clauses of cross-crate associated types when the item was located inside of a trait and we used to just drop them when it was inside of an impl block (trait or inherent). Fixes #112904. `@rustbot` label A-cross-crate-reexports
2 parents c6a4d44 + c643bed commit 40e3fcf

File tree

3 files changed

+74
-43
lines changed

3 files changed

+74
-43
lines changed

src/librustdoc/clean/mod.rs

+45-43
Original file line numberDiff line numberDiff line change
@@ -1352,21 +1352,53 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
13521352
}
13531353
}
13541354

1355+
let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
13551356
if let ty::TraitContainer = assoc_item.container {
13561357
let bounds = tcx
13571358
.explicit_item_bounds(assoc_item.def_id)
13581359
.subst_identity_iter_copied()
13591360
.map(|(c, s)| (c.as_predicate(), s));
1360-
let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
1361-
let predicates =
1362-
tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
1363-
let mut generics = clean_ty_generics(
1364-
cx,
1365-
tcx.generics_of(assoc_item.def_id),
1366-
ty::GenericPredicates { parent: None, predicates },
1367-
);
1368-
// Filter out the bounds that are (likely?) directly attached to the associated type,
1369-
// as opposed to being located in the where clause.
1361+
predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
1362+
}
1363+
let mut generics = clean_ty_generics(
1364+
cx,
1365+
tcx.generics_of(assoc_item.def_id),
1366+
ty::GenericPredicates { parent: None, predicates },
1367+
);
1368+
// Move bounds that are (likely) directly attached to the parameters of the
1369+
// (generic) associated type from the where clause to the respective parameter.
1370+
// There is no guarantee that this is what the user actually wrote but we have
1371+
// no way of knowing.
1372+
let mut where_predicates = ThinVec::new();
1373+
for mut pred in generics.where_predicates {
1374+
if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
1375+
&& let Some(GenericParamDef {
1376+
kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
1377+
..
1378+
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1379+
{
1380+
param_bounds.append(bounds);
1381+
} else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
1382+
&& let Some(GenericParamDef {
1383+
kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
1384+
..
1385+
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1386+
{
1387+
param_bounds.extend(bounds.drain(..).map(|bound| match bound {
1388+
GenericBound::Outlives(lifetime) => lifetime,
1389+
_ => unreachable!(),
1390+
}));
1391+
} else {
1392+
where_predicates.push(pred);
1393+
}
1394+
}
1395+
generics.where_predicates = where_predicates;
1396+
1397+
if let ty::TraitContainer = assoc_item.container {
1398+
// Move bounds that are (likely) directly attached to the associated type
1399+
// from the where-clause to the associated type.
1400+
// There is no guarantee that this is what the user actually wrote but we have
1401+
// no way of knowing.
13701402
let mut bounds: Vec<GenericBound> = Vec::new();
13711403
generics.where_predicates.retain_mut(|pred| match *pred {
13721404
WherePredicate::BoundPredicate {
@@ -1423,33 +1455,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14231455
}
14241456
None => bounds.push(GenericBound::maybe_sized(cx)),
14251457
}
1426-
// Move bounds that are (likely) directly attached to the parameters of the
1427-
// (generic) associated type from the where clause to the respective parameter.
1428-
// There is no guarantee that this is what the user actually wrote but we have
1429-
// no way of knowing.
1430-
let mut where_predicates = ThinVec::new();
1431-
for mut pred in generics.where_predicates {
1432-
if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
1433-
&& let Some(GenericParamDef {
1434-
kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
1435-
..
1436-
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1437-
{
1438-
param_bounds.append(bounds);
1439-
} else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
1440-
&& let Some(GenericParamDef {
1441-
kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
1442-
..
1443-
}) = generics.params.iter_mut().find(|param| &param.name == arg) {
1444-
param_bounds.extend(bounds.drain(..).map(|bound| match bound {
1445-
GenericBound::Outlives(lifetime) => lifetime,
1446-
_ => unreachable!(),
1447-
}));
1448-
} else {
1449-
where_predicates.push(pred);
1450-
}
1451-
}
1452-
generics.where_predicates = where_predicates;
14531458

14541459
if tcx.defaultness(assoc_item.def_id).has_value() {
14551460
AssocTypeItem(
@@ -1461,7 +1466,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14611466
None,
14621467
),
14631468
generics,
1464-
// FIXME: should we obtain the Type from HIR and pass it on here?
14651469
item_type: None,
14661470
}),
14671471
bounds,
@@ -1470,7 +1474,6 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14701474
TyAssocTypeItem(generics, bounds)
14711475
}
14721476
} else {
1473-
// FIXME: when could this happen? Associated items in inherent impls?
14741477
AssocTypeItem(
14751478
Box::new(Typedef {
14761479
type_: clean_middle_ty(
@@ -1479,12 +1482,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
14791482
Some(assoc_item.def_id),
14801483
None,
14811484
),
1482-
generics: Generics {
1483-
params: ThinVec::new(),
1484-
where_predicates: ThinVec::new(),
1485-
},
1485+
generics,
14861486
item_type: None,
14871487
}),
1488+
// Associated types inside trait or inherent impls are not allowed to have
1489+
// item bounds. Thus we don't attempt to move any bounds there.
14881490
Vec::new(),
14891491
)
14901492
}

tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs

+12
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,15 @@ pub use aux::Main;
4242
// @has main/trait.Aid.html
4343
// @has - '//*[@id="associatedtype.Result"]' "type Result<'inter: 'src>"
4444
pub use aux::Aid;
45+
46+
// Below, ensure that we correctly display generic parameters and where-clauses on
47+
// associated types inside trait *impls*. More particularly, check that we don't render
48+
// any bounds (here `Self::Alias<T>: ...`) as item bounds unlike all the trait test cases above.
49+
50+
// @has main/struct.Implementor.html
51+
// @has - '//*[@id="associatedtype.Alias"]' \
52+
// "type Alias<T: Eq> = T \
53+
// where \
54+
// String: From<T>, \
55+
// <Implementor as Implementee>::Alias<T>: From<<Implementor as Implementee>::Alias<T>>"
56+
pub use aux::Implementor;

tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs

+17
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,20 @@ pub trait Helper {
4444
pub trait Aid<'src> {
4545
type Result<'inter: 'src>;
4646
}
47+
48+
pub trait Implementee {
49+
type Alias<T: Eq>
50+
where
51+
String: From<T>;
52+
}
53+
54+
pub struct Implementor;
55+
56+
impl Implementee for Implementor {
57+
type Alias<T: Eq> = T
58+
where
59+
String: From<T>,
60+
// We will check that this bound doesn't get turned into an item bound since
61+
// associated types in impls are not allowed to have any.
62+
Self::Alias<T>: From<Self::Alias<T>>;
63+
}

0 commit comments

Comments
 (0)