@@ -172,6 +172,8 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
172172 fn is_tuple ( this : TyAndLayout < ' a , Self > ) -> bool ;
173173 fn is_unit ( this : TyAndLayout < ' a , Self > ) -> bool ;
174174 fn is_transparent ( this : TyAndLayout < ' a , Self > ) -> bool ;
175+ /// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
176+ fn is_pass_indirectly_in_non_rustic_abis_flag_set ( this : TyAndLayout < ' a , Self > ) -> bool ;
175177}
176178
177179impl < ' a , Ty > TyAndLayout < ' a , Ty > {
@@ -269,6 +271,29 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
269271 Ty :: is_transparent ( self )
270272 }
271273
274+ /// If this method returns `true`, then this type should always have a `PassMode` of
275+ /// `Indirect { on_stack: false, .. }` when being used as the argument type of a function with a
276+ /// non-Rustic ABI (this is true for structs annotated with the
277+ /// `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute).
278+ ///
279+ /// This is used to replicate some of the behaviour of C array-to-pointer decay; however unlike
280+ /// C any changes the caller makes to the passed value will not be reflected in the callee, so
281+ /// the attribute is only useful for types where observing the value in the caller after the
282+ /// function call isn't allowed (a.k.a. `va_list`).
283+ ///
284+ /// This function handles transparent types automatically.
285+ pub fn pass_indirectly_in_non_rustic_abis < C > ( mut self , cx : & C ) -> bool
286+ where
287+ Ty : TyAbiInterface < ' a , C > + Copy ,
288+ {
289+ while self . is_transparent ( )
290+ && let Some ( ( _, field) ) = self . non_1zst_field ( cx)
291+ {
292+ self = field;
293+ }
294+ Ty :: is_pass_indirectly_in_non_rustic_abis_flag_set ( self )
295+ }
296+
272297 /// Finds the one field that is not a 1-ZST.
273298 /// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
274299 pub fn non_1zst_field < C > ( & self , cx : & C ) -> Option < ( FieldIdx , Self ) >
0 commit comments