[
https://issues.apache.org/jira/browse/GROOVY-9902?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Eric Milles updated GROOVY-9902:
--------------------------------
Fix Version/s: 2.5.16
> Generic typecheck in @DelegatesTo doesn't work
> ----------------------------------------------
>
> Key: GROOVY-9902
> URL: https://issues.apache.org/jira/browse/GROOVY-9902
> Project: Groovy
> Issue Type: Bug
> Components: Static compilation
> Affects Versions: 2.5.6, 3.0.7
> Reporter: Felix Scheinost
> Assignee: Eric Milles
> Priority: Major
> Fix For: 3.0.8, 4.0.0-alpha-3, 2.5.16
>
> Time Spent: 1h
> Remaining Estimate: 0h
>
> I found an edge case where @CompileStatic doesn't raise an error when calling
> a method with incompatible types.
> Example code that reproduces the problem:
> [https://groovyconsole.appspot.com/script/5098548152500224]
> {code:java}
> import groovy.transform.CompileStatic
> /**
> * For the bug to be visible this class has to have a generic type
> * Even if in this case the generic seems pointless.
> */
> @CompileStatic
> class Holder<D> {
> TypedProperty<String, D> stringProperty = prop(String)
> TypedProperty<Long, D> longProperty = prop(Long)
> def <T> TypedProperty<T, D> prop(Class<T> clazz) {
> return new TypedProperty<T, D>(clazz: clazz)
> }
> /**
> * This method is also necessary to trigger the bug.
> * Seems like because of the missing <D> in the @DelegatesTo the
> typechecker is tripped up?
> * In the original method in our codebase the signature contains <D> as
> well.
> */
> def <T> T of(@DelegatesTo(value = Holder, strategy =
> Closure.DELEGATE_FIRST) Closure<T> c) {
> c.delegate = this
> c.resolveStrategy = Closure.DELEGATE_FIRST
> c()
> }
> }
> @CompileStatic
> class TypedProperty<T, D> {
> Class<T> clazz
> void eq(T t) {
> // The code fails here, expected String but got GString
> // This should have been catched by the typechecker
> // And/Or the typechecker should have automatically converted GString to
> String
> assert t.class == clazz, "t.class is ${t.class} not ${clazz}"
> }
> }
> @CompileStatic
> class Test {
> static void test() {
> Holder<Object> q = new Holder<Object>()
> // Works:
> // Typechecker catches this: Cannot call TypedProperty <String,
> Object>#eq(java.lang.String) with arguments [groovy.lang.GString]
> // q.stringProperty.eq("${0}")
>
> // Doesn't work because of delegation
> q.of {
> // Typechecker should be able to catch this as well
> // But instead it yields a runtime problem because TypedProperty is
> called with GString and assert fails
> stringProperty.eq("${0}")
>
> // Doesn't get catched by the typecherk as well - completely different
> types Long and String
> longProperty.eq("foo")
> }
> }
> }
> Test.test()
> {code}
>
--
This message was sent by Atlassian Jira
(v8.20.1#820001)