Elide types with one FFI representation #178
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit modifies our codegen to elide arguments and return types
that have exactly one FFI representation, such as
()
struct Foo;
andenum MyEnum { OneVariant }
.For example, the following bridge module:
Will now generate the following foreign function interface:
Notice that the extern function does not take any arguments.
This is invisible to the user, since they'll call a function that looks
like:
Zero-sized types are not C FFI safe, so bridging them
requires some degree of shenanigans.
Before this commit we would bridge unit structs using an unused
u8
.This meant that we would waste one byte of memory per bridged
transparent struct instance.
Now, to be fair, this was fairly tiny overhead, and an unimaginably
small number of users should ever have a use case where they're bridging
enough empty structs for a single byte of overhead per struct to be
noticed.
But, where's the fun in wasted memory?
As of this commit unit structs and other types that have a single
possible FFI representation have a 0 byte FFI representation since
we don't bridge them at all and they instead just "appear" on the
other side of the boundary.
While implementing this change we added a
.has_exactly_one_representation(&self) -> bool
method to theBridgeableType
trait.This will be useful in the future for other use cases where knowing that
a type has exactly one FFI representation is important.
For example, we plan to implement support for
Result<(), E>
in the future.When
E
is a type that is bridged via a pointer,Result<(), E>
can bebridged using a single pointer, since the
T = ()
case can be encoded asa null pointer.
This generalizes for any
T
whereT
is a type that has exactly oneFFI representation.
Notably, this includes single variant enums such as
MyEnum { OneVariant }
.Although, perhaps not that notably, since I'm still not sure whether
anyone will have an FFI use case that involves bridging single-repr
types.
Who knows. Developers will surprise you.