-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Right now format_args!
uses, e.g. ArgumentV1::new(&runtime_data, Debug::fmt)
(for {:?}
), at runtime, using up two pointers per argument at runtime instead of just one (&runtime_data
).
With allow_internal_unsafe
and #44240, we can place the (e.g. Debug::fmt
) fn
pointers in (rvalue-promoted) 'static
data, the remaining hurdle is how to infer the type of the runtime data.
That is, Debug::fmt
is really <_ as Debug>::fmt
and that _
is right now inferred because of ArgumentV1::new
's signature typing them together. If they're separate, we need something new.
I propose using the HList
pattern (struct HCons<H, T>(H, T); struct HNil;
- so for 3 elements, of types A
, B
and C
you'd have HCons<A, HCons<B, HCons<C, HNil>>>
), with #[repr(C)]
, which would give it a deterministic layout which matches that of an array, that is, these two:
&'static HCons<fn(&A), HCons<fn(&B), HCons<fn(&C), HNil>>>
&'static [unsafe fn(*const Opaque); 3]
have the same representation, and the latter can be unsized into a slice. This transformation from HList
to array (and then slice) can be performed on top of a safe, rvalue-promoted HCons
, which is a necessary requirement for moving the fn
pointers into 'static
data at all.
For inference, we can simply insert some function calls to match up the types, e.g. to infer B
we could dofmt::unify_fn_with_data((list.1).0, &b)
, which would makeB
into typeof b
.
It might actually be simpler to have a completely safe "builder" interface, which combines the HList
of formatters with a HList
of runtime references, unifying the types, but I'm a bit worried about compile-times due to all the trait dispatch - in any case, the impact should be measured.