summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-05-04 18:22:34 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-08-11 10:59:15 -0700
commit6f0bb49c17ea1a46283777e39ed5ce016aa048a5 (patch)
treeb39d9328148dee9e53e4eb6ae3ac62f3ffd54f32 /src
parent6858134fb01315c13df05fbef1b310443f3dac95 (diff)
downloadscala-6f0bb49c17ea1a46283777e39ed5ce016aa048a5.tar.gz
scala-6f0bb49c17ea1a46283777e39ed5ce016aa048a5.tar.bz2
scala-6f0bb49c17ea1a46283777e39ed5ce016aa048a5.zip
Reduce flag fiddling
There isn't much point to the late* flags in a world where we're mutating flags left and right in tree and info transformers... So, lets get rid of the indirection until we can include flags in a symbol's type history, like we do for its info. This retires lateDEFERRED (redundant with SYNTHESIZE_IMPL_IN_SUBCLASS). Since it's introduced so late, it makes little sense to have these synthetic members go back to DEFERRED. Instead, just set DEFERRED directly. Also remove unused late* and not* flags. notPRIVATE subsumes lateFINAL for effective finality (scala/scala-dev#126)
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Fields.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala32
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala40
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala24
10 files changed, 52 insertions, 74 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 27a4cbd134..e1decaba3e 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -239,6 +239,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
sym.isErroneous
}
+
/*
* must-single-thread
*/
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index 836893a98b..b2a575d7d1 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -12,6 +12,7 @@ import scala.tools.nsc.backend.jvm.opt._
import scala.tools.nsc.backend.jvm.BTypes._
import BackendReporting._
import scala.tools.nsc.settings.ScalaSettings
+import scala.reflect.internal.Flags.{DEFERRED, SYNTHESIZE_IMPL_IN_SUBCLASS}
/**
* This class mainly contains the method classBTypeFromSymbol, which extracts the necessary
@@ -580,7 +581,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
//
// However, due to https://github.com/scala/scala-dev/issues/126, this currently does not
// work, the abstract accessor for O will be marked effectivelyFinal.
- val effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden && !methodSym.isDeferred
+ val effectivelyFinal = methodSym.isEffectivelyFinalOrNotOverridden && !(methodSym hasFlag DEFERRED | SYNTHESIZE_IMPL_IN_SUBCLASS)
val info = MethodInlineInfo(
effectivelyFinal = effectivelyFinal,
@@ -716,15 +717,9 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
// scala compiler. The word final is heavily overloaded unfortunately;
// for us it means "not overridable". At present you can't override
// vars regardless; this may change.
- //
- // The logic does not check .isFinal (which checks flags for the FINAL flag,
- // and includes symbols marked lateFINAL) instead inspecting rawflags so
- // we can exclude lateFINAL. Such symbols are eligible for inlining, but to
- // avoid breaking proxy software which depends on subclassing, we do not
- // emit ACC_FINAL.
val finalFlag = (
- (((sym.rawflags & symtab.Flags.FINAL) != 0) || isTopLevelModuleClass(sym))
+ (sym.isFinal || isTopLevelModuleClass(sym))
&& !sym.enclClass.isTrait
&& !sym.isClassConstructor
&& (!sym.isMutable || nme.isTraitSetterName(sym.name)) // lazy vals and vars and their setters cannot be final, but trait setters are
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 104e2e8c93..406832c262 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -13,10 +13,6 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
import global._ // the global environment
import definitions._ // standard classes and methods
- /** lateDEFERRED for formerly concrete methods in such traits.
- */
- override def phaseNewFlags: Long = lateDEFERRED
-
def transformMixinInfo(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, clazz) if clazz.isPackageClass || !clazz.isJavaDefined =>
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index dc62b40578..f3fd7c5f67 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -504,7 +504,7 @@ abstract class Erasure extends AddInterfaces
if (!bridgeNeeded)
return
- var newFlags = (member.flags | BRIDGE | ARTIFACT) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED)
+ var newFlags = (member.flags | BRIDGE | ARTIFACT) & ~(ACCESSOR | DEFERRED | LAZY)
// If `member` is a ModuleSymbol, the bridge should not also be a ModuleSymbol. Otherwise we
// end up with two module symbols with the same name in the same scope, which is surprising
// when implementing later phases.
diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala
index 105bf0410d..a9ed8e3aca 100644
--- a/src/compiler/scala/tools/nsc/transform/Fields.scala
+++ b/src/compiler/scala/tools/nsc/transform/Fields.scala
@@ -83,10 +83,10 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
private def accessorImplementedInSubclass(accessor: Symbol) =
(accessor hasFlag SYNTHESIZE_IMPL_IN_SUBCLASS) && (accessor hasFlag (ACCESSOR | MODULE))
- private def concreteOrSynthImpl(sym: Symbol): Boolean = !(sym hasFlag DEFERRED) || (sym hasFlag SYNTHESIZE_IMPL_IN_SUBCLASS)
+ @inline final def notDeferredOrSynthImpl(sym: Symbol): Boolean = !(sym hasFlag DEFERRED) || (sym hasFlag SYNTHESIZE_IMPL_IN_SUBCLASS)
private def synthesizeImplInSubclasses(accessor: Symbol): Unit =
- accessor setFlag lateDEFERRED | SYNTHESIZE_IMPL_IN_SUBCLASS
+ accessor setFlag SYNTHESIZE_IMPL_IN_SUBCLASS
private def setClonedTraitSetterFlags(clazz: Symbol, correspondingGetter: Symbol, cloneInSubclass: Symbol): Unit = {
val overridden = isOverriddenAccessor(correspondingGetter, clazz)
@@ -96,7 +96,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
// TODO: add MIXEDIN (see e.g., `accessed` on `Symbol`)
private def setMixedinAccessorFlags(orig: Symbol, cloneInSubclass: Symbol): Unit =
- cloneInSubclass setFlag OVERRIDE | NEEDS_TREES resetFlag DEFERRED | lateDEFERRED | SYNTHESIZE_IMPL_IN_SUBCLASS
+ cloneInSubclass setFlag OVERRIDE | NEEDS_TREES resetFlag DEFERRED | SYNTHESIZE_IMPL_IN_SUBCLASS
private def setFieldFlags(accessor: Symbol, fieldInSubclass: TermSymbol): Unit =
fieldInSubclass setFlag (NEEDS_TREES |
@@ -128,7 +128,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
def matchingAccessor(pre: Type, member: Symbol, clazz: Symbol) = {
- val res = member.matchingSymbol(clazz, pre) filter (sym => (sym hasFlag ACCESSOR) && concreteOrSynthImpl(sym))
+ val res = member.matchingSymbol(clazz, pre) filter (sym => (sym hasFlag ACCESSOR) && notDeferredOrSynthImpl(sym))
// if (res != NoSymbol) println(s"matching accessor for $member in $clazz = $res (under $pre)")
// else println(s"no matching accessor for $member in $clazz (under $pre) among ${clazz.info.decls}")
res
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 0db9f19597..29ba21cba7 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -76,7 +76,7 @@ abstract class Flatten extends InfoTransform {
decls1 enter sym
if (sym.isModule) {
// In theory, we could assert(sym.isMethod), because nested, non-static modules are
- // transformed to methods (lateMETHOD flag added in RefChecks). But this requires
+ // transformed to methods (METHOD flag added in UnCurry). But this requires
// forcing sym.info (see comment on isModuleNotMethod), which forces stub symbols
// too eagerly (SI-8907).
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 0033736dbe..441ae625d0 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -19,8 +19,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** The name of the phase: */
val phaseName: String = "mixin"
- /** The phase might set the following new flags: */
- override def phaseNewFlags: Long = lateMODULE | notOVERRIDE
/** This map contains a binding (class -> info) if
* the class with this info at phase mixinPhase has been treated for mixin composition
@@ -46,7 +44,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
private def isImplementedStatically(sym: Symbol) = (
sym.isMethod
- && notDeferredOrLate(sym)
+ && notDeferred(sym)
&& sym.owner.isTrait
&& (!sym.isModule || sym.hasFlag(PRIVATE | LIFTED))
&& (!(sym hasFlag (ACCESSOR | SUPERACCESSOR)) || sym.isLazy)
@@ -109,7 +107,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// --------- type transformation -----------------------------------------------
- private def notDeferredOrLate(sym: Symbol) = !sym.hasFlag(DEFERRED) || sym.hasFlag(lateDEFERRED)
+ @inline final def notDeferred(sym: Symbol) = fields.notDeferredOrSynthImpl(sym)
/** Is member overridden (either directly or via a bridge) in base class sequence `bcs`? */
def isOverriddenAccessor(member: Symbol, bcs: List[Symbol]): Boolean = beforeOwnPhase {
@@ -118,7 +116,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
sym =>
sym.hasFlag(ACCESSOR) &&
!sym.hasFlag(MIXEDIN) &&
- notDeferredOrLate(sym) &&
+ notDeferred(sym) &&
matchesType(sym.tpe, member.tpe, alwaysMatchSimple = true))
}
( bcs.head != member.owner
@@ -178,11 +176,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
treatedClassInfos(clazz) = clazz.info
assert(phase == currentRun.mixinPhase, phase)
- /* Create a new getter. Getters are never private or local. They are
- * always accessors and deferred. */
+ /* Create a new getter. Getters are never private or local.
+ * They are always accessors and deferred.
+ *
+ * TODO: I guess newGetter and newSetter are needed for fields added after the fields phase (lambdalift) -- can we fix that?
+ */
def newGetter(field: Symbol): Symbol = {
- // println("creating new getter for "+ field +" : "+ field.info +" at "+ field.locationString+(field hasFlag MUTABLE))
- val newFlags = field.flags & ~PrivateLocal | ACCESSOR | lateDEFERRED | ( if (field.isMutable) 0 else STABLE )
+ //println(s"creating new getter for $field : ${field.info} at ${field.locationString} // mutable: ${field hasFlag MUTABLE}")
+ val newFlags = field.flags & ~PrivateLocal | ACCESSOR | ( if (field.isMutable) 0 else STABLE ) | SYNTHESIZE_IMPL_IN_SUBCLASS // TODO: do we need SYNTHESIZE_IMPL_IN_SUBCLASS to indicate that `notDeferred(setter)` should hold
// TODO preserve pre-erasure info?
clazz.newMethod(field.getterName, field.pos, newFlags) setInfo MethodType(Nil, field.info)
}
@@ -190,9 +191,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/* Create a new setter. Setters are never private or local. They are
* always accessors and deferred. */
def newSetter(field: Symbol): Symbol = {
- //println("creating new setter for "+field+field.locationString+(field hasFlag MUTABLE))
+ //println(s"creating new setter for $field ${field.locationString} // mutable: ${field hasFlag MUTABLE}")
val setterName = field.setterName
- val newFlags = field.flags & ~PrivateLocal | ACCESSOR | lateDEFERRED
+ val newFlags = field.flags & ~PrivateLocal | ACCESSOR | SYNTHESIZE_IMPL_IN_SUBCLASS // TODO: do we need SYNTHESIZE_IMPL_IN_SUBCLASS to indicate that `notDeferred(setter)` should hold
val setter = clazz.newMethod(setterName, field.pos, newFlags)
// TODO preserve pre-erasure info?
setter setInfo MethodType(setter.newSyntheticValueParams(List(field.info)), UnitTpe)
@@ -240,7 +241,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
def cloneAndAddMixinMember(mixinClass: Symbol, mixinMember: Symbol): Symbol = (
cloneAndAddMember(mixinClass, mixinMember, clazz)
setPos clazz.pos
- resetFlag DEFERRED | lateDEFERRED
+ resetFlag DEFERRED
)
/* Mix in members of implementation class mixinClass into class clazz */
@@ -319,9 +320,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}
else if (mixinMember.hasAllFlags(METHOD | MODULE) && mixinMember.hasNoFlags(LIFTED | BRIDGE)) {
// mixin objects: todo what happens with abstract objects?
- // addMember(clazz, mixinMember.cloneSymbol(clazz, mixinMember.flags & ~(DEFERRED | lateDEFERRED)) setPos clazz.pos)
+ // addMember(clazz, mixinMember.cloneSymbol(clazz, mixinMember.flags & ~DEFERRED) setPos clazz.pos)
}
- else if (mixinMember.hasFlag(ACCESSOR) && notDeferredOrLate(mixinMember)
+ else if (mixinMember.hasFlag(ACCESSOR) && notDeferred(mixinMember)
&& (mixinMember hasFlag (LAZY | PARAMACCESSOR))
&& !isOverriddenAccessor(mixinMember, clazz.info.baseClasses)) {
// pick up where `fields` left off -- it already mixed in fields and accessors for regular vals.
@@ -925,9 +926,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
addDefDef(sym)
} else {
// if class is not a trait add accessor definitions
- // used to include `sym` with `sym hasFlag lateDEFERRED` as not deferred,
- // but I don't think MIXEDIN members ever get this flag
- assert(!sym.hasFlag(lateDEFERRED), s"mixedin $sym from $clazz has lateDEFERRED flag?!")
if (sym.hasFlag(ACCESSOR) && !sym.hasFlag(DEFERRED)) {
assert(sym hasFlag (LAZY | PARAMACCESSOR), s"mixed in $sym from $clazz is not lazy/param?!?")
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 40ab8c0cf8..87c14eb3a1 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -59,7 +59,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val phaseName: String = "specialize"
/** The following flags may be set by this phase: */
- override def phaseNewFlags: Long = notPRIVATE | lateFINAL
+ override def phaseNewFlags: Long = notPRIVATE
/** This phase changes base classes. */
override def changesBaseClasses = true
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index d088150db6..a146f9aea5 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -178,13 +178,14 @@ class Flags extends ModifierFlags {
//
// Flags from 1L to (1L << 50) are normal flags.
//
- // The flags DEFERRED (1L << 4) to MODULE (1L << 8) have a `late` counterpart. Late flags change
- // their counterpart from 0 to 1 after a specific phase (see below). The first late flag
- // (lateDEFERRED) is at (1L << 51), i.e., late flags are shifted by 47. The last one is (1L << 55).
+ // The "late" counterpart to flags DEFERRED (1L << 4) to MODULE (1L << 8)
+ // show up in `sym.flags` as their regular counterpart once the phase mask admits them (see below).
+ // The first late flag (lateDEFERRED) is at (1L << 51), i.e., late flags are shifted by 47. The last one is (1L << 55).
+ // Think of it as a poor man's flag history akin to the type history for a symbol's info.
//
- // The flags PROTECTED (1L) to PRIVATE (1L << 2) have a `not` counterpart. Negated flags change
- // their counterpart from 1 to 0 after a specific phase (see below). They are shifted by 56, i.e.,
- // the first negated flag (notPROTECTED) is at (1L << 56), the last at (1L << 58).
+ // The "not" counterpart to flags PROTECTED (1L) to PRIVATE (1L << 2)
+ // are negated flags that suppress their counterpart after a specific phase (see below).
+ // They are shifted by 56, i.e., the first negated flag (notPROTECTED) is at (1L << 56), the last at (1L << 58).
//
// Late and negative flags are only enabled after certain phases, implemented by the phaseNewFlags
// method of the SubComponent, so they implement a bit of a flag history.
@@ -216,20 +217,15 @@ class Flags extends ModifierFlags {
// erasure 15 [START] <latedeferred>
// mixin 20 [START] <latemodule> <notoverride>
//
- // lateMETHOD set in RefChecks#transformInfo.
- // lateFINAL set in Symbols#makeNotPrivate.
// notPRIVATE set in Symbols#makeNotPrivate, IExplicitOuter#transform, Inliners.
// notPROTECTED set in ExplicitOuter#transform.
- // lateDEFERRED set in AddInterfaces, Mixin, etc.
- // lateMODULE set in Mixin#transformInfo.
- // notOVERRIDE set in Mixin#preTransform.
- final val lateDEFERRED = (DEFERRED: Long) << LateShift
- final val lateFINAL = (FINAL: Long) << LateShift
- final val lateMETHOD = (METHOD: Long) << LateShift
- final val lateMODULE = (MODULE: Long) << LateShift
+// final val lateDEFERRED = (DEFERRED: Long) << LateShift // unused
+// final val lateFINAL = (FINAL: Long) << LateShift // only used for inliner -- could be subsumed by notPRIVATE?
+// final val lateMETHOD = (METHOD: Long) << LateShift // unused
+// final val lateMODULE = (MODULE: Long) << LateShift // unused
- final val notOVERRIDE = (OVERRIDE: Long) << AntiShift
+// final val notOVERRIDE = (OVERRIDE: Long) << AntiShift // unused
final val notPRIVATE = (PRIVATE: Long) << AntiShift
final val notPROTECTED = (PROTECTED: Long) << AntiShift
@@ -449,13 +445,13 @@ class Flags extends ModifierFlags {
case JAVA_ENUM => "<enum>" // (1L << 48)
case JAVA_ANNOTATION => "<annotation>" // (1L << 49)
case SYNTHESIZE_IMPL_IN_SUBCLASS => "<sub_synth>" // (1L << 50)
- case `lateDEFERRED` => "<latedeferred>" // (1L << 51)
- case `lateFINAL` => "<latefinal>" // (1L << 52)
- case `lateMETHOD` => "<latemethod>" // (1L << 53)
- case 0x80000000000000L => "" // (1L << 54)
- case `lateMODULE` => "<latemodule>" // (1L << 55)
+ case 0x08000000000000L => "<latedeferred>" // (1L << 51)
+ case 0x10000000000000L => "<latefinal>" // (1L << 52)
+ case 0x20000000000000L => "<latemethod>" // (1L << 53)
+ case 0x40000000000000L => "" // (1L << 54)
+ case 0x80000000000000L => "<latemodule>" // (1L << 55)
case `notPROTECTED` => "<notprotected>" // (1L << 56)
- case `notOVERRIDE` => "<notoverride>" // (1L << 57)
+ case 0x200000000000000L => "<notoverride>" // (1L << 57)
case `notPRIVATE` => "<notprivate>" // (1L << 58)
case NEEDS_TREES => "<needs_trees>" // (1L << 59)
case 0x1000000000000000L => "" // (1L << 60)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index e438856160..487aadf5e5 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -746,10 +746,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def hasGetter = isTerm && nme.isLocalName(name)
/**
- * Nested modules which have no static owner when ModuleDefs are eliminated (refchecks) are
- * given the lateMETHOD flag, which makes them appear as methods after refchecks.
+ * Nested modules with a non-static owner receive the METHOD flag during UnCurry's info transform.
+ * (They are replaced by a ClassDef and DefDef for the module accessor during the fields phase.)
*
- * Note: the lateMETHOD flag is added lazily in the info transformer of the RefChecks phase.
+ * Note: the METHOD flag is added lazily in the info transformer of the UnCurry phase.
* This means that forcing the `sym.info` may change the value of `sym.isMethod`. Forcing the
* info is in the responsibility of the caller. Doing it eagerly here was tried (0ccdb151f) but
* has proven to lead to bugs (SI-8907).
@@ -985,10 +985,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isEffectivelyFinal: Boolean = (
(this hasFlag FINAL | PACKAGE)
|| isModuleOrModuleClass && (isTopLevel || !settings.overrideObjects)
- || isTerm && (
- isPrivate
- || isLocalToBlock
- )
+ || isTerm && (isPrivate || isLocalToBlock || (hasAllFlags(notPRIVATE | METHOD) && !hasFlag(DEFERRED)))
|| 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 */
@@ -2450,14 +2447,9 @@ 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. ... 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)
+ setFlag(notPRIVATE) // this makes it effectively final (isEffectivelyFinal)
+ // don't set FINAL -- methods not marked final by user should not end up final in bytecode
+ // inliner will know it's effectively final (notPRIVATE non-deferred method)
if (!isStaticModule && !isClassConstructor) {
expandName(base)
if (isModule) moduleClass.makeNotPrivate(base)
@@ -2886,7 +2878,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def owner = {
if (Statistics.hotEnabled) Statistics.incCounter(ownerCount)
- // a module symbol may have the lateMETHOD flag after refchecks, see isModuleNotMethod
+ // a non-static module symbol gets the METHOD flag in uncurry's info transform -- see isModuleNotMethod
if (!isMethod && needsFlatClasses) rawowner.owner
else rawowner
}