-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
assert()
should evaluate its arguments in release, and then no-op
#502
Comments
assert()
should evaluate it's arguments in release, and then nop
If we do this, we lose the performance advantages of being able to leave out error checking in release mode 🙁
# panic.gd
extends Object
static func panic(message: String) -> void:
# Will automatically print an error message in the console as well.
OS.alert(message)
# Non-zero exit code to indicate failure.
get_tree().quit(1) Usage: const Panic = preload("res://panic.gd")
func _ready() -> void:
Panic.panic("Error :(") |
IMO, providing a simple mechanism that would warn a user if there are function calls in |
What about the solution taken by the Nim language as well: Having two flavors of assert: The normal In my opinion there is no big benefit of making a failed release assertion a noop for performance reason, because a failed assertion probably indicates something is fairly broken. It could be a time safer when collecting bug reports from users, if the stdout would already contain information on failed |
@bluenote10 |
@Scony You're right. In this case it might be better to have it the other way around: |
assert()
should evaluate it's arguments in release, and then no-op
assert()
should evaluate it's arguments in release, and then no-opassert()
should evaluate its arguments in release, and then no-op
There is the |
I'd also prefer that an At the very least, yes, a warning would be very useful here (but again, it should warn only if the expression has side-effects). |
The issue is that we don't know in advance which methods have side effects and which ones don't. |
I know this'd be something for the long-term (because it'd probably be a lot of effort), but ideally we'd want the GDScript compiler's static analysis to figure this out for us, right? |
@vnen What's your opinion on this? |
This is not useful unless we add Regarding So IMO if this is really needed, we should:
Of course that if adding another one we can flip the meanings, but I would prefer to keep behavior consistent with previous versions. |
Personally I think adding a new keyword like mentioned above like |
How about Edit: I'm not a huge fan anymore because whether or not the method is evaluated is arbitrary. |
In my personal experience with Nim Currently for correct code you required to write if branch for each case, which isn't ergonomic, or define your own implementation in GDScript, something like: func do_assert(status: bool, msg: String = "") -> void:
if not status:
if msg.empty():
push_error("{source}:{function}:{line}".format(get_stack()[1]))
else:
push_error("{source}:{function}:{line} ".format(get_stack()[1]) + msg)
get_tree().quit(1) Which might potentially be quite costly in frequently ran code snippets, such as instancing of common scenes (enemies, for example), but more importantly it requires calling it on node that is already entered the scene (for Current |
In case it helps anyone, here are global methods I use in almost all my projects: ## Assert that the given error is OK.
func ok(err: int) -> void:
assert(err == OK, "An error occurred.")
## Assert that the given flag is true.
func yes(flag: bool) -> void:
assert(flag, "Flag is not true.") Since these are functions, the parameters are always evaluated even in release builds. Usage, (e.g. in AutoLoad G.ok(get_tree().change_scene_to(load("res://scene.tscn"))) G.yes(tween.start()) |
I'm taking a bit of a step to the side here, but my project really needs a way to simplify all my validation checks with RPC.
|
We've discussed it in the proposal review meeting, and would like to ping @vnen again to make the final judgement if we should move forward with this or reject it. |
I just hit this... had important code inside At the very least I would expect debug builds to behave the same and strip the call... so that the build can be, well, debugged. Having debug-only code block/line prefix explicitely could be nice to have instead of
Although naming would be quite unfortunate if this is stripped too in debug builds. Because when I debug, I usually use the editor xD A debug build is something else |
Describe the project you are working on:
Nuclear reactor simulation
Describe the problem or limitation you are having in your project:
Many functions return a status code that is often not checked as it should not fail in normal cases.
If it does fail, something bad has happened. For instance:
get_tree().change_scene("res://actors/fuel_rod/FuelRod.tscn")
I want to be able to assert that this is true, and have it crash debug builds so it fails loudly.
The first way that I'd think to do this is nice and compact:
assert(get_tree().change_scene("res://actors/fuel_rod/FuelRod.tscn") == OK)
However, the
assert()
is entirely compiled out in Release, so the change scene never executes in release builds, and everything breaks.Describe the feature / enhancement and how it helps to overcome the problem or limitation:
assert()
should still evaluate it's arguments in release, it's just thatassert()
behavior should be anop
Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
assert()
still evaluates it's arguments, butassert
then does nothing with the result.This is also more in-line with how assert works in other languages, so it'll help new-comers adapt to GDScript and not have some
WTF is happening
moments when things don't work in release.If this enhancement will not be used often, can it be worked around with a few lines of script?:
Yes, but it's much less compact. And so many Godot functions return codes that if left unchecked result in warnings. In order to check them all means lots of extra code bloat:
Is there a reason why this should be core and not an add-on in the asset library?:
It has to be core as it's a language level feature of GDScript
The text was updated successfully, but these errors were encountered: