NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #2906 most downloaded on crates.io
a multi-language bindings generator for rust (runtime support code)
Last release 14 days ago
23 Sep 2026
Ships fairly regularly
a new release about every 2 months
Nearly every release is documented
notes for 30 of 32 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
32 releases · first in 2023
One column per quarter.
Nothing published for this version
Kotlin: Fixed checksum failure on aarch64
chore: Release uniffi version 0.32.0
chore: Release uniffi version 0.32.0
--config flag now expects a global config file
rather than a flat uniffi.toml-style override. Old-style files will produce a warning and be ignored.
See #2866[ByRef] bytes UDL arguments now map to &[u8] on the Rust side instead of &Vec<u8>. UDL-defined functions whose Rust implementations take &Vec<u8> must change to &[u8]. Proc-macro signatures (fn foo(x: &[u8])) are unchanged. On the Kotlin side, call sites must now pass a direct java.nio.ByteBuffer rather than ByteArray; migrate with ByteBuffer.allocateDirect(arr.size).put(arr).flip(). Swift (Data) and Python (bytes) call sites are unchanged. (#2878)CrateConfigSupplier::from_cargo_metadata_command has changed.
It now inputs a MetadataCommand instance and a CargoMetadataOptions rather than just a no_deps flag.UniFfiTag from clippy::exhaustive_structs since downstream projects may depend on it #2809GlobalConfig struct for managing config. It replaces BindgenPathsLayer::get_config() method which has been removed. See #2866.[ByRef] bytes arguments now travel across the FFI as a ForeignBytes (pointer + length) value rather than a RustBuffer. External bindings need to accept the foreign-language byte buffer at the call site and lower it to ForeignBytes for the duration of the call (no copy). (#2878)Global config file support via --config. See the docs.
Traits can now be exported with #[uniffi::export(foreign)] for foreign-only implementations, or #[uniffi::export(rust, foreign)] for both Rust and foreign implementations. The with_foreign flag is deprecated in favor of rust, foreign.
Recursive enums are now supported. UniFFI automatically detects when enum and record types participate in cycles — self-referential, mutually recursive, or cycling through a record — and generates appropriate bindings: indirect in Swift, forward references in Python (#2834).
Box<T> now automatically implements FFI traits when T implements them, allowing direct use in enum variants and function parameters without NewType wrappers (#2808)
Record fields can now be renamed with the proc-macro name = "new_field_name" attribute (#2794)
Items can be excluded from the generated bindings using uniffi.toml.
Added mutable_records configuration option to allow specific records to remain mutable even when generate_immutable_records is enabled (Kotlin and Swift).
Kotlin objects now have an uniffiIsDestroyed property that returns true if the Rust reference no longer exists (#2825)
Updated askama version to 0.15.6
Custom Types can have docstrings in some languages (#2853)
Ruby: Expose standard Rust traits for generated ruby code (#2883)
Ruby: Add support for sync foreign traits (#2916)
Ruby: Add async support (#2923)
Added zero-copy transfer of &[u8] / [ByRef] bytes arguments from foreign code to Rust. Kotlin (java.nio.ByteBuffer, must be direct), Swift (Data), and Python (bytes-like, buffer protocol) pass byte buffers as pointer + length (ForeignBytes) rather than copying through RustBuffer. Not yet supported on Ruby, and not yet supported in async functions on any language (#2878).
#[uniffi::export(async_runtime = "tokio")] can now be applied to trait exports, wrapping each method's FFI scaffolding future in async_compat::Compat the same way it does for inherent impls and free functions (#2899).
Added support for using HashSet with proc-macros
Allow literal number suffix with derive(uniffi::Enum)(#2926)
Kotlin: Fixed JNA direct-mapped u8/u16 return values by widening the internal return carrier to Int, which avoids signedness mismatches during checksu
u8/u16 return values by widening the internal return carrier to Int, which avoids signedness mismatches during checksum validation and other direct-return paths on Android ARM32. (#2897)FfiConverterString silently stripping a leading U+FEFF byte order mark from Rust strings.Changelog update for 0.31.1
Changelog update for 0.31.1
chore: Release uniffi version 0.31.0
chore: Release uniffi version 0.31.0
uniffi-bindgen command no longer accepts the --lib-file argument. Instead, pass the
library directly without a UDL file.[Swift|Kotlin|Python|Ruby]BindingGenerator types. Use uniffi::generate instead
to generate these bindings.BindgenCrateConfigSupplier. Use the new BindgenPaths type instead.uniffi::generate function. This implements the uniffi-bindgen generate command and
allows it to be run programmatically.--library argument of uniffi-bindgen is deprecated and no longer has an effect.
uniffi-bindgen will now auto-detect when the source path is a library rather than a UDL file.BindgenPaths type, which is the new way to find UDL and TOML data.name = "NewVariantName" attribute (#2783)uniffi-bindgen that doesn't depend on cargo-metadata (#2746)toString(),
equals(), hashCode(), and compareTo() implementations. Flat enums only support exporting Display. (#2700).Eq, Cmp etc would generate invalid code if the Rust name had unusual captialization (#2707).#[doc(...)] attributes in exported blocks (#2777)__eq__ (#2741)0.30.x and the Rust code is built with
0.31.x, or vice-versa.module_path field now stores full module paths rather than crate names only.
External bindings authors will probably need to make some minor changes to work with this.
See https://github.com/mozilla/uniffi-rs/pull/2695/ for examples.chore: Release uniffi version 0.30.0
chore: Release uniffi version 0.30.0
#[uniffi::trait_interface] attribute.class PyTraitName(RustTraitName):name = "NewName" attribute (like already supported for methods and constructors) (#2661)Display, Hash, Eq etc) (#2555)Ord trait, allowing objects to be ordered by Rust (#2583).#[uniffi(default)] literals are now optional - eg, #[uniffi(default)] and #[uniffi(default = 0)] are equivalent.
Similarly for args; #[uniffi::export(default(arg_name))].
When no literal is specifed, named types (objects, records, etc) can be used as long as they have suitable default values.
(#2543).
Custom types too (#2603)enum and object types can be used as error type (#2658)uniffi_bindgen::backend has been removed.#[uniffi(default)] changes how defaults are represented.FfiType::RustArcPtr has been removed and the FFI type for objects/interfaces is now a u64.
Bindings authors will need to update their code to reflect this:
u64 valuesu64 handle rather than a raw pointeru64 handle rather than a raw pointerEnums and Records can have methods, so the Method now carries self_type instead of the object name.
In the templates, for Callable.takes_self() is replaced with Callable.self_type().free, clone, followed by a field for each interface method.
Note That free is now at the start of the vtable rather than the end.Nothing published for this version
Fixed a bug where objects with alignment >= 32 could be freed to early
chore: Release uniffi version 0.29.3
chore: Release uniffi version 0.29.3
Allow uniffi_reexport_scaffolding! macro to work in Rust 2024
Allow uniffi_reexport_scaffolding! macro to work in Rust 2024 (#2476)
Python: fix issues with unusual name capitalization, (#2464)
Swift bindings can now generate automatic conformance to the CaseIterable protocol for simple enums and errors using generate_case_iterable_conformance = true in the configuration.
Swift bindings can now generate automatic conformance to the Codable protocol for records, enums and errors using generate_codable_conformance = true in the configuration. Be aware that serialization in Swift may lead to different and incompatible results compared to serialization in Rust.
Some async-related names have changed. Bindings authors may need to update their code to reflect the new names. This is a name-change only -- the FFI and semantics are still the same.
UniffiForeignFutureFree is now UniffiForeignFutureDroppedCallbackUniffiForeignFuture is UniffiForeignFutureDroppedCallbackStruct.RustFuturePoll::MaybeReady is now RustFuturePoll::Wake.Bindings support lift and lower for CustomTypes in uniffi.toml to match the docs
Bindings support lift and lower for CustomTypes in uniffi.toml to match the docs (#2438)
Python: fix using Vecs and other composite types in tuple enums (#2445)
Kotlin: fix interfaces in sequences and records being not disposed (#2479)
Rust 2024 edition is supported, msrv is 1.82.0
The uniffi-bindgen CLI support no longer brings in the clap/color feature, reducing dependencies (#2435)
Protocols generated for Swift now conform to the Sendable protocol. This means that UniFFI traits will too, but
it also means foreign implemented traits also must when Swift 6 conformance is enabled.
See the Swift section of the manual for more. (#2450)
You can now optionally specify extra frameworks like CoreBluetooth or CoreFoundation when generating a modulemap file for an xcframework.
We've made a number of breaking changes to fix long standing paper-cuts with UniFFI in multi-crate and procmacro+udl environments.
We've made a number of breaking changes to fix long standing paper-cuts with UniFFI in multi-crate and procmacro+udl environments.
See the detailed upgrade notes
While no changes are required to foreign code, we apologize for the inconvenience!
You are impacted if you use UniffiCustomTypeConverter to implement "Custom types",
or use UDL with types from more than one crate.
UniffiCustomTypeConverter has been removed, you must now use the
custom_type! macro instead.
The UDL syntax for external types has changed.
typedef extern MyEnum; has been replaced
with typedef enum MyEnum;. [Custom] and [External] are the only supported attributes for a typedef.
"remote" types (where UDL can re-export a type defined in
a non-UniFFI crate - eg, log::Level) must now use a
[Remote] attribute.
Various use_udl_*/use_remote_type etc macros have been removed.
uniffi::generate_component_scaffolding has been removed. It's almost certainly unused as it is
behind the wrong feature and undocumented. uniffi::generate_scaffolding does exacly the same thing and is
correctly behind the build feature.Kotlin and Swift follow Python: Proc-macros exporting an impl Trait for Struct block now has a class inheritance
hierarcy to reflect that.
#2297, #2363
External types work much better, particularly between UDL and proc-macros. (Kotlin external errors do not work - #2392).
Swift interfaces are marked as Sendable (#2318)
Removed the log dependency and logging statements about FFI calls. These were not really useful
to consumers and could have high overhead when lots of FFI calls are made. Instead, the
ffi-trace feature can be used to get tracing-style printouts about the FFI.
External errors work for Swift and Python. Kotlin does not work - see #2392.
Added disable_java_cleaner option for kotlin to allow for Java 8 compatible code
Proc-macros now allow Enums to hold objects (#1372)
Swift and Kotlin make it possible to opt-out of the runtime checksum integrity tests done as the library is initialized. Opting out will shoot yourself in the foot if you mixup your build pipeline in any way, but might speed the initialization. (Python apparently hasn't made these checks for some time, so no changes there!)
Switching jinja template engine from askama to rinja.
For wasm32 build targets, Futures do not have to be Send (#2418),
making them compatible with wasm-bindgen Futures.
Added the FfiType::MutReference variant.
Callable trait has changed, return_type and throws_type are now references.
Type::External has been removed. Binding authors must now check the type is local themselves before
deciding to treat it as a local or external type.
To get a feel for the impact on the bindings, see where we first did this for custom types, and where we then stopped using it entirely
Fixed bug in metadata extraction with large ELF files.
Added the uniffi-bindgen-swift binary. It works like uniffi-bindgen but with additional Swift-specific features. See https://mozilla.github.io/uniffi-
Added the uniffi-bindgen-swift binary. It works like uniffi-bindgen but with additional
Swift-specific features. See
https://mozilla.github.io/uniffi-rs/latest/swift/uniffi-bindgen-swift.html for details.
Removed the old and outdated diplomat comparison doc
Proc-macros recognise when you are exporting an impl Trait for Struct block.
Python supports this by generating an inheritance hierarcy to reflect that.
#2204
uniffi.toml of crates without a lib type where ignored in 0.28.1Lift errors will not cause an abort when panic=abort is set.
panic=abort is set.cargo_metadata feature, which is on by default. In some cases, this can be disabled
for better compatibility with projects that don't use cargo.--metadata-no-deps is available to avoid processing
cargo_metadata for all dependencies.[Rust=] attribute and use a plain-old typedef.
See the manual page for this.This means if they will work if they happen to be keywords in the language. There's a very small risk of this being a breaking change if you used a ty…
Objects error types can now be as Result<> error type without wrapping them in Arc<>.
Swift errors now provide localizedDescription (#2116)
Procmacros support tuple-errors (ie, enums used as errors can be tuple-enums.)
Fixed a problem with procmacro defined errors when the error was not used as an Err result
in the namespace (#2108)
Custom Type names are now treated as type names by all bindings. This means if they will work if they happen to be keywords in the language. There's a very small risk of this being a breaking change if you used a type name which did not already start with a capital letter, but this changes makes all type naming consistent. (#2073)
Macros uniffi::method and uniffi::constructor can now be used with
cfg_attr. (#2113)
Python: Fix custom types generating invalid code when there are forward references. (#2067)
The internal bindings generation has changed to make it friendlier for external language bindings. However, this a breaking change for these bindings. No consumers of any languages are impacted, only the maintainers of these language bindings. (#2066), (#2094)
The async runtime can be specified for constructors/methods, this will override the runtime specified at the impl block level.
Removed dependencies on unicode-linebreak and unicode-width. They were being pulled in a sub-dependencies for the textwrap crate, but weren't really u
unicode-linebreak and unicode-width. They were being pulled in a
sub-dependencies for the textwrap crate, but weren't really useful.Added the scaffolding-ffi-buffer-fns feature. When enabled, UniFFI will generate an alternate FFI layer that can simplify the foreign bindings code. I
scaffolding-ffi-buffer-fns feature. When enabled, UniFFI will generate an alternate
FFI layer that can simplify the foreign bindings code. It's currently being tested out for the
gecko-js external binding, but other external bindings may also find it useful.Fixed a regression in 0.27.0 which broke throwing constructors (#2061).
Fixed a regression in 0.27.0 which broke throwing constructors (#2061).
Fixed a RustBuffer memory leak (#2056)
Constructors can be async. Alternate constructors work in Python, Kotlin and Swift; only Swift supports primary constructors.
Constructors can be async. Alternate constructors work in Python, Kotlin and Swift; only Swift supports primary constructors.
Enums created with proc macros can now produce literals for variants in Kotlin and Swift. See the section on enum proc-macros for more information.
Objects can be errors - anywhere you can specify an enum error object you can specify
an Arc<Object> - see the manual.
Functions, methods and constructors exported by procmacros can be renamed for the forgeign bindings. See the procmaco manual section.
Trait interfaces can now have async functions, both Rust and foreign-implemented. See the futures manual section for details.
Procmacros support tuple-enums.
RustBuffer was changed to use u64 fields.
This eliminates panics when the capacity of the vec exceeds i32::MAX.
This can happen with the current Vec implementation when String/Vec sizes approach i32::MAX but don't exceed it.
Proc-macro function/method arguments can now have defaults
Proc-macro record defaults now support empty vecs and Some values.
Swift: Records and Enums without object references can now be made Sendable Swift,
by opting in to new Configuration experimental_sendable_value_types in uniffi.toml.
FfiType::Handle variant. This is a general-purpose opaque handle type used for
passing objects cross the FFI. This type is always 64 bits and replaces the various older handle
types including:
FfiType::RustFutureHandle which was removed)FfiType::RustFutureContinuationData which was moved).RustBuffer.len and RustBuffer.capacity are now u64 rather than i32.The weedle2 version is now 5.0.0 rather than 4.0.1. 4.0.1 was yanked because it contained a breaking change.
5.0.0 rather than 4.0.1. 4.0.1 was yanked because it contained a breaking change.The rust_future_continuation_callback_set FFI function was removed. rust_future_poll now inputs the callback pointer. External bindings authors will n
rust_future_continuation_callback_set FFI function was removed. rust_future_poll now
inputs the callback pointer. External bindings authors will need to update their code.Display, Hash and Eq exposed to Kotlin and Swift #1817[WithForeign] attribute#[uniffi::export(with_foreign)] attributeArc<>.Switched to a patched version of oneshot so that consumers who use cargo vendor don't vendor loom and it's sub-dependencies like windows
oneshot so that consumers who use cargo vendor don't vendor
loom and it's sub-dependencies like windowsFixed regression in the name of error enums in Kotlin #1842
Fixed several bugs with async functions were defined in multiple crates that get built together.
Proc-macros can now expose standard Rust traits (eg, Display, Eq, etc)
Proc-macros can now expose standard Rust traits (eg, Display, Eq, etc)
Fixed issues when trying to combine UDL and procmacros in the same crate when the "namespace" is different from the crate name. This meant that the "ffi namespace" has changed to consistently be the crate name, rather than either the crate name or the namespace name depending on whether the item was declared via a procmacro or UDL. This should be invisible in most cases, but custom build environments might require some changes. Specifically:
uniffi::generate_scaffolding(udl_path) now uses the udl_path to locate the corresponding Cargo.toml, which
is parsed to determine the crate name (ie, the name under the [lib] entry). If your environment is such that
Cargo.toml can't be located or parsed, you should instead use uniffi::generate_scaffolding_for_crate(udl_path, crate_name).uniffi_bindgen from the command-line to generate bindings and when not using "library mode",
Cargo.toml will be located and parsed to determine the crate name. Specifying --crate-name on the command-line can
be used to avoid this and use the specified value.Crates can now use proc-macros without UDL files to export their interface. See the "Procedural Macros: Attributes and Derives" manual section for details.
Custom Types are now supported for proc-macros, including a very low-friction way of exposing types implementing the new-type idiom.
Proc-macros: Added support for ByRef arguments
Proc-macros: Implemented custom type conversion error handling (https://mozilla.github.io/uniffi-rs/udl/custom_types.html#error-handling-during-conversion)
Error types must now implement Error + Send + Sync + 'static.
Proc-macros: The handle_unknown_callback_error attribute is no longer needed for callback
interface errors
equals function should be used instead.From<uniffi::UnexpectedUniFFICallbackError is now optional for callback interface error types.
If the error type implements that, things will continue to work as before.
If not, then any unexpected callback error will result in a Rust panic.uniffi_macros: Force-include the Cargo.toml to read
Inline the metadata module in uniffi_meta to avoid a dependency of uniffi_core to avoid hitting an upstream bug during link time
uniffi_meta to avoid a dependency of uniffi_core to avoid hitting an upstream bug during link time (#1666)Python: remove unused import (and unbreak Python 3.6 compatibility)
There are many breaking changes for external bindings - we hope there will be fewer in later releases, but we are laying the groundwork for some nice…
ThreadSafe attribute.External types now require a valid crate name. Before the docs said it must be a crate name,
but any string could be used as long as it was consistent with the external type map in
uniffi.toml.External types must be available in the Rust crate root.ExternalBindingsConfig trait was replaced with BindingsConfig. External bindings implementations will need to make minor changes to implement the new trait instead.--config flag when running the scaffolding command. This flag has never an effect, because there was no scaffolding configuration options.generate --library [path-to-cdylib]. This mode simplifies bindings generation, especially when you have dependencies between multiple UniFFIed crates. See the tutorial for a description.include_scaffolding!() macro must now either be called from your crate root or you must have use the_mod_that_calls_include_scaffolding::* in your crate root. This was always the expectation, but wasn't required before. This will now start failing with errors that say crate::UniFfiTag does not exist.uniffi_types module is no longer needed when using proc-macros.interface by using a [Trait] attribute in the UDL.
See the documentation.bytes primitive type was added, it represents an array of bytes. It maps to ByteArray in Kotlin, bytes in Python, String with Encoding::BINARY in Ruby and Data in Swift. (#1543)str() representations of errors in Python to align with other exceptions in Python. Use repr() or the {!r} format to get the old representation back (#1556)Debug, Display, Eq and Hash can now be exposed over the FFI and bindings may implement special methods for them.
See the documentation.There are many breaking changes for external bindings - we hope there will be fewer in later releases, but we are laying the groundwork for some nice improvements. Significant patches to UniFFI's builtin bindings which you will need to port include:
The version numbers for each crate will no longer by kept in sync after this release. In particular uniffi will have breaking changes less often than…
Cargo.toml file to only depend on the uniffi crate. Follow the directions from the Prerequisites section of the manualuniffi-bindgen binary for your project. Follow the directions from the Foreign language bindings section of the manual.uniffi_bindgen: cargo uninstall uniffi_bindgen. (Not strictly necessary, but you won't be using it anymore).uniffi_bindgen no longer provides a standalone binary. Having a standalone binary resulted in version mismatches when the uniffi version specified in Cargo.toml didn't match the uniffi_bindgen version installed on the system. Read The foreign language bindings section of the manual for how to set up a uniffi-bindgen binary that's local to your workspace.uniffi_bindgen: Removed the run_main function. It's moved to uniffi::uniffi_bindgen_main and now unconditionally succeeds rather than return a Result<()>.uniffi crate and no longer need to depend on uniffi_bindgen, uniffi_build, etc.uniffi will have breaking changes less often than uniffi_bindgen and other crates. This means that UniFFI consumers that specify their versions like uniffi = "0.23" will not need to bump their uniffi version as often as before.Your coding agent can read these notes before it upgrades. Set up the MCP server →