summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala17
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala2
3 files changed, 22 insertions, 11 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 3167bbc5de..30e9f38cbe 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -1644,13 +1644,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def makeNotPrivate(base: Symbol) {
if (this.isPrivate) {
setFlag(notPRIVATE)
- // Marking these methods final causes problems for proxies
- // which use subclassing. If people write their code with no
- // usage of final, we probably shouldn't introduce it ourselves
- // unless we know it is safe.
- //
- // if (isMethod && !isDeferred)
- // setFlag(lateFINAL)
+ // Marking these methods final causes problems for proxies which use subclassing. If people
+ // write their code with no usage of final, we probably shouldn't introduce it ourselves
+ // unless we know it is safe. ... Unfortunately if they aren't marked final the inliner
+ // thinks it can't inline them. So once again marking lateFINAL, and in genjvm we no longer
+ // generate ACC_FINAL on "final" methods which are actually lateFINAL.
+ if (isMethod && !isDeferred)
+ setFlag(lateFINAL)
if (!isStaticModule && !isClassConstructor) {
expandName(base)
if (isModule) moduleClass.makeNotPrivate(base)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 0036fd8060..2acd343ac1 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1905,14 +1905,25 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
def mkFlags(args: Int*) = args.foldLeft(0)(_ | _)
// constructors of module classes should be private
// PP: why are they only being marked private at this stage and not earlier?
- val isConsideredPrivate =
+ val privateFlag =
sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner))
+ // This does not check .isFinal (which checks flags for the FINAL flag),
+ // instead checking rawflags for that flag so as to exclude symbols which
+ // received lateFINAL. These symbols are eligible for inlining, but to
+ // avoid breaking proxy software which depends on subclassing, we avoid
+ // insisting on their finality in the bytecode.
+ val finalFlag = (
+ ((sym.rawflags & Flags.FINAL) != 0)
+ && !sym.enclClass.isInterface
+ && !sym.isClassConstructor
+ )
+
mkFlags(
- if (isConsideredPrivate) ACC_PRIVATE else ACC_PUBLIC,
+ if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0,
if (sym.isInterface) ACC_INTERFACE else 0,
- if (sym.isFinal && !sym.enclClass.isInterface && !sym.isClassConstructor) ACC_FINAL else 0,
+ if (finalFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge || sym.hasFlag(Flags.MIXEDIN) && sym.isMethod) ACC_BRIDGE else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index cf9bf3cdeb..3bded8cca4 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -187,7 +187,7 @@ abstract class Inliners extends SubComponent {
}
else warnNoInline(
if (!isAvailable) "bytecode was not available"
- else "it is not final"
+ else "it can be overridden"
)
inlined
}