Paul King created GROOVY-12639:
----------------------------------

             Summary: Compound assignment to a trait field fails when the 
result needs narrowing to the field's type
                 Key: GROOVY-12639
                 URL: https://issues.apache.org/jira/browse/GROOVY-12639
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 6.0.0, 5.1.3, 4.0.33
            Reporter: Paul King


{code:groovy}
trait T {
    int i = 3
    short s = 1
    byte b = 1
    def m() { i /= 2; s += 1; b <<= 1; [i, s, b] }
}
class C implements T {}
println new C().m()
{code}
Actual: in dynamic code this compiles and then throws 
{{groovy.lang.MissingMethodException: No signature of method: T__i$set for 
class: C is applicable for argument types: (BigDecimal) values: [1.5]}}. With 
@TypeChecked or @CompileStatic, compilation fails with {{[Static type checking] 
- Cannot find matching method 
T$Trait$FieldHelper#T__i$set(java.math.BigDecimal)}}, a message that names the 
internal helper. The {{short}} and {{byte}} fields fail the same way with an 
{{Integer}} argument; {{b <<= 1}} happens to compile under @CompileStatic.

Expected: [1, 2, 2], as for the same fields and method in an ordinary class. A 
compound assignment converts its result back to the type of the target; in 
traits, {{+=}} is also the documented workaround for the unsupported {{x++}}.

Cause: NAryOperationRewriter rewrites {{x op= y}} on a trait field into {{x = x 
op y}}, and TraitReceiverTransformer turns the assignment into a call of the 
field helper's setter (here {{T__i$set(int)}}). The conversion a compound 
assignment applies to its result is lost in the rewrite, so the setter receives 
the wider value. Casting the rewritten value to the field's type would restore 
it.

Since GROOVY-12603 the same applies inside closures and lambdas in trait code, 
where such an update was previously lost without an error.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to