aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-08-24 18:11:09 +0200
committerMartin Odersky <odersky@gmail.com>2014-08-24 18:11:20 +0200
commitd46066bde061663953b9c41297562e0f0466b4dd (patch)
tree9cb160e2ce2dc8dcb140a4f084c3b1bc12083843 /src
parent85d963d913e4fa7e608238e6853c77b02cf223e9 (diff)
downloaddotty-d46066bde061663953b9c41297562e0f0466b4dd.tar.gz
dotty-d46066bde061663953b9c41297562e0f0466b4dd.tar.bz2
dotty-d46066bde061663953b9c41297562e0f0466b4dd.zip
Fixes to erasure
Prompted by compiling more test files with erasure enabled.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala13
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala81
2 files changed, 65 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 48286fe47..4d818cc6f 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -11,6 +11,7 @@ import printing.Disambiguation.disambiguated
import util.{Stats, DotClass, SimpleMap}
import config.Config
import config.Printers._
+import TypeErasure.erasedLub
/** Provides methods to compare types.
*/
@@ -654,7 +655,8 @@ class TypeComparer(initctx: Context) extends DotClass {
{ // special case for situations like:
// foo <: C { type T = foo.T }
tp2.refinedInfo match {
- case TypeBounds(lo, hi) if lo eq hi => (tp1r select name) =:= lo
+ case TypeBounds(lo, hi) if lo eq hi =>
+ !ctx.phase.erasedTypes && (tp1r select name) =:= lo
case _ => false
}
}
@@ -1088,19 +1090,22 @@ class TypeComparer(initctx: Context) extends DotClass {
* Sometimes, the disjunction of two types cannot be formed because
* the types are in conflict of each other. (@see `andType` for an enumeration
* of these cases). In cases of conflict a `MergeError` is raised.
+ *
+ * @param erased Apply erasure semantics. If erased is true, instead of creating
+ * an OrType, the lub will be computed using TypeCreator#erasedLub.
*/
- final def orType(tp1: Type, tp2: Type) = {
+ final def orType(tp1: Type, tp2: Type, erased: Boolean = ctx.erasedTypes) = {
val t1 = distributeOr(tp1, tp2)
if (t1.exists) t1
else {
val t2 = distributeOr(tp2, tp1)
if (t2.exists) t2
- else {
+ else if (erased) erasedLub(tp1, tp2)
+ else
//if (isHKRef(tp1)) tp1
//else if (isHKRef(tp2)) tp2
//else
OrType(tp1, tp2)
- }
}
}
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index b79791aa9..53e253c69 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -158,7 +158,7 @@ object Erasure {
case (defn.ArrayType(treeElem), defn.ArrayType(ptElem))
if treeElem.widen.isPrimitiveValueType && !ptElem.isPrimitiveValueType =>
// See SI-2386 for one example of when this might be necessary.
- cast(runtimeCall(nme.toObjectArray, tree :: Nil), pt)
+ cast(ref(defn.runtimeMethod(nme.toObjectArray)).appliedTo(tree), pt)
case _ =>
ctx.log(s"casting from ${tree.showSummary}: ${tree.tpe.show} to ${pt.show}")
tree.asInstance(pt)
@@ -180,7 +180,9 @@ object Erasure {
case MethodType(Nil, _) =>
adaptToType(tree.appliedToNone, pt)
case _ =>
- if (tpw.isErasedValueType)
+ if (pt.isInstanceOf[ProtoType])
+ tree
+ else if (tpw.isErasedValueType)
adaptToType(box(tree), pt)
else if (pt.isErasedValueType)
adaptToType(unbox(tree, pt), pt)
@@ -191,7 +193,7 @@ object Erasure {
else
cast(tree, pt)
}
- if ((pt eq AnyFunctionProto) || tree.tpe <:< pt) tree
+ if ((pt.isInstanceOf[FunProto]) || tree.tpe <:< pt) tree
else makeConformant(tree.tpe.widen)
}
}
@@ -233,15 +235,18 @@ 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) runtimeCall(tree.name.genericArrayOp, qual :: Nil)
+ def selectArrayMember(qual: Tree, erasedPre: Type) = {
+ if (erasedPre isRef defn.ObjectClass) runtimeCallWithProtoArgs(tree.name.genericArrayOp, pt, qual)
else recur(cast(qual, erasedPre))
+ }
def recur(qual: Tree): Tree = {
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
val symIsPrimitive = sym.owner.isPrimitiveValueClass
- if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass))
+ if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass)) {
+ assert(sym.isConstructor, s"${sym.showLocated}")
select(qual, defn.ObjectClass.info.decl(sym.name).symbol)
+ }
else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.isErasedValueType)
recur(box(qual))
else if (!qualIsPrimitive && symIsPrimitive)
@@ -249,7 +254,7 @@ object Erasure {
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.tpe))
+ selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen))
else
recur(cast(qual, sym.owner.typeRef))
}
@@ -257,6 +262,18 @@ object Erasure {
recur(typed(tree.qualifier, AnySelectionProto))
}
+ private def runtimeCallWithProtoArgs(name: Name, pt: Type, args: Tree*)(implicit ctx: Context): Tree = {
+ val meth = defn.runtimeMethod(name)
+ val followingParams = meth.info.firstParamTypes.drop(args.length)
+ val followingArgs = protoArgs(pt).zipWithConserve(followingParams)(typedExpr).asInstanceOf[List[tpd.Tree]]
+ ref(defn.runtimeMethod(name)).appliedToArgs(args.toList ++ followingArgs)
+ }
+
+ private def protoArgs(pt: Type): List[untpd.Tree] = pt match {
+ case pt: FunProto => pt.args ++ protoArgs(pt.resultType)
+ case _ => Nil
+ }
+
override def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context) = {
val TypeApply(fun, args) = tree
val fun1 = typedExpr(fun, pt)
@@ -268,27 +285,29 @@ 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
- fun match {
- case fun: Apply =>
- typedApply(fun, pt)(ctx.fresh.setTree(tree))
- case _ =>
- def nextOuter(ctx: Context): Context =
- if (ctx.outer.tree eq tree) nextOuter(ctx.outer) else ctx.outer
- def contextArgs(tree: untpd.Apply)(implicit ctx: Context): List[untpd.Tree] =
- ctx.tree match {
- case enclApp @ Apply(enclFun, enclArgs) if enclFun eq tree =>
- enclArgs ++ contextArgs(enclApp)(nextOuter(ctx))
- case _ =>
- Nil
- }
- val allArgs = args ++ contextArgs(tree)
- val fun1 = typedExpr(fun, AnyFunctionProto)
+ typedExpr(fun, FunProto(args, pt, this)) match {
+ case fun1: Apply => // arguments passed in prototype were already passed
+ fun1
+ case fun1 =>
fun1.tpe.widen match {
case mt: MethodType =>
- val allArgs1 = allArgs.zipWithConserve(mt.paramTypes)(typedExpr)
- untpd.cpy.Apply(tree)(fun1, allArgs1) withType mt.resultType
+ val args1 = (args ++ protoArgs(pt)).zipWithConserve(mt.paramTypes)(typedExpr)
+ untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType
case _ =>
throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}")
}
@@ -407,7 +426,19 @@ object Erasure {
override def adapt(tree: Tree, pt: Type, original: untpd.Tree)(implicit ctx: Context): Tree =
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 adaptToType(tree, pt)
+ if (tree.isEmpty) tree
+ else {
+ val tree1 = adaptToType(tree, pt)
+ tree1.tpe match {
+ case ref: TermRef =>
+ assert(
+ ref.isInstanceOf[WithNonMemberSym] ||
+ ref.denot.isInstanceOf[SymDenotation],
+ i"non-sym type $ref of class ${ref.getClass} with denot of class ${ref.denot.getClass} of $tree1")
+ case _ =>
+ }
+ tree1
+ }
}
}
}