paulk-asert opened a new pull request, #3293:
URL: https://github.com/apache/groovy/pull/3293

   This bundles the three open fixes for the regressions that followed 
GROOVY-12714, so they can be reviewed and merged as one consistent change. It 
targets master only; the `GROOVY_6_0_X` port is a separate discussion.
   
   **_It has a "Decisions taken" section. That isn't meant to indicate that 
these are decisions taken by the Groovy project, just what was put into this 
PR. It roles back some of the suggestions in the referenced PRs. Groovy doesn't 
try to be exactly the same as Java but has various changes to provide Groovy's 
ergonomic benefits. The intention of this bundling is to make sure if we align 
more closely with javac behavior on any point, we understand and document any 
reduction in ergonomic benefits at the same time. It retains the original PR 
commits but can be squashed as needed if accepted._**
   
   ## What is in it
   
   - The heads of #3286 (which contains #3285) and #3289, merged with Scott's 
commits unchanged.
   - Five commits on top: four that change behaviour, described below, and one 
that documents the rules in the type checking chapter of the guide, with spec 
tests.
   
   ## Changes on top of the three PRs
   
   **1. `getClass()` follows `instanceof` inference** (reverses 471cb3b9da)
   
   After `o instanceof String`, `o.getClass()` and `o.class` are a `Class<? 
extends String>`, like every other member of `o` in that branch. This differs 
from Java and from what Daniel asked for on #3286. The reason is that 
`instanceof` inference is a documented, deliberate difference from Java, and 
typing one method by the declared type would be a special case inside it. It is 
sound: the class of a value that passed the test is a subtype of `String`.
   
   **2. A diamond constructor call with a wildcard argument** (regression from 
a48ffb4db7)
   
   `new Holder<>(list)` for a `List<? extends Integer>` compiles on master and 
in javac, and was rejected on #3286, even for an unbounded type parameter. For 
a diamond the type parameters of the class are now inferred from the arguments, 
like those of a generic method. That also makes the `List<? extends String>` 
form for `Holder<T extends Number>` a compile error; on master it compiles and 
fails with a `GroovyCastException`.
   
   **3. A nested wildcard for a type parameter named in a bound** (hole in 
efa0808656)
   
   For `<T extends Number, U extends List<T>> m(Class<U>)`, a `Class<? extends 
ArrayList<? extends String>>` was accepted. Master and javac reject it; it is 
rejected again.
   
   **4. Target typing**
   
   - A variable declared with a target-typed call kept the type inferred from 
the arguments, so `List<Class<?>> r = Collections.singletonList(x.getClass()); 
return r` failed on the `return`. That compiles on master. The variable now has 
its declared type.
   - `List<Number> g(List<? extends Number> l) { same(l) }` with `<T extends 
Number> List<T> same(List<T>)` was accepted, so a `List<Integer>` could be 
returned as a `List<Number>`. Master and javac reject it; it is rejected again.
   - A spread expression takes its element type from the target: 
`list*.getClass()` and `list*.class` compile for a `List<Class<?>>`, as they do 
on master, and `people*.name` for a `List<CharSequence>`. This is not 
containment. A spread expression always makes a new list, so it is treated like 
`list.collect { ... }`, which #3286 already accepts. A value that already has a 
type is still not converted: a variable of type `List<Class<? extends String>>` 
is not a `List<Class<?>>`.
   
   ## Decisions taken
   
   - A `Class<?>` value, as `Class.forName` returns, stays rejected for a 
`Class` with a bound, as in #3289. The guide shows `asSubclass` as the fix.
   - The raw-bound rule from #3286 is kept: `? extends Map` is not within `? 
extends Map<String, Object>`. A raw type as a plain type argument (`List<Map>` 
for `List<Map<String, Object>>`) is still not checked. Checking that could be 
an opt-in strict type checking extension, as a follow-up.
   
   ## Not changed
   
   - `First.<Integer>first(ints)` and `Double d = first(ints)` for a `List<? 
extends Integer>` still compile. Both are existing behav
   - A failed generics check is an error; it does not fall back to a less 
specific overload as javac would.
   - Full erasure of the members of a raw type, and a declared-type rule for 
`Class<ArrayList>`, are not included.
   
   ## Documentation
   
   The "Generic types" section of the type checking chapter gains tested 
examples for: a wildcard argument for a bounded type parametrom the target of a 
call or spread expression, a raw type as a wildcard bound, a value that is not 
a `Class` assigned to a
   parameterized `Class`, and the type of `getClass()`. `COMPATIBILITY.md` is 
updated for points 1 and 4.
   
   ## Testing
   
   - Root `:test`: 20,126 tests, 0 failures. Subproject tests were not run 
locally.
   - Each change above has a test in `GenericsSTCTest`, so 
`GenericsStaticCompileTest` runs it too.
   - 27 further programs compared with javac 25.0.4: 23 agree. Of the four that 
differ, three differ on master in the same way, and the fourth is the overload 
fallback listed above.
   
   Supersedes #3285, #3286 and #3289.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to