aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-10-20 09:47:21 +0200
committerMartin Odersky <odersky@gmail.com>2015-10-24 10:34:51 +0200
commita415ca1ab713f92788262057d9810d937dc7499a (patch)
tree309b87812b05d0be733b09abdd78b2ecfb7b6c3b /src/dotty
parent87098e63c2796387c598513a2af2d8f2d1aae91b (diff)
downloaddotty-a415ca1ab713f92788262057d9810d937dc7499a.tar.gz
dotty-a415ca1ab713f92788262057d9810d937dc7499a.tar.bz2
dotty-a415ca1ab713f92788262057d9810d937dc7499a.zip
Allow existential types in hk types
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala44
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala3
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala29
4 files changed, 35 insertions, 43 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 58a6d226d..3fe5afb33 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -846,14 +846,16 @@ object Types {
* (*) normalizes means: follow instantiated typevars and aliases.
*/
def lookupRefined(name: Name)(implicit ctx: Context): Type = {
- def loop(pre: Type, resolved: List[Name]): Type = pre.stripTypeVar match {
+ def loop(pre: Type): Type = pre.stripTypeVar match {
case pre: RefinedType =>
object instantiate extends TypeMap {
var isSafe = true
def apply(tp: Type): Type = tp match {
case TypeRef(RefinedThis(`pre`), name) if name.isLambdaArgName =>
- val TypeAlias(alias) = member(name).info
- alias
+ member(name).info match {
+ case TypeAlias(alias) => alias
+ case _ => isSafe = false; tp
+ }
case tp: TypeVar if !tp.inst.exists =>
isSafe = false
tp
@@ -861,23 +863,37 @@ object Types {
mapOver(tp)
}
}
- def betaReduce(tp: Type) = {
- val lam = pre.parent.LambdaClass(forcing = false)
- if (lam.exists && lam.typeParams.forall(tparam => resolved.contains(tparam.name))) {
- val reduced = instantiate(tp)
+ def instArg(tp: Type): Type = tp match {
+ case tp @ TypeAlias(TypeRef(RefinedThis(`pre`), name)) if name.isLambdaArgName =>
+ member(name).info match {
+ case TypeAlias(alias) => tp.derivedTypeAlias(alias) // needed to keep variance
+ case bounds => bounds
+ }
+ case _ =>
+ instantiate(tp)
+ }
+ def instTop(tp: Type): Type = tp.stripTypeVar match {
+ case tp: RefinedType =>
+ tp.derivedRefinedType(instTop(tp.parent), tp.refinedName, instArg(tp.refinedInfo))
+ case _ =>
+ instantiate(tp)
+ }
+ /** Reduce rhs of $hkApply to make it stand alone */
+ def betaReduce(tp: Type) =
+ if (pre.parent.isSafeLambda) {
+ val reduced = instTop(tp)
if (instantiate.isSafe) reduced else NoType
}
else NoType
- }
pre.refinedInfo match {
case TypeAlias(alias) =>
- if (pre.refinedName ne name) loop(pre.parent, pre.refinedName :: resolved)
+ if (pre.refinedName ne name) loop(pre.parent)
else if (!pre.refinementRefersToThis) alias
else alias match {
case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1)
case _ => if (name == tpnme.hkApply) betaReduce(alias) else NoType // (2)
}
- case _ => loop(pre.parent, resolved)
+ case _ => loop(pre.parent)
}
case RefinedThis(binder) =>
binder.lookupRefined(name)
@@ -887,14 +903,14 @@ object Types {
WildcardType
case pre: TypeRef =>
pre.info match {
- case TypeAlias(alias) => loop(alias, resolved)
+ case TypeAlias(alias) => loop(alias)
case _ => NoType
}
case _ =>
NoType
}
- loop(this, Nil)
+ loop(this)
}
/** The type <this . name> , reduced if possible */
@@ -1886,6 +1902,10 @@ object Types {
s"variance mismatch for $this, $cls, ${cls.typeParams}, ${cls.typeParams.apply(refinedName.LambdaArgIndex).variance}, ${refinedInfo.variance}")
case _ =>
}
+ if (Config.checkProjections &&
+ (refinedName == tpnme.hkApply || refinedName.isLambdaArgName) &&
+ parent.noHK)
+ assert(false, s"illegal refinement of first-order type: $this")
this
}
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 7a25a9870..fc4427277 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -71,7 +71,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
/** Check bounds of AppliedTypeTrees.
* Replace type trees with TypeTree nodes.
* Replace constant expressions with Literal nodes.
- * Note: Demanding idempotency instead of purityin literalize is strictly speaking too loose.
+ * Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
* Example
*
* object O { final val x = 42; println("43") }
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 7225ede14..25030012c 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -344,10 +344,9 @@ trait TypeAssigner {
def assignType(tree: untpd.Return)(implicit ctx: Context) =
tree.withType(defn.NothingType)
- def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) = {
+ def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) =
if (cases.isEmpty) tree.withType(expr.tpe)
else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes))
- }
def assignType(tree: untpd.SeqLiteral, elems: List[Tree])(implicit ctx: Context) = tree match {
case tree: JavaSeqLiteral =>
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 6510ba35b..745eee8f8 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -848,34 +848,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
val args1 = args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]]
// check that arguments conform to bounds is done in phase PostTyper
- val tree1 = assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1)
- if (tree1.tpe.isHKApply)
- for (arg @ TypeBoundsTree(_, _) <- args1)
- ctx.error("illegal wildcard type argument; does not correspond to type parameter of a class", arg.pos)
- // The reason for outlawing such arguments is illustrated by the following example.
- // Say we have
- //
- // type RMap[A, B] = Map[B, A]
- //
- // Then
- //
- // Rmap[_, Int]
- //
- // translates to
- //
- // Lambda$I { type hk$0; type hk$1 = Int; type $apply = Map[$hk1, $hk0] } # $apply
- //
- // Let's call the last type T. You would expect that
- //
- // Map[Int, String] <: RMap[_, Int]
- //
- // But that's not the case given the standard subtyping rules. In fact, the rhs reduces to
- //
- // Map[Int, T # $hk0]
- //
- // That means the second argument to `Map` is unknown and String is certainly not a subtype of it.
- // To avoid the surprise we outlaw problematic wildcard arguments from the start.
- tree1
+ assignType(cpy.AppliedTypeTree(tree)(tpt1, args1), tpt1, args1)
}
}