1
Fork 0

Auto merge of #111697 - rcvalle:rust-cfi-fix-111510, r=bjorn3

CFI: Fix encode_ty: unexpected Param(B/#1)

Fixes #111510 and complements #106547 by adding support for encoding type parameters and also by transforming trait objects' traits into their identities before emitting type checks.
This commit is contained in:
bors 2023-05-21 06:42:05 +00:00
commit d77014a608
4 changed files with 191 additions and 66 deletions

View file

@ -673,6 +673,14 @@ fn encode_ty<'tcx>(
typeid.push_str(&s);
}
// Type parameters
ty::Param(..) => {
// u5param as vendor extended type
let mut s = String::from("u5param");
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
typeid.push_str(&s);
}
// Unexpected types
ty::Bound(..)
| ty::Error(..)
@ -680,7 +688,6 @@ fn encode_ty<'tcx>(
| ty::GeneratorWitnessMIR(..)
| ty::Infer(..)
| ty::Alias(..)
| ty::Param(..)
| ty::Placeholder(..) => {
bug!("encode_ty: unexpected `{:?}`", ty.kind());
}
@ -689,6 +696,41 @@ fn encode_ty<'tcx>(
typeid
}
/// Transforms predicates for being encoded and used in the substitution dictionary.
fn transform_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
_options: EncodeTyOptions,
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
.iter()
.map(|predicate| match predicate.skip_binder() {
ty::ExistentialPredicate::Trait(trait_ref) => {
let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
ty::Binder::dummy(ty::ExistentialPredicate::Trait(
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
))
}
_ => predicate,
})
.collect();
tcx.mk_poly_existential_predicates(&predicates)
}
/// Transforms substs for being encoded and used in the substitution dictionary.
fn transform_substs<'tcx>(
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
options: TransformTyOptions,
) -> SubstsRef<'tcx> {
let substs = substs.iter().map(|subst| match subst.unpack() {
GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
_ => subst,
});
tcx.mk_substs_from_iter(substs)
}
// Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
// c_void types into unit types unconditionally, generalizes pointers if
// TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
@ -697,7 +739,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
let mut ty = ty;
match ty.kind() {
ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) | ty::Dynamic(..) => {}
ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) => {}
ty::Bool => {
if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
@ -870,6 +912,14 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
}
}
ty::Dynamic(predicates, _region, kind) => {
ty = tcx.mk_dynamic(
transform_predicates(tcx, predicates, options),
tcx.lifetimes.re_erased,
*kind,
);
}
ty::Bound(..)
| ty::Error(..)
| ty::GeneratorWitness(..)
@ -885,20 +935,6 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
ty
}
/// Transforms substs for being encoded and used in the substitution dictionary.
fn transform_substs<'tcx>(
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
options: TransformTyOptions,
) -> SubstsRef<'tcx> {
let substs = substs.iter().map(|subst| match subst.unpack() {
GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
_ => subst,
});
tcx.mk_substs_from_iter(substs)
}
/// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
/// extended type qualifiers and types for Rust types that are not used at the FFI boundary.
#[instrument(level = "trace", skip(tcx))]