Skip to content

Commit 7eed169

Browse files
fmeaseMark-Simulacrum
authored andcommitted
rustdoc: correctly deal with self ty params when eliding default object lifetimes
1 parent 61d4817 commit 7eed169

File tree

4 files changed

+65
-22
lines changed

4 files changed

+65
-22
lines changed

Diff for: src/librustdoc/clean/mod.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,7 @@ fn clean_generic_bound<'tcx>(
167167
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(cx.tcx, def_id));
168168

169169
let generic_args = clean_generic_args(generic_args, cx);
170-
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
171-
else {
170+
let GenericArgs::AngleBracketed { bindings, .. } = generic_args else {
172171
bug!("clean: parenthesized `GenericBound::LangItemTrait`");
173172
};
174173

@@ -1818,33 +1817,46 @@ fn can_elide_trait_object_lifetime_bound<'tcx>(
18181817
#[derive(Debug)]
18191818
pub(crate) enum ContainerTy<'tcx> {
18201819
Ref(ty::Region<'tcx>),
1821-
Regular { ty: DefId, substs: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, arg: usize },
1820+
Regular {
1821+
ty: DefId,
1822+
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
1823+
has_self: bool,
1824+
arg: usize,
1825+
},
18221826
}
18231827

18241828
impl<'tcx> ContainerTy<'tcx> {
18251829
fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> {
18261830
match self {
18271831
Self::Ref(region) => ObjectLifetimeDefault::Arg(region),
1828-
Self::Regular { ty: container, substs, arg: index } => {
1832+
Self::Regular { ty: container, args, has_self, arg: index } => {
18291833
let (DefKind::Struct
18301834
| DefKind::Union
18311835
| DefKind::Enum
1832-
| DefKind::TyAlias
1833-
| DefKind::Trait
1834-
| DefKind::AssocTy
1835-
| DefKind::Variant) = tcx.def_kind(container)
1836+
| DefKind::TyAlias { .. }
1837+
| DefKind::Trait) = tcx.def_kind(container)
18361838
else {
18371839
return ObjectLifetimeDefault::Empty;
18381840
};
18391841

18401842
let generics = tcx.generics_of(container);
1841-
let param = generics.params[index].def_id;
1842-
let default = tcx.object_lifetime_default(param);
1843+
debug_assert_eq!(generics.parent_count, 0);
1844+
1845+
// If the container is a trait object type, the arguments won't contain the self type but the
1846+
// generics of the corresponding trait will. In such a case, offset the index by one.
1847+
// For comparison, if the container is a trait inside a bound, the arguments do contain the
1848+
// self type.
1849+
let offset =
1850+
if !has_self && generics.parent.is_none() && generics.has_self { 1 } else { 0 };
1851+
let param = generics.params[index + offset].def_id;
18431852

1853+
let default = tcx.object_lifetime_default(param);
18441854
match default {
18451855
rbv::ObjectLifetimeDefault::Param(lifetime) => {
1856+
// The index is relative to the parent generics but since we don't have any,
1857+
// we don't need to translate it.
18461858
let index = generics.param_def_id_to_index[&lifetime];
1847-
let arg = substs.skip_binder()[index as usize].expect_region();
1859+
let arg = args.skip_binder()[index as usize].expect_region();
18481860
ObjectLifetimeDefault::Arg(arg)
18491861
}
18501862
rbv::ObjectLifetimeDefault::Empty => ObjectLifetimeDefault::Empty,

Diff for: src/librustdoc/clean/utils.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
5454
let primitives = local_crate.primitives(cx.tcx);
5555
let keywords = local_crate.keywords(cx.tcx);
5656
{
57-
let ItemKind::ModuleItem(ref mut m) = *module.kind
58-
else { unreachable!() };
57+
let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() };
5958
m.items.extend(primitives.iter().map(|&(def_id, prim)| {
6059
Item::from_def_id_and_parts(
6160
def_id,
@@ -74,18 +73,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
7473

7574
pub(crate) fn substs_to_args<'tcx>(
7675
cx: &mut DocContext<'tcx>,
77-
substs: ty::Binder<'tcx, &'tcx [ty::subst::GenericArg<'tcx>]>,
78-
mut skip_first: bool,
76+
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
77+
has_self: bool,
7978
container: Option<DefId>,
8079
) -> Vec<GenericArg> {
80+
let mut skip_first = has_self;
8181
let mut ret_val =
82-
Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first {
83-
1
84-
} else {
85-
0
86-
}));
82+
Vec::with_capacity(args.skip_binder().len().saturating_sub(if skip_first { 1 } else { 0 }));
8783

88-
ret_val.extend(substs.iter().enumerate().filter_map(|(index, kind)| {
84+
ret_val.extend(args.iter().enumerate().filter_map(|(index, kind)| {
8985
match kind.skip_binder().unpack() {
9086
GenericArgKind::Lifetime(lt) => {
9187
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
@@ -100,7 +96,8 @@ pub(crate) fn substs_to_args<'tcx>(
10096
None,
10197
container.map(|container| crate::clean::ContainerTy::Regular {
10298
ty: container,
103-
substs,
99+
args,
100+
has_self,
104101
arg: index,
105102
}),
106103
))),

Diff for: tests/rustdoc/inline_cross/auxiliary/dyn_trait.rs

+19
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,22 @@ pub trait HigherRankedBoundTrait1<'e> where for<'l> Self: 'e + 'l {}
6565
pub trait AmbiguousBoundTrait<'a, 'b>: 'a + 'b {}
6666

6767
pub struct AmbiguousBoundWrapper<'a, 'b, T: ?Sized + 'a + 'b>(&'a T, &'b T);
68+
69+
// Trait objects inside of another trait object, a trait bound or an associated type.
70+
71+
pub trait Inner {}
72+
pub trait Outer<T: ?Sized> {}
73+
pub trait Base {
74+
type Type<T: ?Sized>;
75+
}
76+
impl Base for () {
77+
type Type<T: ?Sized> = ();
78+
}
79+
80+
pub type NestedTraitObjects = dyn Outer<dyn Inner>;
81+
82+
pub fn apit_rpit(o: impl Outer<dyn Inner>) -> impl Outer<dyn Inner> {
83+
o
84+
}
85+
86+
pub type AssocTy = <() as Base>::Type<dyn Inner>;

Diff for: tests/rustdoc/inline_cross/dyn_trait.rs

+15
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,18 @@ pub use dyn_trait::BareAmbiguousBoundEarly1;
128128
// @has user/type.BareAmbiguousBoundStatic.html
129129
// @has - '//*[@class="rust item-decl"]//code' "dyn AmbiguousBoundTrait<'o, 'o> + 'static;"
130130
pub use dyn_trait::BareAmbiguousBoundStatic;
131+
132+
// Regression test for issue #115179:
133+
134+
// @has user/type.NestedTraitObjects.html
135+
// @has - '//*[@class="rust item-decl"]//code' "dyn Outer<dyn Inner>;"
136+
pub use dyn_trait::NestedTraitObjects;
137+
138+
// @has user/fn.apit_rpit.html
139+
// @has - '//pre[@class="rust item-decl"]' \
140+
// "apit_rpit(o: impl Outer<dyn Inner>) -> impl Outer<dyn Inner>"
141+
pub use dyn_trait::apit_rpit;
142+
143+
// @has user/type.AssocTy.html
144+
// @has - '//*[@class="rust item-decl"]//code' "<() as Base>::Type<dyn Inner>"
145+
pub use dyn_trait::AssocTy;

0 commit comments

Comments
 (0)