aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-28 22:35:09 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-28 22:36:49 +0200
commitaae91eddee1a90dc5312ce156b772f090001721f (patch)
tree6ce2de879d48939ba1914e8e450ff77f45c5c89c /src/dotty/tools
parentf7d3f3b12e0f3f69954bfb9980134968abf541f5 (diff)
downloaddotty-aae91eddee1a90dc5312ce156b772f090001721f.tar.gz
dotty-aae91eddee1a90dc5312ce156b772f090001721f.tar.bz2
dotty-aae91eddee1a90dc5312ce156b772f090001721f.zip
Fixes to erasure to make -Ycheck:all work.
Main change: Introduce JavaArrayType as a new type constructor for Java erased array. Translate all methods of Array class during erasure to primitive operations on arrays. Some other small fixes for more localized problems.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala113
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala1
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala8
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala10
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala8
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala72
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala19
10 files changed, 151 insertions, 86 deletions
diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala
index c8c54ed03..63b4f396b 100644
--- a/src/dotty/tools/dotc/TypeErasure.scala
+++ b/src/dotty/tools/dotc/TypeErasure.scala
@@ -8,20 +8,17 @@ import util.DotClass
*
* TypeRef(NoPrefix, denot is ClassDenotation)
* TermRef(NoPrefix, denot is SymDenotation)
- * ThisType
- * SuperType
- * PolyParam, only for array types and isInstanceOf, asInstanceOf
- * RefinedType, parent* is Array class
- * TypeBounds, only for array types
+ * JavaArrayType
* AnnotatedType
* MethodType ----+-- JavaMethodType
- * PolyType, only for array types and isInstanceOf, asInstanceOf
- * RefinedThis
* ClassInfo
* NoType
* NoPrefix
* WildcardType
* ErrorType
+ *
+ * only for isInstanceOf, asInstanceOf: PolyType, PolyParam, TypeBounds
+ *
*/
object TypeErasure {
@@ -74,18 +71,19 @@ object TypeErasure {
/** The symbol's erased info. This is the type's erasure, except for the following symbols:
*
* - For $asInstanceOf : [T]T
- * - For $isInstanceOf : [T]scala#Boolean
- * - For Array[T].<init> : [T]{scala#Int)Array[T]
- * - For type members of Array : The original info
- * - For all other abstract types: = ?
+ * - For $isInstanceOf : [T]Boolean
+ * - For all abstract types : = ?
* - For all other symbols : the semi-erasure of their types, with
* isJava, isConstructor set according to symbol.
*/
def transformInfo(sym: Symbol, tp: Type)(implicit ctx: Context): Type = {
val erase = erasureFn(sym is JavaDefined, isSemi = true, sym.isConstructor, wildcardOK = false)
- if ((sym eq defn.Any_asInstanceOf) ||
- (sym eq defn.Any_isInstanceOf) ||
- (sym.owner eq defn.ArrayClass) && (sym.isType || sym.isConstructor)) sym.info
+
+ def eraseParamBounds(tp: PolyType): Type =
+ 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])
else if (sym.isAbstractType) TypeAlias(WildcardType)
else erase(tp)
}
@@ -95,30 +93,56 @@ object TypeErasure {
tp.classSymbol.isPrimitiveValueClass ||
(tp.typeSymbol is JavaDefined))
- def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = {
- val cls2 = tp2.classSymbol
- def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
- case bc :: bcs1 =>
- if (cls2.derivesFrom(bc))
- if (!bc.is(Trait)) bc
- else loop(bcs1, if (bestSoFar.derivesFrom(bc)) bestSoFar else bc)
- else
- loop(bcs1, bestSoFar)
- case nil =>
- bestSoFar
- }
- loop(tp1.baseClasses, defn.ObjectClass).typeRef
+ /** The erased least upper bound is computed as follows
+ * - if both argument are arrays, an array of the lub of the element types
+ * - if one argument is an array, Object
+ * - otherwise a common superclass or trait S of the argument classes, with the
+ * following two properties:
+ * S is minimal: no other common superclass or trait derives from S]
+ * S is last : in the linearization of the first argument type `tp1`
+ * there are no minimal common superclasses or traits that
+ * come after S.
+ * (the reason to pick last is that we prefer classes over traits that way).
+ */
+ def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match {
+ case JavaArrayType(elem1) =>
+ tp2 match {
+ case JavaArrayType(elem2) => JavaArrayType(erasedLub(elem1, elem2))
+ case _ => defn.ObjectType
+ }
+ case _ =>
+ tp2 match {
+ case JavaArrayType(_) => defn.ObjectType
+ case _ =>
+ val cls2 = tp2.classSymbol
+ def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
+ case bc :: bcs1 =>
+ if (cls2.derivesFrom(bc))
+ if (!bc.is(Trait)) bc
+ else loop(bcs1, if (bestSoFar.derivesFrom(bc)) bestSoFar else bc)
+ else
+ loop(bcs1, bestSoFar)
+ case nil =>
+ bestSoFar
+ }
+ loop(tp1.baseClasses, defn.ObjectClass).typeRef
+ }
}
+ /** The erased greatest lower bound picks one of the two argument types. It prefers, in this order:
+ * - arrays over non-arrays
+ * - subtypes over supertypes, unless isJava is set
+ * - real classes over traits
+ */
def erasedGlb(tp1: Type, tp2: Type, isJava: Boolean)(implicit ctx: Context): Type = tp1 match {
- case defn.ArrayType(elem1) =>
+ case JavaArrayType(elem1) =>
tp2 match {
- case defn.ArrayType(elem2) => defn.ArrayType(erasedGlb(elem1, elem2, isJava))
- case _ => defn.ObjectType
+ case JavaArrayType(elem2) => JavaArrayType(erasedGlb(elem1, elem2, isJava))
+ case _ => tp1
}
case _ =>
tp2 match {
- case defn.ArrayType(_) => defn.ObjectType
+ case JavaArrayType(_) => tp2
case _ =>
val tsym1 = tp1.typeSymbol
val tsym2 = tp2.typeSymbol
@@ -145,14 +169,13 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
/** The erasure |T| of a type T. This is:
*
* - For a refined type scala.Array+[T]:
- * - if T is Nothing or Null, scala.Array+[Object]
- * - otherwise, if T <: Object, scala.Array+[|T|]
- * - otherwise, if T is a type paramter coming from Java, scala.Array+[Object].
+ * - if T is Nothing or Null, []Object
+ * - otherwise, if T <: Object, []|T|
+ * - otherwise, if T is a type paramter coming from Java, []Object
* - otherwise, Object
* - For a term ref p.x, the type <noprefix> # x.
* - For a typeref scala.Any, scala.AnyVal, scala.Singleon or scala.NotNull: |java.lang.Object|
* - For a typeref scala.Unit, |scala.runtime.BoxedUnit|.
- * - For a typeref whose symbol is owned by Array: The typeref itself, with prefix = <noprefix>
* - For a typeref P.C where C refers to a class, <noprefix> # C.
* - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
* - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
@@ -175,8 +198,7 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
def apply(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: TypeRef =>
val sym = tp.symbol
- if (!sym.isClass)
- if (sym.exists && (sym.owner eq defn.ArrayClass)) tp else this(tp.info)
+ if (!sym.isClass) this(tp.info)
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp)
else eraseNormalClassRef(tp)
case tp: RefinedType =>
@@ -214,22 +236,25 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
def eraseTypeRef(p: TypeRef) = this(p).asInstanceOf[TypeRef]
val parents: List[TypeRef] =
if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
- else if (cls eq defn.ArrayClass) defn.ObjectClass.typeRef :: Nil
else removeLaterObjects(classParents.mapConserve(eraseTypeRef))
tp.derivedClassInfo(NoPrefix, parents, decls, this(tp.selfType))
// can't replace selftype by NoType because this would lose the sourceModule link
}
- case NoType | NoPrefix | ErrorType =>
+ case NoType | NoPrefix | ErrorType | JavaArrayType(_) =>
tp
case tp: WildcardType if wildcardOK =>
tp
}
- private def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
+ def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
val defn.ArrayType(elemtp) = tp
- if (elemtp derivesFrom defn.NullClass) defn.ObjectArrayType
- else if (isUnboundedGeneric(elemtp)) defn.ObjectType
- else defn.ArrayType(this(elemtp))
+ if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType)
+ else if (isUnboundedGeneric(elemtp))
+ elemtp match {
+ case elemtp: TypeRef if elemtp.symbol.is(JavaDefined) => JavaArrayType(defn.ObjectType)
+ case _ => defn.ObjectType
+ }
+ else JavaArrayType(this(elemtp))
}
private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type =
@@ -277,6 +302,8 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
else if (sym.isDerivedValueClass) sigName(eraseDerivedValueClassRef(tp))
else normalizeClass(sym.asClass).fullName.asTypeName
case defn.ArrayType(elem) =>
+ sigName(this(tp))
+ case JavaArrayType(elem) =>
sigName(elem) ++ "[]"
case tp: TypeBounds =>
sigName(tp.hi)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 304d9853c..c53e00152 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -330,7 +330,6 @@ class Definitions {
def NothingType: Type = NothingClass.typeRef
def NullType: Type = NullClass.typeRef
def SeqType: Type = SeqClass.typeRef
- def ObjectArrayType = ArrayType(ObjectType)
def UnitType: Type = UnitClass.typeRef
def BooleanType: Type = BooleanClass.typeRef
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index e7283c827..74673235a 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -196,6 +196,14 @@ object NameOps {
case nme.clone_ => nme.array_clone
}
+ /** The name of the primitive runtime operation corresponding to an array operation */
+ def primitiveArrayOp: TermName = name match {
+ case nme.apply => nme.primitive.arrayApply
+ case nme.length => nme.primitive.arrayLength
+ case nme.update => nme.primitive.arrayUpdate
+ case nme.CONSTRUCTOR => nme.primitive.arrayConstructor
+ }
+
/** If name length exceeds allowable limit, replace part of it by hash */
def compactified(implicit ctx: Context): TermName = termName(compactify(name.toString))
}
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 91a77a2a8..af4e810de 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -635,6 +635,16 @@ object StdNames {
def newBitmapName(bitmapPrefix: TermName, n: Int): TermName = bitmapPrefix ++ n.toString
def selectorName(n: Int): TermName = "_" + (n + 1)
+
+ object primitive {
+ 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)
+ }
+
+ def isPrimitiveName(name: Name) = primitive.names.contains(name)
}
class ScalaTypeNames extends ScalaNames[TypeName] {
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 660287089..63f998c10 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -924,7 +924,7 @@ object SymDenotations {
/** The type parameters of this class */
override final def typeParams(implicit ctx: Context): List[TypeSymbol] = {
def computeTypeParams = {
- if (ctx.phase.erasedTypes && (symbol ne defn.ArrayClass)) Nil
+ if (ctx.erasedTypes && (symbol ne defn.ArrayClass)) Nil
else if (this ne initial) initial.asSymDenotation.typeParams
else decls.filter(sym =>
(sym is TypeParam) && sym.owner == symbol).asInstanceOf[List[TypeSymbol]]
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index fda9667e9..c9c4595ca 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -735,6 +735,12 @@ class TypeComparer(initctx: Context) extends DotClass {
false
}
compareClassInfo
+ case JavaArrayType(elem2) =>
+ def compareJavaArray = tp1 match {
+ case JavaArrayType(elem1) => isSubType(elem1, elem2)
+ case _ => fourthTry(tp1, tp2)
+ }
+ compareJavaArray
case _ =>
fourthTry(tp1, tp2)
}
@@ -773,6 +779,8 @@ class TypeComparer(initctx: Context) extends DotClass {
} || needsEtaLift(tp2, tp1) && tp2.testLifted(tp1.typeParams, isSubType(tp1, _))
case AndType(tp11, tp12) =>
isNewSubType(tp11, tp2) || isNewSubType(tp12, tp2)
+ case JavaArrayType(elem1) =>
+ tp2 isRef ObjectClass
case _ =>
false
}
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 7669b1a3a..0da9b6d54 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -122,6 +122,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
return "=> " ~ toText(result)
case tp: ClassInfo =>
return toTextParents(tp.instantiatedParents) ~ "{...}"
+ case JavaArrayType(elemtp) =>
+ return toText(elemtp) ~ "[]"
case tp: SelectionProto =>
return toText(RefinedType(WildcardType, tp.name, tp.memberProto))
case tp: ViewProto =>
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index 1efc6b53c..86151fae2 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -24,7 +24,7 @@ import scala.collection.mutable.ListBuffer
import dotty.tools.dotc.core.Flags
import ValueClasses._
import TypeUtils._
-import com.sun.j3d.utils.behaviors.picking.Intersect
+import typer.Mode
class Erasure extends Phase with DenotTransformer { thisTransformer =>
@@ -51,10 +51,13 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
val newOwner = if (oldOwner eq defn.AnyClass) defn.ObjectClass else oldOwner
val oldInfo = ref.info
val newInfo = transformInfo(ref.symbol, oldInfo)
- if ((oldOwner eq newOwner) && (oldInfo eq newInfo)) ref
+ val oldFlags = ref.flags
+ val newFlags = ref.flags &~ Flags.HasDefaultParams // HasDefaultParams needs to be dropped because overriding might become overloading
+ // TODO: define derivedSymDenotation?
+ if ((oldOwner eq newOwner) && (oldInfo eq newInfo) && (oldFlags == newFlags)) ref
else {
assert(!ref.is(Flags.PackageClass), s"trans $ref @ ${ctx.phase} oldOwner = $oldOwner, newOwner = $newOwner, oldInfo = $oldInfo, newInfo = $newInfo ${oldOwner eq newOwner} ${oldInfo eq newInfo}")
- ref.copySymDenotation(owner = newOwner, info = newInfo)
+ ref.copySymDenotation(owner = newOwner, initFlags = newFlags, info = newInfo)
}
}
case ref =>
@@ -155,7 +158,7 @@ object Erasure {
// assert(!pt.isInstanceOf[SingletonType], pt)
if (pt isRef defn.UnitClass) unbox(tree, pt)
else (tree.tpe, pt) match {
- case (defn.ArrayType(treeElem), defn.ArrayType(ptElem))
+ case (JavaArrayType(treeElem), JavaArrayType(ptElem))
if treeElem.widen.isPrimitiveValueType && !ptElem.isPrimitiveValueType =>
// See SI-2386 for one example of when this might be necessary.
cast(ref(defn.runtimeMethod(nme.toObjectArray)).appliedTo(tree), pt)
@@ -209,22 +212,24 @@ object Erasure {
}
/** Type check select nodes, applying the following rewritings exhaustively
- * on selections `e.m`.
+ * on selections `e.m`, where `OT` is the type of the owner of `m` and `ET`
+ * is the erased type of the selection's original qualifier expression.
*
- * e.m1 -> e.m2 if `m1` is a member of Any or AnyVal and `m2` is
- * the same-named member in Object.
- * e.m -> box(e).m if `e` is primitive and `m` is a member or a reference class
- * or `e` has an erased value class type.
- * e.m -> unbox(e).m if `e` is not primitive and `m` is a member of a primtive type.
+ * e.m1 -> e.m2 if `m1` is a member of Any or AnyVal and `m2` is
+ * the same-named member in Object.
+ * e.m -> box(e).m if `e` is primitive and `m` is a member or a reference class
+ * or `e` has an erased value class type.
+ * e.m -> unbox(e).m if `e` is not primitive and `m` is a member of a primtive type.
+ * e.m -> cast(e, OT).m if the type of `e` does not conform to OT and `m`
+ * is not an array operation.
*
- * Additionally, if the type of `e` does not derive from the type `OT` of the owner of `m`,
- * the following rewritings are performed, where `ET` is the erased type of the selection's
- * original qualifier expression.
+ * If `m` is an array operation, i.e. one of the members apply, update, length, clone, and
+ * <init> of class Array, we additionally try the following rewritings:
*
- * e.m -> cast(OT).m if `m` is not an array operation
- * e.m -> cast(ET).m if `m` is an array operation and `ET` is an array type
- * e.m -> runtime.array_m(e)
- * if `m` is an array operation and `ET` is Object
+ * e.m -> runtime.array_m(e) if ET is Object
+ * e.m -> cast(e, ET).m if the type of `e` does not conform to ET
+ * e.clone -> e.clone' where clone' is Object's clone method
+ * e.m -> e.[]m if `m` is an array operation other than `clone`.
*/
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
val sym = tree.symbol
@@ -233,10 +238,15 @@ object Erasure {
def select(qual: Tree, sym: Symbol): Tree =
untpd.cpy.Select(tree)(qual, sym.name) withType qual.tpe.select(sym)
- def selectArrayMember(qual: Tree, erasedPre: Type) = {
- if (erasedPre isRef defn.ObjectClass) runtimeCallWithProtoArgs(tree.name.genericArrayOp, pt, qual)
- else recur(cast(qual, erasedPre))
- }
+ def selectArrayMember(qual: Tree, erasedPre: Type): Tree =
+ if (erasedPre isRef defn.ObjectClass)
+ runtimeCallWithProtoArgs(tree.name.genericArrayOp, pt, qual)
+ else if (!(qual.tpe <:< erasedPre))
+ selectArrayMember(cast(qual, erasedPre), erasedPre)
+ else if (sym == defn.Array_clone)
+ untpd.cpy.Select(tree)(qual, tree.name).withType(defn.Object_clone.termRef)
+ else
+ assignType(untpd.cpy.Select(tree)(qual, tree.name.primitiveArrayOp), qual)
def recur(qual: Tree): Tree = {
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
@@ -249,10 +259,10 @@ object Erasure {
recur(box(qual))
else if (!qualIsPrimitive && symIsPrimitive)
recur(unbox(qual, sym.owner.typeRef))
- else if (qual.tpe.derivesFrom(sym.owner) || qual.isInstanceOf[Super])
- select(qual, sym)
else if (sym.owner eq defn.ArrayClass)
selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen.finalResultType))
+ else if (qual.tpe.derivesFrom(sym.owner) || qual.isInstanceOf[Super])
+ select(qual, sym)
else
recur(cast(qual, sym.owner.typeRef))
}
@@ -274,7 +284,7 @@ object Erasure {
override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context) = {
val TypeApply(fun, args) = tree
- val fun1 = typedExpr(fun, pt)
+ val fun1 = typedExpr(fun, WildcardType)
fun1.tpe.widen match {
case funTpe: PolyType =>
val args1 = args.mapconserve(typedType(_))
@@ -283,19 +293,6 @@ object Erasure {
}
}
-/*
- private def contextArgs(tree: untpd.Tree)(implicit ctx: Context): List[untpd.Tree] = {
- def nextOuter(ctx: Context): Context =
- if (ctx.outer.tree eq tree) nextOuter(ctx.outer) else ctx.outer
- ctx.tree match {
- case enclApp @ Apply(enclFun, enclArgs) if enclFun eq tree =>
- enclArgs ++ contextArgs(enclApp)(nextOuter(ctx))
- case _ =>
- Nil
- }
- }
-*/
-
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
val Apply(fun, args) = tree
typedExpr(fun, FunProto(args, pt, this)) match {
@@ -425,6 +422,7 @@ object Erasure {
ctx.traceIndented(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) {
assert(ctx.phase == ctx.erasurePhase.next, ctx.phase)
if (tree.isEmpty) tree
+ else if (ctx.mode is Mode.Pattern) tree // TODO: replace with assertion once pattern matcher is active
else {
val tree1 = adaptToType(tree, pt)
tree1.tpe match {
diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
index f74f4f208..8c9ffb1fb 100644
--- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
+++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
@@ -86,7 +86,7 @@ class TypeTestsCasts extends MiniPhaseTransform {
else derivedTree(box(qual), defn.Any_asInstanceOf, argType)
}
else if (argCls.isPrimitiveValueClass)
- unbox(qual, argType)
+ unbox(qual.ensureConforms(defn.ObjectType), argType)
else
derivedTree(qual, defn.Any_asInstanceOf, argType)
}
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 4d996fd61..153e0d242 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -5,7 +5,7 @@ package typer
import core._
import ast._
import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._
-import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._
+import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._
import util.Positions._
import config.Printers._
@@ -183,8 +183,21 @@ trait TypeAssigner {
def assignType(tree: untpd.Ident, tp: Type)(implicit ctx: Context) =
tree.withType(tp)
- def assignType(tree: untpd.Select, qual: Tree)(implicit ctx: Context) =
- tree.withType(accessibleSelectionType(tree, qual))
+ def assignType(tree: untpd.Select, qual: Tree)(implicit ctx: Context): Select = {
+ def arrayElemType = {
+ val JavaArrayType(elemtp) = qual.tpe.widen
+ elemtp
+ }
+ val p = nme.primitive
+ val tp = tree.name match {
+ 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, qual.tpe)
+ case _ => accessibleSelectionType(tree, qual)
+ }
+ tree.withType(tp)
+ }
def assignType(tree: untpd.SelectFromTypeTree, qual: Tree)(implicit ctx: Context) =
tree.withType(accessibleSelectionType(tree, qual))