-
-
Notifications
You must be signed in to change notification settings - Fork 23.5k
Core: Implement NotNull<T>
#105962
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
base: master
Are you sure you want to change the base?
Core: Implement NotNull<T>
#105962
Conversation
|
Hmm, not sure why it started failing all of the sudden; maybe the explicit use of |
45293d5 to
c3cd8b4
Compare
|
Cool to see more people tackling this, thanks a lot! 🙂 It seems the main difference of What's very elegant in @dsnopek's PR #86079 is that it's statically impossible to obtain the inner pointer when the value is null (type-state pattern). This provides the confidence that the precondition of a function is truly upheld. In this PR on the other hand, we have void Node::add_child(NotNull<Node *> p_child, bool p_force_readable_name, InternalMode p_internal) {
ERR_FAIL_COND_MSG(data.inside_tree && !Thread::is_main_thread(), "Adding children to a node inside the SceneTree is only allowed from the main thread. Use call_deferred(\"add_child\",node).");
ERR_THREAD_GUARD
ERR_FAIL_NULL(p_child);
... // actual function logic
}and it's possible to accidentally forget the
One thing that cannot be done inside a template like
Where do you see the main advantages of this approach vs. |
|
The most obvious benefit is when using I'll whip up an alternative PR to give that style a spin, see which we wanna roll with |
But they are recoverable as of today, no? Even if "print error and return" isn't necessarily the best course of action, it's in line with Godot's no-crash philosophy as you say 🙂
But in all other cases (likely the majority), the |
RequiredParam<T>andRequiredResult<T>to markObject *arguments and return values as required #86079Nullable<T>template #90767An alternative to David's
RequiredPtr, implemented as a generic wrapper instead. This is a variation of thegsl-liteimplementation ofnot_null, which diverges from that implementation in one main way: there's now a distinction between fatal & non-fatal nullability. That is:NotNull: Non-fatal failure if assigned null, but it will produce an error immediately so it's obvious where the mistake was made. Assignment is generally implicit, making transitioning to it for bound objects easy.NeverNull: Will fatally crash if assigned null, removing the need for external null handlers. Assignment is generally explicit, meaning binding changes need to be deliberate & null comparison is outright disabled.In both cases, this implementation will prevent being assigned pure null/empty values at compile-time. For bound pointers, they can likely be replaced 1-to-1;
Refwrappers will need more work to ensure it functions, which I'll work on finalizing throughout the week. The gsl-lite logic could likely be further reduced in scope, as our needs are more specific, but this gives a functional starting point