aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-04 11:03:51 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-04 11:03:51 +0100
commitc6e2ca6845352a0cdb82f8cd3b9baec2154b4f61 (patch)
tree2abaa2b9a7abf9ee582cb3a1f09eadb5110781f3
parenteeab526ef293abdb15d1776e470aca59c4697cfd (diff)
downloaddotty-c6e2ca6845352a0cdb82f8cd3b9baec2154b4f61.tar.gz
dotty-c6e2ca6845352a0cdb82f8cd3b9baec2154b4f61.tar.bz2
dotty-c6e2ca6845352a0cdb82f8cd3b9baec2154b4f61.zip
Make anonymous methods non-dependent where possible so that they can be used in closures.
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala14
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala4
3 files changed, 16 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index cf6e3cf91..878e11b67 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -89,22 +89,22 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
untpd.Assign(lhs, rhs).withType(defn.UnitType).checked
def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block =
- untpd.Block(stats, expr).withType(blockType(stats, expr.tpe)).checked
+ untpd.Block(stats, expr).withType(avoid(expr.tpe, localSyms(stats))).checked
- def blockType(stats: List[Tree], exprType: Type)(implicit ctx: Context): Type = {
+ def avoid(tp: Type, syms: => List[Symbol])(implicit ctx: Context): Type = {
val widenMap = new TypeMap {
- lazy val locals = localSyms(stats).toSet
- def isLocal(sym: Symbol) = sym.owner.isTerm && (locals contains sym)
+ lazy val avoided = syms.toSet
+ def toAvoid(sym: Symbol) = sym.owner.isTerm && (avoided contains sym)
def apply(tp: Type) = tp match {
- case tp: TermRef if isLocal(tp.symbol) && variance > 0 =>
+ case tp: TermRef if toAvoid(tp.symbol) && variance > 0 =>
apply(tp.info)
- case tp @ TypeRef(pre: TermRef, _) if tp.symbol.isAliasType && isLocal(pre.symbol) =>
+ case tp @ TypeRef(pre: TermRef, _) if tp.symbol.isAliasType && toAvoid(pre.symbol) =>
apply(tp.info.bounds.hi)
case _ =>
mapOver(tp)
}
}
- widenMap(exprType)
+ widenMap(tp)
}
def maybeBlock(stats: List[Tree], expr: Tree)(implicit ctx: Context): Tree =
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 97114d410..629910e09 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -503,12 +503,16 @@ class Namer { typer: Typer =>
if (isSecondaryConstructor) sym.owner.primaryConstructor.typeParams
else tparams map symbolOfTree
def wrapMethType(restpe: Type): Type = {
+ val paramSymss = vparamss.nestedMap(symbolOfTree)
+ val restpe1 = // try to make anonymous functions non-dependent, so that they can be used in closures
+ if (name == nme.ANON_FUN) tpd.avoid(restpe, paramSymss.flatten)
+ else restpe
val monotpe =
- (vparamss :\ restpe) { (params, restpe) =>
+ (paramSymss :\ restpe1) { (params, restpe) =>
val make =
- if (params.nonEmpty && (params.head.mods is Implicit)) ImplicitMethodType
+ if (params.nonEmpty && (params.head is Implicit)) ImplicitMethodType
else MethodType
- make.fromSymbols(params map symbolOfTree, restpe)
+ make.fromSymbols(params, restpe)
}
if (typeParams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe)
else if (vparamss.isEmpty) ExprType(monotpe)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 4352a17d6..f3e61ee1a 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -487,7 +487,7 @@ class Typer extends Namer with Applications with Implicits {
val exprCtx = index(tree.stats)
val stats1 = typedStats(tree.stats, ctx.owner)
val expr1 = typedExpr(tree.expr, pt)(exprCtx)
- val result = cpy.Block(tree, stats1, expr1).withType(blockType(stats1, expr1.tpe))
+ val result = cpy.Block(tree, stats1, expr1).withType(avoid(expr1.tpe, localSyms(stats1)))
val leaks = CheckTrees.escapingRefs(result)
if (leaks.isEmpty) result
else if (isFullyDefined(pt, ForceDegree.all)) {
@@ -606,7 +606,7 @@ class Typer extends Namer with Applications with Implicits {
(pt, TypeTree(pt))
case _ =>
if (!mt.isDependent) (mt.toFunctionType, EmptyTree)
- else throw new Error(s"internal error: cannot turn dependent method type $mt into closure, position = ${tree.pos}") // !!! DEBUG. Eventually, convert to an error?
+ else throw new Error(i"internal error: cannot turn dependent method type $mt into closure, position = ${tree.pos}, raw type = ${mt.toString}") // !!! DEBUG. Eventually, convert to an error?
}
case tp =>
throw new Error(i"internal error: closing over non-method $tp, pos = ${tree.pos}")