diff options
author | Martin Odersky <odersky@gmail.com> | 2014-08-24 18:11:09 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-08-24 18:11:20 +0200 |
commit | d46066bde061663953b9c41297562e0f0466b4dd (patch) | |
tree | 9cb160e2ce2dc8dcb140a4f084c3b1bc12083843 /src | |
parent | 85d963d913e4fa7e608238e6853c77b02cf223e9 (diff) | |
download | dotty-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.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Erasure.scala | 81 |
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 + } } } } |