-
Notifications
You must be signed in to change notification settings - Fork 470
[ENHANCEMENT] Implement null safety #3267
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
Comments
I've been considering null safety when adding new features and modifying existing ones, and I'm all for it. For stuff like this I tend to prefer a bunch of specific changes rather than a giant sweeping change across the entire repo, as it's usually much easier to test. For instance, your recommended change to SoundFrontEnd would be great, along with anything else in that class. In general whenever I think about null safety, I first see if I can make it so that the value is never null, rather than nulling out values in destroy, can they instead be a final var that gets cleared. I've also trying to reduce nullable fields by using enums, where the field is only defined in the cases that use it. I think there's many more cases that can be improved using these methods. There are cases that really baffle me, though. For instance Null-safety is something enabled per-module, right? We could make a checklist of modules that are already null-safe or modules that can easily become null-safe and enable/finalize them |
Correct! You can enforce null safety on a class by annotating the class itself with https://try.haxe.org/#C74a0800 Note there are additional modes for this, they mainly make the code more strict to handle edge cases (such as a variable becoming null after a check, or being set by another thread), but the default "Loose" mode is more than enough to handle things. Note that if there are specific places you need to turn it off internally, you can annotate specific blocks (see the above example again). Null safety will definitely need to be enabled in stages, since enabling it on a large class would cascade out to other classes. We can also look into refactoring chunks of code in order to make it more null-safe (such as making a non-nullable property which fetches an internal nullable one). Null safety doesn't "cascade" out though, so as long as the changes you make to force variables to be non-null don't break existing apps, it should be fine to just add to classes one at a time. I wonder if there's an easy way to generate a module dependency tree... |
Of note, this PR merged into Haxe 5 is needed for the standard library itself to be actually null safe. There are several functions which can return null but whose return types aren't annotated with |
could start with the math classes, and static extension tools |
I wonder if I could generate an ordered list of dependencies... |
I generated an ordered list of dependencies for Funkin', you can grab that here if you like: FunkinCrew/Funkin#4303 (comment) It's not thorough for Flixel but it could help. |
I see: .haxelib\flixel\git\flixel\animation\import.hx
.haxelib\flixel\git\flixel\effects\import.hx
.haxelib\flixel\git\flixel\effects\particles\import.hx
.haxelib\flixel\git\flixel\graphics\FlxAsepriteUtil.hx
.haxelib\flixel\git\flixel\graphics\atlas\import.hx
.haxelib\flixel\git\flixel\graphics\frames\FlxFilterFrames.hx
.haxelib\flixel\git\flixel\graphics\frames\bmfont\import.hx
.haxelib\flixel\git\flixel\graphics\frames\import.hx
.haxelib\flixel\git\flixel\graphics\import.hx
.haxelib\flixel\git\flixel\graphics\tile\import.hx
.haxelib\flixel\git\flixel\group\import.hx
.haxelib\flixel\git\flixel\import.hx
.haxelib\flixel\git\flixel\input\FlxAccelerometer.hx
.haxelib\flixel\git\flixel\input\actions\import.hx
.haxelib\flixel\git\flixel\input\android\FlxAndroidKeyList.hx
.haxelib\flixel\git\flixel\input\android\FlxAndroidKeys.hx
.haxelib\flixel\git\flixel\input\android\import.hx
.haxelib\flixel\git\flixel\input\gamepad\id\import.hx
.haxelib\flixel\git\flixel\input\gamepad\import.hx
.haxelib\flixel\git\flixel\input\gamepad\lists\import.hx
.haxelib\flixel\git\flixel\input\gamepad\mappings\import.hx
.haxelib\flixel\git\flixel\input\import.hx
.haxelib\flixel\git\flixel\input\keyboard\import.hx
.haxelib\flixel\git\flixel\input\mouse\import.hx
.haxelib\flixel\git\flixel\input\touch\import.hx
.haxelib\flixel\git\flixel\math\import.hx
.haxelib\flixel\git\flixel\path\import.hx
.haxelib\flixel\git\flixel\sound\import.hx
.haxelib\flixel\git\flixel\system\FlxPreloader.hx
.haxelib\flixel\git\flixel\system\debug\completion\import.hx
.haxelib\flixel\git\flixel\system\debug\console\import.hx
.haxelib\flixel\git\flixel\system\debug\import.hx
.haxelib\flixel\git\flixel\system\debug\interaction\import.hx
.haxelib\flixel\git\flixel\system\debug\interaction\tools\import.hx
.haxelib\flixel\git\flixel\system\debug\log\import.hx
.haxelib\flixel\git\flixel\system\debug\stats\import.hx
.haxelib\flixel\git\flixel\system\debug\watch\import.hx
.haxelib\flixel\git\flixel\system\frontEnds\HTML5FrontEnd.hx
.haxelib\flixel\git\flixel\system\frontEnds\import.hx
.haxelib\flixel\git\flixel\system\import.hx
.haxelib\flixel\git\flixel\system\macros\import.hx
.haxelib\flixel\git\flixel\system\replay\FlxReplay.hx
.haxelib\flixel\git\flixel\system\replay\import.hx
.haxelib\flixel\git\flixel\system\scaleModes\FillScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\FixedScaleAdjustSizeScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\FixedScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\PixelPerfectScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\RelativeScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\StageSizeScaleMode.hx
.haxelib\flixel\git\flixel\system\scaleModes\import.hx
.haxelib\flixel\git\flixel\system\ui\FlxFocusLostScreen.hx
.haxelib\flixel\git\flixel\system\ui\import.hx
.haxelib\flixel\git\flixel\text\FlxBitmapFont.hx
.haxelib\flixel\git\flixel\text\import.hx
.haxelib\flixel\git\flixel\tile\import.hx
.haxelib\flixel\git\flixel\tweens\import.hx
.haxelib\flixel\git\flixel\tweens\misc\import.hx
.haxelib\flixel\git\flixel\tweens\motion\import.hx
.haxelib\flixel\git\flixel\ui\FlxBitmapTextButton.hx
.haxelib\flixel\git\flixel\ui\FlxSpriteButton.hx
.haxelib\flixel\git\flixel\ui\FlxVirtualPad.hx
.haxelib\flixel\git\flixel\ui\import.hx
.haxelib\flixel\git\flixel\util\helpers\import.hx
.haxelib\flixel\git\flixel\util\import.hx
.haxelib\flixel\git\flixel\util\typeLimit\import.hx
.haxelib\flixel\git\import.hx where are these import.hx files coming from? |
Probably auto-generated. This list was generated from the output of |
Uh oh!
There was an error while loading. Please reload this page.
Null safety is an optional feature of the Haxe compiler which enforces compile-time checking of nullable values.
By implementing null safety throughout HaxeFlixel, we can greatly reduce the frequency of crashes and other errors. This can be done using the
@:nullSafety
annotation at the top of each class, and can be done incrementally until every class in the library is compliant.This would not break existing code which has null safety enabled, but it would:
Null
-able (such asFlxG.sound.music
).As an example of the last case, I have started to enable null safety in Funkin', and have had to create blocks of code where null safety is not enabled in several places, simply because Flixel itself regularly neglects to use
Null<T>
for nullable values (again, trying to setFlxG.sound.music = null
makes the compiler complain until you specifically exclude that line).One major obstacle to implementing null safety is that null safety is not necessarily finalized (see this issue or any of these issues). Overall though, I would like to see it become a long-term goal of the engine, especially since it can be done in a non-breaking manner in most cases.
The text was updated successfully, but these errors were encountered: