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

No way to tell @Immutable that you're using an Immutable List structure already

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.0.5
    • 2.0.6, 2.1.0-beta-1
    • groovy-jdk
    • None

    Description

      Given this class:

      @Grab( 'org.clojure:clojure:1.4.0' )
      import clojure.lang.PersistentList
      import clojure.lang.PersistentVector
      
      //@groovy.transform.Immutable(knownImmutableClasses=[List])
      class Broken {
        List list
        
        Broken( List list ) {
          this.list = list
        }
        
        Broken cons( Object v ) {
          new Broken( list.cons( v ) )
        }
        
        String toString() {
          "$list"
        }
      }
      
      def a = new Broken( PersistentList.EMPTY.cons( 'tim' ) )
      println a.cons( 'yates' )
      
      def b = new Broken( PersistentVector.EMPTY.cons( 'tim' ) )
      println b.cons( 'yates' )
      

      We get the output:

      [yates, tim]
      [tim, yates]
      

      However, if we annotate the class as Immutable (and get rid of the constructor and the toString as would be required)

      @Grab( 'org.clojure:clojure:1.4.0' )
      import clojure.lang.PersistentList
      import clojure.lang.PersistentVector
      
      @groovy.transform.Immutable
      class Broken {
        List list
        
        Broken cons( Object v ) {
          new Broken( list.cons( v ) )
        }
      }
      
      def a = new Broken( PersistentList.EMPTY.cons( 'tim' ) )
      println a.cons( 'yates' )
      
      def b = new Broken( PersistentVector.EMPTY.cons( 'tim' ) )
      println b.cons( 'yates' )
      

      We now get the output:

      Caught: groovy.lang.MissingMethodException: No signature of method: java.util.Collections$UnmodifiableList.cons() is applicable for argument types: (java.lang.String) values: [yates]
      Possible solutions: join(java.lang.String), count(groovy.lang.Closure), count(java.lang.Object), sort(), find(), any()
      groovy.lang.MissingMethodException: No signature of method: java.util.Collections$UnmodifiableList.cons() is applicable for argument types: (java.lang.String) values: [yates]
      Possible solutions: join(java.lang.String), count(groovy.lang.Closure), count(java.lang.Object), sort(), find(), any()
      	at Broken.cons(PList3.groovy:10)
      	at Broken$cons.call(Unknown Source)
      	at PList3.run(PList3.groovy:15)
      

      So the transformation has changed our List field into a UnmodifiableList, and I can no longer call the PersistentVector or PersistentList methods on it.

      Changing the transformation to:

      @groovy.transform.Immutable(knownImmutableClasses=[List])
      

      Makes no change

      Is there (or could there be added) a way of saying that you know that a given field is an Immutable type?

      Cheers,

      Tim

      Attachments

        Activity

          People

            paulk Paul King
            tim_yates Tim Yates
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: