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

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

I've been trying to create a test case for this bug, but it has proven 
difficult due to the fact that it's not 100% reproducible. I've tried running 
the body of the test in a loop (using {{100.times}} for example) but it either 
fails immediately or never, so it's probably related to an initialization. With 
the minimal test case I eventually created, the static type check fails 46% of 
the time.

However, while building this minimal test case and removing as much stuff as I 
could, I noticed that some modifications removed the bug, and it led me to an 
interesting discovery. The test case runs the following script:
{code}
assertScript """import 
org.codehaus.groovy.classgen.asm.sc.bugs.support.Groovy7363Support
    Groovy7363Support.ABC a = new Groovy7363Support.ABC()
    println('' + a.b.object.value)
"""
{code}
which fails, as in my original report, with:
{noformat}
TestScripttestCascadingGenericTypes0.groovy: 3: [Static type checking] - No 
such property: value for class: T
@ line 3, column 26.
               println('' + a.b.object.value)
                            ^
{noformat}
The support Java code started with:
{code}
public class Groovy7363Support {
    public interface A<T, U extends B<T>> {
        U getB();

        void setB(U b);
    }

    public static class ABC implements A<C, BC> {
        @Override
        public BC getB() {
            return new BC();
        }

        @Override
        public void setB(BC b) {}
    }

    // ...
}
{code}


The setter did not seem necessary in the interface so I removed it, along with 
its implementation, and then the check passed. I then added the setter back, 
but only in the implementation, and the check failed again (46% of the time):
{code}
public class Groovy7363Support {
    public interface A<T, U extends B<T>> {
        U getB();
    }

    public static class ABC implements A<C, BC> {
        @Override
        public BC getB() {
            return new BC();
        }

        public void setB(BC b) {}
    }

    // ...
}
{code}


And then I remembered that classes implementing generics have synthetic bridge 
methods generated by the compilation, so I wondered if changing the order of 
the methods might influence the output. And indeed, moving the setter first in 
front of the getter makes the check fail reliably _on my machine_ (MacOS X 
10.10.4, 64-bit Oracle JDK 1.7.0u75):
{code}
public class Groovy7363Support {
    public interface A<T, U extends B<T>> {
        U getB();
    }

    public static class ABC implements A<C, BC> {
        public void setB(BC b) {}

        @Override
        public BC getB() {
            return new BC();
        }
    }

    // ...
}
{code}


Still, I'm reluctant to actually create a pull request from [my 
branch|https://github.com/apache/incubator-groovy/compare/GROOVY_2_4_X...fpavageau:GROOVY-7363?expand=1]
 because the test could actually be flaky in other environments. But [the code 
is there|https://github.com/fpavageau/incubator-groovy/tree/GROOVY-7363], and I 
might try and debug it myself, to find where the analysis of the {{ABC}} class 
takes place and incorrectly initializes the context.

> 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
>         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)

Reply via email to