diff options
author | Martin Odersky <odersky@gmail.com> | 2014-10-29 11:52:43 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-11-09 10:17:34 +0100 |
commit | 936e83f3617e7dd1b9141cf20b1dc8ec3482df97 (patch) | |
tree | c268d2f3b199c80d0a5298070e49621f8c260331 | |
parent | 252b6d9f3a80bdfc789e2f5b463ee7dc7a10b659 (diff) | |
download | dotty-936e83f3617e7dd1b9141cf20b1dc8ec3482df97.tar.gz dotty-936e83f3617e7dd1b9141cf20b1dc8ec3482df97.tar.bz2 dotty-936e83f3617e7dd1b9141cf20b1dc8ec3482df97.zip |
New phase: RestoreScopes
Cleans up after LambdaLift and Flatten. RestoreScopes exhibited a problem (double definition)
when compiling Unpickler. The root of the problem was in Applications.scala. The effect was
that arguments woulkd be lifted out, but then the argument expression would be used anyway. That caused
a closure to be present twice which caused the double def error much later. -Ycheck did not catch it because
the two closure expressions were in non-overlapping scopes.
-rw-r--r-- | src/dotty/tools/dotc/Compiler.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/RestoreScopes.scala | 36 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 2 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 |
4 files changed, 40 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index cb70480ce..d4fa7e671 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -56,7 +56,8 @@ class Compiler { List(new CapturedVars, new Constructors), List(new LambdaLift, - new Flatten) + new Flatten, + new RestoreScopes) ) var runId = 1 diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala new file mode 100644 index 000000000..4a4252326 --- /dev/null +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -0,0 +1,36 @@ +package dotty.tools.dotc +package transform + +import core._ +import DenotTransformers.IdentityDenotTransformer +import Contexts.Context +import Symbols._ +import Scopes._ +import collection.mutable +import TreeTransforms.MiniPhaseTransform +import ast.Trees._ +import TreeTransforms.TransformerInfo + +/** The preceding lambda lift and flatten phases move symbols to different scopes + * and rename them. This miniphase cleans up afterwards and makes sure that all + * class scopes contain the symbols defined in them. + */ +class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform => + import ast.tpd._ + override def phaseName = "restoreScopes" + + override def treeTransformPhase = thisTransform.next + + override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = { + val TypeDef(_, _, Template(constr, _, _, body)) = tree + val restoredDecls = newScope + for (stat <- constr :: body) + if (stat.isInstanceOf[MemberDef] && stat.symbol.exists) + restoredDecls.enter(stat.symbol) + val cinfo = tree.symbol.asClass.classInfo + tree.symbol.copySymDenotation( + info = cinfo.derivedClassInfo( // Dotty deviation: Cannot expand cinfo inline without a type error + decls = restoredDecls: Scope)).installAfter(thisTransform) + tree + } +} diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index 035f19028..a237e7781 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -461,7 +461,7 @@ trait Applications extends Compatibility { self: Typer => val result = { var typedArgs = typedArgBuf.toList - val app0 = cpy.Apply(app)(normalizedFun, typedArgs) + def app0 = cpy.Apply(app)(normalizedFun, typedArgs) // needs to be a `def` because typedArgs can change later val app1 = if (!success) app0.withType(ErrorType) else { diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index ac1fbe735..a52f79abd 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -15,7 +15,7 @@ class tests extends CompilerTest { implicit val defaultOptions = noCheckOptions ++ List( "-Yno-deep-subtypes", - "-Ycheck:patternMatcher,gettersSetters,flatten" + "-Ycheck:patternMatcher,gettersSetters,restoreScopes" ) val twice = List("#runs", "2", "-YnoDoubleBindings") |