diff options
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 b39fee65bb..90c37ba0b3 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -433,7 +433,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 +} |