News for hackers. Stuff that matters.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by inigyou on Friday June 19, 2026 @10:18AM (#48598907)
That's worse than null. Now every object has an invalid state. It works for Go because Go is trying to keep language complexity low. It has no good design principles behind it other than that. Also the zero value of a reference is null so you still haven't answered how a non-nullable reference field would work.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by tsimionescu on Friday June 19, 2026 @10:33AM (#48599087)
Sorry, I misinterpreted your question to be about non-nullable value classes, not non-nullable classes more generally. For reference variables, it seems that the a priori best approach would have been to generate a compiler error if the field was read before it was written; since this ship has long since sailed with final fields, it seems that the same approach would have to be taken - the "not null able" guarantee only applies after the class is fully initialized, and you can observe it as null during initialization. This is probably not a huge problem, given that initialization code always has to deal with a class breaking its invariants, since they are only established at the end of initialization.

Regarding the 0 value choice in Go, I don't agree that this is worse than null. It simply applies a design constraint that is not usually very hard to satisfy - that the 0 value of your type must have well defined semantics.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by inigyou on Saturday June 20, 2026 @09:33PM (#48614833)
The compiler doesn't solve the halting problem so it doesn't know whether a field is read before it's written.

If you allow a nonnull field to hold null at any point then it's trivial to leak that out and have nonnull variables holding null all over the program, which is obviously something to be avoided.

Maybe you can say that if you read a nonnull field when it's null, that throws an exception. That might have its own knock-on effects since nobody expects reading a field from a valid reference to throw an exception, but it might be the best way.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by tsimionescu on Monday June 22, 2026 @07:06AM (#48628579)
You don't need to solve the halting problem to prevent such access, not even close. You simply apply the same strategy as any other property you want to enforce - you prevent any use of the variable that can't be proven safe. You want to pass this in a call from the constructor to a function defined somewhere else where it might access a final/non-null able field that has not yet been initialized? Not allowed, only member functions that don't call other non-member functions allowed from the constructor.

Of course, as I said, this ship has long sailed for general Java classes. It would be far too big of a breaking change to add such a limitation today. However, we know for sure this could have been done in Java: this is exactly how record and now value classes work: any call that could expose un initialized fields is in fact disallowed.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by im3w1l on Saturday June 20, 2026 @01:46AM (#48606661)
I think you should require the code to be written in such a way that the compiler can verify the value is never read before initialization. There might be some subtleties in how to do that but I don't think it should be insurmountable.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by inigyou on Saturday June 20, 2026 @09:34PM (#48614837)
It's completely insurmountable. It basically means you can't call any functions during initialization. Including the one that creates the object you want to point your nonnull reference to.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by tsimionescu on Monday June 22, 2026 @09:47AM (#48630095)
...which is exactly how value classes and (after this JEP) records work. You are not allowed to call any instance methods before the call to `super()` (which happens implicitly at the end of the constructor for value classes and for records, unless you explicitly call it), and you are not allowed to call `super()` without first setting a value for all of your fields.