You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Frank Pavageau (JIRA)" <ji...@apache.org> on 2015/10/22 23:42:27 UTC

[jira] [Commented] (GROOVY-7363) Frequent compilation error on cascading generic types

    [ https://issues.apache.org/jira/browse/GROOVY-7363?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14969951#comment-14969951 ] 

Frank Pavageau commented on GROOVY-7363:
----------------------------------------

I've been running the {{StaticTypeCheckingVisitor}} on my test under the debugger, to understand how it works and where the problem might come from, and I think I've pinpointed the origin.

The reflection finds 2 methods {{getB()}} in {{ABC}}:
- the implemented method {{BC getB()}}
- a bridge method {{B getB()}}, with the original return type as declared in the {{A}} interface

As always with reflection, the order of the methods returned by {{Class.getDeclaredMethods()}} is undefined, which is why the failure can be flaky, even if my test reproduces it reliably on my machine. When the {{ClassNode}} for {{ABC}} is initialized (in {{lazyClassInit()}}), the bridge method is returned first, the implemented method second, and both are registered in {{ClassNode.methodsList}} and {{ClassNode.methods}}.

Then, when resolving the type of the {{a.b}} expression in {{StaticTypeCheckingVisitor.existsProperty()}}, the {{ClassNode}} returns the first getter matching the name and parameters of {{getB()}} ({{MethodNode getter = current.getGetterMethod("get" + capName)}}}): the bridge method with a broader return type ({{B}}) than the actual, implemented method ({{BC}}).

So the question is: is there a point in keeping the bridge methods in the {{ClassNode}}? Are they ever needed? And even if they are, shouldn't the implemented methods have precedence in {{ClassNode.methods}} by being sorted first, so the exact types are always used? Because {{Class.getDeclaredMethods()}} returns an array with an undefined order, I think it's a bad idea to simply store them in the same order.

I'll try both scenarios and see if any existing test breaks (and if it fixes mine), but it's probably better if someone has a opinion on the best route.

> Frequent compilation error on cascading generic types
> -----------------------------------------------------
>
>                 Key: GROOVY-7363
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7363
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static Type Checker
>    Affects Versions: 2.4.2
>         Environment: MacOS X
> Oracle JDK 1.7u75 / 1.8u40
> Maven 3.0.5
>            Reporter: Frank Pavageau
>            Assignee: Cédric Champeau
>              Labels: test
>         Attachments: lost-cascading-types.tar.gz
>
>
> Most of the time, I get the following compilation error:
> {noformat}
> [ERROR] /Users/fpavageau/devs/bugs/lost-cascading-types/src/main/groovy/BadType.groovy: 22: [Static type checking] - No such property: start for class: T
> [ERROR] @ line 22, column 22.
> [ERROR] println("" + rel.currentState.state.start)
> [ERROR] ^
> [ERROR] 
> [ERROR] 1 error
> {noformat}
> where {{rel}} is an instance of a non-parameterized (Java) class implementing a generic interface with the {{currentState}} generic property. So the type of the property should actually be known, but it's lost and I get a compilation error because the {{start}} property is not part of the lower-bound type of {{currentState}}.
> When I say "most of the time", it's because the compilation error is not always triggered (so lots of debugging fun!). I've tried with Oracle JDK 1.7u75 and 1.8u40, and I get around 87% of failures:
> {code:title=JDK 1.7}
> $ failures=0; for i in {1..100}; do mvn clean package > /dev/null 2>&1 || ((failures++)); done; echo $failures
> 87
> {code}
> {code:title=JDK 1.8}
> $ failures=0; for i in {1..100}; do mvn clean package > /dev/null 2>&1 || ((failures++)); done; echo $failures
> 88
> {code}
> I'm attaching a test case, which is also available on [Github|https://github.com/fpavageau/lost-cascading-types].



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)