Skip to content

New middle::Type #152

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: next
Choose a base branch
from
Draft

New middle::Type #152

wants to merge 2 commits into from

Conversation

emiltayl
Copy link
Contributor

I've been busy the last few weeks, but now I am back with a bigger PR.

This PR contains a rewrite of middle::Type. I started to rewrite it because I found it hard to follow how the old Type worked. I realize that I might have just replaced something that I did not understand with something everybody else does not understand, but I have at least tried to separate out safe functionality (such as just describing libffi type signatures) from unsafe code to handle allocation of memory.

In addition, I have made some breaking changes. None of the changes should require major changes downstream (hopefully), but I am not the best judge over what breaking changes are acceptable and not. Please let me know if you have any input on changes that should be made or changes that I've made that should be undone.

Breaking changes

  • middle::Type is now an enum. It does not manage the memory of ffi_types for Cifs, which is handled by new FfiTypeArray and FfiType structs.
    • Cloning and dropping FfiTypes passes tests in middle::types with miri. The tests should probably be modified to use FfiTypeAray as well.
  • middle::Type does not have a void variant as ffi_type_void cannot be used for argument types in libffi. Instead, when creating a Cif, the result type is an Option<Type> where None represents a void return type.
    • () no longer implements CType. Instead, it implements CRetType, a new trait which is implemented for () and all types that implement CType.
  • Removed the RetType from the CType trait as it is no longer needed. It was previously needed, but become obsolete after Fixed out-of-bounds write in low::call #108 was merged.
  • There might be more subtle breaking changes that I have failed to noticed

Other changes

There are a few other changes I have made that I think it is worth to highlight to get eventual feedback.

Memory management

This crate previously used libc::malloc and libc::free to manage memory for ffi_type. This PR exchanges that for creating Boxes, Box::into_raw and Box::from_raw. With this PR, there is no longer any use of libc and it can be removed as a dependency.

Boxes come with their own set of problems, but this change should avoid problems with uniqueness by not creating Boxes except for allocating memory and from_raw when dropping them. This has the advantage that it allocates memory using the global allocator configured in projects using libffi-rs. In the future this should also make it fairly easy to allow the usage of custom (non-global) allocators if anyone should wish to do so.

I did consider using alloc::alloc to allocate memory, but was hesitant to do so as the documentation states that it "is expected to be deprecated".

Documentation of unsafe code

I have tried to add comments where it is useful to understand the memory management and why/when it is safe to do everything needed to manage memory for ffi_types. I am sure there are places where things could be documented better, and there are probably comments that are superfluous and only add clutter.

I will try to review the comments later, but currently I am blind on my own code.

Deprecation of Type functions

Previously, Types had to be constructed from functions such as Type::u8(). Since the new Type is an enum, this is no longer needed (for all types except structs). I chose to keep the old functions, but deprecate them as I find it better to refer directly to the Type enum variants when possible.

Unresolved issues

Does not currently compile with system feature flag on Mac due to missing long double symbols.

emiltayl added 2 commits May 16, 2025 08:25
This commit changes `middle::Type` from a smart pointer to `ffi_type` to
an enum that represents possible types that can be sent to, and returned
from libffi. Allocation of `ffi_type`s has been moved to a separate
`FfiType` struct. A new `FfiTypeArray` has also been created.

Functions that were previously used to create different `Type`s are
still present, but they are deprecated in favor of referring to `Type`
variants directly.

All allocations now happens using functionality from `alloc` instead of
using `libc::malloc` and `libc::free`. After this change, it is possible
to remove libc as a dependency.

`middle::Type` does not contain a `void` variant as it is not a valid
type for arguments in libffi. Instead, functions now accept an
`Option<Type>` for the return type, where `None` represents a void.

`high:CType` was slightly simplified as the `RetType` is no longer
needed after PR tov#108 was merged. For return types, a new `CRetType`
trait was added that is implemented for all types that implements
`CType` in addition to `()`.
@arihant2math arihant2math requested a review from littledivy May 22, 2025 02:14
@emiltayl
Copy link
Contributor Author

Changing middle::Type from a struct to an enum should not have that much of an effect on crates using libffi as I understand it. It does not contain any fields or methods that are used by other crates to interact with the type.

I would say that the "most" breaking change is removing void as a Type. I like how it prevents setting argument types to void, which libffi does not support. For simple calls, this only requires putting return types inside a Some or setting it to None for void return types. For more advanced use cases this might require some larger changes, but I personally cannot see that this should be too big of a problem. While I think removing void provides the best external interface from this crate, I will leave it up to you to decide whether this is a breaking change that is acceptable or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant