Closed ghost closed 1 year ago
This would likely require some reworking of the NativeClass
and NativeClassMethods
traits, so should be considered before releasing 0.10.
This would be a useful feature indeed.
May I ask how this affects existing code (since it's marked as a breaking change)? It technically splits NativeClass
, but since most user code doesn't directly touch those types, this change wouldn't affect them?
From https://github.com/godot-rust/godot-rust/issues/842#issuecomment-1004504829:
I'm proposing that we separate the class name from the implementation types themselves, in the process also allowing users to change any class names at registration site. This is just a side-effect, but might be useful in "plugin"-style libraries, like
gdnative-async
, for avoiding name collisions with user types.Static class names can still be supported through a separate trait (
StaticallyNamed
?), which could be used as a bound for the registration methods.
Regarding class name, we might also want to consider https://github.com/godot-rust/godot-rust/issues/603. I think it would be nice, if for non-monomorphized types, the following would be possible:
struct
's name by default
(I don't know if/how this would work with the name being extracted)#[name = "MyCustomName"]
or so
(this can be done in a separate PR later)I have no problem with using String
as a type instead of &'static str
.
May I ask how this affects existing code (since it's marked as a breaking change)? It technically splits
NativeClass
, but since most user code doesn't directly touch those types, this change wouldn't affect them?
Exactly what you said. It affects manual NativeClass
implementations, that are currently required for generic or renamed types.
- Adopting the Rust
struct
's name by default (I don't know if/how this would work with the name being extracted)
We can support that by using the new trait as a generic bound of add_class
, so to be able to write something like:
impl InitHandle {
pub fn add_class<C: NativeClass + StaticallyNamed>(self) {
self.add_class_with_name(C::class_name()) // now a member of StaticallyNamed
}
pub fn add_class_with_name<C: NativeClass>(self, name: &str) {
// -- original impl of add_class --
}
}
And StaticallyNamed
would be implemented during #[derive(NativeClass)]
?
So the derive-macro would detect whether it's applied to a generic class (-> no name) or not (-> name)? Or the trait is always implemented but not always used?
Sorry for the many questions, maybe it's best if I just look at your implementation π
So the derive-macro would detect whether it's applied to a generic class (-> no name) or not (-> name)? Or the trait is always implemented but not always used?
Having NativeClass
implement it "magically" for non-generic types is the plan, but it would also be possible to make it explicit if you'd prefer that. In the explicit case attempting to derive StaticallyNamed
for a generic type would be a compile-time error.
I'll try to make a PR this weekend.
No, I think having less work left to the user (i.e. implicit) for non-generic types is better.
Thanks a lot, and no rush! π
While it's impossible to derive
NativeClass
in the general case due to monomorphization, it should be possible to export a list of monomorphizations specified by the user. This is most useful when a user needs to wrap a Rust data structure in a NativeScript, and know the list of types necessary.Suppose that we have a
GridMap
type that efficiently stores a value for each tile in a 3D space, for example. Currently, we can wrap it in aNativeClass
like this:We can, then, create and use
GridMap
s containingi32
s in GDScript. However, suppose that we now also want to be able to createGridMap
s that contain strings instead. BecauseNativeClass
andmethods
don't support generics yet, we have no option but to copy and pasteGridMapInt
, along with its 100 extra wrapper methods, which is obviously terrible, or use code generation, which is rather inconvenient. Both options will also limit how one can interact with those wrapper types from Rust, since they are not generic.Instead, with a syntax for explicitly exporting certain monomorphizations, we would be able to write something like:
...which could expand to:
Alternatives
Attributes on the original type instead of type aliases
Instead, we could also put the list of generic arguments above the type for which
NativeScript
is derived:There shouldn't be any implication on implementation difficulty or auto-registration, but I find this syntax much less convenient compared to the one with type aliases, due to how attribute syntax works. It also won't work as well with macros:
Opinions are welcome!