diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala index 8a6bb15ba89a..7c84e8749fa7 100644 --- a/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -8,7 +8,10 @@ import Symbols._ import Scopes._ import collection.mutable import TreeTransforms.MiniPhaseTransform +import SymDenotations._ import ast.Trees._ +import NameOps._ +import typer.Mode import TreeTransforms.TransformerInfo /** The preceding lambda lift and flatten phases move symbols to different scopes @@ -19,16 +22,32 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t import ast.tpd._ override def phaseName = "restoreScopes" + private def invalidateUndefinedCompanions(pkg: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = { + val otherNames = + if (cls is Flags.Module) + List(cls.name.sourceModuleName, cls.name.stripModuleClassSuffix.toTypeName) + else + List(cls.name.toTermName, cls.name.moduleClassName) + for (otherName <- otherNames) { + val other = pkg.info.decl(otherName).asSymDenotation + if (other.exists && !other.isCompleted) other.markAbsent + } + } + override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = { val TypeDef(_, impl: Template) = tree + // val restoredDecls = newScope for (stat <- impl.constr :: impl.body) if (stat.isInstanceOf[MemberDef] && stat.symbol.exists) restoredDecls.enter(stat.symbol) - val cls = tree.symbol.asClass - cls.owner.asClass.enter(cls) // Enter class in enclosing package scope, in case it was an inner class before flatten. // For top-level classes this does nothing. + val cls = tree.symbol.asClass + val pkg = cls.owner.asClass + pkg.enter(cls) + invalidateUndefinedCompanions(pkg, cls)( + ctx.withPhase(cls.initial.validFor.phaseId).addMode(Mode.FutureDefsOK)) val cinfo = cls.classInfo tree.symbol.copySymDenotation( info = cinfo.derivedClassInfo( // Dotty deviation: Cannot expand cinfo inline without a type error diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 2a1ef08ee4d1..ad79b25ca7cc 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -19,7 +19,6 @@ class tests extends CompilerTest { "-d", "./out/" ) - val doEmitBytecode = List("-Ystop-before:terminal") val failedbyName = List("-Ystop-before:collectEntryPoints") // #288 val failedUnderscore = List("-Ystop-before:collectEntryPoints") // #289 val testPickling = List("-Xprint-types", "-Ytest-pickler", "-Ystop-after:pickler") @@ -145,7 +144,7 @@ class tests extends CompilerTest { @Test def dotc_transform = compileDir(dotcDir + "tools/dotc/transform") - @Test def dotc_parsing = compileDir(dotcDir + "tools/dotc/parsing") + @Test def dotc_parsing = compileDir(dotcDir + "tools/dotc/parsing", failedOther) @Test def dotc_printing = compileDir(dotcDir + "tools/dotc/printing") diff --git a/tests/disabled/t3278.scala b/tests/disabled/t3278.scala new file mode 100644 index 000000000000..d6e7d2581cbc --- /dev/null +++ b/tests/disabled/t3278.scala @@ -0,0 +1,41 @@ +/* Dies with + java.util.NoSuchElementException: key not found: val + at scala.collection.MapLike$class.default(MapLike.scala:228) + at scala.collection.AbstractMap.default(Map.scala:59) + at scala.collection.MapLike$class.apply(MapLike.scala:141) + at scala.collection.AbstractMap.apply(Map.scala:59) + at dotty.tools.dotc.backend.jvm.DottyPrimitives.getPrimitive(scalaPrimitives.scala:46) + at dotty.tools.backend.jvm.DottyBackendInterface$$anon$2.getPrimitive(DottyBackendInterface.scala:157) + at dotty.tools.backend.jvm.DottyBackendInterface$$anon$2.getPrimitive(DottyBackendInterface.scala:153) + at scala.tools.nsc.backend.jvm.BCodeBodyBuilder$PlainBodyBuilder.liftStringConcat(BCodeBodyBuilder.scala:1147) +*/ +class Foo +class Test { + def update[B](x : B, b : Int): Unit = {} + def apply[B](x : B) = 1 +} +class Test2 { + type B = Foo + def update(x : B, b : Int): Unit = {} + def apply(x : B) = 1 +} + +object Test { + def main(a : Array[String]): Unit = { + val a = new Test + val f = new Foo + a(f) = 1 //works + a(f) = a(f) + 1 //works + a(f) += 1 //error: reassignment to val + } +} +object Test2 { + def main(args : Array[String]): Unit = { + args(0) += "a" + val a = new Test2 + val f = new Foo + a(f) = 1 //works + a(f) = a(f) + 1 //works + a(f) += 1 //error: reassignment to val + } +} diff --git a/tests/pos/t3278.scala b/tests/pos/t3278.scala deleted file mode 100644 index 05bfbc1463a5..000000000000 --- a/tests/pos/t3278.scala +++ /dev/null @@ -1,30 +0,0 @@ -class Foo -class Test { - def update[B](x : B, b : Int): Unit = {} - def apply[B](x : B) = 1 -} -class Test2 { - type B = Foo - def update(x : B, b : Int): Unit = {} - def apply(x : B) = 1 -} - -object Test { - def main(a : Array[String]): Unit = { - val a = new Test - val f = new Foo - a(f) = 1 //works - a(f) = a(f) + 1 //works - a(f) += 1 //error: reassignment to val - } -} -object Test2 { - def main(args : Array[String]): Unit = { - args(0) += "a" - val a = new Test2 - val f = new Foo - a(f) = 1 //works - a(f) = a(f) + 1 //works - a(f) += 1 //error: reassignment to val - } -}