On Mar 10, 2018, at 1:01 PM, John Rose <[email protected]> wrote: > (I'm going to send a separate note about this.)
We discussed one future option to make the JVM specially aware of <make> the way it is aware of <init>, and then restrict the new/dup/<init> dance to *only* occur inside of <make> in the same nest. If this is the only reason to coin a new magic name <make>, it might not be enough motivation. But there might be other reasons. Another reason for a magic name is to unambiguously link the source construct DoubleComplex(a,b) to a factory method. The JVM does *not* replicate the class base-name as the factory name, and I'd like to avoid that in the future too; I think it's just an artifact of Java's C++ heritage, and nothing to do with VM-level requirements. Hence <init> is the VM-level name where the type name occurs in the source code. So for factories we also need a canonical name for a value class's "principal factory". It could be $make or <make> or some other bikeshed color. I slightly prefer <make> because I think we *will* want to hook some structural constraints on it, and that's easier to swallow of the name is *really* magic, rather than "look he's got a dollar sign on him!". Another way is to allow the translation strategy and/or user to choose the factory name, and for the JVM to define an ACC_FACTORY bit to do the jobs that <make> would do. We'd still want, IMO, to fold DoubleComplex down to something like $make, but with the ACC_FACTORY bit. Either ACC_FACTORY or <make> scales out to other uses besides value type factories. It allows named factories on any kind of type. If we do a translation rule, for values, where DoubleComplex(a,b) is a call to DoubleComplex.$make(a,b), we can also take a later option to have List(a,b) be a call to List.of(a,b), where the ACC_FACTORY bit on List.of gates the decision. Or we would add List.<make> which calls List.of, for the same effect. (I happen to find List(a,b) attractive, though surely opinions will vary widely. Doubtless some people find "new" reassuring, and it was very reassuring in the long ago days when folks didn't trust GC technology and wanted to keep a sharp eye on allocation sites. But the days are long gone of "new" being part of a crisp, simple performance model.) A decision to use $make/ACC_FACTORY instead of <make> allows named factories too: DoubleComplex.imag(x), etc. That seems to be a vote in favor of $make not <make>, or perhaps an argument to have both, one for structural constraints and one for naming of principal factories. We are discovering as part of the Amber project that constructors often occur paired with deconstructors. Principal constructors (or for values factories) are paired with principal deconstructors, which unpack an object in exactly the reverse order in which it was packed by its principal constructor. Name factories want to be paired, also, with named deconstructors. (Anti-factories? Co-factories? Salvage yards?) This leads to the possibility that, if a factory has structural constraints, then maybe a deconstructor has coordinated constraints. I'm just speculating here; I don't see a concrete example yet, except perhaps the treatment of final fields. (See below.) This leads me to the following tentative results, which seem "OK for today" but could change: - The new/dup/<init> dance could be constrained to nests, but there's no tighter constraint (like factories only) that seems useful. - No need seen, yet, for ACC_FACTORY. - Java translation strategies need a tactic for naming principal factories. And for naming deconstructors paired with constructors or factories. There isn't a firm need for the JVM to help with this but doing so would be unsurprising, given <init>. There is a similar line of consideration for handling the initialization *and reinitialization* of final fields, in reconstructors *and reconstructors*. Marking reconstructors (like withers) *might* require an ACC_* bit to relieve structural constraints that relate to final fields, and currently allow enhanced access inside of <init> but only there. Named [re]constructors might need similar access, leading to either an ACC_CONSTRUCTOR bit or else a relaxation of some <init> capabilities to the whole nest. So another "OK for today" conclusion might be: - Consider marking some methods as ACC_RECONSTRUCTOR and allowing final updates in those methods. Use this marker on reconstructors, in place of some extension of the <init> code shapes, which are already overburdened. - Or, consider relaxing rules for update of final fields to the whole nest. (I know we just fixed a security bug in that space, but still look at it.) — John
