Crate compilation error when using mirrored third party Enum in StreamSink
SilverMira opened this issue · comments
Describe the bug
Encountered a rust compilation error when I had both a function to return a third-party Enum to Dart land and a function that writes said Enum to a StreamSink
.
cargo check errors
error[E0277]: the trait bound `allo_isolate::ffi::DartCObject: From<MyEnum>` is not satisfied
--> src\frb_generated.rs:100:47
|
100 | ... .stream_sink::<_, crate::api::simple::MyEnum>(),
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<MyEnum>` is not implemented for `allo_isolate::ffi::DartCObject`, which is required by `MyEnum: IntoDart`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `From<T>`:
<allo_isolate::ffi::DartCObject as From<DartOpaque>>
<allo_isolate::ffi::DartCObject as From<RustOpaqueBase<T, A>>>
= note: required for `MyEnum` to implement `Into<allo_isolate::ffi::DartCObject>`
= note: required for `MyEnum` to implement `IntoDart`
note: required by a bound in `flutter_rust_bridge::rust2dart::context::TaskRust2DartContext::<Rust2DartCodec>::stream_sink`
--> C:\Users\Mira\.cargo\registry\src\index.crates.io-6f17d22bba15001f\flutter_rust_bridge-2.0.0-dev.28\src\rust2dart\context.rs:33:12
|
30 | pub fn stream_sink<T, D>(&self) -> StreamSinkBase<T, Rust2DartCodec>
| ----------- required by a bound in this associated function
...
33 | D: IntoDart,
| ^^^^^^^^ required by this bound in `TaskRust2DartContext::<Rust2DartCodec>::stream_sink`
error[E0277]: the trait bound `MyEnum: IntoIntoDart<MyEnum>` is not satisfied
--> src\frb_generated.rs:100:44
|
100 | ... .stream_sink::<_, crate::api::simple::MyEnum>(),
| ----------- ^ the trait `IntoIntoDart<MyEnum>` is not implemented for `MyEnum`
| |
| required by a bound introduced by this call
|
= help: the trait `IntoIntoDart<mirror_MyEnum>` is implemented for `MyEnum`
= help: for that trait implementation, expected `mirror_MyEnum`, found `MyEnum`
note: required by a bound in `flutter_rust_bridge::rust2dart::context::TaskRust2DartContext::<Rust2DartCodec>::stream_sink`
--> C:\Users\Mira\.cargo\registry\src\index.crates.io-6f17d22bba15001f\flutter_rust_bridge-2.0.0-dev.28\src\rust2dart\context.rs:32:12
|
30 | pub fn stream_sink<T, D>(&self) -> StreamSinkBase<T, Rust2DartCodec>
| ----------- required by a bound in this associated function
31 | where
32 | T: IntoIntoDart<D>,
| ^^^^^^^^^^^^^^^ required by this bound in `TaskRust2DartContext::<Rust2DartCodec>::stream_sink`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rust_lib_repro_frb` (lib) due to 2 previous errors
Also, while preparing this repro, I noticed that apparently the mirrored 3rd party type must also implement Clone due to a derive(Clone) in frb_generated.rs
, is this intended?
#[derive(Clone)]
pub struct mirror_MyEnum(crate::api::simple::MyEnum);
Steps to reproduce
flutter_rust_bridge_codegen create repro_frb
cd repro_frb
cargo new --lib rust-3rdparty
- Modify and add Enum in
rust-3rdparty/src/lib.rs
#[derive(Clone)] pub enum MyEnum { Foo, Bar, Baz, }
- Modify
rust/Cargo.toml
to have dependency onrust-3rdparty
[dependencies] rust-3rdparty = { path = "../rust-3rdparty" }
- Modify
rust/src/api/simple.rs
pub use rust_3rdparty::MyEnum; use crate::frb_generated::StreamSink; #[flutter_rust_bridge::frb(mirror(MyEnum))] pub enum _MyEnum { Foo, Bar, Baz, } pub fn get_enum() -> MyEnum { MyEnum::Foo } pub fn stream_enum(_sink: StreamSink<MyEnum>) {}
flutter_rust_bridge_codegen generate
Logs
N/A
Expected behavior
Rust bridge can compile
Generated binding code
No response
OS
Windows
Version of flutter_rust_bridge_codegen
2.0.0-dev.28
Flutter info
No response
Version of clang++
No response
Additional context
No response
Hmm, do you mean it is OK if we do either be return value or be in stream sink, but error if we do both; Or can the minimal reproducible sample be further reduced to halves?
I noticed that apparently the mirrored 3rd party type must also implement Clone due to a derive(Clone) in frb_generated.rs, is this intended?
If your enum does not support clone (or have other special properties), maybe just make it opaque instead of mirroring it.
The error happens as long as there is a mirrored Enum used in a StreamSink, even if the mirrored Enum is never used as a return value. Cargo check shows that the compilation error is within the generated code when instantiating the actual StreamSink during the .stream_sink
call
StreamSink::new(
context
.rust2dart_context()
.stream_sink::<_, MyEnum>(),
)
If MyEnum
is not mirrored, then FRB generates it as opaque, which does compile, but makes it harder to use on the Dart land
While messing around with the generated code, it looks like the crate can compile if I manually changed the following.
StreamSink::new(
context
.rust2dart_context()
.stream_sink::<_, mirror_MyEnum>(), // codegen had MyEnum as the generic type originally
)
Additionally, not sure if I encountered the same issue but in another way, I'm getting the same compilation error if there is a StreamSink<Option<TestStruct>>
where TestStruct
is opaque.
#[flutter_rust_bridge::frb(opaque)]
pub struct TestStruct {}
pub fn stream_struct(_sink: StreamSink<TestStruct>) {}
pub fn stream_struct_option(_sink: StreamSink<Option<TestStruct>>) {}
I looked at the StreamSink instantiation for stream_struct
and stream_struct_option
and noticed there was a difference. The ordinary StreamSink<TestStruct>
which is compiling fine uses Local_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockTestStruct
as the generic type while the problematic StreamSink<Option<TestStruct>>
was just using Option<TestStruct>
as the generic type. Manually replacing the Option<TestStruct>
generic type within frb_generated.rs
with Option<Local_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockTestStruct>
in fact fixed the compilation issue and Dart land is even receiving the objects correctly.
frb_generated.rs
fn wire_stream_struct_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec,_,_>(flutter_rust_bridge::for_generated::TaskInfo{ debug_name: "stream_struct", port: Some(port_), mode: flutter_rust_bridge::for_generated::FfiCallMode::Stream }, move || {
let message = unsafe { flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_, rust_vec_len_, data_len_) };
let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message);
deserializer.end(); move |context| {
transform_result_sse((move || {
Result::<_,()>::Ok(crate::api::simple::stream_struct(StreamSink::new(context.rust2dart_context().stream_sink::<_,Local_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedrust_asyncRwLockTestStruct>())))
})())
} })
}
fn wire_stream_struct_option_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "stream_struct_option",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Stream,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
deserializer.end();
move |context| {
transform_result_sse((move || {
Result::<_, ()>::Ok(crate::api::simple::stream_struct_option(StreamSink::new(
context
.rust2dart_context()
.stream_sink::<_, Option<TestStruct>>(), // <---- Problematic?
)))
})())
}
},
)
}
it looks like the crate can compile if I manually changed the following
Briefly check it and it looks like it should be mirror_Something
. For example, from pure_dart example we can see some working code looks like:
Feel free to PR to fix it! Alternatively I will work on it in the next batch (hopefully within several days)
Manually replacing the Option generic type within frb_generated.rs with
Good observation! Then looks like it is missing generating this.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.