paulk-asert opened a new pull request, #3164:
URL: https://github.com/apache/groovy/pull/3164
Closures, lambdas, method references and method pointers now share the
method-return check (assignment rules plus loss of precision); a method
reference returning a type parameter is resolved and checked by the type
checker, and static compilation converts what LambdaMetafactory cannot. Adds
ReturnConversionConsistencyTest to keep the return forms in step.
Scott's PRs had Java-like behavior for some char conversions. I have
reverted those to existing behavior. The restructuring would allow us to
reconsider such decisions and make the change in one place.
## Return conversions after this change
A value returned to a primitive functional interface type is now checked as
the `return` of a method declared with that type. A method's `return`, a
lambda, a closure, a method reference (`H::v`), a method reference to a generic
method (`H::id` with `static <T> T id(T t)`) and a method pointer (`H.&v`) give
the same result under both `@TypeChecked` and `@CompileStatic` (checked by
`ReturnConversionConsistencyTest`):
| returned type ↓ / return type → | `int` | `long` | `double` | `boolean` |
`char` |
|---|---|---|---|---|---|
| `byte`, `short`, `Integer` | ✓ | ✓ | ✓ | ✓ | ✗ |
| `int` | ✓ | ✓ | ✓ | ✓ | ✓ ¹ |
| `long`, `Long` | ✗ ² | ✓ | ✓ | ✓ | ✗ |
| `float`, `double` | ✗ ² | ✗ ² | ✓ | ✓ | ✗ |
| `char` | ✗ | ✗ | ✗ | ✓ | ✓ |
| `boolean` | ✗ | ✗ | ✗ | ✓ | ✗ |
| `BigDecimal` | ✗ | ✗ | ✓ | ✓ | ✗ |
| `BigInteger` | ✗ | ✗ | ✗ | ✓ | ✗ |
| `String` | ✗ | ✗ | ✗ | ✓ | ✗ |
✓ compiles and converts the value at run time (`boolean` by Groovy truth); ✗
compile error.
¹ Except a method reference to a generic method: its type argument is
`Integer`, and a method cannot return an `Integer` as a `char` either.
² "Possible loss of precision". A constant that fits is accepted, as for a
method's `return`, for example `IntSupplier s = () -> 7L`.
## Relationship to #3142, #3143 and #3149
This builds on @codeconsole #3142 (GROOVY-12616), #3143 (GROOVY-12617) and
#3149 (GROOVY-12623), whose commits are included unchanged, apart from
resolving the conflict #3143 and #3149 described. Those PRs gave closures and
lambdas JLS widening and method references cast-like conversion. The commit on
top makes them all follow the rule for a method's `return` instead, so that
every form agrees (see the table above).
**Closures and lambdas (#3142)**
- `isWideningPrimitive` is replaced by the shared `checkReturnValue`, which
is also used for a method's `return`.
- `char` is no longer widened to `int` (it isn't for an assignment or a
method's `return` either).
- Newly accepted: a constant that fits (`IntSupplier s = () -> 7L`) and
`BigDecimal` for `double`/`float`; the GROOVY-8168 case now compiles and runs.
- A narrowing is reported as "Possible loss of precision", as for a method.
**Method references with a concrete return type (#3143)**
- The type check uses `checkReturnValue`, so narrowing is now an error
(`IntSupplier s = C::longValue`, as for `int m() { longValue() }`).
- The code writer's adapter is kept for what `LambdaMetafactory` cannot
convert: Groovy truth, and `BigDecimal` to `double`/`float`.
- The adapter decision is merged with #3149's into one
`isReturnConversionRequired`, which uses `isAssignableTo` rather than its own
widening table.
**Method references returning a type parameter (#3149)**
- The type checker now resolves the method's type parameter from the
functional interface's parameter types and checks it. Previously it skipped the
check.
- The code writer reads the resolved type, instead of resolving it a second
time.
- Newly rejected: `ToIntFunction<Character> f = C::id`,
`ToIntFunction<String> f = C::id`, `ToChar<String> f = C::id` and
`ToIntFunction<Long> f = C::id`. The last one compiles and runs on master; see
`COMPATIBILITY.md`.
- Groovy truth, serialization and the cases needing no conversion are
unchanged.
**Also included**
- A method pointer (`.&`) assigned to a functional interface is checked as
it already is when passed as an argument.
- `ReturnConversionConsistencyTest` checks a method's `return` against
lambdas, closures, method references and method pointers, with deliberate
exceptions listed.
- Javadoc on `checkCompatibleAssignmentTypes` and `isAssignableTo` says
which context each serves.
- The `groovy-internals` skill gains a failure mode about adding a separate
compatibility rule.
- A Groovy 7 `COMPATIBILITY.md` entry.
--
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]