diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-12 09:25:57 -0800 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-12 09:25:57 -0800 |
commit | d5801b9eee7df49894c05dea430a56190cae2112 (patch) | |
tree | d676cb68db2a612075972c975554503bbffd9cdc | |
parent | a8122413c0cf2e51cdfd32c0450b91910f8a8cc2 (diff) | |
parent | c91d373a78f0c503ddc635bce1974c1b58008219 (diff) | |
download | scala-d5801b9eee7df49894c05dea430a56190cae2112.tar.gz scala-d5801b9eee7df49894c05dea430a56190cae2112.tar.bz2 scala-d5801b9eee7df49894c05dea430a56190cae2112.zip |
Merge pull request #3328 from retronym/ticket/8111v2.10.4-RC2
Repair symbol owners after abandoned named-/default-args
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 23 | ||||
-rw-r--r-- | test/files/pos/t8111.scala | 24 |
2 files changed, 47 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 40313bdb5d..e09a509839 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3269,6 +3269,28 @@ trait Typers extends Modes with Adaptations with Tags { // calls to the default getters. Example: // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a)) checkNotMacro() + + // SI-8111 transformNamedApplication eagerly shuffles around the application to preserve + // evaluation order. During this process, it calls `changeOwner` on symbols that + // are transplanted underneath synthetic temporary vals. + // + // Here, we keep track of the symbols owned by `context.owner` to enable us to + // rollback, so that we don't end up with "orphaned" symbols. + // + // TODO: Find a better way! + // + // Note that duplicating trees would not be enough to fix this problem, we would also need to + // clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator), + // or, better yet, disentangle the logic in `transformNamedApplication` so that we could + // determine whether names/defaults is viable *before* transforming trees. + def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner + val symsOwnedByContextOwner = tree.collect { + case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol + } + def rollbackNamesDefaultsOwnerChanges() { + symsOwnedByContextOwner foreach (_.owner = context.owner) + } + val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x) if (fun1.isErroneous) duplErrTree else { @@ -3297,6 +3319,7 @@ trait Typers extends Modes with Adaptations with Tags { if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { + rollbackNamesDefaultsOwnerChanges() tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } diff --git a/test/files/pos/t8111.scala b/test/files/pos/t8111.scala new file mode 100644 index 0000000000..0d63a16ba4 --- /dev/null +++ b/test/files/pos/t8111.scala @@ -0,0 +1,24 @@ +trait T { + + def crashy(ma: Any) { + // okay + val f1 = (u: Unit) => ma + foo(f1)() + foo((u: Unit) => ma) + foo(0, (u: Any) => ma) apply () + + // crash due to side effects on the onwer of the symbol in the + // qualifier or arguments of the application during an abandoned + // names/defaults transform. The code type checkes because of + // autp-tupling which promotes and empty parmater list to `(): Unit` + foo((u: Any) => ma)() + + {{(u: Any) => ma}; this}.foo(0)() + + foo({def foo = ma; 0})() + + {def foo = ma; this}.foo(0)() + } + + def foo(f: Any): Any => Any +} |