summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-07-23 14:30:21 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-07-23 14:36:57 +1000
commit93bee55e68522a46e501229dd0d5f2af4b72ac4a (patch)
treeaa9b4158e1959b10c53e5e22c30d5b83eb5b0e97 /src/reflect
parent342afbd52add51d616a68df531e882a8990c1192 (diff)
downloadscala-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.scala1
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)