APIs like call
, callv
, etc should let the caller catch reflection-related errors programmatically
#7751
Replies: 3 comments
-
Returning objects has a performance cost (until GDScript gets structs), so I'd refrain from doing that for now. |
Beta Was this translation helpful? Give feedback.
-
I want to note that it is possible to convert what I posted in the answer into an Something similar came up recently by @tutemic, although it does all the checks in runtime: Easily add support for interfaces in GDScript!. What I'd consider better than that is static checking (consider for example that we might forget to check if the call reported an error). For once, this syntax addresses the name of the method: And for other, GDScript lacks interfaces/contracts, which I believe traits would address: Add a Trait system for GDScript. Of course, this do not address the case of code generation, or any other similar situation where the actual type/code is not known until runtime. I want to mention here an use case that was not mentioned in my answer: some people might want to expose GDScript from an application developed with Godot as an scripting language. @NathanLovato I wonder if you want to share your take on this, given https://gdquest.github.io/learn-gdscript/ I believe the Of course, setting an The next closer API is I do not believe we need a variant for the simple There is also the possibility of returning a Speaking of which, I'll link here Add union types to Typed GDScript and Add structs in GDScript. I'd wish Godot had Right now If we make them return an currently hypothetical I believe, if there will be a version of For possible errors with By the way, right now a deferred call will silently be ignored if it calls on a freed object. Not only that, there is code written assuming this behavior. In fact, reporting these errors was added and reverted: Revert "Let user know about dead instances in deferred calls". |
Beta Was this translation helpful? Give feedback.
-
There is also a problem that you cannot call an arbitrary method on
The |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
From: https://gamedev.stackexchange.com/questions/207215/how-can-i-check-if-call-callv-failed
Reflection APIs are meant to be used at runtime. To be more useful, they should allow the caller to not have to make too many assumptions about the validity of the intended call, and let them handle failure gracefully at runtime. Reflection is meant to be general and not limiting.
The issue
APIs like
call
,callv
,call_deferred
,call_deferred_thread_group
,call_thread_safe
, etc.As far as I know, they log errors (e.g. missing method, wrong number of arguments, wrong type) but there's no simple way to check that failure at runtime. The best you can do, apparently, is making a bunch of specific checks beforehand, that might depend on what you want to do, and hope you catch all possible such errors (see answer linked).
Leaving this up to the user is IMO error-prone. It's the reflection API's job to give feedback to the user about whether the operation succeeded or not. Not having this accessible programmatically is very limiting, in a bad way IMO. The whole point of reflection is to give the coder freedom about what they can do without forcing any assumptions.
The solutions
For APIs that return immediately the call result, like
call
andcallv
(I'm not sure if there are others too, to which this might apply as well), please add an overload that lets the caller gracefully check the result for reflection-related errors. You might (though that's debatable) not log these errors when using these overloads, they are simply returned somehow and it's up to the caller to do whatever they want with that info.For asynchronous APIs like
call_deferred
, return some sort of Task/Promise object or similar which the caller can use to:This would not only solve the undetectable error problem, but improve the asynchronous APIs too with a proper way to get the return value, making it much more useful.
Considerations
For APIs like
call_deferred
, which returns aVariant
described as being always null, it might be possible to just add this behavior without adding a new overload, because the return is meant to be unused (I'm not saying this is a good idea necessarily, I don't know; but one might argue that this isn't considered a "breaking change").For synchronous methods, a new overload would be needed to preserve compatibility. I recommend it returns some sort of tagged union to encourage the caller to take the possible error into consideration. For C#, an alternative would be an
out
parameter. Whatever the implementation is, it must be made in a way where it's possible to differentiate reflection-related errors from any normalError
return value from the method being called successfully.An alternative solution (for synchronous APIs only) would be something like a
can_call(...)
, but IMO having just that is not the best in terms of good practices and usability. It's best to be able to catch an error that actually already happened and handle it afterwards than assume it won't happen if you do things right.Beta Was this translation helpful? Give feedback.
All reactions