Skip to content

Commit 76e040f

Browse files
authored
Support Type::Custom{ builtin: Enum|Object, .. } as throws type (#2658)
1 parent bcefb29 commit 76e040f

File tree

8 files changed

+65
-0
lines changed

8 files changed

+65
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
without a literal) meaning the default value for the type. Named types can also have a default.
2121
([#2543](https://github.com/mozilla/uniffi-rs/pull/2543))
2222
- Custom types support the default value, and specified as its "bridge" type ([#2603](https://github.com/mozilla/uniffi-rs/pull/2603))
23+
- Custom `enum` and `object` types can be used as error type ([#2658](https://github.com/mozilla/uniffi-rs/pull/2658))
2324
- Objects can implement external traits ([#2430](https://github.com/mozilla/uniffi-rs/issues/2430))
2425
- `#[uniffi(default)]` literals are now optional - eg, `#[uniffi(default)]` and `#[uniffi(default = 0)]` are equivalent.
2526
When no literal is specifed, named types (objects, records, etc) can be used as long as they have suitable default values.

fixtures/error-types/src/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,32 @@ fn oops_tuple(i: u16) -> Result<(), TupleError> {
241241
}
242242
}
243243

244+
#[derive(Debug)]
245+
struct CustomError(u16);
246+
247+
impl std::fmt::Display for CustomError {
248+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249+
write!(f, "{:?}", self)
250+
}
251+
}
252+
253+
uniffi::custom_type!(CustomError, TupleError, {
254+
try_lift: |val| {
255+
let TupleError::Value(v) = val else {
256+
return Err(anyhow::anyhow!("not a Value variant"));
257+
};
258+
Ok(CustomError(v))
259+
},
260+
lower: |val| {
261+
TupleError::Value(val.0)
262+
}
263+
});
264+
265+
#[uniffi::export]
266+
fn oops_custom(i: u16) -> Result<(), CustomError> {
267+
Err(CustomError(i))
268+
}
269+
244270
#[uniffi::export(default(t = None))]
245271
fn get_tuple(t: Option<TupleError>) -> TupleError {
246272
t.unwrap_or_else(|| TupleError::Oops("oops".to_string()))

fixtures/error-types/tests/bindings/test.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ try {
103103
assert(e.toString() == "uniffi.error_types.TupleException${'$'}Value: v1=1")
104104
}
105105

106+
try {
107+
oopsCustom(1u)
108+
throw RuntimeException("Should have failed")
109+
} catch (e: TupleException) {
110+
}
111+
106112
runBlocking {
107113
try {
108114
aoops()

fixtures/error-types/tests/bindings/test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,9 @@ def test_tuple_error(self):
130130
self.assertEqual(str(cm.exception), "1")
131131
self.assertEqual(repr(cm.exception), "TupleError.Value(1)")
132132

133+
# custom error type
134+
with self.assertRaises(TupleError) as cm:
135+
oops_custom(1)
136+
133137
if __name__=='__main__':
134138
unittest.main()

fixtures/error-types/tests/bindings/test.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ do {
9494
assert(error.localizedDescription == "error_types.TupleError.Value(1)")
9595
}
9696

97+
do {
98+
try oopsCustom(i: 1)
99+
fatalError("Should have thrown")
100+
} catch {
101+
}
102+
97103
do {
98104
try oopsNowrap()
99105
fatalError("Should have thrown")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
use super::*;
6+
7+
pub fn pass(cb: &mut Callable) -> Result<()> {
8+
// normalize the custom type to its builtin type
9+
if let Some(node) = cb.throws_type.ty.as_mut() {
10+
if let Type::Custom { builtin, .. } = &node.ty {
11+
node.ty = *builtin.clone();
12+
}
13+
}
14+
Ok(())
15+
}

uniffi_bindgen/src/bindings/python/pipeline/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use uniffi_pipeline::{Node, Pipeline};
99
mod callback_interfaces;
1010
mod config;
1111
mod default;
12+
mod error;
1213
mod external_types;
1314
mod ffi_types;
1415
mod interfaces;
@@ -33,4 +34,5 @@ pub fn pipeline() -> Pipeline<initial::Root, Root> {
3334
.pass(types::pass)
3435
.pass(default::pass)
3536
.pass(ffi_types::pass)
37+
.pass(error::pass)
3638
}

uniffi_bindgen/src/interface/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,6 +1289,11 @@ fn throws_name(throws: &Option<Type>) -> Option<&str> {
12891289
match throws {
12901290
None => None,
12911291
Some(Type::Enum { name, .. }) | Some(Type::Object { name, .. }) => Some(name),
1292+
Some(Type::Custom { name, builtin, .. })
1293+
if matches!(&**builtin, Type::Enum { .. } | Type::Object { .. }) =>
1294+
{
1295+
Some(name)
1296+
}
12921297
_ => panic!("unknown throw type: {throws:?}"),
12931298
}
12941299
}

0 commit comments

Comments
 (0)