Skip to content

Conversation

@Bromeon
Copy link
Member

@Bromeon Bromeon commented Oct 17, 2025

Addresses first part of #641.

Stores the type information as a tuple (type-list) for each virtual function.

Attempts to provide type information that's coming from the GDExtension API,
rather than from the user (through the macro). This should help in the future
with more detailed error messages, by using the API signatures as source of truth.
@Bromeon Bromeon added quality-of-life No new functionality, but improves ergonomics/internals c: register Register classes, functions and other symbols to GDScript labels Oct 17, 2025
@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1370

@Yarwin
Copy link
Contributor

Yarwin commented Oct 18, 2025

The outcome adds a new error which still points at #[godot_api]:

after
error[E0050]: method `process` has 1 parameter but the declaration in trait `godot::prelude::INode::process` has 2
  --> src/lib.rs:16:16
   |
16 |     fn process(&mut self) {}
   |                ^^^^^^^^^ expected 2 parameters, found 1
   |
   = note: `process` from trait: `fn(&mut Self, f64)`

error[E0308]: mismatched types
  --> src/lib.rs:14:1
   |
14 | #[godot_api]
   | ^^^^^^^^^^^^
   | |
   | expected `(f64,)`, found `()`
   | expected due to this
   |
   = note:  expected tuple `(f64,)`
           found unit type `()`
   = note: this error originates in the attribute macro `godot_api` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> src/lib.rs:14:1
    |
 14 | #[godot_api]
    | ^^^^^^^^^^^^ argument #2 of type `f64` is missing
    |
note: method defined here
   --> .../target/debug/build/godot-core-b05936b7ac85ab80/out/classes/node.rs:118:12
    |
118 |         fn process(&mut self, delta: f64,) {
    |            ^^^^^^^
    = note: this error originates in the attribute macro `godot_api` (in Nightly builds, run with -Z macro-backtrace for more info)
before
  --> src/lib.rs:16:16
   |
16 |     fn process(&mut self) {}
   |                ^^^^^^^^^ expected 2 parameters, found 1
   |
   = note: `process` from trait: `fn(&mut Self, f64)`

error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> src/lib.rs:14:1
    |
 14 | #[godot_api]
    | ^^^^^^^^^^^^ argument #2 of type `f64` is missing
    |
note: method defined here
   --> .../target/debug/build/godot-core-b05936b7ac85ab80/out/classes/node.rs:118:12
    |
118 |         fn process(&mut self, delta: f64,) {
    |            ^^^^^^^
    = note: this error originates in the attribute macro `godot_api` (in Nightly builds, run with -Z macro-backtrace for more info)

We can do better though – by adding span to params, like that:

    pub fn arg_decl(&self) -> TokenStream {
        let param_types = &self.param_idents;
        let mut sig = Group::new(Delimiter::Parenthesis, quote! { #(#param_types,)* });
        sig.set_span(Span::call_site().resolved_at(self.span));
        sig.to_token_stream()
    }

    pub fn params_type(&self) -> TokenStream {
        let param_types = &self.param_types;
        let mut sig = Group::new(Delimiter::Parenthesis, quote! { #(#param_types,)* });
        sig.set_span(Span::call_site().resolved_at(self.span));
        sig.to_token_stream()
    }

and using properly spanned Ident for params (instead of dummy tokens):

fn make_forwarding_closure(
...
) -> TokenStream {
...
    let method_name = &signature_info.method_name;
    let params = &signature_info.param_idents;
    let params_decl = &signature_info.arg_decl();
    let mut params_ident = ident("params");
    params_ident.set_span(signature_info.span);
...

...
            quote! {
                |instance_ptr, params| {
                    let #params_decl #sig_tuple_annotation = #params_ident;

                    let storage =
                        unsafe { ::godot::private::as_storage::<#class_name>(instance_ptr) };

                    #instance_decl
                    #before_method_call
                    #method_call
                }
            }

We can point new error to the exact user code:

better
error[E0050]: method `process` has 1 parameter but the declaration in trait `godot::prelude::INode::process` has 2
  --> src/lib.rs:16:16
   |
16 |     fn process(&mut self) {}
   |                ^^^^^^^^^ expected 2 parameters, found 1
   |
   = note: `process` from trait: `fn(&mut Self, f64)`

error[E0308]: mismatched types
  --> src/lib.rs:16:15
   |
14 | #[godot_api]
   | ------------ expected due to this
15 | impl INode for MyClass {
16 |     fn process(&mut self) {}
   |               ^^^^^^^^^^^ expected `(f64,)`, found `()`
   |
   = note:  expected tuple `(f64,)`
           found unit type `()`

(rest errors as they were)

I'll do it in separate PR (it will require some consideration to NOT drown in badly glued spans to everything 😅).

(honestly, we can just store groups directly – it is also a bit pointless in this case, since compiler only cares about #params_ident. I would like to have everything spanned well just-in-case tho, it is required for various rewrites – like Gd<Self> virtual methods)

@Bromeon
Copy link
Member Author

Bromeon commented Oct 19, 2025

Very nice, thanks! I actually wanted to make it a draft PR, but wasn't sure about the exact missing pieces. Very glad you have an idea of them, a follow-up PR definitely makes sense! 💪

I won't let this close #641 yet, but your PR could maybe do that.

@Bromeon Bromeon added this pull request to the merge queue Oct 19, 2025
Merged via the queue into master with commit a5d6428 Oct 19, 2025
18 checks passed
@Bromeon Bromeon deleted the qol/spans branch October 19, 2025 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: register Register classes, functions and other symbols to GDScript quality-of-life No new functionality, but improves ergonomics/internals

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants