From 7c22c0dd3449336877e83ed4aaee0400d8189475 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Dec 2014 17:10:46 +0100 Subject: Fix problem with by name params in mixed in methods. Erasure choked on them before. --- src/dotty/tools/dotc/TypeErasure.scala | 15 +++++++++++---- src/dotty/tools/dotc/transform/ElimByName.scala | 13 ++++++++++++- src/dotty/tools/dotc/transform/Erasure.scala | 2 +- 3 files changed, 24 insertions(+), 6 deletions(-) (limited to 'src/dotty/tools') diff --git a/src/dotty/tools/dotc/TypeErasure.scala b/src/dotty/tools/dotc/TypeErasure.scala index de956ca6a..973e50e8e 100644 --- a/src/dotty/tools/dotc/TypeErasure.scala +++ b/src/dotty/tools/dotc/TypeErasure.scala @@ -119,7 +119,8 @@ object TypeErasure { * treated. `eraseInfo` maps them them to nullary method types, whereas `erasure` maps them * to `Function0`. */ - def eraseInfo(tp: Type)(implicit ctx: Context): Type = scalaErasureFn.eraseInfo(tp)(erasureCtx) + def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = + scalaErasureFn.eraseInfo(tp, sym)(erasureCtx) /** The erasure of a function result type. Differs from normal erasure in that * Unit is kept instead of being mapped to BoxedUnit. @@ -145,7 +146,7 @@ object TypeErasure { 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 { + else eraseInfo(tp, sym)(erasureCtx) match { case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) => defn.BoxedUnitClass.typeRef case einfo => @@ -347,8 +348,14 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild else JavaArrayType(this(elemtp)) } - def eraseInfo(tp: Type)(implicit ctx: Context) = tp match { - case ExprType(rt) => MethodType(Nil, Nil, eraseResult(rt)) + def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match { + case ExprType(rt) => + if (sym is Param) apply(tp) + // Note that params with ExprTypes are eliminated by ElimByName, + // but potentially re-introduced by ResolveSuper, when we add + // forwarders to mixin methods. + // See doc comment for ElimByName for speculation how we could improve this. + else MethodType(Nil, Nil, eraseResult(rt)) case tp => erasure(tp) } diff --git a/src/dotty/tools/dotc/transform/ElimByName.scala b/src/dotty/tools/dotc/transform/ElimByName.scala index e06eb0602..ca84fcaec 100644 --- a/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/src/dotty/tools/dotc/transform/ElimByName.scala @@ -22,7 +22,7 @@ import ast.Trees._ * * => T ==> () => T * - * Note that `=> T` types are not eliminated in MnethodTypes. This is done later at erasure. + * Note that `=> T` types are not eliminated in MethodTypes. This is done later at erasure. * Terms are rewritten as follows: * * x ==> x.apply() if x is a parameter that had type => T @@ -41,6 +41,17 @@ import ast.Trees._ * DummyApply: [T](() => T): T * * is a synthetic method defined in Definitions. Erasure will later strip these DummyApply wrappers. + * + * Note: This scheme to have inconsistent types between method types (whose formal types are still + * ExprTypes and parameter valdefs (which are now FunctionTypes) is not pretty. There are two + * other options which have been abandoned or not yet pursued. + * + * Option 1: Transform => T to () => T also in method and function types. The problem with this is + * that is that it rewuires to look at every type, and this forces too much, causing + * Cyclic Reference errors. Abandoned for this reason. + * + * Option 2: Merge ElimByName with erasure, or have it run immediately before. This has not been + * tried yet. */ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransformer => import ast.tpd._ diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala index 0c81b81d0..933252ccd 100644 --- a/src/dotty/tools/dotc/transform/Erasure.scala +++ b/src/dotty/tools/dotc/transform/Erasure.scala @@ -62,7 +62,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer => } } case ref => - ref.derivedSingleDenotation(ref.symbol, eraseInfo(ref.info)) + ref.derivedSingleDenotation(ref.symbol, eraseInfo(ref.info, ref.symbol)) } val eraser = new Erasure.Typer -- cgit v1.2.3