Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssertionFailed with implicit class inside package object #7940

Closed
scabug opened this issue Oct 29, 2013 · 11 comments
Closed

AssertionFailed with implicit class inside package object #7940

scabug opened this issue Oct 29, 2013 · 11 comments

Comments

@scabug
Copy link

scabug commented Oct 29, 2013

I had the following code:

package mytest

import scala.concurrent.Future

package object another {

  implicit class FutureOps[A](future: Future[A]) {
    def fold = ""
  }
}

It resulted in a compiler crash (logged on the console). It is non-deterministic, and it probably has to do with an unfortunate ordering of forcing symbols.

2013-10-29 10:50:42,469 DEBUG [main] - ProjectPartListener - open package.scala
[package.scala]: exception during background compile: java.lang.AssertionError: assertion failed: not found: FutureOps in package package Scope{
  def <init>: <?>
}
java.lang.AssertionError: assertion failed: not found: FutureOps in package package Scope{
  def <init>: <?>
}
	at scala.tools.nsc.typechecker.MethodSynthesis$MethodSynth$ImplicitClassWrapper.derivedSym(MethodSynthesis.scala:389)
	at scala.tools.nsc.typechecker.MethodSynthesis$MethodSynth$class.addDerivedTrees(MethodSynthesis.scala:234)
	at scala.tools.nsc.typechecker.Namers$Namer.addDerivedTrees(Namers.scala:55)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$31.apply(Typers.scala:1917)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$31.apply(Typers.scala:1917)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$rewrappingWrapperTrees$1.apply(Typers.scala:1856)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$rewrappingWrapperTrees$1.apply(Typers.scala:1853)
	at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
	at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
	at scala.collection.immutable.List.foreach(List.scala:318)
	at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
	at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
	at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1917)
	at scala.tools.nsc.typechecker.Typers$Typer.typedModuleDef(Typers.scala:1800)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5551)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5609)
	at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:2928)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$60.apply(Typers.scala:3032)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$60.apply(Typers.scala:3032)
	at scala.collection.immutable.List.loop$1(List.scala:170)
	at scala.collection.immutable.List.mapConserve(List.scala:186)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3032)
	at scala.tools.nsc.typechecker.Typers$Typer.typedPackageDef$1(Typers.scala:5268)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5554)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5609)
	at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:2928)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$60.apply(Typers.scala:3032)
	at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$60.apply(Typers.scala:3032)
	at scala.collection.immutable.List.loop$1(List.scala:170)
	at scala.collection.immutable.List.mapConserve(List.scala:186)
	at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3032)
	at scala.tools.nsc.typechecker.Typers$Typer.typedPackageDef$1(Typers.scala:5268)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5554)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5609)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5671)
	at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.apply(Analyzer.scala:99)
	at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:464)
	at scala.tools.nsc.interactive.Global$TyperRun$$anonfun$applyPhase$1.apply(Global.scala:1153)
	at scala.tools.nsc.interactive.Global$TyperRun$$anonfun$applyPhase$1.apply(Global.scala:1153)
	at scala.reflect.internal.SymbolTable.atPhase(SymbolTable.scala:207)
	at scala.tools.nsc.interactive.Global$TyperRun.applyPhase(Global.scala:1153)
	at scala.tools.nsc.interactive.Global$TyperRun.typeCheck(Global.scala:1146)
	at scala.tools.nsc.interactive.Global.scala$tools$nsc$interactive$Global$$typeCheck(Global.scala:585)
	at scala.tools.nsc.interactive.Global$$anonfun$backgroundCompile$5$$anonfun$apply$7.apply(Global.scala:501)
	at scala.tools.nsc.interactive.Global$$anonfun$backgroundCompile$5.apply(Global.scala:497)
	at scala.tools.nsc.interactive.Global$$anonfun$backgroundCompile$5.apply(Global.scala:497)
	at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:772)
	at scala.collection.immutable.List.foreach(List.scala:318)
	at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:771)
	at scala.tools.nsc.interactive.Global.backgroundCompile(Global.scala:497)
	at scala.tools.nsc.interactive.PresentationCompilerThread.run(PresentationCompilerThread.scala:25)
@scabug
Copy link
Author

scabug commented Oct 29, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7940?orig=1
Reporter: @dragos
Affected Versions: 2.10.3

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said:
Affected version?

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@dragos said:
Sorry, missed that field. I just added it. Could it be made a required field?

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said:
I suspect the fromSource condition in the following code might be at play:

  /** if there's a `package` member object in `pkgClass`, enter its members into it. */
  def openPackageModule(pkgClass: Symbol) {

    val pkgModule = pkgClass.info.decl(nme.PACKAGEkw)
    def fromSource = pkgModule.rawInfo match {
      case ltp: SymLoader => ltp.fromSource
      case _ => false
    }
    if (pkgModule.isModule && !fromSource) {
      // println("open "+pkgModule)//DEBUG
      openPackageModule(pkgModule, pkgClass)
    }
  }

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said (edited on Oct 31, 2013 9:23:02 AM UTC):
Reviewing some of the associated code, I think there are one or two bugs in this example:

package p

trait D {
  class C1 { override def toString = "D#C1" }
}
object `package` extends D {
  class C2 { override def toString = "`package`.C2" }
}

class C1 { override def toString = "C1" }

class C2 { override def toString = "C2" }

object Test {
  def main(args: Array[String]) {
    println(new p.C1, new p.C2)
  }
}
% qbin/scalac sandbox/test2.scala && qbin/scala p.Test
(D#C1,`package`.C2)

% qbin/scalac sandbox/test2.scala && qbin/scala p.Test
sandbox/test2.scala:11: error: C1 is already defined as class C1 in package object D
class C1 { override def toString = "C1" }
      ^
sandbox/test2.scala:13: error: C2 is already defined as class C2 in package object p
class C2 { override def toString = "C2" }
      ^
two errors found

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said:
The code that prompted that test:

    // unlink existing symbols in the package
    for (member <- container.info.decls.iterator) {
      if (!member.isPrivate && !member.isConstructor) {
        // todo: handle overlapping definitions in some way: mark as errors
        // or treat as abstractions. For now the symbol in the package module takes precedence.
        for (existing <- dest.info.decl(member.name).alternatives)
          dest.info.decls.unlink(existing)
      }
    }

It only considers the decls of the package object, rather than members.

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said (edited on Oct 31, 2013 9:38:10 AM UTC):
Back to the original report, here's another relevant piece of code:

  object packageObjects extends {
    val global: Analyzer.this.global.type = Analyzer.this.global
  } with SubComponent {
    val phaseName = "packageobjects"
    val runsAfter = List[String]()
    val runsRightAfter= Some("namer")

    def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
      override val checkable = false
      import global._

      val openPackageObjectsTraverser = new Traverser {
        override def traverse(tree: Tree): Unit = tree match {
          case ModuleDef(_, _, _) =>
            if (tree.symbol.name == nme.PACKAGEkw) {
              openPackageModule(tree.symbol, tree.symbol.owner)
            }
          case ClassDef(_, _, _, _) => () // make it fast
          case _ => super.traverse(tree)
        }
      }

      def apply(unit: CompilationUnit) {
        openPackageObjectsTraverser(unit.body)
      }
    }
  }

Does this run as per normal in the presentation compiler? Or, might the compilation unit containing the package object be evade from this phase, only to be later loaded by the presentations compiler's BrowsingLoader?

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@dragos said:
Normally packageobjects runs as usual when the file is open in an editor. However, the BrowsingLoader might see this file earlier if package.scala wasn't open, but the package was used while typechecking something else.

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@retronym said:
Looks like BrowsingLoaders duplicates the code to enter package object class symbols:

        case ModuleDef(_, name, _) =>
          if (packagePrefix == root.fullName) {
            val module = enterModule(root, name.toString, new SourcefileLoader(src))
            entered += 1
            if (name == nme.PACKAGEkw) {
              println("open package module: "+module)
              openPackageModule(module, root)
            }
          } else println("prefixes differ: "+packagePrefix+","+root.fullName)

Do you see the console output: "open package module" in the logs?

@scabug
Copy link
Author

scabug commented Oct 31, 2013

@dragos said:
Yes, it did appear.

@SethTisue
Copy link
Member

this is so old I'm going to provisionally close it without attempting to reproduce it. we can reopen if someone steps forward with evidence it's still relevant

@SethTisue SethTisue closed this as not planned Won't fix, can't repro, duplicate, stale Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants