Round 3: require binders for substs

This commit is contained in:
Oli Scherer 2022-12-12 13:20:36 +00:00
parent 8b098325ec
commit 21917b0866
4 changed files with 50 additions and 28 deletions

View File

@ -980,6 +980,7 @@ impl<'tcx, T> Binder<'tcx, T>
/// 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())

View File

@ -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<DefId>, 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),
},

View File

@ -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(

View File

@ -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<GenericArg> {
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<TypeBinding>,
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::<Vec<_>>().into(),
match ty.skip_binder().kind() {
ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::<Vec<_>>().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<TypeBinding>,
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);