-
-
Notifications
You must be signed in to change notification settings - Fork 224
Refer to #[func]
names in type-safe ways (not just strings)
#620
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
Comments
Actually I wanted to write a macro which accepts parameter as |
i think this is related to #531 is there a reason you dont just do this? timer.connect(
"timeout".into(),
Callable::from_object_method(
&self.to_gd(),
"__internal_try_start_frame_inner".into()),
),
); or alternatively timer.connect(
"timeout".into(),
self.base().callable("__internal_try_start_frame_inner"),
); for type safety: ideally we'd avoid needing to use timer.connect(
self.timeout,
Self::__internal_try_start_frame_inner
) but im not sure how feasible that is |
This is basically to avoid using string literals whenever possible. Since we're generating bindings from rust code, we can benefit from a lot of compile-time information, and the name of symbol, is of course one of them. Putting any "linkage" behind a string literal throws a lot of advantages into darkness;
Even with the simple macro that I provided first, all above disadvantages can be avoided. And if with the proc-macro support, we can even determine that given rust symbol is bound to Godot script or not, in compile time.
|
Even if the function type can somehow be made working, the problem is that it has no name information associated. We could technically use a A macro is the way to go here (separator to be discussed): func_ref!(method); // self.callable("method") + checks
func_ref!(obj.method); // obj.callable("method") + checks @kang-sw Small request for the future, please don't edit your initial message in a way that makes the conversation flow hard to follow -- the "is there a reason you dont just do this?" question makes no sense once you replace your post with those very suggestions, and it's very unclear where the value of Are there other symbols that need to be referenced statically than |
Apologies for making confusion ... 😢, rolling back again would make another additional
Well I think most of the use case of "binding something FROM rust TO godot" would occur with Of course, as long as we can retrieve static symbols from anything we expose, I think that Anyways, yes, it seems I underestimated the complexity of making verification layer of
|
I'd say we follow YAGNI and not try to find the perfect bullet-proof system. After all, the title of this issue is
😁 Adding hundreds of LoC for a quality-of-life change may not be warranted; this code also needs to be maintained. Last, we need to keep in mind that generating code is not free: it takes time to generate, and takes again time to be parsed by the compiler on user side. So, the less symbols we have to generate, the better. This multiplies with every single user class, which may well be noticeable in larger projects. Your detailed analysis is very valuable, thanks for taking the time! 🙂 Maybe we can agree on some of the points for an initial implementation. If we can refer to user-defined
Do we even need the If we ever need to add other metadata, we can still do that later...
That code is not user-facing -- the generator knows the symbols. So indirection here would add more coupling without real benefits.
Conceptually, it seems wrong that let callable = func_ref!(
obj, // Gd instance
module::MyClass, // class type
foo, // #[func] name
); , then the macro can just do something like fn __type_check<T>(_obj: &Gd<T>) {}
__type_check::<$Class>(&$obj) which would not compile if On another note, I would probably not add a separate trait let callable = func_ref!(foo);
let obj: Gd<Other>;
let callable = func_ref!(obj, foo; module::MyClass); |
Thanks for detailed answer! Following are about initial intentions, and some corrections of myself:
Agree. I noticed that things are not going 'simple' anymore .. Just let's reinterpret the term 'simplicity' as for user side; that frees user from worrying about hidden typo 😁.
Initially that was to differentiate method names from other kind of symbols within __SYMBOLS struct, however, as long as we access to the symbols via macros; that knows what they're referring to(e.g. func_ref only need to find method name), I agree that there's no additional type bound required; Something like below would be sufficient without
Ah yes, this is a shard that I missed during cluttered brainstorming 😄. I agree that above macro usage already provides every information to verify type safety. Thanks for pointing out!
plus
For both, I just didn't have any concrete idea what the internal implementation / exposed interface should look like. Thanks for detailed answer again, it's actually very helpful for me either learning these kind of insight! |
StringName
from rust symbols?#[func]
names in type-safe ways (not just strings)
I haven't been using this library for long, but it seems common in Rust code to connect symbols from GodotClass to signals of other script classes. For this, I end up creating StringName FFI instances to specify the identifiers for these symbols. To make this process more convenient, I wrote a macro.
In particular, I often call registered methods declared within the #[godot_api] block of Rust's GodotClass. The following usage simplifies this process and helps prevent human errors such as typos.
I think it would be beneficial for this type of API to be added to the library, especially if the #[godot_api] generator could also create type tags for methods connected to scripts. This would prevent accidentally creating symbol names for non-script methods with the string_name macro.
Here's a simple example of a compile-time verification macro that is partially supported by proc-macro.
I believe this approach would allow us to handle Rust bindings more safely than simply referencing symbols through strings.
The text was updated successfully, but these errors were encountered: