uniffi-rs icon indicating copy to clipboard operation
uniffi-rs copied to clipboard

How to use an Arc<str> in a custom type?

Open chris13524 opened this issue 1 month ago • 5 comments

[snip by mhammond to stick to the customtype part]

Trying to use a custom type I get a different error:

type ArcStr = std::sync::Arc<str>;
uniffi::custom_type!(ArcStr, String, {
    remote,
    try_lift: |val| Ok(val.into()),
    lower: |obj| obj.to_string(),
});
error[E0119]: conflicting implementations of trait `uniffi::TypeId<UniFfiTag>` for type `std::sync::Arc<str>`
 --> crates/yttrium/src/uniffi_compat/sign/arc_str.rs:2:1
  |
2 | / uniffi::custom_type!(ArcStr, String, {
3 | |     remote,
4 | |     try_lift: |val| Ok(val.into()),
5 | |     lower: |obj| obj.to_string(),
6 | | });
  | |__^
  |
  = note: conflicting implementation in crate `uniffi_core`:
          - impl<T, UT> uniffi::TypeId<UT> for std::sync::Arc<T>
            where std::sync::Arc<T>: uniffi::FfiConverter<UT>, T: ?Sized, std::sync::Arc<T>: ?Sized;
  = note: this error originates in the macro `$crate::derive_ffi_traits` which comes from the expansion of the macro `uniffi::custom_type` (in Nightly builds, run with -Z macro-backtrace for more info)

I tried to implement FfiConverterArc by-hand but there's a big learning curve here.

A workaround is to wrap the Arc<str> in a named type and use uniffi::custom_type!() on that. I also could shim the entire wrapping type e.g. JsonRpcRequestFfi which uses a String instead of an Arc<str>, but I'd love to eliminate this extra layer overall.

I'm using the latest UniFFI version 0.30.0.

chris13524 avatar Nov 12 '25 18:11 chris13524

sorry, we don't support that - https://mozilla.github.io/uniffi-rs/latest/types/records.html mentions no smart pointers etc. I don't see a path to the ffi here. I'll close this because it is documented, but happy to talk more about it!

mhammond avatar Nov 13 '25 02:11 mhammond

@mhammond I can understand why the Arc<str> itself isn't supported, but I would at least expect the custom_type!() to work? That keeps the String for actual FFI layer, while still allowing you to use whatever type you want in the struct.

type ArcStr = std::sync::Arc<str>;
uniffi::custom_type!(ArcStr, String, {
    remote,
    try_lift: |val| Ok(val.into()),
    lower: |obj| obj.to_string(),
});

chris13524 avatar Nov 13 '25 14:11 chris13524

Yeah, fair enough, I don't see an easy answer to that!

mhammond avatar Nov 14 '25 04:11 mhammond

@chris13524 Did you manage to use ArcStr in your bindings? Using uniffi::custom_type! with ArcStr should not work because it is defined in the standard crate. Using the newtype idiom works, i.e., struct ArcStr(std::sync::Arc<str>) though.

paxbun avatar Nov 29 '25 08:11 paxbun

@paxbun wrapping the Arc in a new type worked for me

chris13524 avatar Nov 29 '25 11:11 chris13524