aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-05-07 19:06:17 +0200
committerSamuel Gruetter <samuel.gruetter@epfl.ch>2014-05-20 13:38:49 +0200
commitfb3dba1bac13a755d2304928cbd49e7dde6f1bf9 (patch)
treea4e712103779decdebc439e33aa2c3f8f16890e8 /src/dotty/tools/dotc
parentf7910005038c188e573e8d1a42ff3e31c69c90c1 (diff)
downloaddotty-fb3dba1bac13a755d2304928cbd49e7dde6f1bf9.tar.gz
dotty-fb3dba1bac13a755d2304928cbd49e7dde6f1bf9.tar.bz2
dotty-fb3dba1bac13a755d2304928cbd49e7dde6f1bf9.zip
Avoid hoisting of local classes out of method bodies.
Doing so is unsound. We instead approximate local classes by their parents, but only if the expected type is not fully defined. This makes the test t2421_delitedsl1.scala in the commit pass. The oter test, blockEscapesNeg.scala is modified to fail. Previously it failed outright but with the new rules the nested class Bar is approximated to Object. That means that the block containing `Foo.Bar` typechecks, but with type `Object` instead of the unreachable `Bar`.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala12
3 files changed, 10 insertions, 5 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index 832544706..254f002c1 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -34,6 +34,7 @@ object CheckTrees {
tp namedPartsWith (tp => isLocal(tp.symbol))
def typeLeaks(tp: Type): Boolean = leakingTypes(tp).nonEmpty
def classLeaks(sym: ClassSymbol): Boolean =
+ (ctx.owner is Method) || // can't hoist classes out of method bodies
(sym.info.parents exists typeLeaks) ||
(sym.decls.toList exists (t => typeLeaks(t.info)))
leakingTypes(block.tpe)
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index bd44ccac5..9e34d549a 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -58,7 +58,7 @@ trait Inferencing { this: Checking =>
}
private var toMaximize: Boolean = false
def apply(x: Boolean, tp: Type): Boolean = tp.dealias match {
- case _: WildcardType =>
+ case _: WildcardType | _: ProtoType =>
false
case tvar: TypeVar if !tvar.isInstantiated =>
if (force == ForceDegree.none) false
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 13f65d424..48c263085 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -52,10 +52,14 @@ trait TypeAssigner {
def apply(tp: Type) = tp match {
case tp: TermRef if toAvoid(tp) && variance > 0 =>
apply(tp.info)
- case tp: TypeRef if toAvoid(tp.prefix) =>
+ case tp: TypeRef if (forbidden contains tp.symbol) || toAvoid(tp.prefix) =>
tp.info match {
- case TypeAlias(ref) => apply(ref)
- case _ => mapOver(tp)
+ case TypeAlias(ref) =>
+ apply(ref)
+ case info: ClassInfo =>
+ mapOver(info.instantiatedParents.reduceLeft(AndType(_, _)))
+ case _ =>
+ mapOver(tp)
}
case tp: RefinedType =>
val tp1 @ RefinedType(parent1, _) = mapOver(tp)
@@ -247,7 +251,7 @@ trait TypeAssigner {
tree.withType(defn.UnitType)
def assignType(tree: untpd.Block, stats: List[Tree], expr: Tree)(implicit ctx: Context) =
- tree.withType(avoid(expr.tpe, localSyms(stats)))
+ tree.withType(avoid(expr.tpe, localSyms(stats) filter (_.isTerm)))
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) =
tree.withType(thenp.tpe | elsep.tpe)