Unverified Commit af9bd4ce authored by Mark Hammond's avatar Mark Hammond Committed by GitHub
Browse files

External custom types in UDL must use the [Custom] attribute (#2371)

Previously they were declared with the `External` attribute, but
this mean UniFFI could not know the underlying type, leading to
issues like #2025.

This PR does not however fix any such issues, it instead allows
UniFFI metadata to carry enough information to fix in the future.
This is primarily being done now to include this breaking change
in with all other breaking changes we are making in the next release.
parent 05778b15
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -11,18 +11,19 @@
We've made a number of breaking changes to fix long standing paper-cuts with UniFFI in a
multi-crate environment and to simplify your and our implementations.

While **no changes required to foreign code**, we apologize for the inconvenience!
[See the detailed upgrade notes](https://mozilla.github.io/uniffi-rs/next/Upgrading.html)

You are impacted if you use "Custom types", or use UDL with types from more than one crate.
We have [detailed upgrade notes](https://mozilla.github.io/uniffi-rs/next/Upgrading.html)
While **no changes are required to foreign code**, we apologize for the inconvenience!

- "Custom Types" have changed, all implementations will need to update their Rust code.
  The `UniffiCustomTypeConverter` trait is no longer used, use the
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](https://mozilla.github.io/uniffi-rs/next/types/custom_types.html) instead.

- The [UDL syntax for external types](https://mozilla.github.io/uniffi-rs/next/udl/external_types.html) has changed.
  `typedef extern MyEnum;` has been replaced
  with `typedef enum MyEnum;`. Attributes other than `[External = "crate_name"]` have been removed.
  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
+21 −8
Original line number Diff line number Diff line
@@ -3,13 +3,12 @@
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: UniffiCustomTypeConverter has been removed.
* External types: `extern` has been removed; you must describe the type.

## Custom types

Custom types are now implemented using a macro rather than implementing the `UniffiCustomTypeConverter` trait,
addressing some edge-cases with custom types wrapping types from other crates (eg, Url).
Custom types still implemented via the `UniffiCustomTypeConverter` trait must move to proc-macros.

Before:

@@ -29,7 +28,7 @@ impl UniffiCustomTypeConverter for NewCustomType {

After:

```
```rust
uniffi::custom_type!(NewCustomType, BridgeType, {
    try_lift: |val| { Ok(...) },
    lower: |obj| { ... },
@@ -46,12 +45,12 @@ External types can no longer be described in UDL via `extern` - instead, you mus
For example:
```
[External="crate_name"]
typedef extern MyEnum
typedef extern MyEnum;
```
is no longer accepted - you must use, eg:
```
[External="crate_name"]
typedef enum MyEnum
typedef enum MyEnum;
```

Edge-cases broken include:
@@ -61,6 +60,20 @@ Edge-cases broken include:

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

## External Custom Types

Previously you could describe an external Custom Type `Url` in UDL as:
```
[External="crate_name"]
typedef extern Url;
```

But now you must use:
```
[Custom="crate_name"]
typedef string Url; // replace `string` with any appropriate type.
```

## Remote Types

The macros `ffi_converter_forward` and all `use_*` macros (eg, `use_udl_record!`, `use_udl_object!`, `use_udl_enum!` etc)
@@ -76,7 +89,7 @@ The `Rust` attribute has been removed - use the same typedef syntax described ab
[Rust="record"]
typedef extern One;
```
becomes
becomes a `typedef` with no attributes
```
typedef record One;
```
+6 −10
Original line number Diff line number Diff line
@@ -87,22 +87,18 @@ followed by the custom type.
typedef i64 Handle;
```

**note**: you must still call the `custom_type!` or `custom_newtype!` macros in your Rust code, as described above.


#### Using custom types from other crates

To use custom types from other crates from UDL, use a typedef wrapped with the `[External]` attribute.

For example, if another crate wanted to use the examples here:
You can specify the crate name if the custom type implementation is external.

```idl
[External="crate_defining_handle_name"]
[Custom="crate_defining_handle_name"]
typedef i64 Handle;

[External="crate_defining_log_record_name"]
[Custom="crate_defining_log_record_name"]
typedef dictionary LogRecord;
```

**note**: you must still call the `custom_type!` or `custom_newtype!` macros in your Rust code, as described above.

## User-defined types

All examples so far in this section convert the custom type to a builtin type.
+6 −6
Original line number Diff line number Diff line
@@ -44,15 +44,15 @@ typedef trait UniffiOneUDLTrait;
typedef dictionary UniffiOneProcMacroType;

// A Custom (ie, "wrapped") type defined externally in `../../custom-types/src/lib.rs`,
[External="ext_types_custom"]
typedef custom Guid;
[Custom="ext_types_custom"]
typedef string Guid;

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

[External="custom_types"]
typedef custom Handle;
[Custom="custom_types"]
typedef i64 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.
+8 −1
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@ error: Failed to generate scaffolding from UDL file at ../../../../fixtures/uite
       * "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"]
@@ -15,6 +14,14 @@ error: Failed to generate scaffolding from UDL file at ../../../../fixtures/uite
       typedef enum ExternalEnum;

       See https://mozilla.github.io/uniffi-rs/next/types/remote_ext_types.html for more.

       External Custom Types must be declared in the same way, but with
       [Custom="crate_name"] instead of [Extern="crate_name"]

       [Custom="crate_name"]
       typedef string Url;

       See https://mozilla.github.io/uniffi-rs/next/types/custom_types.html for more.
 --> tests/ui/typedef_extern.rs:2:1
  |
2 | uniffi_macros::generate_and_include_scaffolding!("../../../../fixtures/uitests/src/typedef_extern.udl");
Loading