diff options
author | Paul Phillips <paulp@improving.org> | 2011-09-08 18:37:18 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-09-08 18:37:18 +0000 |
commit | f32a32b1b33c9d7ccd62467e3e10cb69930023c8 (patch) | |
tree | 47ca34246fbdd255f2191ced68bd708e609d22d2 /src/compiler/scala/reflect/internal/Symbols.scala | |
parent | 52c1d019d63d2fffadc8f3f159d654187ac61ece (diff) | |
download | scala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.tar.gz scala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.tar.bz2 scala-f32a32b1b33c9d7ccd62467e3e10cb69930023c8.zip |
Allow for the overriding of objects.
Various and sundry manipulations to allow for objects to be overridden
when the mood is right. It is not enabled by default.
The major contributor of change turned out to be the decoupling of
the FINAL flag (and the "isFinal" test which examines only that flag)
and the many semantics which were attributed to this interpretation
of finality in different circumstances. Since objects no longer have
the FINAL flag automatically applied (only top-level objects and those
marked final in source code do) we need apply a more nuanced test.
Fortunately there is such a nuanced test: isEffectivelyFinal,
which is always true if the FINAL flag is set but also in various
other circumstances. In almost every case, you should be testing
"isEffectivelyFinal", not "isFinal".
To enable overridable objects, use:
-Yoverride-objects
-Xexperimental // includes the above and others
Remain to be done: working out transition logistics. Most likely this
would involve bumping the scala signature version, and all objects in
versions before that would be assumed final.
Review by moors.
Diffstat (limited to 'src/compiler/scala/reflect/internal/Symbols.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/Symbols.scala | 48 |
1 files changed, 33 insertions, 15 deletions
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 |