-
Notifications
You must be signed in to change notification settings - Fork 211
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
Re-organize type-level attributes in NativeClass
derive macro
#848
Comments
Thank you for the detailed proposal! 🙂
Since we have Maybe in the future with GDExtensions, we could even consider something more general. Just brainstorming, e.g.
I like this idea. We could benefit of the rusty "default constructor idiom". I think one limitation is that the derive-macro for #[methods]
impl MyClass {
#[constructor]
fn new() -> Self { ... }
// or:
#[constructor(owner)]
fn new(owner: &Node) -> Self { ... }
} |
It's my opinion that we should instead keep NativeScript and GDExtension classes distinct on the name level, since their behavior differ in many ways, e.g. godotengine/godot#54999. An easy
Currently yes. I think it can be moved to That would have to be left for 0.11 anyway, though, since #350 isn't in the scope for the 0.10 milestone, so I think it would also be acceptable to move it into |
I see, makes sense. What about I'm pretty sure most godot-rust users can't tell the difference between the two terms, so differing here might add more confusion than benefit. Especially since there's also a rather unrelated
Okay, let's revisit this later then. There are quite a few pending improvements related to exporting, so some of them could be bundled for v0.11. |
I suppose |
847: Separate static name from `NativeClass` into new trait r=Bromeon a=chitoyuu This allows NativeScript types to be registered under names only determined at run time, enabling better ergonomics for libraries. Ref #601, #603 ## Unresolved questions This does not implement the `#[name = "MyCustomName"]` static renaming syntax as suggested in #601 (comment), because it's very uncommon (if at all possible) for a key-value pair to be the top-level meta in an attribute. It should also be noted that at this moment, the `NativeClass` macro already utilizes a large number of type-level attributes: - `inherit` - `user_data` - `register_with` - `no_constructor` ...so it might not be wise to add another into the mix, especially under such a non-specific identifier as `name`. We might want to consider bundling (some of) these into a single top-level attribute (like `variant` for the `From`/`ToVariant` macros) instead. See #848. Co-authored-by: Chitose Yuuzaki <[email protected]>
Moving to 0.11 milestone, to avoid blocking the 0.10 release, along with #601. |
999: Implement automatic `NativeClass` registration via inventory. Implement mix-ins. r=chitoyuu a=chitoyuu ## Implement automatic NativeClass registration via inventory This adds the optional `inventory` feature, which allows `NativeClass` types to be automatically registered on supported platforms (everything that OSS Godot currently supports except WASM). Run-time diagnostic functions are added to help debug missing registration problems that are highly likely to arise when porting `inventory`-enabled projects to WASM. An internal `cfg_ex` attribute macro is added to help manage cfg conditions. Close #350. Note that the standalone registration attribute syntax proposed by the original issue isn't implemented, for the limited usefulness -- there are much fewer cases where manual `NativeClass` impls are necessary thanks to all the improvements since the original issue. ## Implement mix-in `#[methods]` blocks Adds the `#[methods(mixin = "Name")]` syntax for declaring mix-in blocks. Mix-in blocks have a many-to-many relationship with `NativeClass` types. Both `impl Type` and `impl Trait for Type` blocks are accepted. The argument name is changed from `as` in the original proposal to `mixin`, because we might still want to keep universal `#[methods]` blocks in the future for ease of use with WASM. `#[methods(mixin)]` makes a lot more sense for a future auto-registered mixin block than `#[methods(as /* as what? */)]`. All mix-in blocks have to be manually registered for gdnative v0.11.x. Some difficulty was encountered when trying to make auto-mixins compatible with existing code. It might still be possible with some tricks like autoref-specialization, but that might be too much effort given that we likely want to re-design much of the hierarchy for 0.12. Close #984. ## Allow `#[register_with]` for `#[monomorphize]` Enables `#[monomorphize]` to take the same standalone `#[register_with]` attribute as `#[derive(NativeClass)]`. This is chosen for short term consistency, but will probably change in a later version w/ #848, which might not still get implemented for a fair bit of time. Co-authored-by: Chitose Yuuzaki <[email protected]>
999: Implement automatic `NativeClass` registration via inventory. Implement mix-ins. r=chitoyuu a=chitoyuu ## Implement automatic NativeClass registration via inventory This adds the optional `inventory` feature, which allows `NativeClass` types to be automatically registered on supported platforms (everything that OSS Godot currently supports except WASM). Run-time diagnostic functions are added to help debug missing registration problems that are highly likely to arise when porting `inventory`-enabled projects to WASM. An internal `cfg_ex` attribute macro is added to help manage cfg conditions. Close #350. Note that the standalone registration attribute syntax proposed by the original issue isn't implemented, for the limited usefulness -- there are much fewer cases where manual `NativeClass` impls are necessary thanks to all the improvements since the original issue. ## Implement mix-in `#[methods]` blocks Adds the `#[methods(mixin = "Name")]` syntax for declaring mix-in blocks. Mix-in blocks have a many-to-many relationship with `NativeClass` types. Both `impl Type` and `impl Trait for Type` blocks are accepted. The argument name is changed from `as` in the original proposal to `mixin`, because we might still want to keep universal `#[methods]` blocks in the future for ease of use with WASM. `#[methods(mixin)]` makes a lot more sense for a future auto-registered mixin block than `#[methods(as /* as what? */)]`. All mix-in blocks have to be manually registered for gdnative v0.11.x. Some difficulty was encountered when trying to make auto-mixins compatible with existing code. It might still be possible with some tricks like autoref-specialization, but that might be too much effort given that we likely want to re-design much of the hierarchy for 0.12. Close #984. ## Allow `#[register_with]` for `#[monomorphize]` Enables `#[monomorphize]` to take the same standalone `#[register_with]` attribute as `#[derive(NativeClass)]`. This is chosen for short term consistency, but will probably change in a later version w/ #848, which might not still get implemented for a fair bit of time. Co-authored-by: Chitose Yuuzaki <[email protected]>
999: Implement automatic `NativeClass` registration via inventory. Implement mix-ins. r=chitoyuu a=chitoyuu ## Implement automatic NativeClass registration via inventory This adds the optional `inventory` feature, which allows `NativeClass` types to be automatically registered on supported platforms (everything that OSS Godot currently supports except WASM). Run-time diagnostic functions are added to help debug missing registration problems that are highly likely to arise when porting `inventory`-enabled projects to WASM. An internal `cfg_ex` attribute macro is added to help manage cfg conditions. Close #350. Note that the standalone registration attribute syntax proposed by the original issue isn't implemented, for the limited usefulness -- there are much fewer cases where manual `NativeClass` impls are necessary thanks to all the improvements since the original issue. ## Implement mix-in `#[methods]` blocks Adds the `#[methods(mixin = "Name")]` syntax for declaring mix-in blocks. Mix-in blocks have a many-to-many relationship with `NativeClass` types. Both `impl Type` and `impl Trait for Type` blocks are accepted. The argument name is changed from `as` in the original proposal to `mixin`, because we might still want to keep universal `#[methods]` blocks in the future for ease of use with WASM. `#[methods(mixin)]` makes a lot more sense for a future auto-registered mixin block than `#[methods(as /* as what? */)]`. All mix-in blocks have to be manually registered for gdnative v0.11.x. Some difficulty was encountered when trying to make auto-mixins compatible with existing code. It might still be possible with some tricks like autoref-specialization, but that might be too much effort given that we likely want to re-design much of the hierarchy for 0.12. Close #984. ## Allow `#[register_with]` for `#[monomorphize]` Enables `#[monomorphize]` to take the same standalone `#[register_with]` attribute as `#[derive(NativeClass)]`. This is chosen for short term consistency, but will probably change in a later version w/ #848, which might not still get implemented for a fair bit of time. Co-authored-by: Chitose Yuuzaki <[email protected]>
The
NativeClass
macro currently utilizes a large number of type-level attributes, making it tricky to add further expansions to its functionality. The current attributes are:inherit
user_data
register_with
no_constructor
... while in the future, we might also like to add:
#[derive(NativeClass)]
types #603)Proposal
My proposal is as follows:
inherit
is to be left as a top-level attribute, because of its significance.#[nativescript]
, as key-value pairs when applicable:#[nativescript(user_data = "path::to::Type<Self>", register_with = "path::to::function", no_constructor)]
Under this new arrangement, generic bounds and static renames can easily be introduced as keys under the
#[nativescript]
attribute:#[nativescript(bound = "T: SomeBound", rename = "SomeNewName")]
. Prior art for this could be found in the ecosystem, for example, in Serde.Unresolved questions
It's a common complaint that the signature of the mandatory
new
is too verbose, theowner
argument being seldom used. However, it isn't obvious how this is best dealt with. Our problem here is the need to distinguish three different semantics at the syntax level:owner
argument.I can see two alternatives to the current situation:
Changing the default constructor to the nullary
Default::default
, requiring aconstructor
key for unary constructorsUnder this arrangement, the possible annotations are:
Default::default
is called to produce a new instance by default.#[nativescript(constructor = "Self::new")]
.Self::new
is called with theowner
argument to produce a new instance. This is consistent with the current behavior.#[nativescript(no_constructor)]
. The NativeScript type would have no default constructor.This makes it much less verbose to declare types with constructors that do not use the owner argument, and frees up the
new
identifier unless requested specifically by the user. The downside is that extra annotation is required to reproduce the current default.Replacing
no_constructor
with a nested key-value pair under theconstructor
metaUnder this arrangement, the possible annotations are:
#[nativescript(constructor(nullary = "Self::default"))]
.Self::default
is called with no arguments to produce a new instance.#[nativescript(constructor(unary = "Self::new"))]
.Self::new
is called with theowner
argument to produce a new instance.#[nativescript(constructor(none))]
. The NativeScript type would have no default constructor.This has the benefit of allowing custom functions for both the nullary case and the unary case, but is very verbose. It should be noted that
Default
can always be implemented for types with nullary constructors, even though it could be undesirable if the constructor in question is expensive, or if there are multiple such functions.The text was updated successfully, but these errors were encountered: