-
-
Notifications
You must be signed in to change notification settings - Fork 218
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
ScriptInstance::call Panics When Using Callable #1031
Comments
@TitanNano I was told to mention you on this as you worked on most of this API. |
@Pspritechologist thanks, I will try to take a look. |
@Pspritechologist after a brief look I think this part of the code is the issue: let callable: Callable = this.base_mut().get("set_name").to();
callable.call(&[name]); The Like this: {
let base = this.base_mut();
let callable: Callable = base.get("set_name").to();
callable.call(&[name]);
} Let me know if this works for you. |
@TitanNano Wow, I had no idea I'd need to keep it bound while performing unrelated operations, thank you a ton, the panics have gone away :) Feel free to close this seeing as it doesn't appear to be a bug. |
Do you think this is something we can/should mention in the docs? If so, what would be a good way? |
I think so yeah, it was unintuitive to me that keeping the SiMut bound would have side effects. Likely just a note in the type docs that it's not just important to use |
I'd probably have a lot of general notes on this API, I wonder if I'm the first person to use it to implement a full scripting runtime 🤔 |
Would you like to add a PR improving the docs? 🙂 |
@Bromeon @Pspritechologist I'm also considering if we should replace |
This is what I didn't like it because:
It's also not given that it would prevent the above issue; someone could still do let callable: Callable = this.with_base_mut(|b| b.get("set_name").to());
callable.call(&[name]); What we should probably do is
Regarding 2), the error is currently
Here, we could additionally mention
Furthermore, one idea I once had for |
I personally like the closure option, I agree it's a little messy but it serves to clarify the usage. Instead of appearing like a standard Rust borrow it looks more like 'entering a context', which seems to be accurate. Mlua does a similar thing with scopes which is actually what I'm using to expose the Struct in the first place. |
Not that we're already using guards for these APIs:
Rust locks/mutexes follow the same. This pattern has generally worked very well. Is this usage here really different enough to choose another approach? Genuine question, maybe it is.
and it's not obvious to which extent the guard/closure contributes to the confusion here. It's also noteworthy that for people who need the explicitness, it's easy to build an (extension) function taking a closure when there is a guard API, but it's impossible to build a guard around a closure API. |
i want to note that the same behavior also happens for also another note is that keeping guards around in rust basically always has side effects. it's not unique to this, for instance a |
I meant more that the side effects of a Mutex are contained within that Mutex and lifetimes related to the guards generated. You can't lock a Mutex and have that affect something with no binding to said Mutex (via the Mutex itself or a lifetime). I totally understand why it works this way (even though I don't know the low level of how it works) but it's not inherently intuitive that the guard needs to be kept past when it's valid to drop in order to interact with data that has no formal connection to the guard itself. |
But as I said, a closure API isn't bulletproof at preventing this, either. let callable: Callable = this.with_base_mut(|b| b.get("set_name").to());
callable.call(&[name]); Imo what we should really do is a combination of two things:
|
Obtaining and calling a Callable from
SiMut::base_mut
causes a panic if done during thecall
callback on aScriptInstance
.Below are the files used to replicate this issue.
The actual code to replicate is extremely small, but the files are large due to the amount of functions in the Traits. I've pushed any actually relevant functions to the top of their impl blocks.
Needlessly large code files
Yields the following panic:
Of note is that both of the above calls actually have the desired effect (presumably once the call fails due to panic Godot calls the base method as intended), the second one simply also yields a panic.
I assume this would not be the case for calls to class methods rather than base methods.
The text was updated successfully, but these errors were encountered: