aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Typer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-01-18 12:03:59 +0100
committerMartin Odersky <odersky@gmail.com>2014-01-18 12:05:23 +0100
commitcb3adb9ff93c45101150dd71b927295e327b3c81 (patch)
tree5fe09e319c738259e0f37f81c5ced22323fbce3d /src/dotty/tools/dotc/typer/Typer.scala
parent5a5806b4c5fb6678d63d9f1da06669447cb97eab (diff)
downloaddotty-cb3adb9ff93c45101150dd71b927295e327b3c81.tar.gz
dotty-cb3adb9ff93c45101150dd71b927295e327b3c81.tar.bz2
dotty-cb3adb9ff93c45101150dd71b927295e327b3c81.zip
Refine avoiding local refs in block's type.
If all else fails, force all type variables with fullyDefinedType. This can avoid references to locals. Example in file dotctest: SourceFile.scala, method calculateLineIndices.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index cc142e7bf..d16ec53ae 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -511,14 +511,30 @@ class Typer extends Namer with Applications with Implicits {
val stats1 = typedStats(tree.stats, ctx.owner)
val expr1 = typedExpr(tree.expr, pt)(exprCtx)
val result = cpy.Block(tree, stats1, expr1).withType(avoid(expr1.tpe, localSyms(stats1)))
- val leaks = CheckTrees.escapingRefs(result)
- if (leaks.isEmpty) result
+ checkNoLocalRefs(result, pt)
+ }
+
+ /** Check that block's type can be expressed without references to locally defined
+ * symbols. The following two remedies are tried before giving up:
+ * 1. If the expected type of the block is fully defined, pick it as the
+ * type of the result expressed by adding a type ascription.
+ * 2. If (1) fails, force all type variables so that the block's type is
+ * fully defined and try again.
+ */
+ def checkNoLocalRefs(block: Block, pt: Type, forcedDefined: Boolean = false)(implicit ctx: Context): Tree = {
+ val Block(stats, expr) = block
+ val leaks = CheckTrees.escapingRefs(block)
+ if (leaks.isEmpty) block
else if (isFullyDefined(pt, ForceDegree.all)) {
- val expr2 = typed(untpd.Typed(untpd.TypedSplice(expr1), untpd.TypeTree(pt)))
- untpd.Block(stats1, expr2) withType expr2.tpe
+ val expr1 = typed(untpd.Typed(untpd.TypedSplice(expr), untpd.TypeTree(pt)))
+ untpd.Block(stats, expr1) withType expr1.tpe
+ } else if (!forcedDefined) {
+ fullyDefinedType(block.tpe, "block", block.pos)
+ val block1 = block.withType(avoid(block.tpe, localSyms(stats)))
+ checkNoLocalRefs(block1, pt, forcedDefined = true)
} else
- errorTree(result,
- i"local definition of ${leaks.head.name} escapes as part of block's type ${result.tpe}"/*; full type: ${result.tpe.toString}"*/)
+ errorTree(block,
+ i"local definition of ${leaks.head.name} escapes as part of block's type ${block.tpe}"/*; full type: ${result.tpe.toString}"*/)
}
def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) = track("typedIf") {