aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala24
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala20
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala2
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala7
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala1
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala4
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala11
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala3
10 files changed, 60 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala
index 1786e2e29..7920667e7 100644
--- a/src/dotty/tools/dotc/TypeErasure.scala
+++ b/src/dotty/tools/dotc/TypeErasure.scala
@@ -142,7 +142,7 @@ object TypeErasure {
tp.derivedPolyType(
tp.paramNames, tp.paramNames map (Function.const(TypeBounds.upper(defn.ObjectType))), tp.resultType)
- if ((sym eq defn.Any_asInstanceOf) || (sym eq defn.Any_isInstanceOf)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
+ if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
else if (sym.isAbstractType) TypeAlias(WildcardType)
else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
else eraseInfo(tp)(erasureCtx) match {
@@ -153,10 +153,24 @@ object TypeErasure {
}
}
- def isUnboundedGeneric(tp: Type)(implicit ctx: Context) = !(
- (tp derivesFrom defn.ObjectClass) ||
- tp.classSymbol.isPrimitiveValueClass ||
- (tp.typeSymbol is JavaDefined))
+ /** Is `tp` an abstract type or polymorphic type parameter that has `Any`
+ * as upper bound and that is not Java defined? Arrays of such types are
+ * erased to `Object` instead of `ObjectArray`.
+ */
+ def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp match {
+ case tp: TypeRef =>
+ tp.symbol.isAbstractType &&
+ !tp.derivesFrom(defn.ObjectClass) &&
+ !tp.typeSymbol.is(JavaDefined)
+ case tp: PolyParam =>
+ !tp.derivesFrom(defn.ObjectClass) &&
+ !tp.binder.resultType.isInstanceOf[JavaMethodType]
+ case tp: TypeProxy => isUnboundedGeneric(tp.underlying)
+ case tp: AndType => isUnboundedGeneric(tp.tp1) || isUnboundedGeneric(tp.tp2)
+ case tp: OrType => isUnboundedGeneric(tp.tp1) && isUnboundedGeneric(tp.tp2)
+ case _ => false
+ }
+
/** The erased least upper bound is computed as follows
* - if both argument are arrays, an array of the lub of the element types
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 98609f9f1..98cc10a22 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -298,6 +298,24 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case ConstantType(value) => Literal(value)
}
+ /** A tree representing a `newXYZArray` operation of the right
+ * kind for the given element type in `typeArg`. No type arguments or
+ * `length` arguments are given.
+ */
+ def newArray(typeArg: Tree, pos: Position)(implicit ctx: Context): Tree = {
+ val elemType = typeArg.tpe
+ val elemClass = elemType.classSymbol
+ def newArr(kind: String) =
+ ref(defn.DottyArraysModule).select(s"new${kind}Array".toTermName).withPos(pos)
+ if (TypeErasure.isUnboundedGeneric(elemType))
+ newArr("Generic").appliedToTypeTrees(typeArg :: Nil)
+ else if (elemClass.isPrimitiveValueClass)
+ newArr(elemClass.name.toString)
+ else
+ newArr("Ref").appliedToTypeTrees(
+ TypeTree(defn.ArrayType(elemType)).withPos(typeArg.pos) :: Nil)
+ }
+
// ------ Creating typed equivalents of trees that exist only in untyped form -------
/** new C(args), calling the primary constructor of C */
@@ -678,7 +696,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)) withPos tree.pos
}
}
-
+
def applyOverloaded(receiver: Tree, method: TermName, args: List[Tree], targs: List[Type], expectedType: Type, isAnnotConstructor: Boolean = false)(implicit ctx: Context): Tree = {
val typer = ctx.typer
val proto = new FunProtoTyped(args, expectedType, typer)
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 6293d18d2..6824cc36c 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -120,7 +120,7 @@ object Contexts {
protected def scope_=(scope: Scope) = _scope = scope
def scope: Scope = _scope
- /** The current type assigner ot typer */
+ /** The current type assigner or typer */
private[this] var _typeAssigner: TypeAssigner = _
protected def typeAssigner_=(typeAssigner: TypeAssigner) = _typeAssigner = typeAssigner
def typeAssigner: TypeAssigner = _typeAssigner
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index d78e09418..20dd899f1 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -193,6 +193,10 @@ class Definitions {
def staticsMethod(name: PreName) = ctx.requiredMethod(ScalaStaticsClass, name)
lazy val DottyPredefModule = ctx.requiredModule("dotty.DottyPredef")
+ lazy val DottyArraysModule = ctx.requiredModule("dotty.runtime.Arrays")
+
+ def newRefArrayMethod = ctx.requiredMethod(DottyArraysModule.moduleClass.asClass, "newRefArray")
+
lazy val NilModule = ctx.requiredModule("scala.collection.immutable.Nil")
lazy val PredefConformsClass = ctx.requiredClass("scala.Predef." + tpnme.Conforms)
@@ -211,6 +215,7 @@ class Definitions {
lazy val Array_update = ctx.requiredMethod(ArrayClass, nme.update)
lazy val Array_length = ctx.requiredMethod(ArrayClass, nme.length)
lazy val Array_clone = ctx.requiredMethod(ArrayClass, nme.clone_)
+ lazy val ArrayConstructor = ctx.requiredMethod(ArrayClass, nme.CONSTRUCTOR)
lazy val traversableDropMethod = ctx.requiredMethod(ScalaRuntimeClass, nme.drop)
lazy val uncheckedStableClass: ClassSymbol = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable")
@@ -428,6 +433,8 @@ class Definitions {
lazy val PhantomClasses = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
+ lazy val isPolymorphicAfterErasure = Set[Symbol](Any_isInstanceOf, Any_asInstanceOf, newRefArrayMethod)
+
lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule)
lazy val overriddenBySynthetic = Set[Symbol](Any_equals, Any_hashCode, Any_toString, Product_canEqual)
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index bc15f6a06..a6b40fe66 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -204,7 +204,6 @@ object NameOps {
case nme.length => nme.primitive.arrayLength
case nme.update => nme.primitive.arrayUpdate
case nme.clone_ => nme.clone_
- case nme.CONSTRUCTOR => nme.primitive.arrayConstructor
}
/** If name length exceeds allowable limit, replace part of it by hash */
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 8393eb56f..959e9cb84 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -433,7 +433,6 @@ object StdNames {
val moduleClass : N = "moduleClass"
val name: N = "name"
val ne: N = "ne"
- val newArray: N = "newArray"
val newFreeTerm: N = "newFreeTerm"
val newFreeType: N = "newFreeType"
val newNestedSymbol: N = "newNestedSymbol"
@@ -691,8 +690,7 @@ object StdNames {
val arrayApply: TermName = "[]apply"
val arrayUpdate: TermName = "[]update"
val arrayLength: TermName = "[]length"
- val arrayConstructor: TermName = "[]<init>"
- val names: Set[Name] = Set(arrayApply, arrayUpdate, arrayLength, arrayConstructor)
+ val names: Set[Name] = Set(arrayApply, arrayUpdate, arrayLength)
}
def isPrimitiveName(name: Name) = primitive.names.contains(name)
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 0a34b9e7c..23f1aada9 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -89,7 +89,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
*/
def assertErased(tree: tpd.Tree)(implicit ctx: Context): Unit = {
assertErased(tree.typeOpt, tree)
- if (!(tree.symbol == defn.Any_isInstanceOf || tree.symbol == defn.Any_asInstanceOf))
+ if (!defn.isPolymorphicAfterErasure(tree.symbol))
assertErased(tree.typeOpt.widen, tree)
if (ctx.mode.isExpr)
tree.tpe match {
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index ba770cf2c..fe45beb04 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -596,7 +596,16 @@ trait Applications extends Compatibility { self: Typer =>
checkBounds(typedArgs, pt)
case _ =>
}
- assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
+ convertNewArray(
+ assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs))
+ }
+
+ /** Rewrite `new Array[T]` trees to calls of newXYZArray methods. */
+ def convertNewArray(tree: Tree)(implicit ctx: Context): Tree = tree match {
+ case TypeApply(tycon, targs) if tycon.symbol == defn.ArrayConstructor =>
+ newArray(targs.head, tree.pos)
+ case _ =>
+ tree
}
def typedUnApply(tree: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = track("typedUnApply") {
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 6c5e48edb..41dc3c3f7 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -208,7 +208,6 @@ trait TypeAssigner {
case p.arrayApply => MethodType(defn.IntType :: Nil, arrayElemType)
case p.arrayUpdate => MethodType(defn.IntType :: arrayElemType :: Nil, defn.UnitType)
case p.arrayLength => MethodType(Nil, defn.IntType)
- case p.arrayConstructor => MethodType(defn.IntType :: Nil, qualType)
case nme.clone_ if qualType.isInstanceOf[JavaArrayType] => MethodType(Nil, qualType)
case _ => accessibleSelectionType(tree, qual)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 7d4e8d132..f6027165b 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1326,7 +1326,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (pt.isInstanceOf[PolyProto]) tree
else {
val (_, tvars) = constrained(poly, tree)
- adaptInterpolated(tree appliedToTypes tvars, pt, original)
+ convertNewArray(
+ adaptInterpolated(tree.appliedToTypes(tvars), pt, original))
}
case wtp =>
pt match {