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.
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 <fo...@univ-mlv.fr<mailto:fo...@univ-mlv.fr>> wrote: ________________________________ From: "Brian Goetz" <brian.go...@oracle.com<mailto:brian.go...@oracle.com>> To: "Kevin Bourrillion" <kev...@google.com<mailto:kev...@google.com>> Cc: "Dan Heidinga" <heidi...@redhat.com<mailto:heidi...@redhat.com>>, "daniel smith" <daniel.sm...@oracle.com<mailto:daniel.sm...@oracle.com>>, "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net<mailto:valhalla-spec-experts@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 <kev...@google.com<mailto:kev...@google.com>> wrote: On Wed, Nov 17, 2021 at 7:05 PM Dan Heidinga <heidi...@redhat.com<mailto:heidi...@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. |kev...@google.com<mailto:kev...@google.com>