summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-01-17 20:32:05 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-01-17 20:32:05 -0800
commitea01bf9670c987a99fdd88bf771da04d82421f5d (patch)
tree5533c51c3d3690f41182bd0e66265a06d20c6440
parent94e64238834541be1afb1e8e1da09b18b9b3520c (diff)
parentd5801b9eee7df49894c05dea430a56190cae2112 (diff)
downloadscala-ea01bf9670c987a99fdd88bf771da04d82421f5d.tar.gz
scala-ea01bf9670c987a99fdd88bf771da04d82421f5d.tar.bz2
scala-ea01bf9670c987a99fdd88bf771da04d82421f5d.zip
Merge commit 'd5801b9eee' from 2.10.x into master
Conflicts: src/compiler/scala/tools/nsc/typechecker/Typers.scala
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala23
-rw-r--r--test/files/pos/t8111.scala24
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 5d0d5392dd..9b7c79b614 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3326,6 +3326,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// 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 {
@@ -3354,6 +3376,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
} else {
+ rollbackNamesDefaultsOwnerChanges()
tryTupleApply orElse 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
+}