[External] : Re: EG meeting, 2021-11-17
forax at univ-mlv.fr
forax at univ-mlv.fr
Fri Nov 19 14:23:46 UTC 2021
> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "Dan Heidinga" <heidinga at redhat.com>
> Cc: "Remi Forax" <forax at univ-mlv.fr>, "Kevin Bourrillion" <kevinb at google.com>,
> "daniel smith" <daniel.smith at oracle.com>, "valhalla-spec-experts"
> <valhalla-spec-experts at openjdk.java.net>
> Sent: Vendredi 19 Novembre 2021 14:32:38
> Subject: Re: [External] : Re: EG meeting, 2021-11-17
> The translation model I had in mind was more complicated, but my point was that
> the reason we disallow inheritance is because we’re trying to disallow layout
> polymorphism for concrete types, so that we know exactly how big a “C” is. And
> this is not inconsistent with abstract superclasses contributing fields.
> There’s definitely translational complexity, but its not insurmountable. I
> raised it because Kevin seemed to be going somewhere with extension, and I
> wanted to get a better sense of what that was. I have definitely wished for
> abstract records a few times before, and I could imagine Kevin has similar use
> cases in mind.
For records, it's easy to avoid abstract inheritance because all states are public,
so instead of
abstract A { int a; }
abstract B extends A { int b; }
record C() extends B { }
one can write
interface A { int a(); }
interface B extends A { int b(); }
record C(int a, int b) implements B { }
Rémi
>> The model requires fields in value types to be final so each of those
>> fields should be marked as `final` to ensure they show the right
>> properties to users via reflection. Additionally, that means that A &
>> B would need to have constructors to set those final fields to be
>> consistent with the rest of the language, but C will never run those
>> constructors.
>> Without a constructor, there's no place for A & B to set invariants on
>> their fields. If they can't define the contract for those fields,
>> then they shouldn't define the fields. This is similar to how
>> interfaces work: the interface can define a "int getX()" method that
>> implementers have to implement, but it can't define the "int x" field
>> directly.
>> If we relaxed the "must be final" field constraint, we'd need some
>> other rule to prevent A or B from defining a setter for their fields
>> as there is no single set of bytecode that can implement a setter for
>> both a value and an identity class:
>> void setA(int a) { putfield A.a }
>> vs
>> A setA(int a) { withfield A.a; areturn; }
>> Note in particular that the second *must* return a new A as values are
>> immutable.
>> The details around this would be hard for users to keep straight and
>> would be easy to violate when refactoring as the authors of A & B
>> would need to know that their subclasses include value types. And
>> this would be incredibly hard to keep straight across maintenance
>> boundaries.
>> --Dan
>>> On Nov 18, 2021, at 5:58 PM, Remi Forax < [ mailto:forax at univ-mlv.fr |
>>> forax at univ-mlv.fr ] > wrote:
>>> ________________________________
>>> From: "Brian Goetz" < [ mailto:brian.goetz at oracle.com | brian.goetz at oracle.com ]
>>> >
>>> To: "Kevin Bourrillion" < [ mailto:kevinb at google.com | kevinb at google.com ] >
>>> Cc: "Dan Heidinga" < [ mailto:heidinga at redhat.com | heidinga at redhat.com ] >,
>>> "daniel smith" < [ mailto:daniel.smith at oracle.com | daniel.smith at oracle.com ]
>>> >, "valhalla-spec-experts" < [ mailto:valhalla-spec-experts at openjdk.java.net |
>>> valhalla-spec-experts at openjdk.java.net ] >
>>> Sent: Jeudi 18 Novembre 2021 23:34:51
>>> Subject: Re: EG meeting, 2021-11-17
>>> I think it is reasonable to consider allowing bucket two classes to be abstract.
>>> They could be extended by other classes which would either be abstract or
>>> final. The intermediate types are polymorphic but the terminal type is
>>> monomorphic.
>>> A similar argument works for records.
>>> I suppose you are talking about empty (no field) abstract classes.
>>> We need that for j.l.Object, j.l.Number or j.l.Record.
>>> From a user POV, it's not very different from an interface with default methods.
>>> Rémi
>>> Sent from my iPad
>>> On Nov 18, 2021, at 5:27 PM, Kevin Bourrillion < [ mailto:kevinb at google.com |
>>> kevinb at google.com ] > wrote:
>>> On Wed, Nov 17, 2021 at 7:05 PM Dan Heidinga < [ mailto:heidinga at redhat.com |
>>> heidinga at redhat.com ] > wrote:
>>>> Let me turn the question around: What do we gain by allowing
>>>> subclassing of B2 classes?
>>> I'm not claiming it's much. I'm just coming into this from a different
>>> direction.
>>> In my experience most immutable (or stateless) classes have no real interest in
>>> exposing identity, but just get defaulted into it. Any dependency on the
>>> distinction between one instance and another that equals() it would be a
>>> probable bug.
>>> When B2 exists I see myself advocating that a developer's first instinct should
>>> be to make new classes in B2 except when they need something from B1 like
>>> mutability (and perhaps subclassability belongs in this list too!). As far as I
>>> can tell, this makes sense whether there are even any performance benefits at
>>> all, and the performance benefits just make it a lot more motivating to do what
>>> is already probably technically best anyway.
>>> Now, if subclassability legitimately belongs in that list of B1-forcing-factors,
>>> that'll be fine, I just hadn't fully thought it through and was implicitly
>>> treating it like an open question, which probably made my initial question in
>>> this subthread confusing.
>>> --
>>> Kevin Bourrillion | Java Librarian | Google, Inc. | [ mailto:kevinb at google.com |
>>> kevinb at google.com ]
More information about the valhalla-spec-observers
mailing list