You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (Jira)" <ji...@apache.org> on 2021/03/15 07:24:00 UTC
[jira] [Updated] (GROOVY-9902) Generic typecheck in @DelegatesTo
doesn't work
[ https://issues.apache.org/jira/browse/GROOVY-9902?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Paul King updated GROOVY-9902:
------------------------------
Fix Version/s: 3.0.8
> 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
>
> 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.3.4#803005)