From 8f020bb6632d5d68e169f8caa7d9cbc1bc819d35 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 7 May 2015 11:32:35 +0200 Subject: [PATCH 01/16] Fix #536 - only load member classes of classes that are currently compiled. It seems wasteful to load the member classes even of classes that are not currently compiled. It also makes us vulnerable to any misinterpretation of Java file formats. In th particular case of #536, we parsed a class an anonymous Collection$1 which was referring to the type parameter of its enclosing class, but was not diagnosed as an inner class of the enclosing class. --- .../backend/jvm/DottyBackendInterface.scala | 20 +++++++++++++++++-- src/dotty/tools/dotc/core/Phases.scala | 2 ++ tests/pos/i536.scala | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i536.scala diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index dc6752460488..7a510857d020 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -678,8 +678,24 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ // members def primaryConstructor: Symbol = toDenot(sym).primaryConstructor - def nestedClasses: List[Symbol] = memberClasses //exitingPhase(currentRun.lambdaliftPhase)(sym.memberClasses) - def memberClasses: List[Symbol] = toDenot(sym).info.memberClasses.map(_.symbol).toList + + /** For currently compiled classes: All locally defined classes including local classes. + * The empty list for classes that are not currently compiled. + */ + def nestedClasses: List[Symbol] = localClasses(ctx.flattenPhase) + + /** For currently compiled classes: All classes that are declared as members of this class + * (but not inherited ones). The empty list for classes that are not currently compiled. + */ + def memberClasses: List[Symbol] = localClasses(ctx.lambdaLiftPhase) + + private def localClasses(phase: Phase) = + if (sym.isDefinedInCurrentRun) + ctx.atPhase(phase) { implicit ctx => + toDenot(sym).info.decls.filter(_.isClass).toList + } + else Nil + def annotations: List[Annotation] = Nil def companionModuleMembers: List[Symbol] = { // phase travel to exitingPickler: this makes sure that memberClassesOf only sees member classes, diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 406a3457a0eb..e0496185ed8e 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -235,6 +235,7 @@ object Phases { private val extensionMethodsCache = new PhaseCache(classOf[ExtensionMethods]) private val erasureCache = new PhaseCache(classOf[Erasure]) private val patmatCache = new PhaseCache(classOf[PatternMatcher]) + private val lambdaLiftCache = new PhaseCache(classOf[LambdaLift]) private val flattenCache = new PhaseCache(classOf[Flatten]) private val explicitOuterCache = new PhaseCache(classOf[ExplicitOuter]) private val gettersCache = new PhaseCache(classOf[Getters]) @@ -245,6 +246,7 @@ object Phases { def extensionMethodsPhase = extensionMethodsCache.phase def erasurePhase = erasureCache.phase def patmatPhase = patmatCache.phase + def lambdaLiftPhase = lambdaLiftCache.phase def flattenPhase = flattenCache.phase def explicitOuterPhase = explicitOuterCache.phase def gettersPhase = gettersCache.phase diff --git a/tests/pos/i536.scala b/tests/pos/i536.scala new file mode 100644 index 000000000000..db9fb9b389c4 --- /dev/null +++ b/tests/pos/i536.scala @@ -0,0 +1,3 @@ +object Max { + java.util.Collections.max(null) +} From 7481babc3c5d72b2f86fdb50c043a608ad4f8dc0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 7 May 2015 11:34:47 +0200 Subject: [PATCH 02/16] Make isTerm/isType not force the denotation of a symbol to be up-to-date. Symbols never change betwene terms and types. So we do not need to the current denotation to decide what they are. Less forcing -> less potential for cyclic references. --- src/dotty/tools/dotc/core/Symbols.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 94ac258daf6e..f7d74d73e220 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -406,8 +406,8 @@ object Symbols { } /** Subclass tests and casts */ - final def isTerm(implicit ctx: Context): Boolean = denot.isTerm - final def isType(implicit ctx: Context): Boolean = denot.isType + final def isTerm(implicit ctx: Context): Boolean = lastDenot.isTerm + final def isType(implicit ctx: Context): Boolean = lastDenot.isType final def isClass: Boolean = isInstanceOf[ClassSymbol] final def asTerm(implicit ctx: Context): TermSymbol = { assert(isTerm, s"asTerm called on not-a-Term $this" ); asInstanceOf[TermSymbol] } From f1d4e8494b2a345ed165ae75077b72fa7c4e6161 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 7 May 2015 11:38:39 +0200 Subject: [PATCH 03/16] Rename localClasses -> definedClasses --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 7a510857d020..ef293db653c1 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -682,14 +682,14 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ /** For currently compiled classes: All locally defined classes including local classes. * The empty list for classes that are not currently compiled. */ - def nestedClasses: List[Symbol] = localClasses(ctx.flattenPhase) + def nestedClasses: List[Symbol] = definedClasses(ctx.flattenPhase) /** For currently compiled classes: All classes that are declared as members of this class * (but not inherited ones). The empty list for classes that are not currently compiled. */ - def memberClasses: List[Symbol] = localClasses(ctx.lambdaLiftPhase) + def memberClasses: List[Symbol] = definedClasses(ctx.lambdaLiftPhase) - private def localClasses(phase: Phase) = + private def definedClasses(phase: Phase) = if (sym.isDefinedInCurrentRun) ctx.atPhase(phase) { implicit ctx => toDenot(sym).info.decls.filter(_.isClass).toList From 10610cbc65cce2e5056b8606968c738532e55bfd Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Fri, 8 May 2015 13:32:28 +0200 Subject: [PATCH 04/16] Make isTerm/isType not force the denotation of a symbols defined in this run. See discussion in #544 --- src/dotty/tools/dotc/core/Symbols.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index f7d74d73e220..14acf26f5e6c 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -406,8 +406,12 @@ object Symbols { } /** Subclass tests and casts */ - final def isTerm(implicit ctx: Context): Boolean = lastDenot.isTerm - final def isType(implicit ctx: Context): Boolean = lastDenot.isType + final def isTerm(implicit ctx: Context): Boolean = + (if(isDefinedInCurrentRun) lastDenot else denot).isTerm + + final def isType(implicit ctx: Context): Boolean = + (if(isDefinedInCurrentRun) lastDenot else denot).isType + final def isClass: Boolean = isInstanceOf[ClassSymbol] final def asTerm(implicit ctx: Context): TermSymbol = { assert(isTerm, s"asTerm called on not-a-Term $this" ); asInstanceOf[TermSymbol] } From 1f1359349787b571a3c1b1d570548f71da8a767f Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 5 May 2015 22:18:46 +0200 Subject: [PATCH 05/16] Drop the requirement that extractors with `get` must implement Product We used to require that the result type of an extractor `get` is a product, or else the type of the `get` itself would be taken as the result type of the unapply. This is now relaxed so that we automatically select with _1, _2, ... as soon as there are multiple argument patterns, and (1) the result type is not a Seq, (2) the number of consecutive product conselectors matches the number of arguments. --- src/dotty/tools/dotc/typer/Applications.scala | 10 ++++-- tests/pos/extractors.scala | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/pos/extractors.scala diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 7a826fee8eaa..ce181c0cc951 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -51,9 +51,12 @@ object Applications { sels.takeWhile(_.exists).toList } - def getUnapplySelectors(tp: Type, args:List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = - if (defn.isProductSubType(tp) && args.length > 1) productSelectorTypes(tp, pos) - else tp :: Nil + def getUnapplySelectors(tp: Type, args: List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = + if (args.length > 1 && !(tp.derivesFrom(defn.SeqClass))) { + val sels = productSelectorTypes(tp, pos) + if (sels.length == args.length) sels + else tp :: Nil + } else tp :: Nil def unapplyArgs(unapplyResult: Type, unapplyFn:Tree, args:List[untpd.Tree], pos: Position = NoPosition)(implicit ctx: Context): List[Type] = { @@ -747,6 +750,7 @@ trait Applications extends Compatibility { self: Typer => case _ => args } if (argTypes.length != bunchedArgs.length) { + println(argTypes) ctx.error(d"wrong number of argument patterns for $qual; expected: ($argTypes%, %)", tree.pos) argTypes = argTypes.take(args.length) ++ List.fill(argTypes.length - args.length)(WildcardType) diff --git a/tests/pos/extractors.scala b/tests/pos/extractors.scala new file mode 100644 index 000000000000..8e5b0e9d2b68 --- /dev/null +++ b/tests/pos/extractors.scala @@ -0,0 +1,32 @@ +object test { + + class Tree + class Apply(val fun: Tree, val args: List[Tree]) extends Tree + + trait DeconstructorCommon[T >: Null <: AnyRef] { + var field: T = null + def get: this.type = this + def isEmpty: Boolean = field eq null + def isDefined = !isEmpty + def unapply(s: T): this.type ={ + field = s + this + } + } + + trait ApplyDeconstructor extends DeconstructorCommon[Apply] { + def _1: Tree + def _2: List[Tree] + } + + object Apply extends ApplyDeconstructor { + def _1: Tree = field.fun + def _2: List[Tree] = field.args + } + + def assocsFromApply(tree: Tree) = { + tree match { + case Apply(fun, args) => ??? + } + } +} From 2350f4d5db9fc20acedf784bc57fac33a6b27805 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 5 May 2015 22:41:16 +0200 Subject: [PATCH 06/16] Remove debug println --- src/dotty/tools/dotc/typer/Applications.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index ce181c0cc951..fec6482b8d41 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -750,7 +750,6 @@ trait Applications extends Compatibility { self: Typer => case _ => args } if (argTypes.length != bunchedArgs.length) { - println(argTypes) ctx.error(d"wrong number of argument patterns for $qual; expected: ($argTypes%, %)", tree.pos) argTypes = argTypes.take(args.length) ++ List.fill(argTypes.length - args.length)(WildcardType) From 66899f85cdeedf823da3f45c2ef0a55ccd6c3d99 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Sun, 3 May 2015 19:37:43 +0200 Subject: [PATCH 07/16] Do not use deprecated procedure syntax in GenBCode. --- .../backend/jvm/DottyBackendInterface.scala | 17 ++++++++++------ src/dotty/tools/backend/jvm/GenBCode.scala | 20 +++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index ef293db653c1..1f70e1bd3070 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -230,7 +230,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ private def emitArgument(av: AnnotationVisitor, name: String, - arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = { (arg: @unchecked) match { case Literal(const @ Constant(_)) => @@ -296,7 +296,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } } - override def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + override def emitAnnotations(cw: asm.ClassVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers) + (innerClasesStore: bcodeStore.BCInnerClassGen) = { for(annot <- annotations; if shouldEmitAnnotation(annot)) { val typ = annot.atp val assocs = annot.assocs @@ -305,14 +306,16 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } } - private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers) + (innerClasesStore: bcodeStore.BCInnerClassGen) = { for ((name, value) <- assocs) { emitArgument(av, name.toString(), value.asInstanceOf[Tree], bcodeStore)(innerClasesStore) } av.visitEnd() } - override def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + override def emitAnnotations(mw: asm.MethodVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers) + (innerClasesStore: bcodeStore.BCInnerClassGen) = { for(annot <- annotations; if shouldEmitAnnotation(annot)) { val typ = annot.atp val assocs = annot.assocs @@ -321,7 +324,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } } - override def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + override def emitAnnotations(fw: asm.FieldVisitor, annotations: List[Annotation], bcodeStore: BCodeHelpers) + (innerClasesStore: bcodeStore.BCInnerClassGen) = { for(annot <- annotations; if shouldEmitAnnotation(annot)) { val typ = annot.atp val assocs = annot.assocs @@ -330,7 +334,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ } } - override def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]], bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen) { + override def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[Annotation]], bcodeStore: BCodeHelpers) + (innerClasesStore: bcodeStore.BCInnerClassGen): Unit = { val annotationss = pannotss map (_ filter shouldEmitAnnotation) if (annotationss forall (_.isEmpty)) return for ((annots, idx) <- annotationss.zipWithIndex; diff --git a/src/dotty/tools/backend/jvm/GenBCode.scala b/src/dotty/tools/backend/jvm/GenBCode.scala index 22184388146f..d7557acecb10 100644 --- a/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/src/dotty/tools/backend/jvm/GenBCode.scala @@ -116,7 +116,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter val caseInsensitively = scala.collection.mutable.Map.empty[String, Symbol] - def run() { + def run(): Unit = { while (true) { val item = q1.poll if (item.isPoison) { @@ -140,7 +140,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter * enqueues them in queue-2. * */ - def visit(item: Item1) { + def visit(item: Item1) = { val Item1(arrivalPos, cd, cunit) = item val claszSymbol = cd.symbol @@ -218,7 +218,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter /*BackendStats.timed(BackendStats.methodOptTimer)*/(localOpt.methodOptimizations(classNode)) } - def run() { + def run(): Unit = { while (true) { val item = q2.poll if (item.isPoison) { @@ -238,7 +238,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } } - private def addToQ3(item: Item2) { + private def addToQ3(item: Item2) = { def getByteArray(cn: asm.tree.ClassNode): Array[Byte] = { val cw = new CClassWriter(extraProc) @@ -277,7 +277,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter * (c) tear down (closing the classfile-writer and clearing maps) * */ - def run(t: Tree) { + def run(t: Tree) = { this.tree = t // val bcodeStart = Statistics.startTimer(BackendStats.bcodeTimer) @@ -321,7 +321,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter * (c) dequeue one at a time from queue-2, convert it to byte-array, place in queue-3 * (d) serialize to disk by draining queue-3. */ - private def buildAndSendToDisk(needsOutFolder: Boolean) { + private def buildAndSendToDisk(needsOutFolder: Boolean) = { feedPipeline1() // val genStart = Statistics.startTimer(BackendStats.bcodeGenStat) @@ -337,8 +337,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } /* Feed pipeline-1: place all ClassDefs on q1, recording their arrival position. */ - private def feedPipeline1() { - def gen(tree: Tree) { + private def feedPipeline1() = { + def gen(tree: Tree): Unit = { tree match { case EmptyTree => () case PackageDef(_, stats) => stats foreach gen @@ -353,9 +353,9 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter } /* Pipeline that writes classfile representations to disk. */ - private def drainQ3() { + private def drainQ3() = { - def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile) { + def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile): Unit = { if (cfr != null){ val SubItem3(jclassName, jclassBytes) = cfr try { From 918cea1e9f7e93d0a5263a1fff073cc2d704a323 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Sun, 3 May 2015 19:38:35 +0200 Subject: [PATCH 08/16] Compile Dotty including runtime and utils. --- test/dotc/tests.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 0e86303a2c2a..4dc3c70d6a23 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -37,11 +37,11 @@ class tests extends CompilerTest { val negDir = testsDir + "neg/" val newDir = testsDir + "new/" - val dottyDir = "./src/dotty/" - val toolsDir = dottyDir + "tools/" - val dotcDir = toolsDir + "dotc/" - val coreDir = dotcDir + "core/" - + val sourceDir = "./src/" + val dottyDir = sourceDir + "dotty/" + val toolsDir = dottyDir + "tools/" + val dotcDir = toolsDir + "dotc/" + val coreDir = dotcDir + "core/" @Test def pickle_pickleOK = compileDir(testsDir, "pickling", testPickling) @Test def pickle_pickling = compileDir(coreDir, "pickling", testPickling) @Test def pickle_ast = compileDir(dotcDir, "ast", testPickling) @@ -135,8 +135,8 @@ class tests extends CompilerTest { @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) - @Test def dotc = compileDir(toolsDir, "dotc", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument + @Test def dotty = compileDir(sourceDir, "", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument @Test def dotc_ast = compileDir(dotcDir, "ast") @Test def dotc_config = compileDir(dotcDir, "config") @Test def dotc_core = compileDir(dotcDir, "core")("-Yno-double-bindings" :: allowDeepSubtypes)// twice omitted to make tests run faster From f15e9b2bd1ee0ade14216582f1726028a3dca8df Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Sun, 3 May 2015 19:42:25 +0200 Subject: [PATCH 09/16] Data race in typer: seems due to presence of DottyPredef both on class path and in compiled source. [error] Test dotc.tests.dotty failed: java.lang.AssertionError: assertion failed: data race? overwriting symbol of dotty.DottyPredef$ / TypeRef(ThisType(TypeRef(NoPrefix,dotty)),DottyPredef$) / class dotty.tools.dotc.core.Types$CachedTypeRef / 9007 / 9748, took 1.276 sec [error] at scala.Predef$.assert(Predef.scala:165) [error] at dotty.tools.dotc.core.Types$NamedType.checkSymAssign(Types.scala:1263) [error] at dotty.tools.dotc.core.Types$NamedType.setDenot(Types.scala:1293) [error] at dotty.tools.dotc.core.Types$NamedType.withDenot(Types.scala:1286) [error] at dotty.tools.dotc.core.Types$TypeRef$.apply(Types.scala:1669) [error] at dotty.tools.dotc.core.Types$Type.select(Types.scala:819) [error] at dotty.tools.dotc.typer.Namer.moduleValSig(Namer.scala:602) [error] at dotty.tools.dotc.typer.Namer$Completer.typeSig(Namer.scala:465) [error] at dotty.tools.dotc.typer.Namer$Completer.completeInCreationContext(Namer.scala:499) [error] at dotty.tools.dotc.typer.Namer$Completer.complete(Namer.scala:495) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.completeFrom(SymDenotations.scala:161) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.info(SymDenotations.scala:143) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.ensureCompleted(SymDenotations.scala:253) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.flags(SymDenotations.scala:97) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.is(SymDenotations.scala:119) [error] at dotty.tools.dotc.core.SymDenotations$SymDenotation.isStable(SymDenotations.scala:464) [error] at dotty.tools.dotc.core.Types$Type.widenIfUnstable(Types.scala:691) [error] at dotty.tools.dotc.core.Types$Type$$anonfun$member$1.apply(Types.scala:394) [error] at dotty.tools.dotc.core.Types$Type$$anonfun$member$1.apply(Types.scala:394) [error] at dotty.tools.dotc.util.Stats$.track(Stats.scala:35) [error] at dotty.tools.dotc.core.Types$Type.member(Types.scala:393) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedIdent$1.wildImportRef$1(Typer.scala:192) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedIdent$1.findRef$1(Typer.scala:240) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedIdent$1.apply(Typer.scala:263) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedIdent$1.apply(Typer.scala:79) [error] at dotty.tools.dotc.util.Stats$.track(Stats.scala:35) [error] at dotty.tools.dotc.typer.Typer.typedIdent(Typer.scala:79) [error] at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:1017) [error] at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1076) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typed$2.apply(Typer.scala:1088) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typed$2.apply(Typer.scala:1086) [error] at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:147) [error] at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:51) [error] at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1086) [error] at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1125) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedPackageDef$1.apply(Typer.scala:961) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typedPackageDef$1.apply(Typer.scala:960) [error] at dotty.tools.dotc.util.Stats$.track(Stats.scala:35) [error] at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:960) [error] at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:1066) [error] at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:1078) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typed$2.apply(Typer.scala:1088) [error] at dotty.tools.dotc.typer.Typer$$anonfun$typed$2.apply(Typer.scala:1086) [error] at dotty.tools.dotc.reporting.Reporting$class.traceIndented(Reporter.scala:147) [error] at dotty.tools.dotc.core.Contexts$Context.traceIndented(Contexts.scala:51) [error] at dotty.tools.dotc.typer.Typer.typed(Typer.scala:1086) [error] at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:1125) [error] at dotty.tools.dotc.typer.FrontEnd$$anonfun$typeCheck$1.apply$mcV$sp(FrontEnd.scala:41) [error] at dotty.tools.dotc.typer.FrontEnd.monitor(FrontEnd.scala:18) [error] at dotty.tools.dotc.typer.FrontEnd.typeCheck(FrontEnd.scala:39) [error] at dotty.tools.dotc.typer.FrontEnd$$anonfun$runOn$3.apply(FrontEnd.scala:52) [error] at dotty.tools.dotc.typer.FrontEnd$$anonfun$runOn$3.apply(FrontEnd.scala:52) [error] at scala.collection.immutable.List.foreach(List.scala:381) [error] at dotty.tools.dotc.typer.FrontEnd.runOn(FrontEnd.scala:52) [error] at dotty.tools.dotc.Run$$anonfun$compileSources$1$$anonfun$apply$mcV$sp$3.apply(Run.scala:55) [error] at dotty.tools.dotc.Run$$anonfun$compileSources$1$$anonfun$apply$mcV$sp$3.apply(Run.scala:52) [error] at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) [error] at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) [error] at dotty.tools.dotc.Run$$anonfun$compileSources$1.apply$mcV$sp(Run.scala:52) [error] at dotty.tools.dotc.Run$$anonfun$compileSources$1.apply(Run.scala:47) [error] at dotty.tools.dotc.Run$$anonfun$compileSources$1.apply(Run.scala:47) [error] at dotty.tools.dotc.util.Stats$.monitorHeartBeat(Stats.scala:68) [error] at dotty.tools.dotc.Run.compileSources(Run.scala:46) [error] at dotty.tools.dotc.Run.compile(Run.scala:33) [error] at dotty.tools.dotc.Driver.doCompile(Driver.scala:20) [error] at dotty.tools.dotc.Bench$.dotty$tools$dotc$Bench$$super$doCompile(Bench.scala:38) [error] at dotty.tools.dotc.Bench$$anonfun$doCompile$1.apply(Bench.scala:38) [error] at dotty.tools.dotc.Bench$$anonfun$doCompile$1.apply(Bench.scala:36) [error] at dotty.tools.dotc.Bench$$anonfun$ntimes$1.apply(Bench.scala:30) [error] at dotty.tools.dotc.Bench$$anonfun$ntimes$1.apply(Bench.scala:30) [error] at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:142) [error] at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:142) [error] at scala.collection.immutable.Range.foreach(Range.scala:166) [error] at scala.collection.TraversableOnce$class.foldLeft(TraversableOnce.scala:142) [error] at scala.collection.AbstractTraversable.foldLeft(Traversable.scala:104) [error] at scala.collection.TraversableOnce$class.$div$colon(TraversableOnce.scala:136) [error] at scala.collection.AbstractTraversable.$div$colon(Traversable.scala:104) [error] at dotty.tools.dotc.Bench$.ntimes(Bench.scala:30) [error] at dotty.tools.dotc.Bench$.doCompile(Bench.scala:36) [error] at dotty.tools.dotc.Driver.process(Driver.scala:31) [error] at dotty.tools.dotc.Bench$.dotty$tools$dotc$Bench$$super$process(Bench.scala:53) [error] at dotty.tools.dotc.Bench$$anonfun$process$1.apply(Bench.scala:53) [error] at dotty.tools.dotc.Bench$$anonfun$process$1.apply(Bench.scala:53) [error] at dotty.tools.dotc.Bench$$anonfun$ntimes$1.apply(Bench.scala:30) [error] at dotty.tools.dotc.Bench$$anonfun$ntimes$1.apply(Bench.scala:30) [error] at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:142) [error] at scala.collection.TraversableOnce$$anonfun$foldLeft$1.apply(TraversableOnce.scala:142) [error] at scala.collection.immutable.Range.foreach(Range.scala:166) [error] at scala.collection.TraversableOnce$class.foldLeft(TraversableOnce.scala:142) [error] at scala.collection.AbstractTraversable.foldLeft(Traversable.scala:104) [error] at scala.collection.TraversableOnce$class.$div$colon(TraversableOnce.scala:136) [error] at scala.collection.AbstractTraversable.$div$colon(Traversable.scala:104) [error] at dotty.tools.dotc.Bench$.ntimes(Bench.scala:30) [error] at dotty.tools.dotc.Bench$.process(Bench.scala:53) [error] at test.CompilerTest.compileArgs(CompilerTest.scala:159) [error] at test.CompilerTest.compileDir(CompilerTest.scala:104) [error] at dotc.tests.dotty(tests.scala:141) --- test/dotc/tests.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 4dc3c70d6a23..753a3a6c4591 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -42,6 +42,7 @@ class tests extends CompilerTest { val toolsDir = dottyDir + "tools/" val dotcDir = toolsDir + "dotc/" val coreDir = dotcDir + "core/" +/* @Test def pickle_pickleOK = compileDir(testsDir, "pickling", testPickling) @Test def pickle_pickling = compileDir(coreDir, "pickling", testPickling) @Test def pickle_ast = compileDir(dotcDir, "ast", testPickling) @@ -134,9 +135,9 @@ class tests extends CompilerTest { @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) - - +*/ @Test def dotty = compileDir(sourceDir, "", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument +/* @Test def dotc_ast = compileDir(dotcDir, "ast") @Test def dotc_config = compileDir(dotcDir, "config") @Test def dotc_core = compileDir(dotcDir, "core")("-Yno-double-bindings" :: allowDeepSubtypes)// twice omitted to make tests run faster @@ -177,6 +178,6 @@ class tests extends CompilerTest { ), List(/* "-Ylog:frontend", */ "-Xprompt") ++ staleSymbolError ++ twice) val javaDir = "./tests/pos/java-interop/" - @Test def java_all = compileFiles(javaDir, twice) + @Test def java_all = compileFiles(javaDir, twice)*/ //@Test def dotc_compilercommand = compileFile(dotcDir + "config/", "CompilerCommand") } From 38e4f578a68ede3f246484ad9f0354c21fe9015e Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Tue, 5 May 2015 15:36:33 +0200 Subject: [PATCH 10/16] Address some of dotty deviations in backend. Implicit vals need explicit type, anonymous classes are widened. --- src/dotty/tools/backend/jvm/LabelDefs.scala | 2 +- src/dotty/tools/backend/jvm/scalaPrimitives.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/backend/jvm/LabelDefs.scala b/src/dotty/tools/backend/jvm/LabelDefs.scala index 8f9e3bdcca2f..371396e3681b 100644 --- a/src/dotty/tools/backend/jvm/LabelDefs.scala +++ b/src/dotty/tools/backend/jvm/LabelDefs.scala @@ -164,7 +164,7 @@ class LabelDefs extends MiniPhaseTransform { } } - val collectLabelDefs = new TreeMap() { + object collectLabelDefs extends TreeMap() { // label calls from this DefDef var parentLabelCalls: mutable.Set[Tree] = new mutable.HashSet[Tree]() diff --git a/src/dotty/tools/backend/jvm/scalaPrimitives.scala b/src/dotty/tools/backend/jvm/scalaPrimitives.scala index 857a92d21407..8e742faf1952 100644 --- a/src/dotty/tools/backend/jvm/scalaPrimitives.scala +++ b/src/dotty/tools/backend/jvm/scalaPrimitives.scala @@ -125,7 +125,7 @@ class DottyPrimitives(ctx: Context) { /** Initialize the primitive map */ private def init: immutable.Map[Symbol, Int] = { - implicit val ctx = this.ctx + implicit val ctx: Context = this.ctx import core.Symbols.defn val primitives = new mutable.HashMap[Symbol, Int]() From 1838eb04314f30afd74d7ce1bce61ff08989786b Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Tue, 5 May 2015 15:37:48 +0200 Subject: [PATCH 11/16] Do not try to compile dotty runtime yet. Problems with DottyPredef. --- test/dotc/tests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 753a3a6c4591..512cad90ef7b 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -136,7 +136,7 @@ class tests extends CompilerTest { @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) */ - @Test def dotty = compileDir(sourceDir, "", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument + @Test def dotty = compileDir(toolsDir, "", "-deep" :: allowDeepSubtypes ++ twice) // note the -deep argument /* @Test def dotc_ast = compileDir(dotcDir, "ast") @Test def dotc_config = compileDir(dotcDir, "config") From ff091be1075911d5979d7b34ebcec7153eb5486e Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 6 May 2015 17:03:33 +0200 Subject: [PATCH 12/16] Workaround dotty deviation in for loop patterns. --- .../tools/backend/jvm/DottyBackendInterface.scala | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 1f70e1bd3070..7795f3b95fb9 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -308,8 +308,12 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ private def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, Object)], bcodeStore: BCodeHelpers) (innerClasesStore: bcodeStore.BCInnerClassGen) = { - for ((name, value) <- assocs) { - emitArgument(av, name.toString(), value.asInstanceOf[Tree], bcodeStore)(innerClasesStore) + //for ((name, value) <- assocs) { // dotty deviation, does not work + + for (nv <- assocs) { + val name = nv._1 + val value = nv._2 + emitArgument(av, name.toString, value.asInstanceOf[Tree], bcodeStore)(innerClasesStore) } av.visitEnd() } @@ -802,7 +806,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ def primitiveOrClassToBType(sym: Symbol): BType = { assert(sym.isClass, sym) assert(sym != ArrayClass || isCompilingArray, sym) - primitiveTypeMap.getOrElse(sym, storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol])) + primitiveTypeMap.getOrElse(sym.asInstanceOf[ct.bTypes.coreBTypes.bTypes.int.Symbol], + storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol])).asInstanceOf[BType] } /** @@ -811,7 +816,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ */ def nonClassTypeRefToBType(sym: Symbol): ClassBType = { assert(sym.isType && isCompilingArray, sym) - ObjectReference + ObjectReference.asInstanceOf[ct.bTypes.ClassBType] } tp.widenDealias match { @@ -856,7 +861,7 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ "If possible, please file a bug on issues.scala-lang.org.") tp match { - case ThisType(ArrayClass) => ObjectReference // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test + case ThisType(ArrayClass) => ObjectReference.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test case ThisType(sym) => storage.getClassBTypeAndRegisterInnerClass(sym.asInstanceOf[ct.int.Symbol]) // case t: SingletonType => primitiveOrClassToBType(t.classSymbol) case t: SingletonType => t.underlying.toTypeKind(ct)(storage) From ebe3290f487b12cf4778c5affeeb42324cd5fbc6 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 6 May 2015 17:49:10 +0200 Subject: [PATCH 13/16] Remove NonExistentTree. --- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 7795f3b95fb9..4aa2e75dd115 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -33,7 +33,6 @@ import StdNames.nme import NameOps._ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ - trait NonExistentTree extends tpd.Tree type Symbol = Symbols.Symbol type Type = Types.Type type Tree = tpd.Tree @@ -68,8 +67,8 @@ class DottyBackendInterface()(implicit ctx: Context) extends BackendInterface{ type Modifiers = tpd.Modifiers type Annotation = Annotations.Annotation type ArrayValue = tpd.JavaSeqLiteral - type ApplyDynamic = NonExistentTree - type ModuleDef = NonExistentTree + type ApplyDynamic = Null + type ModuleDef = Null type LabelDef = tpd.DefDef type Closure = tpd.Closure From 1206a813e8550cb49ebc3fbcc1de51c6daa3eadd Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 6 May 2015 17:49:39 +0200 Subject: [PATCH 14/16] PatternMatcher: fix bug with undefined variable inside huge patterns. --- src/dotty/tools/dotc/transform/PatternMatcher.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala index 0a019e1c59f5..b1140a144a90 100644 --- a/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -464,7 +464,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans // all potentially stored subpat binders val potentiallyStoredBinders = stored.unzip._1.toSet // compute intersection of all symbols in the tree `in` and all potentially stored subpat binders - new DeepFolder[Unit]((x: Unit, t:Tree) => if (potentiallyStoredBinders(t.symbol)) usedBinders += t.symbol).apply((), in) + new DeepFolder[Unit]((x: Unit, t:Tree) => + if (potentiallyStoredBinders(t.symbol)) usedBinders += t.symbol).apply((), in) if (usedBinders.isEmpty) in else { @@ -1440,9 +1441,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans // require (nbSubPats > 0 && (!lastIsStar || isSeq)) protected def subPatRefs(binder: Symbol): List[Tree] = { val refs = if (totalArity > 0 && isSeq) subPatRefsSeq(binder) - else if (defn.isProductSubType(binder.info)) productElemsToN(binder, totalArity) + else if (totalArity > 1 && !isSeq) productElemsToN(binder, totalArity) else ref(binder):: Nil - val refsSymbols = refs.map(_.symbol) // just for debugging refs } From 7972f3d6864429dad967b19d0673c403fb80d208 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 7 May 2015 12:16:16 +0200 Subject: [PATCH 15/16] Update scala-compiler fork. Includes fixes to lambas, and no type projections in signatures. --- project/Build.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Build.scala b/project/Build.scala index b395f6f09851..89d79a8af9ff 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -38,7 +38,7 @@ object DottyBuild extends Build { // get reflect and xml onboard libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value, "org.scala-lang.modules" %% "scala-xml" % "1.0.1", - "me.d-d" % "scala-compiler" % "2.11.5-20150416-144435-09c4a520e1", + "me.d-d" % "scala-compiler" % "2.11.5-20150506-175515-8fc7635b56", "org.scala-lang.modules" %% "scala-partest" % "1.0.5" % "test", "jline" % "jline" % "2.12"), From 6edf859c9dae24aa4232110244a8b1119b0c63e0 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 7 May 2015 15:15:54 +0200 Subject: [PATCH 16/16] Reload denotations that are not defined at current phase Up to now a NotDefinedHere exception was thrown if a denotation was not defined at the current phase, but was defined elsewhere in the current run. However, if the denotation is a SingleDenotation or MultiDenotation it is possible that the particular Single- or Multi-Denotation was not computed at the current phase, but the underlying SymDenotation is valid. With the changes in this commit, we reaload the denotation as a second try. --- src/dotty/tools/dotc/core/Denotations.scala | 35 ++++++++++++++----- .../tools/dotc/core/SymDenotations.scala | 5 ++- src/dotty/tools/dotc/core/Types.scala | 5 ++- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 6502c4a400a3..756e0b02d525 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -2,7 +2,7 @@ package dotty.tools package dotc package core -import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation } +import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, NotDefinedHereDenotation } import Contexts.{Context, ContextBase} import Names.{Name, PreName} import Names.TypeName @@ -128,7 +128,17 @@ object Denotations { */ def atSignature(sig: Signature, site: Type = NoPrefix)(implicit ctx: Context): SingleDenotation - /** The variant of this denotation that's current in the given context. */ + /** The variant of this denotation that's current in the given context, or + * `NotDefinedHereDenotation` if this denotation does not exist at current phase, but + * is defined elsewhere in this run. + */ + def currentIfExists(implicit ctx: Context): Denotation + + /** The variant of this denotation that's current in the given context. + * If no such denotation exists: If Mode.FutureDefs is set, the + * denotation with each alternative at its first point of definition, + * otherwise a `NotDefinedHere` exception is thrown. + */ def current(implicit ctx: Context): Denotation /** Is this denotation different from NoDenotation or an ErrorDenotation? */ @@ -349,6 +359,8 @@ object Denotations { final def signature(implicit ctx: Context) = Signature.OverloadedSignature def atSignature(sig: Signature, site: Type)(implicit ctx: Context): SingleDenotation = denot1.atSignature(sig, site) orElse denot2.atSignature(sig, site) + def currentIfExists(implicit ctx: Context): Denotation = + derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists) def current(implicit ctx: Context): Denotation = derivedMultiDenotation(denot1.current, denot2.current) def altsWith(p: Symbol => Boolean): List[SingleDenotation] = @@ -530,7 +542,7 @@ object Denotations { * is brought forward to be valid in the new runId. Otherwise * the symbol is stale, which constitutes an internal error. */ - def current(implicit ctx: Context): SingleDenotation = { + def currentIfExists(implicit ctx: Context): SingleDenotation = { val currentPeriod = ctx.period val valid = myValidFor if (valid.code <= 0) { @@ -593,17 +605,24 @@ object Denotations { //println(s"searching: $cur at $currentPeriod, valid for ${cur.validFor}") cur = cur.nextInRun cnt += 1 - if (cnt > MaxPossiblePhaseId) - if (ctx.mode is Mode.FutureDefsOK) - return current(ctx.withPhase(coveredInterval.firstPhaseId)) - else - throw new NotDefinedHere(demandOutsideDefinedMsg) + if (cnt > MaxPossiblePhaseId) return NotDefinedHereDenotation } cur } } } + def current(implicit ctx: Context): SingleDenotation = { + val d = currentIfExists + if (d ne NotDefinedHereDenotation) d else currentNoDefinedHere + } + + private def currentNoDefinedHere(implicit ctx: Context): SingleDenotation = + if (ctx.mode is Mode.FutureDefsOK) + current(ctx.withPhase(coveredInterval.firstPhaseId)) + else + throw new NotDefinedHere(demandOutsideDefinedMsg) + private def demandOutsideDefinedMsg(implicit ctx: Context): String = s"demanding denotation of $this at phase ${ctx.phase}(${ctx.phaseId}) outside defined interval: defined periods are${definedPeriodsString}" diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 275fb825732c..b93585324283 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1650,7 +1650,7 @@ object SymDenotations { } } - object NoDenotation extends SymDenotation( + class NoDenotation extends SymDenotation( NoSymbol, NoSymbol, "".toTermName, Permanent, NoType) { override def exists = false override def isTerm = false @@ -1660,6 +1660,9 @@ object SymDenotations { validFor = Period.allInRun(NoRunId) // will be brought forward automatically } + val NoDenotation = new NoDenotation + val NotDefinedHereDenotation = new NoDenotation + // ---- Completion -------------------------------------------------------- /** Instances of LazyType are carried by uncompleted symbols. diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 512ddc41aaf8..24f59ee439e0 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1244,7 +1244,10 @@ object Types { } case d => if (d.validFor.runId != ctx.period.runId) loadDenot - else d.current + else { + val newd = d.currentIfExists + if (newd ne NotDefinedHereDenotation) newd else loadDenot + } } if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot") else if (d.exists) {