aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-12-16 17:10:46 +0100
committerMartin Odersky <odersky@gmail.com>2014-12-16 17:10:46 +0100
commit7c22c0dd3449336877e83ed4aaee0400d8189475 (patch)
tree0315a7d6446322bd670cdb10f5ae3b17d2c3eb47 /src/dotty
parent21fa5dd1a47727c977848163e2610be745951dbc (diff)
downloaddotty-7c22c0dd3449336877e83ed4aaee0400d8189475.tar.gz
dotty-7c22c0dd3449336877e83ed4aaee0400d8189475.tar.bz2
dotty-7c22c0dd3449336877e83ed4aaee0400d8189475.zip
Fix problem with by name params in mixed in methods.
Erasure choked on them before.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/TypeErasure.scala15
-rw-r--r--src/dotty/tools/dotc/transform/ElimByName.scala13
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala2
3 files changed, 24 insertions, 6 deletions
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