Felix Scheinost created GROOVY-9902:
---------------------------------------
Summary: 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: 3.0.7, 2.5.6
Reporter: Felix Scheinost
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.3.4#803005)