Value types, encapsulation, and uninitialized values
Remi Forax
forax at univ-mlv.fr
Thu Oct 11 18:05:28 UTC 2018
Being able use the default constructor to initialize the default value has a circular issue currently because a constructor is actually transformed to a default + with + with etc,
so to call the default constructor you need to have acces to the default value.
The circle can be broken if the default factory corresponding to the default constructor takes the initial default value as parameter, so the VM can pass a all zeroes value as parameter and record the resulting value returned.
I wonder if it's not better at least for the VM to require that the classfile of a value type should always have a default static factory.
In the language, we can have a special construct to explain that the all zeroes values should be used.
By example
class Complex {
Complex() default;
...
}
And there is another question, if we have a user defined default is what if there is an exception when the default static factory is called,
does it means that the bytecode default and the creation of an arry should throw an Error (like a linkage error) ?
Rémi
----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Envoyé: Jeudi 11 Octobre 2018 16:14:29
> Objet: Value types, encapsulation, and uninitialized values
> Our story is "Codes like a class, works like an int". A key part of
> this is that value types support the same lifecycle as objects, and the
> same ability to hide their internals.
>
> Except, the current story falls down here, because authors must content
> with the special all-zero default value, because, unlike classes, we
> cannot guarantee that instances are the result of a constructor. For
> some classes (e.g., Complex, Point, etc), this forced-on-you default is
> just fine, but for others (e.g., wrappers for native resources), this is
> not unlike the regrettable situation with serialization, where class
> implementations may confront instances that could not have resulted from
> a constructor.
>
> Classes guard against this through the magic of null; an instance method
> will never have to contend with a null receiver, because by the time we
> transfer control to the method, we'd already have gotten an NPE. Values
> do not have this protection. While there are many things for which we
> can say "users will learn", I do not think this is one of them; if a
> class has a constructor, it will be assumed that the receiver in a
> method invocation will be on an instance that has resulted from
> construction. I do not think we can expose the programming model as-is;
> it claims to be like classes, but in this aspect is more like structs.
>
> So, some values (but not all) will want some sort of protection against
> uninitialized values. One approach here would be to try to emulate
> null, by, say, injecting checks for the default value prior to
> dereferences. Another would be to take the route C# did, and allow
> users to specify a no-arg constructor, which would customize the default
> value. (Since both are opt-ins, we can educate users about the costs of
> selecting these tools, and users can get the benefits of flatness and
> density even if these have additional runtime costs.) The latter route
> is less rich, but probably workable. Both eliminate the (likely
> perennial) surprise over uninitialized values for zero-sensitive classes.
More information about the valhalla-spec-observers
mailing list