groovy
  1. groovy
  2. GROOVY-3830

java.lang.IncompatibleClassChangeError thrown with Interface containing variable

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7-beta-2
    • Fix Version/s: 1.6.6, 1.7-rc-1
    • Component/s: Compiler
    • Labels:
      None
    • Number of attachments :
      2

      Description

      First reported in http://jira.codehaus.org/browse/GROOVY-3823, opening a new Jira, as advised.

      With:

      interface II {
        Integer i
        Integer 2i = i * 2
      }
      

      Currently (1.7b2), one gets:

      groovy> interface II {
      groovy>   Integer i
      groovy>   Integer i2 = i * 2
      groovy> }
      groovy> println II.i
      groovy> println II.i2
      

      Exception thrown

      java.lang.IncompatibleClassChangeError: Found interface II, but class was expected
      
      	at II.<clinit>(ConsoleScript0:3)
      
      	at ConsoleScript0.class$(ConsoleScript0)
      
      	at ConsoleScript0.$get$$class$II(ConsoleScript0)
      
      	at ConsoleScript0.run(ConsoleScript0:6)
      
      1. v16x_3830_v2.txt
        7 kB
        Roshan Dawrani
      2. v16x_3830.txt
        6 kB
        Roshan Dawrani

        Issue Links

          Activity

          Hide
          Roshan Dawrani added a comment -

          I think the IncompatibleClassChangeError is coming because in the interface II's <clinit>, there is an invokestatic call being made for method $getCallSiteArray()[0] (for the multiply operation in i * 2).

          Since interface II itself cannot contain any static methods such as $getCallSiteArray() or $createCallSiteArray(), callsites for the interface should probably be pushed into its synthetic, inner class and referenced as II$1.$getCallSiteArray()?

          Is there any other, simpler suggestion?

          Show
          Roshan Dawrani added a comment - I think the IncompatibleClassChangeError is coming because in the interface II's <clinit>, there is an invokestatic call being made for method $getCallSiteArray() [0] (for the multiply operation in i * 2). Since interface II itself cannot contain any static methods such as $getCallSiteArray() or $createCallSiteArray(), callsites for the interface should probably be pushed into its synthetic, inner class and referenced as II$1.$getCallSiteArray()? Is there any other, simpler suggestion?
          Hide
          Roshan Dawrani added a comment -

          Attaching a patch for review.

          Basically the fix is that the callsites used in the interface are being pushed to its helper inner class and later on instead of invoking $getCallSiteArray() on the interface, the call is delegated to its inner class.

          Also in this case, $getCallSiteArray() is made public in the inner class (usually it is private) so that it can be invoked from static constructor of the outer interface class.

          Show
          Roshan Dawrani added a comment - Attaching a patch for review. Basically the fix is that the callsites used in the interface are being pushed to its helper inner class and later on instead of invoking $getCallSiteArray() on the interface, the call is delegated to its inner class. Also in this case, $getCallSiteArray() is made public in the inner class (usually it is private) so that it can be invoked from static constructor of the outer interface class.
          Hide
          blackdrag blackdrag added a comment -

          I think I would prefer a solution that does not expose call sites, especially not in ClassNode, since callsites make no sense in more early phases

          Show
          blackdrag blackdrag added a comment - I think I would prefer a solution that does not expose call sites, especially not in ClassNode, since callsites make no sense in more early phases
          Hide
          Roshan Dawrani added a comment -

          Where else the callsites can be stored between the ACG invocations for interface ClassNode and its inner class ClassNode?

          I was trying to change the patch to store these callsites in an ACG instance variable but then CompilationUnit uses different instances of ACG for both these ClassNodes.

          Any better suggestions?

          Show
          Roshan Dawrani added a comment - Where else the callsites can be stored between the ACG invocations for interface ClassNode and its inner class ClassNode? I was trying to change the patch to store these callsites in an ACG instance variable but then CompilationUnit uses different instances of ACG for both these ClassNodes. Any better suggestions?
          Hide
          Roshan Dawrani added a comment -

          Here is a slightly modified version of the patch.

          The slight difference now is that on the interface ClassNode, callsites are not set until its classgen phase and helper InnerClassNode does not try to use these callsites until its classgen phase.

          So, callsites are not really set and seen by earlier phases now.

          Show
          Roshan Dawrani added a comment - Here is a slightly modified version of the patch. The slight difference now is that on the interface ClassNode, callsites are not set until its classgen phase and helper InnerClassNode does not try to use these callsites until its classgen phase. So, callsites are not really set and seen by earlier phases now.
          Hide
          Roshan Dawrani added a comment -

          Jochen, the 2nd patch also won't do?

          Show
          Roshan Dawrani added a comment - Jochen, the 2nd patch also won't do?
          Hide
          Roshan Dawrani added a comment -

          Jochen, busy, is it?

          This fix is in wait mode because of this little thing you raised in the comments earlier. Are you comfortable with the 2nd patch? Or do you suggest anything?

          Show
          Roshan Dawrani added a comment - Jochen, busy, is it? This fix is in wait mode because of this little thing you raised in the comments earlier. Are you comfortable with the 2nd patch? Or do you suggest anything?
          Hide
          blackdrag blackdrag added a comment -

          wouldn't the finer solution to make a subclass of InnerClassNode for that interface helper?

          Show
          blackdrag blackdrag added a comment - wouldn't the finer solution to make a subclass of InnerClassNode for that interface helper?
          Hide
          Roshan Dawrani added a comment -

          OOPs.

          Thanks.

          Fixed.

          Show
          Roshan Dawrani added a comment - OOPs. Thanks. Fixed.

            People

            • Assignee:
              Roshan Dawrani
              Reporter:
              alpheratz
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: