aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-06-19 13:41:18 +0200
committerMartin Odersky <odersky@gmail.com>2014-06-19 13:41:18 +0200
commit91e44df57185a32988c22823551d8049b3c43da8 (patch)
tree79d73bb9f528b2f635cb1d8487e4c8a8a5756690 /src/dotty/tools/dotc/core
parent76238566c281b9d87b17c7e361feb649ceb7a6d0 (diff)
downloaddotty-91e44df57185a32988c22823551d8049b3c43da8.tar.gz
dotty-91e44df57185a32988c22823551d8049b3c43da8.tar.bz2
dotty-91e44df57185a32988c22823551d8049b3c43da8.zip
Fixes to lambda abstraction
1) Honor variance of Apply and $hkArgs when instantiating them 2) Eta-lifting a higher-kinded type is straight eta expansion, no arguments are applied.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala14
-rw-r--r--src/dotty/tools/dotc/core/Types.scala7
3 files changed, 17 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index bd323bab5..6a318b0fe 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -460,7 +460,7 @@ class Definitions {
val paramDecls = newScope
for (i <- 0 until vcs.length)
newTypeParam(cls, tpnme.lambdaArgName(i), varianceFlags(vcs(i)), paramDecls)
- newTypeField(cls, tpnme.Apply, EmptyFlags, paramDecls)
+ newTypeField(cls, tpnme.Apply, Covariant, paramDecls)
val parentTraitRefs =
for (i <- 0 until vcs.length if vcs(i) != 0)
yield lambdaTrait(vcs.updated(i, 0)).typeRef
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 9411ed004..3452a499b 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -108,7 +108,7 @@ class TypeApplications(val self: Type) extends AnyVal {
* @param forcing if set, might force completion. If not, never forces
* but returns NoSymbol when it would have to otherwise.
*/
- def LambdaClass(forcing: Boolean)(implicit ctx: Context): Symbol = ctx.traceIndented(i"LambdaClass($self)", hk) { self.stripTypeVar match {
+ def LambdaClass(forcing: Boolean)(implicit ctx: Context): Symbol = track("LambdaClass") { self.stripTypeVar match {
case self: TypeRef =>
val sym = self.symbol
if (sym.isLambdaTrait) sym
@@ -432,7 +432,7 @@ class TypeApplications(val self: Type) extends AnyVal {
val substitutedRHS = (rt: RefinedType) => {
val argRefs = boundSyms.indices.toList.map(i =>
RefinedThis(rt).select(tpnme.lambdaArgName(i)))
- tp.bounds.subst(boundSyms, argRefs)
+ tp.subst(boundSyms, argRefs).bounds.withVariance(1)
}
val res = RefinedType(lambda.typeRef, tpnme.Apply, substitutedRHS)
//println(i"lambda abstract $self wrt $boundSyms%, % --> $res")
@@ -475,8 +475,10 @@ class TypeApplications(val self: Type) extends AnyVal {
param2.variance == param2.variance || param2.variance == 0
if ((tycon.typeParams corresponds tparams)(variancesMatch)) {
val expanded = tycon.EtaExpand
- val res = (expanded /: targs)((partialInst, arg) =>
- RefinedType(partialInst, partialInst.typeParams.head.name, arg.bounds))
+ val res = (expanded /: targs) { (partialInst, targ) =>
+ val tparam = partialInst.typeParams.head
+ RefinedType(partialInst, tparam.name, targ.bounds.withVariance(tparam.variance))
+ }
hk.println(i"eta lifting $self --> $res")
res
}
@@ -484,6 +486,8 @@ class TypeApplications(val self: Type) extends AnyVal {
case nil =>
NoType
}
- if (tparams.isEmpty) NoType else tryLift(self.baseClasses)
+ if (tparams.isEmpty) NoType
+ else if (typeParams.nonEmpty) EtaExpand
+ else tryLift(self.baseClasses)
}
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 794f05319..718d01ebe 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2096,6 +2096,13 @@ object Types {
if (lo eq tp) this
else TypeAlias(tp, variance)
+ /** If this is an alias, a derived alias with the new variance,
+ * Otherwise the type itself.
+ */
+ def withVariance(variance: Int)(implicit ctx: Context) =
+ if (lo ne hi) this
+ else derivedTypeBounds(lo, hi, variance)
+
def contains(tp: Type)(implicit ctx: Context) = tp match {
case tp: TypeBounds => lo <:< tp.lo && tp.hi <:< hi
case _ => lo <:< tp && tp <:< hi