Skip to content

Commit ea01bf9

Browse files
committed
Merge commit 'd5801b9eee' from 2.10.x into master
Conflicts: src/compiler/scala/tools/nsc/typechecker/Typers.scala
2 parents 94e6423 + d5801b9 commit ea01bf9

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3326,6 +3326,28 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
33263326
// calls to the default getters. Example:
33273327
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
33283328
checkNotMacro()
3329+
3330+
// SI-8111 transformNamedApplication eagerly shuffles around the application to preserve
3331+
// evaluation order. During this process, it calls `changeOwner` on symbols that
3332+
// are transplanted underneath synthetic temporary vals.
3333+
//
3334+
// Here, we keep track of the symbols owned by `context.owner` to enable us to
3335+
// rollback, so that we don't end up with "orphaned" symbols.
3336+
//
3337+
// TODO: Find a better way!
3338+
//
3339+
// Note that duplicating trees would not be enough to fix this problem, we would also need to
3340+
// clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator),
3341+
// or, better yet, disentangle the logic in `transformNamedApplication` so that we could
3342+
// determine whether names/defaults is viable *before* transforming trees.
3343+
def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner
3344+
val symsOwnedByContextOwner = tree.collect {
3345+
case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol
3346+
}
3347+
def rollbackNamesDefaultsOwnerChanges() {
3348+
symsOwnedByContextOwner foreach (_.owner = context.owner)
3349+
}
3350+
33293351
val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
33303352
if (fun1.isErroneous) duplErrTree
33313353
else {
@@ -3354,6 +3376,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
33543376
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
33553377
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
33563378
} else {
3379+
rollbackNamesDefaultsOwnerChanges()
33573380
tryTupleApply orElse duplErrorTree(NotEnoughArgsError(tree, fun, missing))
33583381
}
33593382
}

test/files/pos/t8111.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
trait T {
2+
3+
def crashy(ma: Any) {
4+
// okay
5+
val f1 = (u: Unit) => ma
6+
foo(f1)()
7+
foo((u: Unit) => ma)
8+
foo(0, (u: Any) => ma) apply ()
9+
10+
// crash due to side effects on the onwer of the symbol in the
11+
// qualifier or arguments of the application during an abandoned
12+
// names/defaults transform. The code type checkes because of
13+
// autp-tupling which promotes and empty parmater list to `(): Unit`
14+
foo((u: Any) => ma)()
15+
16+
{{(u: Any) => ma}; this}.foo(0)()
17+
18+
foo({def foo = ma; 0})()
19+
20+
{def foo = ma; this}.foo(0)()
21+
}
22+
23+
def foo(f: Any): Any => Any
24+
}

0 commit comments

Comments
 (0)