aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-10-17 15:35:11 +0200
committerMartin Odersky <odersky@gmail.com>2014-10-26 16:24:00 +0100
commit3fea9472c0d068bc08ae764429ca6b4bca95bcd8 (patch)
tree06a7a208ec8e4afb1a3a964d64fb22e594c74c0c /src/dotty/tools/dotc/typer
parent25a8937f115ed2ac1af33c41c73a621dab4ee712 (diff)
downloaddotty-3fea9472c0d068bc08ae764429ca6b4bca95bcd8.tar.gz
dotty-3fea9472c0d068bc08ae764429ca6b4bca95bcd8.tar.bz2
dotty-3fea9472c0d068bc08ae764429ca6b4bca95bcd8.zip
Avoid hoisting local classes
The patch disables hoisting of classes local to a block into the result type of the block. Instead, we widen the result type of the block to one which reflects all refinements made to the parents type of the local class. Test cases in avoid.scala, t1569.scala. The original t1569.scala no longer works. Why is explained in neg/t1569-failedAvoid.scala
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala16
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala11
2 files changed, 16 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index ccf67b55b..cb6fefab1 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -49,7 +49,21 @@ trait TypeAssigner {
case TypeAlias(ref) =>
apply(ref)
case info: ClassInfo =>
- mapOver(info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _)))
+ val parentType = info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _))
+ def addRefinement(parent: Type, decl: Symbol) = {
+ val inherited = parentType.findMember(decl.name, info.cls.thisType, Private)
+ val inheritedInfo = inherited.atSignature(decl.info .signature).info
+ if (inheritedInfo.exists && decl.info <:< inheritedInfo && !(inheritedInfo <:< decl.info))
+ typr.echo(
+ i"add ref $parent $decl --> ",
+ RefinedType(parent, decl.name, decl.info))
+ else
+ parent
+ }
+ val refinableDecls = info.decls.filterNot(
+ sym => sym.is(TypeParamAccessor | Private) || sym.isConstructor)
+ val fullType = (parentType /: refinableDecls)(addRefinement)
+ mapOver(fullType)
case _ =>
mapOver(tp)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 80eb5965c..1cab2fa46 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -415,17 +415,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def escapingRefs(block: Block)(implicit ctx: Context): collection.Set[NamedType] = {
var hoisted: Set[Symbol] = Set()
lazy val locals = localSyms(block.stats).toSet
- def isLocal(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): collection.Set[NamedType] =
- tp namedPartsWith (tp => isLocal(tp.symbol))
+ tp namedPartsWith (tp => locals.contains(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