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

Compilation order important to CompileStatic

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Duplicate
    • Affects Version/s: 2.0.0
    • Fix Version/s: 2.0.1
    • Component/s: Static compilation
    • Labels:
      None

      Description

      Discovered whilst I was debugging why STS was having a hard time compiling grails.

      Here is a cut down version of the issue:
      PSI.groovy:

      class PSI {
        Set<String> pluginNames = []
      }
      

      PBS.groovy

      import groovy.transform.*;
      
      class PBS {
        @CompileStatic
        protected def foo(PSI compileInfo) {
          compileInfo.pluginNames
        }
      }
      

      Compile them like this:
      > groovyc PSI.groovy PBS.groovy

      it works fine.

      Compile them like this:
      > groovyc PBS.groovy PSI.groovy

      org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
      PBS.groovy: 6: Access to PSI#pluginNames is forbidden @ line 6, column 5.
             compileInfo.pluginNames
             ^
      1 error
      

      The 'forbidden' message is coming out because under the covers the PSI type does not implement GroovyObject at the time the static type checking is done. In the AsmClassGenerator.visitAttributeExpression() method, the code block:

        } else {
          adapter = getField;
          if (isGroovyObject(objectExpression)) adapter = getGroovyObjectField;
          if (usesSuper(expression)) adapter = getFieldOnSuper;
        }
      

      The isGroovyObject(...) test fails (it is asking about PSI). The wrong adapter is used and then the code in AsmClassGenerator.visitAttributeOrProperty() makes the wrong choice:

       if (adapter == getProperty && !expression.isSpreadSafe() && propName != null) {
         controller.getCallSiteWriter().makeGetPropertySite(objectExpression, propName, expression.isSafe(), expression.isImplicitThis());
       } else if (adapter == getGroovyObjectProperty && !expression.isSpreadSafe() && propName != null) {      
         controller.getCallSiteWriter().makeGroovyObjectGetPropertySite(objectExpression, propName, expression.isSafe(), expression.isImplicitThis());
      

      As far as I can tell. The verifier adds GroovyObject but that runs in phase 9 whilst the static type checker is running in phase 7... before the verifier has done its work. So this is kind of behaving only if the relevant type has been all through the process before the question is asked about whether it is a groovyobject.

      Note, I have only been debugging under STS which does have a slightly different compilation sequence to regular groovy but hopefully that debug info from a above is somewhat useful.

        Attachments

          Activity

            People

            • Assignee:
              melix Cédric Champeau
              Reporter:
              aclement Andy Clement
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: