Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-11341

@CompileStatic: Compilation fails due to a synthetic bridge method in the subclass

    XMLWordPrintableJSON

Details

    Description

      Given the following Java classes:

      public interface InterfaceBase {
          Object getValue();
      }
       
      
      public class MyImplBase {
          public Long getValue() {
              return 42L;
          }
      }
       
      
      public class MyImpl extends MyImplBase implements InterfaceBase {
      } 

       
      And the following SimpleCaller.groovy:

      @groovy.transform.CompileStatic
      class SimpleCaller {
      
         public static void main(String[] args) {
            Long v = new MyImpl().getValue();
            System.out.println(v); //42
         }
      
      } 

      The compilation fails with:
       
      SimpleCaller.groovy: 7: [Static type checking] - Cannot assign value of type java.lang.Object to variable of type java.lang.Long
       @ line 7, column 16.
               Long v = new MyImpl().getValue();
                        ^
       
      Compiling the equivalent SimpleCaller.java with javac completes successfully.
       
      This structure is a bit uncommon, because MyImplBase uses a covariant return type and doesn't implement the interface directly, only its subclass does.
       
      I believe the problem is connected to the synthetic bridge method inserted into the bytecode of MyImpl, which is picked up and preferred by groovyc over the non-synthetic method in MyImplBase.
       
       
      In case this is related: The synthetic bridge method is selected when using reflection as well, causing the inferred type by javac and reflection to diverge:

      Method getValueMethod = MyImpl.class.getMethod("getValue");
      // public java.lang.Object MyImpl.getValue() 

       
       
      Workarounds: 

       

      • Disable static compilation
      • An explicit cast to Long in SimpleCaller.
      • Explicitly repeat the covariant method signature in MyImpl
      • If possible, add/Move the implements to MyImplBase - then the synthetic method is in the same class as the real one, which groovyc is able to detect.

      Using generics in the Interface doesn't work either (probably due to type erasure).
       
      Seems to be a more generalized issue when compared to the similar GROOVY-5003

      Attachments

        Issue Links

          Activity

            People

              emilles Eric Milles
              peter99 Peter Schmitz
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: