Uploaded image for project: 'Scala Programming Language'
  1. Scala Programming Language
  2. SI-4717

mixin transforms lazy vals incorrectly under specialization: crash

    Details

      Description

      trait Bug1[@specialized +A] extends TraversableOnce[A] {  
        def ++[B >: A](that: TraversableOnce[B]): Iterator[B] = new Iterator[B] {
          lazy val it = that.toIterator
          def hasNext = it.hasNext
          def next = it.next
        }
      }
      

      [running phase cleanup on bug1.scala]
      [running phase icode on bug1.scala]
      error: java.lang.Error: Unknown type: [<deferred> <param> T0 >: ? <: ?]()T0, [<deferred> <param> T0 >: ? <: ?]()T0 [class scala.reflect.internal.Types$PolyType, class scala.reflect.internal.Types$PolyType] TypeRef? false
      at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:31)
      at scala.tools.nsc.backend.icode.TypeKinds$class.toTypeKind(TypeKinds.scala:390)

      Analysis points the finger at mixin.

      // before mixin - asInstanceOf[Iterator]
      private <stable> <accessor> lazy def it(): Iterator = {
        Bug1$mcD$sp$$anon$10.this.it _=(Bug1$mcD$sp$$anon$10.this.that$10.toIterator());
        Bug1$mcD$sp$$anon$10.this.it .$asInstanceOf[Iterator]()
      };
       
      // after mixin - asInstanceOf is unapplied, polytype reaches back end
      private lazy var it : Iterator = _;
      private <stable> <accessor> lazy def it(): Iterator = {
        if (Bug1$mcD$sp$$anon$10.this.bitmap$priv$0.&(4).==(0))
          {
            Bug1$mcD$sp$$anon$10.this.synchronized({
              if (Bug1$mcD$sp$$anon$10.this.bitmap$priv$0.&(4).==(0))
                {
                  Bug1$mcD$sp$$anon$10.this.it _=(Bug1$mcD$sp$$anon$10.this.that$10.toIterator());
                  Bug1$mcD$sp$$anon$10.this.bitmap$priv$0 = Bug1$mcD$sp$$anon$10.this.bitmap$priv$0.|(4);
                  ()
                };
              scala.runtime.BoxedUnit.UNIT
            });
            Bug1$mcD$sp$$anon$10.this.that$10 = null
          };
        Bug1$mcD$sp$$anon$10.this.$asInstanceOf
      };
      

        Attachments

          Activity

          Hide
          extempore Paul Phillips added a comment -

          Closed SI-4123 as a duplicate. Here's retronym's even more minimized case from that.

          trait Bounds[@specialized A] {
            // okay without `>: A`
            def x[B >: A]: Unit = new Bounds[B] {
              lazy val it = ???  // def or val okay
              it
            }
          }
          

          Show
          extempore Paul Phillips added a comment - Closed SI-4123 as a duplicate. Here's retronym's even more minimized case from that. trait Bounds[@specialized A] { // okay without `>: A` def x[B >: A]: Unit = new Bounds[B] { lazy val it = ??? // def or val okay it } }
          Hide
          prokopec Aleksandar Prokopec added a comment - - edited

          I'm getting:

          error: scala.reflect.internal.Types$TypeError: value it  is not a member of Bounds[B]{}
          

          For some reason the `typedThis` in the typechecker:

                def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match {
                  case NoSymbol => tree
                  case clazz    =>
                    log("typedThis: " + qual)
                    tree setSymbol clazz setType clazz.thisType.underlying
                    if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree
                }
          

          does not add `lazy val it` to the list of members. I'm trying to figure this out.

          Show
          prokopec Aleksandar Prokopec added a comment - - edited I'm getting: error: scala.reflect.internal.Types$TypeError: value it is not a member of Bounds[B]{} For some reason the `typedThis` in the typechecker: def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match { case NoSymbol => tree case clazz => log("typedThis: " + qual) tree setSymbol clazz setType clazz.thisType.underlying if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree } does not add `lazy val it` to the list of members. I'm trying to figure this out.
          Hide
          prokopec Aleksandar Prokopec added a comment -

          I think the `lazy val` gets assigned the wrong owner in the `invalidate` method in `Duplicators`.

          Show
          prokopec Aleksandar Prokopec added a comment - I think the `lazy val` gets assigned the wrong owner in the `invalidate` method in `Duplicators`.
          Hide
          prokopec Aleksandar Prokopec added a comment -
          Show
          prokopec Aleksandar Prokopec added a comment - Should be fixed here: https://github.com/scala/scala/pull/576

            People

            • Assignee:
              prokopec Aleksandar Prokopec
              Reporter:
              extempore Paul Phillips
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: