Skip to content

Add compiler option to use immutable.Seq as the default Seq. #4797

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package ast
import dotty.tools.dotc.transform.{ExplicitOuter, Erasure}
import dotty.tools.dotc.typer.ProtoTypes.FunProtoTyped
import transform.SymUtils._
import transform.TypeUtils._
import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._, NameOps._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Symbols._
Expand Down Expand Up @@ -377,7 +378,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}

/** A tree representing a `newXYZArray` operation of the right
* kind for the given element type in `typeArg`. No type arguments or
* kind for the given element type in `elemTpe`. No type arguments or
* `length` arguments are given.
*/
def newArray(elemTpe: Type, returnTpe: Type, pos: Position, dims: JavaSeqLiteral)(implicit ctx: Context): Tree = {
Expand All @@ -392,6 +393,32 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
newArr.appliedToArgs(clsOf(elemTpe) :: clsOf(returnTpe) :: dims :: Nil).withPos(pos)
}

/** The wrapped array method name for an array of type elemtp */
def wrapArrayMethodName(elemtp: Type)(implicit ctx: Context): TermName = {
val elemCls = elemtp.classSymbol
if (elemCls.isPrimitiveValueClass) nme.wrapXArray(elemCls.name)
else if (elemCls.derivesFrom(defn.ObjectClass) && !elemCls.isNotRuntimeClass) nme.wrapRefArray
else nme.genericWrapArray
}

/** A tree representing a `wrapXYZArray(tree)` operation of the right
* kind for the given element type in `elemTpe`.
*/
def wrapArray(tree: Tree, elemtp: Type)(implicit ctx: Context): Tree = {
val wrapped = ref(defn.ScalaPredefModule)
.select(wrapArrayMethodName(elemtp))
.appliedToTypes(if (elemtp.isPrimitiveValueType) Nil else elemtp :: Nil)
.appliedTo(tree)

if (ctx.settings.YimmutableSeq.value) {
// wrapXYZArray returns a `mutable.Seq`. We need to convert to a `immutable.Seq`.
// TODO: revert once we use the 2.13 standard library and have better
// collections for immutable wrapped arrays (i.e. immutbale.ArraySeq)
wrapped.select(nme.toList)
}
else wrapped
}

// ------ Creating typed equivalents of trees that exist only in untyped form -------

/** new C(args), calling the primary constructor of C */
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class ScalaSettings extends Settings.SettingGroup {
val YcheckAllPatmat = BooleanSetting("-Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm)")
val YretainTrees = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree")
val YshowTreeIds = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.")
val YimmutableSeq = BooleanSetting("-Yimmutable-seq", "Use collection.immutable.Seq as the default Seq type")

val YprofileEnabled = BooleanSetting("-Yprofile-enabled", "Enable profiling.")
val YprofileDestination = StringSetting("-Yprofile-destination", "file", "where to send profiling output - specify a file, default is to the console.", "")
Expand Down
10 changes: 7 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import scala.collection.{ mutable, immutable }
import PartialFunction._
import collection.mutable
import util.common.alwaysZero
import dotty.tools.dotc.transform.TreeGen

object Definitions {

Expand Down Expand Up @@ -347,7 +346,7 @@ class Definitions {
def Predef_undefined(implicit ctx: Context) = Predef_undefinedR.symbol
// The set of all wrap{X, Ref}Array methods, where X is a value type
val Predef_wrapArray = new PerRun[collection.Set[Symbol]]({ implicit ctx =>
val methodNames = ScalaValueTypes.map(TreeGen.wrapArrayMethodName) + nme.wrapRefArray
val methodNames = ScalaValueTypes.map(ast.tpd.wrapArrayMethodName) + nme.wrapRefArray
methodNames.map(ScalaPredefModule.requiredMethodRef(_).symbol)
})

Expand Down Expand Up @@ -401,7 +400,12 @@ class Definitions {
List(AnyClass.typeRef), EmptyScope)
lazy val SingletonType: TypeRef = SingletonClass.typeRef

lazy val SeqType: TypeRef = ctx.requiredClassRef("scala.collection.Seq")
lazy val SeqType: TypeRef = {
val fullName =
if (ctx.settings.YimmutableSeq.value) "scala.collection.immutable.Seq"
else "scala.collection.Seq"
ctx.requiredClassRef(fullName)
}
def SeqClass(implicit ctx: Context) = SeqType.symbol.asClass
lazy val Seq_applyR = SeqClass.requiredMethodRef(nme.apply)
def Seq_apply(implicit ctx: Context) = Seq_applyR.symbol
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase =>
val elemtp = varArgRef.tpe.widen.argTypes.head
ref(original.termRef)
.appliedToTypes(trefs)
.appliedToArgs(vrefs :+ TreeGen.wrapArray(varArgRef, elemtp))
.appliedToArgs(vrefs :+ tpd.wrapArray(varArgRef, elemtp))
.appliedToArgss(vrefss1)
})

Expand Down
10 changes: 1 addition & 9 deletions compiler/src/dotty/tools/dotc/transform/SeqLiterals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,6 @@ class SeqLiterals extends MiniPhase {
val arr = JavaSeqLiteral(tree.elems, tree.elemtpt)
//println(i"trans seq $tree, arr = $arr: ${arr.tpe} ${arr.tpe.elemType}")
val elemtp = tree.elemtpt.tpe
val elemCls = elemtp.classSymbol
val (wrapMethStr, targs) =
if (elemCls.isPrimitiveValueClass) (s"wrap${elemCls.name}Array", Nil)
else if (elemtp derivesFrom defn.ObjectClass) ("wrapRefArray", elemtp :: Nil)
else ("genericWrapArray", elemtp :: Nil)
ref(defn.ScalaPredefModule)
.select(wrapMethStr.toTermName)
.appliedToTypes(targs)
.appliedTo(arr)
wrapArray(arr, elemtp)
}
}
26 changes: 0 additions & 26 deletions compiler/src/dotty/tools/dotc/transform/TreeGen.scala

This file was deleted.

2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ object Implicits {
/** The implicit references */
def refs: List[ImplicitRef]

private var SingletonClass: ClassSymbol = null
private[this] var SingletonClass: ClassSymbol = null

/** Widen type so that it is neither a singleton type nor a type that inherits from scala.Singleton. */
private def widenSingleton(tp: Type)(implicit ctx: Context): Type = {
Expand Down
6 changes: 4 additions & 2 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CompilationTests extends ParallelTesting {
compileFile("tests/pos-special/completeFromSource/Test.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
compileFile("tests/pos-special/completeFromSource/Test2.scala", defaultOptions.and("-sourcepath", "tests/pos-special")) +
compileFile("tests/pos-special/completeFromSource/Test3.scala", defaultOptions.and("-sourcepath", "tests/pos-special", "-scansource")) +
compileFile("tests/pos-special/repeatedArgs.scala", defaultOptions.and("-Yimmutable-seq")) +
compileFilesInDir("tests/pos-special/fatal-warnings", defaultOptions.and("-Xfatal-warnings")) +
compileList(
"compileMixed",
Expand Down Expand Up @@ -189,8 +190,9 @@ class CompilationTests extends ParallelTesting {
compileFile("tests/neg-custom-args/i3882.scala", allowDeepSubtypes) +
compileFile("tests/neg-custom-args/i4372.scala", allowDeepSubtypes) +
compileFile("tests/neg-custom-args/i1754.scala", allowDeepSubtypes) +
compileFilesInDir("tests/neg-custom-args/isInstanceOf", allowDeepSubtypes and "-Xfatal-warnings") +
compileFile("tests/neg-custom-args/i3627.scala", allowDeepSubtypes)
compileFile("tests/neg-custom-args/i3627.scala", allowDeepSubtypes) +
compileFile("tests/neg-custom-args/repeatedArgs.scala", defaultOptions.and("-Yimmutable-seq")) +
compileFilesInDir("tests/neg-custom-args/isInstanceOf", allowDeepSubtypes and "-Xfatal-warnings")
}.checkExpectedErrors()

// Run tests -----------------------------------------------------------------
Expand Down
19 changes: 19 additions & 0 deletions tests/neg-custom-args/repeatedArgs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import scala.collection.{immutable, mutable}
import java.nio.file.Paths

/** Compiled with `-Yimmutable-seq` */
class repeatedArgs {
def bar(xs: String*): Int = xs.length

def test(xs: immutable.Seq[String], ys: collection.Seq[String], zs: Array[String]): Unit = {
bar("a", "b", "c")
bar(xs: _*)
bar(ys: _*) // error: immutable.Seq expected, found Seq
bar(zs: _*) // error: immutable.Seq expected, found Array

Paths.get("Hello", "World")
Paths.get("Hello", xs: _*)
Paths.get("Hello", ys: _*) // error: immutable.Seq expected, found Seq
Paths.get("Hello", zs: _*) // error: immutable.Seq expected, found Array
}
}
18 changes: 18 additions & 0 deletions tests/pos-special/repeatedArgs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import scala.collection.{immutable, mutable}
import java.nio.file.Paths

/** Compiled with `-Yimmutable-seq` */
class repeatedArgs {
def bar(xs: String*): Int = xs.length

def test(xs: immutable.Seq[String]): Unit = {
bar("a", "b", "c")
bar(xs: _*)

Paths.get("Hello", "World")
Paths.get("Hello", xs: _*)

val List(_, others: _*) = xs.toList // toList should not be needed, see #4790
val x: immutable.Seq[String] = others
}
}
23 changes: 21 additions & 2 deletions tests/pos/repeatedArgs.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
object testRepeated {
def foo = java.lang.System.out.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
import scala.collection.{immutable, mutable}
import java.nio.file.Paths

class repeatedArgs {
def bar(xs: String*): Int = xs.length

def test(xs: immutable.Seq[String], ys: collection.Seq[String], zs: Array[String]): Unit = {
bar("a", "b", "c")
bar(xs: _*)
bar(ys: _*) // error in 2.13
bar(zs: _*)

Paths.get("Hello", "World")
Paths.get("Hello", xs: _*)
Paths.get("Hello", ys: _*) // error in 2.13
Paths.get("Hello", zs: _*)

val List(_, others: _*) = xs.toList // toList should not be needed, see #4790
val x: collection.Seq[String] = others
// val y: immutable.Seq[String] = others // ok in 2.13
}
}