diff options
author | Martin Odersky <odersky@gmail.com> | 2014-01-04 11:03:51 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-01-04 11:03:51 +0100 |
commit | c6e2ca6845352a0cdb82f8cd3b9baec2154b4f61 (patch) | |
tree | 2abaa2b9a7abf9ee582cb3a1f09eadb5110781f3 /src/dotty/tools/dotc | |
parent | eeab526ef293abdb15d1776e470aca59c4697cfd (diff) | |
download | dotty-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.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 4 |
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}") |