Agreed with Brian.

With best regards,
Tagir Valeev.

On Fri, Jan 10, 2020 at 11:22 PM Brian Goetz <brian.go...@oracle.com> wrote:
>
> There is a whole category if "ooh, shiny new language construct, this is an 
> opportunity to slide in some new features."  We saw this with lambdas -- "can 
> you please make the parameters of lambdas implicitly final."  The motivation 
> for such requests is obvious; we wish all parameters could be implicitly 
> final (perhaps with an opt-out), but we can't turn back the clock, so we 
> console ourselves with "well, at least I can have _some_ finality.)  But this 
> consolation is often disappointing, because it creates (a) challenges for 
> migration between existing constructs (anon classes) and the new construct 
> (lambdas), often in both directions, and (b) requires users to keep track of 
> complex, history-driven rules for when they can use a feature ("oops, can't 
> have static fields in inner classes.")  These are often a siren song, and are 
> best avoided.
>
> Turning to records, an example of a feature we've rejected on the basis of 
> this siren song:  Named parameter invocation (`new Point(x: 1, y: 2)`.)  Yes, 
> parameter names are part of the API, so this becomes easier for records than 
> constructors/statics (which is easier, in turn, than for instance methods.)  
> Instead, we specified that record component names are always reified through 
> reflection, so that if/when we ever get to a more general story for named 
> invocation, records will be ready.
>
> While the user burden is less in this case, compiling `new R(...)` to a 
> factory invocation feels like pushing on the wrong end of the "constructor 
> rehabilitation" lever, because doing so will create binary compatibility 
> trouble for records that want to migrate back to classes.  (Like with enums, 
> this is not 100% compatible, because of the supertype (Enum/Record), but like 
> with enums, it is not uncommon to hit the wall and want to refactor back to 
> classes.  Let's not make this harder.)
>
> So my vote is #0.  But, if we have a story for moving _all_ classes towards 
> factory construction, then we should make sure records play well.  I don't 
> think we have to do anything now for which we'd regret inaction, because 
> whatever problem we have with legacy records, we'll already have with every 
> class ever written.
>
>
>
>
> On 1/10/2020 1:36 AM, John Rose wrote:
>
> Another bit of translation strategy:  What does “new R(a,b,c)” compile
> to, at the bytecode level?  At some point we will cut over to factory methods,
> for at least some types (inlines).  Should be pre-empt this trend for records,
> and mandate that records are *always* created by factory methods?
>
> The benefit is that records can be evolved to inline types without
> recompiling their *clients*.  The risk is that (if we don’t take this
> option) that we will have records which are constrained to be identity]
> types *until all clients are recompiled*.  (No I don’t believe that you
> can translate “new;dup;invokespecial<init>” into “invokestatic”.
> Sorry, that's a pipe dream.)  This seems sad, given that records are
> partially inspired by value types.
>
> (From my 2012 blog on value types: “A value type is immutable… The
> equals and hashCode operations are strictly component-wise.”  Kind
> of like a record.  Meanwhile, inlines in Valhalla give component-wise
> meaning to acmp not equals and identityHashCode not hashCode.)
>
> I see three options regarding factories (apart from the above pipe dream):
>
> 0.  Do nothing.  Records are just abbreviated classes.  Whatever works
> or doesn’t for evolving general identity classes to inline classes works
> or doesn’t for records.  No special benefit, in this vein, to declaring
> something a record.
>
> 1. Define a factory, on top of today’s JVM.  Records use a hidden API,
> desugaring “new R(a,b)” to a static “R.$make$(a,b)”.
>
> 2. Define a factory, anticipating Valhalla, using a JVM-defined entry point.
> The expression “new R(a,b)” compiles to “invokestatic R.<init>(int,int)R”,
> preceded by a push of a and b.  This requires a (relatively shallow) change
> to the JVM to double down on the name “<init>” as the factory behind a
> constructor.
>
> The advantage of 2 is that, if we correctly predict that “<init>” is the 
> claimed
> factory method for value types, then records can be evolved to inlines out
> of the box.  The advantage of 1 is that we don’t need to make that prediction.
>
> There’s also this:
>
> 3. Do 1. but when 2. becomes an option create an auto-bridge from “$make$”
> to “<init>”.  New code doesn’t need the bridge because it compiles to call
> “<init>” out of the box.
>
> Here’s a gut check for this group:  Are we confident enough with Valhalla
> that we can settled on “invokestatic <init>” as the new dance for creating
> an instance that may or may not be an inline?
>
> — John
>
>

Reply via email to