diff options
author | Martin Odersky <odersky@gmail.com> | 2015-10-20 09:47:21 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-10-24 10:34:51 +0200 |
commit | a415ca1ab713f92788262057d9810d937dc7499a (patch) | |
tree | 309b87812b05d0be733b09abdd78b2ecfb7b6c3b /src/dotty | |
parent | 87098e63c2796387c598513a2af2d8f2d1aae91b (diff) | |
download | dotty-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.scala | 44 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 29 |
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) } } |