summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala9
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala48
-rw-r--r--src/compiler/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/Settings.scala3
-rw-r--r--src/compiler/scala/reflect/std/ReflectSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala25
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala76
-rw-r--r--src/library/scala/reflect/generic/HasFlags.scala71
15 files changed, 128 insertions, 131 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 2bffca6335..a37ae9cd4d 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -131,10 +131,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
RootClass.sourceModule = rp
rp
}
- // This is the actual root of everything, including the package _root_.
- lazy val RootClass: ModuleClassSymbol = NoSymbol.newModuleClass(NoPosition, tpnme.ROOT)
- .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader)
+ // This is the actual root of everything, including the package _root_.
+ lazy val RootClass: ModuleClassSymbol = (
+ NoSymbol.newModuleClass(NoPosition, tpnme.ROOT)
+ setFlag (FINAL | MODULE | PACKAGE | JAVA)
+ setInfo rootLoader
+ )
// The empty package, which holds all top level types without given packages.
lazy val EmptyPackage = RootClass.newPackage(NoPosition, nme.EMPTY_PACKAGE_NAME).setFlag(FINAL)
lazy val EmptyPackageClass = EmptyPackage.moduleClass
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index 201a960ec7..de3607ffe9 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -243,7 +243,7 @@ class Flags extends ModifierFlags {
final val ConstrFlags: Long = JAVA
/** Module flags inherited by their module-class */
- final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA
+ final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA | FINAL
def getterFlags(fieldFlags: Long): Long = ACCESSOR + (
if ((fieldFlags & MUTABLE) != 0) fieldFlags & ~MUTABLE & ~PRESUPER
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 2a38e6ee9b..60b0c411da 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -90,20 +90,31 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
newMethod(pos, name).setFlag(LABEL)
final def newConstructor(pos: Position) =
newMethod(pos, nme.CONSTRUCTOR)
- final def newModule(pos: Position, name: TermName, clazz: ClassSymbol) =
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- .setModuleClass(clazz)
- final def newModule(name: TermName, clazz: Symbol, pos: Position = NoPosition) =
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- .setModuleClass(clazz.asInstanceOf[ClassSymbol])
- final def newModule(pos: Position, name: TermName) = {
- val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- m.setModuleClass(new ModuleClassSymbol(m))
- }
- final def newPackage(pos: Position, name: TermName) = {
+
+ private def finishModule(m: ModuleSymbol, clazz: ClassSymbol): ModuleSymbol = {
+ // Top-level objects can be automatically marked final, but others
+ // must be explicitly marked final if overridable objects are enabled.
+ val flags = if (isPackage || !settings.overrideObjects.value) MODULE | FINAL else MODULE
+ m setFlag flags
+ m setModuleClass clazz
+ m
+ }
+ private def finishModule(m: ModuleSymbol): ModuleSymbol =
+ finishModule(m, new ModuleClassSymbol(m))
+
+ final def newModule(pos: Position, name: TermName, clazz: ClassSymbol): ModuleSymbol =
+ finishModule(new ModuleSymbol(this, pos, name), clazz)
+
+ final def newModule(name: TermName, clazz: Symbol, pos: Position = NoPosition): ModuleSymbol =
+ newModule(pos, name, clazz.asInstanceOf[ClassSymbol])
+
+ final def newModule(pos: Position, name: TermName): ModuleSymbol =
+ finishModule(new ModuleSymbol(this, pos, name))
+
+ final def newPackage(pos: Position, name: TermName): ModuleSymbol = {
assert(name == nme.ROOT || isPackageClass)
val m = newModule(pos, name).setFlag(JAVA | PACKAGE)
- m.moduleClass.setFlag(JAVA | PACKAGE)
+ m.moduleClass setFlag (JAVA | PACKAGE)
m
}
final def newThisSym(pos: Position) =
@@ -522,8 +533,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
isPackageClass || isModuleClass && isStatic
/** Is this symbol effectively final? I.e, it cannot be overridden */
- final def isEffectivelyFinal: Boolean = isFinal || isTerm && (
- hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE))
+ final def isEffectivelyFinal: Boolean = (
+ isFinal
+ || hasModuleFlag && !settings.overrideObjects.value
+ || isTerm && (
+ isPrivate
+ || isLocal
+ || owner.isClass && owner.isEffectivelyFinal
+ )
+ )
/** Is this symbol locally defined? I.e. not accessed from outside `this` instance */
final def isLocal: Boolean = owner.isTerm
@@ -2314,7 +2332,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var module: Symbol = null
def this(module: TermSymbol) = {
this(module.owner, module.pos, module.name.toTypeName)
- setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
+ setFlag(module.getFlag(ModuleToClassFlags) | MODULE)
sourceModule = module
}
override def sourceModule = module
diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
index 0dfd12cc2d..3bf296760f 100644
--- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
@@ -29,6 +29,7 @@ abstract class MutableSettings extends AbsSettings {
}
}
+ def overrideObjects: SettingValue { type T = Boolean }
def printtypes: SettingValue { type T = Boolean }
def debug: SettingValue { type T = Boolean }
def YdepMethTpes: SettingValue { type T = Boolean }
diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala
index 088ea019e2..4bd72ce47b 100644
--- a/src/compiler/scala/reflect/runtime/Settings.scala
+++ b/src/compiler/scala/reflect/runtime/Settings.scala
@@ -19,6 +19,7 @@ class Settings extends internal.settings.MutableSettings {
v = x
}
+ val overrideObjects = new BooleanSetting(false)
val debug = new BooleanSetting(false)
val YdepMethTpes = new BooleanSetting(false)
val Ynotnull = new BooleanSetting(false)
@@ -29,4 +30,4 @@ class Settings extends internal.settings.MutableSettings {
val printtypes = new BooleanSetting(false)
val Yrecursion = new IntSetting(0)
val maxClassfileName = new IntSetting(255)
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/reflect/std/ReflectSettings.scala b/src/compiler/scala/reflect/std/ReflectSettings.scala
index 178f1e5c0c..d445b04bde 100644
--- a/src/compiler/scala/reflect/std/ReflectSettings.scala
+++ b/src/compiler/scala/reflect/std/ReflectSettings.scala
@@ -10,6 +10,7 @@ class ReflectSettings extends internal.settings.MutableSettings {
override def isDefault = v == init
}
+ val overrideObjects = newSetting(false)
val debug = newSetting(false)
val YdepMethTpes = newSetting(false)
val Ynotnull = newSetting(false)
@@ -20,4 +21,4 @@ class ReflectSettings extends internal.settings.MutableSettings {
val printtypes = newSetting(false)
val Yrecursion = newSetting(0)
val maxClassfileName = newSetting(255)
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index f24b4ac6bb..48b5d7cdce 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1901,7 +1901,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
// 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.rawflags & (Flags.FINAL | Flags.MODULE)) != 0)
&& !sym.enclClass.isInterface
&& !sym.isClassConstructor
)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 9522f4b3ea..311a3b916a 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -270,7 +270,7 @@ abstract class DeadCodeElimination extends SubComponent {
}
private def isPure(sym: Symbol) = (
- (sym.isGetter && sym.isFinal && !sym.isLazy)
+ (sym.isGetter && sym.isEffectivelyFinal && !sym.isLazy)
|| (sym.isPrimaryConstructor && (sym.enclosingPackage == RuntimePackage || inliner.isClosureClass(sym.owner)))
)
/** Is 'sym' a side-effecting method? TODO: proper analysis. */
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 3bded8cca4..f79cec532d 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -139,13 +139,18 @@ abstract class Inliners extends SubComponent {
icodes.load(concreteMethod.enclClass)
def isAvailable = icodes available concreteMethod.enclClass
- def isCandidate = isClosureClass(receiver) || concreteMethod.isEffectivelyFinal || receiver.isFinal
+ def isCandidate = (
+ isClosureClass(receiver)
+ || concreteMethod.isEffectivelyFinal
+ || receiver.isEffectivelyFinal
+ )
def isApply = concreteMethod.name == nme.apply
- def isCountable = !(isClosureClass(receiver)
- || isApply
- || isMonadicMethod(concreteMethod)
- || receiver.enclosingPackage == definitions.RuntimePackage
- ) // only count non-closures
+ def isCountable = !(
+ isClosureClass(receiver)
+ || isApply
+ || isMonadicMethod(concreteMethod)
+ || receiver.enclosingPackage == definitions.RuntimePackage
+ ) // only count non-closures
debuglog("Treating " + i
+ "\n\treceiver: " + receiver
@@ -260,8 +265,12 @@ abstract class Inliners extends SubComponent {
*/
def lookupImplFor(sym: Symbol, clazz: Symbol): Symbol = {
// TODO: verify that clazz.superClass is equivalent here to clazz.tpe.parents(0).typeSymbol (.tpe vs .info)
- def needsLookup = (clazz != NoSymbol) && (clazz != sym.owner) && !sym.isEffectivelyFinal && clazz.isFinal
-
+ def needsLookup = (
+ (clazz != NoSymbol)
+ && (clazz != sym.owner)
+ && !sym.isEffectivelyFinal
+ && clazz.isEffectivelyFinal
+ )
def lookup(clazz: Symbol): Symbol = {
// println("\t\tlooking up " + meth + " in " + clazz.fullName + " meth.owner = " + meth.owner)
if (sym.owner == clazz || isBottomType(clazz)) sym
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index ca7ca5b41f..68496b61ce 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -93,7 +93,7 @@ trait ScalaSettings extends AbsScalaSettings
// Experimental Extensions
val Xexperimental = BooleanSetting ("-Xexperimental", "Enable experimental extensions.") .
- withPostSetHook(set => List(YdepMethTpes, YmethodInfer) foreach (_.value = set.value)) //YvirtClasses,
+ withPostSetHook(set => List(YdepMethTpes, YmethodInfer, overrideObjects) foreach (_.value = set.value)) //YvirtClasses,
/** Compatibility stubs for options whose value name did
* not previously match the option name.
@@ -108,6 +108,7 @@ trait ScalaSettings extends AbsScalaSettings
/**
* -Y "Private" settings
*/
+ val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.")
val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.")
val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index e29f085de7..dc8585e8cb 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -215,7 +215,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
// the symbol is an outer accessor of a final class which does not override another outer accessor. )
def maybeOmittable(sym: Symbol) = sym.owner == clazz && (
sym.isParamAccessor && sym.isPrivateLocal ||
- sym.isOuterAccessor && sym.owner.isFinal && !sym.isOverridingSymbol &&
+ sym.isOuterAccessor && sym.owner.isEffectivelyFinal && !sym.isOverridingSymbol &&
!(clazz isSubClass DelayedInitClass)
)
@@ -228,7 +228,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
override def traverse(tree: Tree) = {
tree match {
case DefDef(_, _, _, _, _, body)
- if (tree.symbol.isOuterAccessor && tree.symbol.owner == clazz && clazz.isFinal) =>
+ if (tree.symbol.isOuterAccessor && tree.symbol.owner == clazz && clazz.isEffectivelyFinal) =>
log("outerAccessors += " + tree.symbol.fullName)
outerAccessors ::= ((tree.symbol, body))
case Select(_, _) =>
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 992a746e1e..8db759266b 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -150,7 +150,7 @@ abstract class ExplicitOuter extends InfoTransform
val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType
decls1 enter (clazz.newOuterAccessor(clazz.pos) setInfo MethodType(Nil, restpe))
if (hasOuterField(clazz)) { //2
- val access = if (clazz.isFinal) PRIVATE | LOCAL else PROTECTED
+ val access = if (clazz.isEffectivelyFinal) PRIVATE | LOCAL else PROTECTED
decls1 enter (
clazz.newValue(clazz.pos, nme.OUTER_LOCAL)
setFlag (SYNTHETIC | PARAMACCESSOR | access)
@@ -215,7 +215,7 @@ abstract class ExplicitOuter extends InfoTransform
val outerFld =
if (outerAcc.owner == currentClass &&
base.tpe =:= currentClass.thisType &&
- outerAcc.owner.isFinal)
+ outerAcc.owner.isEffectivelyFinal)
outerField(currentClass) suchThat (_.owner == currentClass)
else
NoSymbol
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 5a336d9027..c3062b3b2e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -93,7 +93,7 @@ trait Namers { self: Analyzer =>
else 0l
def moduleClassFlags(moduleFlags: Long) =
- (moduleFlags & ModuleToClassFlags) | FINAL | inConstructorFlag
+ (moduleFlags & ModuleToClassFlags) | inConstructorFlag
def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = {
debuglog("overwriting " + sym)
@@ -244,9 +244,9 @@ trait Namers { self: Analyzer =>
/** Enter a module symbol. The tree parameter can be either a module definition
* or a class definition */
def enterModuleSymbol(tree : ModuleDef): Symbol = {
- // .pos, mods.flags | MODULE | FINAL, name
+ // .pos, mods.flags | MODULE, name
var m: Symbol = context.scope.lookup(tree.name)
- val moduleFlags = tree.mods.flags | MODULE | FINAL
+ val moduleFlags = tree.mods.flags | MODULE
if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) {
updatePosFlags(m, tree.pos, moduleFlags)
setPrivateWithin(tree, m, tree.mods)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index c05a5e721e..0ff886dea6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -204,6 +204,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
* overrides some other member.
*/
private def checkAllOverrides(clazz: Symbol, typesOnly: Boolean = false) {
+ val self = clazz.thisType
+ def classBoundAsSeen(tp: Type) = {
+ tp.typeSymbol.classBound.asSeenFrom(self, tp.typeSymbol.owner)
+ }
case class MixinOverrideError(member: Symbol, msg: String)
@@ -223,8 +227,17 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
- val self = clazz.thisType
+ def isConformingObjectOverride(tp1: Type, tp2: Type) = {
+ tp1.typeSymbol.isModuleClass && tp2.typeSymbol.isModuleClass && {
+ val cb1 = classBoundAsSeen(tp1)
+ val cb2 = classBoundAsSeen(tp2)
+ (cb1 <:< cb2) && {
+ log("Allowing %s to override %s because %s <:< %s".format(tp1, tp2, cb1, cb2))
+ true
+ }
+ }
+ }
def isAbstractTypeWithoutFBound(sym: Symbol) = // (part of DEVIRTUALIZE)
sym.isAbstractType && !sym.isFBounded
@@ -248,10 +261,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
rtp1 <:< rtp2
case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) =>
rtp1 <:< rtp2
- case (TypeRef(_, sym, _), _) if (sym.isModuleClass) =>
+ case (TypeRef(_, sym, _), _) if sym.isModuleClass =>
overridesType(NullaryMethodType(tp1), tp2)
case _ =>
- tp1 <:< tp2
+ (tp1 <:< tp2) || isConformingObjectOverride(tp1, tp2)
}
/** Check that all conditions for overriding `other` by `member`
@@ -260,24 +273,43 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def checkOverride(clazz: Symbol, member: Symbol, other: Symbol) {
def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType
def isRootOrNone(sym: Symbol) = sym == RootClass || sym == NoSymbol
+ def objectOverrideErrorMsg = (
+ "overriding " + other.fullLocationString + " with " + member.fullLocationString + ":\n" +
+ "an overriding object must conform to the overridden object's class bound" +
+ analyzer.foundReqMsg(classBoundAsSeen(member.tpe), classBoundAsSeen(other.tpe))
+ )
+
+ def overrideErrorMsg(msg: String): String = {
+ val isConcreteOverAbstract =
+ (other.owner isSubClass member.owner) && other.isDeferred && !member.isDeferred
+ val addendum =
+ if (isConcreteOverAbstract)
+ ";\n (Note that %s is abstract,\n and is therefore overridden by concrete %s)".format(
+ infoStringWithLocation(other),
+ infoStringWithLocation(member)
+ )
+ else ""
+
+ "overriding %s;\n %s %s%s".format(
+ infoStringWithLocation(other), infoString(member), msg, addendum
+ )
+ }
+ def emitOverrideError(fullmsg: String) {
+ if (member.owner == clazz) unit.error(member.pos, fullmsg)
+ else mixinOverrideErrors += new MixinOverrideError(member, fullmsg)
+ }
def overrideError(msg: String) {
- if (noErrorType) {
- val fullmsg =
- "overriding "+infoStringWithLocation(other)+";\n "+
- infoString(member)+" "+msg+
- (if ((other.owner isSubClass member.owner) && other.isDeferred && !member.isDeferred)
- ";\n (Note that "+infoStringWithLocation(other)+" is abstract,"+
- "\n and is therefore overridden by concrete "+infoStringWithLocation(member)+")"
- else "")
- if (member.owner == clazz) unit.error(member.pos, fullmsg)
- else mixinOverrideErrors += new MixinOverrideError(member, fullmsg)
- }
+ if (noErrorType)
+ emitOverrideError(overrideErrorMsg(msg))
}
def overrideTypeError() {
if (noErrorType) {
- overrideError("has incompatible type")
+ emitOverrideError(
+ if (member.isModule && other.isModule) objectOverrideErrorMsg
+ else overrideErrorMsg("has incompatible type")
+ )
}
}
@@ -331,11 +363,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
if (!isOverrideAccessOK) {
overrideAccessError()
- } else if (other.isClass || other.isModule) {
- overrideError("cannot be used here - classes and objects cannot be overridden");
- } else if (!other.isDeferred && (member.isClass || member.isModule)) {
- overrideError("cannot be used here - classes and objects can only override abstract types");
- } else if (other hasFlag FINAL) { // (1.2)
+ } else if (other.isClass) {
+ overrideError("cannot be used here - class definitions cannot be overridden");
+ } else if (!other.isDeferred && member.isClass) {
+ overrideError("cannot be used here - classes can only override abstract types");
+ } else if (other.isFinal) { // (1.2)
overrideError("cannot override final member");
} else if (!other.isDeferred && !(member hasFlag (OVERRIDE | ABSOVERRIDE | SYNTHETIC))) { // (1.3), SYNTHETIC because of DEVIRTUALIZE
overrideError("needs `override' modifier");
@@ -1006,9 +1038,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
else if (isWarnable) {
if (isNew(qual)) // new X == y
nonSensibleWarning("a fresh object", false)
- else if (isNew(args.head) && (receiver.isFinal || isReferenceOp)) // object X ; X == new Y
+ else if (isNew(args.head) && (receiver.isEffectivelyFinal || isReferenceOp)) // object X ; X == new Y
nonSensibleWarning("a fresh object", false)
- else if (receiver.isFinal && !(receiver isSubClass actual)) { // object X, Y; X == Y
+ else if (receiver.isEffectivelyFinal && !(receiver isSubClass actual)) { // object X, Y; X == Y
if (isEitherNullable)
nonSensible("non-null ", false)
else
diff --git a/src/library/scala/reflect/generic/HasFlags.scala b/src/library/scala/reflect/generic/HasFlags.scala
index 7f869bfdc2..33d0a51243 100644
--- a/src/library/scala/reflect/generic/HasFlags.scala
+++ b/src/library/scala/reflect/generic/HasFlags.scala
@@ -6,76 +6,7 @@
package scala.reflect
package generic
-/** ISSUE #1: Flag names vs. Test method names
- *
- * The following methods from Symbol have a name of
- * the form isFoo where FOO is the name of a flag, but where the method
- * body tests for more than whether the flag is set.
- *
- * There are two possibilities with such methods. Either the extra
- * tests are strictly to partition among overloaded flags (which is
- * the case we can live with in the short term, if each such flag's
- * partitioning assumptions are documented) or they aren't.
- *
- * The second case implies that "x hasFlag FOO" and "x.isFoo" have
- * different semantics, and this we can't live with, because even if
- * we're smart enough to avoid being tripped up by that, the next guy isn't.
- *
- * No extreme measures necessary, only renaming isFoo to something
- * which hews more closely to its implementation. (Or renaming the flag.)
- *
- // Defined in the compiler Symbol
- //
- final def isLabel = isMethod && !hasAccessorFlag && hasFlag(LABEL)
- final def isLocal: Boolean = owner.isTerm
- final def isModuleVar: Boolean = isVariable && hasFlag(MODULEVAR)
- final def isStable =
- isTerm &&
- !hasTraitFlag &&
- (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
- !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
- final def isStatic: Boolean =
- hasFlag(STATIC) || isRoot || owner.isStaticOwner
- override final def isTrait: Boolean =
- isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE)
-
- // Defined in the library Symbol
- //
- def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes.
- final def isContravariant = isType && hasFlag(CONTRAVARIANT)
- final def isCovariant = isType && hasFlag(COVARIANT)
- final def isMethod = isTerm && hasFlag(METHOD)
- final def isModule = isTerm && hasFlag(MODULE)
- final def isPackage = isModule && hasFlag(PACKAGE)
- *
- */
-
-/** ISSUE #2: Implicit flag relationships must be made explicit.
- *
- * For instance, every time the MODULE flag is set, the FINAL flag is
- * set along with it:
- *
- .setFlag(FINAL | MODULE | PACKAGE | JAVA)
- .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader)
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
- sourceModule.flags = MODULE | FINAL
-
- * However the same is not true of when the MODULE flag is cleared:
-
- sym.resetFlag(MODULE)
- .setFlag(sym.flags | STABLE).resetFlag(MODULE)
- sym.resetFlag(MODULE | FINAL | CASE)
-
- * It's not relevant whether this example poses any issues: we must
- * not tolerate these uncertainties. If the flags are to move together
- * then both setting and clearing have to be encapsulated. If there
- * is a useful and used distinction between the various permutations
- * of on and off, then it must be documented. It's the only way!
- */
-
+/** Comment deleted, see internal.HasFlags. */
import Flags._
/** Common code utilized by `Modifiers` (which carry the flags associated