diff options
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 14 | ||||
| -rw-r--r-- | src/librustdoc/clean/utils.rs | 31 |
2 files changed, 29 insertions, 16 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 520d60f5b9b..9cc2d9cecb7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1988,8 +1988,9 @@ pub(crate) enum ContainerTy<'tcx> { Ref(ty::Region<'tcx>), Regular { ty: DefId, + /// The arguments *have* to contain an arg for the self type if the corresponding generics + /// contain a self type. args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, - has_self: bool, arg: usize, }, } @@ -1998,7 +1999,7 @@ impl<'tcx> ContainerTy<'tcx> { fn object_lifetime_default(self, tcx: TyCtxt<'tcx>) -> ObjectLifetimeDefault<'tcx> { match self { Self::Ref(region) => ObjectLifetimeDefault::Arg(region), - Self::Regular { ty: container, args, has_self, arg: index } => { + Self::Regular { ty: container, args, arg: index } => { let (DefKind::Struct | DefKind::Union | DefKind::Enum @@ -2011,14 +2012,7 @@ impl<'tcx> ContainerTy<'tcx> { let generics = tcx.generics_of(container); debug_assert_eq!(generics.parent_count, 0); - // If the container is a trait object type, the arguments won't contain the self type but the - // generics of the corresponding trait will. In such a case, offset the index by one. - // For comparison, if the container is a trait inside a bound, the arguments do contain the - // self type. - let offset = - if !has_self && generics.parent.is_none() && generics.has_self { 1 } else { 0 }; - let param = generics.params[index + offset].def_id; - + let param = generics.params[index].def_id; let default = tcx.object_lifetime_default(param); match default { rbv::ObjectLifetimeDefault::Param(lifetime) => { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index cb5cfef6382..aadc308d5ec 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -78,7 +78,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { pub(crate) fn clean_middle_generic_args<'tcx>( cx: &mut DocContext<'tcx>, args: ty::Binder<'tcx, &'tcx [ty::GenericArg<'tcx>]>, - has_self: bool, + mut has_self: bool, owner: DefId, ) -> Vec<GenericArg> { if args.skip_binder().is_empty() { @@ -86,12 +86,30 @@ pub(crate) fn clean_middle_generic_args<'tcx>( return Vec::new(); } - let params = &cx.tcx.generics_of(owner).params; + let generics = cx.tcx.generics_of(owner); let mut elision_has_failed_once_before = false; let offset = if has_self { 1 } else { 0 }; let mut clean_args = Vec::with_capacity(args.skip_binder().len().saturating_sub(offset)); + // If the container is a trait object type, the arguments won't contain the self type but the + // generics of the corresponding trait will. In such a case, prepend a dummy self type in order + // to align the arguments and parameters for the iteration below and to enable us to correctly + // instantiate the generic parameter default later. + let args = if !has_self && generics.parent.is_none() && generics.has_self { + has_self = true; + // FIXME(fmease): Don't arena-allocate the args (blocked on further refactorings)! + args.map_bound(|args| { + &*cx.tcx.arena.alloc_from_iter( + [cx.tcx.types.trait_object_dummy_self.into()] + .into_iter() + .chain(args.iter().copied()), + ) + }) + } else { + args + }; + let clean_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| match arg.unpack() { GenericArgKind::Lifetime(lt) => { Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided()))) @@ -99,7 +117,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( GenericArgKind::Type(_) if has_self && index == 0 => None, GenericArgKind::Type(ty) => { if !elision_has_failed_once_before - && let Some(default) = params[index].default_value(cx.tcx) + && let Some(default) = generics.param_at(index, cx.tcx).default_value(cx.tcx) { let default = args.map_bound(|args| default.instantiate(cx.tcx, args).expect_ty()); @@ -114,17 +132,18 @@ pub(crate) fn clean_middle_generic_args<'tcx>( args.rebind(ty), cx, None, - Some(crate::clean::ContainerTy::Regular { ty: owner, args, has_self, arg: index }), + Some(crate::clean::ContainerTy::Regular { ty: owner, args, arg: index }), ))) } GenericArgKind::Const(ct) => { - if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = params[index].kind + if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } = + generics.param_at(index, cx.tcx).kind { return None; } if !elision_has_failed_once_before - && let Some(default) = params[index].default_value(cx.tcx) + && let Some(default) = generics.param_at(index, cx.tcx).default_value(cx.tcx) { let default = args.map_bound(|args| default.instantiate(cx.tcx, args).expect_const()); |
