Skip to content
1 change: 1 addition & 0 deletions scripts/common
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ update() {
git fetch --tags "https://github.com/$1/$2.git"
(git fetch "https://github.com/$1/$2.git" $4 && git checkout -fq FETCH_HEAD) #|| git checkout -fq $4 # || fallback is for local testing on tag
git reset --hard
cd -
}

export LC_ALL=en_US.UTF-8
Expand Down
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class Compiler {
new FunctionalInterfaces),
List(new LambdaLift, // in this mini-phase block scopes are incorrect. No phases that rely on scopes should be here
new Flatten,
new ElimStaticThis,
new RestoreScopes),
List(/*new PrivateToStatic,*/
new ExpandPrivate,
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Thicket(valdef, clsdef)
}

def initValue(tpe: Types.Type)(implicit ctx: Context) = {
def defaultValue(tpe: Types.Type)(implicit ctx: Context) = {
val tpw = tpe.widen

if (tpw isRef defn.IntClass) Literal(Constant(0))
Expand Down
43 changes: 43 additions & 0 deletions src/dotty/tools/dotc/transform/ElimStaticThis.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package dotty.tools.dotc
package transform

import core._
import Contexts.Context
import Flags._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.SymDenotations.SymDenotation
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
import dotty.tools.dotc.core.Types.{ThisType, TermRef}
import Phases.Phase

/** Replace This references to module classes in static methods by global identifiers to the
* corresponding modules.
*/
class ElimStaticThis extends MiniPhaseTransform {
import ast.tpd._
def phaseName: String = "elimStaticThis"

override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Flatten])

override def transformThis(tree: This)(implicit ctx: Context, info: TransformerInfo): Tree =
if (!tree.symbol.is(Package) && ctx.owner.enclosingMethod.is(JavaStatic)) {
assert(tree.symbol.is(ModuleClass))
ref(tree.symbol.sourceModule)
}
else tree

override def transformIdent(tree: tpd.Ident)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
val meth = ctx.owner.enclosingMethod
// We cannot use meth.enclosingClass because it skips other static classes,
// so instead we require this phase to run after Flatten and use meth.owner
if (meth.is(JavaStatic) && meth.owner.is(ModuleClass)) {
tree.tpe match {
case TermRef(thiz: ThisType, _) if (thiz.underlying.typeSymbol == meth.owner) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of .underlying.termSymbol it's simpler to use just .cls.

ref(thiz.underlying.typeSymbol.sourceModule).select(tree.symbol)
case _ => tree
}
}
else tree
}
}
48 changes: 18 additions & 30 deletions src/dotty/tools/dotc/transform/ElimWildcardIdents.scala
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
package dotty.tools.dotc.transform
package dotty.tools.dotc
package transform

import dotty.tools.dotc.transform.TreeTransforms.{TransformerInfo, TreeTransform, TreeTransformer, MiniPhaseTransform}
import dotty.tools.dotc.ast.{untpd, tpd}
import dotty.tools.dotc.core.Contexts.Context
import scala.collection.mutable.ListBuffer
import dotty.tools.dotc.core.{Scopes, Flags}
import dotty.tools.dotc.core.Symbols.NoSymbol
import scala.annotation.tailrec
import dotty.tools.dotc.core._
import TreeTransforms.{MiniPhaseTransform, TransformerInfo}
import ast.tpd
import ast.Trees._
import core._
import Contexts.Context
import Symbols._
import scala.Some
import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
import dotty.tools.dotc.core.Contexts.Context
import scala.collection.mutable
import dotty.tools.dotc.core.Names.Name
import NameOps._
import Types._
import scala.collection.SortedSet
import Decorators._
import StdNames._
import dotty.tools.dotc.util.Positions.Position
import dotty.tools.dotc.config.JavaPlatform

/**
* Replace Ident("_") in tree with default values of corresponding type:
Expand All @@ -29,21 +17,21 @@ import dotty.tools.dotc.config.JavaPlatform
* classes: `null`
*/
class ElimWildcardIdents extends MiniPhaseTransform {
import tpd._
import ast.tpd._
def phaseName: String = "elimWildcardIdents"


override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
def stripBlocks(arg: Tree): Tree = arg match {
case b: Block if b.stats.isEmpty => stripBlocks(b.expr)
case _ => arg
}
val b = stripBlocks(tree.rhs)
b match {
case x: Ident if (x.name == nme.WILDCARD && x.symbol.isClass) =>
tpd.DefDef(tree.symbol.asTerm, tpd.initValue(x.tpe))
def wildcardToDefaultValue(tree: Tree)(implicit ctx: Context) = {
def recur(x: Tree): Tree = x match {
case x: Ident if x.name == nme.WILDCARD && x.symbol.isClass => defaultValue(tree.tpe)
case Block(Nil, y) => recur(y)
case _ => tree
}
recur(tree)
}

override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
cpy.ValDef(tree)(rhs = wildcardToDefaultValue(tree.rhs))

override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
cpy.DefDef(tree)(rhs = wildcardToDefaultValue(tree.rhs))
}
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/transform/LambdaLift.scala
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class LambdaLift extends MiniPhase with IdentityDenotTransformer { thisTransform
val encClass = local.enclosingClass
val topClass = local.topLevelClass
// member of a static object
if (encClass.isStatic && encClass.isContainedIn(topClass)) {
if (encClass.isStatic && encClass.isProperlyContainedIn(topClass)) {
// though the second condition seems weird, it's not true for symbols which are defined in some
// weird combinations of super calls.
(encClass, EmptyFlags)
Expand Down
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/transform/LazyVals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
tpe, coord = x.symbol.coord
).entered

val containerTree = ValDef(containerSymbol, initValue(tpe))
val containerTree = ValDef(containerSymbol, defaultValue(tpe))
if (x.tpe.isNotNull && tpe <:< defn.ObjectType) { // can use 'null' value instead of flag
val slowPath = DefDef(x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, x.rhs))
Thicket(List(containerTree, slowPath))
Expand Down Expand Up @@ -234,7 +234,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
val thiz = This(claz)(ctx.fresh.setOwner(claz))

val resultSymbol = ctx.newSymbol(methodSymbol, lazyNme.result, containerFlags, tp)
val resultDef = ValDef(resultSymbol, initValue(tp))
val resultDef = ValDef(resultSymbol, defaultValue(tp))

val retrySymbol = ctx.newSymbol(methodSymbol, lazyNme.retry, containerFlags, defn.BooleanType)
val retryDef = ValDef(retrySymbol, Literal(Constants.Constant(true)))
Expand Down Expand Up @@ -332,7 +332,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {

val containerName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL).toTermName
val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).entered
val containerTree = ValDef(containerSymbol, initValue(tpe))
val containerTree = ValDef(containerSymbol, defaultValue(tpe))

val offset = ref(companion).ensureApplied.select(offsetSymbol)
val getFlag = Select(ref(helperModule), lazyNme.RLazyVals.get)
Expand Down
1 change: 0 additions & 1 deletion src/dotty/tools/dotc/transform/TraitConstructors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class TraitConstructors extends MiniPhaseTransform with SymTransformer {
import dotty.tools.dotc.ast.tpd._
def phaseName: String = "traitConstructors"


override def treeTransformPhase: Phase = this.phase

def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
Expand Down
14 changes: 13 additions & 1 deletion src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1337,10 +1337,22 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
}

/** Adapt an expression of constant type to a different constant type `tpe`. */
def adaptConstant(tree: Tree, tpe: ConstantType): Tree = {
def lit = Literal(tpe.value).withPos(tree.pos)
tree match {
case Literal(c) => lit
case tree @ Block(stats, expr) => tpd.cpy.Block(tree)(stats, adaptConstant(expr, tpe))
case tree =>
if (isIdempotentExpr(tree)) lit // See discussion in phase Literalize why we demand isIdempotentExpr
else Block(tree :: Nil, lit)
}
}

def adaptToSubType(wtp: Type): Tree = {
// try converting a constant to the target type
val folded = ConstFold(tree, pt)
if (folded ne tree) return folded
if (folded ne tree) return adaptConstant(folded, folded.tpe.asInstanceOf[ConstantType])
// drop type if prototype is Unit
if (pt isRef defn.UnitClass)
return tpd.Block(tree :: Nil, Literal(Constant(())))
Expand Down
2 changes: 1 addition & 1 deletion test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ 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 run_all = runFiles(runDir)

Expand Down
File renamed without changes.
File renamed without changes.
13 changes: 8 additions & 5 deletions tests/run/t5375.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
object Test extends dotty.runtime.LegacyApp {
object Test {
val foos = (1 to 1000).toSeq
try
foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i)
catch {
case ex: RuntimeException => println("Runtime exception")

def main(args: Array[String]): Unit = {
try
foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i)
catch {
case ex: RuntimeException => println("Runtime exception")
}
}
}
10 changes: 6 additions & 4 deletions tests/run/t6052.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@



object Test extends dotty.runtime.LegacyApp {
object Test {
def seqarr(i: Int) = Array[Int]() ++ (0 until i)
def pararr(i: Int) = seqarr(i).par

Expand All @@ -15,7 +15,9 @@ object Test extends dotty.runtime.LegacyApp {
assert(gseq == gpar, (gseq, gpar))
}

for (i <- 0 until 20) check(i, _ > 0)
for (i <- 0 until 20) check(i, _ % 2)
for (i <- 0 until 20) check(i, _ % 4)
def main(args: Array[String]): Unit = {
for (i <- 0 until 20) check(i, _ > 0)
for (i <- 0 until 20) check(i, _ % 2)
for (i <- 0 until 20) check(i, _ % 4)
}
}
1 change: 0 additions & 1 deletion tests/run/t6260-delambdafy.check
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
f(C@2e)

apply
get$Lambda
12 changes: 7 additions & 5 deletions tests/run/t6410.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@



object Test extends dotty.runtime.LegacyApp {
val x = collection.parallel.mutable.ParArray.range(1,10) groupBy { _ % 2 } mapValues { _.size }
println(x)
val y = collection.parallel.immutable.ParVector.range(1,10) groupBy { _ % 2 } mapValues { _.size }
println(y)
object Test {
def main(args: Array[String]): Unit = {
val x = collection.parallel.mutable.ParArray.range(1,10) groupBy { _ % 2 } mapValues { _.size }
println(x)
val y = collection.parallel.immutable.ParVector.range(1,10) groupBy { _ % 2 } mapValues { _.size }
println(y)
}
}
12 changes: 7 additions & 5 deletions tests/run/t6467.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import collection._



object Test extends dotty.runtime.LegacyApp {
object Test {

def compare(s1: String, s2: String): Unit = {
assert(s1 == s2, s1 + "\nvs.\n" + s2)
}

compare(List(1, 2, 3, 4).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234")
compare(List(1, 2, 3, 4).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234")
compare(Seq(0 until 100: _*).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString)
compare(Seq(0 until 100: _*).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString)
def main(args: Array[String]): Unit = {
compare(List(1, 2, 3, 4).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234")
compare(List(1, 2, 3, 4).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234")
compare(Seq(0 until 100: _*).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString)
compare(Seq(0 until 100: _*).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString)
}

}
10 changes: 6 additions & 4 deletions tests/run/t7498.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@



object Test extends dotty.runtime.LegacyApp {
object Test {
import scala.collection.concurrent.TrieMap

class Collision(val idx: Int) {
override def hashCode = idx % 10
}

val tm = TrieMap[Collision, Unit]()
for (i <- 0 until 1000) tm(new Collision(i)) = ()
def main(args: Array[String]): Unit = {
val tm = TrieMap[Collision, Unit]()
for (i <- 0 until 1000) tm(new Collision(i)) = ()

tm.par.foreach(kv => ())
tm.par.foreach(kv => ())
}
}