Scala Programming Language
  1. Scala Programming Language
  2. SI-5489

FSC generating spurious errors in the face of anonymous classes

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Scala 2.9.1
    • Fix Version/s: Scala 2.10.0-M4
    • Component/s: Misc Compiler
    • Labels:
    • Environment:

      Windows XP x64 SP2; JDK 1.6.0_30; IntelliJ IDEA 10.0.2; Scala plugin 0.5.369

      Description

      package repro
      
      trait HasString {
        def string: String
      }
      
      class CausesProblems {
        def problems = (
          if ("don't optimize me away!".length == 0)
            new HasString { def string = "wut" }
          else
            new HasString { def string = "okay" }
        ).string
      }
      

      Compiles fine without FSC. Compiles fine with FSC too, the first time. Attempting to recompile it without kicking FSC results in:

          Error:Error:line (3)error: overriding method string in trait HasString of type ()String;
      method string in class Object of type ()java.lang.String has incompatible type;
      (Note that method string in trait HasString of type ()String is abstract,
      and is therefore overridden by concrete method string in class Object of type ()java.lang.String)
      trait HasString {
          Error:Error:line (10)error: overriding method string in class Object of type ()java.lang.String;
      method string needs `override' modifier
      new HasString { def string = "wut" }
          Error:Error:line (12)error: overriding method string in class Object of type ()java.lang.String;
      method string needs `override' modifier
      new HasString { def string = "okay" }
      

        Issue Links

          Activity

          Hide
          Jason Zaugg added a comment - - edited

          (s/string/blerg/g from the original example)

          During erasure, the compiler lubs the two branches of the if, and ends up calling:

          https://github.com/scala/scala/blob/1d67fe/src/reflect/scala/reflect/internal/Symbols.scala#L1439

          
          // in Type#elimAnonymousClass($anon#10194)
          
          clazz.classBound.asSeenFrom(pre, clazz.owner)
          
          
          // in Symbol#classBound
          
          this       // anonymous class $anon#10194
          
          val tp = refinedType(info.parents, owner) // Object#1815
          val thistp = tp.typeSymbol.thisType       // Object#1815
          info.decls // Scope{
                     //  def <init>#10195(arg$outer#16869: repro.CausesProblems#7101): $anon#10194;
                     //  override def blerg#10196(): String#1899;
                     //  val repro$CausesProblems$$anon$$$outer#11591(): repro.CausesProblems#7101;
                     //  private[this] val $outer#11592: repro.CausesProblems#7101
          
          // Egads!
          addMember(Object#1815, Object#1815, blerg#10196)
          addMember(Object#1815, Object#1815, repro$CausesProblems$$anon$$$outer#11591)
          

          I tracked this down by adding this to Scope#enter:

          
                try {
                  if (e.sym.name.containsName("blerg") && this == definitions.ObjectClass.info.decls) {
                    println("phase = " + phase)
                    println("Entering into: " + System.identityHashCode(this))
                    println("System.identityHashCode(definitions.ObjectClass.info.decls): " + System.identityHashCode(definitions.ObjectClass.info.decls))
                    println("Containing: " + this.map(_.nameString).mkString(","))
                    println("From: " + Thread.currentThread().getStackTrace.take(10).map(_.getMethodName).mkString(" -> "))
                    println("definitions.ObjectClass.info.decl(newTermName(\"blerg\")) = " + definitions.ObjectClass.info.decl(newTermName("blerg")))
                  }
                } catch {
                  case x: Throwable => // ignore
                }
          

          I'm not sure about the right way to avoid this.

          Show
          Jason Zaugg added a comment - - edited (s/string/blerg/g from the original example) During erasure, the compiler lubs the two branches of the if, and ends up calling: https://github.com/scala/scala/blob/1d67fe/src/reflect/scala/reflect/internal/Symbols.scala#L1439 // in Type#elimAnonymousClass($anon#10194) clazz.classBound.asSeenFrom(pre, clazz.owner) // in Symbol#classBound this // anonymous class $anon#10194 val tp = refinedType(info.parents, owner) // Object#1815 val thistp = tp.typeSymbol.thisType // Object#1815 info.decls // Scope{ // def <init>#10195(arg$outer#16869: repro.CausesProblems#7101): $anon#10194; // override def blerg#10196(): String#1899; // val repro$CausesProblems$$anon$$$outer#11591(): repro.CausesProblems#7101; // private[this] val $outer#11592: repro.CausesProblems#7101 // Egads! addMember(Object#1815, Object#1815, blerg#10196) addMember(Object#1815, Object#1815, repro$CausesProblems$$anon$$$outer#11591) I tracked this down by adding this to Scope#enter : try { if (e.sym.name.containsName("blerg") && this == definitions.ObjectClass.info.decls) { println("phase = " + phase) println("Entering into: " + System.identityHashCode(this)) println("System.identityHashCode(definitions.ObjectClass.info.decls): " + System.identityHashCode(definitions.ObjectClass.info.decls)) println("Containing: " + this.map(_.nameString).mkString(",")) println("From: " + Thread.currentThread().getStackTrace.take(10).map(_.getMethodName).mkString(" -> ")) println("definitions.ObjectClass.info.decl(newTermName(\"blerg\")) = " + definitions.ObjectClass.info.decl(newTermName("blerg"))) } } catch { case x: Throwable => // ignore } I'm not sure about the right way to avoid this.
          Hide
          Jason Zaugg added a comment -
          Show
          Jason Zaugg added a comment - Here's the advent of addMember within classBound . https://issues.scala-lang.org/browse/SI-438 https://github.com/scala/scala/commit/d3a71dbd8#L0L641
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/pull/802

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Ryan Hendrickson
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development