summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Symbols.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-07-25 15:21:16 -0700
committerPaul Phillips <paulp@improving.org>2012-07-26 10:04:20 -0700
commitadeffda25e94ed0206d35bdb9b42523227a89f8c (patch)
tree1c07a172eadb99b5854ccee6c288097df4e24fe0 /src/reflect/scala/reflect/internal/Symbols.scala
parentfe513d1f147e60988414b01e5928811bb6f78714 (diff)
downloadscala-adeffda25e94ed0206d35bdb9b42523227a89f8c.tar.gz
scala-adeffda25e94ed0206d35bdb9b42523227a89f8c.tar.bz2
scala-adeffda25e94ed0206d35bdb9b42523227a89f8c.zip
Refined isEffectivelyFinal logic for sealedness.
If the enclosing class of a method is sealed and has only final subclasses, then the method is effectively final in the sealed class if none of the subclasses overrides it. This makes it possible to inline more methods without explicitly marking them final. Note that the test doesn't fail before this patch due to SI-6142, a bug in the optimizer, but here's a bytecode diff to prove it: @@ -16,8 +16,10 @@ public final class Test$ { Code: : getstatic // Field Foo$.MODULE$:LFoo$; : invokevirtual // Method Foo$.mkFoo:()LFoo; +: pop : bipush -: invokevirtual // Method Foo.bar:(I)I +: iconst_1 +: iadd : ireturn And the test in neg, which is manually made to fail due to the absence of inline warnings, correctly refuses to inline the methods. Review by @dragos.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Symbols.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 636f1e2f01..7e6de14295 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -191,7 +191,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
} else None
}
-
+
// Begin Reflection Helpers
// Replaces a repeated parameter type at the end of the parameter list
@@ -354,7 +354,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val selection = select(alts, defaultFilteringOps)
val knownApplicable = applicable(selection)
-
+
if (knownApplicable.size == 1) knownApplicable.head
else NoSymbol
}
@@ -1016,6 +1016,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isTopLevelModule = hasFlag(MODULE) && owner.isPackageClass
+ /** A helper function for isEffectivelyFinal. */
+ private def isNotOverridden = (
+ owner.isClass && (
+ owner.isEffectivelyFinal
+ || owner.isSealed && owner.children.forall(c => c.isEffectivelyFinal && (overridingSymbol(c) == NoSymbol))
+ )
+ )
+
/** Is this symbol effectively final? I.e, it cannot be overridden */
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
@@ -1023,8 +1031,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| isTerm && (
isPrivate
|| isLocal
- || owner.isClass && owner.isEffectivelyFinal
- )
+ || isNotOverridden
+ )
)
/** Is this symbol locally defined? I.e. not accessed from outside `this` instance */