-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Advice: transfer the logic of PartialEq from Rust to Dart #2238
Comments
Yes, that looks quite reasonable and feel free to PR for this new feature! Currently I guess you may workaround by: |
After testing, seems that this
I would give it a try after I finish my current job if this feature is still not implemented then. |
Hmm, then maybe need to check what makes it ignored.
Looking forward to it! I guess it will not be too hard, especially the v2 codebase is clearer than v1. |
Currently, I'm using Riverpod which accepts a RustOpaque parameter which is obtained from public accessor of a non_opaque struct. However, since RustOpaque does not seem to have an underlying override of #[frb(non_opaque)]
pub struct MyStruct {
pub a: i32,
pub b: third_party::SomeType
}
/// types.rs
pub use third_party::SomeType;
#[frb(opaque)]
#[frb(mirror(SomeType))
struct _SomeType();
/// types.rs
pub use third_party::SomeType;
#[frb(opaque)]
#[frb(mirror(SomeType))
#[frb(dart_code="
@override
bool operator ==(Object other) {
return other is SomeType && equals(other as SomeType);
}
")]
struct _SomeType();
#[ext]
pub(crate) impl SomeType {
#[frb(sync)]
#[frb(positional)]
fn frb_override_equals(&self, other: &SomeType) -> bool {
self == other
}
} Directly using The above code gets us abstract class SomeType implements RustOpaqueInterface, SomeTypeExt {
@override
bool equals(SomeType other);
@override
bool operator ==(Object other) {
return other is SomeType && equals(other);
}
}
/// frb_generated.dart
@sealed
class SomeTypeImpl extends RustOpaque implements SomeType {
// ...
bool equals(SomeType other) => MyLib.instance.api
.crateApiSomeTypeFrbOverrideEquals(that: this, other: other);
// ...
}
Because the concrete type FRB returns is actually it looks like perhaps making the declaration as |
Brainstorm: Another way may be, put the custom dart_code in both SomeType and SomeTypeImpl. (since making SomeType a mixin may not be ideal since users may want to use it somewhere) |
Pretty sure We definitely need the definition to be on both the And we can do that by either duplicating dart_code or using the inheriting behavior of mixins. Personally I think that mixins will probably be better, since otherwise the concrete methods in |
Hmm, will changing And I am not sure that, since we expose SomeType to end users, they may feel confused "this is reasonable to be an abstract class, but why do you make it a mixin?". So I would like to hide the Copy-paste I guess is not a problem, since everything is auto-generated, which is unlike normal copy-pasting (which is a problem) ;) |
I'm fairly certain As for changing In any case, if all else fails, we can always reach for the almighty copy pasta. Though, I think dart_code probably should be phased out when dart class augmentation eventually drops, so users can just do whatever they want with the generated classes without having some obscure functionality be taken into account in the codegen. |
@SilverMira, you just mentioned using RiverPod for statement management, and this just remind me that a case I met when using GetX, for example: import 'package:get/get.dart';
class MyStruct {
String name;
int age;
double height;
MyStruct({required this.name, required this.age, required this.height});
}
class MyTestController extends GetxController {
final Rx<MyStruct> myStruct =
MyStruct(name: 'John Doe', age: 25, height: 175.0).obs;
@override
void onInit() {
super.onInit();
// Listen for changes in myStruct
ever(myStruct, (obj) {
});
}
...
} But here I just want to react(the body of Therefore, I finally give up the way with modifying the generated class, in my case, I put the listen logic code just in the import 'package:get/get.dart';
class MyStruct {
String name;
int age;
double height;
MyStruct({required this.name, required this.age, required this.height});
}
class MyTestController extends GetxController {
final Rx<MyStruct> myStruct =
MyStruct(name: 'John Doe', age: 25, height: 175.0).obs;
// Create a reactive variable to track the name field of myStruct
late final RxString _trackedName;
@override
void onInit() {
super.onInit();
// Initialize _trackedName and associate it with myStruct.name
_trackedName = myStruct.value.name.obs;
// Listen for changes in myStruct and update _trackedName
ever(myStruct, (obj) {
print('myStruct has been updated: ${obj}');
_trackedName.value = myStruct.value.name;
});
// Only listen for changes in _trackedName
ever(_trackedName, _onNameChanged);
}
void _onNameChanged(String newName) {
print('Name has been updated to: $newName');
}
} This does add some code, but at least semantically easy to maintain. Just for reference, I am not familiar with RiverPod , don't know if there is similar way to work around your case. |
Or course there are ways to workaround the issue, I can use riverpod to cache the opaque type (which will remain usable until eventually a method that moves the opaque type is called if any). But it does feel that the ergonomics can be improved here without all the manual plumbing work. Currently my workaround for this is to use custom encoders to convert my opaque type (actually a url::Url) to dart's core Uri type through intermediary string representation, which let me avoid this situation. Actually, I think this issue only applies for RustOpaques, because frb can generate operator== for non_opaques without issues. |
Currently(Frb v2.2.0), for a Rust type with macro like this
or manually written like this:
The logic to compare the equivalence of instance of the type can't be transferred to Dart. As we know that Dart would generally compare the memory addresses of instances but not content of the compared instance.
I hope this logic stated in Rust could be transferred to Dart, even not in default, at least it could be transferred by some flag setting or frb attribute macro tag.
The text was updated successfully, but these errors were encountered: