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]