diff options
23 files changed, 85 insertions, 19 deletions
@@ -753,6 +753,7 @@ TODO: <path refid="quick.repl.build.path"/> <path refid="quick.actors.build.path"/> <pathelement location="${build-quick.dir}/classes/scalap"/> + <pathelement location="${build-quick.dir}/classes/scaladoc"/> <path refid="external-modules-nocore"/> </path> diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 03b76ed99e..6b14461cac 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1798,10 +1798,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) private def writeICode() { val printer = new icodes.TextPrinter(null, icodes.linearizer) icodes.classes.values.foreach((cls) => { - val suffix = if (cls.symbol.hasModuleFlag) "$.icode" else ".icode" + val suffix = s"${if (cls.symbol.hasModuleFlag) "$" else ""}_${phase}.icode" val file = getFile(cls.symbol, suffix) -// if (file.exists()) -// file = new File(file.getParentFile(), file.getName() + "1") try { val stream = new FileOutputStream(file) printer.setWriter(new PrintWriter(stream, true)) 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..90c37ba0b3 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -95,8 +95,10 @@ abstract class DeadCodeElimination extends SubComponent { localStores.clear() clobbers.clear() m.code.blocks.clear() + m.code.touched = true accessedLocals = m.params.reverse m.code.blocks ++= linearizer.linearize(m) + m.code.touched = true collectRDef(m) mark() sweep(m) @@ -431,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/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 50744f2d72..b42113c84f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1328,7 +1328,8 @@ trait Infer extends Checkable { eligible else eligible filter (alt => - !mexists(alt.info.paramss)(_.hasDefault) && isApplicableBasedOnArity(alt.tpe, argtpes.length, varargsStar, tuplingAllowed = true) + !alt.info.params.exists(_.hasDefault) // run/t8197b first parameter list only! + && isApplicableBasedOnArity(alt.tpe, argtpes.length, varargsStar, tuplingAllowed = true) ) } diff --git a/src/library/scala/App.scala b/src/library/scala/App.scala index ef39ee2134..62245322da 100644 --- a/src/library/scala/App.scala +++ b/src/library/scala/App.scala @@ -31,6 +31,8 @@ import scala.collection.mutable.ListBuffer * It should also be noted that the `main` method should not be overridden: * the whole class body becomes the “main method”. * + * Future versions of this trait will no longer extend `DelayedInit`. + * * @author Martin Odersky * @version 2.1, 15/02/2011 */ @@ -38,10 +40,12 @@ trait App extends DelayedInit { /** The time when the execution of this program started, in milliseconds since 1 * January 1970 UTC. */ + @deprecatedOverriding("executionStart should not be overridden", "2.11.0") val executionStart: Long = currentTime /** The command line arguments passed to the application's `main` method. */ + @deprecatedOverriding("args should not be overridden", "2.11.0") protected def args: Array[String] = _args private var _args: Array[String] = _ @@ -55,6 +59,7 @@ trait App extends DelayedInit { * themselves define a `delayedInit` method. * @param body the initialization code to be stored for later execution */ + @deprecated("The delayedInit mechanism will disappear.", "2.11.0") override def delayedInit(body: => Unit) { initCode += (() => body) } diff --git a/src/library/scala/DelayedInit.scala b/src/library/scala/DelayedInit.scala index cfbbf30793..7f976b073f 100644 --- a/src/library/scala/DelayedInit.scala +++ b/src/library/scala/DelayedInit.scala @@ -43,6 +43,7 @@ package scala * * @author Martin Odersky */ +@deprecated("DelayedInit semantics can be surprising. Support for `App` will continue.\nSee the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1", "2.11.0") trait DelayedInit { def delayedInit(x: => Unit): Unit }
\ No newline at end of file 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/neg/delayed-init-ref.check b/test/files/neg/delayed-init-ref.check index ce5b205832..90bc027969 100644 --- a/test/files/neg/delayed-init-ref.check +++ b/test/files/neg/delayed-init-ref.check @@ -4,9 +4,13 @@ delayed-init-ref.scala:17: warning: Selecting value vall from object O, which ex delayed-init-ref.scala:19: warning: Selecting value vall from object O, which extends scala.DelayedInit, is likely to yield an uninitialized value println(vall) // warn ^ +delayed-init-ref.scala:28: warning: trait DelayedInit in package scala is deprecated: DelayedInit semantics can be surprising. Support for `App` will continue. +See the release notes for more details: https://github.com/scala/scala/releases/tag/v2.11.0-RC1 +trait Before extends DelayedInit { + ^ delayed-init-ref.scala:40: warning: Selecting value foo from trait UserContext, which extends scala.DelayedInit, is likely to yield an uninitialized value println({locally(()); this}.foo) // warn (spurious, but we can't discriminate) ^ error: No warnings can be incurred under -Xfatal-warnings. -three warnings found +four warnings found one error found diff --git a/test/files/neg/delayed-init-ref.flags b/test/files/neg/delayed-init-ref.flags index 7949c2afa2..88a3e4c676 100644 --- a/test/files/neg/delayed-init-ref.flags +++ b/test/files/neg/delayed-init-ref.flags @@ -1 +1 @@ --Xlint -Xfatal-warnings +-deprecation -Xlint -Xfatal-warnings 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 +} diff --git a/test/files/pos/t8315.flags b/test/files/pos/t8315.flags new file mode 100644 index 0000000000..c926ad6493 --- /dev/null +++ b/test/files/pos/t8315.flags @@ -0,0 +1 @@ +-Yinline -Ydead-code diff --git a/test/files/pos/t8315.scala b/test/files/pos/t8315.scala new file mode 100644 index 0000000000..2f7742ed67 --- /dev/null +++ b/test/files/pos/t8315.scala @@ -0,0 +1,12 @@ +object Test { + def crash(as: Listt): Unit = { + map(as, (_: Any) => return) + } + + final def map(x: Listt, f: Any => Any): Any = { + if (x eq Nill) "" else f("") + } +} + +object Nill extends Listt +class Listt diff --git a/test/files/pos/t8315b.flags b/test/files/pos/t8315b.flags new file mode 100644 index 0000000000..c926ad6493 --- /dev/null +++ b/test/files/pos/t8315b.flags @@ -0,0 +1 @@ +-Yinline -Ydead-code diff --git a/test/files/pos/t8315b.scala b/test/files/pos/t8315b.scala new file mode 100644 index 0000000000..d7a2bf565f --- /dev/null +++ b/test/files/pos/t8315b.scala @@ -0,0 +1,11 @@ +object Test extends Object { + def crash: Unit = { + val key = "" + try map(new F(key)) + catch { case _: Throwable => } + }; + final def map(f: F): Any = f.apply(""); +}; +final class F(key: String) { + final def apply(a: Any): Any = throw new RuntimeException(key); +} diff --git a/test/files/run/delay-bad.check b/test/files/run/delay-bad.check index 2ae88267c5..5d8c5fa1d4 100644 --- a/test/files/run/delay-bad.check +++ b/test/files/run/delay-bad.check @@ -4,6 +4,7 @@ delay-bad.scala:53: warning: a pure expression does nothing in statement positio delay-bad.scala:73: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses f(new { val x = 5 } with E() { 5 }) ^ +warning: there were 1 deprecation warning(s); re-run with -deprecation for details // new C { } diff --git a/test/files/run/t4396.check b/test/files/run/t4396.check index 58f4fc5138..a75e1f257f 100644 --- a/test/files/run/t4396.check +++ b/test/files/run/t4396.check @@ -1,3 +1,4 @@ +warning: there were 1 deprecation warning(s); re-run with -deprecation for details hallo constructor out:22 diff --git a/test/files/run/t4680.check b/test/files/run/t4680.check index b2e5209dc5..512bfd4b54 100644 --- a/test/files/run/t4680.check +++ b/test/files/run/t4680.check @@ -4,6 +4,7 @@ t4680.scala:51: warning: a pure expression does nothing in statement position; y t4680.scala:69: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses new { val x = 5 } with E() { 5 } ^ +warning: there were 1 deprecation warning(s); re-run with -deprecation for details // new C { } diff --git a/test/files/run/t6481.check b/test/files/run/t6481.check index 7ec29631b1..df40722242 100644 --- a/test/files/run/t6481.check +++ b/test/files/run/t6481.check @@ -1,3 +1,4 @@ +warning: there were 1 deprecation warning(s); re-run with -deprecation for details delayed init new foo(1, 2) delayed init diff --git a/test/files/run/t8197b.scala b/test/files/run/t8197b.scala new file mode 100644 index 0000000000..8b3e0af0db --- /dev/null +++ b/test/files/run/t8197b.scala @@ -0,0 +1,8 @@ +object O { + def foo[T](t: T) = 0 + def foo(s: String)(implicit i: DummyImplicit = null) = 1 +} + +object Test extends App { + assert(O.foo("") == 1) +} |