Skip to content

Commit ca03148

Browse files
committed
Merge pull request #296 from dotty-staging/fix/#288-by-name-params-in-mixins
Fix problem with by name params in mixed in methods.
2 parents d489eb4 + 7c22c0d commit ca03148

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

src/dotty/tools/dotc/TypeErasure.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ object TypeErasure {
119119
* treated. `eraseInfo` maps them them to nullary method types, whereas `erasure` maps them
120120
* to `Function0`.
121121
*/
122-
def eraseInfo(tp: Type)(implicit ctx: Context): Type = scalaErasureFn.eraseInfo(tp)(erasureCtx)
122+
def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
123+
scalaErasureFn.eraseInfo(tp, sym)(erasureCtx)
123124

124125
/** The erasure of a function result type. Differs from normal erasure in that
125126
* Unit is kept instead of being mapped to BoxedUnit.
@@ -145,7 +146,7 @@ object TypeErasure {
145146
if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
146147
else if (sym.isAbstractType) TypeAlias(WildcardType)
147148
else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
148-
else eraseInfo(tp)(erasureCtx) match {
149+
else eraseInfo(tp, sym)(erasureCtx) match {
149150
case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) =>
150151
defn.BoxedUnitClass.typeRef
151152
case einfo =>
@@ -347,8 +348,14 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
347348
else JavaArrayType(this(elemtp))
348349
}
349350

350-
def eraseInfo(tp: Type)(implicit ctx: Context) = tp match {
351-
case ExprType(rt) => MethodType(Nil, Nil, eraseResult(rt))
351+
def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match {
352+
case ExprType(rt) =>
353+
if (sym is Param) apply(tp)
354+
// Note that params with ExprTypes are eliminated by ElimByName,
355+
// but potentially re-introduced by ResolveSuper, when we add
356+
// forwarders to mixin methods.
357+
// See doc comment for ElimByName for speculation how we could improve this.
358+
else MethodType(Nil, Nil, eraseResult(rt))
352359
case tp => erasure(tp)
353360
}
354361

src/dotty/tools/dotc/transform/ElimByName.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import ast.Trees._
2222
*
2323
* => T ==> () => T
2424
*
25-
* Note that `=> T` types are not eliminated in MnethodTypes. This is done later at erasure.
25+
* Note that `=> T` types are not eliminated in MethodTypes. This is done later at erasure.
2626
* Terms are rewritten as follows:
2727
*
2828
* x ==> x.apply() if x is a parameter that had type => T
@@ -41,6 +41,17 @@ import ast.Trees._
4141
* DummyApply: [T](() => T): T
4242
*
4343
* is a synthetic method defined in Definitions. Erasure will later strip these DummyApply wrappers.
44+
*
45+
* Note: This scheme to have inconsistent types between method types (whose formal types are still
46+
* ExprTypes and parameter valdefs (which are now FunctionTypes) is not pretty. There are two
47+
* other options which have been abandoned or not yet pursued.
48+
*
49+
* Option 1: Transform => T to () => T also in method and function types. The problem with this is
50+
* that is that it rewuires to look at every type, and this forces too much, causing
51+
* Cyclic Reference errors. Abandoned for this reason.
52+
*
53+
* Option 2: Merge ElimByName with erasure, or have it run immediately before. This has not been
54+
* tried yet.
4455
*/
4556
class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransformer =>
4657
import ast.tpd._

src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
6262
}
6363
}
6464
case ref =>
65-
ref.derivedSingleDenotation(ref.symbol, eraseInfo(ref.info))
65+
ref.derivedSingleDenotation(ref.symbol, eraseInfo(ref.info, ref.symbol))
6666
}
6767

6868
val eraser = new Erasure.Typer

0 commit comments

Comments
 (0)