diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cac12e5ee0bb9..b23209a15c5b7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1831,6 +1831,11 @@ impl<'tcx> Ty<'tcx> { self.0.0.flags } + #[inline] + pub fn is_tuple(self) -> bool { + matches!(self.kind(), Tuple(..)) + } + #[inline] pub fn is_unit(self) -> bool { match self.kind() { @@ -2207,6 +2212,11 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), FnDef(..) | FnPtr(_)) } + #[inline] + pub fn is_fn_def(self) -> bool { + matches!(self.kind(), FnDef(..)) + } + #[inline] pub fn is_fn_ptr(self) -> bool { matches!(self.kind(), FnPtr(_)) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 02bb1fde75c1b..1373563f4b133 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,6 +91,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![feature(iter_order_by)] +#![feature(let_chains)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_symbol_mangling/src/typeid.rs b/compiler/rustc_symbol_mangling/src/typeid.rs index e8763e49e624b..31efeb44c2c25 100644 --- a/compiler/rustc_symbol_mangling/src/typeid.rs +++ b/compiler/rustc_symbol_mangling/src/typeid.rs @@ -4,7 +4,7 @@ /// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, /// see design document in the tracking issue #89653. use bitflags::bitflags; -use rustc_middle::ty::{Instance, Ty, TyCtxt}; +use rustc_middle::ty::{Instance, List, Ty, TyCtxt}; use rustc_target::abi::call::FnAbi; use std::hash::Hasher; use twox_hash::XxHash64; @@ -27,7 +27,11 @@ pub fn typeid_for_fnabi<'tcx>( fn_abi: &FnAbi<'tcx, Ty<'tcx>>, options: TypeIdOptions, ) -> String { - typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options) + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, None), + options, + ) } /// Returns a type metadata identifier for the specified Instance. @@ -36,7 +40,16 @@ pub fn typeid_for_instance<'tcx>( instance: &Instance<'tcx>, options: TypeIdOptions, ) -> String { - typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options) + let fn_abi = tcx + .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, List::empty()))) + .unwrap_or_else(|instance| { + bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) + }); + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, Some(instance)), + options, + ) } /// Returns a KCFI type metadata identifier for the specified FnAbi. @@ -48,7 +61,14 @@ pub fn kcfi_typeid_for_fnabi<'tcx>( // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options).as_bytes()); + hash.write( + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, None), + options, + ) + .as_bytes(), + ); hash.finish() as u32 } @@ -58,9 +78,21 @@ pub fn kcfi_typeid_for_instance<'tcx>( instance: &Instance<'tcx>, options: TypeIdOptions, ) -> u32 { + let fn_abi = tcx + .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, List::empty()))) + .unwrap_or_else(|instance| { + bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) + }); // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes()); + hash.write( + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, Some(instance)), + options, + ) + .as_bytes(), + ); hash.finish() as u32 } diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 51e2c96120caa..1aeb0b4b093f3 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -277,7 +277,9 @@ fn encode_region<'tcx>(region: Region<'tcx>, dict: &mut FxHashMap, s.push('E'); compress(dict, DictKey::Region(region), &mut s); } - // FIXME(@lcnr): Why is `ReEarlyParam` reachable here. + // This is possible becasuse trait objects created by new_dynamic_trait and + // new_dynamic_fn_trait are created with tcx.lifetimes.re_erased, and non Fn traits are + // transformed into their identities in transform_predicate. RegionKind::ReEarlyParam(..) | RegionKind::ReErased => { s.push_str("u6region"); compress(dict, DictKey::Region(region), &mut s); @@ -637,37 +639,6 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } - // Function types - ty::FnDef(def_id, args) - | ty::Closure(def_id, args) - | ty::CoroutineClosure(def_id, args) => { - // u[IE], where is , - // as vendor extended type. - let mut s = String::new(); - let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, args, dict, options)); - compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); - typeid.push_str(&s); - } - - ty::Coroutine(def_id, args, ..) => { - // u[IE], where is , - // as vendor extended type. - let mut s = String::new(); - let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); - // Encode parent args only - s.push_str(&encode_args( - tcx, - tcx.mk_args(args.as_coroutine().parent_args()), - dict, - options, - )); - compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); - typeid.push_str(&s); - } - // Pointer types ty::Ref(region, ty0, ..) => { // [U3mut]u3refIE as vendor extended type qualifier and type @@ -719,6 +690,20 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + // Associated type projections + ty::Alias(_, alias_ty) => { + // u[IE], where is , + // as vendor extended type. + let mut s = String::new(); + let name = encode_ty_name(tcx, alias_ty.def_id); + let _ = write!(s, "u{}{}", name.len(), &name); + s.push_str(&encode_args(tcx, alias_ty.args, dict, options)); + compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); + typeid.push_str(&s); + } + + // This is possible because non Fn traits are transformed into their identities in + // transform_predicate. // Type parameters ty::Param(..) => { // u5param as vendor extended type @@ -728,9 +713,12 @@ fn encode_ty<'tcx>( } // Unexpected types - ty::Alias(..) - | ty::Bound(..) + ty::Bound(..) + | ty::Closure(..) | ty::Error(..) + | ty::FnDef(..) + | ty::Coroutine(..) + | ty::CoroutineClosure(..) | ty::CoroutineWitness(..) | ty::Infer(..) | ty::Placeholder(..) => { @@ -741,25 +729,333 @@ fn encode_ty<'tcx>( typeid } +/// Returns the list of arguments if principal is an Fn trait. +pub fn fn_trait_args<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: &List>, +) -> Option<&'tcx List>> { + if is_fn_trait(tcx, predicates) { + if let Some(args) = principal_args(predicates) + && !args.is_empty() + && args[0].expect_ty().is_tuple() + { + Some(args[0].expect_ty().tuple_fields()) + } else { + bug!("fn_trait_args: unexpected non-tuple arg `{:?}`", principal_args(predicates)); + } + } else { + None + } +} + +/// Returns the output if principal is an Fn trait. +pub fn fn_trait_output<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: &List>, +) -> Option> { + if is_fn_trait(tcx, predicates) { + if let Some(projection) = predicates.projection_bounds().next() + && let Some(ty) = projection.skip_binder().term.ty() + { + Some(ty) + } else { + bug!( + "fn_trait_output: unexpected non-term projection `{:?}`", + predicates.projection_bounds().next() + ); + } + } else { + None + } +} + +/// Returns the signature if principal is an Fn trait. +pub fn fn_trait_sig<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: &List>, +) -> Option> { + if is_fn_trait(tcx, predicates) { + Some(tcx.mk_fn_sig( + fn_trait_args(tcx, predicates).unwrap(), + fn_trait_output(tcx, predicates).unwrap(), + false, + hir::Unsafety::Normal, + Abi::Rust, + )) + } else { + None + } +} + +/// Returns true if the FnAbi is an unpacked "rust-call" ABI closure call. +fn is_closure_call<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> bool { + if fn_abi.conv == Conv::Rust + && !fn_abi.c_variadic + && !fn_abi.args.is_empty() + && fn_abi.args[0].is_ignore() + && let ty::Closure(_, args) = fn_abi.args[0].layout.ty.peel_refs().kind() + { + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + return fn_sig + .skip_binder() + .inputs() + .iter() + .eq_by(&fn_abi.args[1..], |ty, arg| *ty == arg.layout.ty) + && fn_sig.output().skip_binder() == fn_abi.ret.layout.ty; + } + false +} + +/// Returns true if the FnAbi is a dynamic Fn trait call. +fn is_dynamic_fn_call<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> bool { + if fn_abi.conv == Conv::Rust + && !fn_abi.c_variadic + && !fn_abi.args.is_empty() + && let ty::Dynamic(predicates, ..) = fn_abi.args[0].layout.ty.peel_refs().kind() + { + if is_fn_trait(tcx, predicates) { + return fn_trait_args(tcx, predicates) + .unwrap() + .iter() + .eq_by(&fn_abi.args[1..], |ty, arg| ty == arg.layout.ty) + && fn_trait_output(tcx, predicates).unwrap() == fn_abi.ret.layout.ty; + } + } + false +} + +/// Returns true if the trait object is an Fn trait object. +#[inline(always)] +fn is_dynamic_fn_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::Dynamic(predicates, ..) => is_fn_trait(tcx, predicates), + _ => false, + } +} + +/// Returns true if principal is an Fn trait. +#[inline(always)] +pub fn is_fn_trait<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: &List>, +) -> bool { + if let Some(principal) = predicates.principal() + && tcx.is_fn_trait(principal.skip_binder().def_id) + { + true + } else { + false + } +} + +/// Creates a trait object. +fn new_dynamic_trait<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: GenericArgsRef<'tcx>, +) -> Ty<'tcx> { + let predicate = + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id: def_id, args: args }); + let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]); + Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn) +} + +/// Creates an Fn trait object. +fn new_dynamic_fn_trait<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: &[Ty<'tcx>], + output: Ty<'tcx>, +) -> Ty<'tcx> { + let trait_ref = ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { + def_id: def_id, + args: tcx.mk_args(&[Ty::new_tup(tcx, args).into()]), + }); + let projection = ty::ExistentialPredicate::Projection(ty::ExistentialProjection { + def_id: tcx.lang_items().fn_once_output().unwrap(), + args: List::empty(), + term: output.into(), + }); + let predicates = tcx.mk_poly_existential_predicates(&[ + ty::Binder::dummy(trait_ref), + ty::Binder::dummy(projection), + ]); + Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn) +} + +/// Returns the principal list of arguments. +pub fn principal_args<'tcx>( + predicates: &List>, +) -> Option<&'tcx List>> { + predicates.principal().map(|trait_ref| trait_ref.skip_binder().args) +} + +/// Transforms an FnAbi for being encoded and used in the substitution dictionary. +/// +/// * Replaces the concrete self of trait default implementations and trait implementations by a +/// reference to a trait object. +/// * Transforms closure and Fn trait object calls into function pointer calls unconditionally. +/// +pub fn transform_fnabi<'tcx>( + tcx: TyCtxt<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + _options: EncodeTyOptions, + instance: Option<&Instance<'tcx>>, +) -> FnAbi<'tcx, Ty<'tcx>> { + if let Some(instance) = instance + && matches!(instance.def, ty::InstanceDef::Item(..)) + && let Some(impl_def_id) = tcx.impl_of_method(instance.def_id()) + && let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) + && !fn_abi.args.is_empty() + && fn_abi.args[0].layout.ty.is_ref() + { + // Replace the concrete self by a reference to a trait object + let self_ty = if tcx.is_fn_trait(trait_ref.skip_binder().def_id) { + // For the actual Fn traits default implementations, remove unsubstituted args from + // their trait objects to prevent these from being used as parameters when Fn trait + // objects are transformed into function pointers in transform_ty. + if fn_abi.args[0].layout.ty.is_mutable_ptr() { + Ty::new_mut_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_fn_trait( + tcx, + trait_ref.skip_binder().def_id, + &[], + Ty::new_unit(tcx), + ), + ) + } else { + Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_fn_trait( + tcx, + trait_ref.skip_binder().def_id, + &[], + Ty::new_unit(tcx), + ), + ) + } + } else { + // For non Fn traits, either leave or remove unsubstituted args from their trait objects + // because non Fn traits are transformed into their identities anyway in + // transform_predicate. + if fn_abi.args[0].layout.ty.is_mutable_ptr() { + Ty::new_mut_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_trait( + tcx, + trait_ref.skip_binder().def_id, + trait_ref.skip_binder().args, + ), + ) + } else { + Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_trait( + tcx, + trait_ref.skip_binder().def_id, + trait_ref.skip_binder().args, + ), + ) + } + }; + let mut fn_abi = fn_abi.clone(); + // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the + // other fields are never used. + fn_abi.args[0].layout.ty = self_ty; + + return fn_abi; + } else if is_closure_call(tcx, fn_abi) + && let ty::Closure(_, args) = fn_abi.args[0].layout.ty.peel_refs().kind() + { + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + return tcx + .fn_abi_of_fn_ptr(ty::ParamEnv::empty().and((fn_sig, List::empty()))) + .unwrap_or_else(|fn_abi_error| { + bug!("transform_fnabi: couldn't get fn_abi of fn_sig {:?}", fn_abi_error) + }) + .clone(); + } else if is_dynamic_fn_call(tcx, fn_abi) { + let fn_sig = ty::Binder::bind_with_vars( + tcx.mk_fn_sig( + fn_abi.args[1..].iter().map(|arg| arg.layout.ty), + fn_abi.ret.layout.ty, + false, + hir::Unsafety::Normal, + Abi::Rust, + ), + List::empty(), + ); + return tcx + .fn_abi_of_fn_ptr(ty::ParamEnv::empty().and((fn_sig, List::empty()))) + .unwrap_or_else(|fn_abi_error| { + bug!("transform_fnabi: couldn't get fn_abi of fn_sig {:?}", fn_abi_error) + }) + .clone(); + } + + fn_abi.clone() +} + +/// Transforms a predicate for being encoded and used in the substitution dictionary. +fn transform_predicate<'tcx>( + tcx: TyCtxt<'tcx>, + predicate: ty::PolyExistentialPredicate<'tcx>, + _options: EncodeTyOptions, +) -> ty::PolyExistentialPredicate<'tcx> { + match predicate.as_ref().skip_binder() { + ty::ExistentialPredicate::Trait(trait_ref) => { + if tcx.is_fn_trait(trait_ref.def_id) { + // Fn trait objects are transformed into function pointers in + // transform_ty instead. + bug!("transform_predicate: unexpected Fn trait `{}`", trait_ref) + } else { + // Transform non Fn traits into their identities + 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, + } +} + /// Transforms predicates for being encoded and used in the substitution dictionary. fn transform_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: &List>, + options: EncodeTyOptions, ) -> &'tcx List> { let predicates: Vec> = predicates + .iter() + .filter_map(|predicate| Some(transform_predicate(tcx, predicate, options))) + .collect(); + + // Use either the base trait or autotraits only as discriminant + let (base_trait, autotraits): ( + Vec>, + Vec>, + ) = 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::Trait(..) => Some(predicate), ty::ExistentialPredicate::Projection(..) => None, ty::ExistentialPredicate::AutoTrait(..) => Some(predicate), }) - .collect(); - tcx.mk_poly_existential_predicates(&predicates) + .partition(|predicate| match predicate.skip_binder() { + ty::ExistentialPredicate::AutoTrait(..) => true, + _ => false, + }); + if !base_trait.is_empty() { + tcx.mk_poly_existential_predicates(&base_trait) + } else { + tcx.mk_poly_existential_predicates(&autotraits) + } } /// Transforms args for being encoded and used in the substitution dictionary. @@ -776,15 +1072,25 @@ fn transform_args<'tcx>( tcx.mk_args_from_iter(args) } -// 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::NORMALIZE_INTEGERS option is set. +/// Transforms a ty:Ty for being encoded and used in the substitution dictionary. +/// +/// * Transforms all c_void types into unit types unconditionally. +/// * Generalizes pointers if TransformTyOptions::GENERALIZE_POINTERS option is set. +/// * Normalizes integers if TransformTyOptions::NORMALIZE_INTEGERS option is set. +/// * Generalizes any repr(transparent) user-defined type that is either a pointer or reference, and +/// either references itself or any other type that contains or references itself, to avoid a +/// reference cycle. +/// * Transforms repr(transparent) types without non-ZST field into (). +/// * Transforms function items into function pointers unconditionally. +/// * Transforms closures into function pointers unconditionally. +/// * Transforms Fn trait objects into function pointers unconditionally. +/// * Transforms non Fn traits into their identities unconditionally (in transform_predicate). +/// fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptions) -> Ty<'tcx> { let mut ty = ty; match ty.kind() { - ty::Float(..) | ty::Str | ty::Never | ty::Foreign(..) | ty::CoroutineWitness(..) => {} + ty::Alias(..) | ty::Float(..) | ty::Str | ty::Never | ty::Foreign(..) | ty::Param(..) => {} ty::Bool => { if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) { @@ -898,34 +1204,53 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } } - ty::FnDef(def_id, args) => { - ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, options)); + ty::FnDef(def_id, ..) => { + // Transform function items into function pointers + let fn_sig = tcx.fn_sig(def_id).skip_binder(); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); } - ty::Closure(def_id, args) => { - ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options)); + ty::Closure(_, args) => { + // Transform closures into function pointers + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); } - ty::CoroutineClosure(def_id, args) => { - ty = Ty::new_coroutine_closure(tcx, *def_id, transform_args(tcx, args, options)); - } - - ty::Coroutine(def_id, args) => { - ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options)); + ty::Coroutine(_, args) => { + let def_id = tcx.require_lang_item(hir::LangItem::Coroutine, None); + let gen_sig = args.as_coroutine().sig(); + ty = new_dynamic_trait( + tcx, + def_id, + tcx.mk_args(&[ + gen_sig.resume_ty.into(), + gen_sig.yield_ty.into(), + gen_sig.return_ty.into(), + ]), + ); } 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 { - ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); - } + // Remove references from function items, closures, and Fn trait objects + if ty0.is_fn_def() || ty0.is_closure() || is_dynamic_fn_trait(tcx, *ty0) { + ty = transform_ty(tcx, *ty0, options); } else { - if ty.is_mutable_ptr() { - ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + 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 { + ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); + } } else { - ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + if ty.is_mutable_ptr() { + ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + } else { + ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + } } } } @@ -974,23 +1299,31 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } ty::Dynamic(predicates, _region, kind) => { - ty = Ty::new_dynamic( - tcx, - transform_predicates(tcx, predicates), - tcx.lifetimes.re_erased, - *kind, - ); - } - - ty::Alias(..) => { - ty = transform_ty( - tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty), - options, - ); + if is_fn_trait(tcx, predicates) { + // Transform Fn trait objects into function pointers + let fn_sig = ty::Binder::bind_with_vars( + fn_trait_sig(tcx, predicates).unwrap(), + List::empty(), + ); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); + } else { + ty = Ty::new_dynamic( + tcx, + transform_predicates(tcx, predicates, options), + tcx.lifetimes.re_erased, + *kind, + ); + } } - ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => { + ty::Bound(..) + | ty::Error(..) + | ty::CoroutineClosure(..) + | ty::CoroutineWitness(..) + | ty::Infer(..) + | ty::Placeholder(..) => { bug!("transform_ty: unexpected `{:?}`", ty.kind()); } } @@ -1074,58 +1407,3 @@ pub fn typeid_for_fnabi<'tcx>( typeid } - -/// Returns a type metadata identifier for the specified Instance using the Itanium C++ ABI with -/// vendor extended type qualifiers and types for Rust types that are not used at the FFI boundary. -pub fn typeid_for_instance<'tcx>( - tcx: TyCtxt<'tcx>, - instance: &Instance<'tcx>, - options: TypeIdOptions, -) -> String { - let fn_abi = tcx - .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, ty::List::empty()))) - .unwrap_or_else(|instance| { - bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) - }); - - // If this instance is a method and self is a reference, get the impl it belongs to - let impl_def_id = tcx.impl_of_method(instance.def_id()); - if impl_def_id.is_some() && !fn_abi.args.is_empty() && fn_abi.args[0].layout.ty.is_ref() { - // If this impl is not an inherent impl, get the trait it implements - if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id.unwrap()) { - // Transform the concrete self into a reference to a trait object - let existential_predicate = trait_ref.map_bound(|trait_ref| { - ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty( - tcx, trait_ref, - )) - }); - let existential_predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy( - existential_predicate.skip_binder(), - )]); - // Is the concrete self mutable? - let self_ty = if fn_abi.args[0].layout.ty.is_mutable_ptr() { - Ty::new_mut_ref( - tcx, - tcx.lifetimes.re_erased, - Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), - ) - } else { - Ty::new_imm_ref( - tcx, - tcx.lifetimes.re_erased, - Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), - ) - }; - - // Replace the concrete self in an fn_abi clone by the reference to a trait object - let mut fn_abi = fn_abi.clone(); - // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the - // other fields are never used. - fn_abi.args[0].layout.ty = self_ty; - - return typeid_for_fnabi(tcx, &fn_abi, options); - } - } - - typeid_for_fnabi(tcx, fn_abi, options) -} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs new file mode 100644 index 0000000000000..56d99b166a0de --- /dev/null +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs @@ -0,0 +1,55 @@ +// Verifies that type metadata identifiers for closures are emitted correctly. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 + +#![crate_type="lib"] +pub fn foo1(a: fn(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"[[TYPE1B:_ZTSFu3i32S_E]]") + a(1); +} + +pub fn bar1() { + foo1(|a| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar1{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo1(a); + // CHECK-LABEL: define{{.*}}4bar11a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +pub fn foo2(a: &dyn Fn(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"[[TYPE1B]]") + a(1); +} + +pub fn bar2() { + foo2(&|a: i32| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar2{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo2(&a); + // CHECK-LABEL: define{{.*}}4bar21a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +pub fn foo3(a: &mut dyn FnMut(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%.+}}, metadata !"[[TYPE1B]]") + a(1); +} + +pub fn bar3() { + foo3(&mut |a: i32| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar3{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo3(&mut a); + // CHECK-LABEL: define{{.*}}4bar31a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +// CHECK: ![[TYPE1A]] = !{i64 0, !"[[TYPE1B]]"} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs similarity index 50% rename from tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs rename to tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs index 318aad9291c4a..c517f392bc522 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs @@ -6,144 +6,155 @@ #![crate_type="lib"] pub trait Trait1 { - fn foo(&self); + fn foo1(&self); } #[derive(Clone, Copy)] pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { + fn foo1(&self) { } + // CHECK-LABEL: define{{.*}}Type1$u20$as$u20${{.*}}Trait1$GT$4foo1 + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait2 { - fn bar(&self); + fn foo2(&self); } pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { + fn foo2(&self) { } + // CHECK-LABEL: define{{.*}}Type2$u20$as$u20${{.*}}Trait2$LT$i32$GT$$GT$4foo2 + // CHECK-SAME: {{.*}}!type ![[TYPE2A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait3 { - fn baz(&self, _: &T); + fn foo3(&self, _: &T); } pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { + fn foo3(&self, _: &U) { } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait3$LT$U$GT$$GT$4foo3 + // CHECK-SAME: {{.*}}!type ![[TYPE3A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait4<'a, T> { type Output: 'a; - fn qux(&self, _: &T) -> Self::Output; + fn foo4(&self, _: &T) -> Self::Output; } pub struct Type4; impl<'a, T, U> Trait4<'a, U> for T { type Output = &'a i32; - fn qux(&self, _: &U) -> Self::Output { + fn foo4(&self, _: &U) -> Self::Output { &0 } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait4$LT$U$GT$$GT$4foo4 + // CHECK-SAME: {{.*}}!type ![[TYPE4A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait5 { - fn quux(&self, _: &[T; N]); + fn foo5(&self, _: &[T; N]); } #[derive(Copy, Clone)] pub struct Type5; impl Trait5 for T { - fn quux(&self, _: &[U; N]) { + fn foo5(&self, _: &[U; N]) { } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait5$LT$U$C$_$GT$$GT$4foo5 + // CHECK-SAME: {{.*}}!type ![[TYPE5A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub fn foo1(a: &dyn Trait1) { - a.foo(); + a.foo1(); // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait1u6regionEEE]]") } pub fn bar1() { let a = Type1; + foo1(&a); let b = &a as &dyn Trait1; - b.foo(); + b.foo1(); // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1B]]") } pub fn foo2(a: &dyn Trait2) { - a.bar(); + a.foo2(); // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait2Iu5paramEu6regionEEE]]") } pub fn bar2() { let a = Type2; foo2(&a); let b = &a as &dyn Trait2; - b.bar(); + b.foo2(); // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2B]]") } pub fn foo3(a: &dyn Trait3) { let b = Type3; - a.baz(&b); + a.foo3(&b); // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait3Iu5paramEu6regionEEu3refIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type3EE]]") } pub fn bar3() { let a = Type3; foo3(&a); let b = &a as &dyn Trait3; - b.baz(&a); + b.foo3(&a); // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3B]]") } pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) { let b = Type4; - a.qux(&b); + a.foo4(&b); // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4B:_ZTSFu3refIu3i32Eu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait4Iu6regionu5paramEu6regionEEu3refIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type4EE]]") } pub fn bar4<'a>() { let a = Type4; foo4(&a); let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>; - b.qux(&a); + b.foo4(&a); // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4B]]") } pub fn foo5(a: &dyn Trait5) { let b = &[Type5; 32]; - a.quux(&b); + a.foo5(&b); // CHECK-LABEL: define{{.*}}4foo5{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait5Iu5paramLu5usizeEEu6regionEEu3refIA32u[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type5EE]]") } pub fn bar5() { let a = &[Type5; 32]; foo5(&a); let b = &a as &dyn Trait5; - b.quux(&a); + b.foo5(&a); // CHECK-LABEL: define{{.*}}4bar5{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5B]]") } -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE5]]"} +// CHECK: ![[TYPE1A]] = !{i64 0, !"[[TYPE1B]]"} +// CHECK: ![[TYPE2A]] = !{i64 0, !"[[TYPE2B]]"} +// CHECK: ![[TYPE3A]] = !{i64 0, !"[[TYPE3B]]"} +// CHECK: ![[TYPE4A]] = !{i64 0, !"[[TYPE4B]]"} +// CHECK: ![[TYPE5A]] = !{i64 0, !"[[TYPE5B]]"} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index 5f49909712f96..e4325558752df 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -7,7 +7,7 @@ #![allow(dead_code)] #![allow(incomplete_features)] #![allow(unused_must_use)] -#![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)] +#![feature(adt_const_params, coroutines, extern_types, inline_const, type_alias_impl_trait)] extern crate core; use core::ffi::*; @@ -43,15 +43,33 @@ impl Trait1 for i32 { fn foo(&self) { } } -// Trait implementation -impl Trait1 for Struct1 { - fn foo(&self) { } +// Helper type to make Type1 have an unique id +struct Foo(i32); + +// repr(transparent) user-defined type +#[repr(transparent)] +pub struct Type1 { + member1: (), + member2: PhantomData, + member3: Foo, } +// Self-referencing repr(transparent) user-defined type +#[repr(transparent)] +pub struct Type2<'a> { + member1: (), + member2: PhantomData, + member3: &'a Type2<'a>, +} + +// Helper type to make Type3 have an unique id +pub struct Bar; + +// repr(transparent) user-defined generic type +#[repr(transparent)] +pub struct Type3(T); + // impl Trait type aliases for helping with defining other types (see below) -pub type Type1 = impl Send; -pub type Type2 = impl Send; -pub type Type3 = impl Send; pub type Type4 = impl Send; pub type Type5 = impl Send; pub type Type6 = impl Send; @@ -62,9 +80,6 @@ pub type Type10 = impl Send; pub type Type11 = impl Send; pub fn fn1<'a>() where - Type1: 'static, - Type2: 'static, - Type3: 'static, Type4: 'static, Type5: 'static, Type6: 'static, @@ -74,47 +89,36 @@ pub fn fn1<'a>() where Type10: 'static, Type11: 'static, { - // Closure - let closure1 = || { }; - let _: Type1 = closure1; - // Constructor pub struct Foo(i32); - let _: Type2 = Foo; + let _: Type4 = Foo; + + // Closure + let closure1 = |_: i64| { }; + let _: Type5 = closure1; + + // Coroutine + let coroutine1 = || { yield 1; 1 }; + let _: Type6 = coroutine1; // Type in extern path extern { fn foo(); } - let _: Type3 = foo; + let _: Type7 = foo; // Type in closure path || { pub struct Foo; - let _: Type4 = Foo; + let _: Type8 = Foo; }; // Type in const path const { pub struct Foo; - fn foo() -> Type5 { Foo } + fn foo() -> Type9 { Foo } }; - // Type in impl path - impl Struct1 { - fn foo(&self) { } - } - let _: Type6 = >::foo; - - // Trait method - let _: Type7 = >::foo; - - // Trait method - let _: Type8 = >::foo; - - // Trait method - let _: Type9 = as Trait1>::foo; - // Const generics pub struct Qux([T; N]); let _: Type10 = Qux([0; 32]); @@ -125,32 +129,6 @@ pub fn fn1<'a>() where let _: Type11 = Quuux; } -// Helper type to make Type12 have an unique id -struct Foo(i32); - -// repr(transparent) user-defined type -#[repr(transparent)] -pub struct Type12 { - member1: (), - member2: PhantomData, - member3: Foo, -} - -// Self-referencing repr(transparent) user-defined type -#[repr(transparent)] -pub struct Type13<'a> { - member1: (), - member2: PhantomData, - member3: &'a Type13<'a>, -} - -// Helper type to make Type14 have an unique id -pub struct Bar; - -// repr(transparent) user-defined generic type -#[repr(transparent)] -pub struct Type14(T); - pub fn foo0(_: ()) { } // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} pub fn foo1(_: (), _: c_void) { } @@ -339,118 +317,94 @@ pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) { } // CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} pub fn foo93(_: fn(i32) -> i32) { } // CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo94(_: fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } // CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo95(_: fn(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } // CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo96(_: &dyn Fn(i32) -> i32) { } +pub fn foo96(_: &dyn Trait1) { } // CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo97(_: &dyn Trait1, _: &dyn Trait1) { } // CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo98(_: &dyn Trait1, _: &dyn Trait1, _: &dyn Trait1) { } // CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo99(_: &dyn FnMut(i32) -> i32) { } +pub fn foo99(_: &dyn Send) { } // CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo100(_: &dyn Send, _: &dyn Send) { } // CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo101(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } // CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo102(_: &dyn FnOnce(i32) -> i32) { } +pub fn foo102(_: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } +pub fn foo103(_: &(dyn Send + Sync), _: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo104(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} +pub fn foo104(_: &(dyn Send + Sync), _: &(dyn Send + Sync), _: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo105(_: &dyn Send) { } +pub fn foo105(_: Type1) { } // CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo106(_: &dyn Send, _: &dyn Send) { } +pub fn foo106(_: Type1, _: Type1) { } // CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } +pub fn foo107(_: Type1, _: Type1, _: Type1) { } // CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo108(_: Type1) { } +pub fn foo108(_: Type2) { } // CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo109(_: Type1, _: Type1) { } +pub fn foo109(_: Type2, _: Type2) { } // CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo110(_: Type1, _: Type1, _: Type1) { } +pub fn foo110(_: Type2, _: Type2, _: Type2) { } // CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo111(_: Type2) { } +pub fn foo111(_: Type3) { } // CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo112(_: Type2, _: Type2) { } +pub fn foo112(_: Type3, _: Type3) { } // CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo113(_: Type2, _: Type2, _: Type2) { } +pub fn foo113(_: Type3, _: Type3, _: Type3) { } // CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo114(_: Type3) { } +pub fn foo114(_: Type4) { } // CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo115(_: Type3, _: Type3) { } +pub fn foo115(_: Type4, _: Type4) { } // CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo116(_: Type3, _: Type3, _: Type3) { } +pub fn foo116(_: Type4, _: Type4, _: Type4) { } // CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo117(_: Type4) { } +pub fn foo117(_: Type5) { } // CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo118(_: Type4, _: Type4) { } +pub fn foo118(_: Type5, _: Type5) { } // CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo119(_: Type4, _: Type4, _: Type4) { } +pub fn foo119(_: Type5, _: Type5, _: Type5) { } // CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo120(_: Type5) { } +pub fn foo120(_: Type6) { } // CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo121(_: Type5, _: Type5) { } +pub fn foo121(_: Type6, _: Type6) { } // CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo122(_: Type5, _: Type5, _: Type5) { } +pub fn foo122(_: Type6, _: Type6, _: Type6) { } // CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo123(_: Type6) { } +pub fn foo123(_: Type7) { } // CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo124(_: Type6, _: Type6) { } +pub fn foo124(_: Type7, _: Type7) { } // CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo125(_: Type6, _: Type6, _: Type6) { } +pub fn foo125(_: Type7, _: Type7, _: Type7) { } // CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo126(_: Type7) { } +pub fn foo126(_: Type8) { } // CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo127(_: Type7, _: Type7) { } +pub fn foo127(_: Type8, _: Type8) { } // CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo128(_: Type7, _: Type7, _: Type7) { } +pub fn foo128(_: Type8, _: Type8, _: Type8) { } // CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo129(_: Type8) { } +pub fn foo129(_: Type9) { } // CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo130(_: Type8, _: Type8) { } +pub fn foo130(_: Type9, _: Type9) { } // CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo131(_: Type8, _: Type8, _: Type8) { } +pub fn foo131(_: Type9, _: Type9, _: Type9) { } // CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo132(_: Type9) { } +pub fn foo132(_: Type10) { } // CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo133(_: Type9, _: Type9) { } +pub fn foo133(_: Type10, _: Type10) { } // CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo134(_: Type9, _: Type9, _: Type9) { } +pub fn foo134(_: Type10, _: Type10, _: Type10) { } // CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo135(_: Type10) { } +pub fn foo135(_: Type11) { } // CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo136(_: Type10, _: Type10) { } +pub fn foo136(_: Type11, _: Type11) { } // CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo137(_: Type10, _: Type10, _: Type10) { } +pub fn foo137(_: Type11, _: Type11, _: Type11) { } // CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo138(_: Type11) { } -// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo139(_: Type11, _: Type11) { } -// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo140(_: Type11, _: Type11, _: Type11) { } -// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo141(_: Type12) { } -// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo142(_: Type12, _: Type12) { } -// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo143(_: Type12, _: Type12, _: Type12) { } -// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo144(_: Type13) { } -// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo145(_: Type13, _: Type13) { } -// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo146(_: Type13, _: Type13, _: Type13) { } -// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo147(_: Type14) { } -// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo148(_: Type14, _: Type14) { } -// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo149(_: Type14, _: Type14, _: Type14) { } -// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"} @@ -548,57 +502,45 @@ pub fn foo149(_: Type14, _: Type14, _: Type14) { } // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"} // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"} // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"} -// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"} -// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"} -// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"} -// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"} -// CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"} -// CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"} -// CHECK: ![[TYPE108]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvEE"} -// CHECK: ![[TYPE109]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_E"} -// CHECK: ![[TYPE110]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_S1_E"} -// CHECK: ![[TYPE111]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}E"} -// CHECK: ![[TYPE112]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_E"} -// CHECK: ![[TYPE113]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_S_E"} -// CHECK: ![[TYPE114]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooE"} -// CHECK: ![[TYPE115]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_E"} -// CHECK: ![[TYPE116]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_S_E"} -// CHECK: ![[TYPE117]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooE"} -// CHECK: ![[TYPE118]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"} -// CHECK: ![[TYPE119]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"} -// CHECK: ![[TYPE120]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooE"} -// CHECK: ![[TYPE121]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_E"} -// CHECK: ![[TYPE122]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"} -// CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"} -// CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"} -// CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"} -// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32EE"} -// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32ES4_E"} -// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"} -// CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_EE"} -// CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_ES0_E"} -// CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_ES0_S0_E"} -// CHECK: ![[TYPE132]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_EE"} -// CHECK: ![[TYPE133]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_ES1_E"} -// CHECK: ![[TYPE134]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_ES1_S1_E"} -// CHECK: ![[TYPE135]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EEE"} -// CHECK: ![[TYPE136]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_E"} -// CHECK: ![[TYPE137]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_S2_E"} -// CHECK: ![[TYPE138]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_EE"} -// CHECK: ![[TYPE139]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_E"} -// CHECK: ![[TYPE140]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_S0_E"} -// CHECK: ![[TYPE141]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooE"} -// CHECK: ![[TYPE142]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_E"} -// CHECK: ![[TYPE143]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_S_E"} -// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIvEE"} -// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIvES_E"} -// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} -// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarE"} -// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_E"} -// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_S_E"} +// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEEE"} +// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEES3_E"} +// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEES3_S3_E"} +// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"} +// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"} +// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"} +// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEEE"} +// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEES3_E"} +// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEES3_S3_E"} +// CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooE"} +// CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_E"} +// CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_S_E"} +// CHECK: ![[TYPE108]] = !{i64 0, !"_ZTSFvu3refIvEE"} +// CHECK: ![[TYPE109]] = !{i64 0, !"_ZTSFvu3refIvES_E"} +// CHECK: ![[TYPE110]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} +// CHECK: ![[TYPE111]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarE"} +// CHECK: ![[TYPE112]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_E"} +// CHECK: ![[TYPE113]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_S_E"} +// CHECK: ![[TYPE114]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32EE"} +// CHECK: ![[TYPE115]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32ES1_E"} +// CHECK: ![[TYPE116]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32ES1_S1_E"} +// CHECK: ![[TYPE117]] = !{i64 0, !"_ZTSFvPFvu3i64EE"} +// CHECK: ![[TYPE118]] = !{i64 0, !"_ZTSFvPFvu3i64ES0_E"} +// CHECK: ![[TYPE119]] = !{i64 0, !"_ZTSFvPFvu3i64ES0_S0_E"} +// CHECK: ![[TYPE120]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9coroutine9CoroutineIvu3i32S_Eu6regionEE"} +// CHECK: ![[TYPE121]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9coroutine9CoroutineIvu3i32S_Eu6regionES2_E"} +// CHECK: ![[TYPE122]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9coroutine9CoroutineIvu3i32S_Eu6regionES2_S2_E"} +// CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvPFvvEE"} +// CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvPFvvES_E"} +// CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvPFvvES_S_E"} +// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooE"} +// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"} +// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"} +// CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooE"} +// CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_E"} +// CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"} +// CHECK: ![[TYPE132]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EEE"} +// CHECK: ![[TYPE133]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_E"} +// CHECK: ![[TYPE134]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_S2_E"} +// CHECK: ![[TYPE135]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEEE"} +// CHECK: ![[TYPE136]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEES6_E"} +// CHECK: ![[TYPE137]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEES6_S6_E"} diff --git a/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs b/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs new file mode 100644 index 0000000000000..966a87b7f71fd --- /dev/null +++ b/tests/ui/sanitizer/cfi-closure-fn-ptr-cast.rs @@ -0,0 +1,16 @@ +// Tests that converting a closure to a function pointer works +// The notable thing being tested here is that when the closure does not capture anything, +// the call method from its Fn trait takes a ZST representing its environment. The compiler then +// uses the assumption that the ZST is non-passed to reify this into a function pointer. +// +// This checks that the reified function pointer will have the expected alias set at its call-site. + +//@ needs-sanitizer-cfi +//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi +//@ compile-flags:-C codegen-units=1 -C opt-level=0 +//@ run-pass + +pub fn main() { + let f: &fn() = &((|| ()) as _); + f(); +}