From 7d414eb69b28fa0f6855168aa7afe43a75b3f23e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 16 Aug 2014 11:55:57 +0200 Subject: Roll Uncurry into Erasure Making cpy recompute types uncovered errors in uncurry. In a nutshell, the intermediate Apply nodes of a curried function were ill-typed, which caused errors produced by TypeAssigner. These nodes were eliminated down the road, but the errors are already issued. I did not find a good way to treat uncurry as a treetransform. Since it is rather trivial, it did not seem warranted to make it a full transformer either. So in the end the uncurry functionality became part of erasure. --- src/dotty/tools/dotc/Compiler.scala | 4 +- src/dotty/tools/dotc/core/transform/Erasure.scala | 12 ++++-- src/dotty/tools/dotc/transform/Erasure.scala | 27 ++++++++++--- .../dotc/transform/UncurryTreeTransform.scala | 46 ---------------------- 4 files changed, 31 insertions(+), 58 deletions(-) delete mode 100644 src/dotty/tools/dotc/transform/UncurryTreeTransform.scala (limited to 'src') diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index fffcfd8f8..cae8c5782 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -32,9 +32,7 @@ class Compiler { new TypeTestsCasts, new InterceptedMethods, new Literalize), - List(new Erasure)//, - //List(new UncurryTreeTransform - // /* , new Constructors */) + List(new Erasure) ) var runId = 1 diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index 41254c982..19662d22a 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -107,7 +107,8 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard * - For T1 & T2, erasure(T1) (??) * - For T1 | T2, the first base class in the linearization of T which is also a base class of T2 * - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit. - * - For any other method type (Fs)T, (|Fs|)|T|. + * - For any other uncurried method type (Fs)T, (|Fs|)|T|. + * - For a curried method type (Fs1)(Fs2)T, (|Fs1|,Es2)ET where (Es2)ET = |(Fs2)T|. * - For a polymorphic type, the erasure of its result type. * - For the class info type of java.lang.Object, the same type without any parents. * - For a class info type of a value class, the same type without any parents. @@ -140,8 +141,13 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard this(tp.baseTypeRef(lubClass(tp1, tp2))) case tp: MethodType => val paramErasure = erasureFn(tp.isJava, isSemi, isConstructor, wildcardOK)(_) - tp.derivedMethodType( - tp.paramNames, tp.paramTypes.mapConserve(paramErasure), eraseResult(tp.resultType)) + val formals = tp.paramTypes.mapConserve(paramErasure) + eraseResult(tp.resultType) match { + case rt: MethodType => + tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramTypes, rt.resultType) + case rt => + tp.derivedMethodType(tp.paramNames, formals, rt) + } case tp: PolyType => this(tp.resultType) case tp @ ClassInfo(pre, cls, classParents, decls, _) => diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 6b2a5a676..f02846735 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -264,13 +264,28 @@ object Erasure { override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { val Apply(fun, args) = tree - val fun1 = typedExpr(fun, WildcardType) - fun1.tpe.widen match { - case mt: MethodType => - val args1 = args.zipWithConserve(mt.paramTypes)(typedExpr) - untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType + fun match { + case fun: Apply => + typedApply(fun, pt)(ctx.fresh.setTree(tree)) case _ => - throw new MatchError(i"tree $tree has uxpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}") + 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, WildcardType) + fun1.tpe.widen match { + case mt: MethodType => + val allArgs1 = allArgs.zipWithConserve(mt.paramTypes)(typedExpr) + untpd.cpy.Apply(tree)(fun1, allArgs1) withType mt.resultType + case _ => + throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}") + } } } diff --git a/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala b/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala deleted file mode 100644 index cf7668079..000000000 --- a/src/dotty/tools/dotc/transform/UncurryTreeTransform.scala +++ /dev/null @@ -1,46 +0,0 @@ -package dotty.tools.dotc -package transform - -import TreeTransforms._ -import core.DenotTransformers._ -import core.Denotations._ -import core.SymDenotations._ -import core.Contexts._ -import core.Types._ -import core.Symbols._ -import ast.Trees._ -import ast.tpd.{Apply, Tree, cpy} - -class UncurryTreeTransform extends MiniPhaseTransform with InfoTransformer { - - override def name: String = "uncurry" - override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = - ctx.traceIndented(s"transforming ${tree.show}", show = true) { - tree.fun match { - case Apply(fn, args) => - def showType(implicit ctx: Context) = - ctx.log(s"at ${ctx.phase} ${fn.symbol} has type ${fn.symbol.info.widen.show}") - showType - ctx.atNextPhase(showType(_)) - showType - cpy.Apply(tree)(tree.fun, args ++ tree.args) - case _ => tree - }} - - def uncurry(tp: Type)(implicit ctx: Context): Type = tp match { - case tp @ MethodType(pnames1, ptypes1) => - tp.resultType match { - case rt @ MethodType(pnames2, ptypes2) => - tp.derivedMethodType(pnames1 ++ pnames2, ptypes1 ++ ptypes2, rt.resultType) - case _ => - tp - } - case tp: PolyType => - tp.derivedPolyType(tp.paramNames, tp.paramBounds, uncurry(tp.resultType)) - case _ => - tp - } - - def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = - uncurry(tp) -} \ No newline at end of file -- cgit v1.2.3