Skip to content

Commit 5b32681

Browse files
committed
Offset args of trait object types when cleaning
1 parent f141a52 commit 5b32681

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,8 +1988,9 @@ pub(crate) enum ContainerTy<'tcx> {
19881988
Ref(ty::Region<'tcx>),
19891989
Regular {
19901990
ty: DefId,
1991+
/// The arguments *have* to contain an arg for the self type if the corresponding generics
1992+
/// contain a self type.
19911993
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
1992-
has_self: bool,
19931994
arg: usize,
19941995
},
19951996
}
@@ -1998,7 +1999,7 @@ impl<'tcx> ContainerTy<'tcx> {
19981999
fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> {
19992000
match self {
20002001
Self::Ref(region) => ObjectLifetimeDefault::Arg(region),
2001-
Self::Regular { ty: container, args, has_self, arg: index } => {
2002+
Self::Regular { ty: container, args, arg: index } => {
20022003
let (DefKind::Struct
20032004
| DefKind::Union
20042005
| DefKind::Enum
@@ -2011,14 +2012,7 @@ impl<'tcx> ContainerTy<'tcx> {
20112012
let generics = tcx.generics_of(container);
20122013
debug_assert_eq!(generics.parent_count, 0);
20132014

2014-
// If the container is a trait object type, the arguments won't contain the self type but the
2015-
// generics of the corresponding trait will. In such a case, offset the index by one.
2016-
// For comparison, if the container is a trait inside a bound, the arguments do contain the
2017-
// self type.
2018-
let offset =
2019-
if !has_self && generics.parent.is_none() && generics.has_self { 1 } else { 0 };
2020-
let param = generics.params[index + offset].def_id;
2021-
2015+
let param = generics.params[index].def_id;
20222016
let default = tcx.object_lifetime_default(param);
20232017
match default {
20242018
rbv::ObjectLifetimeDefault::Param(lifetime) => {

src/librustdoc/clean/utils.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,28 +78,46 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
7878
pub(crate) fn clean_middle_generic_args<'tcx>(
7979
cx: &mut DocContext<'tcx>,
8080
args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>,
81-
has_self: bool,
81+
mut has_self: bool,
8282
owner: DefId,
8383
) -> Vec<GenericArg> {
8484
if args.skip_binder().is_empty() {
8585
// Fast path which avoids executing the query `generics_of`.
8686
return Vec::new();
8787
}
8888

89-
let params = &cx.tcx.generics_of(owner).params;
89+
let generics = cx.tcx.generics_of(owner);
9090
let mut elision_has_failed_once_before = false;
9191

9292
let offset = if has_self { 1 } else { 0 };
9393
let mut clean_args = Vec::with_capacity(args.skip_binder().len().saturating_sub(offset));
9494

95+
// If the container is a trait object type, the arguments won't contain the self type but the
96+
// generics of the corresponding trait will. In such a case, prepend a dummy self type in order
97+
// to align the arguments and parameters for the iteration below and to enable us to correctly
98+
// instantiate the generic parameter default later.
99+
let args = if !has_self && generics.parent.is_none() && generics.has_self {
100+
has_self = true;
101+
// FIXME(fmease): Don't arena-allocate the args (blocked on further refactorings)!
102+
args.map_bound(|args| {
103+
&*cx.tcx.arena.alloc_from_iter(
104+
[cx.tcx.types.trait_object_dummy_self.into()]
105+
.into_iter()
106+
.chain(args.iter().copied()),
107+
)
108+
})
109+
} else {
110+
args
111+
};
112+
95113
let clean_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| match arg.unpack() {
96114
GenericArgKind::Lifetime(lt) => {
97115
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
98116
}
99117
GenericArgKind::Type(_) if has_self && index == 0 => None,
100118
GenericArgKind::Type(ty) => {
101119
if !elision_has_failed_once_before
102-
&& let Some(default) = params[index].default_value(cx.tcx)
120+
&& let Some(default) = generics.param_at(index, cx.tcx).default_value(cx.tcx)
103121
{
104122
let default = args.map_bound(|args| default.instantiate(cx.tcx, args).expect_ty());
105123

@@ -114,17 +132,18 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
114132
args.rebind(ty),
115133
cx,
116134
None,
117-
Some(crate::clean::ContainerTy::Regular { ty: owner, args, has_self, arg: index }),
135+
Some(crate::clean::ContainerTy::Regular { ty: owner, args, arg: index }),
118136
)))
119137
}
120138
GenericArgKind::Const(ct) => {
121-
if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind
139+
if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } =
140+
generics.param_at(index, cx.tcx).kind
122141
{
123142
return None;
124143
}
125144

126145
if !elision_has_failed_once_before
127-
&& let Some(default) = params[index].default_value(cx.tcx)
146+
&& let Some(default) = generics.param_at(index, cx.tcx).default_value(cx.tcx)
128147
{
129148
let default =
130149
args.map_bound(|args| default.instantiate(cx.tcx, args).expect_const());

0 commit comments

Comments
 (0)