Aladdin - Scala Bugtracking
[#723] project: compiler priority: high category: bug
submitter assigned to status date submitted
Sean Martin fixed 2006-09-04 17:50:46.0
subject mixins, separate compilation, class format error
code
// 2 FILES
// ScalaParser2.scala
package lampion.scalax;
trait ScalaParser2 { 
  trait NodeImpl { 
    trait Link extends ScalaParser2.this.Link {
      def from = NodeImpl.this;
    }
  }
  trait Link {
    def from : NodeImpl;
  }
  trait NonExpressionLink extends Link {
    def from   : IsLinked;
  }
  trait IsLinked extends NodeImpl {
    trait Link extends ScalaParser2.this.NonExpressionLink with super.Link {
      override def from = IsLinked.this;
    }
  }
  trait HasClassBody extends IsLinked {
    object classBody extends Link {
      type To = NodeImpl; 
    }
  }
  trait ClassLikeImpl extends HasClassBody;
}
// ScalaTyper2.scala
package lampion.scalax;
trait ScalaTyper2 extends ScalaParser2 {
  trait ClassLikeImpl extends super.ClassLikeImpl { 
    def foo(x : Any) = x == classBody;
  }
}

what happened
src mcdirmid$ scalac -d ../bin lampion/scalax/ScalaTyper2.scala lampion/scalax/ScalaParser2.scala 

bin mcdirmid$ javap -private 'lampion.scalax.ScalaParser2$HasClassBody$classBody$' | grep 'from()'
    public lampion.scalax.ScalaParser2$NodeImpl from();
    public lampion.scalax.ScalaParser2$NodeImpl from();
    public lampion.scalax.ScalaParser2$IsLinked from();
Compiling in the reverse order (ScalaParser2 before ScalaTyper2 in the command line argument) does not cause the\ NodeImpl from method to be duplicated.
what expected
[back to overview]
Changes of this bug report
Martin  edited on  2006-09-06 18:23:17.0
What an awful bug! I commented and cleaned up the whole Mixin phase in the hunt for it. In the end it was something completely unrelated: Erasure entered bridge methods into the scope of the enclosing class, but it did so at phase erasure, not erasure.next. Because erasure also transforms types, this caused the scope to get lost sometimes, depending on compilaton order. So bridge methods would sometimes disappear from the scope. But the bridge definition was generated anyway. Then, in the mixin phase, the symbol overridden by the bridge would get mixed in, because mixin did not see that a bridge was generated. Aaaargh!