On Feb 28, 2019, at 7:54 AM, Brian Goetz <brian.go...@oracle.com> wrote: > >> I think that trying to come that will encompass lazy instance field and lazy >> static field is a trap, because in the lazy instance case there is no >> constant pool to store the value. > > I tend to agree with Remi on this one. Condy may be a “mere” implementation > tactic, but it’s a darn good one, it has the semantics we want, and the use > case of lazy statics is far more important than lazy instance vars. (We we > would be happy if we only had lazy statics and not lazy instances.)
See previous message. I agree with what you are saying, with one reservation, that "far more important" is a time-dependent assertion; it can change. There was a time when inner classes were "far more important" than lambdas. Internally in the JDK we make *heavy use* of lazy non-statics, in the form of @Stable fields. This genie is going to come out of its bottle sooner or later. And, while agreeing with you (with that one reservation), I still say it's smart to exclude the T.default value for a lazy value. If we don't do that, we *block* ourselves from removing "static" as a constraint. Or we put off the irregularity, because we will have to say "lazy statics can have T.default but lazy non-statics cannot." In a nutshell: We should make *both* moves, exclude T.default *and* align with condy. The limitation against T.default can be spun, to many users, as a common sense error check, against uninitialized variables. To more curious users, it can be spun as a conscious reservation for efficient implementations. Scala went the other way with their lazies and they have struggled (in vain I think) with the consequences. You need transactional memory to do race-free initialization of 64-bit lazies, if you don't reserve a neutral value. Let's learn from their difficulty. We have enough foresight here to accept the irregularity now, when it will do the least damage. > Note too that the DynamicConstantValue story is a tradeoff to enable a binary > compatible migration from non-lazy to lazy; I think this is a sort of corner > case, as the vast majority of field accesses are within the same class. If > we didn’t care about binary-compatible migrations for public static final > fields, there’s a translation-based story that is way simpler — cross-class > field access desguars to invocations of a synthetic accessor. Desugaring a field to a method is a simple move, but it's not a free move. Iit has the usual problems of virtualizing something the user thinks is concrete. I think it's at least as disruptive than making a limitation on the value space of lazies. Also, this assertion is certainly time-dependent: > the vast majority of field accesses are within the same class That's true because the existing options for exporting fields as API points are so limited. Adding features like lazy finals or sealed (semi-public) fields will increase the applicable use cases. If and when it becomes safer to expose a field outside the capsule, more folks will build fields into their APIs. — John