summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala14
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala3
-rw-r--r--test/files/pos/t8234.scala16
7 files changed, 30 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index 2e44c405cf..676ee12683 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -415,7 +415,7 @@ abstract class TypeFlowAnalysis {
}
val concreteMethod = inliner.lookupImplFor(msym, receiver)
val isCandidate = {
- ( inliner.isClosureClass(receiver) || concreteMethod.isEffectivelyFinal || receiver.isEffectivelyFinal ) &&
+ ( inliner.isClosureClass(receiver) || concreteMethod.isEffectivelyFinalOrNotOverridden || receiver.isEffectivelyFinalOrNotOverridden ) &&
!blackballed(concreteMethod)
}
if(isCandidate) {
@@ -501,7 +501,7 @@ abstract class TypeFlowAnalysis {
}
private def isReceiverKnown(cm: opcodes.CALL_METHOD): Boolean = {
- cm.method.isEffectivelyFinal && cm.method.owner.isEffectivelyFinal
+ cm.method.isEffectivelyFinalOrNotOverridden && cm.method.owner.isEffectivelyFinalOrNotOverridden
}
private def putOnRadar(blocks: Traversable[BasicBlock]) {
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 0f317422ac..e70c558db0 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -431,7 +431,7 @@ abstract class DeadCodeElimination extends SubComponent {
}
private def isPure(sym: Symbol) = (
- (sym.isGetter && sym.isEffectivelyFinal && !sym.isLazy)
+ (sym.isGetter && sym.isEffectivelyFinalOrNotOverridden && !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 fa424584b2..f6de522d09 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -72,8 +72,8 @@ abstract class Inliners extends SubComponent {
def needsLookup = (
(clazz != NoSymbol)
&& (clazz != sym.owner)
- && !sym.isEffectivelyFinal
- && clazz.isEffectivelyFinal
+ && !sym.isEffectivelyFinalOrNotOverridden
+ && clazz.isEffectivelyFinalOrNotOverridden
)
def lookup(clazz: Symbol): Symbol = {
// println("\t\tlooking up " + meth + " in " + clazz.fullName + " meth.owner = " + meth.owner)
@@ -362,7 +362,7 @@ abstract class Inliners extends SubComponent {
for(x <- inputBlocks; easyCake = callsites(x); if easyCake.nonEmpty) {
breakable {
for(ocm <- easyCake) {
- assert(ocm.method.isEffectivelyFinal && ocm.method.owner.isEffectivelyFinal)
+ assert(ocm.method.isEffectivelyFinalOrNotOverridden && ocm.method.owner.isEffectivelyFinalOrNotOverridden)
if(analyzeInc(ocm, x, ocm.method.owner, -1, ocm.method)) {
inlineCount += 1
break()
@@ -409,8 +409,8 @@ abstract class Inliners extends SubComponent {
def isCandidate = (
isClosureClass(receiver)
- || concreteMethod.isEffectivelyFinal
- || receiver.isEffectivelyFinal
+ || concreteMethod.isEffectivelyFinalOrNotOverridden
+ || receiver.isEffectivelyFinalOrNotOverridden
)
def isApply = concreteMethod.name == nme.apply
@@ -425,7 +425,7 @@ abstract class Inliners extends SubComponent {
debuglog("Treating " + i
+ "\n\treceiver: " + receiver
+ "\n\ticodes.available: " + isAvailable
- + "\n\tconcreteMethod.isEffectivelyFinal: " + concreteMethod.isEffectivelyFinal)
+ + "\n\tconcreteMethod.isEffectivelyFinalOrNotOverridden: " + concreteMethod.isEffectivelyFinalOrNotOverridden)
if (!isCandidate) warnNoInline("it can be overridden")
else if (!isAvailable) warnNoInline("bytecode unavailable")
@@ -592,7 +592,7 @@ abstract class Inliners extends SubComponent {
/** Should method 'sym' being called in 'receiver' be loaded from disk? */
def shouldLoadImplFor(sym: Symbol, receiver: Symbol): Boolean = {
def alwaysLoad = (receiver.enclosingPackage == RuntimePackage) || (receiver == PredefModule.moduleClass)
- def loadCondition = sym.isEffectivelyFinal && isMonadicMethod(sym) && isHigherOrderMethod(sym)
+ def loadCondition = sym.isEffectivelyFinalOrNotOverridden && isMonadicMethod(sym) && isHigherOrderMethod(sym)
val res = hasInline(sym) || alwaysLoad || loadCondition
debuglog("shouldLoadImplFor: " + receiver + "." + sym + ": " + res)
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 5973c70583..714f189ead 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -116,7 +116,7 @@ abstract class TailCalls extends Transform {
def tailLabels: Set[Symbol]
def enclosingType = method.enclClass.typeOfThis
- def isEligible = method.isEffectivelyFinal
+ def isEligible = method.isEffectivelyFinalOrNotOverridden
def isMandatory = method.hasAnnotation(TailrecClass)
def isTransformed = isEligible && accessed(label)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index b899cd8994..13884404b3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -203,7 +203,7 @@ trait Checkable {
private def isSealedOrFinal(sym: Symbol) = sym.isSealed || sym.isFinal
private def isEffectivelyFinal(sym: Symbol): Boolean = (
// initialization important
- sym.initialize.isEffectivelyFinal || (
+ sym.initialize.isEffectivelyFinalOrNotOverridden || (
settings.future && isTupleSymbol(sym) // SI-7294 step into the future and treat TupleN as final.
)
)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 83c2e2acdb..03d8f97831 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -943,9 +943,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| isTerm && (
isPrivate
|| isLocalToBlock
- || isNotOverridden
)
)
+ /** Is this symbol effectively final or a concrete term member of sealed class whose childred do not override it */
+ final def isEffectivelyFinalOrNotOverridden: Boolean = isEffectivelyFinal || (isTerm && !isDeferred && isNotOverridden)
/** Is this symbol owned by a package? */
final def isTopLevel = owner.isPackageClass
diff --git a/test/files/pos/t8234.scala b/test/files/pos/t8234.scala
new file mode 100644
index 0000000000..2cb1562326
--- /dev/null
+++ b/test/files/pos/t8234.scala
@@ -0,0 +1,16 @@
+package p1
+
+private abstract class ProjectDef(val autoPlugins: Any) extends ProjectDefinition
+sealed trait ResolvedProject extends ProjectDefinition {
+ def autoPlugins: Any
+}
+
+sealed trait ProjectDefinition {
+ private[p1] def autoPlugins: Any
+}
+
+
+object Test {
+ // was "error: value autoPlugins in class ProjectDef of type Any cannot override final member"
+ new ProjectDef(null) with ResolvedProject
+}