diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 470bfc484bfc..25b8d01918b2 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -980,6 +980,7 @@ where /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. + #[track_caller] pub fn dummy(value: T) -> Binder<'tcx, T> { assert!(!value.has_escaping_bound_vars()); Binder(value, ty::List::empty()) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0174b1a71b5d..89c8abe4f99e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -165,7 +165,7 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>( } inline::record_extern_fqn(cx, trait_ref.def_id(), kind); let path = - external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.skip_binder().substs); + external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs)); debug!(?trait_ref); @@ -437,7 +437,7 @@ fn clean_projection<'tcx>( }; let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type); Type::QPath(Box::new(QPathData { - assoc: projection_to_path_segment(ty.skip_binder(), cx), + assoc: projection_to_path_segment(ty, cx), should_show_cast, self_type, trait_, @@ -452,15 +452,16 @@ fn compute_should_show_cast(self_def_id: Option, trait_: &Path, self_type } fn projection_to_path_segment<'tcx>( - ty: ty::ProjectionTy<'tcx>, + ty: ty::Binder<'tcx, ty::ProjectionTy<'tcx>>, cx: &mut DocContext<'tcx>, ) -> PathSegment { - let item = cx.tcx.associated_item(ty.item_def_id); - let generics = cx.tcx.generics_of(ty.item_def_id); + let item = cx.tcx.associated_item(ty.skip_binder().item_def_id); + let generics = cx.tcx.generics_of(ty.skip_binder().item_def_id); PathSegment { name: item.name, args: GenericArgs::AngleBracketed { - args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(), + args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false) + .into(), bindings: Default::default(), }, } @@ -1732,12 +1733,18 @@ pub(crate) fn clean_middle_ty<'tcx>( AdtKind::Enum => ItemType::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, did, false, ThinVec::new(), substs); + let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs)); Type::Path { path } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); - let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty()); + let path = external_path( + cx, + did, + false, + ThinVec::new(), + ty::Binder::dummy(InternalSubsts::empty()), + ); Type::Path { path } } ty::Dynamic(obj, ref reg, _) => { @@ -1750,9 +1757,9 @@ pub(crate) fn clean_middle_ty<'tcx>( .or_else(|| dids.next()) .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?")); let substs = match obj.principal() { - Some(principal) => principal.skip_binder().substs, + Some(principal) => principal.map_bound(|p| p.substs), // marker traits have no substs. - _ => cx.tcx.intern_substs(&[]), + _ => ty::Binder::dummy(InternalSubsts::empty()), }; inline::record_extern_fqn(cx, did, ItemType::Trait); @@ -1763,7 +1770,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let lifetime = clean_middle_region(*reg); let mut bounds = dids .map(|did| { - let empty = cx.tcx.intern_substs(&[]); + let empty = ty::Binder::dummy(InternalSubsts::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); PolyTrait { trait_: path, generic_params: Vec::new() } @@ -1774,11 +1781,13 @@ pub(crate) fn clean_middle_ty<'tcx>( .projection_bounds() .map(|pb| TypeBinding { assoc: projection_to_path_segment( - pb.skip_binder() - // HACK(compiler-errors): Doesn't actually matter what self - // type we put here, because we're only using the GAT's substs. - .with_self_ty(cx.tcx, cx.tcx.types.self_param) - .projection_ty, + pb.map_bound(|pb| { + pb + // HACK(compiler-errors): Doesn't actually matter what self + // type we put here, because we're only using the GAT's substs. + .with_self_ty(cx.tcx, cx.tcx.types.self_param) + .projection_ty + }), cx, ), kind: TypeBindingKind::Equality { @@ -1883,7 +1892,10 @@ fn clean_middle_opaque_bounds<'tcx>( { if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { Some(TypeBinding { - assoc: projection_to_path_segment(proj.projection_ty, cx), + assoc: projection_to_path_segment( + bound.kind().rebind(proj.projection_ty), + cx, + ), kind: TypeBindingKind::Equality { term: clean_middle_term(bound.kind().rebind(proj.term), cx), }, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 98329e7fc919..7a7313c4bc99 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1343,7 +1343,7 @@ pub(crate) enum GenericBound { impl GenericBound { pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); - let empty = cx.tcx.intern_substs(&[]); + let empty = ty::Binder::dummy(ty::InternalSubsts::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 6c1bc2801d81..a12f764fa8e3 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { pub(crate) fn substs_to_args<'tcx>( cx: &mut DocContext<'tcx>, - substs: &[ty::subst::GenericArg<'tcx>], + substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>, mut skip_first: bool, ) -> Vec { let mut ret_val = - Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 })); - ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() { + Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first { + 1 + } else { + 0 + })); + ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() { GenericArgKind::Lifetime(lt) => { Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided()))) } @@ -92,10 +96,10 @@ pub(crate) fn substs_to_args<'tcx>( None } GenericArgKind::Type(ty) => { - Some(GenericArg::Type(clean_middle_ty(ty::Binder::dummy(ty), cx, None))) + Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None))) } GenericArgKind::Const(ct) => { - Some(GenericArg::Const(Box::new(clean_middle_const(ty::Binder::dummy(ct), cx)))) + Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx)))) } })); ret_val @@ -106,15 +110,20 @@ fn external_generic_args<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: SubstsRef<'tcx>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> GenericArgs { - let args = substs_to_args(cx, substs, has_self); + let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self); if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { + let ty = substs + .iter() + .nth(if has_self { 1 } else { 0 }) + .unwrap() + .map_bound(|arg| arg.expect_ty()); let inputs = // The trait's first substitution is the one after self, if there is one. - match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() { - ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty::Binder::dummy(t), cx, None)).collect::>().into(), + match ty.skip_binder().kind() { + ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::>().into(), _ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, }; let output = bindings.into_iter().next().and_then(|binding| match binding.kind { @@ -134,7 +143,7 @@ pub(super) fn external_path<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: SubstsRef<'tcx>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> Path { let def_kind = cx.tcx.def_kind(did); let name = cx.tcx.item_name(did);