codeconsole opened a new pull request, #3276:
URL: https://github.com/apache/groovy/pull/3276

   Fixes [GROOVY-12741](https://issues.apache.org/jira/browse/GROOVY-12741).
   
   The contracts transform runs in semantic analysis, before the trait 
transform, and treated a trait as a class: it generated the condition class 
from the trait method's parameters and marked the trait `@Contracted`. The 
trait transform then moved each method with a body into the helper class as a 
static method with a leading `$self` parameter, and the helper was woven in 
instruction selection with one argument more than the condition class accepts. 
The effects: `@Requires` on a trait method with a parameter crashed class 
generation (`ArrayIndexOutOfBoundsException` in 
`InvocationWriter.loadArguments`, or `StaticInvocationWriter` under 
`@CompileStatic`); `@Requires` without parameters and `@Ensures` compiled, then 
every call failed with `No such property: $GCONTRACTS_ENABLED for class: 
Bank$Trait$Helper`; a trait `@Invariant` was inherited by the implementing 
class and failed while the trait's fields were still being initialised. 
`@ThrowsIf` and `@Decreases` on a trait method with a
  body are woven into the helper class after the trait transform has rewritten 
the body, so a condition that refers to trait state has no receiver there.
   
   Supporting contracts on trait methods needs a design (where the check runs, 
what `this` is, how a trait invariant interacts with trait field 
initialisation, private and static trait methods). This change makes the module 
report a compile error instead of crashing or failing at run time. 
`ClosureExpressionEvaluationASTTransformation` rejects, for every trait in the 
unit, a class-level contract annotation (`@Invariant is not supported on a 
trait (Bank).`) and a contract, `@ThrowsIf` or `@Decreases` on a method with a 
body (`@Requires is not supported on a trait method with a body (Bank.deposit); 
only an abstract trait method may carry a contract.`). A contract on an 
abstract trait method keeps working, as does one on an interface method a trait 
implements.
   
   The crash that `@ThrowsIf` and `@Decreases` on a trait method hit first, in 
core `TraitComposer`, is 
[GROOVY-12743](https://issues.apache.org/jira/browse/GROOVY-12743) with its own 
pull request; this change rejects them before that point is reached, so the two 
are independent.
   
   Tests: a new `TraitContractValidationTests` (six tests: precondition with 
and without parameters, postcondition, trait invariant, statically compiled 
trait, and the abstract trait method that keeps working), two tests in 
`ThrowsIfTests` and one in `MethodDecreasesTests`. The `groovy-contracts` 
module passes with the change (405 tests).
   


-- 
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