fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.09k stars 278 forks source link

Rust types that implement std::error::Error should implement Exception in Dart #2163

Open 0xNF opened 2 months ago

0xNF commented 2 months ago

After experimenting with some of the type translations, I notice that Err(e) in Rust are thrown as objects in Dart:


#[derive(Debug, Clone)]
pub enum CustomErrType {
    Error(String),
    IoError(std::io::ErrorKind, String),
    AuthenticationError,
    Serde(String, usize, usize),
}

impl std::error::Error for CustomErrType{}
impl fmt::Display for CustomErrType{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CustomErrType::Error(e) => write!(f, "Error: {}", e),
            CustomErrType::IoError(kind, err) => write!(f, "IO: {:?} {}", kind, err),
            CustomErrType::AuthenticationError => write!(f, "Authentication Error"),
            CustomErrType::Serde(e, l, c) => write!(f, "Serde Error @{}:{} {}", l, c, e),
        }
    }
}

#[flutter_rust_bridge::frb(sync)]
pub fn dostuff() -> Result<String, CustomErrType> {
    Err(CustomErrType::Serde("couldnt deserde".into(), 7, 12))
}

In Dart, this portion is generated like so:

// Rust type: RustOpaqueMoi<flutter_rust_bridge::for_generated::RustAutoOpaqueInner<CustomErrType>>
abstract class CustomErrType implements RustOpaqueInterface {}

Which means that try/catches act like this:

  void call_dostuff() {
    try {
      dostuff();
    } on Error catch (e) {
     // Not an error, won't be caught here
    } on Exception catch (e) {
     // Not an exception, won't be caught here either
    } catch (e) {
      // Will be caught here because it's a generic object
      print('found object type $e');
    }
  }

This conflicts with some of the officially supported dart lints, such as avoid_catches_without_on_clauses.

It'd be nice if the generated code for these types was instead

abstract class CustomErrType implements RustOpaqueInterface, Exception {}
fzyzcjy commented 2 months ago

Looks reasonable, and feel free to PR for this! (I am happy to provide hints)

Alternatively, I will work on it in the next batch.

0xNF commented 2 months ago

Looks like in some cases they are generated with implements FrbException which in turn is implements Exception, which is what should be happening. In my case it seems like it might be related to not handing in extra crate information to the rust_input: field of the flutter_rust_bridge.yaml file

Seems like pub use xyz items aren't being scanned fully, and will be given a generic implementation in the FRB output

fzyzcjy commented 2 months ago

Hmm, then could you please provide a minimal reproducible sample? Then it is easier to see what is going wrong exactly.