aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast/CheckTrees.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/ast/CheckTrees.scala')
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala43
1 files changed, 23 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index a004789e6..b1806df4b 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -17,6 +17,27 @@ object CheckTrees {
check(bounds contains arg.tpe)
}
+ def escapingRefs(block: Block)(implicit ctx: Context): Set[NamedType] = {
+ var hoisted: Set[Symbol] = Set()
+ lazy val locals = localSyms(block.stats).toSet
+ def isNonLocal(sym: Symbol): Boolean =
+ !(locals contains sym) || isHoistableClass(sym)
+ def isHoistableClass(sym: Symbol) =
+ sym.isClass && {
+ (hoisted contains sym) || {
+ hoisted += sym
+ !classLeaks(sym.asClass)
+ }
+ }
+ def leakingTypes(tp: Type): Set[NamedType] =
+ tp namedPartsWith (tp => isNonLocal(tp.symbol))
+ def typeLeaks(tp: Type) = leakingTypes(tp).isEmpty
+ def classLeaks(sym: ClassSymbol): Boolean =
+ (sym.info.parents exists typeLeaks) ||
+ (sym.decls.toList exists (t => typeLeaks(t.info)))
+ leakingTypes(block.tpe)
+ }
+
def checkType(tree: Tree)(implicit ctx: Context): Unit = tree match {
case Ident(name) =>
case Select(qualifier, name) =>
@@ -79,27 +100,9 @@ object CheckTrees {
check(false)
}
check(rhs.tpe <:< lhs.tpe.widen)
- case Block(stats, expr) =>
- var hoisted: Set[Symbol] = Set()
- lazy val locals = localSyms(stats).toSet
+ case tree @ Block(stats, expr) =>
check(expr.isValue)
- def isNonLocal(sym: Symbol): Boolean =
- !(locals contains sym) || isHoistableClass(sym)
- def isHoistableClass(sym: Symbol) =
- sym.isClass && {
- (hoisted contains sym) || {
- hoisted += sym
- noLeaksInClass(sym.asClass)
- }
- }
- def noLeaksIn(tp: Type): Boolean = tp forallParts {
- case tp: NamedType => isNonLocal(tp.symbol)
- case _ => true
- }
- def noLeaksInClass(sym: ClassSymbol): Boolean =
- (sym.info.parents forall noLeaksIn) &&
- (sym.decls.toList forall (t => noLeaksIn(t.info)))
- check(noLeaksIn(tree.tpe))
+ check(escapingRefs(tree).isEmpty)
case If(cond, thenp, elsep) =>
check(cond.isValue); check(thenp.isValue); check(elsep.isValue)
check(cond.tpe.derivesFrom(defn.BooleanClass))