CFI: Change type transformation to use TypeFolder
Change type transformation to use TypeFolder.
This commit is contained in:
parent
b38b6caa3e
commit
bc8c3eff6b
@ -11,13 +11,14 @@
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
use rustc_middle::ty::TypeVisitableExt;
|
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Const, ExistentialPredicate, FloatTy, FnSig, Instance, IntTy, List, Region, RegionKind,
|
self, Const, ExistentialPredicate, FloatTy, FnSig, Instance, IntTy, List, Region, RegionKind,
|
||||||
TermKind, Ty, TyCtxt, UintTy,
|
TermKind, Ty, TyCtxt, UintTy,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
|
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
|
||||||
|
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
|
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
|
||||||
@ -182,14 +183,15 @@ fn encode_fnsig<'tcx>(
|
|||||||
// Encode the return type
|
// Encode the return type
|
||||||
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
|
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
|
||||||
.unwrap_or_else(|| bug!("encode_fnsig: invalid option(s) `{:?}`", options.bits()));
|
.unwrap_or_else(|| bug!("encode_fnsig: invalid option(s) `{:?}`", options.bits()));
|
||||||
let ty = transform_ty(tcx, fn_sig.output(), &mut Vec::new(), transform_ty_options);
|
let mut type_folder = TransformTy::new(tcx, transform_ty_options);
|
||||||
|
let ty = fn_sig.output().fold_with(&mut type_folder);
|
||||||
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
|
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
|
||||||
|
|
||||||
// Encode the parameter types
|
// Encode the parameter types
|
||||||
let tys = fn_sig.inputs();
|
let tys = fn_sig.inputs();
|
||||||
if !tys.is_empty() {
|
if !tys.is_empty() {
|
||||||
for ty in tys {
|
for ty in tys {
|
||||||
let ty = transform_ty(tcx, *ty, &mut Vec::new(), transform_ty_options);
|
let ty = ty.fold_with(&mut type_folder);
|
||||||
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
|
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,15 +525,9 @@ fn encode_ty<'tcx>(
|
|||||||
|
|
||||||
ty::Array(ty0, len) => {
|
ty::Array(ty0, len) => {
|
||||||
// A<array-length><element-type>
|
// A<array-length><element-type>
|
||||||
|
let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
|
||||||
let mut s = String::from("A");
|
let mut s = String::from("A");
|
||||||
let _ = write!(
|
let _ = write!(s, "{}", &len);
|
||||||
s,
|
|
||||||
"{}",
|
|
||||||
&len.try_to_scalar()
|
|
||||||
.unwrap()
|
|
||||||
.to_target_usize(&tcx.data_layout)
|
|
||||||
.expect("Array lens are defined in usize")
|
|
||||||
);
|
|
||||||
s.push_str(&encode_ty(tcx, *ty0, dict, options));
|
s.push_str(&encode_ty(tcx, *ty0, dict, options));
|
||||||
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
|
||||||
typeid.push_str(&s);
|
typeid.push_str(&s);
|
||||||
@ -756,278 +752,208 @@ fn encode_ty<'tcx>(
|
|||||||
typeid
|
typeid
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms predicates for being encoded and used in the substitution dictionary.
|
struct TransformTy<'tcx> {
|
||||||
fn transform_predicates<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
|
|
||||||
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
|
|
||||||
tcx.mk_poly_existential_predicates_from_iter(predicates.iter().filter_map(|predicate| {
|
|
||||||
match predicate.skip_binder() {
|
|
||||||
ty::ExistentialPredicate::Trait(trait_ref) => {
|
|
||||||
let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
|
|
||||||
Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
|
|
||||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
ty::ExistentialPredicate::Projection(..) => None,
|
|
||||||
ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transforms args for being encoded and used in the substitution dictionary.
|
|
||||||
fn transform_args<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
args: GenericArgsRef<'tcx>,
|
|
||||||
parents: &mut Vec<Ty<'tcx>>,
|
|
||||||
options: TransformTyOptions,
|
options: TransformTyOptions,
|
||||||
) -> GenericArgsRef<'tcx> {
|
parents: Vec<Ty<'tcx>>,
|
||||||
let args = args.iter().map(|arg| match arg.unpack() {
|
|
||||||
GenericArgKind::Type(ty) if ty.is_c_void(tcx) => Ty::new_unit(tcx).into(),
|
|
||||||
GenericArgKind::Type(ty) => transform_ty(tcx, ty, parents, options).into(),
|
|
||||||
_ => arg,
|
|
||||||
});
|
|
||||||
tcx.mk_args_from_iter(args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
|
impl<'tcx> TransformTy<'tcx> {
|
||||||
// c_void types into unit types unconditionally, generalizes pointers if
|
fn new(tcx: TyCtxt<'tcx>, options: TransformTyOptions) -> Self {
|
||||||
|
TransformTy { tcx, options, parents: Vec::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
|
||||||
|
// 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
|
// TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
|
||||||
// TransformTyOptions::NORMALIZE_INTEGERS option is set.
|
// TransformTyOptions::NORMALIZE_INTEGERS option is set.
|
||||||
fn transform_ty<'tcx>(
|
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
match t.kind() {
|
||||||
mut ty: Ty<'tcx>,
|
ty::Array(..)
|
||||||
parents: &mut Vec<Ty<'tcx>>,
|
| ty::Closure(..)
|
||||||
options: TransformTyOptions,
|
| ty::Coroutine(..)
|
||||||
) -> Ty<'tcx> {
|
| ty::CoroutineClosure(..)
|
||||||
match ty.kind() {
|
| ty::CoroutineWitness(..)
|
||||||
ty::Float(..) | ty::Str | ty::Never | ty::Foreign(..) | ty::CoroutineWitness(..) => {}
|
| ty::Float(..)
|
||||||
|
| ty::FnDef(..)
|
||||||
|
| ty::Foreign(..)
|
||||||
|
| ty::Never
|
||||||
|
| ty::Slice(..)
|
||||||
|
| ty::Str
|
||||||
|
| ty::Tuple(..) => t.super_fold_with(self),
|
||||||
|
|
||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
||||||
// Note: on all platforms that Rust's currently supports, its size and alignment are
|
// Note: on all platforms that Rust's currently supports, its size and alignment
|
||||||
// 1, and its ABI class is INTEGER - see Rust Layout and ABIs.
|
// are 1, and its ABI class is INTEGER - see Rust Layout and ABIs.
|
||||||
//
|
//
|
||||||
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#bool.)
|
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#bool.)
|
||||||
//
|
//
|
||||||
// Clang represents bool as an 8-bit unsigned integer.
|
// Clang represents bool as an 8-bit unsigned integer.
|
||||||
ty = tcx.types.u8;
|
self.tcx.types.u8
|
||||||
|
} else {
|
||||||
|
t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Char => {
|
ty::Char => {
|
||||||
if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
||||||
// Since #118032, char is guaranteed to have the same size, alignment, and function
|
// Since #118032, char is guaranteed to have the same size, alignment, and
|
||||||
// call ABI as u32 on all platforms.
|
// function call ABI as u32 on all platforms.
|
||||||
ty = tcx.types.u32;
|
self.tcx.types.u32
|
||||||
|
} else {
|
||||||
|
t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Int(..) | ty::Uint(..) => {
|
ty::Int(..) | ty::Uint(..) => {
|
||||||
if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
if self.options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
|
||||||
// Note: C99 7.18.2.4 requires uintptr_t and intptr_t to be at least 16-bit wide.
|
// Note: C99 7.18.2.4 requires uintptr_t and intptr_t to be at least 16-bit
|
||||||
// All platforms we currently support have a C platform, and as a consequence,
|
// wide. All platforms we currently support have a C platform, and as a
|
||||||
// isize/usize are at least 16-bit wide for all of them.
|
// consequence, isize/usize are at least 16-bit wide for all of them.
|
||||||
//
|
//
|
||||||
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize.)
|
// (See https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize.)
|
||||||
match ty.kind() {
|
match t.kind() {
|
||||||
ty::Int(IntTy::Isize) => match tcx.sess.target.pointer_width {
|
ty::Int(IntTy::Isize) => match self.tcx.sess.target.pointer_width {
|
||||||
16 => ty = tcx.types.i16,
|
16 => self.tcx.types.i16,
|
||||||
32 => ty = tcx.types.i32,
|
32 => self.tcx.types.i32,
|
||||||
64 => ty = tcx.types.i64,
|
64 => self.tcx.types.i64,
|
||||||
128 => ty = tcx.types.i128,
|
128 => self.tcx.types.i128,
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
"transform_ty: unexpected pointer width `{}`",
|
"fold_ty: unexpected pointer width `{}`",
|
||||||
tcx.sess.target.pointer_width
|
self.tcx.sess.target.pointer_width
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
ty::Uint(UintTy::Usize) => match tcx.sess.target.pointer_width {
|
ty::Uint(UintTy::Usize) => match self.tcx.sess.target.pointer_width {
|
||||||
16 => ty = tcx.types.u16,
|
16 => self.tcx.types.u16,
|
||||||
32 => ty = tcx.types.u32,
|
32 => self.tcx.types.u32,
|
||||||
64 => ty = tcx.types.u64,
|
64 => self.tcx.types.u64,
|
||||||
128 => ty = tcx.types.u128,
|
128 => self.tcx.types.u128,
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
"transform_ty: unexpected pointer width `{}`",
|
"fold_ty: unexpected pointer width `{}`",
|
||||||
tcx.sess.target.pointer_width
|
self.tcx.sess.target.pointer_width
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => t,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ if ty.is_unit() => {}
|
ty::Adt(..) if t.is_c_void(self.tcx) => self.tcx.types.unit,
|
||||||
|
|
||||||
ty::Tuple(tys) => {
|
|
||||||
ty = Ty::new_tup_from_iter(
|
|
||||||
tcx,
|
|
||||||
tys.iter().map(|ty| transform_ty(tcx, ty, parents, options)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Array(ty0, len) => {
|
|
||||||
let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
|
|
||||||
|
|
||||||
ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, parents, options), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Slice(ty0) => {
|
|
||||||
ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, parents, options));
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Adt(adt_def, args) => {
|
ty::Adt(adt_def, args) => {
|
||||||
if ty.is_c_void(tcx) {
|
if adt_def.repr().transparent() && adt_def.is_struct() && !self.parents.contains(&t)
|
||||||
ty = Ty::new_unit(tcx);
|
|
||||||
} else if options.contains(TransformTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c()
|
|
||||||
{
|
|
||||||
ty = Ty::new_adt(tcx, *adt_def, ty::List::empty());
|
|
||||||
} else if adt_def.repr().transparent() && adt_def.is_struct() && !parents.contains(&ty)
|
|
||||||
{
|
{
|
||||||
// Don't transform repr(transparent) types with an user-defined CFI encoding to
|
// Don't transform repr(transparent) types with an user-defined CFI encoding to
|
||||||
// preserve the user-defined CFI encoding.
|
// preserve the user-defined CFI encoding.
|
||||||
if let Some(_) = tcx.get_attr(adt_def.did(), sym::cfi_encoding) {
|
if let Some(_) = self.tcx.get_attr(adt_def.did(), sym::cfi_encoding) {
|
||||||
return ty;
|
return t;
|
||||||
}
|
}
|
||||||
let variant = adt_def.non_enum_variant();
|
let variant = adt_def.non_enum_variant();
|
||||||
let param_env = tcx.param_env(variant.def_id);
|
let param_env = self.tcx.param_env(variant.def_id);
|
||||||
let field = variant.fields.iter().find(|field| {
|
let field = variant.fields.iter().find(|field| {
|
||||||
let ty = tcx.type_of(field.did).instantiate_identity();
|
let ty = self.tcx.type_of(field.did).instantiate_identity();
|
||||||
let is_zst =
|
let is_zst = self
|
||||||
tcx.layout_of(param_env.and(ty)).is_ok_and(|layout| layout.is_zst());
|
.tcx
|
||||||
|
.layout_of(param_env.and(ty))
|
||||||
|
.is_ok_and(|layout| layout.is_zst());
|
||||||
!is_zst
|
!is_zst
|
||||||
});
|
});
|
||||||
if let Some(field) = field {
|
if let Some(field) = field {
|
||||||
let ty0 = tcx.type_of(field.did).instantiate(tcx, args);
|
let ty0 = self.tcx.type_of(field.did).instantiate(self.tcx, args);
|
||||||
// Generalize any repr(transparent) user-defined type that is either a pointer
|
// Generalize any repr(transparent) user-defined type that is either a
|
||||||
// or reference, and either references itself or any other type that contains or
|
// pointer or reference, and either references itself or any other type that
|
||||||
// references itself, to avoid a reference cycle.
|
// contains or references itself, to avoid a reference cycle.
|
||||||
|
|
||||||
// If the self reference is not through a pointer, for example, due
|
// If the self reference is not through a pointer, for example, due
|
||||||
// to using `PhantomData`, need to skip normalizing it if we hit it again.
|
// to using `PhantomData`, need to skip normalizing it if we hit it again.
|
||||||
parents.push(ty);
|
self.parents.push(t);
|
||||||
if ty0.is_any_ptr() && ty0.contains(ty) {
|
let ty = if ty0.is_any_ptr() && ty0.contains(t) {
|
||||||
ty = transform_ty(
|
let options = self.options;
|
||||||
tcx,
|
self.options |= TransformTyOptions::GENERALIZE_POINTERS;
|
||||||
ty0,
|
let ty = ty0.fold_with(self);
|
||||||
parents,
|
self.options = options;
|
||||||
options | TransformTyOptions::GENERALIZE_POINTERS,
|
ty
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
ty = transform_ty(tcx, ty0, parents, options);
|
ty0.fold_with(self)
|
||||||
}
|
};
|
||||||
parents.pop();
|
self.parents.pop();
|
||||||
|
ty
|
||||||
} else {
|
} else {
|
||||||
// Transform repr(transparent) types without non-ZST field into ()
|
// Transform repr(transparent) types without non-ZST field into ()
|
||||||
ty = Ty::new_unit(tcx);
|
self.tcx.types.unit
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ty = Ty::new_adt(tcx, *adt_def, transform_args(tcx, args, parents, options));
|
t.super_fold_with(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::FnDef(def_id, args) => {
|
ty::Ref(..) => {
|
||||||
ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, parents, options));
|
if self.options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
||||||
}
|
if t.is_mutable_ptr() {
|
||||||
|
Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, self.tcx.types.unit)
|
||||||
ty::Closure(def_id, args) => {
|
|
||||||
ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, parents, options));
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::CoroutineClosure(def_id, args) => {
|
|
||||||
ty = Ty::new_coroutine_closure(
|
|
||||||
tcx,
|
|
||||||
*def_id,
|
|
||||||
transform_args(tcx, args, parents, options),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Coroutine(def_id, args) => {
|
|
||||||
ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, parents, options));
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::Ref(region, ty0, ..) => {
|
|
||||||
if options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
|
||||||
if ty.is_mutable_ptr() {
|
|
||||||
ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx));
|
|
||||||
} else {
|
} else {
|
||||||
ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx));
|
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, self.tcx.types.unit)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ty.is_mutable_ptr() {
|
t.super_fold_with(self)
|
||||||
ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, parents, options));
|
|
||||||
} else {
|
|
||||||
ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, parents, options));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::RawPtr(ptr_ty, _) => {
|
ty::RawPtr(..) => {
|
||||||
if options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
if self.options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
||||||
if ty.is_mutable_ptr() {
|
if t.is_mutable_ptr() {
|
||||||
ty = Ty::new_mut_ptr(tcx, Ty::new_unit(tcx));
|
Ty::new_mut_ptr(self.tcx, self.tcx.types.unit)
|
||||||
} else {
|
} else {
|
||||||
ty = Ty::new_imm_ptr(tcx, Ty::new_unit(tcx));
|
Ty::new_imm_ptr(self.tcx, self.tcx.types.unit)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ty.is_mutable_ptr() {
|
t.super_fold_with(self)
|
||||||
ty = Ty::new_mut_ptr(tcx, transform_ty(tcx, *ptr_ty, parents, options));
|
|
||||||
} else {
|
|
||||||
ty = Ty::new_imm_ptr(tcx, transform_ty(tcx, *ptr_ty, parents, options));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::FnPtr(fn_sig) => {
|
ty::FnPtr(..) => {
|
||||||
if options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
if self.options.contains(TransformTyOptions::GENERALIZE_POINTERS) {
|
||||||
ty = Ty::new_imm_ptr(tcx, Ty::new_unit(tcx));
|
Ty::new_imm_ptr(self.tcx, self.tcx.types.unit)
|
||||||
} else {
|
} else {
|
||||||
let parameters: Vec<Ty<'tcx>> = fn_sig
|
t.super_fold_with(self)
|
||||||
.skip_binder()
|
|
||||||
.inputs()
|
|
||||||
.iter()
|
|
||||||
.map(|ty| transform_ty(tcx, *ty, parents, options))
|
|
||||||
.collect();
|
|
||||||
let output = transform_ty(tcx, fn_sig.skip_binder().output(), parents, options);
|
|
||||||
ty = Ty::new_fn_ptr(
|
|
||||||
tcx,
|
|
||||||
ty::Binder::bind_with_vars(
|
|
||||||
tcx.mk_fn_sig(
|
|
||||||
parameters,
|
|
||||||
output,
|
|
||||||
fn_sig.c_variadic(),
|
|
||||||
fn_sig.unsafety(),
|
|
||||||
fn_sig.abi(),
|
|
||||||
),
|
|
||||||
fn_sig.bound_vars(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Dynamic(predicates, _region, kind) => {
|
ty::Dynamic(predicates, _region, kind) => {
|
||||||
ty = Ty::new_dynamic(
|
let predicates = self.tcx.mk_poly_existential_predicates_from_iter(
|
||||||
tcx,
|
predicates.iter().filter_map(|predicate| match predicate.skip_binder() {
|
||||||
transform_predicates(tcx, predicates),
|
ty::ExistentialPredicate::Trait(trait_ref) => {
|
||||||
tcx.lifetimes.re_erased,
|
let trait_ref = ty::TraitRef::identity(self.tcx, trait_ref.def_id);
|
||||||
*kind,
|
Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
|
||||||
|
ty::ExistentialTraitRef::erase_self_ty(self.tcx, trait_ref),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::Projection(..) => None,
|
||||||
|
ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Ty::new_dynamic(self.tcx, predicates, self.tcx.lifetimes.re_erased, *kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Alias(..) => {
|
ty::Alias(..) => {
|
||||||
ty = transform_ty(
|
self.fold_ty(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), t))
|
||||||
tcx,
|
|
||||||
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty),
|
|
||||||
parents,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => {
|
ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => {
|
||||||
bug!("transform_ty: unexpected `{:?}`", ty.kind());
|
bug!("fold_ty: unexpected `{:?}`", t.kind());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty
|
fn interner(&self) -> TyCtxt<'tcx> {
|
||||||
|
self.tcx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
|
/// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
|
||||||
@ -1068,7 +994,8 @@ pub fn typeid_for_fnabi<'tcx>(
|
|||||||
// Encode the return type
|
// Encode the return type
|
||||||
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
|
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
|
||||||
.unwrap_or_else(|| bug!("typeid_for_fnabi: invalid option(s) `{:?}`", options.bits()));
|
.unwrap_or_else(|| bug!("typeid_for_fnabi: invalid option(s) `{:?}`", options.bits()));
|
||||||
let ty = transform_ty(tcx, fn_abi.ret.layout.ty, &mut Vec::new(), transform_ty_options);
|
let mut type_folder = TransformTy::new(tcx, transform_ty_options);
|
||||||
|
let ty = fn_abi.ret.layout.ty.fold_with(&mut type_folder);
|
||||||
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
||||||
|
|
||||||
// Encode the parameter types
|
// Encode the parameter types
|
||||||
@ -1080,7 +1007,7 @@ pub fn typeid_for_fnabi<'tcx>(
|
|||||||
let mut pushed_arg = false;
|
let mut pushed_arg = false;
|
||||||
for arg in fn_abi.args.iter().filter(|arg| arg.mode != PassMode::Ignore) {
|
for arg in fn_abi.args.iter().filter(|arg| arg.mode != PassMode::Ignore) {
|
||||||
pushed_arg = true;
|
pushed_arg = true;
|
||||||
let ty = transform_ty(tcx, arg.layout.ty, &mut Vec::new(), transform_ty_options);
|
let ty = arg.layout.ty.fold_with(&mut type_folder);
|
||||||
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
||||||
}
|
}
|
||||||
if !pushed_arg {
|
if !pushed_arg {
|
||||||
@ -1093,8 +1020,7 @@ pub fn typeid_for_fnabi<'tcx>(
|
|||||||
if fn_abi.args[n].mode == PassMode::Ignore {
|
if fn_abi.args[n].mode == PassMode::Ignore {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let ty =
|
let ty = fn_abi.args[n].layout.ty.fold_with(&mut type_folder);
|
||||||
transform_ty(tcx, fn_abi.args[n].layout.ty, &mut Vec::new(), transform_ty_options);
|
|
||||||
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user