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]

Reply via email to