On Wed, Mar 28, 2018 at 3:55 PM Dan Smith <daniel.sm...@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 expressions. > 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 > chosen? > 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 behaviour).