Skip to content

Commit

Permalink
Stop supporting typedef extern, [ExternalInterface=...] in UDL et…
Browse files Browse the repository at this point in the history
…c. (#2355)

This consolidates how external types are expressed in UDL. Instead of

```
[External="crate_name"]
typedef extern MyEnum

[ExternalInterface="crate_name"]
typedef extern MyInterface

```
you would use:
```
[External="crate_name"]
typedef enum MyEnum

[External="crate_name"]
typedef interface MyInterface
```

See the docs and upgrading notes in this commit for more.
  • Loading branch information
mhammond authored Dec 20, 2024
1 parent fa02b83 commit fbe146f
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 321 deletions.
50 changes: 49 additions & 1 deletion docs/manual/src/Upgrading.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# v0.28.x -> v0.29.x
# Upgrading v0.28.x -> v0.29.x

We've made a number of breaking changes in this release, particularly
to:

* Custom types (both UDL and proc-macros impacted)
* External Types (UDL impacted)

## Custom types

Expand Down Expand Up @@ -32,3 +38,45 @@ uniffi::custom_type!(NewCustomType, BridgeType, {

The `custom_type!` macro is more flexible than the old system - eg, the closures can be omitted in many cases where `From` and `Into` exist.
See the [Custom Types](./types/custom_types.md) for details.

## External Types

External types can no longer be described in UDL via `extern` - instead, you must specify the type.

For example:
```
[External="crate_name"]
typedef extern MyEnum
```
is no longer accepted - you must use, eg:
```
[External="crate_name"]
typedef enum MyEnum
```

Edge-cases broken include:

* Different variations of the `External` attribute (eg, `[ExternalInterface]`) are no longer supported; eg, `[ExternalInterface=".."] typedef extern ...` becomes `[External=".."] typedef interface ...` )
* The `[Rust=..]` attribute has been removed - you should just remove the attribute entirely.

See [Remote and External Types](./types/remote_ext_types.md) for more detail.

## Remote Types

The macros `ffi_converter_forward` and all `use_*` macros (eg, `use_udl_record!`, `use_udl_object!`, `use_udl_enum!` etc)
are now unnecessary so have been removed.

See [Remote and External Types](./types/remote_ext_types.md) for more detail.

## Shared Rust/UDL types

The `Rust` attribute has been removed - use the same typedef syntax described above for External Types.

```
[Rust="record"]
typedef extern One;
```
becomes
```
typedef record One;
```
2 changes: 2 additions & 0 deletions docs/manual/src/tutorial/foreign_language_bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ You can now run `uniffi-bindgen` from your project using `cargo run --features=u
### Multi-crate workspaces

In a multiple crates workspace, you can create a separate crate for running `uniffi-bindgen`:

- Name the crate `uniffi-bindgen`, add it to your workspace.
- Add this dependency to `Cargo.toml`: `uniffi = {version = "0.XX.0", features = ["cli"] }`
- As above, add the `uniffi-bindgen` binary target
Expand All @@ -57,6 +58,7 @@ Then look in the `out` directory.
When using library mode, if multiple crates get built into the library that use UniFFI, all will have bindings generated for them.

Library mode comes with some extra requirements:

- It must be run from within the cargo workspace of your project
- Each crate must use exactly 1 UDL file when compiling the Rust library. However, crates can have
multiple UDL files as long as they ensure only one is used for any particular build,
Expand Down
1 change: 1 addition & 0 deletions docs/manual/src/types/remote_ext_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Supported values for the typedef type:
* Records: `record`, `dictionary` or `struct`
* Objects: `object`, `impl` or `interface`
* Traits: `trait`, `callback` or `trait_with_foreign`
* Custom types: `custom`

# Special cases for remote types

Expand Down
36 changes: 36 additions & 0 deletions docs/manual/src/udl/external_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Using types defined outside a UDL.

Often you need to refer to types described outside of this UDL - they
may be defined in a proc-macro in this crate or defined in an external crate.

You declare such types using:
```idl
typedef [type] [TypeName];
```
`TypeName` is then able to be used as a normal type in this UDL (ie, be returned from functions, in records, etc)

`type` indicates the actual type of `TypeName` and can be any of the following values:
* "enum" for Enums.
* "record", "dictionary" or "struct" for Records.
* "object", "impl" or "interface" for objects.
* "trait", "callback" or "trait_with_foreign" for traits.
* "custom" for Custom Types.

for example, if this crate has:
```rust
#[derive(::uniffi::Object)]
struct MyObject { ... }
```
our UDL could use this type with:
```
typedef interface MyObject;
```

# External Crates

The `[External="crate_name"]` attribute can be used whenever the type is in another crate - whether in UDL or in a proc-macro.

```
[External = "other_crate"]
typedef interface OtherObject;
```
23 changes: 11 additions & 12 deletions fixtures/ext-types/lib/src/ext-types-lib.udl
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,34 @@ namespace imported_types_lib {
// A type defined in a .udl file in the `uniffi-one` crate (ie, in
// `../../uniffi-one/src/uniffi-one.udl`)
[External="uniffi_one"]
typedef extern UniffiOneType;
typedef dictionary UniffiOneType;

// An enum in the same crate
[External="uniffi_one"]
typedef extern UniffiOneEnum;
typedef enum UniffiOneEnum;

// An interface in the same crate
[ExternalInterface="uniffi_one"]
typedef extern UniffiOneInterface;
[External="uniffi_one"]
typedef interface UniffiOneInterface;

// An UDL defined trait
[ExternalTrait="uniffi_one"]
typedef extern UniffiOneUDLTrait;
[External="uniffi_one"]
typedef trait UniffiOneUDLTrait;

// A type defined via procmacros in an external crate
[ExternalExport="uniffi_one"]
typedef extern UniffiOneProcMacroType;
[External="uniffi_one"]
typedef dictionary UniffiOneProcMacroType;

// A Custom (ie, "wrapped") type defined externally in `../../custom-types/src/lib.rs`,
// but because it's in a UDL it's still "external" from our POV, so same as the `.udl` type above.
[External="ext_types_custom"]
typedef extern Guid;
typedef custom Guid;

// And re-use the `custom-types` example - this exposes `Url` and `Handle`
[External="custom_types"]
typedef extern Url;
typedef custom Url;

[External="custom_types"]
typedef extern Handle;
typedef custom Handle;

// Here are some different kinds of remote types - the types are described
// in this UDL, but the types themselves are defined in a different crate.
Expand Down
21 changes: 5 additions & 16 deletions fixtures/proc-macro-no-implicit-prelude/src/proc-macro.udl
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,11 @@ dictionary Zero {
string inner;
};

// NOTE: `[Rust=..]` is deprecated and this test hasn't migrated.
// This helps testing the attribute, so don't remove them unless you are removing support entirely!
[Rust="record"]
typedef extern One;

[Rust="enum"]
typedef extern MaybeBool;

[Rust="interface"]
typedef extern Object;

[Rust="trait"]
typedef extern Trait;

[Rust="trait_with_foreign"]
typedef extern TraitWithForeign;
typedef record One;
typedef enum MaybeBool;
typedef interface Object;
typedef trait Trait;
typedef trait_with_foreign TraitWithForeign;

// Then stuff defined here but referencing the imported types.
dictionary Externals {
Expand Down
3 changes: 3 additions & 0 deletions fixtures/uitests/src/typedef_extern.udl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace uitests {};

typedef extern Foo;
4 changes: 4 additions & 0 deletions fixtures/uitests/tests/ui/typedef_extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Unfortunately, path is relative to a temporary build directory :-/
uniffi_macros::generate_and_include_scaffolding!("../../../../fixtures/uitests/src/typedef_extern.udl");

fn main() { /* empty main required by `trybuild` */}
23 changes: 23 additions & 0 deletions fixtures/uitests/tests/ui/typedef_extern.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error: Failed to generate scaffolding from UDL file at ../../../../fixtures/uitests/src/typedef_extern.udl: `typedef extern` is no longer supported.
You must replace `extern` with the type of the object:
* "enum" for Enums.
* "record", "dictionary" or "struct" for Records.
* "object", "impl" or "interface" for objects.
* "trait", "callback" or "trait_with_foreign" for traits.
* "custom" for Custom Types.

For example:
[External="crate_name"]
typedef extern ExternalEnum;

Would be replaced with:
[External="crate_name"]
typedef enum ExternalEnum;

See https://mozilla.github.io/uniffi-rs/next/types/remote_ext_types.html for more.
--> tests/ui/typedef_extern.rs:2:1
|
2 | uniffi_macros::generate_and_include_scaffolding!("../../../../fixtures/uitests/src/typedef_extern.udl");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `uniffi_macros::generate_and_include_scaffolding` (in Nightly builds, run with -Z macro-backtrace for more info)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ nav:
- ./udl/functions.md
- ./udl/interfaces.md
- ./udl/records.md
- ./udl/external_types.md
- ./udl/docstrings.md
- 'Proc macros':
- ./proc_macro/index.md
Expand Down
Loading

0 comments on commit fbe146f

Please sign in to comment.