Design decisions: forward reference, corralling, method keys

Brian Goetz brian.goetz at oracle.com
Mon May 18 18:34:00 UTC 2015


>> But using this new status (ActiveFailed) widens the envelope and
>> introduces some new issues, two are known so far:
>>
>> (A) Thanks, Andrei, for pointing this out.  If a variable with
>> initializer is in ActiveFailed an update can move it to Active.
>> What is the value of the variable?  Should the initializer be
>> run?      If the initializer was the location of the unresolved, it
>> seems     silly not to run it.  Yet, this would be running arbitrary
>> code on     update which is sure to have surprising behavior in some
>> cases.      Here are the not so perfect options as I see them:

I think deferring the initializer until later creates more problems than 
it solves.

For the case of

    C c;

where C is currently undefined, I think our current strategy of 
corralling the variable declaration until C becomes defined is fine. 
It's only when we try to cross the bridge to

    C c = e;

where things get ugly, because this would involve triggering execution 
(not merely recompilation) when C is updated.  I think that's a bridge 
too far.

So, my inclination here is to just reject a variable-with-initializer if 
we cannot resolve all the types involved.  This may ultimately make it 
impossible to cut-and-paste from some constructions, for example:

     int x = getFoo();
     int getFoo() { if (x == 0) return 1; else return 2; }

but this can still be manually restructured into

     int x;
     int getFoo() { if (x == 0) return 1; else return 2; }
     x = getFoo();


>> (B) The key for classes and variables is determined by just their
>> name.  But because of overloading, for methods, the key is the
>> name     plus the parameter types.  This is fine if the method
>> signature can     be compiled (the body can be stubbed-out as is the
>> case when     corralled), as the full qualified name of the parameter
>> types is     then known.  But if one of the parameter types is
>> unresolved its     full name is not known either so the correct key
>> cannot be     determined.  This is significant because if it is put
>> in     ActiveFailed it can updated into Active (or ActiveCorralled)
>> at     which point its actual key is then known and a central
>> invariant is     that the key for an input does not change,  And here
>> is another set     of non-ideal options that I can think for this:

This is not an issue of "what should the REPL do"; it is more an 
accident of the internal Key abstraction we've created.

I think you left off an option from your list; what about using the text 
typed by the user?  So

   m(foo.bar.Baz)
and
   m(Baz)

would have different keys but would point to the same overload of m. 
This could cause some UI anomalies but would it present any semantic 
challenges?



More information about the kulla-dev mailing list