diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-07-23 14:30:21 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-07-23 14:36:57 +1000 |
commit | 93bee55e68522a46e501229dd0d5f2af4b72ac4a (patch) | |
tree | aa9b4158e1959b10c53e5e22c30d5b83eb5b0e97 /src/reflect | |
parent | 342afbd52add51d616a68df531e882a8990c1192 (diff) | |
download | scala-93bee55e68522a46e501229dd0d5f2af4b72ac4a.tar.gz scala-93bee55e68522a46e501229dd0d5f2af4b72ac4a.tar.bz2 scala-93bee55e68522a46e501229dd0d5f2af4b72ac4a.zip |
SI-9408 Avoid capturing outer class in local classes.
Previously, only local classes declared final would be candidates
for outer pointer elision in the constructor phase.
This commit infers finality of local classes to expand the scope
of this optimization.
== Background ==
This was brought to our attention when shapeless enabled
indylambda and found that a hitherto serializable
data structure started to capture the enclosing class and hence
lost its serializability.
class NotSerializable {
def test = () => {
class C; assertSerializable(new C)
}
}
Under `-Ydelambdafy:inline`, it used to capture the enclosing anon
function class as its outer, which, being final, didn't in turn
capture the enclosing class.
class NotSerializable {
def test = new anonFun$1
}
class anonFun$1 {
def apply = assertSerializable(new C(this))
}
class ...$C(outer$: anonFun)
indylambda perturbs the enclosing structure of the function body.
class NotSerializable {
def anonFun$1 = {class C; assertSerializable(new C()))
def test = lambdaMetaFactory(<<anonFun$1>>)
}
Which leads to:
class NotSerializable$C(outer$: NotSerializable)
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 15ab97dc3f..ff26ce26ac 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -992,6 +992,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => isPrivate || isLocalToBlock ) + || isClass && originalOwner.isTerm && children.isEmpty // we track known subclasses of term-owned classes, use that infer finality ) /** Is this symbol effectively final or a concrete term member of sealed class whose children do not override it */ final def isEffectivelyFinalOrNotOverridden: Boolean = isEffectivelyFinal || (isTerm && !isDeferred && isNotOverridden) |