Feedback wanted: switch expression typing
cushon at google.com
Fri Mar 30 00:47:21 UTC 2018
On Wed, Mar 28, 2018 at 3:55 PM Dan Smith <daniel.smith at oracle.com> wrote:
> Subjectively, big picture: how concerned would you be about changing
> typing rules in these cases?
My initial impression is that the compatibility impact of (C) would be
manageable, especially with the change you mentioned to allow e.g. `Long j
= flag ? jbox : 0`.
The cases where existing code would be rejected look rare, and should be
easy to understand and fix. I'm more concerned about situations where it
would change the outcome of overload resolution, since existing code could
be accepted but have subtly different behaviour, but those cases appear to
be even rarer.
As an aside, it might be valuable to have tools to help programmers prepare
for this kind of change. For example I could imagine providing a
refactoring that suggested fixes to some of the common incompatibilities,
and it would be helpful if javac could warn about cases where target typing
caused a different overload to be selected.
> 1) The incompatibilities are maybe the biggest concern. And it's not clear
> that it's helpful for the compiler to reject these sorts of conversions, so
> maybe we should change the rules.
> In particular, this is silly:
> Short s = 0; // fine
> Long l = 0; // error
> So: what portion of "primitive.conditional.incompatible" are something
> other than a literal? Other than a constant expression?
92% of them are constants, <2% of those constants are non-literal constant
> 2) Often, the choice of box class doesn't matter (e.g., if printing a
> Byte/Short/Integer/Long as a string). What portion of
> "primitive.conditional.box" seem to care about the which box class is
I surveyed a sample of these. 60-80% immediately converted the expression
to a string (e.g. log statements, String.format), and <10% of the samples
cared about which box class was chosen. (The remainder weren't obviously in
either category and I haven't investigated them yet.)
In some of the cases that care which box is chosen, the change causes a
different overload to be selected.
> 3) A common pattern for null checking is:
> Integer ibox2 = (ibox == null) ? 0 : ibox;
> I'm guessing many of your "primitive.conditional.null" cases look like
> that. And if not, they're likely to guarantee in the surrounding context
> that no nulls are present. What portion of these actually seem to need and
> expect a null pointer check?
I surveyed a sample of these. >95% of them are doing explicit null handling
and don't require an implicit check, and most of those were trivial
variations on `x != null ? x : defaultValue`
I didn't find any cases where the implicit null check was expected. I may
have missed some, but it appears to be rare.
> 4) The overload resolution test casts a somewhat wide net, because
> actually simulating overload resolution is complicated. So the test is
> looking for cases in which there are other candidates that would be
> considered. What portion of these invocations actually appear that they
> would prompt a different overload choice or an ambiguity? And if the
> resolved method changes, how often is it a behaviorally significant change
> (often different overloads have the same behavior)?
The most common overloads reported by the diagnostic were String.valueOf,
assertEquals, log, StringBuilder#append, and PrintStream#println.
I audited some of the less common overloads, and all of them appeared to be
'well behaved' (selecting either one would have resulted in equivalent
More information about the amber-spec-observers