diff options
873 files changed, 8671 insertions, 11187 deletions
diff --git a/.gitattributes b/.gitattributes index 958b0b9f28..ac98781b3d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,16 @@ +# fallback on built-in heuristics +# this must be first so later entries will override it +* text=auto + # These files are text and should be normalized (convert crlf => lf) *.c text *.check text *.css text +*.flags text *.html text *.java text *.js text +*.policy text *.sbt text *.scala text *.sh text diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..1927f85d2e --- /dev/null +++ b/.mailmap @@ -0,0 +1,7 @@ +Aleksandar Prokopec <aleksandar@aleksandar-Latitude-E6500.(none)> +Aleksandar Prokopec <aleksandar@htpc.(none)> +Aleksandar Prokopec <aleksandar@htpc-axel22.(none)> +Aleksandar Prokopec <aleksandar@lampmac14.epfl.ch> +Aleksandar Prokopec <aleksandar.prokopec@epfl.ch> +Daniel C. Sobral <dcs@dcs-132-CK-NF79.(none)> +Pavel Pavlov <pavel.e.pavlov@gmail.com> diff --git a/build.number b/build.number index f28886751b..51674b6915 100644 --- a/build.number +++ b/build.number @@ -1,7 +1,7 @@ #Tue Sep 11 19:21:09 CEST 2007 version.major=2 -version.minor=10 -version.patch=1 +version.minor=11 +version.patch=0 # This is the -N part of a version. if it's 0, it's dropped from maven versions. version.bnum=0 diff --git a/build.number.maven b/build.number.maven index eed9f3897c..a8da54397d 100644 --- a/build.number.maven +++ b/build.number.maven @@ -1,3 +1,3 @@ version.major=2 -version.minor=10 +version.minor=11 version.patch=0 diff --git a/lib/scala-compiler-src.jar.desired.sha1 b/lib/scala-compiler-src.jar.desired.sha1 index 082d86ff67..768602d1cc 100644 --- a/lib/scala-compiler-src.jar.desired.sha1 +++ b/lib/scala-compiler-src.jar.desired.sha1 @@ -1 +1 @@ -cfa3ee21f76cd5c115bd3bc070a3b401587bafb5 ?scala-compiler-src.jar +7372c94d194f8337998a0afa9e5ee9d3394748bf ?scala-compiler-src.jar diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index bb39b4d6a6..7b604eb027 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -d54b99f215d4d42b3f0b3489fbb1081270700992 ?scala-compiler.jar +44aa635da7fb0b7f19d9e5d89bc25893df7b6b21 ?scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index cd42c23291..e9bdba2e02 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -8bdac1cdd60b73ff7e12fd2b556355fa10343e2d ?scala-library-src.jar +2deb25c6b47e7dd6f7519d131d607e6e874ef763 ?scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index 6bdeaa903b..4dc4cb88c7 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -1e0e39fae15b42e85998740511ec5a3830e26243 ?scala-library.jar +a31ad1eb7109119873ca8bfe2db00f5c9858d8bc ?scala-library.jar diff --git a/lib/scala-reflect-src.jar.desired.sha1 b/lib/scala-reflect-src.jar.desired.sha1 index d630c938f2..21b08dc5ad 100644 --- a/lib/scala-reflect-src.jar.desired.sha1 +++ b/lib/scala-reflect-src.jar.desired.sha1 @@ -1 +1 @@ -d229f4c91ea8ab1a81559b5803efd9b0b1632f0b ?scala-reflect-src.jar +11596221c2a2ecc346b4478e7d630c269c69b888 ?scala-reflect-src.jar diff --git a/lib/scala-reflect.jar.desired.sha1 b/lib/scala-reflect.jar.desired.sha1 index a5d6701749..b2da327618 100644 --- a/lib/scala-reflect.jar.desired.sha1 +++ b/lib/scala-reflect.jar.desired.sha1 @@ -1 +1 @@ -288f47dbe1002653e030fd25ca500b9ffe1ebd64 ?scala-reflect.jar +b3420811aed2fb7cfcf25ebd26700a1e7847bf93 ?scala-reflect.jar diff --git a/project/ShaResolve.scala b/project/ShaResolve.scala index cea2b2d6cc..e5b25a29cf 100644 --- a/project/ShaResolve.scala +++ b/project/ShaResolve.scala @@ -105,6 +105,7 @@ object ShaResolve { def parseShaFile(file: File): (File, String) = IO.read(file).split("\\s") match { case Array(sha, filename) if filename.startsWith("?") => (new File(file.getParentFile, filename.drop(1)), sha) + case Array(sha, filename) if filename.startsWith("*") => (new File(file.getParentFile, filename.drop(1)), sha) case Array(sha, filename) => (new File(file.getParentFile, filename), sha) case _ => error(file.getAbsolutePath + " is an invalid sha file") } diff --git a/src/actors/scala/actors/Future.scala b/src/actors/scala/actors/Future.scala index 3037f82141..1abd7b160e 100644 --- a/src/actors/scala/actors/Future.scala +++ b/src/actors/scala/actors/Future.scala @@ -174,7 +174,7 @@ object Futures { * or timeout + `System.currentTimeMillis()` is negative. */ def awaitAll(timeout: Long, fts: Future[Any]*): List[Option[Any]] = { - var resultsMap: scala.collection.mutable.Map[Int, Option[Any]] = new scala.collection.mutable.HashMap[Int, Option[Any]] + val resultsMap: scala.collection.mutable.Map[Int, Option[Any]] = new scala.collection.mutable.HashMap[Int, Option[Any]] var cnt = 0 val mappedFts = fts.map(ft => diff --git a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala index be5f2dbe83..d9f337b5ba 100644 --- a/src/compiler/scala/reflect/macros/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/macros/runtime/Enclosures.scala @@ -5,7 +5,6 @@ trait Enclosures { self: Context => import universe._ - import mirror._ private def site = callsiteTyper.context private def enclTrees = site.enclosingContextChain map (_.tree) diff --git a/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala b/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala index 672699f00e..a719beed97 100644 --- a/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala +++ b/src/compiler/scala/reflect/macros/runtime/ExprUtils.scala @@ -5,7 +5,6 @@ trait ExprUtils { self: Context => import universe._ - import mirror._ def literalNull = Expr[Null](Literal(Constant(null)))(TypeTag.Null) diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala index 3d7cb95792..0ff098e1da 100644 --- a/src/compiler/scala/reflect/reify/Errors.scala +++ b/src/compiler/scala/reflect/reify/Errors.scala @@ -7,7 +7,6 @@ trait Errors { self: Reifier => import global._ - import definitions._ def defaultErrorPosition = { val stack = currents collect { case t: Tree if t.pos != NoPosition => t.pos } @@ -22,11 +21,6 @@ trait Errors { throw new ReificationException(defaultErrorPosition, msg) } - def CannotReifySymbol(sym: Symbol) = { - val msg = "implementation restriction: cannot reify symbol %s (%s)".format(sym, sym.accurateKindString) - throw new ReificationException(defaultErrorPosition, msg) - } - def CannotReifyWeakType(details: Any) = { val msg = "cannot create a TypeTag" + details + ": use WeakTypeTag instead" throw new ReificationException(defaultErrorPosition, msg) diff --git a/src/compiler/scala/reflect/reify/Phases.scala b/src/compiler/scala/reflect/reify/Phases.scala index 1710cae2a5..d43532090c 100644 --- a/src/compiler/scala/reflect/reify/Phases.scala +++ b/src/compiler/scala/reflect/reify/Phases.scala @@ -10,7 +10,6 @@ trait Phases extends Reshape self: Reifier => import global._ - import definitions._ private var alreadyRun = false @@ -26,7 +25,7 @@ trait Phases extends Reshape if (reifyDebug) println("[reshape phase]") tree = reshape.transform(tree) if (reifyDebug) println("[interlude]") - if (reifyDebug) println("reifee = " + (if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)) + if (reifyDebug) println("reifee = " + (if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)) if (reifyDebug) println("[calculate phase]") calculate.traverse(tree) @@ -41,4 +40,4 @@ trait Phases extends Reshape result } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala index 47669f57b0..b3224b1aa6 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -57,7 +57,7 @@ abstract class Reifier extends States val result = reifee match { case tree: Tree => - reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) + reifyTrace("reifying = ")(if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) reifyTrace("reifee is located at: ")(tree.pos) reifyTrace("universe = ")(universe) reifyTrace("mirror = ")(mirror) diff --git a/src/compiler/scala/reflect/reify/States.scala b/src/compiler/scala/reflect/reify/States.scala index 58455c9f3c..29bfa19845 100644 --- a/src/compiler/scala/reflect/reify/States.scala +++ b/src/compiler/scala/reflect/reify/States.scala @@ -4,7 +4,6 @@ trait States { self: Reifier => import global._ - import definitions._ /** Encapsulates reifier state * diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index cbaee41890..af0341fd38 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -8,7 +8,6 @@ abstract class Taggers { import c.universe._ import definitions._ - import treeBuild._ val coreTags = Map( ByteTpe -> nme.Byte, diff --git a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala index dec491aabe..5a454e1e07 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala @@ -5,7 +5,6 @@ trait GenAnnotationInfos { self: Reifier => import global._ - import definitions._ // usually annotations are reified as their originals from Modifiers // however, when reifying free and tough types, we're forced to reify annotation infos as is @@ -52,4 +51,4 @@ trait GenAnnotationInfos { val reifiedAssocs = ann.assocs map (assoc => scalaFactoryCall(nme.Tuple2, reify(assoc._1), reifyClassfileAnnotArg(assoc._2))) mirrorFactoryCall(nme.Annotation, reify(ann.atp), mkList(reifiedArgs), mkListMap(reifiedAssocs)) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/codegen/GenNames.scala b/src/compiler/scala/reflect/reify/codegen/GenNames.scala index 4abf88f475..7c3c1d1149 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenNames.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenNames.scala @@ -5,10 +5,9 @@ trait GenNames { self: Reifier => import global._ - import definitions._ def reifyName(name: Name) = { val factory = if (name.isTypeName) nme.nmeNewTypeName else nme.nmeNewTermName mirrorCall(factory, Literal(Constant(name.toString))) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/codegen/GenPositions.scala b/src/compiler/scala/reflect/reify/codegen/GenPositions.scala index 8c5db04454..1d151c5135 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenPositions.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenPositions.scala @@ -5,7 +5,6 @@ trait GenPositions { self: Reifier => import global._ - import definitions._ // we do not reify positions because this inflates resulting trees, but doesn't buy as anything // where would one use positions? right, in error messages @@ -14,4 +13,4 @@ trait GenPositions { // however both macros and toolboxes have their own means to report errors in synthetic trees def reifyPosition(pos: Position): Tree = reifyMirrorObject(NoPosition) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 22a834d2e4..39103b801e 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -5,7 +5,6 @@ trait GenSymbols { self: Reifier => import global._ - import definitions._ /** Symbol table of the reifee. * diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala index bdcc7383b0..86ad23cd15 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala @@ -64,7 +64,7 @@ trait GenTrees { // usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why. - if (reifyTreeSymbols && tree.hasSymbol) { + if (reifyTreeSymbols && tree.hasSymbolField) { if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree)) rtree = mirrorBuildCall(nme.setSymbol, rtree, reify(tree.symbol)) } @@ -86,8 +86,8 @@ trait GenTrees { // see ``Metalevels'' for more info about metalevel breaches // and about how we deal with splices that contain them - val isMetalevelBreach = splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) - val isRuntimeEval = splicee exists (sub => sub.hasSymbol && sub.symbol == ExprSplice) + val isMetalevelBreach = splicee exists (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) + val isRuntimeEval = splicee exists (sub => sub.hasSymbolField && sub.symbol == ExprSplice) if (isMetalevelBreach || isRuntimeEval) { // we used to convert dynamic splices into runtime evals transparently, but we no longer do that // why? see comments in ``Metalevels'' diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index 7aa87dc2f8..ca44938f50 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -74,7 +74,6 @@ trait GenTypes { if (reifyDebug) println("splicing " + tpe) val tagFlavor = if (concrete) tpnme.TypeTag.toString else tpnme.WeakTypeTag.toString - val key = (tagFlavor, tpe.typeSymbol) // if this fails, it might produce the dreaded "erroneous or inaccessible type" error // to find out the whereabouts of the error run scalac with -Ydebug if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(universe, tagFlavor, tpe)) diff --git a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala index 49877b4286..e2275f79ff 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenUtils.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenUtils.scala @@ -5,7 +5,6 @@ trait GenUtils { self: Reifier => import global._ - import definitions._ def reifyList(xs: List[Any]): Tree = mkList(xs map reify) @@ -91,22 +90,6 @@ trait GenUtils { /** An (unreified) path that refers to term definition with given fully qualified name */ def termPath(fullname: String): Tree = path(fullname, newTermName) - /** An (unreified) path that refers to type definition with given fully qualified name */ - def typePath(fullname: String): Tree = path(fullname, newTypeName) - - def isTough(tpe: Type) = { - def isTough(tpe: Type) = tpe match { - case _: RefinedType => true - case _: ExistentialType => true - case _: ClassInfoType => true - case _: MethodType => true - case _: PolyType => true - case _ => false - } - - tpe != null && (tpe exists isTough) - } - object TypedOrAnnotated { def unapply(tree: Tree): Option[Tree] = tree match { case ty @ Typed(_, _) => @@ -118,15 +101,6 @@ trait GenUtils { } } - def isAnnotated(tpe: Type) = { - def isAnnotated(tpe: Type) = tpe match { - case _: AnnotatedType => true - case _ => false - } - - tpe != null && (tpe exists isAnnotated) - } - def isSemiConcreteTypeMember(tpe: Type) = tpe match { case TypeRef(SingleType(_, _), sym, _) if sym.isAbstractType && !sym.isExistential => true case _ => false @@ -145,4 +119,4 @@ trait GenUtils { if (origin == "") origin = "of unknown origin" origin } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala index 55f8684df2..7be57c0cb7 100644 --- a/src/compiler/scala/reflect/reify/package.scala +++ b/src/compiler/scala/reflect/reify/package.scala @@ -1,11 +1,10 @@ package scala.reflect -import scala.language.implicitConversions -import scala.reflect.macros.{Context, ReificationException, UnexpectedReificationException} +import scala.reflect.macros.ReificationException import scala.tools.nsc.Global package object reify { - private def mkReifier(global1: Global)(typer: global1.analyzer.Typer, universe: global1.Tree, mirror: global1.Tree, reifee: Any, concrete: Boolean = false): Reifier { val global: global1.type } = { + private def mkReifier(global1: Global)(typer: global1.analyzer.Typer, universe: global1.Tree, mirror: global1.Tree, reifee: Any, concrete: Boolean): Reifier { val global: global1.type } = { val typer1: typer.type = typer val universe1: universe.type = universe val mirror1: mirror.type = mirror @@ -24,7 +23,8 @@ package object reify { private[reify] def mkDefaultMirrorRef(global: Global)(universe: global.Tree, typer0: global.analyzer.Typer): global.Tree = { import global._ - import definitions._ + import definitions.JavaUniverseClass + val enclosingErasure = { val rClassTree = reifyEnclosingRuntimeClass(global)(typer0) // HACK around SI-6259 @@ -71,7 +71,6 @@ package object reify { // a class/object body, this will return an EmptyTree. def reifyEnclosingRuntimeClass(global: Global)(typer0: global.analyzer.Typer): global.Tree = { import global._ - import definitions._ def isThisInScope = typer0.context.enclosingContextChain exists (_.tree.isInstanceOf[ImplDef]) if (isThisInScope) { val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef } diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala index 4d1e22abe7..5566fd7a77 100644 --- a/src/compiler/scala/reflect/reify/phases/Calculate.scala +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -5,7 +5,6 @@ trait Calculate { self: Reifier => import global._ - import definitions._ implicit class RichCalculateSymbol(sym: Symbol) { def metalevel: Int = { assert(sym != null && sym != NoSymbol); localSymbols.getOrElse(sym, 0) } diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala index fbbd12a42f..cccf080dbf 100644 --- a/src/compiler/scala/reflect/reify/phases/Metalevels.scala +++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala @@ -1,11 +1,12 @@ package scala.reflect.reify package phases +import scala.collection.{ mutable } + trait Metalevels { self: Reifier => import global._ - import definitions._ /** * Makes sense of cross-stage bindings. @@ -102,7 +103,7 @@ trait Metalevels { */ val metalevels = new Transformer { var insideSplice = false - var inlineableBindings = scala.collection.mutable.Map[TermName, Tree]() + val inlineableBindings = mutable.Map[TermName, Tree]() def withinSplice[T](op: => T) = { val old = insideSplice @@ -124,7 +125,7 @@ trait Metalevels { withinSplice { super.transform(TreeSplice(ReifiedTree(universe, mirror, symtab1, rtree, tpe, rtpe, concrete))) } case TreeSplice(splicee) => if (reifyDebug) println("entering splice: " + splicee) - val breaches = splicee filter (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) + val breaches = splicee filter (sub => sub.hasSymbolField && sub.symbol != NoSymbol && sub.symbol.metalevel > 0) if (!insideSplice && breaches.nonEmpty) { // we used to convert dynamic splices into runtime evals transparently, but we no longer do that // why? see comments above diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala index dc0028be38..2741785752 100644 --- a/src/compiler/scala/reflect/reify/phases/Reify.scala +++ b/src/compiler/scala/reflect/reify/phases/Reify.scala @@ -2,7 +2,6 @@ package scala.reflect.reify package phases import scala.runtime.ScalaRunTime.isAnyVal -import scala.runtime.ScalaRunTime.isTuple import scala.reflect.reify.codegen._ trait Reify extends GenSymbols @@ -16,7 +15,6 @@ trait Reify extends GenSymbols self: Reifier => import global._ - import definitions._ private object reifyStack { def currents: List[Any] = state.reifyStack @@ -56,4 +54,4 @@ trait Reify extends GenSymbols case _ => throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass)) }) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index 1b7509fdbe..f31c3d4755 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -48,13 +48,13 @@ trait Reshape { val Template(parents, self, body) = impl var body1 = trimAccessors(classDef, reshapeLazyVals(body)) body1 = trimSyntheticCaseClassMembers(classDef, body1) - var impl1 = Template(parents, self, body1).copyAttrs(impl) + val impl1 = Template(parents, self, body1).copyAttrs(impl) ClassDef(mods, name, params, impl1).copyAttrs(classDef) case moduledef @ ModuleDef(mods, name, impl) => val Template(parents, self, body) = impl var body1 = trimAccessors(moduledef, reshapeLazyVals(body)) body1 = trimSyntheticCaseClassMembers(moduledef, body1) - var impl1 = Template(parents, self, body1).copyAttrs(impl) + val impl1 = Template(parents, self, body1).copyAttrs(impl) ModuleDef(mods, name, impl1).copyAttrs(moduledef) case template @ Template(parents, self, body) => val discardedParents = parents collect { case tt: TypeTree => tt } filter isDiscarded @@ -116,7 +116,6 @@ trait Reshape { private def toPreTyperModifiers(mods: Modifiers, sym: Symbol) = { if (!sym.annotations.isEmpty) { - val Modifiers(flags, privateWithin, annotations) = mods val postTyper = sym.annotations filter (_.original != EmptyTree) if (reifyDebug && !postTyper.isEmpty) println("reify symbol annotations for: " + sym) if (reifyDebug && !postTyper.isEmpty) println("originals are: " + sym.annotations) @@ -252,7 +251,7 @@ trait Reshape { val DefDef(mods0, name0, _, _, tpt0, rhs0) = ddef val name1 = nme.dropLocalSuffix(name0) val Modifiers(flags0, privateWithin0, annotations0) = mods0 - var flags1 = (flags0 & GetterFlags) & ~(STABLE | ACCESSOR | METHOD) + val flags1 = (flags0 & GetterFlags) & ~(STABLE | ACCESSOR | METHOD) val mods1 = Modifiers(flags1, privateWithin0, annotations0) setPositions mods0.positions val mods2 = toPreTyperModifiers(mods1, ddef.symbol) ValDef(mods2, name1, tpt0, extractRhs(rhs0)) @@ -267,7 +266,7 @@ trait Reshape { def detectBeanAccessors(prefix: String): Unit = { if (defdef.name.startsWith(prefix)) { - var name = defdef.name.toString.substring(prefix.length) + val name = defdef.name.toString.substring(prefix.length) def uncapitalize(s: String) = if (s.length == 0) "" else { val chars = s.toCharArray; chars(0) = chars(0).toLower; new String(chars) } def findValDef(name: String) = (symdefs.values collect { case vdef: ValDef if nme.dropLocalSuffix(vdef.name).toString == name => vdef }).headOption val valdef = findValDef(name).orElse(findValDef(uncapitalize(name))).orNull @@ -279,11 +278,11 @@ trait Reshape { detectBeanAccessors("is") }); - var stats1 = stats flatMap { + val stats1 = stats flatMap { case vdef @ ValDef(mods, name, tpt, rhs) if !mods.isLazy => val mods1 = if (accessors.contains(vdef)) { val ddef = accessors(vdef)(0) // any accessor will do - val Modifiers(flags, privateWithin, annotations) = mods + val Modifiers(flags, _, annotations) = mods var flags1 = flags & ~LOCAL if (!ddef.symbol.isPrivate) flags1 = flags1 & ~PRIVATE val privateWithin1 = ddef.mods.privateWithin @@ -326,7 +325,8 @@ trait Reshape { case Some(ddef) => toPreTyperLazyVal(ddef) case None => - CannotReifyInvalidLazyVal(vdef) + if (reifyDebug) println("couldn't find corresponding lazy val accessor") + vdef } if (reifyDebug) println(s"reconstructed lazy val is $vdef1") vdef1::Nil diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala index b60d15c1d4..50bd309b52 100644 --- a/src/compiler/scala/reflect/reify/utils/Extractors.scala +++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala @@ -187,7 +187,7 @@ trait Extractors { Literal(Constant(origin: String))))) if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeTerm == nme.newFreeTerm && uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => - Some(uref1, name, reifyBinding(tree), flags, origin) + Some((uref1, name, reifyBinding(tree), flags, origin)) case _ => None } @@ -204,7 +204,7 @@ trait Extractors { Literal(Constant(origin: String))))) if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeType == nme.newFreeType && uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits => - Some(uref1, name, reifyBinding(tree), flags, origin) + Some((uref1, name, reifyBinding(tree), flags, origin)) case _ => None } diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index aca18c7df7..97ec479a6c 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -11,8 +11,6 @@ trait NodePrinters { self: Utils => import global._ - import definitions._ - import Flag._ object reifiedNodeToString extends (Tree => String) { def apply(tree: Tree): String = { @@ -25,8 +23,8 @@ trait NodePrinters { // Rolling a full-fledged, robust TreePrinter would be several times more code. // Also as of late we have tests that ensure that UX won't be broken by random changes to the reifier. val lines = (tree.toString.split(EOL) drop 1 dropRight 1).toList splitAt 2 - var (List(universe, mirror), reification) = lines - reification = (for (line <- reification) yield { + val (List(universe, mirror), reification0) = lines + val reification = (for (line <- reification0) yield { var s = line substring 2 s = s.replace(nme.UNIVERSE_PREFIX.toString, "") s = s.replace(".apply", "") diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala index dbb0836e0a..5f8de9894f 100644 --- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala +++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala @@ -8,8 +8,6 @@ trait SymbolTables { self: Utils => import global._ - import definitions._ - import Flag._ class SymbolTable private[SymbolTable] ( private[SymbolTable] val symtab: immutable.ListMap[Symbol, Tree] = immutable.ListMap[Symbol, Tree](), @@ -17,9 +15,6 @@ trait SymbolTables { private[SymbolTable] val original: Option[List[Tree]] = None) { def syms: List[Symbol] = symtab.keys.toList - def isConcrete: Boolean = symtab.values forall (sym => !FreeTypeDef.unapply(sym).isDefined) - -// def aliases: Map[Symbol, List[TermName]] = aliases.distinct groupBy (_._1) mapValues (_ map (_._2)) def symDef(sym: Symbol): Tree = symtab.getOrElse(sym, EmptyTree) @@ -89,11 +84,6 @@ trait SymbolTables { add(ValDef(NoMods, freshName(name0), TypeTree(), reification) updateAttachment bindingAttachment) } - private def add(sym: Symbol, name: TermName): SymbolTable = { - if (!(syms contains sym)) error("cannot add an alias to a symbol not in the symbol table") - add(sym, name, EmptyTree) - } - private def remove(sym: Symbol): SymbolTable = { val newSymtab = symtab - sym val newAliases = aliases filter (_._1 != sym) @@ -107,7 +97,7 @@ trait SymbolTables { newSymtab = newSymtab map { case ((sym, tree)) => val ValDef(mods, primaryName, tpt, rhs) = tree val tree1 = - if (!(newAliases contains (sym, primaryName))) { + if (!(newAliases contains ((sym, primaryName)))) { val primaryName1 = newAliases.find(_._1 == sym).get._2 ValDef(mods, primaryName1, tpt, rhs).copyAttrs(tree) } else tree @@ -143,7 +133,7 @@ trait SymbolTables { var result = new SymbolTable(original = Some(encoded)) encoded foreach (entry => (entry.attachments.get[ReifyBindingAttachment], entry.attachments.get[ReifyAliasAttachment]) match { case (Some(ReifyBindingAttachment(_)), _) => result += entry - case (_, Some(ReifyAliasAttachment(sym, alias))) => result = new SymbolTable(result.symtab, result.aliases :+ (sym, alias)) + case (_, Some(ReifyAliasAttachment(sym, alias))) => result = new SymbolTable(result.symtab, result.aliases :+ ((sym, alias))) case _ => // do nothing, this is boilerplate that can easily be recreated by subsequent `result.encode` }) result @@ -214,4 +204,4 @@ trait SymbolTables { } } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/ant/Pack200Task.scala b/src/compiler/scala/tools/ant/Pack200Task.scala index 255efe55ec..3180911414 100644 --- a/src/compiler/scala/tools/ant/Pack200Task.scala +++ b/src/compiler/scala/tools/ant/Pack200Task.scala @@ -99,8 +99,8 @@ class Pack200Task extends ScalaMatchingTask { private def getFileList: List[File] = { var files: List[File] = Nil val fs = getImplicitFileSet - var ds = fs.getDirectoryScanner(getProject()) - var dir = fs.getDir(getProject()) + val ds = fs.getDirectoryScanner(getProject()) + val dir = fs.getDir(getProject()) for (filename <- ds.getIncludedFiles() if filename.toLowerCase.endsWith(".jar")) { val file = new File(dir, filename) diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index 73d09e82ba..cf3b5f949b 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -19,6 +19,7 @@ import org.apache.tools.ant.util.facade.{FacadeTaskHelper, ImplementationSpecificArgument} import scala.tools.nsc.{Global, Settings, CompilerCommand} +import scala.tools.nsc.interactive.RangePositions import scala.tools.nsc.io.{Path => SPath} import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} @@ -518,7 +519,10 @@ class Scalac extends ScalaMatchingTask with ScalacShared { new Settings(error) protected def newGlobal(settings: Settings, reporter: Reporter) = - new Global(settings, reporter) + if (settings.Yrangepos.value) + new Global(settings, reporter) with RangePositions + else + new Global(settings, reporter) /*============================================================================*\ ** The big execute method ** diff --git a/src/compiler/scala/tools/ant/sabbus/Settings.scala b/src/compiler/scala/tools/ant/sabbus/Settings.scala index fde61e9564..d0fefdaa03 100644 --- a/src/compiler/scala/tools/ant/sabbus/Settings.scala +++ b/src/compiler/scala/tools/ant/sabbus/Settings.scala @@ -10,7 +10,7 @@ package scala.tools.ant.sabbus import java.io.File -import org.apache.tools.ant.types.{Path, Reference} +import org.apache.tools.ant.types.Path class Settings { diff --git a/src/compiler/scala/tools/cmd/CommandLine.scala b/src/compiler/scala/tools/cmd/CommandLine.scala index 75f96d3c4b..cf0463423c 100644 --- a/src/compiler/scala/tools/cmd/CommandLine.scala +++ b/src/compiler/scala/tools/cmd/CommandLine.scala @@ -19,7 +19,7 @@ class CommandLine(val spec: Reference, val originalArgs: List[String]) extends C def this(spec: Reference, line: String) = this(spec, Parser tokenize line) def this(spec: Reference, args: Array[String]) = this(spec, args.toList) - import spec.{ isAnyOption, isUnaryOption, isBinaryOption, isExpandOption } + import spec.{ isUnaryOption, isBinaryOption, isExpandOption } val Terminator = "--" val ValueForUnaryOption = "true" // so if --opt is given, x(--opt) = true diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala index cba2e99998..433bbb167e 100644 --- a/src/compiler/scala/tools/cmd/FromString.scala +++ b/src/compiler/scala/tools/cmd/FromString.scala @@ -6,7 +6,7 @@ package scala.tools package cmd -import nsc.io.{ Path, File, Directory } +import scala.tools.nsc.io.{ File, Directory } import scala.reflect.runtime.{universe => ru} import scala.tools.reflect.StdRuntimeTags._ @@ -24,18 +24,11 @@ abstract class FromString[+T](implicit t: ru.TypeTag[T]) extends PartialFunction } object FromString { - // We need these because we clash with the String => Path implicits. - private def toFile(s: String) = new File(new java.io.File(s)) + // We need this because we clash with the String => Path implicits. private def toDir(s: String) = new Directory(new java.io.File(s)) /** Path related stringifiers. */ - val ExistingFile: FromString[File] = new FromString[File]()(tagOfFile) { - override def isDefinedAt(s: String) = toFile(s).isFile - def apply(s: String): File = - if (isDefinedAt(s)) toFile(s) - else cmd.runAndExit(println("'%s' is not an existing file." format s)) - } val ExistingDir: FromString[Directory] = new FromString[Directory]()(tagOfDirectory) { override def isDefinedAt(s: String) = toDir(s).isDirectory def apply(s: String): Directory = diff --git a/src/compiler/scala/tools/cmd/Reference.scala b/src/compiler/scala/tools/cmd/Reference.scala index bcbb454771..ec2a414065 100644 --- a/src/compiler/scala/tools/cmd/Reference.scala +++ b/src/compiler/scala/tools/cmd/Reference.scala @@ -26,7 +26,6 @@ trait Reference extends Spec { def isUnaryOption(s: String) = unary contains toOpt(s) def isBinaryOption(s: String) = binary contains toOpt(s) def isExpandOption(s: String) = expansionMap contains toOpt(s) - def isAnyOption(s: String) = isUnaryOption(s) || isBinaryOption(s) || isExpandOption(s) def expandArg(arg: String) = expansionMap.getOrElse(fromOpt(arg), List(arg)) @@ -46,7 +45,7 @@ object Reference { val MaxLine = 80 class Accumulators() { - private var _help = new ListBuffer[() => String] + private val _help = new ListBuffer[() => String] private var _unary = List[String]() private var _binary = List[String]() private var _expand = Map[String, List[String]]() diff --git a/src/compiler/scala/tools/cmd/gen/CodegenSpec.scala b/src/compiler/scala/tools/cmd/gen/CodegenSpec.scala index 903517c5b4..ee7e605425 100644 --- a/src/compiler/scala/tools/cmd/gen/CodegenSpec.scala +++ b/src/compiler/scala/tools/cmd/gen/CodegenSpec.scala @@ -12,8 +12,6 @@ trait CodegenSpec extends Spec with Meta.StdOpts with Interpolation { def referenceSpec = CodegenSpec def programInfo = Spec.Info("codegen", "", "scala.tools.cmd.gen.Codegen") - import FromString.ExistingDir - help("Usage: codegen [<options>]") // val inDir = "in" / "directory containing templates" --^ ExistingDir diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index 4e7ba60d5e..663fbeceb0 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -6,7 +6,7 @@ package scala.tools.nsc import util.FreshNameCreator -import scala.reflect.internal.util.{ Position, NoPosition, BatchSourceFile, SourceFile, NoSourceFile } +import scala.reflect.internal.util.{ SourceFile, NoSourceFile } import scala.collection.mutable import scala.collection.mutable.{ LinkedHashSet, ListBuffer } @@ -26,7 +26,7 @@ trait CompilationUnits { self: Global => class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { /** the fresh name creator */ - var fresh: FreshNameCreator = new FreshNameCreator.Default + val fresh: FreshNameCreator = new FreshNameCreator.Default def freshTermName(prefix: String): TermName = newTermName(fresh.newName(prefix)) def freshTypeName(prefix: String): TypeName = newTypeName(fresh.newName(prefix)) @@ -36,16 +36,6 @@ trait CompilationUnits { self: Global => def exists = source != NoSourceFile && source != null -// def parseSettings() = { -// val argsmarker = "SCALAC_ARGS" -// if(comments nonEmpty) { -// val pragmas = comments find (_.text.startsWith("//#")) // only parse first one -// pragmas foreach { p => -// val i = p.text.indexOf(argsmarker) -// if(i > 0) -// } -// } -// } /** Note: depends now contains toplevel classes. * To get their sourcefiles, you need to dereference with .sourcefile */ @@ -107,18 +97,5 @@ trait CompilationUnits { self: Global => lazy val isJava = source.file.name.endsWith(".java") override def toString() = source.toString() - - def clear() { - fresh = new FreshNameCreator.Default - body = EmptyTree - depends.clear() - defined.clear() - synthetics.clear() - toCheck.clear() - checkedFeatures = Set() - icode.clear() - } } } - - diff --git a/src/compiler/scala/tools/nsc/CompileClient.scala b/src/compiler/scala/tools/nsc/CompileClient.scala index 731f6926f0..c756a1b0d9 100644 --- a/src/compiler/scala/tools/nsc/CompileClient.scala +++ b/src/compiler/scala/tools/nsc/CompileClient.scala @@ -5,7 +5,6 @@ package scala.tools.nsc -import java.io.{ BufferedReader, File, InputStreamReader, PrintWriter } import settings.FscSettings import scala.tools.util.CompileOutputCommon import sys.SystemProperties.preferIPv4Stack diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index c23c1e6154..f79990d526 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -5,7 +5,7 @@ package scala.tools.nsc -import java.io.{ BufferedOutputStream, FileOutputStream, PrintStream } +import java.io.PrintStream import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.reflect.internal.util.FakePos //Position import scala.tools.util.SocketServer @@ -29,8 +29,6 @@ class StandardCompileServer extends SocketServer { var shutdown = false var verbose = false - val versionMsg = "Fast " + Properties.versionMsg - val MaxCharge = 0.8 private val runtime = Runtime.getRuntime() diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala index 9a3e8d1530..6b55537195 100644 --- a/src/compiler/scala/tools/nsc/CompileSocket.scala +++ b/src/compiler/scala/tools/nsc/CompileSocket.scala @@ -5,13 +5,9 @@ package scala.tools.nsc -import java.io.{ IOException, FileNotFoundException, PrintWriter, FileOutputStream } -import java.io.{ BufferedReader, FileReader } -import java.util.regex.Pattern -import java.net._ +import java.io.{ FileNotFoundException, PrintWriter, FileOutputStream } import java.security.SecureRandom import io.{ File, Path, Directory, Socket } -import scala.util.control.Exception.catching import scala.tools.util.CompileOutputCommon import scala.reflect.internal.util.StringOps.splitWhere import scala.sys.process._ diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index e994150f6f..0462e69f74 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -5,7 +5,6 @@ package scala.tools.nsc -import scala.collection.mutable.ListBuffer import io.File /** A class representing command line info for scalac */ @@ -15,9 +14,6 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { type Setting = Settings#Setting - /** file extensions of files that the compiler can process */ - lazy val fileEndings = Properties.fileEndings - private val processArgumentsResult = if (shouldProcessArguments) processArguments else (true, Nil) @@ -41,8 +37,6 @@ class CompilerCommand(arguments: List[String], val settings: Settings) { """.stripMargin.trim + "\n" def shortUsage = "Usage: %s <options> <source files>" format cmdName - def createUsagePreface(shouldExplain: Boolean) = - if (shouldExplain) shortUsage + "\n" + explainAdvanced else "" /** Creates a help message for a subset of options based on cond */ def createUsageMsg(cond: Setting => Boolean): String = { diff --git a/src/compiler/scala/tools/nsc/CompilerRun.scala b/src/compiler/scala/tools/nsc/CompilerRun.scala deleted file mode 100644 index 6746b08155..0000000000 --- a/src/compiler/scala/tools/nsc/CompilerRun.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Martin Odersky - */ - -package scala.tools.nsc - -class CompilerRun { - def firstPhase: Phase = NoPhase - def terminalPhase: Phase = NoPhase - def namerPhase: Phase = NoPhase - def typerPhase: Phase = NoPhase - def refchecksPhase: Phase = NoPhase - def explicitouterPhase: Phase = NoPhase - def erasurePhase: Phase = NoPhase - def flattenPhase: Phase = NoPhase - def mixinPhase: Phase = NoPhase - def icodePhase: Phase = NoPhase - def phaseNamed(name: String): Phase = NoPhase -} - diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala index 1775602122..b5fd20e1cc 100644 --- a/src/compiler/scala/tools/nsc/Driver.scala +++ b/src/compiler/scala/tools/nsc/Driver.scala @@ -1,11 +1,11 @@ package scala.tools.nsc -import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} +import scala.tools.nsc.reporters.ConsoleReporter import Properties.{ versionString, copyrightString, residentPromptString } -import scala.reflect.internal.util.{ BatchSourceFile, FakePos } +import scala.reflect.internal.util.FakePos abstract class Driver { - + val prompt = residentPromptString val versionMsg = "Scala compiler " + @@ -68,4 +68,4 @@ abstract class Driver { sys.exit(if (reporter.hasErrors) 1 else 0) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala index 9c2db11a56..ad75d02bff 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala @@ -39,7 +39,4 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) { val nc = BooleanSetting( "-nc", "do not use the fsc compilation daemon") withAbbreviation "-nocompdaemon" - - @deprecated("Use `nc` instead", "2.9.0") def nocompdaemon = nc - @deprecated("Use `save` instead", "2.9.0") def savecompiled = save } diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index b0288c0149..397e6c42d7 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -8,14 +8,12 @@ package scala.tools.nsc import java.io.{ File, FileOutputStream, PrintWriter, IOException, FileNotFoundException } import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException } import scala.compat.Platform.currentTime -import scala.tools.util.PathResolver import scala.collection.{ mutable, immutable } import io.{ SourceReader, AbstractFile, Path } import reporters.{ Reporter, ConsoleReporter } -import util.{ Exceptional, ClassPath, MergedClassPath, StatisticsInfo, ScalaClassLoader, returning } -import scala.reflect.internal.util.{ NoPosition, OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } +import util.{ ClassPath, MergedClassPath, StatisticsInfo, returning, stackTraceString, stackTraceHeadString } +import scala.reflect.internal.util.{ OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile } import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat } -import settings.{ AestheticSettings } import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers } import symtab.classfile.Pickler import dependencies.DependencyAnalysis @@ -30,8 +28,6 @@ import backend.jvm.{GenJVM, GenASM} import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination } import backend.icode.analysis._ import scala.language.postfixOps -import scala.reflect.internal.StdAttachments -import scala.reflect.ClassTag class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable @@ -74,8 +70,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def this(settings: Settings) = this(settings, new ConsoleReporter(settings)) - def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = gen.mkAttributedQualifier(tpe, termSym) - def picklerPhase: Phase = if (currentRun.isDefined) currentRun.picklerPhase else NoPhase // platform specific elements @@ -172,7 +166,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (lastPrintedSource == source) println(": tree is unchanged since " + lastPrintedPhase) else { - lastPrintedPhase = phase.prev // since we're running inside "afterPhase" + lastPrintedPhase = phase.prev // since we're running inside "exitingPhase" lastPrintedSource = source println("") println(source) @@ -257,27 +251,26 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (settings.debug.value) body } - // Warnings issued only under -Ydebug. For messages which should reach - // developer ears, but are not adequately actionable by users. - @inline final override def debugwarn(msg: => String) { - if (settings.debug.value) - warning(msg) + /** This is for WARNINGS which should reach the ears of scala developers + * whenever they occur, but are not useful for normal users. They should + * be precise, explanatory, and infrequent. Please don't use this as a + * logging mechanism. !!! is prefixed to all messages issued via this route + * to make them visually distinct. + */ + @inline final override def devWarning(msg: => String) { + if (settings.developer.value || settings.debug.value) + warning("!!! " + msg) } private def elapsedMessage(msg: String, start: Long) = msg + " in " + (currentTime - start) + "ms" def informComplete(msg: String): Unit = reporter.withoutTruncating(inform(msg)) - def informProgress(msg: String) = if (opt.verbose) inform("[" + msg + "]") - def inform[T](msg: String, value: T): T = returning(value)(x => inform(msg + x)) + def informProgress(msg: String) = if (settings.verbose.value) inform("[" + msg + "]") def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start)) def logError(msg: String, t: Throwable): Unit = () - def logAfterEveryPhase[T](msg: String)(op: => T) { - log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op)) - } - override def shouldLogAtThisPhase = settings.log.isSetByUser && ( (settings.log containsPhase globalPhase) || (settings.log containsPhase phase) ) @@ -299,7 +292,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) private val reader: SourceReader = { val defaultEncoding = Properties.sourceEncoding - val defaultReader = Properties.sourceReader def loadCharset(name: String) = try Some(Charset.forName(name)) @@ -312,7 +304,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) None } - val charset = opt.encoding flatMap loadCharset getOrElse { + val charset = ( if (settings.encoding.isSetByUser) Some(settings.encoding.value) else None ) flatMap loadCharset getOrElse { settings.encoding.value = defaultEncoding // A mandatory charset Charset.forName(defaultEncoding) } @@ -327,7 +319,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - opt.sourceReader flatMap loadReader getOrElse { + ( if (settings.sourceReader.isSetByUser) Some(settings.sourceReader.value) else None ) flatMap loadReader getOrElse { new SourceReader(charset.newDecoder(), reporter) } } @@ -335,54 +327,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (!dependencyAnalysis.off) dependencyAnalysis.loadDependencyAnalysis() - if (opt.verbose || opt.logClasspath) { + if (settings.verbose.value || settings.Ylogcp.value) { // Uses the "do not truncate" inform informComplete("[search path for source files: " + classPath.sourcepaths.mkString(",") + "]") informComplete("[search path for class files: " + classPath.asClasspathString + "]") } - object opt extends AestheticSettings { - def settings = Global.this.settings - - // protected implicit lazy val globalPhaseOrdering: Ordering[Phase] = Ordering[Int] on (_.id) - def isActive(ph: Settings#PhasesSetting) = ph containsPhase globalPhase - def wasActive(ph: Settings#PhasesSetting) = ph containsPhase globalPhase.prev - - // Allows for syntax like scalac -Xshow-class Random@erasure,typer - private def splitClassAndPhase(str: String, term: Boolean): Name = { - def mkName(s: String) = if (term) newTermName(s) else newTypeName(s) - (str indexOf '@') match { - case -1 => mkName(str) - case idx => - val phasePart = str drop (idx + 1) - settings.Yshow.tryToSetColon(phasePart split ',' toList) - mkName(str take idx) - } - } - - // behavior - - // debugging - def checkPhase = wasActive(settings.check) - def logPhase = isActive(settings.log) - - // Write *.icode files right after GenICode when -Xprint-icode was given. - def writeICodeAtICode = settings.writeICode.isSetByUser && isActive(settings.writeICode) - - // showing/printing things - def browsePhase = isActive(settings.browse) - def echoFilenames = opt.debug && (opt.verbose || currentRun.size < 5) - def noShow = settings.Yshow.isDefault - def printLate = settings.printLate.value - def printPhase = isActive(settings.Xprint) - def showNames = List(showClass, showObject).flatten - def showPhase = isActive(settings.Yshow) - def showSymbols = settings.Yshowsyms.value - def showTrees = settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value - val showClass = optSetting[String](settings.Xshowcls) map (x => splitClassAndPhase(x, false)) - val showObject = optSetting[String](settings.Xshowobj) map (x => splitClassAndPhase(x, true)) - } - // The current division between scala.reflect.* and scala.tools.nsc.* is pretty // clunky. It is often difficult to have a setting influence something without having // to create it on that side. For this one my strategy is a constant def at the file @@ -391,11 +341,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // Here comes another one... override protected val enableTypeVarExperimentals = settings.Xexperimental.value - // True if -Xscript has been set, indicating a script run. - def isScriptRun = opt.script.isDefined - def getSourceFile(f: AbstractFile): BatchSourceFile = - if (isScriptRun) ScriptSourceFile(f, reader read f) + if (settings.script.isSetByUser) ScriptSourceFile(f, reader read f) else new BatchSourceFile(f, reader read f) def getSourceFile(name: String): SourceFile = { @@ -450,7 +397,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if ((unit ne null) && unit.exists) lastSeenSourceFile = unit.source - if (opt.echoFilenames) + if (settings.debug.value && (settings.verbose.value || currentRun.size < 5)) inform("[running phase " + name + " on " + unit + "]") val unit0 = currentUnit @@ -469,8 +416,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } /** Switch to turn on detailed type logs */ - var printTypings = settings.Ytyperdebug.value - var printInfers = settings.Yinferdebug.value + val printTypings = settings.Ytyperdebug.value + val printInfers = settings.Yinferdebug.value // phaseName = "parser" object syntaxAnalyzer extends { @@ -688,13 +635,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - // phaseName = "SAMPLE PHASE" - object sampleTransform extends { - val global: Global.this.type = Global.this - val runsAfter = List[String]() - val runsRightAfter = None - } with SampleTransform - /** The checkers are for validating the compiler data structures * at phase boundaries. */ @@ -828,48 +768,16 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Returns List of (phase, value) pairs, including only those * where the value compares unequal to the previous phase's value. */ - def afterEachPhase[T](op: => T): List[(Phase, T)] = { + def afterEachPhase[T](op: => T): List[(Phase, T)] = { // used in tests phaseDescriptors.map(_.ownPhase).filterNot(_ eq NoPhase).foldLeft(List[(Phase, T)]()) { (res, ph) => - val value = afterPhase(ph)(op) + val value = exitingPhase(ph)(op) if (res.nonEmpty && res.head._2 == value) res else ((ph, value)) :: res } reverse } - /** Returns List of ChangeAfterPhase objects, encapsulating those - * phase transitions where the result of the operation gave a different - * list than it had when run during the previous phase. - */ - def changesAfterEachPhase[T](op: => List[T]): List[ChangeAfterPhase[T]] = { - val ops = ((NoPhase, Nil)) :: afterEachPhase(op) - - ops sliding 2 map { - case (_, before) :: (ph, after) :: Nil => - val lost = before filterNot (after contains _) - val gained = after filterNot (before contains _) - ChangeAfterPhase(ph, lost, gained) - case _ => ??? - } toList - } private def numberedPhase(ph: Phase) = "%2d/%s".format(ph.id, ph.name) - case class ChangeAfterPhase[+T](ph: Phase, lost: List[T], gained: List[T]) { - private def mkStr(what: String, xs: List[_]) = ( - if (xs.isEmpty) "" - else xs.mkString(what + " after " + numberedPhase(ph) + " {\n ", "\n ", "\n}\n") - ) - override def toString = mkStr("Lost", lost) + mkStr("Gained", gained) - } - - def describeAfterEachPhase[T](op: => T): List[String] = - afterEachPhase(op) map { case (ph, t) => "[after %-15s] %s".format(numberedPhase(ph), t) } - - def describeAfterEveryPhase[T](op: => T): String = - describeAfterEachPhase(op) map (" " + _ + "\n") mkString - - def printAfterEachPhase[T](op: => T): Unit = - describeAfterEachPhase(op) foreach (m => println(" " + m)) - // ------------ Invalidations --------------------------------- /** Is given package class a system package class that cannot be invalidated? @@ -1092,40 +1000,37 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile - // TODO - trim these to the absolute minimum. - @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op) - @inline final def afterPostErasure[T](op: => T): T = afterPhase(currentRun.posterasurePhase)(op) - @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op) - @inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op) - @inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op) - @inline final def afterMixin[T](op: => T): T = afterPhase(currentRun.mixinPhase)(op) - @inline final def afterPickler[T](op: => T): T = afterPhase(currentRun.picklerPhase)(op) - @inline final def afterRefchecks[T](op: => T): T = afterPhase(currentRun.refchecksPhase)(op) - @inline final def afterSpecialize[T](op: => T): T = afterPhase(currentRun.specializePhase)(op) - @inline final def afterTyper[T](op: => T): T = afterPhase(currentRun.typerPhase)(op) - @inline final def afterUncurry[T](op: => T): T = afterPhase(currentRun.uncurryPhase)(op) - @inline final def beforeErasure[T](op: => T): T = beforePhase(currentRun.erasurePhase)(op) - @inline final def beforeExplicitOuter[T](op: => T): T = beforePhase(currentRun.explicitouterPhase)(op) - @inline final def beforeFlatten[T](op: => T): T = beforePhase(currentRun.flattenPhase)(op) - @inline final def beforeIcode[T](op: => T): T = beforePhase(currentRun.icodePhase)(op) - @inline final def beforeMixin[T](op: => T): T = beforePhase(currentRun.mixinPhase)(op) - @inline final def beforePickler[T](op: => T): T = beforePhase(currentRun.picklerPhase)(op) - @inline final def beforeRefchecks[T](op: => T): T = beforePhase(currentRun.refchecksPhase)(op) - @inline final def beforeSpecialize[T](op: => T): T = beforePhase(currentRun.specializePhase)(op) - @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op) - @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op) - - def explainContext(c: analyzer.Context): String = ( - if (c == null) "" else ( - """| context owners: %s - | - |Enclosing block or template: - |%s""".format( - c.owner.ownerChain.takeWhile(!_.isPackageClass).mkString(" -> "), - nodePrinters.nodeToString(c.enclClassOrMethod.tree) - ) - ) + def isGlobalInitialized = ( + definitions.isDefinitionsInitialized + && rootMirror.isMirrorInitialized ) + override def isPastTyper = ( + (curRun ne null) + && isGlobalInitialized // defense against init order issues + && (globalPhase.id > currentRun.typerPhase.id) + ) + + // TODO - trim these to the absolute minimum. + @inline final def exitingErasure[T](op: => T): T = exitingPhase(currentRun.erasurePhase)(op) + @inline final def exitingPostErasure[T](op: => T): T = exitingPhase(currentRun.posterasurePhase)(op) + @inline final def exitingExplicitOuter[T](op: => T): T = exitingPhase(currentRun.explicitouterPhase)(op) + @inline final def exitingFlatten[T](op: => T): T = exitingPhase(currentRun.flattenPhase)(op) + @inline final def exitingMixin[T](op: => T): T = exitingPhase(currentRun.mixinPhase)(op) + @inline final def exitingPickler[T](op: => T): T = exitingPhase(currentRun.picklerPhase)(op) + @inline final def exitingRefchecks[T](op: => T): T = exitingPhase(currentRun.refchecksPhase)(op) + @inline final def exitingSpecialize[T](op: => T): T = exitingPhase(currentRun.specializePhase)(op) + @inline final def exitingTyper[T](op: => T): T = exitingPhase(currentRun.typerPhase)(op) + @inline final def exitingUncurry[T](op: => T): T = exitingPhase(currentRun.uncurryPhase)(op) + @inline final def enteringErasure[T](op: => T): T = enteringPhase(currentRun.erasurePhase)(op) + @inline final def enteringExplicitOuter[T](op: => T): T = enteringPhase(currentRun.explicitouterPhase)(op) + @inline final def enteringFlatten[T](op: => T): T = enteringPhase(currentRun.flattenPhase)(op) + @inline final def enteringIcode[T](op: => T): T = enteringPhase(currentRun.icodePhase)(op) + @inline final def enteringMixin[T](op: => T): T = enteringPhase(currentRun.mixinPhase)(op) + @inline final def enteringPickler[T](op: => T): T = enteringPhase(currentRun.picklerPhase)(op) + @inline final def enteringRefchecks[T](op: => T): T = enteringPhase(currentRun.refchecksPhase)(op) + @inline final def enteringTyper[T](op: => T): T = enteringPhase(currentRun.typerPhase)(op) + @inline final def enteringUncurry[T](op: => T): T = enteringPhase(currentRun.uncurryPhase)(op) + // Owners up to and including the first package class. private def ownerChainString(sym: Symbol): String = ( if (sym == null) "" @@ -1138,9 +1043,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) pairs.toList collect { case (k, v) if v != null => "%20s: %s".format(k, v) } mkString "\n" ) - def explainTree(t: Tree): String = formatExplain( - ) - /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. */ @@ -1152,7 +1054,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val info1 = formatExplain( "while compiling" -> currentSource.path, - "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ), + "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, enteringPhase=%s".format(globalPhase, phase) ), "library version" -> scala.util.Properties.versionString, "compiler version" -> Properties.versionString, "reconstructed args" -> settings.recreateArgs.mkString(" ") @@ -1168,7 +1070,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val info3: List[String] = ( ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) ) ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) ) - ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) + ++ ( if (!settings.debug.value) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) ) ++ ( List(errorMessage) ) ) @@ -1182,7 +1084,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def echoPhaseSummary(ph: Phase) = { /** Only output a summary message under debug if we aren't echoing each file. */ - if (opt.debug && !opt.echoFilenames) + if (settings.debug.value && !(settings.verbose.value || currentRun.size < 5)) inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]") } @@ -1198,7 +1100,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } def newUnitParser(code: String) = new syntaxAnalyzer.UnitParser(newCompilationUnit(code)) - def newUnitScanner(code: String) = new syntaxAnalyzer.UnitScanner(newCompilationUnit(code)) def newCompilationUnit(code: String) = new CompilationUnit(newSourceFile(code)) def newSourceFile(code: String) = new BatchSourceFile("<console>", code) @@ -1221,18 +1122,14 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings) val allConditionalWarnings = List(deprecationWarnings0, uncheckedWarnings0, featureWarnings, inlinerWarnings) - // for sbt's benefit - def uncheckedWarnings: List[(Position, String)] = uncheckedWarnings0.warnings.toList - def deprecationWarnings: List[(Position, String)] = deprecationWarnings0.warnings.toList + def uncheckedWarnings: List[(Position, String)] = uncheckedWarnings0.warnings.toList // used in sbt + def deprecationWarnings: List[(Position, String)] = deprecationWarnings0.warnings.toList // used in sbt var reportedFeature = Set[Symbol]() /** Has any macro expansion used a fallback during this run? */ var seenMacroExpansionsFallingBack = false - /** To be initialized from firstPhase. */ - private var terminalPhase: Phase = NoPhase - private val unitbuf = new mutable.ListBuffer[CompilationUnit] val compiledFiles = new mutable.HashSet[String] @@ -1393,7 +1290,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val namerPhase = phaseNamed("namer") // val packageobjectsPhase = phaseNamed("packageobjects") val typerPhase = phaseNamed("typer") - val inlineclassesPhase = phaseNamed("inlineclasses") + // val inlineclassesPhase = phaseNamed("inlineclasses") // val superaccessorsPhase = phaseNamed("superaccessors") val picklerPhase = phaseNamed("pickler") val refchecksPhase = phaseNamed("refchecks") @@ -1406,7 +1303,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val erasurePhase = phaseNamed("erasure") val posterasurePhase = phaseNamed("posterasure") // val lazyvalsPhase = phaseNamed("lazyvals") - val lambdaliftPhase = phaseNamed("lambdalift") + // val lambdaliftPhase = phaseNamed("lambdalift") // val constructorsPhase = phaseNamed("constructors") val flattenPhase = phaseNamed("flatten") val mixinPhase = phaseNamed("mixin") @@ -1416,12 +1313,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val inlineExceptionHandlersPhase = phaseNamed("inlineExceptionHandlers") val closelimPhase = phaseNamed("closelim") val dcePhase = phaseNamed("dce") - val jvmPhase = phaseNamed("jvm") + // val jvmPhase = phaseNamed("jvm") // val msilPhase = phaseNamed("msil") def runIsAt(ph: Phase) = globalPhase.id == ph.id - def runIsPast(ph: Phase) = globalPhase.id > ph.id - // def runIsAtBytecodeGen = (runIsAt(jvmPhase) || runIsAt(msilPhase)) def runIsAtOptimiz = { runIsAt(inlinerPhase) || // listing phases in full for robustness when -Ystop-after has been given. runIsAt(inlineExceptionHandlersPhase) || @@ -1490,8 +1385,24 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - private def showMembers() = - opt.showNames foreach (x => showDef(x, opt.declsOnly, globalPhase)) + private def showMembers() = { + // Allows for syntax like scalac -Xshow-class Random@erasure,typer + def splitClassAndPhase(str: String, term: Boolean): Name = { + def mkName(s: String) = if (term) newTermName(s) else newTypeName(s) + (str indexOf '@') match { + case -1 => mkName(str) + case idx => + val phasePart = str drop (idx + 1) + settings.Yshow.tryToSetColon(phasePart split ',' toList) + mkName(str take idx) + } + } + if (settings.Xshowcls.isSetByUser) + showDef(splitClassAndPhase(settings.Xshowcls.value, false), false, globalPhase) + + if (settings.Xshowobj.isSetByUser) + showDef(splitClassAndPhase(settings.Xshowobj.value, true), false, globalPhase) + } // Similarly, this will only be created under -Yshow-syms. object trackerFactory extends SymbolTrackers { @@ -1499,7 +1410,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) lazy val trackers = currentRun.units.toList map (x => SymbolTracker(x)) def snapshot() = { inform("\n[[symbol layout at end of " + phase + "]]") - afterPhase(phase) { + exitingPhase(phase) { trackers foreach { t => t.snapshot() inform(t.show("Heading from " + phase.prev.name + " to " + phase.name)) @@ -1509,6 +1420,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } def reportCompileErrors() { + if (!reporter.hasErrors && reporter.hasWarnings && settings.fatalWarnings.value) + globalError("No warnings can be incurred under -Xfatal-warnings.") + if (reporter.hasErrors) { for ((sym, file) <- symSource.iterator) { sym.reset(new loaders.SourcefileLoader(file)) @@ -1528,8 +1442,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Compile list of source files */ def compileSources(_sources: List[SourceFile]) { - val depSources = dependencyAnalysis calculateFiles _sources.distinct - val sources = coreClassesFirst(depSources) + val sources = dependencyAnalysis calculateFiles _sources.distinct // there is a problem already, e.g. a plugin was passed a bad option if (reporter.hasErrors) return @@ -1547,12 +1460,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { try compileUnitsInternal(units, fromPhase) catch { case ex: Throwable => - val shown = if (settings.verbose.value) { - val pw = new java.io.PrintWriter(new java.io.StringWriter) - ex.printStackTrace(pw) - pw.toString - } else ex.getClass.getName - // ex.printStackTrace(Console.out) // DEBUG for fsc, note that error stacktraces do not print in fsc + val shown = if (settings.verbose.value) + stackTraceString(ex) + else + stackTraceHeadString(ex) // note that error stacktraces do not print in fsc + globalError(supplementErrorMessage("uncaught exception during compilation: " + shown)) throw ex } @@ -1576,37 +1488,40 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // progress update informTime(globalPhase.description, startTime) phaseTimings(globalPhase) = currentTime - startTime - - if (opt.writeICodeAtICode || (opt.printPhase && runIsAtOptimiz)) { + val shouldWriteIcode = ( + (settings.writeICode.isSetByUser && (settings.writeICode containsPhase globalPhase)) + || (!settings.Xprint.doAllPhases && (settings.Xprint containsPhase globalPhase) && runIsAtOptimiz) + ) + if (shouldWriteIcode) { // Write *.icode files when -Xprint-icode or -Xprint:<some-optimiz-phase> was given. writeICode() - } else if (opt.printPhase || opt.printLate && runIsAt(cleanupPhase)) { + } else if ((settings.Xprint containsPhase globalPhase) || settings.printLate.value && runIsAt(cleanupPhase)) { // print trees - if (opt.showTrees) nodePrinters.printAll() + if (settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value) nodePrinters.printAll() else printAllUnits() } // print the symbols presently attached to AST nodes - if (opt.showSymbols) + if (settings.Yshowsyms.value) trackerFactory.snapshot() // print members - if (opt.showPhase) + if (settings.Yshow containsPhase globalPhase) showMembers() // browse trees with swing tree viewer - if (opt.browsePhase) + if (settings.browse containsPhase globalPhase) treeBrowser browse (phase.name, units) // move the pointer globalPhase = globalPhase.next // run tree/icode checkers - if (opt.checkPhase) + if (settings.check containsPhase globalPhase.prev) runCheckers() // output collected statistics - if (opt.printStats) + if (settings.Ystatistics.value) statistics.print(phase) advancePhase @@ -1616,7 +1531,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) units map (_.body) foreach (traceSymbols recordSymbolsInTree _) // In case no phase was specified for -Xshow-class/object, show it now for sure. - if (opt.noShow) + if (settings.Yshow.isDefault) showMembers() reportCompileErrors() @@ -1632,7 +1547,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // Reset project if (!stopPhase("namer")) { - atPhase(namerPhase) { + enteringPhase(namerPhase) { resetProjectClasses(RootClass) } } @@ -1648,7 +1563,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def compile(filenames: List[String]) { try { val sources: List[SourceFile] = - if (isScriptRun && filenames.size > 1) returning(Nil)(_ => globalError("can only compile one script at a time")) + if (settings.script.isSetByUser && filenames.size > 1) returning(Nil)(_ => globalError("can only compile one script at a time")) else filenames map getSourceFile compileSources(sources) @@ -1672,7 +1587,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (firstPhase ne null) { // we might get here during initialization, is a source is newer than the binary val maxId = math.max(globalPhase.id, typerPhase.id) firstPhase.iterator takeWhile (_.id < maxId) foreach (ph => - atPhase(ph)(ph.asInstanceOf[GlobalPhase] applyPhase unit)) + enteringPhase(ph)(ph.asInstanceOf[GlobalPhase] applyPhase unit)) refreshProgress } } @@ -1681,56 +1596,16 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * is needed for?) */ private def resetPackageClass(pclazz: Symbol) { - atPhase(firstPhase) { - pclazz.setInfo(atPhase(typerPhase)(pclazz.info)) + enteringPhase(firstPhase) { + pclazz.setInfo(enteringPhase(typerPhase)(pclazz.info)) } if (!pclazz.isRoot) resetPackageClass(pclazz.owner) } - - /** - * Re-orders the source files to - * 1. This Space Intentionally Left Blank - * 2. LowPriorityImplicits / EmbeddedControls (i.e. parents of Predef) - * 3. the rest - * - * 1 is to avoid cyclic reference errors. - * 2 is due to the following. When completing "Predef" (*), typedIdent is called - * for its parents (e.g. "LowPriorityImplicits"). typedIdent checks whether - * the symbol reallyExists, which tests if the type of the symbol after running - * its completer is != NoType. - * If the "namer" phase has not yet run for "LowPriorityImplicits", the symbol - * has a SourcefileLoader as type. Calling "doComplete" on it does nothing at - * all, because the source file is part of the files to be compiled anyway. - * So the "reallyExists" test will return "false". - * Only after the namer, the symbol has a lazy type which actually computes - * the info, and "reallyExists" behaves as expected. - * So we need to make sure that the "namer" phase is run on predef's parents - * before running it on predef. - * - * (*) Predef is completed early when calling "mkAttributedRef" during the - * addition of "import Predef._" to sourcefiles. So this situation can't - * happen for user classes. - * - */ - private def coreClassesFirst(files: List[SourceFile]) = { - val goLast = 4 - def rank(f: SourceFile) = { - if (f.file.container.name != "scala") goLast - else f.file.name match { - case "LowPriorityImplicits.scala" => 2 - case "StandardEmbeddings.scala" => 2 - case "EmbeddedControls.scala" => 2 - case "Predef.scala" => 3 /* Predef.scala before Any.scala, etc. */ - case _ => goLast - } - } - files sortBy rank - } } // class Run def printAllUnits() { print("[[syntax trees at end of %25s]]".format(phase)) - afterPhase(phase)(currentRun.units foreach { unit => + exitingPhase(phase)(currentRun.units foreach { unit => nodePrinters showUnit unit }) } @@ -1739,7 +1614,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) */ def showDef(fullName: Name, declsOnly: Boolean, ph: Phase) = { val boringOwners = Set[Symbol](definitions.AnyClass, definitions.AnyRefClass, definitions.ObjectClass) - def phased[T](body: => T): T = afterPhase(ph)(body) + def phased[T](body: => T): T = exitingPhase(ph)(body) def boringMember(sym: Symbol) = boringOwners(sym.owner) def symString(sym: Symbol) = if (sym.isTerm) sym.defString else sym.toString @@ -1785,7 +1660,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) val printer = new icodes.TextPrinter(null, icodes.linearizer) icodes.classes.values.foreach((cls) => { val suffix = if (cls.symbol.hasModuleFlag) "$.icode" else ".icode" - var file = getFile(cls.symbol, suffix) + val file = getFile(cls.symbol, suffix) // if (file.exists()) // file = new File(file.getParentFile(), file.getName() + "1") try { @@ -1795,7 +1670,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) informProgress("wrote " + file) } catch { case ex: IOException => - if (opt.debug) ex.printStackTrace() + if (settings.debug.value) ex.printStackTrace() globalError("could not write file " + file) } }) @@ -1806,14 +1681,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) // and forScaladoc default to onlyPresentation, which is the same as defaulting // to false except in old code. The downside is that this leaves us calling a // deprecated method: but I see no simple way out, so I leave it for now. - def forJVM = opt.jvm - override def forMSIL = opt.msil - def forInteractive = onlyPresentation - def forScaladoc = onlyPresentation + // def forJVM = settings.target.value startsWith "jvm" + override def forMSIL = settings.target.value startsWith "msil" + def forInteractive = false + def forScaladoc = false def createJavadoc = false - - @deprecated("Use forInteractive or forScaladoc, depending on what you're after", "2.9.0") - def onlyPresentation = false } object Global { diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index 7d112dfb3e..5a3ea56f67 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -7,15 +7,12 @@ package scala.tools.nsc import java.io.File import File.pathSeparator - import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager } import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position} import Properties.msilLibPath /** The main class for NSC, a compiler for the programming - * language Scala. + * language Scala. */ object Main extends Driver with EvalLoop { diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala index f18ff19d7d..03190a63f3 100644 --- a/src/compiler/scala/tools/nsc/MainBench.scala +++ b/src/compiler/scala/tools/nsc/MainBench.scala @@ -5,28 +5,20 @@ package scala.tools.nsc -import java.io.File -import File.pathSeparator - -import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager } -import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position} -import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath } import scala.reflect.internal.util.Statistics /** The main class for NSC, a compiler for the programming * language Scala. */ object MainBench extends Driver with EvalLoop { - + lazy val theCompiler = Global(settings, reporter) - + override def newCompiler() = theCompiler - + val NIter = 50 val NBest = 10 - + override def main(args: Array[String]) = { val times = new Array[Long](NIter) var start = System.nanoTime() diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala index e4a20b4a8c..adb03ca374 100644 --- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala +++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala @@ -5,8 +5,6 @@ package scala.tools.nsc -import java.net.URL -import scala.tools.util.PathResolver import io.{ File } import util.{ ClassPath, ScalaClassLoader } import Properties.{ versionString, copyrightString } diff --git a/src/compiler/scala/tools/nsc/ObjectRunner.scala b/src/compiler/scala/tools/nsc/ObjectRunner.scala index f5123513c4..95264aeda6 100644 --- a/src/compiler/scala/tools/nsc/ObjectRunner.scala +++ b/src/compiler/scala/tools/nsc/ObjectRunner.scala @@ -8,15 +8,9 @@ package scala.tools.nsc import java.net.URL import util.ScalaClassLoader -import java.lang.reflect.InvocationTargetException import util.Exceptional.unwrap trait CommonRunner { - /** Check whether a class with the specified name - * exists on the specified class path. */ - def classExists(urls: List[URL], objectName: String): Boolean = - ScalaClassLoader.classExists(urls, objectName) - /** Run a given object, specified by name, using a * specified classpath and argument list. * diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala index cff3590b3f..67dc1e3b66 100644 --- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala +++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala @@ -55,7 +55,7 @@ trait PhaseAssembly { * node object does not exist, then create it. */ def getNodeByPhase(phs: SubComponent): Node = { - var node: Node = getNodeByPhase(phs.phaseName) + val node: Node = getNodeByPhase(phs.phaseName) node.phaseobj match { case None => node.phaseobj = Some(List[SubComponent](phs)) @@ -75,7 +75,7 @@ trait PhaseAssembly { * list of the nodes */ def softConnectNodes(frm: Node, to: Node) { - var e = new Edge(frm, to, false) + val e = new Edge(frm, to, false) this.edges += e frm.after += e @@ -87,7 +87,7 @@ trait PhaseAssembly { * list of the nodes */ def hardConnectNodes(frm: Node, to: Node) { - var e = new Edge(frm, to, true) + val e = new Edge(frm, to, true) this.edges += e frm.after += e @@ -164,7 +164,7 @@ trait PhaseAssembly { } else { - var promote = hl.to.before.filter(e => (!e.hard)) + val promote = hl.to.before.filter(e => (!e.hard)) hl.to.before.clear sanity foreach (edge => hl.to.before += edge) for (edge <- promote) { @@ -182,7 +182,7 @@ trait PhaseAssembly { /** Remove all nodes in the given graph, that have no phase object * Make sure to clean up all edges when removing the node object - * <code>Inform</code> with warnings, if an external phase has a + * `Inform` with warnings, if an external phase has a * dependency on something that is dropped. */ def removeDanglingNodes() { @@ -245,7 +245,7 @@ trait PhaseAssembly { for (phs <- phsSet) { - var fromnode = graph.getNodeByPhase(phs) + val fromnode = graph.getNodeByPhase(phs) phs.runsRightAfter match { case None => @@ -306,7 +306,7 @@ trait PhaseAssembly { sbuf.append("\"" + node.allPhaseNames + "(" + node.level + ")" + "\" [color=\"#0000ff\"]\n") } sbuf.append("}\n") - var out = new BufferedWriter(new FileWriter(filename)) + val out = new BufferedWriter(new FileWriter(filename)) out.write(sbuf.toString) out.flush() out.close() diff --git a/src/compiler/scala/tools/nsc/Phases.scala b/src/compiler/scala/tools/nsc/Phases.scala index c914344fd5..1266622b6d 100644 --- a/src/compiler/scala/tools/nsc/Phases.scala +++ b/src/compiler/scala/tools/nsc/Phases.scala @@ -5,7 +5,6 @@ package scala.tools.nsc -import symtab.Flags import scala.reflect.internal.util.TableDef import scala.language.postfixOps @@ -21,7 +20,6 @@ object Phases { } val values = new Array[Cell](MaxPhases + 1) def results = values filterNot (_ == null) - def apply(ph: Phase): T = values(ph.id).value def update(ph: Phase, value: T): Unit = values(ph.id) = Cell(ph, value) } /** A class for recording the elapsed time of each phase in the @@ -39,7 +37,6 @@ object Phases { >> ("ms" -> (_.value)) >+ " " << ("share" -> (_.value.toDouble * 100 / total formatted "%.2f")) } - def formatted = "" + table() } } diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala index 55fd196716..570d5572d6 100644 --- a/src/compiler/scala/tools/nsc/Properties.scala +++ b/src/compiler/scala/tools/nsc/Properties.scala @@ -21,5 +21,4 @@ object Properties extends scala.util.PropertiesTrait { // derived values def isEmacsShell = propOrEmpty("env.emacs") != "" - def fileEndings = fileEndingString.split("""\|""").toList } diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index 107c4b3df3..92b2dc79ed 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -7,7 +7,6 @@ package scala.tools.nsc import io.{ Directory, File, Path } import java.io.IOException -import java.net.URL import scala.tools.nsc.reporters.{Reporter,ConsoleReporter} import util.Exceptional.unwrap @@ -49,25 +48,12 @@ class ScriptRunner extends HasCompileSocket { case x => x } - def isScript(settings: Settings) = settings.script.value != "" - /** Choose a jar filename to hold the compiled version of a script. */ private def jarFileFor(scriptFile: String)= File( if (scriptFile endsWith ".jar") scriptFile else scriptFile.stripSuffix(".scala") + ".jar" ) - /** Read the entire contents of a file as a String. */ - private def contentsOfFile(filename: String) = File(filename).slurp() - - /** Split a fully qualified object name into a - * package and an unqualified object name */ - private def splitObjectName(fullname: String): (Option[String], String) = - (fullname lastIndexOf '.') match { - case -1 => (None, fullname) - case idx => (Some(fullname take idx), fullname drop (idx + 1)) - } - /** Compile a script using the fsc compilation daemon. */ private def compileWithDaemon(settings: GenericRunnerSettings, scriptFileIn: String) = { diff --git a/src/compiler/scala/tools/nsc/SubComponent.scala b/src/compiler/scala/tools/nsc/SubComponent.scala index a0468a22b9..9b8582ae02 100644 --- a/src/compiler/scala/tools/nsc/SubComponent.scala +++ b/src/compiler/scala/tools/nsc/SubComponent.scala @@ -47,8 +47,8 @@ abstract class SubComponent { private var ownPhaseCache: WeakReference[Phase] = new WeakReference(null) private var ownPhaseRunId = global.NoRunId - @inline final def beforeOwnPhase[T](op: => T) = global.beforePhase(ownPhase)(op) - @inline final def afterOwnPhase[T](op: => T) = global.afterPhase(ownPhase)(op) + @inline final def beforeOwnPhase[T](op: => T) = global.enteringPhase(ownPhase)(op) + @inline final def afterOwnPhase[T](op: => T) = global.exitingPhase(ownPhase)(op) /** The phase corresponding to this subcomponent in the current compiler run */ def ownPhase: Phase = { diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index 5a4be5125d..023f3c229c 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -7,10 +7,7 @@ package scala.tools.nsc package ast import symtab._ -import reporters._ -import scala.reflect.internal.util.{Position, NoPosition} import util.DocStrings._ -import scala.reflect.internal.Chars._ import scala.collection.mutable /* @@ -24,11 +21,6 @@ trait DocComments { self: Global => /** The raw doc comment map */ val docComments = mutable.HashMap[Symbol, DocComment]() - /** Associate comment with symbol `sym` at position `pos`. */ - def docComment(sym: Symbol, docStr: String, pos: Position = NoPosition) = - if ((sym ne null) && (sym ne NoSymbol)) - docComments += (sym -> DocComment(docStr, pos)) - /** The raw doc comment of symbol `sym`, as it appears in the source text, "" if missing. */ def rawDocComment(sym: Symbol): String = @@ -123,8 +115,6 @@ trait DocComments { self: Global => getDocComment(sym) map getUseCases getOrElse List() } - def useCases(sym: Symbol): List[(Symbol, String, Position)] = useCases(sym, sym.enclClass) - /** Returns the javadoc format of doc comment string `s`, including wiki expansion */ def toJavaDoc(s: String): String = expandWiki(s) @@ -464,7 +454,7 @@ trait DocComments { self: Global => //val (classes, pkgs) = site.ownerChain.span(!_.isPackageClass) //val sites = (classes ::: List(pkgs.head, rootMirror.RootClass))) //findIn(sites) - findIn(site.ownerChain ::: List(definitions.EmptyPackage)) + findIn(site.ownerChain ::: List(rootMirror.EmptyPackage)) } def getType(str: String, variable: String): Type = { diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala index d8fb632f73..77acbba056 100644 --- a/src/compiler/scala/tools/nsc/ast/Positions.scala +++ b/src/compiler/scala/tools/nsc/ast/Positions.scala @@ -1,7 +1,7 @@ package scala.tools.nsc package ast -import scala.reflect.internal.util.{ SourceFile, Position, OffsetPosition, NoPosition } +import scala.reflect.internal.util.{ SourceFile, OffsetPosition } trait Positions extends scala.reflect.internal.Positions { self: Global => diff --git a/src/compiler/scala/tools/nsc/ast/Printers.scala b/src/compiler/scala/tools/nsc/ast/Printers.scala index 83222a24b4..b9f348632a 100644 --- a/src/compiler/scala/tools/nsc/ast/Printers.scala +++ b/src/compiler/scala/tools/nsc/ast/Printers.scala @@ -7,8 +7,6 @@ package scala.tools.nsc package ast import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } -import symtab.Flags._ -import symtab.SymbolTable trait Printers extends scala.reflect.internal.Printers { this: Global => @@ -202,91 +200,12 @@ trait Printers extends scala.reflect.internal.Printers { this: Global => override def printTree(tree: Tree) { print(safe(tree)) } } - class TreeMatchTemplate { - // non-trees defined in Trees - // - // case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) - // case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) - // - def apply(t: Tree): Unit = t match { - // eliminated by typer - case Annotated(annot, arg) => - case AssignOrNamedArg(lhs, rhs) => - case DocDef(comment, definition) => - case Import(expr, selectors) => - - // eliminated by refchecks - case ModuleDef(mods, name, impl) => - case TypeTreeWithDeferredRefCheck() => - - // eliminated by erasure - case TypeDef(mods, name, tparams, rhs) => - case Typed(expr, tpt) => - - // eliminated by cleanup - case ApplyDynamic(qual, args) => - - // eliminated by explicitouter - case Alternative(trees) => - case Bind(name, body) => - case CaseDef(pat, guard, body) => - case Star(elem) => - case UnApply(fun, args) => - - // eliminated by lambdalift - case Function(vparams, body) => - - // eliminated by uncurry - case AppliedTypeTree(tpt, args) => - case CompoundTypeTree(templ) => - case ExistentialTypeTree(tpt, whereClauses) => - case SelectFromTypeTree(qual, selector) => - case SingletonTypeTree(ref) => - case TypeBoundsTree(lo, hi) => - - // survivors - case Apply(fun, args) => - case ArrayValue(elemtpt, trees) => - case Assign(lhs, rhs) => - case Block(stats, expr) => - case ClassDef(mods, name, tparams, impl) => - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - case EmptyTree => - case Ident(name) => - case If(cond, thenp, elsep) => - case LabelDef(name, params, rhs) => - case Literal(value) => - case Match(selector, cases) => - case New(tpt) => - case PackageDef(pid, stats) => - case Return(expr) => - case Select(qualifier, selector) => - case Super(qual, mix) => - case Template(parents, self, body) => - case This(qual) => - case Throw(expr) => - case Try(block, catches, finalizer) => - case TypeApply(fun, args) => - case TypeTree() => - case ValDef(mods, name, tpt, rhs) => - - // missing from the Trees comment - case Parens(args) => // only used during parsing - case SelectFromArray(qual, name, erasure) => // only used during erasure - } - } - def asString(t: Tree): String = render(t, newStandardTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value) def asCompactString(t: Tree): String = render(t, newCompactTreePrinter, settings.printtypes.value, settings.uniqid.value, settings.Yshowsymkinds.value) def asCompactDebugString(t: Tree): String = render(t, newCompactTreePrinter, true, true, true) def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) - def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream)) - def newStandardTreePrinter(): TreePrinter = newStandardTreePrinter(new PrintWriter(ConsoleWriter)) - def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer) - def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream)) - def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter)) override def newTreePrinter(writer: PrintWriter): TreePrinter = if (settings.Ycompacttrees.value) newCompactTreePrinter(writer) diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 5c954096f4..30a9348fb0 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -16,8 +16,6 @@ import javax.swing.tree._ import scala.concurrent.Lock import scala.text._ -import symtab.Flags._ -import symtab.SymbolTable import scala.language.implicitConversions /** @@ -509,7 +507,7 @@ abstract class TreeBrowsers { /** Return a textual representation of this t's symbol */ def symbolText(t: Tree): String = { val prefix = - if (t.hasSymbol) "[has] " + if (t.hasSymbolField) "[has] " else if (t.isDef) "[defines] " else "" @@ -529,10 +527,9 @@ abstract class TreeBrowsers { * attributes */ def symbolAttributes(t: Tree): String = { val s = t.symbol - var att = "" if ((s ne null) && (s != NoSymbol)) { - var str = flagsToString(s.flags) + var str = s.flagString if (s.isStaticMember) str = str + " isStatic "; (str + " annotations: " + s.annotations.mkString("", " ", "") + (if (s.isTypeSkolem) "\ndeSkolemized annotations: " + s.deSkolemize.annotations.mkString("", " ", "") else "")) diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 9a5b92e795..e8bc932bf5 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -21,7 +21,6 @@ trait TreeDSL { import global._ import definitions._ - import gen.{ scalaDot } object CODE { // Add a null check to a Tree => Tree function @@ -85,16 +84,12 @@ trait TreeDSL { def ANY_EQ (other: Tree) = OBJ_EQ(other AS ObjectClass.tpe) def ANY_== (other: Tree) = fn(target, Any_==, other) def ANY_!= (other: Tree) = fn(target, Any_!=, other) - def OBJ_== (other: Tree) = fn(target, Object_==, other) def OBJ_!= (other: Tree) = fn(target, Object_!=, other) def OBJ_EQ (other: Tree) = fn(target, Object_eq, other) def OBJ_NE (other: Tree) = fn(target, Object_ne, other) - def INT_| (other: Tree) = fn(target, getMember(IntClass, nme.OR), other) - def INT_& (other: Tree) = fn(target, getMember(IntClass, nme.AND), other) def INT_>= (other: Tree) = fn(target, getMember(IntClass, nme.GE), other) def INT_== (other: Tree) = fn(target, getMember(IntClass, nme.EQ), other) - def INT_!= (other: Tree) = fn(target, getMember(IntClass, nme.NE), other) // generic operations on ByteClass, IntClass, LongClass def GEN_| (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.OR), other) @@ -102,9 +97,6 @@ trait TreeDSL { def GEN_== (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.EQ), other) def GEN_!= (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.NE), other) - def BOOL_&& (other: Tree) = fn(target, Boolean_and, other) - def BOOL_|| (other: Tree) = fn(target, Boolean_or, other) - /** Apply, Select, Match **/ def APPLY(params: Tree*) = Apply(target, params.toList) def APPLY(params: List[Tree]) = Apply(target, params) @@ -130,8 +122,6 @@ trait TreeDSL { def IS(tpe: Type) = gen.mkIsInstanceOf(target, tpe, true) def IS_OBJ(tpe: Type) = gen.mkIsInstanceOf(target, tpe, false) - // XXX having some difficulty expressing nullSafe in a way that doesn't freak out value types - // def TOSTRING() = nullSafe(fn(_: Tree, nme.toString_), LIT("null"))(target) def TOSTRING() = fn(target, nme.toString_) def GETCLASS() = fn(target, Object_getClass) } @@ -159,7 +149,6 @@ trait TreeDSL { def mkTree(rhs: Tree): ResultTreeType def ===(rhs: Tree): ResultTreeType - private var _mods: Modifiers = null private var _tpt: Tree = null private var _pos: Position = null @@ -167,19 +156,12 @@ trait TreeDSL { _tpt = TypeTree(tp) this } - def withFlags(flags: Long*): this.type = { - if (_mods == null) - _mods = defaultMods - - _mods = flags.foldLeft(_mods)(_ | _) - this - } def withPos(pos: Position): this.type = { _pos = pos this } - final def mods = if (_mods == null) defaultMods else _mods + final def mods = defaultMods final def tpt = if (_tpt == null) defaultTpt else _tpt final def pos = if (_pos == null) defaultPos else _pos } @@ -244,7 +226,6 @@ trait TreeDSL { } class TryStart(body: Tree, catches: List[CaseDef], fin: Tree) { def CATCH(xs: CaseDef*) = new TryStart(body, xs.toList, fin) - def FINALLY(x: Tree) = Try(body, catches, x) def ENDTRY = Try(body, catches, fin) } @@ -252,16 +233,9 @@ trait TreeDSL { def DEFAULT: CaseStart = new CaseStart(WILD.empty, EmptyTree) class SymbolMethods(target: Symbol) { - def BIND(body: Tree) = Bind(target, body) - def IS_NULL() = REF(target) OBJ_EQ NULL - def NOT_NULL() = REF(target) OBJ_NE NULL - - def GET() = fn(REF(target), nme.get) - - // name of nth indexed argument to a method (first parameter list), defaults to 1st - def ARG(idx: Int = 0) = Ident(target.paramss.head(idx)) - def ARGS = target.paramss.head - def ARGNAMES = ARGS map Ident + def IS_NULL() = REF(target) OBJ_EQ NULL + def GET() = fn(REF(target), nme.get) + def ARGS = target.paramss.head } /** Top level accessible. */ @@ -269,32 +243,13 @@ trait TreeDSL { def THROW(sym: Symbol, msg: Tree): Throw = Throw(sym.tpe, msg.TOSTRING()) def NEW(tpt: Tree, args: Tree*): Tree = New(tpt, List(args.toList)) - def NEW(sym: Symbol, args: Tree*): Tree = New(sym.tpe, args: _*) - - def DEF(name: Name, tp: Type): DefTreeStart = DEF(name) withType tp - def DEF(name: Name): DefTreeStart = new DefTreeStart(name) def DEF(sym: Symbol): DefSymStart = new DefSymStart(sym) - - def VAL(name: Name, tp: Type): ValTreeStart = VAL(name) withType tp - def VAL(name: Name): ValTreeStart = new ValTreeStart(name) def VAL(sym: Symbol): ValSymStart = new ValSymStart(sym) - def VAR(name: Name, tp: Type): ValTreeStart = VAL(name, tp) withFlags Flags.MUTABLE - def VAR(name: Name): ValTreeStart = VAL(name) withFlags Flags.MUTABLE - def VAR(sym: Symbol): ValSymStart = VAL(sym) withFlags Flags.MUTABLE - - def LAZYVAL(name: Name, tp: Type): ValTreeStart = VAL(name, tp) withFlags Flags.LAZY - def LAZYVAL(name: Name): ValTreeStart = VAL(name) withFlags Flags.LAZY - def LAZYVAL(sym: Symbol): ValSymStart = VAL(sym) withFlags Flags.LAZY - def AND(guards: Tree*) = if (guards.isEmpty) EmptyTree else guards reduceLeft gen.mkAnd - def OR(guards: Tree*) = - if (guards.isEmpty) EmptyTree - else guards reduceLeft gen.mkOr - def IF(tree: Tree) = new IfStart(tree, EmptyTree) def TRY(tree: Tree) = new TryStart(tree, Nil, EmptyTree) def BLOCK(xs: Tree*) = Block(xs.init.toList, xs.last) @@ -312,11 +267,6 @@ trait TreeDSL { case List(tree) if flattenUnary => tree case _ => Apply(TupleClass(trees.length).companionModule, trees: _*) } - def makeTupleType(trees: List[Tree], flattenUnary: Boolean): Tree = trees match { - case Nil => gen.scalaUnitConstr - case List(tree) if flattenUnary => tree - case _ => AppliedTypeTree(REF(TupleClass(trees.length)), trees) - } /** Implicits - some of these should probably disappear **/ implicit def mkTreeMethods(target: Tree): TreeMethods = new TreeMethods(target) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 53d35791b6..1adcf46958 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -8,7 +8,6 @@ package ast import scala.collection.mutable.ListBuffer import symtab.Flags._ -import symtab.SymbolTable import scala.language.postfixOps /** XXX to resolve: TreeGen only assumes global is a SymbolTable, but @@ -22,7 +21,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { def mkCheckInit(tree: Tree): Tree = { val tpe = - if (tree.tpe != null || !tree.hasSymbol) tree.tpe + if (tree.tpe != null || !tree.hasSymbolField) tree.tpe else tree.symbol.tpe if (!global.phase.erasedTypes && settings.warnSelectNullable.value && @@ -52,7 +51,10 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { } // wrap the given expression in a SoftReference so it can be gc-ed - def mkSoftRef(expr: Tree): Tree = atPos(expr.pos)(New(SoftReferenceClass.tpe, expr)) + def mkSoftRef(expr: Tree): Tree = atPos(expr.pos) { + val constructor = SoftReferenceClass.info.nonPrivateMember(nme.CONSTRUCTOR).suchThat(_.paramss.flatten.size == 1) + NewFromConstructor(constructor, expr) + } // annotate the expression with @unchecked def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) { @@ -60,72 +62,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { // are very picky about things and it crashes the compiler with "unexpected new". Annotated(New(scalaDot(UncheckedClass.name), ListOfNil), expr) } - // if it's a Match, mark the selector unchecked; otherwise nothing. - def mkUncheckedMatch(tree: Tree) = tree match { - case Match(selector, cases) => atPos(tree.pos)(Match(mkUnchecked(selector), cases)) - case _ => tree - } - - def mkSynthSwitchSelector(expr: Tree): Tree = atPos(expr.pos) { - // This can't be "Annotated(New(SwitchClass), expr)" because annotations - // are very picky about things and it crashes the compiler with "unexpected new". - Annotated(Ident(nme.synthSwitch), expr) - } - - // TODO: would be so much nicer if we would know during match-translation (i.e., type checking) - // whether we should emit missingCase-style apply (and isDefinedAt), instead of transforming trees post-factum - class MatchMatcher { - def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = unknownTree(orig) - def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = unknownTree(orig) - def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree): Tree = unknownTree(orig) - - def genVirtualizedMatch(prologue: List[Tree], cases: List[Tree], matchEndDef: Tree): Tree = Block(prologue ++ cases, matchEndDef) - - def apply(matchExpr: Tree): Tree = matchExpr match { - // old-style match or virtpatmat switch - case Match(selector, cases) => // println("simple match: "+ (selector, cases) + "for:\n"+ matchExpr ) - caseMatch(matchExpr, selector, cases, identity) - // old-style match or virtpatmat switch - case Block((vd: ValDef) :: Nil, orig@Match(selector, cases)) => // println("block match: "+ (selector, cases, vd) + "for:\n"+ matchExpr ) - caseMatch(matchExpr, selector, cases, m => copyBlock(matchExpr, List(vd), m)) - // virtpatmat - case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr ) - caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher) - // optimized version of virtpatmat - case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) => - // the assumption is once we encounter a case, the remainder of the block will consist of cases - // the prologue may be empty, usually it is the valdef that stores the scrut - val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef]) - caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity) - // optimized version of virtpatmat - case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall treeInfo.hasSynthCaseSymbol) => - val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef]) - caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m)) - case other => - unknownTree(other) - } - - def unknownTree(t: Tree): Tree = throw new MatchError(t) - def copyBlock(orig: Tree, stats: List[Tree], expr: Tree): Block = Block(stats, expr) - - def dropSyntheticCatchAll(cases: List[CaseDef]): List[CaseDef] = - if (!opt.virtPatmat) cases - else cases filter { - case CaseDef(pat, EmptyTree, Throw(Apply(Select(New(exTpt), nme.CONSTRUCTOR), _))) if (treeInfo.isWildcardArg(pat) && (exTpt.tpe.typeSymbol eq MatchErrorClass)) => false - case CaseDef(pat, guard, body) => true - } - } - - def mkCached(cvar: Symbol, expr: Tree): Tree = { - val cvarRef = mkUnattributedRef(cvar) - Block( - List( - If(Apply(Select(cvarRef, nme.eq), List(Literal(Constant(null)))), - Assign(cvarRef, expr), - EmptyTree)), - cvarRef - ) - } // Builds a tree of the form "{ lhs = rhs ; lhs }" def mkAssignAndReturn(lhs: Symbol, rhs: Tree): Tree = { @@ -148,11 +84,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { ValDef(mval) } - // def m: T = { if (m$ eq null) m$ = new m$class(...) m$ } - // where (...) are eventual outer accessors - def mkCachedModuleAccessDef(accessor: Symbol, mvar: Symbol) = - DefDef(accessor, mkCached(mvar, newModule(accessor, mvar.tpe))) - def mkModuleAccessDef(accessor: Symbol, msym: Symbol) = DefDef(accessor, Select(This(msym.owner), msym)) @@ -162,10 +93,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { else New(tpe, This(accessor.owner.enclClass)) } - // def m: T; - def mkModuleAccessDcl(accessor: Symbol) = - DefDef(accessor setFlag lateDEFERRED, EmptyTree) - def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = mkRuntimeCall(meth, Nil, args) @@ -206,7 +133,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { else AppliedTypeTree(Ident(clazz), targs map TypeTree) )) } - def mkSuperSelect = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) + def mkSuperInitCall: Select = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) def wildcardStar(tree: Tree) = atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) } @@ -262,25 +189,6 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { else mkCast(tree, pt) - def mkZeroContravariantAfterTyper(tp: Type): Tree = { - // contravariant -- for replacing an argument in a method call - // must use subtyping, as otherwise we miss types like `Any with Int` - val tree = - if (NullClass.tpe <:< tp) Literal(Constant(null)) - else if (UnitClass.tpe <:< tp) Literal(Constant()) - else if (BooleanClass.tpe <:< tp) Literal(Constant(false)) - else if (FloatClass.tpe <:< tp) Literal(Constant(0.0f)) - else if (DoubleClass.tpe <:< tp) Literal(Constant(0.0d)) - else if (ByteClass.tpe <:< tp) Literal(Constant(0.toByte)) - else if (ShortClass.tpe <:< tp) Literal(Constant(0.toShort)) - else if (IntClass.tpe <:< tp) Literal(Constant(0)) - else if (LongClass.tpe <:< tp) Literal(Constant(0L)) - else if (CharClass.tpe <:< tp) Literal(Constant(0.toChar)) - else mkCast(Literal(Constant(null)), tp) - - tree - } - /** Translate names in Select/Ident nodes to type names. */ def convertToTypeName(tree: Tree): Option[RefTree] = tree match { diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index cbbb4c8ba8..f53f99a279 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -6,10 +6,6 @@ package scala.tools.nsc package ast -import scala.reflect.internal.HasFlags -import scala.reflect.internal.Flags._ -import symtab._ - /** This class ... * * @author Martin Odersky @@ -19,8 +15,6 @@ abstract class TreeInfo extends scala.reflect.internal.TreeInfo { val global: Global import global._ - import definitions.ThrowableClass - /** Is tree legal as a member definition of an interface? */ override def isInterfaceMember(tree: Tree): Boolean = tree match { @@ -42,7 +36,4 @@ abstract class TreeInfo extends scala.reflect.internal.TreeInfo { case ClassDef(_, `name`, _, _) :: Nil => true case _ => super.firstDefinesClassOrObject(trees, name) } - - def isInterface(mods: HasFlags, body: List[Tree]) = - mods.isTrait && (body forall isInterfaceMember) } diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index ed73464c93..c78c40dcd3 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -116,7 +116,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1; - val superRef: Tree = atPos(superPos)(gen.mkSuperSelect) + val superRef: Tree = atPos(superPos)(gen.mkSuperInitCall) val superCall = (superRef /: argss) (Apply.apply) List( atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( @@ -341,7 +341,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => tree case _ => val dupl = tree.duplicate - if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) + if (tree.hasSymbolField && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel)) dupl.symbol = NoSymbol dupl.tpe = null dupl diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index 553a2088a6..639780149e 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -10,10 +10,8 @@ import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer } import scala.util.control.ControlThrowable import scala.tools.nsc.util.CharArrayReader -import scala.reflect.internal.util.SourceFile -import scala.xml.{ Text, TextBuffer } +import scala.xml.TextBuffer import scala.xml.parsing.MarkupParserCommon -import scala.xml.Utility.{ isNameStart, isNameChar, isSpace } import scala.reflect.internal.Chars.{ SU, LF } // XXX/Note: many/most of the functions in here are almost direct cut and pastes @@ -26,12 +24,6 @@ import scala.reflect.internal.Chars.{ SU, LF } // I rewrote most of these, but not as yet the library versions: so if you are // tempted to touch any of these, please be aware of that situation and try not // to let it get any worse. -- paulp - -/** This trait ... - * - * @author Burak Emir - * @version 1.0 - */ trait MarkupParsers { self: Parsers => @@ -51,7 +43,7 @@ trait MarkupParsers { class MarkupParser(parser: SourceFileParser, final val preserveWS: Boolean) extends MarkupParserCommon { - import Tokens.{ EMPTY, LBRACE, RBRACE } + import Tokens.{ LBRACE, RBRACE } type PositionType = Position type InputType = CharArrayReader @@ -89,7 +81,7 @@ trait MarkupParsers { var xEmbeddedBlock = false - private var debugLastStartElement = new mutable.Stack[(Int, String)] + private val debugLastStartElement = new mutable.Stack[(Int, String)] private def debugLastPos = debugLastStartElement.top._1 private def debugLastElem = debugLastStartElement.top._2 @@ -124,7 +116,6 @@ trait MarkupParsers { val start = curOffset val key = xName xEQ - val delim = ch val mid = curOffset val value: Tree = ch match { case '"' | '\'' => @@ -219,9 +210,6 @@ trait MarkupParsers { /** Returns true if it encounters an end tag (without consuming it), * appends trees to ts as side-effect. - * - * @param ts ... - * @return ... */ private def content_LT(ts: ArrayBuffer[Tree]): Boolean = { if (ch == '/') @@ -410,7 +398,7 @@ trait MarkupParsers { * | Name [S] '/' '>' */ def xPattern: Tree = { - var start = curOffset + val start = curOffset val qname = xName debugLastStartElement.push((start, qname)) xSpaceOpt diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index a2a45d0684..f430f1fc34 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -9,7 +9,8 @@ package scala.tools.nsc package ast.parser -import scala.collection.mutable.{ListBuffer, StringBuilder} +import scala.collection.{ mutable, immutable } +import mutable.{ ListBuffer, StringBuilder } import scala.reflect.internal.{ ModifierFlags => Flags } import scala.reflect.internal.Chars.{ isScalaLetter } import scala.reflect.internal.util.{ SourceFile, OffsetPosition } @@ -94,7 +95,7 @@ trait ParsersCommon extends ScannersCommon { * <ol> * <li> * Places all pattern variables in Bind nodes. In a pattern, for - * identifiers <code>x</code>:<pre> + * identifiers `x`:<pre> * x => x @ _ * x:T => x @ (_ : T)</pre> * </li> @@ -167,7 +168,6 @@ self => object symbXMLBuilder extends SymbolicXMLBuilder(this, preserveWS = true) { // DEBUG choices val global: self.global.type = self.global - def freshName(prefix: String): Name = SourceFileParser.this.freshName(prefix) } def xmlLiteral : Tree = xmlp.xLiteral @@ -299,11 +299,7 @@ self => inScalaPackage = false currentPackage = "" } - private lazy val primitiveNames: Set[Name] = tpnme.ScalaValueNames.toSet - - private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" - private def isScalaArray(name: Name) = inScalaRootPackage && name == tpnme.Array - private def isPrimitiveType(name: Name) = inScalaRootPackage && primitiveNames(name) + private def inScalaRootPackage = inScalaPackage && currentPackage == "scala" def parseStartRule: () => Tree @@ -380,7 +376,6 @@ self => * } * }}} */ - import definitions._ def emptyPkg = atPos(0, 0, 0) { Ident(nme.EMPTY_PACKAGE_NAME) } def emptyInit = DefDef( @@ -389,7 +384,7 @@ self => Nil, ListOfNil, TypeTree(), - Block(List(Apply(gen.mkSuperSelect, Nil)), Literal(Constant(()))) + Block(List(Apply(gen.mkSuperInitCall, Nil)), Literal(Constant(()))) ) // def main @@ -468,7 +463,7 @@ self => /* ------------- ERROR HANDLING ------------------------------------------- */ - var assumedClosingParens = scala.collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0) + val assumedClosingParens = mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0) private var inFunReturnType = false @inline private def fromWithinReturnType[T](body: => T): T = { @@ -645,8 +640,6 @@ self => case _ => false } - def isTypeIntro: Boolean = isTypeIntroToken(in.token) - def isStatSeqEnd = in.token == RBRACE || in.token == EOF def isStatSep(token: Int): Boolean = @@ -770,10 +763,6 @@ self => } } - def checkSize(kind: String, size: Int, max: Int) { - if (size > max) syntaxError("too many "+kind+", maximum = "+max, false) - } - def checkAssoc(offset: Int, op: Name, leftAssoc: Boolean) = if (treeInfo.isLeftAssoc(op) != leftAssoc) syntaxError( @@ -923,7 +912,7 @@ self => ) def compoundTypeRest(t: Tree): Tree = { - var ts = new ListBuffer[Tree] += t + val ts = new ListBuffer[Tree] += t while (in.token == WITH) { in.nextToken() ts += annotType() @@ -980,11 +969,8 @@ self => /** Assumed (provisionally) to be TermNames. */ def ident(skipIt: Boolean): Name = - if (isIdent) { - val name = in.name.encode - in.nextToken() - name - } else { + if (isIdent) rawIdent().encode + else { syntaxErrorOrIncomplete(expectedMsg(IDENTIFIER), skipIt) nme.ERROR } @@ -1138,16 +1124,7 @@ self => }) } - private def stringOp(t: Tree, op: TermName) = { - val str = in.strVal - in.nextToken() - if (str.length == 0) t - else atPos(t.pos.startOrPoint) { - Apply(Select(t, op), List(Literal(Constant(str)))) - } - } - - private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) { + private def interpolatedString(inPattern: Boolean): Tree = atPos(in.offset) { val start = in.offset val interpolator = in.name @@ -1231,15 +1208,6 @@ self => /* ----------- EXPRESSIONS ------------------------------------------------ */ - /** {{{ - * EqualsExpr ::= `=' Expr - * }}} - */ - def equalsExpr(): Tree = { - accept(EQUALS) - expr() - } - def condExpr(): Tree = { if (in.token == LPAREN) { in.nextToken() @@ -1283,7 +1251,7 @@ self => def expr(): Tree = expr(Local) def expr(location: Int): Tree = { - var savedPlaceholderParams = placeholderParams + val savedPlaceholderParams = placeholderParams placeholderParams = List() var res = expr0(location) if (!placeholderParams.isEmpty && !isWildcard(res)) { @@ -1333,7 +1301,6 @@ self => parseTry case WHILE => def parseWhile = { - val start = in.offset atPos(in.skipToken()) { val lname: Name = freshTermName(nme.WHILE_PREFIX) val cond = condExpr() @@ -1345,7 +1312,6 @@ self => parseWhile case DO => def parseDo = { - val start = in.offset atPos(in.skipToken()) { val lname: Name = freshTermName(nme.DO_WHILE_PREFIX) val body = expr() @@ -1809,7 +1775,6 @@ self => * }}} */ def pattern2(): Tree = { - val nameOffset = in.offset val p = pattern3() if (in.token != AT) p @@ -1922,7 +1887,7 @@ self => val start = in.offset in.token match { case IDENTIFIER | BACKQUOTED_IDENT | THIS => - var t = stableId() + val t = stableId() in.token match { case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => t match { @@ -1984,7 +1949,6 @@ self => /** Default entry points into some pattern contexts. */ def pattern(): Tree = noSeq.pattern() - def patterns(): List[Tree] = noSeq.patterns() def seqPatterns(): List[Tree] = seqOK.patterns() def xmlSeqPatterns(): List[Tree] = xmlSeqOK.patterns() // Called from xml parser def argumentPatterns(): List[Tree] = inParens { @@ -2629,7 +2593,6 @@ self => in.nextToken() newLinesOpt() atPos(start, in.offset) { - val nameOffset = in.offset val name = identForType() // @M! a type alias as well as an abstract type may declare type parameters val tparams = typeParamClauseOpt(name, null) @@ -2906,7 +2869,6 @@ self => * }}} */ def packaging(start: Int): Tree = { - val nameOffset = in.offset val pkg = pkgQualId() val stats = inBracesOrNil(topStatSeq()) makePackaging(start, pkg, stats) @@ -3116,7 +3078,6 @@ self => ts ++= topStatSeq() } } else { - val nameOffset = in.offset in.flushDoc val pkg = pkgQualId() diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 4f564c5d0b..af7f48988f 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -10,7 +10,8 @@ import scala.reflect.internal.util._ import scala.reflect.internal.Chars._ import Tokens._ import scala.annotation.switch -import scala.collection.mutable.{ ListBuffer, ArrayBuffer } +import scala.collection.{ mutable, immutable } +import mutable.{ ListBuffer, ArrayBuffer } import scala.xml.Utility.{ isNameStart } /** See Parsers.scala / ParsersCommon for some explanation of ScannersCommon. @@ -26,7 +27,6 @@ trait ScannersCommon { trait ScannerCommon extends CommonTokenData { // things to fill in, in addition to buf, decodeUni which come from CharArrayReader - def warning(off: Int, msg: String): Unit def error (off: Int, msg: String): Unit def incompleteInputError(off: Int, msg: String): Unit def deprecationWarning(off: Int, msg: String): Unit @@ -50,9 +50,6 @@ trait Scanners extends ScannersCommon { /** Offset into source character array */ type Offset = Int - /** An undefined offset */ - val NoOffset: Offset = -1 - trait TokenData extends CommonTokenData { /** the next token */ @@ -88,8 +85,6 @@ trait Scanners extends ScannersCommon { def isAtEnd = charOffset >= buf.length - def flush = { charOffset = offset; nextChar(); this } - def resume(lastCode: Int) = { token = lastCode if (next.token != EMPTY && !reporter.hasErrors) @@ -98,10 +93,6 @@ trait Scanners extends ScannersCommon { nextToken() } - /** the last error offset - */ - var errOffset: Offset = NoOffset - /** A character buffer for literals */ val cbuf = new StringBuilder @@ -283,10 +274,16 @@ trait Scanners extends ScannersCommon { prev copyFrom this val nextLastOffset = charOffset - 1 fetchToken() + def resetOffset() { + offset = prev.offset + lastOffset = prev.lastOffset + } if (token == CLASS) { token = CASECLASS + resetOffset() } else if (token == OBJECT) { token = CASEOBJECT + resetOffset() } else { lastOffset = nextLastOffset next copyFrom this @@ -402,7 +399,7 @@ trait Scanners extends ScannersCommon { * there a realistic situation where one would need it? */ if (isDigit(ch)) { - if (opt.future) syntaxError("Non-zero numbers may not have a leading zero.") + if (settings.future.value) syntaxError("Non-zero numbers may not have a leading zero.") else deprecationWarning("Treating numbers with a leading zero as octal is deprecated.") } base = 8 @@ -607,7 +604,10 @@ trait Scanners extends ScannersCommon { if (ch == '`') { nextChar() finishNamed(BACKQUOTED_IDENT) - if (name.length == 0) syntaxError("empty quoted identifier") + if (name.length == 0) + syntaxError("empty quoted identifier") + else if (name == nme.WILDCARD) + syntaxError("wildcard invalid as backquoted identifier") } else syntaxError("unclosed quoted identifier") } @@ -998,9 +998,9 @@ trait Scanners extends ScannersCommon { val c = lookahead.getc() /** As of scala 2.11, it isn't a number unless c here is a digit, so - * opt.future excludes the rest of the logic. + * settings.future.value excludes the rest of the logic. */ - if (opt.future && !isDigit(c)) + if (settings.future.value && !isDigit(c)) return setStrVal() val isDefinitelyNumber = (c: @switch) match { @@ -1054,7 +1054,6 @@ trait Scanners extends ScannersCommon { def syntaxError(off: Offset, msg: String) { error(off, msg) token = ERROR - errOffset = off } /** generate an error at the current token offset @@ -1067,7 +1066,6 @@ trait Scanners extends ScannersCommon { def incompleteInputError(msg: String) { incompleteInputError(offset, msg) token = EOF - errOffset = offset } override def toString() = token match { @@ -1232,7 +1230,6 @@ trait Scanners extends ScannersCommon { override val decodeUni: Boolean = !settings.nouescape.value // suppress warnings, throw exception on errors - def warning(off: Offset, msg: String): Unit = () def deprecationWarning(off: Offset, msg: String): Unit = () def error (off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) def incompleteInputError(off: Offset, msg: String): Unit = throw new MalformedInput(off, msg) @@ -1243,7 +1240,6 @@ trait Scanners extends ScannersCommon { class UnitScanner(unit: CompilationUnit, patches: List[BracePatch]) extends SourceFileScanner(unit.source) { def this(unit: CompilationUnit) = this(unit, List()) - override def warning(off: Offset, msg: String) = unit.warning(unit.position(off), msg) override def deprecationWarning(off: Offset, msg: String) = unit.deprecationWarning(unit.position(off), msg) override def error (off: Offset, msg: String) = unit.error(unit.position(off), msg) override def incompleteInputError(off: Offset, msg: String) = unit.incompleteInputError(unit.position(off), msg) @@ -1302,7 +1298,7 @@ trait Scanners extends ScannersCommon { } class ParensAnalyzer(unit: CompilationUnit, patches: List[BracePatch]) extends UnitScanner(unit, patches) { - var balance = scala.collection.mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0) + val balance = mutable.Map(RPAREN -> 0, RBRACKET -> 0, RBRACE -> 0) init() @@ -1424,18 +1420,6 @@ trait Scanners extends ScannersCommon { else bp :: insertPatch(bps, patch) } - def leftColumn(offset: Int) = - if (offset == -1) -1 else column(lineStart(line(offset))) - - def rightColumn(offset: Int, default: Int) = - if (offset == -1) -1 - else { - val rlin = line(offset) - if (lineStart(rlin) == offset) column(offset) - else if (rlin + 1 < lineStart.length) column(lineStart(rlin + 1)) - else default - } - def insertRBrace(): List[BracePatch] = { def insert(bps: List[BracePair]): List[BracePatch] = bps match { case List() => patches @@ -1477,17 +1461,6 @@ trait Scanners extends ScannersCommon { delete(bracePairs) } - def imbalanceMeasure: Int = { - def measureList(bps: List[BracePair]): Int = - (bps map measure).sum - def measure(bp: BracePair): Int = - (if (bp.lindent != bp.rindent) 1 else 0) + measureList(bp.nested) - measureList(bracePairs) - } - - def improves(patches1: List[BracePatch]): Boolean = - imbalanceMeasure > new ParensAnalyzer(unit, patches1).imbalanceMeasure - override def error(offset: Int, msg: String) {} } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index e8ef670222..4329ccefc7 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -11,7 +11,6 @@ import scala.xml.{ EntityRef, Text } import scala.xml.XML.{ xmlns } import symtab.Flags.MUTABLE import scala.reflect.internal.util.StringOps.splitWhere -import scala.language.implicitConversions /** This class builds instance of `Tree` that represent XML. * diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala index c3fd414426..5a7dc4950d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala @@ -6,15 +6,11 @@ package scala.tools.nsc package ast.parser -import scala.annotation.switch - /** Common code between JavaTokens and Tokens. Not as much (and not as concrete) * as one might like because JavaTokens for no clear reason chose new numbers for * identical token sets. */ abstract class Tokens { - import scala.reflect.internal.Chars._ - /** special tokens */ final val EMPTY = -3 final val UNDEF = -2 @@ -34,14 +30,6 @@ abstract class Tokens { def isIdentifier(code: Int): Boolean def isLiteral(code: Int): Boolean - def isKeyword(code: Int): Boolean - def isSymbol(code: Int): Boolean - - final def isSpace(at: Char) = at == ' ' || at == '\t' - final def isNewLine(at: Char) = at == CR || at == LF || at == FF - final def isBrace(code: Int) = code >= LPAREN && code <= RBRACE - final def isOpenBrace(code: Int) = isBrace(code) && (code % 2 == 0) - final def isCloseBrace(code: Int) = isBrace(code) && (code % 2 == 1) } object Tokens extends Tokens { @@ -52,20 +40,10 @@ object Tokens extends Tokens { def isLiteral(code: Int) = code >= CHARLIT && code <= INTERPOLATIONID - /** identifiers */ final val IDENTIFIER = 10 final val BACKQUOTED_IDENT = 11 - def isIdentifier(code: Int) = - code >= IDENTIFIER && code <= BACKQUOTED_IDENT - - @switch def canBeginExpression(code: Int) = code match { - case IDENTIFIER|BACKQUOTED_IDENT|USCORE => true - case LBRACE|LPAREN|LBRACKET|COMMENT => true - case IF|DO|WHILE|FOR|NEW|TRY|THROW => true - case NULL|THIS|TRUE|FALSE => true - case code => isLiteral(code) - } + def isIdentifier(code: Int) = code >= IDENTIFIER && code <= BACKQUOTED_IDENT // used by ide /** keywords */ final val IF = 20 @@ -113,17 +91,6 @@ object Tokens extends Tokens { final val MACRO = 62 // not yet used in 2.10 final val THEN = 63 // not yet used in 2.10 - def isKeyword(code: Int) = - code >= IF && code <= LAZY - - @switch def isDefinition(code: Int) = code match { - case CLASS|TRAIT|OBJECT => true - case CASECLASS|CASEOBJECT => true - case DEF|VAL|VAR => true - case TYPE => true - case _ => false - } - /** special symbols */ final val COMMA = 70 final val SEMI = 71 @@ -141,9 +108,6 @@ object Tokens extends Tokens { final val AT = 83 final val VIEWBOUND = 84 - def isSymbol(code: Int) = - code >= COMMA && code <= VIEWBOUND - /** parenthesis */ final val LPAREN = 90 final val RPAREN = 91 diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 0ac46a18bc..d6c499d838 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -26,15 +26,11 @@ abstract class TreeBuilder { def o2p(offset: Int): Position def r2p(start: Int, point: Int, end: Int): Position - def rootId(name: Name) = gen.rootId(name) def rootScalaDot(name: Name) = gen.rootScalaDot(name) def scalaDot(name: Name) = gen.scalaDot(name) def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) - def scalaAnyValConstr = scalaDot(tpnme.AnyVal) - def scalaAnyConstr = scalaDot(tpnme.Any) def scalaUnitConstr = scalaDot(tpnme.Unit) def productConstr = scalaDot(tpnme.Product) - def productConstrN(n: Int) = scalaDot(newTypeName("Product" + n)) def serializableConstr = scalaDot(tpnme.Serializable) def convertToTypeName(t: Tree) = gen.convertToTypeName(t) @@ -191,7 +187,7 @@ abstract class TreeBuilder { } else { val x = freshTermName() Block( - List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))), + List(ValDef(Modifiers(SYNTHETIC | ARTIFACT), x, TypeTree(), stripParens(left))), Apply(atPos(opPos union right.pos) { Select(stripParens(right), op.encode) }, List(Ident(x)))) } } else { @@ -379,13 +375,6 @@ abstract class TreeBuilder { def makeCombination(pos: Position, meth: TermName, qual: Tree, pat: Tree, body: Tree): Tree = Apply(Select(qual, meth) setPos qual.pos, List(makeClosure(pos, pat, body))) setPos pos - /** Optionally, if pattern is a `Bind`, the bound name, otherwise None. - */ - def patternVar(pat: Tree): Option[Name] = pat match { - case Bind(name, _) => Some(name) - case _ => None - } - /** If `pat` is not yet a `Bind` wrap it in one with a fresh name */ def makeBind(pat: Tree): Tree = pat match { @@ -451,18 +440,6 @@ abstract class TreeBuilder { def makeForYield(enums: List[Enumerator], body: Tree): Tree = makeFor(nme.map, nme.flatMap, enums, body) - /** Create tree for a lifted expression XX-LIFTING - */ - def makeLifted(gs: List[ValFrom], body: Tree): Tree = { - def combine(gs: List[ValFrom]): ValFrom = (gs: @unchecked) match { - case g :: Nil => g - case ValFrom(pos1, pat1, rhs1) :: gs2 => - val ValFrom(pos2, pat2, rhs2) = combine(gs2) - ValFrom(pos1, makeTuple(List(pat1, pat2), false), Apply(Select(rhs1, nme.zip), List(rhs2))) - } - makeForYield(List(combine(gs)), body) - } - /** Create tree for a pattern alternative */ def makeAlternative(ts: List[Tree]): Tree = { def alternatives(t: Tree): List[Tree] = t match { @@ -497,7 +474,7 @@ abstract class TreeBuilder { def makeCatchFromExpr(catchExpr: Tree): CaseDef = { val binder = freshTermName("x") val pat = Bind(binder, Typed(Ident(nme.WILDCARD), Ident(tpnme.Throwable))) - val catchDef = ValDef(NoMods, freshTermName("catchExpr"), TypeTree(), catchExpr) + val catchDef = ValDef(Modifiers(ARTIFACT), freshTermName("catchExpr"), TypeTree(), catchExpr) val catchFn = Ident(catchDef.name) val body = atPos(catchExpr.pos.makeTransparent)(Block( List(catchDef), @@ -568,7 +545,7 @@ abstract class TreeBuilder { val tmp = freshTermName() val firstDef = atPos(matchExpr.pos) { - ValDef(Modifiers(PrivateLocal | SYNTHETIC | (mods.flags & LAZY)), + ValDef(Modifiers(PrivateLocal | SYNTHETIC | ARTIFACT | (mods.flags & LAZY)), tmp, TypeTree(), matchExpr) } var cnt = 0 diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala index fc5d4372c5..fd4366baf1 100644 --- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala +++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala @@ -8,7 +8,6 @@ package backend import io.AbstractFile import util.{ClassPath,JavaClassPath,MergedClassPath,DeltaClassPath} -import util.ClassPath.{ JavaContext, DefaultJavaContext } import scala.tools.util.PathResolver trait JavaPlatform extends Platform { diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala index 8cbb5bc980..f6b0701f86 100644 --- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala +++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package backend -import scala.tools.nsc.backend.icode._ import scala.collection.{ mutable, immutable } /** Scala primitive operations are represented as methods in `Any` and @@ -565,7 +564,7 @@ abstract class ScalaPrimitives { import definitions._ val code = getPrimitive(fun) - def elementType = beforeTyper { + def elementType = enteringTyper { val arrayParent = tpe :: tpe.parents collectFirst { case TypeRef(_, ArrayClass, elem :: Nil) => elem } diff --git a/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala b/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala index 798a80ea37..45ca39fee4 100644 --- a/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala +++ b/src/compiler/scala/tools/nsc/backend/WorklistAlgorithm.scala @@ -6,8 +6,7 @@ package scala.tools.nsc package backend -import scala.tools.nsc.ast._ -import scala.collection.{ mutable, immutable } +import scala.collection.mutable /** * Simple implementation of a worklist algorithm. A processing @@ -32,8 +31,6 @@ trait WorklistAlgorithm { * Run the iterative algorithm until the worklist remains empty. * The initializer is run once before the loop starts and should * initialize the worklist. - * - * @param initWorklist ... */ def run(initWorklist: => Unit) = { initWorklist diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala index 068836fe4f..34bdc1ede4 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala @@ -17,7 +17,7 @@ trait BasicBlocks { self: ICodes => import opcodes._ - import global.{ ifDebug, settings, log, nme } + import global.{ settings, log, nme } import nme.isExceptionResultName /** Override Array creation for efficiency (to not go through reflection). */ @@ -122,7 +122,7 @@ trait BasicBlocks { def closed: Boolean = hasFlag(CLOSED) def closed_=(b: Boolean) = if (b) setFlag(CLOSED) else resetFlag(CLOSED) - /** When set, the <code>emit</code> methods will be ignored. */ + /** When set, the `emit` methods will be ignored. */ def ignore: Boolean = hasFlag(IGNORING) def ignore_=(b: Boolean) = if (b) setFlag(IGNORING) else resetFlag(IGNORING) @@ -260,7 +260,7 @@ trait BasicBlocks { } } - /** Replaces <code>oldInstr</code> with <code>is</code>. It does not update + /** Replaces `oldInstr` with `is`. It does not update * the position field in the newly inserted instructions, so it behaves * differently than the one-instruction versions of this function. * @@ -280,17 +280,7 @@ trait BasicBlocks { } } - /** Insert instructions in 'is' immediately after index 'idx'. */ - def insertAfter(idx: Int, is: List[Instruction]) { - assert(closed, "Instructions can be replaced only after the basic block is closed") - - instrs = instrs.patch(idx + 1, is, 0) - code.touched = true - } - /** Removes instructions found at the given positions. - * - * @param positions ... */ def removeInstructionsAt(positions: Int*) { assert(closed, this) @@ -311,8 +301,6 @@ trait BasicBlocks { } /** Replaces all instructions found in the map. - * - * @param map ... */ def subst(map: Map[Instruction, Instruction]): Unit = if (!closed) @@ -339,10 +327,6 @@ trait BasicBlocks { * is closed, which sets the DIRTYSUCCS flag. */ def emit(instr: Instruction, pos: Position) { -/* if (closed) { - print() - Console.println("trying to emit: " + instr) - } */ assert(!closed || ignore, this) if (ignore) { @@ -436,11 +420,6 @@ trait BasicBlocks { ignore = true } - def exitIgnoreMode() { - assert(ignore, "Exit ignore mode when not in ignore mode: " + this) - ignore = false - } - /** Return the last instruction of this basic block. */ def lastInstruction = if (closed) instrs(instrs.length - 1) @@ -497,17 +476,6 @@ trait BasicBlocks { override def hashCode = label * 41 + code.hashCode - // Instead of it, rather use a printer - def print() { print(java.lang.System.out) } - - def print(out: java.io.PrintStream) { - out.println("block #"+label+" :") - foreach(i => out.println(" " + i)) - out.print("Successors: ") - successors.foreach((x: BasicBlock) => out.print(" "+x.label.toString())) - out.println() - } - private def succString = if (successors.isEmpty) "[S: N/A]" else successors.distinct.mkString("[S: ", ", ", "]") private def predString = if (predecessors.isEmpty) "[P: N/A]" else predecessors.distinct.mkString("[P: ", ", ", "]") diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala index 2cebf7ad99..7c2961778f 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala @@ -7,7 +7,7 @@ package scala.tools.nsc package backend package icode -import scala.collection.{ mutable, immutable } +import scala.collection.immutable /** * Exception handlers are pieces of code that `handle` exceptions on @@ -71,10 +71,4 @@ trait ExceptionHandlers { override def toString() = "finalizer_" + label override def dup: Finalizer = new Finalizer(method, label, pos) } - - object NoFinalizer extends Finalizer(null, newTermNameCached("<no finalizer>"), NoPosition) { - override def startBlock: BasicBlock = sys.error("NoFinalizer cannot have a start block."); - override def setStartBlock(b: BasicBlock): Unit = sys.error("NoFinalizer cannot have a start block."); - override def dup = this - } } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index ea4e8475f9..f07c331fb0 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -13,10 +13,8 @@ import scala.collection.mutable.{ ListBuffer, Buffer } import scala.tools.nsc.symtab._ import scala.annotation.switch import PartialFunction._ -import scala.language.postfixOps -/** This class ... - * +/** * @author Iulian Dragos * @version 1.0 */ @@ -160,8 +158,6 @@ abstract class GenICode extends SubComponent { * and not produce any value. Use genLoad for expressions which leave * a value on top of the stack. * - * @param tree ... - * @param ctx ... * @return a new context. This is necessary for control flow instructions * which may change the current basic block. */ @@ -264,11 +260,6 @@ abstract class GenICode extends SubComponent { } /** Generate primitive array operations. - * - * @param tree ... - * @param ctx ... - * @param code ... - * @return ... */ private def genArrayOp(tree: Tree, ctx: Context, code: Int, expectedType: TypeKind): (Context, TypeKind) = { import scalaPrimitives._ @@ -432,7 +423,7 @@ abstract class GenICode extends SubComponent { private def genPrimitiveOp(tree: Apply, ctx: Context, expectedType: TypeKind): (Context, TypeKind) = { val sym = tree.symbol - val Apply(fun @ Select(receiver, _), args) = tree + val Apply(fun @ Select(receiver, _), _) = tree val code = scalaPrimitives.getPrimitive(sym, receiver.tpe) if (scalaPrimitives.isArithmeticOp(code)) @@ -543,9 +534,8 @@ abstract class GenICode extends SubComponent { // emits CIL_LOAD_ARRAY_ITEM_ADDRESS case Apply(fun, args) => if (isPrimitive(fun.symbol)) { - val sym = tree.symbol - val Apply(fun @ Select(receiver, _), args) = tree + val Select(receiver, _) = fun val code = scalaPrimitives.getPrimitive(sym, receiver.tpe) if (isArrayOp(code)) { @@ -858,7 +848,7 @@ abstract class GenICode extends SubComponent { // we store this boxed value to a local, even if not really needed. // boxing optimization might use it, and dead code elimination will // take care of unnecessary stores - var loc1 = ctx.makeLocal(tree.pos, expr.tpe, "boxed") + val loc1 = ctx.makeLocal(tree.pos, expr.tpe, "boxed") ctx1.bb.emit(STORE_LOCAL(loc1)) ctx1.bb.emit(LOAD_LOCAL(loc1)) } @@ -1104,7 +1094,7 @@ abstract class GenICode extends SubComponent { case Match(selector, cases) => def genLoadMatch = { debuglog("Generating SWITCH statement."); - var ctx1 = genLoad(selector, ctx, INT) // TODO: Java 7 allows strings in switches (so, don't assume INT and don't convert the literals using intValue) + val ctx1 = genLoad(selector, ctx, INT) // TODO: Java 7 allows strings in switches (so, don't assume INT and don't convert the literals using intValue) val afterCtx = ctx1.newBlock var caseCtx: Context = null generatedType = toTypeKind(tree.tpe) @@ -1163,34 +1153,30 @@ abstract class GenICode extends SubComponent { resCtx } - private def adapt(from: TypeKind, to: TypeKind, ctx: Context, pos: Position): Unit = { - if (!(from <:< to) && !(from == NullReference && to == NothingReference)) { - to match { - case UNIT => - ctx.bb.emit(DROP(from), pos) - debuglog("Dropped an " + from); - - case _ => - debugassert(from != UNIT, "Can't convert from UNIT to " + to + " at: " + pos) - assert(!from.isReferenceType && !to.isReferenceType, - "type error: can't convert from " + from + " to " + to +" in unit " + unit.source + " at " + pos) - - ctx.bb.emit(CALL_PRIMITIVE(Conversion(from, to)), pos) - } - } else if (from == NothingReference) { - ctx.bb.emit(THROW(ThrowableClass)) - ctx.bb.enterIgnoreMode - } else if (from == NullReference) { - ctx.bb.emit(DROP(from)) - ctx.bb.emit(CONSTANT(Constant(null))) + private def adapt(from: TypeKind, to: TypeKind, ctx: Context, pos: Position) { + // An awful lot of bugs explode here - let's leave ourselves more clues. + // A typical example is an overloaded type assigned after typer. + log(s"GenICode#adapt($from, $to, $ctx, $pos)") + + val conforms = (from <:< to) || (from == NullReference && to == NothingReference) + def coerce(from: TypeKind, to: TypeKind) = ctx.bb.emit(CALL_PRIMITIVE(Conversion(from, to)), pos) + def checkAssertions() { + def msg = s"Can't convert from $from to $to in unit ${unit.source} at $pos" + debugassert(from != UNIT, msg) + assert(!from.isReferenceType && !to.isReferenceType, msg) } - else if (from == ThrowableReference && !(ThrowableClass.tpe <:< to.toType)) { - log("Inserted check-cast on throwable to " + to + " at " + pos) - ctx.bb.emit(CHECK_CAST(to)) + if (conforms) from match { + case NothingReference => ctx.bb.emit(THROW(ThrowableClass)) ; ctx.bb.enterIgnoreMode + case NullReference => ctx.bb.emit(Seq(DROP(from), CONSTANT(Constant(null)))) + case ThrowableReference if !(ThrowableClass.tpe <:< to.toType) => ctx.bb.emit(CHECK_CAST(to)) // downcast throwables + case _ => + // widen subrange types + if (from.isIntSizedType && to == LONG) + coerce(INT, LONG) } - else (from, to) match { - case (BYTE, LONG) | (SHORT, LONG) | (CHAR, LONG) | (INT, LONG) => ctx.bb.emit(CALL_PRIMITIVE(Conversion(INT, LONG))) - case _ => () + else to match { + case UNIT => ctx.bb.emit(DROP(from), pos) // value discarding + case _ => checkAssertions() ; coerce(from, to) // other primitive coercions } } @@ -1257,8 +1243,11 @@ abstract class GenICode extends SubComponent { val sym = ( if (!tree.symbol.isPackageClass) tree.symbol else tree.symbol.info.member(nme.PACKAGE) match { - case NoSymbol => assert(false, "Cannot use package as value: " + tree) ; NoSymbol - case s => debugwarn("Bug: found package class where package object expected. Converting.") ; s.moduleClass + case NoSymbol => + abort("Cannot use package as value: " + tree) + case s => + devWarning(s"Found ${tree.symbol} where a package object is required. Converting to ${s.moduleClass}") + s.moduleClass } ) debuglog("LOAD_MODULE from %s: %s".format(tree.shortClass, sym)) @@ -1392,10 +1381,6 @@ abstract class GenICode extends SubComponent { // } /** Generate string concatenation. - * - * @param tree ... - * @param ctx ... - * @return ... */ def genStringConcat(tree: Tree, ctx: Context): Context = { liftStringConcat(tree) match { @@ -1709,8 +1694,6 @@ abstract class GenICode extends SubComponent { * If the block consists of a single unconditional jump, prune * it by replacing the instructions in the predecessor to jump * directly to the JUMP target of the block. - * - * @param method ... */ def prune(method: IMethod) = { var changed = false @@ -1906,18 +1889,8 @@ abstract class GenICode extends SubComponent { var handlerCount = 0 - override def toString(): String = { - val buf = new StringBuilder() - buf.append("\tpackage: ").append(packg).append('\n') - buf.append("\tclazz: ").append(clazz).append('\n') - buf.append("\tmethod: ").append(method).append('\n') - buf.append("\tbb: ").append(bb).append('\n') - buf.append("\tlabels: ").append(labels).append('\n') - buf.append("\texception handlers: ").append(handlers).append('\n') - buf.append("\tcleanups: ").append(cleanups).append('\n') - buf.append("\tscope: ").append(scope).append('\n') - buf.toString() - } + override def toString = + s"package $packg { class $clazz { def $method { bb=$bb } } }" def loadException(ctx: Context, exh: ExceptionHandler, pos: Position) = { debuglog("Emitting LOAD_EXCEPTION for class: " + exh.loadExceptionClass) @@ -1976,18 +1949,7 @@ abstract class GenICode extends SubComponent { this } - def removeFinalizer(f: Tree): this.type = { - assert(cleanups.head contains f, - "Illegal nesting of cleanup operations: " + cleanups + " while exiting finalizer " + f); - cleanups = cleanups.tail - this - } - /** Prepare a new context upon entry into a method. - * - * @param m ... - * @param d ... - * @return ... */ def enterMethod(m: IMethod, d: DefDef): Context = { val ctx1 = new Context(this) setMethod(m) @@ -2059,16 +2021,6 @@ abstract class GenICode extends SubComponent { currentExceptionHandlers = currentExceptionHandlers.tail } - /** Remove the given handler from the list of active exception handlers. */ - def removeActiveHandler(exh: ExceptionHandler): Unit = { - assert(handlerCount > 0 && handlers.head == exh, - "Wrong nesting of exception handlers." + this + " for " + exh) - handlerCount -= 1 - handlers = handlers.tail - debuglog("removed handler: " + exh); - - } - /** Clone the current context */ def dup: Context = new Context(this) @@ -2087,14 +2039,14 @@ abstract class GenICode extends SubComponent { * It returns the resulting context, with the same active handlers as * before the call. Use it like: * - * <code> ctx.Try( ctx => { + * ` ctx.Try( ctx => { * ctx.bb.emit(...) // protected block * }, (ThrowableClass, * ctx => { * ctx.bb.emit(...); // exception handler * }), (AnotherExceptionClass, * ctx => {... - * } ))</code> + * } ))` */ def Try(body: Context => Context, handlers: List[(Symbol, TypeKind, Context => Context)], @@ -2130,7 +2082,7 @@ abstract class GenICode extends SubComponent { } else ctx - val finalizerExh = if (finalizer != EmptyTree) Some({ + if (finalizer != EmptyTree) { val exh = outerCtx.newExceptionHandler(NoSymbol, toTypeKind(finalizer.tpe), finalizer.pos) // finalizer covers exception handlers this.addActiveHandler(exh) // .. and body aswell val ctx = finalizerCtx.enterExceptionHandler(exh) @@ -2143,21 +2095,20 @@ abstract class GenICode extends SubComponent { ctx1.bb.enterIgnoreMode; ctx1.bb.close finalizerCtx.endHandler() - exh - }) else None - - val exhs = handlers.map { case (sym, kind, handler) => // def genWildcardHandler(sym: Symbol): (Symbol, TypeKind, Context => Context) = - val exh = this.newExceptionHandler(sym, kind, tree.pos) - var ctx1 = outerCtx.enterExceptionHandler(exh) - ctx1.addFinalizer(finalizer, finalizerCtx) - loadException(ctx1, exh, tree.pos) - ctx1 = handler(ctx1) - // emit finalizer - val ctx2 = emitFinalizer(ctx1) - ctx2.bb.closeWith(JUMP(afterCtx.bb)) - outerCtx.endHandler() - exh - } + } + + for ((sym, kind, handler) <- handlers) { + val exh = this.newExceptionHandler(sym, kind, tree.pos) + var ctx1 = outerCtx.enterExceptionHandler(exh) + ctx1.addFinalizer(finalizer, finalizerCtx) + loadException(ctx1, exh, tree.pos) + ctx1 = handler(ctx1) + // emit finalizer + val ctx2 = emitFinalizer(ctx1) + ctx2.bb.closeWith(JUMP(afterCtx.bb)) + outerCtx.endHandler() + } + val bodyCtx = this.newBlock if (finalizer != EmptyTree) bodyCtx.addFinalizer(finalizer, finalizerCtx) @@ -2356,7 +2307,6 @@ abstract class GenICode extends SubComponent { val locals: ListBuffer[Local] = new ListBuffer def add(l: Local) = locals += l - def remove(l: Local) = locals -= l /** Return all locals that are in scope. */ def varsInScope: Buffer[Local] = outer.varsInScope.clone() ++= locals diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala index f05def3123..95913c7768 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala @@ -9,7 +9,6 @@ package icode import scala.collection.mutable import scala.collection.mutable.ListBuffer -import scala.tools.nsc.symtab._ abstract class ICodeCheckers { val global: Global @@ -49,7 +48,7 @@ abstract class ICodeCheckers { * @author Iulian Dragos * @version 1.0, 06/09/2005 * - * @todo Better checks for <code>MONITOR_ENTER/EXIT</code> + * @todo Better checks for `MONITOR_ENTER/EXIT` * Better checks for local var initializations * * @todo Iulian says: I think there's some outdated logic in the checker. @@ -103,7 +102,6 @@ abstract class ICodeCheckers { private def posStr(p: Position) = if (p.isDefined) p.line.toString else "<??>" - private def indent(s: String, spaces: Int): String = indent(s, " " * spaces) private def indent(s: String, prefix: String): String = { val lines = s split "\\n" lines map (prefix + _) mkString "\n" @@ -170,7 +168,6 @@ abstract class ICodeCheckers { val preds = bl.predecessors def hasNothingType(s: TypeStack) = s.nonEmpty && (s.head == NothingReference) - def hasNullType(s: TypeStack) = s.nonEmpty && (s.head == NullReference) /** XXX workaround #1: one stack empty, the other has BoxedUnit. * One example where this arises is: @@ -296,7 +293,7 @@ abstract class ICodeCheckers { else prefix + " with initial stack " + initial.types.mkString("[", ", ", "]") }) - var stack = new TypeStack(initial) + val stack = new TypeStack(initial) def checkStack(len: Int) { if (stack.length < len) ICodeChecker.this.icodeError("Expected at least " + len + " elements on the stack", stack) @@ -369,11 +366,6 @@ abstract class ICodeCheckers { } } - /** Return true if k1 is a subtype of any of the following types, - * according to the somewhat relaxed subtyping standards in effect here. - */ - def isOneOf(k1: TypeKind, kinds: TypeKind*) = kinds exists (k => isSubtype(k1, k)) - def subtypeTest(k1: TypeKind, k2: TypeKind): Unit = if (isSubtype(k1, k2)) () else typeError(k2, k1) @@ -381,10 +373,9 @@ abstract class ICodeCheckers { for (instr <- b) { this.instruction = instr - def checkLocal(local: Local): Unit = { - method lookupLocal local.sym.name getOrElse { - icodeError(" " + local + " is not defined in method " + method) - } + def checkLocal(local: Local) { + if ((method lookupLocal local.sym.name).isEmpty) + icodeError(s" $local is not defined in method $method") } def checkField(obj: TypeKind, field: Symbol): Unit = obj match { case REFERENCE(sym) => @@ -422,10 +413,7 @@ abstract class ICodeCheckers { } /** Checks that the object passed as receiver has a method - * <code>method</code> and that it is callable from the current method. - * - * @param receiver ... - * @param method ... + * `method` and that it is callable from the current method. */ def checkMethod(receiver: TypeKind, method: Symbol) = receiver match { @@ -495,7 +483,7 @@ abstract class ICodeCheckers { case LOAD_MODULE(module) => checkBool((module.isModule || module.isModuleClass), - "Expected module: " + module + " flags: " + Flags.flagsToString(module.flags)); + "Expected module: " + module + " flags: " + module.flagString); pushStack(toTypeKind(module.tpe)); case STORE_THIS(kind) => diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 93201089e4..e2d387c65d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -8,8 +8,6 @@ package backend package icode import java.io.PrintWriter -import scala.collection.mutable -import scala.tools.nsc.symtab._ import analysis.{ Liveness, ReachingDefinitions } import scala.tools.nsc.symtab.classfile.ICodeReader @@ -30,14 +28,14 @@ abstract class ICodes extends AnyRef with Repository { val global: Global - import global.{ log, definitions, settings, perRunCaches } + import global.{ log, definitions, settings, perRunCaches, devWarning } /** The ICode representation of classes */ val classes = perRunCaches.newMap[global.Symbol, IClass]() /** Debugging flag */ def shouldCheckIcode = settings.check contains global.genicode.phaseName - def checkerDebug(msg: String) = if (shouldCheckIcode && global.opt.debug) println(msg) + def checkerDebug(msg: String) = if (shouldCheckIcode && global.settings.debug.value) println(msg) /** The ICode linearizer. */ val linearizer: Linearizer = settings.Xlinearizer.value match { @@ -84,7 +82,7 @@ abstract class ICodes extends AnyRef // Something is leaving open/empty blocks around (see SI-4840) so // let's not kill the deal unless it's nonempty. if (b.isEmpty) { - log("!!! Found open but empty block while inlining " + m + ": removing from block list.") + devWarning(s"Found open but empty block while inlining $m: removing from block list.") m.code removeBlock b } else dumpMethodAndAbort(m, b) diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala index a38eab4515..b8a98955c9 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package backend package icode -import scala.tools.nsc.ast._ import scala.collection.{ mutable, immutable } import mutable.ListBuffer diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 7ba212f42e..12daa32186 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -7,10 +7,8 @@ package scala.tools.nsc package backend package icode -import java.io.PrintWriter import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.{ SourceFile, NoSourceFile } -import symtab.Flags.{ DEFERRED } trait ReferenceEquality { override def hashCode = System.identityHashCode(this) @@ -128,9 +126,7 @@ trait Members { override def toString() = symbol.fullName - def lookupField(s: Symbol) = fields find (_.symbol == s) def lookupMethod(s: Symbol) = methods find (_.symbol == s) - def lookupMethod(s: Name) = methods find (_.symbol.name == s) /* returns this methods static ctor if it has one. */ def lookupStaticCtor: Option[IMethod] = methods find (_.symbol.isStaticConstructor) @@ -161,7 +157,6 @@ trait Members { def linearizedBlocks(lin: Linearizer = self.linearizer): List[BasicBlock] = lin linearize this def foreachBlock[U](f: BasicBlock => U): Unit = blocks foreach f - def foreachInstr[U](f: Instruction => U): Unit = foreachBlock(_.toList foreach f) var native = false @@ -194,7 +189,6 @@ trait Members { } def addLocals(ls: List[Local]) = ls foreach addLocal - def addParams(as: List[Local]) = as foreach addParam def lookupLocal(n: Name): Option[Local] = locals find (_.sym.name == n) def lookupLocal(sym: Symbol): Option[Local] = locals find (_.sym == sym) @@ -209,28 +203,7 @@ trait Members { override def toString() = symbol.fullName - def matchesSignature(other: IMethod) = { - (symbol.name == other.symbol.name) && - (params corresponds other.params)(_.kind == _.kind) && - (returnType == other.returnType) - } - import opcodes._ - def checkLocals(): Unit = { - def localsSet = (code.blocks flatMap { bb => - bb.iterator collect { - case LOAD_LOCAL(l) => l - case STORE_LOCAL(l) => l - } - }).toSet - - if (hasCode) { - log("[checking locals of " + this + "]") - locals filterNot localsSet foreach { l => - log("Local " + l + " is not declared in " + this) - } - } - } /** Merge together blocks that have a single successor which has a * single predecessor. Exception handlers are taken into account (they @@ -296,9 +269,6 @@ trait Members { /** Starting PC for this local's visibility range. */ var start: Int = _ - /** Ending PC for this local's visibility range. */ - var end: Int = _ - /** PC-based ranges for this local variable's visibility */ var ranges: List[(Int, Int)] = Nil diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 8c9a72638d..eaa742a1da 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -3,13 +3,10 @@ * @author Martin Odersky */ - - package scala.tools.nsc package backend package icode -import scala.tools.nsc.ast._ import scala.reflect.internal.util.{Position,NoPosition} /* @@ -67,7 +64,7 @@ import scala.reflect.internal.util.{Position,NoPosition} * in the source files. */ trait Opcodes { self: ICodes => - import global.{Symbol, NoSymbol, Type, Name, Constant}; + import global.{Symbol, NoSymbol, Name, Constant}; // categories of ICode instructions final val localsCat = 1 @@ -111,17 +108,11 @@ trait Opcodes { self: ICodes => // Vlad: I wonder why we keep producedTypes around -- it looks like an useless thing to have def producedTypes: List[TypeKind] = Nil - /** This method returns the difference of size of the stack when the instruction is used */ - def difference = produced-consumed - /** The corresponding position in the source file */ private var _pos: Position = NoPosition def pos: Position = _pos - /** Used by dead code elimination. */ - var useful: Boolean = false - def setPos(p: Position): this.type = { _pos = p this @@ -133,13 +124,6 @@ trait Opcodes { self: ICodes => } object opcodes { - - def mayThrow(i: Instruction): Boolean = i match { - case LOAD_LOCAL(_) | STORE_LOCAL(_) | CONSTANT(_) | THIS(_) | CZJUMP(_, _, _, _) - | DROP(_) | DUP(_) | RETURN(_) | LOAD_EXCEPTION(_) | JUMP(_) | CJUMP(_, _, _, _) => false - case _ => true - } - /** Loads "this" on top of the stack. * Stack: ... * ->: ...:ref @@ -715,8 +699,6 @@ trait Opcodes { self: ICodes => /** Is this a static method call? */ def isStatic: Boolean = false - def isSuper: Boolean = false - /** Is this an instance method call? */ def hasInstance: Boolean = true @@ -750,7 +732,6 @@ trait Opcodes { self: ICodes => * On JVM, translated to `invokespecial`. */ case class SuperCall(mix: Name) extends InvokeStyle { - override def isSuper = true override def toString(): String = { "super(" + mix + ")" } } @@ -815,7 +796,7 @@ trait Opcodes { self: ICodes => case class CIL_NEWOBJ(method: Symbol) extends Instruction { override def toString(): String = "CIL_NEWOBJ " + hostClass.fullName + method.fullName - var hostClass: Symbol = method.owner; + val hostClass: Symbol = method.owner; override def consumed = method.tpe.paramTypes.length override def consumedTypes = method.tpe.paramTypes map toTypeKind override def produced = 1 diff --git a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala index c8579041ba..351d99f51a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala @@ -76,25 +76,12 @@ trait Primitives { self: ICodes => /** Pretty printer for primitives */ class PrimitivePrinter(out: PrintWriter) { - def print(s: String): PrimitivePrinter = { out.print(s) this } def print(o: AnyRef): PrimitivePrinter = print(o.toString()) - - def printPrimitive(prim: Primitive) = prim match { - case Negation(kind) => - print("!") - - case Test(op, kind, zero) => - print(op).print(kind) - - case Comparison(op, kind) => - print(op).print("(").print(kind) - - } } /** This class represents a comparison operation. */ diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala index 6cac641e3e..61af6e5119 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala @@ -8,13 +8,9 @@ package backend package icode import java.io.PrintWriter -import scala.tools.nsc.symtab.Flags -import scala.reflect.internal.util.Position trait Printers { self: ICodes => import global._ - import global.icodes.opcodes._ - import global.icodes._ class TextPrinter(writer: PrintWriter, lin: Linearizer) { private var margin = 0 diff --git a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala index e73015c4da..e92e61c957 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Repository.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Repository.scala @@ -26,17 +26,6 @@ trait Repository { /** The icode of the given class, if available */ def icode(sym: Symbol): Option[IClass] = (classes get sym) orElse (loaded get sym) - /** The icode of the given class. If not available, it loads - * its bytecode. - */ - def icode(sym: Symbol, force: Boolean): IClass = - icode(sym) getOrElse { - log("loading " + sym) - load(sym) - assert(available(sym)) - loaded(sym) - } - /** Load bytecode for given symbol. */ def load(sym: Symbol): Boolean = { try { diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index 4f8fda8024..0990cfba6f 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -55,7 +55,7 @@ trait TypeKinds { self: ICodes => def toType: Type = reversePrimitiveMap get this map (_.tpe) getOrElse { this match { - case REFERENCE(cls) => cls.tpe + case REFERENCE(cls) => cls.tpe_* case ARRAY(elem) => arrayType(elem.toType) case _ => abort("Unknown type kind.") } @@ -66,7 +66,6 @@ trait TypeKinds { self: ICodes => def isValueType = false def isBoxedType = false final def isRefOrArrayType = isReferenceType || isArrayType - final def isRefArrayOrBoxType = isRefOrArrayType || isBoxedType final def isNothingType = this == NothingReference final def isNullType = this == NullReference final def isInterfaceType = this match { @@ -114,8 +113,6 @@ trait TypeKinds { self: ICodes => } } - var lubs0 = 0 - /** * The least upper bound of two typekinds. They have to be either * REFERENCE or ARRAY kinds. @@ -139,8 +136,7 @@ trait TypeKinds { self: ICodes => * Here we make the adjustment by rewinding to a pre-erasure state and * sifting through the parents for a class type. */ - def lub0(tk1: TypeKind, tk2: TypeKind): Type = beforeUncurry { - import definitions._ + def lub0(tk1: TypeKind, tk2: TypeKind): Type = enteringUncurry { val tp = global.lub(List(tk1.toType, tk2.toType)) val (front, rest) = tp.parents span (_.typeSymbol.isTrait) diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala index 23d3d05c64..57d51dad49 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeStacks.scala @@ -15,15 +15,11 @@ package icode trait TypeStacks { self: ICodes => - import opcodes._ - /* This class simulates the type of the operand * stack of the ICode. */ type Rep = List[TypeKind] - object NoTypeStack extends TypeStack(Nil) { } - class TypeStack(var types: Rep) { if (types.nonEmpty) checkerDebug("Created " + this) @@ -71,14 +67,6 @@ trait TypeStacks { def apply(n: Int): TypeKind = types(n) - /** - * A TypeStack agrees with another one if they have the same - * length and each type kind agrees position-wise. Two - * types agree if one is a subtype of the other. - */ - def agreesWith(other: TypeStack): Boolean = - (types corresponds other.types)((t1, t2) => t1 <:< t2 || t2 <:< t1) - /* This method returns a String representation of the stack */ override def toString() = if (types.isEmpty) "[]" diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index 53111d0ade..7f32b2b764 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -26,12 +26,8 @@ abstract class CopyPropagation { case object This extends Location /** Values that can be on the stack. */ - abstract class Value { - def isRecord = false - } - case class Record(cls: Symbol, bindings: mutable.Map[Symbol, Value]) extends Value { - override def isRecord = true - } + abstract class Value { } + case class Record(cls: Symbol, bindings: mutable.Map[Symbol, Value]) extends Value { } /** The value of some location in memory. */ case class Deref(l: Location) extends Value @@ -91,16 +87,6 @@ abstract class CopyPropagation { loop(l) getOrElse Deref(LocalVar(l)) } - /* Return the binding for the given field of the given record */ - def getBinding(r: Record, f: Symbol): Value = { - assert(r.bindings contains f, "Record " + r + " does not contain a field " + f) - - r.bindings(f) match { - case Deref(LocalVar(l)) => getBinding(l) - case target => target - } - } - /** Return a local which contains the same value as this field, if any. * If the field holds a reference to a local, the returned value is the * binding of that local. @@ -463,14 +449,9 @@ abstract class CopyPropagation { } } - /** Update the state <code>s</code> after the call to <code>method</code>. + /** Update the state `s` after the call to `method`. * The stack elements are dropped and replaced by the result of the call. * If the method is impure, all bindings to record fields are cleared. - * - * @param state ... - * @param method ... - * @param static ... - * @return ... */ final def simulateCall(state: copyLattice.State, method: Symbol, static: Boolean): copyLattice.State = { val out = new copyLattice.State(state.bindings, state.stack); @@ -554,10 +535,7 @@ abstract class CopyPropagation { bindings } - /** Is symbol <code>m</code> a pure method? - * - * @param m ... - * @return ... + /** Is symbol `m` a pure method? */ final def isPureMethod(m: Symbol): Boolean = m.isGetter // abstract getters are still pure, as we 'know' diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala index 04c3eedbad..cc3a7eb876 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/DataFlowAnalysis.scala @@ -34,15 +34,6 @@ trait DataFlowAnalysis[L <: SemiLattice] { f } - /** Reinitialize, but keep the old solutions. Should be used when reanalyzing the - * same method, after some code transformation. - */ - def reinit(f: => Unit): Unit = { - iterations = 0 - worklist.clear; visited.clear; - f - } - def run(): Unit /** Implements forward dataflow analysis: the transfer function is @@ -82,10 +73,6 @@ trait DataFlowAnalysis[L <: SemiLattice] { sys.error("Could not find element " + e.getMessage) } - /** ... - * - * @param f ... - */ def backwardAnalysis(f: (P, lattice.Elem) => lattice.Elem): Unit = while (worklist.nonEmpty) { if (stat) iterations += 1 diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala index 2717c432e8..48755d4424 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala @@ -52,7 +52,7 @@ abstract class ReachingDefinitions { // it makes it harder to spot the real problems. val result = (a.stack, b.stack).zipped map (_ ++ _) if (settings.debug.value && (a.stack.length != b.stack.length)) - debugwarn("Mismatched stacks in ReachingDefinitions#lub2: " + a.stack + ", " + b.stack + ", returning " + result) + devWarning(s"Mismatched stacks in ReachingDefinitions#lub2: ${a.stack}, ${b.stack}, returning $result") result } ) @@ -155,7 +155,7 @@ abstract class ReachingDefinitions { import lattice.IState def updateReachingDefinition(b: BasicBlock, idx: Int, rd: ListSet[Definition]): ListSet[Definition] = { val STORE_LOCAL(local) = b(idx) - var tmp = local + val tmp = local (rd filter { case (l, _, _) => l != tmp }) + ((tmp, b, idx)) } @@ -197,7 +197,7 @@ abstract class ReachingDefinitions { def findDefs(bb: BasicBlock, idx: Int, m: Int, depth: Int): List[(BasicBlock, Int)] = if (idx > 0) { assert(bb.closed, bb) - var instrs = bb.getArray + val instrs = bb.getArray var res: List[(BasicBlock, Int)] = Nil var i = idx var n = m 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 b2ecb431ee..c9d295a350 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala @@ -68,7 +68,6 @@ abstract class TypeFlowAnalysis { * names to types and a type stack. */ object typeFlowLattice extends SemiLattice { - import icodes._ type Elem = IState[VarBinding, icodes.TypeStack] val top = new Elem(new VarBinding, typeStackLattice.top) @@ -136,7 +135,7 @@ abstract class TypeFlowAnalysis { timer.start // icodes.lubs0 = 0 forwardAnalysis(blockTransfer) - val t = timer.stop + timer.stop if (settings.debug.value) { linearizer.linearize(method).foreach(b => if (b != method.startBlock) assert(visited.contains(b), @@ -269,36 +268,6 @@ abstract class TypeFlowAnalysis { out } // interpret - - class SimulatedStack { - private var types: List[InferredType] = Nil - private var depth = 0 - - /** Remove and return the topmost element on the stack. If the - * stack is empty, return a reference to a negative index on the - * stack, meaning it refers to elements pushed by a predecessor block. - */ - def pop: InferredType = types match { - case head :: rest => - types = rest - head - case _ => - depth -= 1 - TypeOfStackPos(depth) - } - - def pop2: (InferredType, InferredType) = { - (pop, pop) - } - - def push(t: InferredType) { - depth += 1 - types = types ::: List(t) - } - - def push(k: TypeKind) { push(Const(k)) } - } - abstract class InferredType { /** Return the type kind pointed by this inferred type. */ def getKind(in: lattice.Elem): icodes.TypeKind = this match { @@ -326,7 +295,6 @@ abstract class TypeFlowAnalysis { class TransferFunction(consumed: Int, gens: List[Gen]) extends (lattice.Elem => lattice.Elem) { def apply(in: lattice.Elem): lattice.Elem = { val out = lattice.IState(new VarBinding(in.vars), new TypeStack(in.stack)) - val bindings = out.vars val stack = out.stack out.stack.pop(consumed) @@ -389,7 +357,7 @@ abstract class TypeFlowAnalysis { timer.start forwardAnalysis(blockTransfer) - val t = timer.stop + timer.stop /* Now that `forwardAnalysis(blockTransfer)` has finished, all inlining candidates can be found in `remainingCALLs`, whose keys are callsites and whose values are pieces of information about the typestack just before the callsite in question. @@ -546,9 +514,6 @@ abstract class TypeFlowAnalysis { relevantBBs ++= blocks } - /* the argument is also included in the result */ - private def transitivePreds(b: BasicBlock): Set[BasicBlock] = { transitivePreds(List(b)) } - /* those BBs in the argument are also included in the result */ private def transitivePreds(starters: Traversable[BasicBlock]): Set[BasicBlock] = { val result = mutable.Set.empty[BasicBlock] @@ -562,19 +527,6 @@ abstract class TypeFlowAnalysis { result.toSet } - /* those BBs in the argument are also included in the result */ - private def transitiveSuccs(starters: Traversable[BasicBlock]): Set[BasicBlock] = { - val result = mutable.Set.empty[BasicBlock] - var toVisit: List[BasicBlock] = starters.toList.distinct - while(toVisit.nonEmpty) { - val h = toVisit.head - toVisit = toVisit.tail - result += h - for(p <- h.successors; if !result(p) && !toVisit.contains(p)) { toVisit = p :: toVisit } - } - result.toSet - } - /* A basic block B is "on the perimeter" of the current control-flow subgraph if none of its successors belongs to that subgraph. * In that case, for the purposes of inlining, we're interested in the typestack right before the last inline candidate in B, not in those afterwards. * In particular we can do without computing the outflow at B. */ @@ -685,12 +637,6 @@ abstract class TypeFlowAnalysis { if(!worklist.contains(b)) { worklist += b } } - /* this is not a general purpose method to add to the worklist, - * because the assert is expected to hold only when called from MTFAGrowable.reinit() */ - private def enqueue(bs: Traversable[BasicBlock]) { - bs foreach enqueue - } - private def blankOut(blocks: scala.collection.Set[BasicBlock]) { blocks foreach { b => in(b) = typeFlowLattice.bottom @@ -761,10 +707,6 @@ abstract class TypeFlowAnalysis { private var lastStart = 0L - def reset() { - millis = 0L - } - def start() { lastStart = System.currentTimeMillis } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala index fb1f45fa40..8c8950d295 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala @@ -10,8 +10,7 @@ import java.io.{ DataOutputStream, FileOutputStream, OutputStream, File => JFile import scala.tools.nsc.io._ import scala.tools.nsc.util.ScalaClassLoader import scala.tools.util.JavapClass -import java.util.jar.{ JarEntry, JarOutputStream, Attributes } -import Attributes.Name +import java.util.jar.Attributes.Name import scala.language.postfixOps /** For the last mile: turning generated bytecode in memory into @@ -23,7 +22,7 @@ trait BytecodeWriters { import global._ private def outputDirectory(sym: Symbol): AbstractFile = ( - settings.outputDirs.outputDirFor(beforeFlatten(sym.sourceFile)) + settings.outputDirs.outputDirFor(enteringFlatten(sym.sourceFile)) ) private def getFile(base: AbstractFile, /*cls.getName()*/ clsName: String, suffix: String): AbstractFile = { var dir = base @@ -102,7 +101,7 @@ trait BytecodeWriters { super.writeClass(label, jclassName, jclassBytes, sym) val pathName = jclassName - var dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile; + val dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile; dumpFile.parent.createDirectory() val outstream = new DataOutputStream(new FileOutputStream(dumpFile.path)) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 6eb05c4402..1aa80d5c5b 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -6,12 +6,9 @@ package scala.tools.nsc package backend.jvm -import java.nio.ByteBuffer import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer } import scala.tools.nsc.symtab._ -import scala.tools.nsc.io.AbstractFile - import scala.tools.asm import asm.Label @@ -32,19 +29,15 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** Create a new phase */ override def newPhase(p: Phase): Phase = new AsmPhase(p) - private def outputDirectory(sym: Symbol): AbstractFile = - settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) + /** From the reference documentation of the Android SDK: + * The `Parcelable` interface identifies classes whose instances can be written to and restored from a `Parcel`. + * Classes implementing the `Parcelable` interface must also have a static field called `CREATOR`, + * which is an object implementing the `Parcelable.Creator` interface. + */ + private val androidFieldName = newTermName("CREATOR") - private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = { - var dir = base - val pathParts = clsName.split("[./]").toList - for (part <- pathParts.init) { - dir = dir.subdirectoryNamed(part) - } - dir.fileNamed(pathParts.last + suffix) - } - private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile = - getFile(outputDirectory(sym), clsName, suffix) + private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable") + private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator") /** JVM code generation phase */ @@ -53,7 +46,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters { override def erasedTypes = true def apply(cls: IClass) = sys.error("no implementation") - val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") + // Lazy val; can't have eager vals in Phase constructors which may + // cause cycles before Global has finished initialization. + lazy val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") def isJavaEntryPoint(icls: IClass) = { val sym = icls.symbol @@ -81,9 +76,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // At this point it's a module with a main-looking method, so either succeed or warn that it isn't. hasApproximate && { // Before erasure so we can identify generic mains. - beforeErasure { + enteringErasure { val companion = sym.linkedClassOfClass - val companionMain = companion.tpe.member(nme.main) if (hasJavaMainMethod(companion)) failNoForwarder("companion contains its own main method") @@ -311,7 +305,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } def isTopLevelModule(sym: Symbol): Boolean = - afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } + exitingPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } def isStaticModule(sym: Symbol): Boolean = { sym.isModuleClass && !sym.isImplClass && !sym.isLifted @@ -461,7 +455,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** basic functionality for class file building */ abstract class JBuilder(bytecodeWriter: BytecodeWriter) { - val EMPTY_JTYPE_ARRAY = Array.empty[asm.Type] val EMPTY_STRING_ARRAY = Array.empty[String] val mdesc_arglessvoid = "()V" @@ -529,7 +522,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { /** Specialized array conversion to prevent calling * java.lang.reflect.Array.newInstance via TraversableOnce.toArray */ - def mkArray(xs: Traversable[asm.Type]): Array[asm.Type] = { val a = new Array[asm.Type](xs.size); xs.copyToArray(a); a } def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a } // ----------------------------------------------------------------------------------------- @@ -579,7 +571,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { * of inner class all until root class. */ def collectInnerClass(s: Symbol): Unit = { - // TODO: some beforeFlatten { ... } which accounts for + // TODO: some enteringFlatten { ... } which accounts for // being nested in parameterized classes (if we're going to selectively flatten.) val x = innerClassSymbolFor(s) if(x ne NoSymbol) { @@ -594,7 +586,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { collectInnerClass(sym) - var hasInternalName = (sym.isClass || (sym.isModule && !sym.isMethod)) + val hasInternalName = (sym.isClass || (sym.isModule && !sym.isMethod)) val cachedJN = javaNameCache.getOrElseUpdate(sym, { if (hasInternalName) { sym.javaBinaryName } else { sym.javaSimpleName } @@ -604,12 +596,18 @@ abstract class GenASM extends SubComponent with BytecodeWriters { val internalName = cachedJN.toString() val trackedSym = jsymbol(sym) reverseJavaName.get(internalName) match { - case None => + case Some(oldsym) if oldsym.exists && trackedSym.exists => + assert( + // In contrast, neither NothingClass nor NullClass show up bytecode-level. + (oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass) || (oldsym.isModuleClass && (oldsym.sourceModule == trackedSym.sourceModule)), + s"""|Different class symbols have the same bytecode-level internal name: + | name: $internalName + | oldsym: ${oldsym.fullNameString} + | tracked: ${trackedSym.fullNameString} + """.stripMargin + ) + case _ => reverseJavaName.put(internalName, trackedSym) - case Some(oldsym) => - assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass) || - (oldsym.isModuleClass && (oldsym.sourceModule == trackedSym.sourceModule)), // In contrast, neither NothingClass nor NullClass show up bytecode-level. - "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: " + internalName) } } @@ -682,7 +680,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { innerSym.rawname + innerSym.moduleSuffix // add inner classes which might not have been referenced yet - afterErasure { + exitingErasure { for (sym <- List(csym, csym.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass) innerClassBuffer += m } @@ -873,7 +871,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { if (!needsGenericSignature(sym)) { return null } - val memberTpe = beforeErasure(owner.thisType.memberInfo(sym)) + val memberTpe = enteringErasure(owner.thisType.memberInfo(sym)) val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe) if (jsOpt.isEmpty) { return null } @@ -907,7 +905,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } if ((settings.check containsName phaseName)) { - val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe)) + val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { getCurrentCUnit().warning(sym.pos, @@ -1168,7 +1166,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { debuglog("Dumping mirror class for object: " + moduleClass) val linkedClass = moduleClass.companionClass - val linkedModule = linkedClass.companionSymbol lazy val conflictingNames: Set[Name] = { (linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name }).toSet } @@ -1194,16 +1191,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { trait JAndroidBuilder { self: JPlainBuilder => - /** From the reference documentation of the Android SDK: - * The `Parcelable` interface identifies classes whose instances can be written to and restored from a `Parcel`. - * Classes implementing the `Parcelable` interface must also have a static field called `CREATOR`, - * which is an object implementing the `Parcelable.Creator` interface. - */ - private val androidFieldName = newTermName("CREATOR") - - private lazy val AndroidParcelableInterface = rootMirror.getClassIfDefined("android.os.Parcelable") - private lazy val AndroidCreatorClass = rootMirror.getClassIfDefined("android.os.Parcelable$Creator") - def isAndroidParcelableClass(sym: Symbol) = (AndroidParcelableInterface != NoSymbol) && (sym.parentSymbols contains AndroidParcelableInterface) @@ -1336,7 +1323,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { // Additional interface parents based on annotations and other cues def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { - case SerializableAttr => Some(SerializableClass) case CloneableAttr => Some(CloneableClass) case RemoteAttr => Some(RemoteInterfaceClass) case _ => None @@ -1440,7 +1426,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { if (lmoc != NoSymbol) { // it must be a top level class (name contains no $s) val isCandidateForForwarders = { - afterPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass } + exitingPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass } } if (isCandidateForForwarders) { log("Adding static forwarders from '%s' to implementations in '%s'".format(c.symbol, lmoc)) @@ -1769,11 +1755,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { import asm.Opcodes; - def aconst(cst: AnyRef) { - if (cst == null) { jmethod.visitInsn(Opcodes.ACONST_NULL) } - else { jmethod.visitLdcInsn(cst) } - } - final def boolconst(b: Boolean) { iconst(if(b) 1 else 0) } def iconst(cst: Int) { @@ -2219,7 +2200,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { def getMerged(): scala.collection.Map[Local, List[Interval]] = { // TODO should but isn't: unbalanced start(s) of scope(s) - val shouldBeEmpty = pending filter { p => val Pair(k, st) = p; st.nonEmpty }; + val shouldBeEmpty = pending filter { p => val Pair(_, st) = p; st.nonEmpty }; val merged = mutable.Map[Local, List[Interval]]() def addToMerged(lv: Local, start: Label, end: Label) { val intv = Interval(start, end) @@ -2282,7 +2263,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { } // quest for deterministic output that Map.toList doesn't provide (so that ant test.stability doesn't complain). val srtd = fltnd.sortBy { kr => - val Triple(name: String, local: Local, intrvl: Interval) = kr + val Triple(name: String, _, intrvl: Interval) = kr Triple(intrvl.start, intrvl.end - intrvl.start, name) // ie sort by (start, length, name) } @@ -2402,6 +2383,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { import asm.Opcodes (instr.category: @scala.annotation.switch) match { + case icodes.localsCat => def genLocalInstr() = (instr: @unchecked) match { case THIS(_) => jmethod.visitVarInsn(Opcodes.ALOAD, 0) @@ -2440,7 +2422,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case LOAD_MODULE(module) => // assert(module.isModule, "Expected module: " + module) - debuglog("generating LOAD_MODULE for: " + module + " flags: " + Flags.flagsToString(module.flags)); + debuglog("generating LOAD_MODULE for: " + module + " flags: " + module.flagString); if (clasz.symbol == module.moduleClass && jMethodName != nme.readResolve.toString) { jmethod.visitVarInsn(Opcodes.ALOAD, 0) } else { @@ -2495,7 +2477,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { case icodes.objsCat => def genObjsInstr() = (instr: @unchecked) match { - case BOX(kind) => val MethodNameAndType(mname, mdesc) = jBoxTo(kind) jcode.invokestatic(BoxesRunTime, mname, mdesc) @@ -2517,8 +2498,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { def genFldsInstr() = (instr: @unchecked) match { case lf @ LOAD_FIELD(field, isStatic) => - var owner = javaName(lf.hostClass) - debuglog("LOAD_FIELD with owner: " + owner + " flags: " + Flags.flagsToString(field.owner.flags)) + val owner = javaName(lf.hostClass) + debuglog("LOAD_FIELD with owner: " + owner + " flags: " + field.owner.flagString) val fieldJName = javaName(field) val fieldDescr = descriptor(field) val opc = if (isStatic) Opcodes.GETSTATIC else Opcodes.GETFIELD @@ -2936,15 +2917,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { ////////////////////// local vars /////////////////////// - // def sizeOf(sym: Symbol): Int = sizeOf(toTypeKind(sym.tpe)) - def sizeOf(k: TypeKind): Int = if(k.isWideType) 2 else 1 - // def indexOf(m: IMethod, sym: Symbol): Int = { - // val Some(local) = m lookupLocal sym - // indexOf(local) - // } - final def indexOf(local: Local): Int = { assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ") local.index @@ -3350,8 +3324,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { var wasReduced = false val entryPoints: List[BasicBlock] = m.startBlock :: (m.exh map (_.startBlock)); - var elided = mutable.Set.empty[BasicBlock] // debug - var newTargets = mutable.Set.empty[BasicBlock] // debug + val elided = mutable.Set.empty[BasicBlock] // debug + val newTargets = mutable.Set.empty[BasicBlock] // debug for (ep <- entryPoints) { var reachable = directSuccStar(ep) // this list may contain blocks belonging to jump-chains that we'll skip over diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 3d29b2590e..e1484d1f97 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package backend.jvm -import java.io.{ByteArrayOutputStream, DataOutputStream, OutputStream } import java.nio.ByteBuffer import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer } @@ -16,8 +15,6 @@ import scala.reflect.internal.ClassfileConstants._ import ch.epfl.lamp.fjbg._ import JAccessFlags._ import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT } -import java.util.jar.{ JarEntry, JarOutputStream } -import scala.tools.nsc.io.AbstractFile import scala.language.postfixOps /** This class ... @@ -37,20 +34,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with /** Create a new phase */ override def newPhase(p: Phase): Phase = new JvmPhase(p) - private def outputDirectory(sym: Symbol): AbstractFile = - settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) - - private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = { - var dir = base - val pathParts = clsName.split("[./]").toList - for (part <- pathParts.init) { - dir = dir.subdirectoryNamed(part) - } - dir.fileNamed(pathParts.last + suffix) - } - private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile = - getFile(outputDirectory(sym), clsName, suffix) - /** JVM code generation phase */ class JvmPhase(prev: Phase) extends ICodePhase(prev) { @@ -85,9 +68,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // succeed or warn that it isn't. hasApproximate && { // Before erasure so we can identify generic mains. - beforeErasure { + enteringErasure { val companion = sym.linkedClassOfClass - val companionMain = companion.tpe.member(nme.main) if (hasJavaMainMethod(companion)) failNoForwarder("companion contains its own main method") @@ -200,15 +182,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val StringBuilderType = new JObjectType(StringBuilderClassName) // TODO use ASMType.getObjectType val toStringType = new JMethodType(JAVA_LANG_STRING, JType.EMPTY_ARRAY) // TODO use ASMType.getMethodType val arrayCloneType = new JMethodType(JAVA_LANG_OBJECT, JType.EMPTY_ARRAY) - val MethodTypeType = new JObjectType("java.dyn.MethodType") - val JavaLangClassType = new JObjectType("java.lang.Class") - val MethodHandleType = new JObjectType("java.dyn.MethodHandle") // Scala attributes val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo") - val BeanInfoSkipAttr = rootMirror.getRequiredClass("scala.beans.BeanInfoSkip") - val BeanDisplayNameAttr = rootMirror.getRequiredClass("scala.beans.BeanDisplayName") - val BeanDescriptionAttr = rootMirror.getRequiredClass("scala.beans.BeanDescription") final val ExcludedForwarderFlags = { import Flags._ @@ -218,7 +194,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // Additional interface parents based on annotations and other cues def newParentForAttr(attr: Symbol): Option[Symbol] = attr match { - case SerializableAttr => Some(SerializableClass) case CloneableAttr => Some(JavaCloneableClass) case RemoteAttr => Some(RemoteInterfaceClass) case _ => None @@ -273,7 +248,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with var method: IMethod = _ var jclass: JClass = _ var jmethod: JMethod = _ - // var jcode: JExtendedCode = _ def isParcelableClass = isAndroidParcelableClass(clasz.symbol) def isRemoteClass = clasz.symbol hasAnnotation RemoteAttr @@ -282,9 +256,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } val fjbgContext = new FJBGContext(49, 0) - - val emitSource = debugLevel >= 1 - val emitLines = debugLevel >= 2 val emitVars = debugLevel >= 3 // bug had phase with wrong name; leaving enabled for brief pseudo deprecation @@ -318,7 +289,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with * of inner class all until root class. */ def collectInnerClass(s: Symbol): Unit = { - // TODO: some beforeFlatten { ... } which accounts for + // TODO: some enteringFlatten { ... } which accounts for // being nested in parameterized classes (if we're going to selectively flatten.) val x = innerClassSymbolFor(s) if(x ne NoSymbol) { @@ -448,7 +419,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // it must be a top level class (name contains no $s) def isCandidateForForwarders(sym: Symbol): Boolean = - afterPickler { + exitingPickler { !(sym.name.toString contains '$') && sym.hasModuleFlag && !sym.isImplClass && !sym.isNestedClass } @@ -529,9 +500,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with * @author Ross Judson (ross.judson@soletta.com) */ def genBeanInfoClass(c: IClass) { - val description = c.symbol getAnnotation BeanDescriptionAttr - // informProgress(description.toString) - val beanInfoClass = fjbgContext.JClass(javaFlags(c.symbol), javaName(c.symbol) + "BeanInfo", "scala/beans/ScalaBeanInfo", @@ -736,13 +704,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ) def addGenericSignature(jmember: JMember, sym: Symbol, owner: Symbol) { if (needsGenericSignature(sym)) { - val memberTpe = beforeErasure(owner.thisType.memberInfo(sym)) + val memberTpe = enteringErasure(owner.thisType.memberInfo(sym)) erasure.javaSig(sym, memberTpe) foreach { sig => // This seems useful enough in the general case. log(sig) if (checkSignatures) { - val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe)) + val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { clasz.cunit.warning(sym.pos, @@ -757,8 +725,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } val index = jmember.getConstantPool.addUtf8(sig).toShort - if (opt.verboseDebug) - beforeErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)) + if (settings.verbose.value && settings.debug.value) + enteringErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)) val buf = ByteBuffer.allocate(2) buf putShort index @@ -834,7 +802,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with innerSym.rawname + innerSym.moduleSuffix // add inner classes which might not have been referenced yet - afterErasure { + exitingErasure { for (sym <- List(clasz.symbol, clasz.symbol.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass) innerClassBuffer += m } @@ -1078,7 +1046,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with var i = 0 var index = 0 - var argTypes = mirrorMethod.getArgumentTypes() + val argTypes = mirrorMethod.getArgumentTypes() while (i < argTypes.length) { mirrorCode.emitLOAD(index, argTypes(i)) index += argTypes(i).getSize() @@ -1110,7 +1078,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val className = jclass.getName val linkedClass = moduleClass.companionClass - val linkedModule = linkedClass.companionSymbol lazy val conflictingNames: Set[Name] = { linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet } @@ -1176,9 +1143,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with var linearization: List[BasicBlock] = Nil var isModuleInitialized = false - /** - * @param m ... - */ def genCode(m: IMethod) { val jcode = jmethod.getCode.asInstanceOf[JExtendedCode] @@ -1354,9 +1318,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with case LOAD_LOCAL(local) => jcode.emitLOAD(indexOf(local), javaType(local.kind)) case lf @ LOAD_FIELD(field, isStatic) => - var owner = javaName(lf.hostClass) + val owner = javaName(lf.hostClass) debuglog("LOAD_FIELD with owner: " + owner + - " flags: " + Flags.flagsToString(field.owner.flags)) + " flags: " + field.owner.flagString) val fieldJName = javaName(field) val fieldJType = javaType(field) if (isStatic) jcode.emitGETSTATIC(owner, fieldJName, fieldJType) @@ -1364,7 +1328,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with case LOAD_MODULE(module) => // assert(module.isModule, "Expected module: " + module) - debuglog("generating LOAD_MODULE for: " + module + " flags: " + Flags.flagsToString(module.flags)); + debuglog("generating LOAD_MODULE for: " + module + " flags: " + module.flagString); if (clasz.symbol == module.moduleClass && jmethod.getName() != nme.readResolve.toString) jcode.emitALOAD_0() else @@ -1628,11 +1592,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } - - /** - * @param primitive ... - * @param pos ... - */ def genPrimitive(primitive: Primitive, pos: Position) { primitive match { case Negation(kind) => @@ -1812,7 +1771,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with * Synthetic locals are skipped. All variables are method-scoped. */ private def genLocalVariableTable(m: IMethod, jcode: JCode) { - val vars = m.locals filterNot (_.sym.isSynthetic) + val vars = m.locals filterNot (_.sym.isArtifact) if (vars.isEmpty) return val pool = jclass.getConstantPool @@ -1866,15 +1825,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ////////////////////// local vars /////////////////////// - def sizeOf(sym: Symbol): Int = sizeOf(toTypeKind(sym.tpe)) - def sizeOf(k: TypeKind): Int = if(k.isWideType) 2 else 1 - def indexOf(m: IMethod, sym: Symbol): Int = { - val Some(local) = m lookupLocal sym - indexOf(local) - } - def indexOf(local: Local): Int = { assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ") local.index @@ -1989,7 +1941,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ) def isTopLevelModule(sym: Symbol): Boolean = - afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } + exitingPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } def isStaticModule(sym: Symbol): Boolean = { sym.isModuleClass && !sym.isImplClass && !sym.isLifted diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala index e002a614bd..613f8f893e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala @@ -14,7 +14,6 @@ trait GenJVMUtil { import global._ import icodes._ - import icodes.opcodes._ import definitions._ /** Map from type kinds to the Java reference types. It is used for diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index aaffaa84d8..2fb6550239 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package backend.msil import java.io.{File, IOException} -import java.nio.{ByteBuffer, ByteOrder} import scala.collection.{ mutable, immutable } import scala.tools.nsc.symtab._ @@ -24,8 +23,6 @@ abstract class GenMSIL extends SubComponent { import icodes._ import icodes.opcodes._ - val x = loaders - /** Create a new phase */ override def newPhase(p: Phase) = new MsilPhase(p) @@ -45,8 +42,8 @@ abstract class GenMSIL extends SubComponent { //classes is ICodes.classes, a HashMap[Symbol, IClass] classes.values foreach codeGenerator.findEntryPoint - if( opt.showClass.isDefined && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead - val entryclass = opt.showClass.get.toString + if( settings.Xshowcls.isSetByUser && (codeGenerator.entryPoint == null) ) { // TODO introduce dedicated setting instead + val entryclass = settings.Xshowcls.value.toString warning("Couldn't find entry class " + entryclass) } @@ -84,9 +81,6 @@ abstract class GenMSIL extends SubComponent { SYMTAB_DEFAULT_CONSTR => SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR} val EXCEPTION = clrTypes.getType("System.Exception") - val MBYTE_ARRAY = clrTypes.mkArrayType(MBYTE) - - val ICLONEABLE = clrTypes.getType("System.ICloneable") val MEMBERWISE_CLONE = MOBJECT.GetMethod("MemberwiseClone", MsilType.EmptyTypes) val MMONITOR = clrTypes.getType("System.Threading.Monitor") @@ -103,9 +97,6 @@ abstract class GenMSIL extends SubComponent { val INT_PTR = clrTypes.getType("System.IntPtr") - val JOBJECT = definitions.ObjectClass - val JSTRING = definitions.StringClass - val SystemConvert = clrTypes.getType("System.Convert") val objParam = Array(MOBJECT) @@ -124,7 +115,6 @@ abstract class GenMSIL extends SubComponent { // Scala attributes // symtab.Definitions -> object (singleton..) - val SerializableAttr = definitions.SerializableAttr.tpe val CloneableAttr = definitions.CloneableAttr.tpe val TransientAtt = definitions.TransientAttr.tpe // remoting: the architectures are too different, no mapping (no portable code @@ -259,9 +249,9 @@ abstract class GenMSIL extends SubComponent { * and thus shouldn't be added by this method. */ def addAttributes(member: ICustomAttributeSetter, annotations: List[AnnotationInfo]) { - val attributes = annotations.map(_.atp.typeSymbol).collect { - case definitions.TransientAttr => null // TODO this is just an example - } + // val attributes = annotations.map(_.atp.typeSymbol).collect { + // case definitions.TransientAttr => null // TODO this is just an example + // } return // TODO: implement at some point } @@ -313,7 +303,7 @@ abstract class GenMSIL extends SubComponent { /* def getAttributeArgs(consts: List[Constant], nvPairs: List[(Name, Constant)]): Array[Byte] = { val buf = ByteBuffer.allocate(2048) // FIXME: this may be not enough! - buf.order(ByteOrder.LITTLE_ENDIAN) + buf.order(java.nio.ByteOrder.LITTLE_ENDIAN) buf.putShort(1.toShort) // signature def emitSerString(str: String) = { @@ -466,7 +456,7 @@ abstract class GenMSIL extends SubComponent { private[GenMSIL] def genClass(iclass: IClass) { val sym = iclass.symbol - debuglog("Generating class " + sym + " flags: " + Flags.flagsToString(sym.flags)) + debuglog("Generating class " + sym + " flags: " + sym.flagString) clasz = iclass val tBuilder = getType(sym).asInstanceOf[TypeBuilder] @@ -511,7 +501,7 @@ abstract class GenMSIL extends SubComponent { private def genMethod(m: IMethod) { - debuglog("Generating method " + m.symbol + " flags: " + Flags.flagsToString(m.symbol.flags) + + debuglog("Generating method " + m.symbol + " flags: " + m.symbol.flagString + " owner: " + m.symbol.owner) method = m localBuilders.clear @@ -526,8 +516,8 @@ abstract class GenMSIL extends SubComponent { mcode = mBuilder.GetILGenerator() } catch { case e: Exception => - java.lang.System.out.println("m.symbol = " + Flags.flagsToString(m.symbol.flags) + " " + m.symbol) - java.lang.System.out.println("m.symbol.owner = " + Flags.flagsToString(m.symbol.owner.flags) + " " + m.symbol.owner) + java.lang.System.out.println("m.symbol = " + m.symbol.flagString + " " + m.symbol) + java.lang.System.out.println("m.symbol.owner = " + m.symbol.owner.flagString + " " + m.symbol.owner) java.lang.System.out.println("mBuilder = " + mBuilder) java.lang.System.out.println("mBuilder.DeclaringType = " + TypeAttributes.toString(mBuilder.DeclaringType.Attributes) + @@ -624,7 +614,7 @@ abstract class GenMSIL extends SubComponent { * - emit `Leave handlerReturnLabel` instead of the Return * - emit code at the end: load the local and return its value */ - var currentHandlers = new mutable.Stack[ExceptionHandler] + val currentHandlers = new mutable.Stack[ExceptionHandler] // The IMethod the Local/Label/Kind below belong to var handlerReturnMethod: IMethod = _ // Stores the result when returning inside an exception block @@ -823,8 +813,8 @@ abstract class GenMSIL extends SubComponent { def loadFieldOrAddress(field: Symbol, isStatic: Boolean, msg: String, loadAddr : Boolean) { debuglog(msg + " with owner: " + field.owner + - " flags: " + Flags.flagsToString(field.owner.flags)) - var fieldInfo = fields.get(field) match { + " flags: " + field.owner.flagString) + val fieldInfo = fields.get(field) match { case Some(fInfo) => fInfo case None => val fInfo = getType(field.owner).GetField(msilName(field)) @@ -1126,7 +1116,7 @@ abstract class GenMSIL extends SubComponent { } // method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType - val (isDelegateView, paramType, resType) = beforeTyper { + val (isDelegateView, paramType, resType) = enteringTyper { msym.tpe match { case MethodType(params, resultType) if (params.length == 1 && msym.name == nme.view_) => @@ -1255,7 +1245,7 @@ abstract class GenMSIL extends SubComponent { mcode.Emit(OpCodes.Stloc, switchLocal) var i = 0 for (l <- tags) { - var targetLabel = labels(branches(i)) + val targetLabel = labels(branches(i)) for (i <- l) { mcode.Emit(OpCodes.Ldloc, switchLocal) loadI4(i, mcode) @@ -1633,18 +1623,6 @@ abstract class GenMSIL extends SubComponent { mf = mf | (if (sym hasFlag Flags.ABSTRACT) TypeAttributes.Abstract else 0) mf = mf | (if (sym.isTrait && !sym.isImplClass) TypeAttributes.Interface else TypeAttributes.Class) mf = mf | (if (sym isFinal) TypeAttributes.Sealed else 0) - - sym.annotations foreach { a => a match { - case AnnotationInfo(SerializableAttr, _, _) => - // TODO: add the Serializable TypeAttribute also if the annotation - // System.SerializableAttribute is present (.net annotation, not scala) - // Best way to do it: compare with - // definitions.getClass("System.SerializableAttribute").tpe - // when frontend available - mf = mf | TypeAttributes.Serializable - case _ => () - }} - mf // static: not possible (or?) } @@ -1731,8 +1709,8 @@ abstract class GenMSIL extends SubComponent { false } - if((entryPoint == null) && opt.showClass.isDefined) { // TODO introduce dedicated setting instead - val entryclass = opt.showClass.get.toString + if((entryPoint == null) && settings.Xshowcls.isSetByUser) { // TODO introduce dedicated setting instead + val entryclass = settings.Xshowcls.value.toString val cfn = cls.symbol.fullName if(cfn == entryclass) { for (m <- cls.methods; if isEntryPoint(m.symbol)) { entryPoint = m.symbol } @@ -1884,7 +1862,7 @@ abstract class GenMSIL extends SubComponent { val sym = ifield.symbol debuglog("Adding field: " + sym.fullName) - var attributes = msilFieldFlags(sym) + val attributes = msilFieldFlags(sym) val fieldTypeWithCustomMods = new PECustomMod(msilType(sym.tpe), customModifiers(sym.annotations)) @@ -1913,12 +1891,12 @@ abstract class GenMSIL extends SubComponent { if (iclass.symbol != definitions.ArrayClass) { for (m: IMethod <- iclass.methods) { val sym = m.symbol - debuglog("Creating MethodBuilder for " + Flags.flagsToString(sym.flags) + " " + + debuglog("Creating MethodBuilder for " + sym.flagString + " " + sym.owner.fullName + "::" + sym.name) val ownerType = getType(sym.enclClass).asInstanceOf[TypeBuilder] assert(mtype == ownerType, "mtype = " + mtype + "; ownerType = " + ownerType) - var paramTypes = msilParamTypes(sym) + val paramTypes = msilParamTypes(sym) val attr = msilMethodFlags(sym) if (m.symbol.isClassConstructor) { @@ -1930,7 +1908,7 @@ abstract class GenMSIL extends SubComponent { mapConstructor(sym, constr) addAttributes(constr, sym.annotations) } else { - var resType = msilType(m.returnType) + val resType = msilType(m.returnType) val method = ownerType.DefineMethod(msilName(sym), attr, resType, paramTypes) for (i <- 0.until(paramTypes.length)) { @@ -1955,7 +1933,7 @@ abstract class GenMSIL extends SubComponent { } // createClassMembers0 private def isTopLevelModule(sym: Symbol): Boolean = - beforeRefchecks { + enteringRefchecks { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } @@ -2050,7 +2028,6 @@ abstract class GenMSIL extends SubComponent { } private def generateMirrorClass(sym: Symbol) { - val tBuilder = getType(sym) assert(sym.isModuleClass, "Can't generate Mirror-Class for the Non-Module class " + sym) debuglog("Dumping mirror class for object: " + sym) val moduleName = msilName(sym) @@ -2257,100 +2234,9 @@ abstract class GenMSIL extends SubComponent { methods(sym) = mInfo } - /* - * add mapping between sym and method with newName, paramTypes of newClass - */ - private def mapMethod(sym: Symbol, newClass: MsilType, newName: String, paramTypes: Array[MsilType]) { - val methodInfo = newClass.GetMethod(newName, paramTypes) - assert(methodInfo != null, "Can't find mapping for " + sym + " -> " + - newName + "(" + paramTypes + ")") - mapMethod(sym, methodInfo) - if (methodInfo.IsStatic) - dynToStatMapped += sym - } - - /* - * add mapping between method with name and paramTypes of clazz to - * method with newName and newParamTypes of newClass (used for instance - * for "wait") - */ - private def mapMethod( - clazz: Symbol, name: Name, paramTypes: Array[Type], - newClass: MsilType, newName: String, newParamTypes: Array[MsilType]) { - val methodSym = lookupMethod(clazz, name, paramTypes) - assert(methodSym != null, "cannot find method " + name + "(" + - paramTypes + ")" + " in class " + clazz) - mapMethod(methodSym, newClass, newName, newParamTypes) - } - - /* - * add mapping for member with name and paramTypes to member - * newName of newClass (same parameters) - */ - private def mapMethod( - clazz: Symbol, name: Name, paramTypes: Array[Type], - newClass: MsilType, newName: String) { - mapMethod(clazz, name, paramTypes, newClass, newName, paramTypes map msilType) - } - - /* - * add mapping for all methods with name of clazz to the corresponding - * method (same parameters) with newName of newClass - */ - private def mapMethod( - clazz: Symbol, name: Name, - newClass: MsilType, newName: String) { - val memberSym: Symbol = clazz.tpe.member(name) - memberSym.tpe match { - // alternatives: List[Symbol] - case OverloadedType(_, alternatives) => - alternatives.foreach(s => mapMethod(s, newClass, newName, msilParamTypes(s))) - - // paramTypes: List[Type], resType: Type - case MethodType(params, resType) => - mapMethod(memberSym, newClass, newName, msilParamTypes(memberSym)) - - case _ => - abort("member not found: " + clazz + ", " + name) - } - } - - - /* - * find the method in clazz with name and paramTypes - */ - private def lookupMethod(clazz: Symbol, name: Name, paramTypes: Array[Type]): Symbol = { - val memberSym = clazz.tpe.member(name) - memberSym.tpe match { - case OverloadedType(_, alternatives) => - alternatives.find(s => { - var i: Int = 0 - var typesOK: Boolean = true - if (paramTypes.length == s.tpe.paramTypes.length) { - while(i < paramTypes.length) { - if (paramTypes(i) != s.tpe.paramTypes(i)) - typesOK = false - i += 1 - } - } else { - typesOK = false - } - typesOK - }) match { - case Some(sym) => sym - case None => abort("member of " + clazz + ", " + name + "(" + - paramTypes + ") not found") - } - - case MethodType(_, _) => memberSym - - case _ => abort("member not found: " + name + " of " + clazz) - } - } - private def showsym(sym: Symbol): String = (sym.toString + - "\n symbol = " + Flags.flagsToString(sym.flags) + " " + sym + - "\n owner = " + Flags.flagsToString(sym.owner.flags) + " " + sym.owner + "\n symbol = " + sym.flagString + " " + sym + + "\n owner = " + sym.owner.flagString + " " + sym.owner ) } // class BytecodeGenerator diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala index bb14c3dce0..650775b259 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package backend.opt import scala.tools.nsc.backend.icode.analysis.LubException -import scala.tools.nsc.symtab._ /** * @author Iulian Dragos @@ -120,7 +119,7 @@ abstract class ClosureElimination extends SubComponent { case LOAD_FIELD(f, false) /* if accessible(f, m.symbol) */ => def replaceFieldAccess(r: Record) { - val Record(cls, bindings) = r + val Record(cls, _) = r info.getFieldNonRecordValue(r, f) foreach { v => bb.replaceInstruction(i, DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil) debuglog(s"replaced $i with $v") @@ -188,25 +187,17 @@ abstract class ClosureElimination extends SubComponent { case Boxed(LocalVar(v)) => LOAD_LOCAL(v) } - - /** is field 'f' accessible from method 'm'? */ - def accessible(f: Symbol, m: Symbol): Boolean = - f.isPublic || (f.isProtected && (f.enclosingPackageClass == m.enclosingPackageClass)) } /* class ClosureElim */ /** Peephole optimization. */ abstract class PeepholeOpt { - - private var method: IMethod = NoIMethod - /** Concrete implementations will perform their optimizations here */ def peep(bb: BasicBlock, i1: Instruction, i2: Instruction): Option[List[Instruction]] var liveness: global.icodes.liveness.LivenessAnalysis = null def apply(m: IMethod): Unit = if (m.hasCode) { - method = m liveness = new global.icodes.liveness.LivenessAnalysis liveness.init(m) liveness.run diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index fee683ce3a..f7e743a6f1 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package backend.opt import scala.collection.{ mutable, immutable } -import symtab._ /** */ @@ -280,13 +279,6 @@ abstract class DeadCodeElimination extends SubComponent { compensations } - private def withClosed[a](bb: BasicBlock)(f: => a): a = { - if (bb.nonEmpty) bb.close - val res = f - if (bb.nonEmpty) bb.open - res - } - private def findInstruction(bb: BasicBlock, i: Instruction): (BasicBlock, Int) = { for (b <- linearizer.linearizeAt(method, bb)) { val idx = b.toList indexWhere (_ eq i) diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala index ab238af239..c534c2230c 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala @@ -4,7 +4,6 @@ package scala.tools.nsc package backend.opt -import scala.util.control.Breaks._ /** * This optimization phase inlines the exception handlers so that further phases can optimize the code better diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 521b6cc132..ca1cfc8929 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -50,6 +50,7 @@ abstract class Inliners extends SubComponent { val phaseName = "inliner" /** Debug - for timing the inliner. */ + /**** private def timed[T](s: String, body: => T): T = { val t1 = System.currentTimeMillis() val res = body @@ -60,6 +61,7 @@ abstract class Inliners extends SubComponent { res } + ****/ /** Look up implementation of method 'sym in 'clazz'. */ @@ -193,7 +195,7 @@ abstract class Inliners extends SubComponent { private var currentIClazz: IClass = _ private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg) - private def ownedName(sym: Symbol): String = afterUncurry { + private def ownedName(sym: Symbol): String = exitingUncurry { val count = ( if (!sym.isMethod) 1 else if (sym.owner.isAnonymousFunction) 3 @@ -279,7 +281,7 @@ abstract class Inliners extends SubComponent { } val tfa = new analysis.MTFAGrowable() - tfa.stat = global.opt.printStats + tfa.stat = global.settings.Ystatistics.value val staleOut = new mutable.ListBuffer[BasicBlock] val splicedBlocks = mutable.Set.empty[BasicBlock] val staleIn = mutable.Set.empty[BasicBlock] @@ -320,8 +322,8 @@ abstract class Inliners extends SubComponent { if (settings.debug.value) inlineLog("caller", ownedName(m.symbol), "in " + m.symbol.owner.fullName) - var sizeBeforeInlining = m.code.blockCount - var instrBeforeInlining = m.code.instructionCount + val sizeBeforeInlining = m.code.blockCount + val instrBeforeInlining = m.code.instructionCount var retry = false var count = 0 @@ -477,7 +479,7 @@ abstract class Inliners extends SubComponent { * As a whole, both `preInline()` invocations amount to priming the inlining process, * so that the first TFA that is run afterwards is able to gain more information as compared to a cold-start. */ - val totalPreInlines = { + /*val totalPreInlines = */ { // Val name commented out to emphasize it is never used val firstRound = preInline(true) if(firstRound == 0) 0 else (firstRound + preInline(false)) } @@ -569,7 +571,6 @@ abstract class Inliners extends SubComponent { m.normalize if (sizeBeforeInlining > 0) { val instrAfterInlining = m.code.instructionCount - val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) "!!" else "" val inlinings = caller.inlinedCalls if (inlinings > 0) { val s1 = s"instructions $instrBeforeInlining -> $instrAfterInlining" @@ -584,7 +585,7 @@ abstract class Inliners extends SubComponent { private def isHigherOrderMethod(sym: Symbol) = ( sym.isMethod - && beforeExplicitOuter(sym.info.paramTypes exists isFunctionType) // was "at erasurePhase.prev" + && enteringExplicitOuter(sym.info.paramTypes exists isFunctionType) // was "at erasurePhase.prev" ) /** Should method 'sym' being called in 'receiver' be loaded from disk? */ @@ -601,7 +602,6 @@ abstract class Inliners extends SubComponent { override def toString = m.toString val sym = m.symbol - val name = sym.name def owner = sym.owner def paramTypes = sym.info.paramTypes def minimumStack = paramTypes.length + 1 @@ -617,13 +617,11 @@ abstract class Inliners extends SubComponent { def length = blocks.length def openBlocks = blocks filterNot (_.closed) def instructions = m.code.instructions - // def linearized = linearizer linearize m def isSmall = (length <= SMALL_METHOD_SIZE) && blocks(0).length < 10 def isLarge = length > MAX_INLINE_SIZE def isRecursive = m.recursive def hasHandlers = handlers.nonEmpty || m.bytecodeHasEHs - def hasClosureParam = paramTypes exists (tp => isByNameParamType(tp) || isFunctionType(tp)) def isSynchronized = sym.hasFlag(Flags.SYNCHRONIZED) def hasNonFinalizerHandler = handlers exists { @@ -731,7 +729,6 @@ abstract class Inliners extends SubComponent { */ sealed abstract class InlineSafetyInfo { def isSafe = false - def isUnsafe = !isSafe } case object NeverSafeToInline extends InlineSafetyInfo case object InlineableAtThisCaller extends InlineSafetyInfo { override def isSafe = true } @@ -1031,7 +1028,6 @@ abstract class Inliners extends SubComponent { case Public => true } private def sameSymbols = caller.sym == inc.sym - private def sameOwner = caller.owner == inc.owner /** Gives green light for inlining (which may still be vetoed later). Heuristics: * - it's bad to make the caller larger (> SMALL_METHOD_SIZE) if it was small @@ -1058,8 +1054,8 @@ abstract class Inliners extends SubComponent { if (inc.isMonadic) score += 3 else if (inc.isHigherOrder) score += 1 - if (inc.isInClosure) score += 2 - if (inlinedMethodCount(inc.sym) > 2) score -= 2 + if (inc.isInClosure) score += 2; + if (inlinedMethodCount(inc.sym) > 2) score -= 2; score } } diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala index 7f5f412a20..b3cacee20a 100644 --- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala +++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala @@ -61,12 +61,7 @@ abstract class Changes { annotationsChecked.forall(a => (sym1.hasAnnotation(a) == sym2.hasAnnotation(a))) - private def sameType(tp1: Type, tp2: Type)(implicit strict: Boolean) = { - def typeOf(tp: Type): String = tp.toString + "[" + tp.getClass + "]" - val res = sameType0(tp1, tp2) - //if (!res) println("\t different types: " + typeOf(tp1) + " : " + typeOf(tp2)) - res - } + private def sameType(tp1: Type, tp2: Type)(implicit strict: Boolean) = sameType0(tp1, tp2) private def sameType0(tp1: Type, tp2: Type)(implicit strict: Boolean): Boolean = ((tp1, tp2) match { /*case (ErrorType, _) => false @@ -170,7 +165,6 @@ abstract class Changes { /** Return the list of changes between 'from' and 'toSym.info'. */ def changeSet(from: Type, toSym: Symbol): List[Change] = { - implicit val defaultReason = "types" implicit val defaultStrictTypeRefTest = true val to = toSym.info diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala index cdde768274..4d4b6589a0 100644 --- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala +++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala @@ -3,7 +3,6 @@ package dependencies import io.Path import scala.collection._ -import symtab.Flags import scala.tools.nsc.io.AbstractFile import scala.reflect.internal.util.SourceFile @@ -145,7 +144,7 @@ trait DependencyAnalysis extends SubComponent with Files { val name = d.toString d.symbol match { case s : ModuleClassSymbol => - val isTopLevelModule = afterPickler { !s.isImplClass && !s.isNestedClass } + val isTopLevelModule = exitingPickler { !s.isImplClass && !s.isNestedClass } if (isTopLevelModule && (s.companionModule != NoSymbol)) { dependencies.emits(source, nameToFile(unit.source.file, name)) @@ -183,7 +182,7 @@ trait DependencyAnalysis extends SubComponent with Files { // was "at uncurryPhase.prev", which is actually non-deterministic // because the continuations plugin may or may not supply uncurry's // immediately preceding phase. - beforeRefchecks(checkType(tree.symbol.tpe)) + enteringRefchecks(checkType(tree.symbol.tpe)) } tree match { @@ -191,7 +190,7 @@ trait DependencyAnalysis extends SubComponent with Files { !cdef.symbol.isAnonymousFunction => if (cdef.symbol != NoSymbol) buf += cdef.symbol // was "at erasurePhase.prev" - beforeExplicitOuter { + enteringExplicitOuter { for (s <- cdef.symbol.info.decls) s match { case ts: TypeSymbol if !ts.isClass => @@ -203,7 +202,7 @@ trait DependencyAnalysis extends SubComponent with Files { case ddef: DefDef => // was "at typer.prev" - beforeTyper { checkType(ddef.symbol.tpe) } + enteringTyper { checkType(ddef.symbol.tpe) } super.traverse(tree) case a @ Select(q, n) if ((a.symbol != NoSymbol) && (q.symbol != null)) => // #2556 if (!a.symbol.isConstructor && diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala index 642e330a57..a091bc3e62 100644 --- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -8,9 +8,7 @@ package doc import scala.util.control.ControlThrowable import reporters.Reporter -import scala.reflect.internal.util.{ NoPosition, BatchSourceFile} -import io.{ File, Directory } -import DocParser.Parsed +import scala.reflect.internal.util.BatchSourceFile /** A documentation processor controls the process of generating Scala * documentation, which is as follows. diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala index 10a0d8d879..16f3c3776b 100644 --- a/src/compiler/scala/tools/nsc/doc/Settings.scala +++ b/src/compiler/scala/tools/nsc/doc/Settings.scala @@ -6,9 +6,7 @@ package scala.tools.nsc package doc -import java.io.File import java.net.URI -import java.lang.System import scala.language.postfixOps /** An extended version of compiler settings, with additional Scaladoc-specific options. diff --git a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala index d3e5c869e0..9447e36610 100644 --- a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala +++ b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala @@ -15,7 +15,7 @@ trait Uncompilable { val global: Global val settings: Settings - import global.{ reporter, inform, warning, newTypeName, newTermName, Symbol, Name, DocComment, NoSymbol } + import global.{ reporter, inform, warning, newTypeName, newTermName, Symbol, DocComment, NoSymbol } import global.definitions.AnyRefClass import global.rootMirror.RootClass diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala index e8131e242b..c898348526 100644 --- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala @@ -10,7 +10,7 @@ package html import model._ import comment._ -import scala.xml.{XML, NodeSeq} +import scala.xml.NodeSeq import scala.xml.dtd.{DocType, PublicID} import scala.collection._ import java.io.Writer diff --git a/src/compiler/scala/tools/nsc/doc/html/Page.scala b/src/compiler/scala/tools/nsc/doc/html/Page.scala index 62166f7def..ef9beb1dce 100644 --- a/src/compiler/scala/tools/nsc/doc/html/Page.scala +++ b/src/compiler/scala/tools/nsc/doc/html/Page.scala @@ -88,12 +88,6 @@ abstract class Page { def relativeLinkTo(destClass: TemplateEntity): String = relativeLinkTo(templateToPath(destClass)) - /** A relative link from this page to some destination page in the Scaladoc site. - * @param destPage The page that the link will point to. */ - def relativeLinkTo(destPage: HtmlPage): String = { - relativeLinkTo(destPage.path) - } - /** A relative link from this page to some destination path. * @param destPath The path that the link will point to. */ def relativeLinkTo(destPath: List[String]): String = { diff --git a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala index ee78f4ea7a..2783a27811 100644 --- a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala +++ b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala @@ -40,7 +40,7 @@ private[html] object SyntaxHigh { /** Standard library classes/objects, sorted alphabetically */ val standards = Array ( - "WeakTypeTag", "Any", "AnyRef", "AnyVal", "App", "Application", "Array", + "WeakTypeTag", "Any", "AnyRef", "AnyVal", "App", "Array", "Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest", "Console", "Double", "Enumeration", "Float", "Function", "Int", "List", "Long", "Manifest", "Map", diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala index 86407fb9a3..daa9df690c 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala @@ -9,10 +9,8 @@ package html package page import model._ - import scala.collection._ import scala.xml._ -import scala.util.parsing.json.{JSONObject, JSONArray} class Index(universe: doc.Universe, val index: doc.Index) extends HtmlPage { diff --git a/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala index a205e02533..e3c94505ab 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/IndexScript.scala @@ -8,7 +8,6 @@ package scala.tools.nsc.doc.html.page import scala.tools.nsc.doc import scala.tools.nsc.doc.model.{Package, DocTemplateEntity} import scala.tools.nsc.doc.html.{Page, HtmlFactory} -import java.nio.channels.Channels import scala.util.parsing.json.{JSONObject, JSONArray} class IndexScript(universe: doc.Universe, index: doc.Index) extends Page { diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Source.scala b/src/compiler/scala/tools/nsc/doc/html/page/Source.scala index 807a1bc11a..37145756d9 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Source.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Source.scala @@ -8,9 +8,7 @@ package doc package html package page -import model._ -import comment._ -import scala.xml.{NodeSeq, Unparsed} +import scala.xml.NodeSeq import java.io.File class Source(sourceFile: File) extends HtmlPage { diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index 008999e09f..3f40e2cd0a 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -8,10 +8,6 @@ package doc package html package page -import model._ -import model.diagram._ -import diagram._ - import scala.xml.{ NodeSeq, Text, UnprefixedAttribute } import scala.language.postfixOps @@ -527,7 +523,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp val sourceLink: Seq[scala.xml.Node] = mbr match { case dtpl: DocTemplateEntity if (isSelf && dtpl.sourceUrl.isDefined && dtpl.inSource.isDefined && !isReduced) => - val (absFile, line) = dtpl.inSource.get + val (absFile, _) = dtpl.inSource.get <dt>Source</dt> <dd>{ <a href={ dtpl.sourceUrl.get.toString } target="_blank">{ Text(absFile.file.getName) }</a> }</dd> case _ => NodeSeq.Empty @@ -651,7 +647,6 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp case dtpl: DocTemplateEntity if isSelf && !isReduced => val diagram = f(dtpl) if (diagram.isDefined) { - val s = universe.settings val diagramSvg = generator.generate(diagram.get, tpl, this) if (diagramSvg != NodeSeq.Empty) { <div class="toggleContainer block diagram-container" id={ id + "-container"}> diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala index 304c534bdc..df7c7d3dcd 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala @@ -10,7 +10,6 @@ package diagram import scala.xml.{NodeSeq, XML, PrefixedAttribute, Elem, MetaData, Null, UnprefixedAttribute} import scala.collection.immutable._ -import javax.xml.parsers.SAXParser import model._ import model.diagram._ @@ -22,8 +21,6 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator { private var pathToLib: String = null // maps nodes to unique indices private var node2Index: Map[Node, Int] = null - // maps an index to its corresponding node - private var index2Node: Map[Int, Node] = null // true if the current diagram is a class diagram private var isInheritanceDiagram = false // incoming implicit nodes (needed for determining the CSS class of a node) @@ -42,7 +39,6 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator { // clean things up a bit, so we don't leave garbage on the heap this.page = null node2Index = null - index2Node = null incomingImplicitNodes = List() result } @@ -116,7 +112,6 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator { node2Index = d.nodes.zipWithIndex.toMap incomingImplicitNodes = List() } - index2Node = node2Index map {_.swap} val implicitsDot = { if (!isInheritanceDiagram) "" @@ -215,7 +210,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator { def escape(name: String) = name.replace("&", "&").replace("<", "<").replace(">", ">"); // assemble node attribues in a map - var attr = scala.collection.mutable.Map[String, String]() + val attr = scala.collection.mutable.Map[String, String]() // link node.doctpl match { diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala index 5cdd5c74a4..2fa1bf62f3 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotRunner.scala @@ -10,12 +10,10 @@ import java.io.InputStreamReader import java.io.OutputStreamWriter import java.io.BufferedWriter import java.io.BufferedReader -import java.io.IOException import scala.sys.process._ import scala.concurrent.SyncVar import model._ -import model.diagram._ /** This class takes care of running the graphviz dot utility */ class DotRunner(settings: doc.Settings) { @@ -183,7 +181,7 @@ class DotProcess(settings: doc.Settings) { private[this] def outputFn(stdOut: InputStream): Unit = { val reader = new BufferedReader(new InputStreamReader(stdOut)) - var buffer: StringBuilder = new StringBuilder() + val buffer: StringBuilder = new StringBuilder() try { var line = reader.readLine while (!error && line != null) { @@ -209,7 +207,6 @@ class DotProcess(settings: doc.Settings) { private[this] def errorFn(stdErr: InputStream): Unit = { val reader = new BufferedReader(new InputStreamReader(stdErr)) - var buffer: StringBuilder = new StringBuilder() try { var line = reader.readLine while (line != null) { @@ -225,4 +222,4 @@ class DotProcess(settings: doc.Settings) { errorBuffer.append(" Error thread in " + templateName + ": Exception: " + exc + "\n") } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index c3f9101f17..04046accc4 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -23,10 +23,6 @@ import diagram._ * - type and value parameters; * - annotations. */ trait Entity { - - /** Similar to symbols, so we can track entities */ - def id: Int - /** The name of the entity. Note that the name does not qualify this entity uniquely; use its `qualifiedName` * instead. */ def name : String @@ -59,9 +55,6 @@ trait Entity { /** Indicates whether this entity lives in the types namespace (classes, traits, abstract/alias types) */ def isType: Boolean - - /** Indicates whether this entity lives in the terms namespace (objects, packages, methods, values) */ - def isTerm: Boolean } object Entity { @@ -97,9 +90,6 @@ trait TemplateEntity extends Entity { /** Whether documentation is available for this template. */ def isDocTemplate: Boolean - /** Whether documentation is available for this template. */ - def isNoDocMemberTemplate: Boolean - /** Whether this template is a case class. */ def isCaseClass: Boolean @@ -149,9 +139,6 @@ trait MemberEntity extends Entity { /** Some migration warning if this member has a migration annotation, or none otherwise. */ def migration: Option[Body] - @deprecated("Use `inDefinitionTemplates` instead", "2.9.0") - def inheritedFrom: List[TemplateEntity] - /** For members representing values: the type of the value returned by this member; for members * representing types: the type itself. */ def resultType: TypeEntity @@ -177,12 +164,6 @@ trait MemberEntity extends Entity { /** Whether this member is an abstract type. */ def isAbstractType: Boolean - /** Whether this member is a template. */ - def isTemplate: Boolean - - /** Whether this member is implicit. */ - def isImplicit: Boolean - /** Whether this member is abstract. */ def isAbstract: Boolean @@ -384,14 +365,9 @@ trait RootPackage extends Package /** A non-template member (method, value, lazy value, variable, constructor, alias type, and abstract type). */ trait NonTemplateMemberEntity extends MemberEntity { - /** Whether this member is a use case. A use case is a member which does not exist in the documented code. * It corresponds to a real member, and provides a simplified, yet compatible signature for that member. */ def isUseCase: Boolean - - /** Whether this member is a bridge member. A bridge member does only exist for binary compatibility reasons - * and should not appear in ScalaDoc. */ - def isBridge: Boolean } @@ -506,12 +482,6 @@ trait ImplicitConversion { /** The result type after the conversion */ def targetType: TypeEntity - /** The result type after the conversion - * Note: not all targetTypes have a corresponding template. Examples include conversions resulting in refinement - * types. Need to check it's not option! - */ - def targetTemplate: Option[TemplateEntity] - /** The components of the implicit conversion type parents */ def targetTypeComponents: List[(TemplateEntity, TypeEntity)] diff --git a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala index 10e2f23142..1d6063255d 100755 --- a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala @@ -17,8 +17,6 @@ object IndexModelFactory { object result extends mutable.HashMap[Char,SymbolMap] { - /* Owner template ordering */ - implicit def orderingSet = math.Ordering.String.on { x: MemberEntity => x.name.toLowerCase } /* symbol name ordering */ implicit def orderingMap = math.Ordering.String.on { x: String => x.toLowerCase } diff --git a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala index 6c13d5a6d3..361837b743 100644 --- a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala +++ b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package doc package model -import scala.collection._ - abstract sealed class LinkTo final case class LinkToTpl(tpl: DocTemplateEntity) extends LinkTo final case class LinkToMember(mbr: MemberEntity, inTpl: DocTemplateEntity) extends LinkTo diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala index 5257db1610..4793716b9f 100644 --- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala +++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala @@ -4,8 +4,6 @@ package model import comment._ -import scala.reflect.internal.util.FakePos //Position - /** This trait extracts all required information for documentation from compilation units */ trait MemberLookup { thisFactory: ModelFactory => @@ -19,7 +17,7 @@ trait MemberLookup { def memberLookup(pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]): LinkTo = { assert(modelFinished) - var members = breakMembers(query) + val members = breakMembers(query) //println(query + " => " + members) // (1) First look in the root package, as most of the links are qualified diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 3ae1210ebf..04f95455a5 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -43,20 +43,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def modelFinished: Boolean = _modelFinished private var universe: Universe = null - private def dbg(msg: String) = if (sys.props contains "scala.scaladoc.debug") println(msg) - protected def closestPackage(sym: Symbol) = { - if (sym.isPackage || sym.isPackageClass) sym - else sym.enclosingPackage - } - - private def printWithoutPrefix(memberSym: Symbol, templateSym: Symbol) = { - dbg( - "memberSym " + memberSym + " templateSym " + templateSym + " encls = " + - closestPackage(memberSym) + ", " + closestPackage(templateSym) - ) - memberSym.isOmittablePrefix || (closestPackage(memberSym) == closestPackage(templateSym)) - } - def makeModel: Option[Universe] = { val universe = new Universe { thisUniverse => thisFactory.universe = thisUniverse @@ -86,7 +72,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { /* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */ abstract class EntityImpl(val sym: Symbol, val inTpl: TemplateImpl) extends Entity { - val id = { ids += 1; ids } val name = optimize(sym.nameString) val universe = thisFactory.universe @@ -100,7 +85,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def annotations = sym.annotations.map(makeAnnotation) def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject def isType = sym.name.isTypeName - def isTerm = sym.name.isTermName } trait TemplateImpl extends EntityImpl with TemplateEntity { @@ -112,7 +96,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def isObject = sym.isModule && !sym.isPackage def isCaseClass = sym.isCaseClass def isRootPackage = false - def isNoDocMemberTemplate = false def selfType = if (sym.thisSym eq sym) None else Some(makeType(sym.thisSym.typeOfThis, this)) } @@ -127,18 +110,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } if (inTpl != null) thisFactory.comment(sym, thisTpl, inTpl) else None } - def group = if (comment.isDefined) comment.get.group.getOrElse(defaultGroup) else defaultGroup + def group = comment flatMap (_.group) getOrElse defaultGroup override def inTemplate = inTpl override def toRoot: List[MemberImpl] = this :: inTpl.toRoot - def inDefinitionTemplates = this match { - case mb: NonTemplateMemberEntity if (mb.useCaseOf.isDefined) => - mb.useCaseOf.get.inDefinitionTemplates - case _ => - if (inTpl == null) - List(makeRootPackage) - else - makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) - } + def inDefinitionTemplates = + if (inTpl == null) + List(makeRootPackage) + else + makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) def visibility = { if (sym.isPrivateLocal) PrivateInInstance() else if (sym.isProtectedLocal) ProtectedInInstance() @@ -149,8 +128,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { else None if (sym.isPrivate) PrivateInTemplate(inTpl) else if (sym.isProtected) ProtectedInTemplate(qual getOrElse inTpl) - else if (qual.isDefined) PrivateInTemplate(qual.get) - else Public() + else qual match { + case Some(q) => PrivateInTemplate(q) + case None => Public() + } } } def flags = { @@ -189,9 +170,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { }) else None - def inheritedFrom = - if (inTemplate.sym == this.sym.owner || inTemplate.sym.isPackage) Nil else - makeTemplate(this.sym.owner) :: (sym.allOverriddenSymbols map { os => makeTemplate(os.owner) }) + def resultType = { def resultTpe(tpe: Type): Type = tpe match { // similar to finalResultType, except that it leaves singleton types alone case PolyType(_, res) => resultTpe(res) @@ -199,14 +178,13 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { case NullaryMethodType(res) => resultTpe(res) case _ => tpe } - val tpe = if (!isImplicitlyInherited) sym.tpe else byConversion.get.toType memberInfo sym + val tpe = byConversion.fold(sym.tpe) (_.toType memberInfo sym) makeTypeInTemplateContext(resultTpe(tpe), inTemplate, sym) } def isDef = false def isVal = false def isLazyVal = false def isVar = false - def isImplicit = sym.isImplicit def isConstructor = false def isAliasType = false def isAbstractType = false @@ -214,7 +192,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { // for the explanation of conversion == null see comment on flags ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) && (!isImplicitlyInherited)) || sym.isAbstractClass || sym.isAbstractType) && !sym.isSynthetic - def isTemplate = false + def signature = externalSignature(sym) lazy val signatureCompat = { @@ -268,25 +246,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { */ abstract class MemberTemplateImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with MemberTemplateEntity { // no templates cache for this class, each owner gets its own instance - override def isTemplate = true def isDocTemplate = false - override def isNoDocMemberTemplate = true lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name) def valueParams: List[List[ValueParam]] = Nil /** TODO, these are now only computed for DocTemplates */ - // Seems unused - // def parentTemplates = - // if (sym.isPackage || sym == AnyClass) - // List() - // else - // sym.tpe.parents.flatMap { tpe: Type => - // val tSym = tpe.typeSymbol - // if (tSym != NoSymbol) - // List(makeTemplate(tSym)) - // else - // List() - // } filter (_.isInstanceOf[DocTemplateEntity]) - def parentTypes = if (sym.isPackage || sym == AnyClass) List() else { val tps = (this match { @@ -391,9 +354,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this)).toList // the inherited templates (classes, traits or objects) - var memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOwner(t, this)) + val memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOwner(t, this)) // the direct members (methods, values, vars, types and directly contained templates) - var memberSymsEager = memberSyms.filter(!memberSymsLazy.contains(_)) + val memberSymsEager = memberSyms.filter(!memberSymsLazy.contains(_)) // the members generated by the symbols in memberSymsEager val ownMembers = (memberSymsEager.flatMap(makeMember(_, None, this))) @@ -439,17 +402,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { conversions flatMap (conv => if (!implicitExcluded(conv.conversionQualifiedName)) conv.targetTypeComponents map { - case pair@(template, tpe) => + case (template, tpe) => template match { case d: DocTemplateImpl if (d != this) => d.registerImplicitlyConvertibleClass(this, conv) case _ => // nothing } - (pair._1, pair._2, conv) + (template, tpe, conv) } else List() ) - override def isTemplate = true override def isDocTemplate = true private[this] lazy val companionSymbol = if (sym.isAliasType || sym.isAbstractType) { @@ -524,31 +486,26 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity { override lazy val comment = { val inRealTpl = - /* Variable precendence order for implicitly added members: Take the variable defifinitions from ... - * 1. the target of the implicit conversion - * 2. the definition template (owner) - * 3. the current template - */ - if (conversion.isDefined) findTemplateMaybe(conversion.get.toType.typeSymbol) match { - case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package - case _ => findTemplateMaybe(sym.owner) match { - case Some(d) if d != makeRootPackage => d //in case of NoSymbol, it will give us the root package - case _ => inTpl - } - } else inTpl - if (inRealTpl != null) thisFactory.comment(sym, None, inRealTpl) else None + conversion.fold(Option(inTpl)) { conv => + /* Variable precendence order for implicitly added members: Take the variable defifinitions from ... + * 1. the target of the implicit conversion + * 2. the definition template (owner) + * 3. the current template + */ + findTemplateMaybe(conv.toType.typeSymbol) filterNot (_ == makeRootPackage) orElse ( + findTemplateMaybe(sym.owner) filterNot (_ == makeRootPackage) orElse Option(inTpl) + ) + } + inRealTpl flatMap (thisFactory.comment(sym, None, _)) } + override def inDefinitionTemplates = useCaseOf.fold(super.inDefinitionTemplates)(_.inDefinitionTemplates) + override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name) lazy val definitionName = { - // this contrived name is here just to satisfy some older tests -- if you decide to remove it, be my guest, and - // also remove property("package object") from test/scaladoc/scalacheck/HtmlFactoryTest.scala so you don't break - // the test suite... - val packageObject = if (inPackageObject) ".package" else "" - if (!conversion.isDefined) optimize(inDefinitionTemplates.head.qualifiedName + packageObject + "#" + name) - else optimize(conversion.get.conversionQualifiedName + packageObject + "#" + name) + val qualifiedName = conversion.fold(inDefinitionTemplates.head.qualifiedName)(_.conversionQualifiedName) + optimize(qualifiedName + "#" + name) } - def isBridge = sym.isBridge def isUseCase = useCaseOf.isDefined override def byConversion: Option[ImplicitConversionImpl] = conversion override def isImplicitlyInherited = { assert(modelFinished); conversion.isDefined } @@ -561,7 +518,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl) extends NonTemplateMemberImpl(sym, conversion, useCaseOf, inTpl) { def valueParams = { - val info = if (!isImplicitlyInherited) sym.info else conversion.get.toType memberInfo sym + val info = conversion.fold(sym.info)(_.toType memberInfo sym) info.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl) }} @@ -710,7 +667,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { override def inTemplate = this override def toRoot = this :: Nil override def qualifiedName = "_root_" - override def inheritedFrom = Nil override def isRootPackage = true override lazy val memberSyms = (bSym.info.members ++ EmptyPackage.info.members).toList filter { s => @@ -780,7 +736,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } } - /** Get the root package */ def makeRootPackage: PackageImpl = docTemplatesCache(RootPackage).asInstanceOf[PackageImpl] // TODO: Should be able to override the type @@ -857,16 +812,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } def findMember(aSym: Symbol, inTpl: DocTemplateImpl): Option[MemberImpl] = { - val tplSym = normalizeTemplate(aSym.owner) + normalizeTemplate(aSym.owner) inTpl.members.find(_.sym == aSym) } - @deprecated("Use `findLinkTarget` instead.", "2.10.0") - def findTemplate(query: String): Option[DocTemplateImpl] = { - assert(modelFinished) - docTemplatesCache.values find { (tpl: DocTemplateImpl) => tpl.qualifiedName == query && !packageDropped(tpl) && !tpl.isObject } - } - def findTemplateMaybe(aSym: Symbol): Option[DocTemplateImpl] = { assert(modelFinished) docTemplatesCache.get(normalizeTemplate(aSym)).filterNot(packageDropped(_)) @@ -877,20 +826,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def makeTemplate(aSym: Symbol, inTpl: Option[TemplateImpl]): TemplateImpl = { assert(modelFinished) - def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl = { - val bSym = normalizeTemplate(aSym) - noDocTemplatesCache.get(bSym) match { - case Some(noDocTpl) => noDocTpl - case None => new NoDocTemplateImpl(bSym, inTpl) - } - } + def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl = + noDocTemplatesCache getOrElse (aSym, new NoDocTemplateImpl(aSym, inTpl)) - findTemplateMaybe(aSym) match { - case Some(dtpl) => - dtpl - case None => - val bSym = normalizeTemplate(aSym) - makeNoDocTemplate(bSym, if (inTpl.isDefined) inTpl.get else makeTemplate(bSym.owner)) + findTemplateMaybe(aSym) getOrElse { + val bSym = normalizeTemplate(aSym) + makeNoDocTemplate(bSym, inTpl getOrElse makeTemplate(bSym.owner)) } } @@ -983,10 +924,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { val ignoreParents = Set[Symbol](AnyClass, AnyRefClass, ObjectClass) val filtParents = // we don't want to expose too many links to AnyRef, that will just be redundant information - if (tpl.isDefined && { val sym = tpl.get.sym; (!sym.isModule && parents.length < 2) || (sym == AnyValClass) || (sym == AnyRefClass) || (sym == AnyClass) }) - parents - else - parents.filterNot((p: Type) => ignoreParents(p.typeSymbol)) + tpl match { + case Some(tpl) if (!tpl.sym.isModule && parents.length < 2) || (tpl.sym == AnyValClass) || (tpl.sym == AnyRefClass) || (tpl.sym == AnyClass) => parents + case _ => parents.filterNot((p: Type) => ignoreParents(p.typeSymbol)) + } /** Returns: * - a DocTemplate if the type's symbol is documented @@ -1017,9 +958,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } def makeQualifiedName(sym: Symbol, relativeTo: Option[Symbol] = None): String = { - val stop = if (relativeTo.isDefined) relativeTo.get.ownerChain.toSet else Set[Symbol]() + val stop = relativeTo map (_.ownerChain.toSet) getOrElse Set[Symbol]() var sym1 = sym - var path = new StringBuilder() + val path = new StringBuilder() // var path = List[Symbol]() while ((sym1 != NoSymbol) && (path.isEmpty || !stop(sym1))) { @@ -1088,7 +1029,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def findExternalLink(sym: Symbol, name: String): Option[LinkTo] = { val sym1 = if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass - else if (sym.isPackage) + else if (sym.isPackage) /* Get package object which has associatedFile ne null */ sym.info.member(newTermName("package")) else sym diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index 5334de3797..015fce294e 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -13,12 +13,7 @@ package model import comment._ import scala.collection._ -import scala.util.matching.Regex - import symtab.Flags -import io._ - -import model.{ RootPackage => RootPackageEntity } /** * This trait finds implicit conversions for a class in the default scope and creates scaladoc entries for each of them. @@ -58,7 +53,6 @@ trait ModelFactoryImplicitSupport { import global._ import global.analyzer._ import global.definitions._ - import rootMirror.{RootPackage, RootClass, EmptyPackage, EmptyPackageClass} import settings.hardcoded // debugging: @@ -96,9 +90,9 @@ trait ModelFactoryImplicitSupport { // But we don't want that, so we'll simply refuse to find implicit conversions on for Nothing and Null if (!(sym.isClass || sym.isTrait || sym == AnyRefClass) || sym == NothingClass || sym == NullClass) Nil else { - var context: global.analyzer.Context = global.analyzer.rootContext(NoCompilationUnit) + val context: global.analyzer.Context = global.analyzer.rootContext(NoCompilationUnit) - val results = global.analyzer.allViewsFrom(sym.tpe, context, sym.typeParams) + val results = global.analyzer.allViewsFrom(sym.tpe_*, context, sym.typeParams) var conversions = results.flatMap(result => makeImplicitConversion(sym, result._1, result._2, context, inTpl)) // also keep empty conversions, so they appear in diagrams // conversions = conversions.filter(!_.members.isEmpty) @@ -109,7 +103,7 @@ trait ModelFactoryImplicitSupport { hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName)) // Filter out non-sensical conversions from value types - if (isPrimitiveValueType(sym.tpe)) + if (isPrimitiveValueType(sym.tpe_*)) conversions = conversions.filter((ic: ImplicitConversionImpl) => hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName)) @@ -351,15 +345,6 @@ trait ModelFactoryImplicitSupport { makeRootPackage } - def targetTemplate: Option[TemplateEntity] = toType match { - // @Vlad: I'm being extra conservative in template creation -- I don't want to create templates for complex types - // such as refinement types because the template can't represent the type corectly (a template corresponds to a - // package, class, trait or object) - case t: TypeRef => Some(makeTemplate(t.sym)) - case RefinedType(parents, decls) => None - case _ => error("Scaladoc implicits: Could not create template for: " + toType + " of type " + toType.getClass); None - } - def targetTypeComponents: List[(TemplateEntity, TypeEntity)] = makeParentTypes(toType, None, inTpl) def convertorMethod: Either[MemberEntity, String] = { @@ -387,7 +372,6 @@ trait ModelFactoryImplicitSupport { lazy val memberImpls: List[MemberImpl] = { // Obtain the members inherited by the implicit conversion val memberSyms = toType.members.filter(implicitShouldDocument(_)).toList - val existingSyms = sym.info.members // Debugging part :) debug(sym.nameString + "\n" + "=" * sym.nameString.length()) @@ -424,66 +408,52 @@ trait ModelFactoryImplicitSupport { /* ========================= HELPER METHODS ========================== */ /** * Computes the shadowing table for all the members in the implicit conversions - * @param mbrs All template's members, including usecases and full signature members + * @param members All template's members, including usecases and full signature members * @param convs All the conversions the template takes part in - * @param inTpl the ususal :) + * @param inTpl the usual :) */ - def makeShadowingTable(mbrs: List[MemberImpl], + def makeShadowingTable(members: List[MemberImpl], convs: List[ImplicitConversionImpl], inTpl: DocTemplateImpl): Map[MemberEntity, ImplicitMemberShadowing] = { assert(modelFinished) - var shadowingTable = Map[MemberEntity, ImplicitMemberShadowing]() + val shadowingTable = mutable.Map[MemberEntity, ImplicitMemberShadowing]() + val membersByName: Map[Name, List[MemberImpl]] = members.groupBy(_.sym.name) + val convsByMember = (Map.empty[MemberImpl, ImplicitConversionImpl] /: convs) { + case (map, conv) => map ++ conv.memberImpls.map (_ -> conv) + } for (conv <- convs) { - val otherConvs = convs.filterNot(_ == conv) + val otherConvMembers: Map[Name, List[MemberImpl]] = convs filterNot (_ == conv) flatMap (_.memberImpls) groupBy (_.sym.name) for (member <- conv.memberImpls) { - // for each member in our list val sym1 = member.sym val tpe1 = conv.toType.memberInfo(sym1) - // check if it's shadowed by a member in the original class - var shadowedBySyms: List[Symbol] = List() - for (mbr <- mbrs) { - val sym2 = mbr.sym - if (sym1.name == sym2.name) { - val shadowed = !settings.docImplicitsSoundShadowing.value || { - val tpe2 = inTpl.sym.info.memberInfo(sym2) - !isDistinguishableFrom(tpe1, tpe2) - } - if (shadowed) - shadowedBySyms ::= sym2 - } + // check if it's shadowed by a member in the original class. + val shadowed = membersByName.get(sym1.name).toList.flatten filter { other => + !settings.docImplicitsSoundShadowing.value || !isDistinguishableFrom(tpe1, inTpl.sym.info.memberInfo(other.sym)) } - val shadowedByMembers = mbrs.filter((mb: MemberImpl) => shadowedBySyms.contains(mb.sym)) - - // check if it's shadowed by another member - var ambiguousByMembers: List[MemberEntity] = List() - for (conv <- otherConvs) - for (member2 <- conv.memberImpls) { - val sym2 = member2.sym - if (sym1.name == sym2.name) { - val tpe2 = conv.toType.memberInfo(sym2) - // Ambiguity should be an equivalence relation - val ambiguated = !isDistinguishableFrom(tpe1, tpe2) || !isDistinguishableFrom(tpe2, tpe1) - if (ambiguated) - ambiguousByMembers ::= member2 - } - } + // check if it's shadowed by another conversion. + val ambiguous = otherConvMembers.get(sym1.name).toList.flatten filter { other => + val tpe2 = convsByMember(other).toType.memberInfo(other.sym) + !isDistinguishableFrom(tpe1, tpe2) || !isDistinguishableFrom(tpe2, tpe1) + } // we finally have the shadowing info - val shadowing = new ImplicitMemberShadowing { - def shadowingMembers: List[MemberEntity] = shadowedByMembers - def ambiguatingMembers: List[MemberEntity] = ambiguousByMembers - } + if (!shadowed.isEmpty || !ambiguous.isEmpty) { + val shadowing = new ImplicitMemberShadowing { + def shadowingMembers: List[MemberEntity] = shadowed + def ambiguatingMembers: List[MemberEntity] = ambiguous + } - shadowingTable += (member -> shadowing) + shadowingTable += (member -> shadowing) + } } } - shadowingTable + shadowingTable.toMap } @@ -513,14 +483,14 @@ trait ModelFactoryImplicitSupport { /** * Make implicits explicit - Not used curently */ - object implicitToExplicit extends TypeMap { - def apply(tp: Type): Type = mapOver(tp) match { - case MethodType(params, resultType) => - MethodType(params.map(param => if (param.isImplicit) param.cloneSymbol.resetFlag(Flags.IMPLICIT) else param), resultType) - case other => - other - } - } + // object implicitToExplicit extends TypeMap { + // def apply(tp: Type): Type = mapOver(tp) match { + // case MethodType(params, resultType) => + // MethodType(params.map(param => if (param.isImplicit) param.cloneSymbol.resetFlag(Flags.IMPLICIT) else param), resultType) + // case other => + // other + // } + // } /** * removeImplicitParameters transforms implicit parameters from the view result type into constraints and @@ -608,4 +578,4 @@ trait ModelFactoryImplicitSupport { false } else true // the member structure is different foo(3, 5) vs foo(3)(5) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala index 942ccaf1ba..1876415f2a 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala @@ -9,13 +9,6 @@ import comment._ import diagram._ import scala.collection._ -import scala.util.matching.Regex - -import symtab.Flags - -import io._ - -import model.{ RootPackage => RootPackageEntity } /** This trait extracts all required information for documentation from compilation units */ trait ModelFactoryTypeSupport { @@ -28,14 +21,11 @@ trait ModelFactoryTypeSupport { import global._ import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass } - import rootMirror.{ RootPackage, RootClass, EmptyPackage } protected val typeCache = new mutable.LinkedHashMap[Type, TypeEntity] /** */ def makeType(aType: Type, inTpl: TemplateImpl): TypeEntity = { - def templatePackage = closestPackage(inTpl.sym) - def createTypeEntity = new TypeEntity { private var nameBuffer = new StringBuilder private var refBuffer = new immutable.TreeMap[Int, (LinkTo, Int)] @@ -231,7 +221,6 @@ trait ModelFactoryTypeSupport { def appendClauses = { nameBuffer append " forSome {" var first = true - val qset = quantified.toSet for (sym <- quantified) { if (!first) { nameBuffer append ", " } else first = false if (sym.isSingletonExistential) { diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala index bd7534ded4..b972649194 100755 --- a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala @@ -21,7 +21,7 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory => def makeTree(rhs: Tree): Option[TreeEntity] = { - var expr = new StringBuilder + val expr = new StringBuilder var refs = new immutable.TreeMap[Int, (Entity, Int)] // start, (Entity to be linked to , end) rhs.pos match { @@ -39,7 +39,7 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory => * stores it in tree.refs with its position */ def makeLink(rhs: Tree){ - var start = pos.startOrPoint - firstIndex + val start = pos.startOrPoint - firstIndex val end = pos.endOrPoint - firstIndex if(start != end) { var asym = rhs.symbol diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala index 3e5e634e18..8848af95eb 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala @@ -10,8 +10,6 @@ package comment import scala.collection._ -import java.net.URL - /** A body of text. A comment has a single body, which is composed of * at least one block. Inside every body is exactly one summary (see * [[scala.tools.nsc.doc.model.comment.Summary]]). */ diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala index 3e172544dd..736727fc1a 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala @@ -102,9 +102,6 @@ abstract class Comment { /** A usage example related to the entity. */ def example: List[Body] - /** The comment as it appears in the source text. */ - def source: Option[String] - /** A description for the primary constructor */ def constructor: Option[Body] diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index 40057bbb52..c798def4cb 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -8,11 +8,9 @@ package doc package model package comment -import reporters.Reporter import scala.collection._ import scala.util.matching.Regex -import scala.annotation.switch -import scala.reflect.internal.util.{NoPosition, Position} +import scala.reflect.internal.util.Position import scala.language.postfixOps /** The comment parser transforms raw comment strings into `Comment` objects. @@ -30,11 +28,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member protected val commentCache = mutable.HashMap.empty[(global.Symbol, TemplateImpl), Comment] - def addCommentBody(sym: global.Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): global.Symbol = { - commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None) - sym - } - def comment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = { val key = (sym, inTpl) if (commentCache isDefinedAt key) @@ -134,7 +127,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member val note = note0 val example = example0 val constructor = constructor0 - val source = source0 val inheritDiagram = inheritDiagram0 val contentDiagram = contentDiagram0 val groupDesc = groupDesc0 @@ -477,7 +469,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member var summaryParsed = false def document(): Body = { - nextChar() val blocks = new mutable.ListBuffer[Block] while (char != endOfText) blocks += block() @@ -559,21 +550,21 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member def code(): Block = { jumpWhitespace() jump("{{{") - readUntil("}}}") + val str = readUntil("}}}") if (char == endOfText) reportError(pos, "unclosed code block") else jump("}}}") blockEnded("code block") - Code(normalizeIndentation(getRead)) + Code(normalizeIndentation(str)) } /** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */ def title(): Block = { jumpWhitespace() - val inLevel = repeatJump("=") + val inLevel = repeatJump('=') val text = inline(check("=" * inLevel)) - val outLevel = repeatJump("=", inLevel) + val outLevel = repeatJump('=', inLevel) if (inLevel != outLevel) reportError(pos, "unbalanced or unclosed heading") blockEnded("heading") @@ -583,7 +574,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member /** {{{ hrule ::= "----" { '-' } '\n' }}} */ def hrule(): Block = { jumpWhitespace() - repeatJump("-") + repeatJump('-') blockEnded("horizontal rule") HorizontalRule() } @@ -621,8 +612,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member } do { - readUntil { char == safeTagMarker || char == endOfText } - val str = getRead() + val str = readUntil { char == safeTagMarker || char == endOfText } nextChar() list += str @@ -660,8 +650,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member else if (check(",,")) subscript() else if (check("[[")) link() else { - readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine } - Text(getRead()) + val str = readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine } + Text(str) } } @@ -698,9 +688,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member def htmlTag(): HtmlTag = { jump(safeTagMarker) - readUntil(safeTagMarker) + val read = readUntil(safeTagMarker) if (char != endOfText) jump(safeTagMarker) - var read = getRead HtmlTag(read) } @@ -762,14 +751,10 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member def link(): Inline = { val SchemeUri = """([a-z]+:.*)""".r jump("[[") - var parens = 1 - readUntil { parens += 1; !check("[") } - getRead // clear the buffer - val start = "[" * parens + val parens = 2 + repeatJump('[') val stop = "]" * parens //println("link with " + parens + " matching parens") - readUntil { check(stop) || check(" ") } - val target = getRead() + val target = readUntil { check(stop) || check(" ") } val title = if (!check(stop)) Some({ jump(" ") @@ -811,7 +796,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member */ def normalizeIndentation(_code: String): String = { - var code = _code.trim + val code = _code.trim var maxSkip = Integer.MAX_VALUE var crtSkip = 0 var wsArea = true @@ -860,7 +845,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member (char == endOfText) || ((char == endOfLine) && { val poff = offset - val pc = char nextChar() // read EOL val ok = { checkSkipInitWhitespace(endOfLine) || @@ -870,7 +854,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member checkSkipInitWhitespace('\u003D') } offset = poff - char = pc ok }) } @@ -882,40 +865,31 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member protected sealed class CharReader(buffer: String) { reader => - var char: Char = _ var offset: Int = 0 + def char: Char = + if (offset >= buffer.length) endOfText else buffer charAt offset final def nextChar() { - if (offset >= buffer.length) - char = endOfText - else { - char = buffer charAt offset - offset += 1 - } + offset += 1 } final def check(chars: String): Boolean = { val poff = offset - val pc = char val ok = jump(chars) offset = poff - char = pc ok } def checkSkipInitWhitespace(c: Char): Boolean = { val poff = offset - val pc = char jumpWhitespace() val ok = jump(c) offset = poff - char = pc ok } def checkSkipInitWhitespace(chars: String): Boolean = { val poff = offset - val pc = char jumpWhitespace() val (ok0, chars0) = if (chars.charAt(0) == ' ') @@ -924,20 +898,17 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member (true, chars) val ok = ok0 && jump(chars0) offset = poff - char = pc ok } def countWhitespace: Int = { var count = 0 val poff = offset - val pc = char while (isWhitespace(char) && char != endOfText) { nextChar() count += 1 } offset = poff - char = pc count } @@ -964,38 +935,10 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member index == chars.length } - final def checkedJump(chars: String): Boolean = { - val poff = offset - val pc = char - val ok = jump(chars) - if (!ok) { - offset = poff - char = pc - } - ok - } - - final def repeatJump(chars: String, max: Int): Int = { + final def repeatJump(c: Char, max: Int = Int.MaxValue): Int = { var count = 0 - var more = true - while (more && count < max) { - if (!checkedJump(chars)) - more = false - else - count += 1 - } - count - } - - final def repeatJump(chars: String): Int = { - var count = 0 - var more = true - while (more) { - if (!checkedJump(chars)) - more = false - else - count += 1 - } + while (jump(c) && count < max) + count += 1 count } @@ -1008,20 +951,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member count } - final def jumpUntil(chars: String): Int = { - assert(chars.length > 0) - var count = 0 - val c = chars.charAt(0) - while (!check(chars) && char != endOfText) { - nextChar() - while (char != c && char != endOfText) { - nextChar() - count += 1 - } - } - count - } - final def jumpUntil(pred: => Boolean): Int = { var count = 0 while (!pred && char != endOfText) { @@ -1035,47 +964,41 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member /* READERS */ - private val readBuilder = new mutable.StringBuilder - - final def getRead(): String = { - val bld = readBuilder.toString - readBuilder.clear() - if (bld.length < 6) bld.intern else bld - } - - final def readUntil(ch: Char): Int = { - var count = 0 - while (char != ch && char != endOfText) { - readBuilder += char - nextChar() + final def readUntil(c: Char): String = { + withRead { + while (char != c && char != endOfText) { + nextChar() + } } - count } - final def readUntil(chars: String): Int = { + final def readUntil(chars: String): String = { assert(chars.length > 0) - var count = 0 - val c = chars.charAt(0) - while (!check(chars) && char != endOfText) { - readBuilder += char - nextChar() - while (char != c && char != endOfText) { - readBuilder += char + withRead { + val c = chars.charAt(0) + while (!check(chars) && char != endOfText) { nextChar() + while (char != c && char != endOfText) + nextChar() } } - count } - final def readUntil(pred: => Boolean): Int = { - var count = 0 - while (!pred && char != endOfText) { - readBuilder += char - nextChar() + final def readUntil(pred: => Boolean): String = { + withRead { + while (char != endOfText && !pred) { + nextChar() + } } - count } + private def withRead(read: => Unit): String = { + val start = offset + read + buffer.substring(start, offset) + } + + /* CHARS CLASSES */ def isWhitespace(c: Char) = c == ' ' || c == '\t' diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala index c2aa1f17f3..150b293b81 100644 --- a/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala +++ b/src/compiler/scala/tools/nsc/doc/model/diagram/Diagram.scala @@ -36,20 +36,12 @@ case class InheritanceDiagram(thisNode: ThisNode, override def isInheritanceDiagram = true lazy val depthInfo = new DepthInfo { def maxDepth = 3 - def nodeDepth(node: Node) = - if (node == thisNode) 1 - else if (superClasses.contains(node)) 0 - else if (subClasses.contains(node)) 2 - else if (incomingImplicits.contains(node) || outgoingImplicits.contains(node)) 1 - else -1 } } trait DepthInfo { /** Gives the maximum depth */ def maxDepth: Int - /** Gives the depth of any node in the diagram or -1 if the node is not in the diagram */ - def nodeDepth(node: Node): Int } abstract class Node { @@ -142,5 +134,4 @@ class ContentDiagramDepth(pack: ContentDiagram) extends DepthInfo { } val maxDepth = _maxDepth - def nodeDepth(node: Node) = _nodeDepth.getOrElse(node, -1) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala index 49cfaffc2e..fbf6e3386b 100644 --- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala +++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala @@ -7,9 +7,6 @@ import comment.CommentFactory import java.util.regex.{Pattern, Matcher} import scala.util.matching.Regex -// statistics -import html.page.diagram.DiagramStats - /** * This trait takes care of parsing @{inheritance, content}Diagram annotations * @@ -154,7 +151,6 @@ trait DiagramDirectiveParser { private val NodeSpecRegex = "\\\"[A-Za-z\\*][A-Za-z\\.\\*]*\\\"" private val NodeSpecPattern = Pattern.compile(NodeSpecRegex) private val EdgeSpecRegex = "\\(" + NodeSpecRegex + "\\s*\\->\\s*" + NodeSpecRegex + "\\)" - private val EdgeSpecPattern = Pattern.compile(NodeSpecRegex) // And the composed regexes: private val HideNodesRegex = new Regex("^hideNodes(\\s*" + NodeSpecRegex + ")+$") private val HideEdgesRegex = new Regex("^hideEdges(\\s*" + EdgeSpecRegex + ")+$") @@ -183,7 +179,7 @@ trait DiagramDirectiveParser { def warning(message: String) = { // we need the position from the package object (well, ideally its comment, but yeah ...) val sym = if (template.sym.isPackage) template.sym.info.member(global.nme.PACKAGE) else template.sym - assert((sym != global.NoSymbol) || (sym == global.definitions.RootPackage)) + assert((sym != global.NoSymbol) || (sym == global.rootMirror.RootPackage)) global.reporter.warning(sym.pos, message) } @@ -259,4 +255,4 @@ trait DiagramDirectiveParser { result } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala index db2d0c0175..849a2ac4b3 100644 --- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala @@ -4,7 +4,6 @@ package diagram import model._ import comment.CommentFactory -import scala.collection.mutable // statistics import html.page.diagram.DiagramStats @@ -48,7 +47,7 @@ trait DiagramFactory extends DiagramDirectiveParser { val thisNode = ThisNode(tpl.resultType, Some(tpl))(Some(tpl.qualifiedName + " (this " + tpl.kind + ")")) // superclasses - var superclasses: List[Node] = + val superclasses: List[Node] = tpl.parentTypes.collect { case p: (TemplateEntity, TypeEntity) if !classExcluded(p._1) => NormalNode(p._2, Some(p._1))() }.reverse diff --git a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala index 3e7ac573e9..6b72eb12f8 100644 --- a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala @@ -7,11 +7,6 @@ package scala.tools.nsc package interactive import scala.collection._ - -import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.reflect.internal.util.FakePos - -import dependencies._ import io.AbstractFile import scala.language.implicitConversions @@ -20,9 +15,6 @@ trait BuildManager { /** Add the given source files to the managed build process. */ def addSourceFiles(files: Set[AbstractFile]) - /** Remove the given files from the managed build process. */ - def removeFiles(files: Set[AbstractFile]) - /** The given files have been modified by the user. Recompile * them and their dependent files. */ @@ -76,8 +68,6 @@ object BuildManagerTest extends EvalLoop { val settings = new Settings(buildError) settings.Ybuildmanagerdebug.value = true val command = new CompilerCommand(args.toList, settings) -// settings.make.value = "off" -// val buildManager: BuildManager = new SimpleBuildManager(settings) val buildManager: BuildManager = new RefinedBuildManager(settings) buildManager.addSourceFiles(command.files) diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index b4af8f00d6..f3cd41f32f 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -7,8 +7,6 @@ package interactive import scala.util.control.ControlThrowable import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.symtab._ -import scala.tools.nsc.ast._ import scala.tools.nsc.util.FailedInterrupt import scala.tools.nsc.util.EmptyAction import scala.tools.nsc.util.WorkScheduler diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala index b2568e34bd..93ef4c4d6c 100644 --- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package interactive import scala.collection.mutable.ArrayBuffer -import scala.reflect.internal.util.Position trait ContextTrees { self: Global => diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 2ab389445f..e4bff1e192 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -8,17 +8,13 @@ package interactive import java.io.{ PrintWriter, StringWriter, FileReader, FileWriter } import scala.collection.mutable import mutable.{LinkedHashMap, SynchronizedMap, HashSet, SynchronizedSet} -import scala.concurrent.SyncVar import scala.util.control.ControlThrowable import scala.tools.nsc.io.{ AbstractFile, LogReplay, Logger, NullLogger, Replayer } -import scala.tools.nsc.util.{ WorkScheduler, MultiHashMap } +import scala.tools.nsc.util.MultiHashMap import scala.reflect.internal.util.{ SourceFile, BatchSourceFile, Position, RangePosition, NoPosition } import scala.tools.nsc.reporters._ import scala.tools.nsc.symtab._ -import scala.tools.nsc.ast._ -import scala.tools.nsc.io.Pickler._ import scala.tools.nsc.typechecker.DivergentImplicit -import scala.annotation.tailrec import symtab.Flags.{ACCESSOR, PARAMACCESSOR} import scala.annotation.elidable import scala.language.implicitConversions @@ -361,7 +357,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } // don't forget to service interrupt requests - val iqs = scheduler.dequeueAllInterrupts(_.execute()) + scheduler.dequeueAllInterrupts(_.execute()) debugLog("ShutdownReq: cleaning work queue (%d items)".format(units.size)) debugLog("Cleanup up responses (%d loadedType pending, %d parsedEntered pending)" @@ -399,41 +395,6 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") if (typerRun != currentTyperRun) demandNewCompilerRun() } - def debugInfo(source : SourceFile, start : Int, length : Int): String = { - println("DEBUG INFO "+source+"/"+start+"/"+length) - val end = start+length - val pos = rangePos(source, start, start, end) - - val tree = locateTree(pos) - val sw = new StringWriter - val pw = new PrintWriter(sw) - newTreePrinter(pw).print(tree) - pw.flush - - val typed = new Response[Tree] - askTypeAt(pos, typed) - val typ = typed.get.left.toOption match { - case Some(tree) => - val sw = new StringWriter - val pw = new PrintWriter(sw) - newTreePrinter(pw).print(tree) - pw.flush - sw.toString - case None => "<None>" - } - - val completionResponse = new Response[List[Member]] - askTypeCompletion(pos, completionResponse) - val completion = completionResponse.get.left.toOption match { - case Some(members) => - members mkString "\n" - case None => "<None>" - } - - source.content.view.drop(start).take(length).mkString+" : "+source.path+" ("+start+", "+end+ - ")\n\nlocateTree:\n"+sw.toString+"\n\naskTypeAt:\n"+typ+"\n\ncompletion:\n"+completion - } - // ----------------- The Background Runner Thread ----------------------- private var threadId = 0 @@ -1059,7 +1020,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") - def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) = + def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) { try { interruptsEnabled = false respond(response) { @@ -1068,6 +1029,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } finally { interruptsEnabled = true } + } // ---------------- Helper classes --------------------------- @@ -1099,7 +1061,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") * @return true iff typechecked correctly */ private def applyPhase(phase: Phase, unit: CompilationUnit) { - atPhase(phase) { phase.asInstanceOf[GlobalPhase] applyPhase unit } + enteringPhase(phase) { phase.asInstanceOf[GlobalPhase] applyPhase unit } } } diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index ffad19fbaa..1dc891b984 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -6,12 +6,10 @@ package scala.tools.nsc package interactive import util.InterruptReq -import scala.reflect.internal.util.{SourceFile, BatchSourceFile} -import io.{AbstractFile, PlainFile} - +import scala.reflect.internal.util.{ SourceFile, BatchSourceFile } +import io.{ AbstractFile, PlainFile, Pickler, CondPickler } import util.EmptyAction -import scala.reflect.internal.util.{Position, RangePosition, NoPosition, OffsetPosition, TransparentPosition} -import io.{Pickler, CondPickler} +import scala.reflect.internal.util.{ RangePosition, OffsetPosition, TransparentPosition } import io.Pickler._ import scala.collection.mutable import mutable.ListBuffer diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala index dacfa679dd..d1a29aeb07 100644 --- a/src/compiler/scala/tools/nsc/interactive/REPL.scala +++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala @@ -5,15 +5,11 @@ package scala.tools.nsc package interactive -import scala.concurrent.SyncVar import scala.reflect.internal.util._ -import scala.tools.nsc.symtab._ -import scala.tools.nsc.ast._ import scala.tools.nsc.reporters._ import scala.tools.nsc.io._ import scala.tools.nsc.scratchpad.SourceInserter -import scala.tools.nsc.interpreter.AbstractFileClassLoader -import java.io.{File, FileWriter} +import java.io.FileWriter /** Interface of interactive compiler to a client such as an IDE */ diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index b95f1fa7ca..ecaa793da7 100644 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -8,7 +8,6 @@ package interactive import ast.Trees import ast.Positions import scala.reflect.internal.util.{SourceFile, Position, RangePosition, NoPosition} -import scala.tools.nsc.util.WorkScheduler import scala.collection.mutable.ListBuffer /** Handling range positions @@ -60,7 +59,7 @@ self: scala.tools.nsc.Global => } // -------------- ensuring no overlaps ------------------------------- - + /** Ensure that given tree has no positions that overlap with * any of the positions of `others`. This is done by * shortening the range, assigning TransparentPositions diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala index b2ef45a7d8..9873276f05 100644 --- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala @@ -12,7 +12,6 @@ import scala.util.control.Breaks._ import scala.tools.nsc.symtab.Flags import dependencies._ -import scala.reflect.internal.util.FakePos import util.ClassPath import io.AbstractFile import scala.tools.util.PathResolver @@ -49,7 +48,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana protected def newCompiler(settings: Settings) = new BuilderGlobal(settings) val compiler = newCompiler(settings) - import compiler.{ Symbol, Type, beforeErasure } + import compiler.{ Symbol, Type, enteringErasure } import compiler.dependencyAnalysis.Inherited private case class SymWithHistory(sym: Symbol, befErasure: Type) @@ -69,7 +68,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana private var inherited: mutable.Map[AbstractFile, immutable.Set[Inherited]] = _ /** Reverse of definitions, used for caching */ - private var classes: mutable.Map[String, AbstractFile] = + private val classes: mutable.Map[String, AbstractFile] = new mutable.HashMap[String, AbstractFile] { override def default(key: String) = null } @@ -161,7 +160,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana isCorrespondingSym(s.sym, sym)) match { case Some(SymWithHistory(oldSym, info)) => val changes = changeSet(oldSym.info, sym) - val changesErasure = beforeErasure(changeSet(info, sym)) + val changesErasure = enteringErasure(changeSet(info, sym)) changesOf(oldSym) = (changes ++ changesErasure).distinct case _ => @@ -332,7 +331,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana for (src <- files; localDefs = compiler.dependencyAnalysis.definitions(src)) { definitions(src) = (localDefs map (s => { this.classes += s.fullName -> src - SymWithHistory(s.cloneSymbol, beforeErasure(s.info.cloneInfo(s))) + SymWithHistory(s.cloneSymbol, enteringErasure(s.info.cloneInfo(s))) })) } this.references = compiler.dependencyAnalysis.references diff --git a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala index 465dcaaf1c..ff25dac7ac 100644 --- a/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/SimpleBuildManager.scala @@ -8,9 +8,6 @@ package interactive import scala.collection._ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import dependencies._ - -import scala.reflect.internal.util.FakePos import io.AbstractFile /** A simple build manager, using the default scalac dependency tracker. diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala index 62d274bc70..f2614bcc42 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala @@ -7,14 +7,6 @@ package interactive package tests import core._ - -import java.io.File.pathSeparatorChar -import java.io.File.separatorChar - -import scala.annotation.migration -import scala.reflect.internal.util.Position -import scala.reflect.internal.util.SourceFile - import scala.collection.mutable.ListBuffer /** A base class for writing interactive compiler tests. @@ -110,6 +102,7 @@ abstract class InteractiveTest } /** Perform n random tests with random changes. */ + /**** private def randomTests(n: Int, files: Array[SourceFile]) { val tester = new Tester(n, files, settings) { override val compiler = self.compiler @@ -117,6 +110,7 @@ abstract class InteractiveTest } tester.run() } + ****/ /** shutdown the presentation compiler. */ protected def shutdown() { diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala index 4d85ab9d88..ad5c61b2b0 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTestSettings.scala @@ -25,7 +25,6 @@ trait InteractiveTestSettings extends TestSettings with PresentationCompilerInst * test. */ override protected def prepareSettings(settings: Settings) { - import java.io.File._ def adjustPaths(paths: settings.PathSetting*) { for (p <- paths if argsString.contains(p.name)) p.value = p.value.map { case '/' => separatorChar @@ -45,10 +44,10 @@ trait InteractiveTestSettings extends TestSettings with PresentationCompilerInst case _ => () } - // Make the --sourcepath path provided in the .flags file (if any) relative to the test's base directory + // Make the --sourcepath path provided in the .flags file (if any) relative to the test's base directory if(settings.sourcepath.isSetByUser) settings.sourcepath.value = (baseDir / Path(settings.sourcepath.value)).path - + adjustPaths(settings.bootclasspath, settings.classpath, settings.javabootclasspath, settings.sourcepath) } @@ -67,4 +66,4 @@ trait InteractiveTestSettings extends TestSettings with PresentationCompilerInst reporter.println("\targsString: %s".format(argsString)) super.printClassPath(reporter) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala index c8e6b6ccce..9085eb56e6 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala @@ -3,7 +3,6 @@ package interactive package tests.core import scala.reflect.internal.util.Position -import scala.tools.nsc.interactive.tests.core._ /** Set of core test definitions that are executed for each test run. */ private[tests] trait CoreTestDefs @@ -77,7 +76,8 @@ private[tests] trait CoreTestDefs // askHyperlinkPos for `Int` at (73,19) pi.scala --> class Int in package scala has null sourceFile! val treePath = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.path else null val treeName = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.name else null - val sourceFile = sourceFiles.find(_.path == treePath) match { + + sourceFiles.find(_.path == treePath) match { case Some(source) => compiler.askLinkPos(tree.symbol, source, r) r.get match { @@ -97,4 +97,4 @@ private[tests] trait CoreTestDefs } } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala index 5c1837b3bf..b3f80168ff 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala @@ -3,7 +3,6 @@ package interactive package tests.core import reporters.{Reporter => CompilerReporter} -import scala.reflect.internal.util.Position /** Trait encapsulating the creation of a presentation compiler's instance.*/ private[tests] trait PresentationCompilerInstance extends TestSettings { @@ -28,4 +27,4 @@ private[tests] trait PresentationCompilerInstance extends TestSettings { reporter.println("\tbootClassPath: %s".format(settings.bootclasspath.value)) reporter.println("\tverbose: %b".format(settings.verbose.value)) } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala index 9cf2aa4fe4..4d5b4e1129 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala @@ -1,6 +1,5 @@ package scala.tools.nsc.interactive.tests.core -import scala.tools.nsc.interactive.Global import scala.reflect.internal.util.Position trait PresentationCompilerTestDef { @@ -16,4 +15,4 @@ trait PresentationCompilerTestDef { protected def format(pos: Position): String = (if(pos.isDefined) "(%d,%d)".format(pos.line, pos.column) else "<no position>") -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala index e80b741a8d..676feeba8a 100644 --- a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala +++ b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala @@ -4,7 +4,6 @@ import scala.reflect.internal.util.{SourceFile,BatchSourceFile} import scala.tools.nsc.io.{AbstractFile,Path} private[tests] object SourcesCollector { - import Path._ type SourceFilter = Path => Boolean /** @@ -17,6 +16,5 @@ private[tests] object SourcesCollector { } private def source(file: Path): SourceFile = source(AbstractFile.getFile(file.toFile)) - private def source(filename: String): SourceFile = source(AbstractFile.getFile(filename)) private def source(file: AbstractFile): SourceFile = new BatchSourceFile(file) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala index 638bca8a72..fcb485defd 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala @@ -5,7 +5,7 @@ package scala.tools.nsc package interpreter -import scala.tools.nsc.io.{ File, AbstractFile } +import scala.tools.nsc.io.AbstractFile import util.ScalaClassLoader import java.net.URL import scala.collection.{ mutable, immutable } diff --git a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala index 40e9d3d600..48890a21c6 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package interpreter import java.lang.reflect -import java.util.concurrent.ConcurrentHashMap import util.ScalaClassLoader import ScalaClassLoader.appLoader import scala.reflect.NameTransformer._ @@ -39,25 +38,5 @@ object ByteCode { } yield names - /** Attempts to retrieve case parameter names for given class name. - */ - def caseParamNamesForPath(path: String) = - for { - module <- DECODER - method <- decoderMethod("caseParamNames", classOf[String]) - names <- method.invoke(module, path).asInstanceOf[Option[List[String]]] - } - yield names - def aliasesForPackage(pkg: String) = aliasMap flatMap (_(pkg)) - - /** Attempts to find type aliases in package objects. - */ - def aliasForType(path: String): Option[String] = { - val (pkg, name) = (path lastIndexOf '.') match { - case -1 => return None - case idx => (path take idx, path drop (idx + 1)) - } - aliasesForPackage(pkg) flatMap (_ get name) - } } diff --git a/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala deleted file mode 100644 index 1741a82775..0000000000 --- a/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala +++ /dev/null @@ -1,50 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package interpreter - -import CodeHandlers.NoSuccess -import scala.util.control.ControlThrowable - -/** - * The start of a simpler interface for utilizing the compiler with piecemeal - * code strings. The "T" here could potentially be a Tree, a Type, a Symbol, - * a Boolean, or something even more exotic. - */ -trait CodeHandlers[T] { - self => - - // Expressions are composed of operators and operands. - def expr(code: String): T - - // Statements occur as parts of blocks and templates. - // A statement can be an import, a definition or an expression, or it can be empty. - // Statements used in the template of a class definition can also be declarations. - def stmt(code: String): T - def stmts(code: String): Seq[T] - - object opt extends CodeHandlers[Option[T]] { - val handler: PartialFunction[Throwable, Option[T]] = { - case _: NoSuccess => None - } - val handlerSeq: PartialFunction[Throwable, Seq[Option[T]]] = { - case _: NoSuccess => Nil - } - - def expr(code: String) = try Some(self.expr(code)) catch handler - def stmt(code: String) = try Some(self.stmt(code)) catch handler - def stmts(code: String) = try (self.stmts(code) map (x => Some(x))) catch handlerSeq - } -} - -object CodeHandlers { - def incomplete() = throw CodeIncomplete - def fail(msg: String) = throw new CodeException(msg) - - trait NoSuccess extends ControlThrowable - class CodeException(msg: String) extends RuntimeException(msg) with NoSuccess { } - object CodeIncomplete extends CodeException("CodeIncomplete") -} diff --git a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala b/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala index 8042f0aee2..0ab92ab769 100644 --- a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala +++ b/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala @@ -10,5 +10,4 @@ package interpreter */ class CommandLine(arguments: List[String], error: String => Unit) extends CompilerCommand(arguments, error) { override def cmdName = "scala" - override lazy val fileEndings = List(".scalaint") } diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala index 1dfccbfbf7..84a5cb49ae 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala @@ -23,8 +23,6 @@ object NoCompletion extends Completion { } object Completion { - def empty: Completion = NoCompletion - case class Candidates(cursor: Int, candidates: List[String]) { } val NoCandidates = Candidates(-1, Nil) diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala index ab96f415db..3dd5d93390 100644 --- a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala +++ b/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package interpreter -import scala.reflect.NameTransformer - /** An interface for objects which are aware of tab completion and * will supply their own candidates and resolve their own paths. */ @@ -53,31 +51,3 @@ trait CompletionAware { results.sorted } } - -object CompletionAware { - val Empty = new CompletionAware { def completions(verbosity: Int) = Nil } - - def unapply(that: Any): Option[CompletionAware] = that match { - case x: CompletionAware => Some((x)) - case _ => None - } - - /** Create a CompletionAware object from the given functions. - * The first should generate the list of completions whenever queried, - * and the second should return Some(CompletionAware) object if - * subcompletions are possible. - */ - def apply(terms: () => List[String], followFunction: String => Option[CompletionAware]): CompletionAware = - new CompletionAware { - def completions = terms() - def completions(verbosity: Int) = completions - override def follow(id: String) = followFunction(id) - } - - /** Convenience factories. - */ - def apply(terms: () => List[String]): CompletionAware = apply(terms, _ => None) - def apply(map: scala.collection.Map[String, CompletionAware]): CompletionAware = - apply(() => map.keys.toList, map.get _) -} - diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala index 13880bb8af..c647ef6f51 100644 --- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala +++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala @@ -38,7 +38,6 @@ trait CompletionOutput { def relativize(str: String): String = quietString(str stripPrefix (pkg + ".")) def relativize(tp: Type): String = relativize(tp.normalize.toString) - def relativize(sym: Symbol): String = relativize(sym.info) def braceList(tparams: List[String]) = if (tparams.isEmpty) "" else (tparams map relativize).mkString("[", ", ", "]") def parenList(params: List[Any]) = params.mkString("(", ", ", ")") diff --git a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala index 07e36f4f27..48af261937 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala @@ -7,19 +7,12 @@ package scala.tools.nsc package interpreter import scala.tools.jline.console.{ ConsoleReader, CursorBuffer } -import scala.tools.jline.console.completer.CompletionHandler -import Completion._ trait ConsoleReaderHelper extends ConsoleReader { - def currentLine = "" + getCursorBuffer.buffer - def currentPos = getCursorBuffer.cursor def terminal = getTerminal() def width = terminal.getWidth() def height = terminal.getHeight() - def paginate = isPaginationEnabled() - def paginate_=(value: Boolean) = setPaginationEnabled(value) - def goBack(num: Int): Unit def readOneKey(prompt: String): Int def eraseLine(): Unit diff --git a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala b/src/compiler/scala/tools/nsc/interpreter/Delimited.scala index 80debfacb9..e88a044931 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Delimited.scala @@ -26,7 +26,6 @@ trait Delimited { def delimited: Char => Boolean def escapeChars: List[Char] = List('\\') - def quoteChars: List[(Char, Char)] = List(('\'', '\''), ('"', '"')) /** Break String into args based on delimiting function. */ @@ -39,6 +38,4 @@ trait Delimited { def isDelimiterChar(ch: Char) = delimited(ch) def isEscapeChar(ch: Char): Boolean = escapeChars contains ch - def isQuoteStart(ch: Char): Boolean = quoteChars map (_._1) contains ch - def isQuoteEnd(ch: Char): Boolean = quoteChars map (_._2) contains ch } diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala index c4a672ac37..b087547cf8 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package interpreter -import scala.reflect.internal.util.BatchSourceFile import scala.tools.nsc.ast.parser.Tokens.EOF trait ExprTyper { @@ -15,10 +14,11 @@ trait ExprTyper { import repl._ import global.{ reporter => _, Import => _, _ } import definitions._ - import syntaxAnalyzer.{ UnitParser, UnitScanner, token2name } + import syntaxAnalyzer.UnitParser import naming.freshInternalVarName - object codeParser extends { val global: repl.global.type = repl.global } with CodeHandlers[Tree] { + object codeParser { + val global: repl.global.type = repl.global def applyRule[T](code: String, rule: UnitParser => T): T = { reporter.reset() val scanner = newUnitParser(code) @@ -29,11 +29,7 @@ trait ExprTyper { result } - - def defns(code: String) = stmts(code) collect { case x: DefTree => x } - def expr(code: String) = applyRule(code, _.expr()) def stmts(code: String) = applyRule(code, _.templateStats()) - def stmt(code: String) = stmts(code).last // guaranteed nonempty } /** Parse a line into a sequence of trees. Returns None if the input is incomplete. */ @@ -46,10 +42,6 @@ trait ExprTyper { else Some(trees) } } - // def parsesAsExpr(line: String) = { - // import codeParser._ - // (opt expr line).isDefined - // } def symbolOfLine(code: String): Symbol = { def asExpr(): Symbol = { @@ -63,7 +55,7 @@ trait ExprTyper { case IR.Success => val sym0 = symbolOfTerm(name) // drop NullaryMethodType - val sym = sym0.cloneSymbol setInfo afterTyper(sym0.info.finalResultType) + val sym = sym0.cloneSymbol setInfo exitingTyper(sym0.info.finalResultType) if (sym.info.typeSymbol eq UnitClass) NoSymbol else sym case _ => NoSymbol diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index b7e07ecdd6..612a90f3ea 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -8,24 +8,20 @@ package interpreter import Predef.{ println => _, _ } import java.io.{ BufferedReader, FileReader } -import java.util.concurrent.locks.ReentrantLock -import scala.sys.process.Process import session._ -import scala.util.Properties.{ jdkHome, javaVersion } -import scala.tools.util.{ Javap } import scala.annotation.tailrec -import scala.collection.mutable.ListBuffer -import scala.concurrent.ops +import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName } +import scala.tools.util.{ Javap } import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } -import interpreter._ import io.{ File, Directory } -import scala.reflect.NameTransformer._ import util.ScalaClassLoader import ScalaClassLoader._ import scala.tools.util._ import scala.language.{implicitConversions, existentials} -import scala.reflect.{ClassTag, classTag} +import scala.reflect.classTag import scala.tools.reflect.StdRuntimeTags._ +import scala.concurrent.{ ExecutionContext, Await, Future, future } +import ExecutionContext.Implicits._ /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -42,77 +38,41 @@ import scala.tools.reflect.StdRuntimeTags._ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) extends AnyRef with LoopCommands - with ILoopInit { def this(in0: BufferedReader, out: JPrintWriter) = this(Some(in0), out) def this() = this(None, new JPrintWriter(Console.out, true)) - var in: InteractiveReader = _ // the input stream from which commands come - var settings: Settings = _ - var intp: IMain = _ - @deprecated("Use `intp` instead.", "2.9.0") def interpreter = intp @deprecated("Use `intp` instead.", "2.9.0") def interpreter_= (i: Interpreter): Unit = intp = i - /** Having inherited the difficult "var-ness" of the repl instance, - * I'm trying to work around it by moving operations into a class from - * which it will appear a stable prefix. - */ - private def onIntp[T](f: IMain => T): T = f(intp) - - class IMainOps[T <: IMain](val intp: T) { - import intp._ - import global._ - - def printAfterTyper(msg: => String) = - intp.reporter printUntruncatedMessage afterTyper(msg) - - /** Strip NullaryMethodType artifacts. */ - private def replInfo(sym: Symbol) = { - sym.info match { - case NullaryMethodType(restpe) if sym.isAccessor => restpe - case info => info - } - } - def echoTypeStructure(sym: Symbol) = - printAfterTyper("" + deconstruct.show(replInfo(sym))) + var in: InteractiveReader = _ // the input stream from which commands come + var settings: Settings = _ + var intp: IMain = _ - def echoTypeSignature(sym: Symbol, verbose: Boolean) = { - if (verbose) ILoop.this.echo("// Type signature") - printAfterTyper("" + replInfo(sym)) + private var globalFuture: Future[Boolean] = _ - if (verbose) { - ILoop.this.echo("\n// Internal Type structure") - echoTypeStructure(sym) - } - } + /** Print a welcome message */ + def printWelcome() { + echo(s""" + |Welcome to Scala $versionString ($javaVmName, Java $javaVersion). + |Type in expressions to have them evaluated. + |Type :help for more information.""".trim.stripMargin + ) + replinfo("[info] started at " + new java.util.Date) } - implicit def stabilizeIMain(intp: IMain) = new IMainOps[intp.type](intp) - /** TODO - - * -n normalize - * -l label with case class parameter names - * -c complete - leave nothing out - */ - private def typeCommandInternal(expr: String, verbose: Boolean): Result = { - onIntp { intp => - val sym = intp.symbolOfLine(expr) - if (sym.exists) intp.echoTypeSignature(sym, verbose) - else "" - } + protected def asyncMessage(msg: String) { + if (isReplInfo || isReplPower) + echoAndRefresh(msg) } override def echoCommandMessage(msg: String) { intp.reporter printUntruncatedMessage msg } - def isAsync = !settings.Yreplsync.value lazy val power = new Power(intp, new StdReplVals(this))(tagOfStdReplVals, classTag[StdReplVals]) def history = in.history - /** The context class loader at the time this object was created */ - protected val originalClassLoader = Thread.currentThread.getContextClassLoader - // classpath entries added via :cp var addedClasspath: String = "" @@ -166,20 +126,18 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) def helpCommand(line: String): Result = { if (line == "") helpSummary() else uniqueCommand(line) match { - case Some(lc) => echo("\n" + lc.longHelp) + case Some(lc) => echo("\n" + lc.help) case _ => ambiguousError(line) } } private def helpSummary() = { val usageWidth = commands map (_.usageMsg.length) max - val formatStr = "%-" + usageWidth + "s %s %s" + val formatStr = "%-" + usageWidth + "s %s" echo("All commands can be abbreviated, e.g. :he instead of :help.") - echo("Those marked with a * have more detailed help, e.g. :help imports.\n") commands foreach { cmd => - val star = if (cmd.hasLongHelp) "*" else " " - echo(formatStr.format(cmd.usageMsg, star, cmd.help)) + echo(formatStr.format(cmd.usageMsg, cmd.help)) } } private def ambiguousError(cmd: String): Result = { @@ -229,10 +187,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) out println msg out.flush() } - protected def echoNoNL(msg: String) = { - out print msg - out.flush() - } /** Search the history */ def searchHistory(_cmdline: String) { @@ -243,8 +197,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) echo("%d %s".format(index + offset, line)) } - private var currentPrompt = Properties.shellPromptString - def setPrompt(prompt: String) = currentPrompt = prompt + private val currentPrompt = Properties.shellPromptString + /** Prompt to print when awaiting input */ def prompt = currentPrompt @@ -257,7 +211,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) historyCommand, cmd("h?", "<string>", "search the history", searchHistory), cmd("imports", "[name name ...]", "show import history, identifying sources of names", importsCommand), - cmd("implicits", "[-v]", "show the implicits in scope", implicitsCommand), + cmd("implicits", "[-v]", "show the implicits in scope", intp.implicitsCommand), cmd("javap", "<path|class>", "disassemble a file or class name", javapCommand), cmd("load", "<path>", "load and interpret a Scala file", loadCommand), nullary("paste", "enter paste mode: all input up to ctrl-D compiled together", pasteCommand), @@ -276,25 +230,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) cmd("phase", "<phase>", "set the implicit phase for power commands", phaseCommand) ) - private def dumpCommand(): Result = { - echo("" + power) - history.asStrings takeRight 30 foreach echo - in.redrawLine() - } - private def valsCommand(): Result = power.valsDescription - - private val typeTransforms = List( - "scala.collection.immutable." -> "immutable.", - "scala.collection.mutable." -> "mutable.", - "scala.collection.generic." -> "generic.", - "java.lang." -> "jl.", - "scala.runtime." -> "runtime." - ) - private def importsCommand(line: String): Result = { val tokens = words(line) val handlers = intp.languageWildcardHandlers ++ intp.importHandlers - val isVerbose = tokens contains "-v" handlers.filterNot(_.importedSymbols.isEmpty).zipWithIndex foreach { case (handler, idx) => @@ -316,63 +254,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - private def implicitsCommand(line: String): Result = onIntp { intp => - import intp._ - import global._ - - def p(x: Any) = intp.reporter.printMessage("" + x) - - // If an argument is given, only show a source with that - // in its name somewhere. - val args = line split "\\s+" - val filtered = intp.implicitSymbolsBySource filter { - case (source, syms) => - (args contains "-v") || { - if (line == "") (source.fullName.toString != "scala.Predef") - else (args exists (source.name.toString contains _)) - } - } - - if (filtered.isEmpty) - return "No implicits have been imported other than those in Predef." - - filtered foreach { - case (source, syms) => - p("/* " + syms.size + " implicit members imported from " + source.fullName + " */") - - // This groups the members by where the symbol is defined - val byOwner = syms groupBy (_.owner) - val sortedOwners = byOwner.toList sortBy { case (owner, _) => afterTyper(source.info.baseClasses indexOf owner) } - - sortedOwners foreach { - case (owner, members) => - // Within each owner, we cluster results based on the final result type - // if there are more than a couple, and sort each cluster based on name. - // This is really just trying to make the 100 or so implicits imported - // by default into something readable. - val memberGroups: List[List[Symbol]] = { - val groups = members groupBy (_.tpe.finalResultType) toList - val (big, small) = groups partition (_._2.size > 3) - val xss = ( - (big sortBy (_._1.toString) map (_._2)) :+ - (small flatMap (_._2)) - ) - - xss map (xs => xs sortBy (_.name.toString)) - } - - val ownerMessage = if (owner == source) " defined in " else " inherited from " - p(" /* " + members.size + ownerMessage + owner.fullName + " */") - - memberGroups foreach { group => - group foreach (s => p(" " + intp.symbolDefString(s))) - p("") - } - } - p("") - } - } - private def findToolsJar() = { val jdkPath = Directory(jdkHome) val jar = jdkPath / "lib" / "tools.jar" toFile; @@ -398,32 +279,12 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - protected def newJavap() = new JavapClass(addToolsJarToLoader(), new IMain.ReplStrippingWriter(intp)) { - override def tryClass(path: String): Array[Byte] = { - val hd :: rest = path split '.' toList; - // If there are dots in the name, the first segment is the - // key to finding it. - if (rest.nonEmpty) { - intp optFlatName hd match { - case Some(flat) => - val clazz = flat :: rest mkString NAME_JOIN_STRING - val bytes = super.tryClass(clazz) - if (bytes.nonEmpty) bytes - else super.tryClass(clazz + MODULE_SUFFIX_STRING) - case _ => super.tryClass(path) - } - } - else { - // Look for Foo first, then Foo$, but if Foo$ is given explicitly, - // we have to drop the $ to find object Foo, then tack it back onto - // the end of the flattened name. - def className = intp flatName path - def moduleName = (intp flatName path.stripSuffix(MODULE_SUFFIX_STRING)) + MODULE_SUFFIX_STRING - - val bytes = super.tryClass(className) - if (bytes.nonEmpty) bytes - else super.tryClass(moduleName) - } + protected def newJavap() = { + val intp = ILoop.this.intp + import intp._ + + new JavapClass(addToolsJarToLoader(), new IMain.ReplStrippingWriter(intp)) { + override def tryClass(path: String) = super.tryClass(translatePath(path) getOrElse path) } } private lazy val javap = substituteAndLog[Javap]("javap", NoJavap)(newJavap()) @@ -432,8 +293,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) private def typeCommand(line0: String): Result = { line0.trim match { case "" => ":type [-v] <expression>" - case s if s startsWith "-v " => typeCommandInternal(s stripPrefix "-v " trim, true) - case s => typeCommandInternal(s, false) + case s if s startsWith "-v " => intp.typeCommandInternal(s stripPrefix "-v " trim, true) + case s => intp.typeCommandInternal(s, false) } } @@ -458,37 +319,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - private def wrapCommand(line: String): Result = { - def failMsg = "Argument to :wrap must be the name of a method with signature [T](=> T): T" - onIntp { intp => - import intp._ - import global._ + private def pathToPhaseWrapper = intp.originalPath("$r") + ".phased.atCurrent" - words(line) match { - case Nil => - intp.executionWrapper match { - case "" => "No execution wrapper is set." - case s => "Current execution wrapper: " + s - } - case "clear" :: Nil => - intp.executionWrapper match { - case "" => "No execution wrapper is set." - case s => intp.clearExecutionWrapper() ; "Cleared execution wrapper." - } - case wrapper :: Nil => - intp.typeOfExpression(wrapper) match { - case PolyType(List(targ), MethodType(List(arg), restpe)) => - intp setExecutionWrapper intp.pathToTerm(wrapper) - "Set wrapper to '" + wrapper + "'" - case tp => - failMsg + "\nFound: <unknown>" - } - case _ => failMsg - } - } - } - - private def pathToPhaseWrapper = intp.pathToTerm("$r") + ".phased.atCurrent" private def phaseCommand(name: String): Result = { val phased: Phased = power.phased import phased.NoPhaseName @@ -547,33 +379,30 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) true } + // return false if repl should exit + def processLine(line: String): Boolean = { + import scala.concurrent.duration._ + Await.ready(globalFuture, 60.seconds) + + (line ne null) && (command(line) match { + case Result(false, _) => false + case Result(_, Some(line)) => addReplay(line) ; true + case _ => true + }) + } + + private def readOneLine() = { + out.flush() + in readLine prompt + } + /** The main read-eval-print loop for the repl. It calls * command() for each line of input, and stops when * command() returns false. */ - def loop() { - def readOneLine() = { - out.flush() - in readLine prompt - } - // return false if repl should exit - def processLine(line: String): Boolean = { - if (isAsync) { - if (!awaitInitialized()) return false - runThunks() - } - if (line eq null) false // assume null means EOF - else command(line) match { - case Result(false, _) => false - case Result(_, Some(finalLine)) => addReplay(finalLine) ; true - case _ => true - } - } - def innerLoop() { - if ( try processLine(readOneLine()) catch crashRecovery ) - innerLoop() - } - innerLoop() + @tailrec final def loop() { + if ( try processLine(readOneLine()) catch crashRecovery ) + loop() } /** interpret all lines from a specified file */ @@ -819,48 +648,39 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) SimpleReader() } } - def process(settings: Settings): Boolean = savingContextLoader { - this.settings = settings - createInterpreter() - // sets in to some kind of reader depending on environmental cues - in = in0 match { - case Some(reader) => SimpleReader(reader, out, true) - case None => - // some post-initialization - chooseReader(settings) match { - case x: JLineReader => addThunk(x.consoleReader.postInit) ; x - case x => x - } + private def loopPostInit() { + in match { + case x: JLineReader => x.consoleReader.postInit + case _ => } // Bind intp somewhere out of the regular namespace where // we can get at it in generated code. - addThunk(intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain]))) - addThunk({ - import scala.tools.nsc.io._ - import Properties.userHome - import scala.compat.Platform.EOL - val autorun = replProps.replAutorunCode.option flatMap (f => io.File(f).safeSlurp()) - if (autorun.isDefined) intp.quietRun(autorun.get) - }) - - loadFiles(settings) - // it is broken on startup; go ahead and exit - if (intp.reporter.hasErrors) - return false - - // This is about the illusion of snappiness. We call initialize() - // which spins off a separate thread, then print the prompt and try - // our best to look ready. The interlocking lazy vals tend to - // inter-deadlock, so we break the cycle with a single asynchronous - // message to an actor. - if (isAsync) { - intp initialize initializedCallback() - createAsyncListener() // listens for signal to run postInitialization + intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain])) + // Auto-run code via some setting. + ( replProps.replAutorunCode.option + flatMap (f => io.File(f).safeSlurp()) + foreach (intp quietRun _) + ) + // classloader and power mode setup + intp.setContextClassLoader + if (isReplPower) { + replProps.power setValue true + unleashAndSetPhase() + asyncMessage(power.banner) } - else { + } + def process(settings: Settings): Boolean = savingContextLoader { + this.settings = settings + createInterpreter() + + // sets in to some kind of reader depending on environmental cues + in = in0.fold(chooseReader(settings))(r => SimpleReader(r, out, true)) + globalFuture = future { intp.initializeSynchronous() - postInitialization() + loopPostInit() + loadFiles(settings) + !intp.reporter.hasErrors } printWelcome() @@ -871,27 +691,12 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) true } - /** process command-line arguments and do as they request */ - def process(args: Array[String]): Boolean = { - val command = new CommandLine(args.toList, echo) - def neededHelp(): String = - (if (command.settings.help.value) command.usageMsg + "\n" else "") + - (if (command.settings.Xhelp.value) command.xusageMsg + "\n" else "") - - // if they asked for no help and command is valid, we call the real main - neededHelp() match { - case "" => command.ok && process(command.settings) - case help => echoNoNL(help) ; true - } - } - @deprecated("Use `process` instead", "2.9.0") - def main(settings: Settings): Unit = process(settings) + def main(settings: Settings): Unit = process(settings) //used by sbt } object ILoop { implicit def loopToInterpreter(repl: ILoop): IMain = repl.intp - private def echo(msg: String) = Console println msg // Designed primarily for use by test code: take a String with a // bunch of code, and prints out a transcript of what it would look diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala deleted file mode 100644 index e3c0494fa3..0000000000 --- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala +++ /dev/null @@ -1,125 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package interpreter - -import scala.reflect.internal.util.Position -import scala.util.control.Exception.ignoring -import scala.tools.nsc.util.stackTraceString - -/** - * Machinery for the asynchronous initialization of the repl. - */ -trait ILoopInit { - self: ILoop => - - /** Print a welcome message */ - def printWelcome() { - import Properties._ - val welcomeMsg = - """|Welcome to Scala %s (%s, Java %s). - |Type in expressions to have them evaluated. - |Type :help for more information.""" . - stripMargin.format(versionString, javaVmName, javaVersion) - echo(welcomeMsg) - replinfo("[info] started at " + new java.util.Date) - } - - protected def asyncMessage(msg: String) { - if (isReplInfo || isReplPower) - echoAndRefresh(msg) - } - - private val initLock = new java.util.concurrent.locks.ReentrantLock() - private val initCompilerCondition = initLock.newCondition() // signal the compiler is initialized - private val initLoopCondition = initLock.newCondition() // signal the whole repl is initialized - private val initStart = System.nanoTime - - private def withLock[T](body: => T): T = { - initLock.lock() - try body - finally initLock.unlock() - } - // a condition used to ensure serial access to the compiler. - @volatile private var initIsComplete = false - @volatile private var initError: String = null - private def elapsed() = "%.3f".format((System.nanoTime - initStart).toDouble / 1000000000L) - - // the method to be called when the interpreter is initialized. - // Very important this method does nothing synchronous (i.e. do - // not try to use the interpreter) because until it returns, the - // repl's lazy val `global` is still locked. - protected def initializedCallback() = withLock(initCompilerCondition.signal()) - - // Spins off a thread which awaits a single message once the interpreter - // has been initialized. - protected def createAsyncListener() = { - io.spawn { - withLock(initCompilerCondition.await()) - asyncMessage("[info] compiler init time: " + elapsed() + " s.") - postInitialization() - } - } - - // called from main repl loop - protected def awaitInitialized(): Boolean = { - if (!initIsComplete) - withLock { while (!initIsComplete) initLoopCondition.await() } - if (initError != null) { - println(""" - |Failed to initialize the REPL due to an unexpected error. - |This is a bug, please, report it along with the error diagnostics printed below. - |%s.""".stripMargin.format(initError) - ) - false - } else true - } - // private def warningsThunks = List( - // () => intp.bind("lastWarnings", "" + typeTag[List[(Position, String)]], intp.lastWarnings _), - // ) - - protected def postInitThunks = List[Option[() => Unit]]( - Some(intp.setContextClassLoader _), - if (isReplPower) Some(() => enablePowerMode(true)) else None - ).flatten - // ++ ( - // warningsThunks - // ) - // called once after init condition is signalled - protected def postInitialization() { - try { - postInitThunks foreach (f => addThunk(f())) - runThunks() - } catch { - case ex: Throwable => - initError = stackTraceString(ex) - throw ex - } finally { - initIsComplete = true - - if (isAsync) { - asyncMessage("[info] total init time: " + elapsed() + " s.") - withLock(initLoopCondition.signal()) - } - } - } - // code to be executed only after the interpreter is initialized - // and the lazy val `global` can be accessed without risk of deadlock. - private var pendingThunks: List[() => Unit] = Nil - protected def addThunk(body: => Unit) = synchronized { - pendingThunks :+= (() => body) - } - protected def runThunks(): Unit = synchronized { - if (pendingThunks.nonEmpty) - repldbg("Clearing " + pendingThunks.size + " thunks.") - - while (pendingThunks.nonEmpty) { - val thunk = pendingThunks.head - pendingThunks = pendingThunks.tail - thunk() - } - } -} diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 2b97f81024..3f49e782b0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -11,37 +11,19 @@ import util.stringFromWriter import scala.reflect.internal.util._ import java.net.URL import scala.sys.BooleanProp -import io.VirtualDirectory import scala.tools.nsc.io.AbstractFile import reporters._ -import symtab.Flags -import scala.reflect.internal.Names import scala.tools.util.PathResolver import scala.tools.nsc.util.ScalaClassLoader import ScalaClassLoader.URLClassLoader import scala.tools.nsc.util.Exceptional.unwrap import scala.collection.{ mutable, immutable } -import scala.util.control.Exception.{ ultimately } import IMain._ import java.util.concurrent.Future -import typechecker.Analyzer -import scala.language.implicitConversions import scala.reflect.runtime.{ universe => ru } import scala.reflect.{ ClassTag, classTag } import scala.tools.reflect.StdRuntimeTags._ -/** directory to save .class files to */ -private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) { - private def pp(root: AbstractFile, indentLevel: Int) { - val spaces = " " * indentLevel - out.println(spaces + root.name) - if (root.isDirectory) - root.toList sortBy (_.name) foreach (x => pp(x, indentLevel + 1)) - } - // print the contents hierarchically - def show() = pp(this, 0) -} - /** An interpreter for Scala code. * * The main public entry points are compile(), interpret(), and bind(). @@ -77,16 +59,19 @@ private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory(" class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports { imain => - /** Leading with the eagerly evaluated. - */ - val virtualDirectory: VirtualDirectory = new ReplVirtualDirectory(out) // "directory" for classfiles - private var currentSettings: Settings = initialSettings - private[nsc] var printResults = true // whether to print result lines - private[nsc] var totalSilence = false // whether to print anything - private var _initializeComplete = false // compiler is initialized - private var _isInitialized: Future[Boolean] = null // set up initialization future - private var bindExceptions = true // whether to bind the lastException variable - private var _executionWrapper = "" // code to be wrapped around all lines + object replOutput extends ReplOutput(settings.Yreploutdir) { } + + @deprecated("Use replOutput.dir instead", "2.11.0") + def virtualDirectory = replOutput.dir + // Used in a test case. + def showDirectory() = replOutput.show(out) + + private[nsc] var printResults = true // whether to print result lines + private[nsc] var totalSilence = false // whether to print anything + private var _initializeComplete = false // compiler is initialized + private var _isInitialized: Future[Boolean] = null // set up initialization future + private var bindExceptions = true // whether to bind the lastException variable + private var _executionWrapper = "" // code to be wrapped around all lines /** We're going to go to some trouble to initialize the compiler asynchronously. * It's critical that nothing call into it until it's been initialized or we will @@ -98,20 +83,11 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private var _classLoader: AbstractFileClassLoader = null // active classloader private val _compiler: Global = newCompiler(settings, reporter) // our private compiler - private val nextReqId = { - var counter = 0 - () => { counter += 1 ; counter } - } - def compilerClasspath: Seq[URL] = ( if (isInitializeComplete) global.classPath.asURLs else new PathResolver(settings).result.asURLs // the compiler's classpath ) - def settings = currentSettings - def mostRecentLine = prevRequestList match { - case Nil => "" - case req :: _ => req.originalLine - } + def settings = initialSettings // Run the code body with the given boolean settings flipped to true. def withoutWarnings[T](body: => T): T = beQuietDuring { val saved = settings.nowarn.value @@ -126,12 +102,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true)) def this() = this(new Settings()) - lazy val repllog: Logger = new Logger { - val out: JPrintWriter = imain.out - val isInfo: Boolean = BooleanProp keyExists "scala.repl.info" - val isDebug: Boolean = BooleanProp keyExists "scala.repl.debug" - val isTrace: Boolean = BooleanProp keyExists "scala.repl.trace" - } lazy val formatting: Formatting = new Formatting { val prompt = Properties.shellPromptString } @@ -153,6 +123,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends catch AbstractOrMissingHandler() } private def tquoted(s: String) = "\"\"\"" + s + "\"\"\"" + private val logScope = scala.sys.props contains "scala.repl.scope" + private def scopelog(msg: String) = if (logScope) Console.err.println(msg) // argument is a thunk to execute after init is done def initialize(postInitSignal: => Unit) { @@ -187,15 +159,24 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends else null } } - @deprecated("Use `global` for access to the compiler instance.", "2.9.0") - lazy val compiler: global.type = global import global._ - import definitions.{ScalaPackage, JavaLangPackage, termMember, typeMember} - import rootMirror.{RootClass, getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass} + import definitions.{ ObjectClass, termMember, dropNullaryMethod} + + lazy val runtimeMirror = ru.runtimeMirror(classLoader) + + private def noFatal(body: => Symbol): Symbol = try body catch { case _: FatalError => NoSymbol } + + def getClassIfDefined(path: String) = ( + noFatal(runtimeMirror staticClass path) + orElse noFatal(rootMirror staticClass path) + ) + def getModuleIfDefined(path: String) = ( + noFatal(runtimeMirror staticModule path) + orElse noFatal(rootMirror staticModule path) + ) implicit class ReplTypeOps(tp: Type) { - def orElse(other: => Type): Type = if (tp ne NoType) tp else other def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp) } @@ -208,10 +189,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends // make sure we don't overwrite their unwisely named res3 etc. def freshUserTermName(): TermName = { val name = newTermName(freshUserVarName()) - if (definedNameMap contains name) freshUserTermName() + if (replScope containsName name) freshUserTermName() else name } - def isUserTermName(name: Name) = isUserVarName("" + name) def isInternalTermName(name: Name) = isInternalVarName("" + name) } import naming._ @@ -260,9 +240,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** Instantiate a compiler. Overridable. */ protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = { - settings.outputDirs setSingleOutput virtualDirectory + settings.outputDirs setSingleOutput replOutput.dir settings.exposeEmptyPackage.value = true - new Global(settings, reporter) with ReplGlobal + if (settings.Yrangepos.value) + new Global(settings, reporter) with ReplGlobal with interactive.RangePositions + else + new Global(settings, reporter) with ReplGlobal } /** Parent classloader. Overridable. */ @@ -295,20 +278,51 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends ensureClassLoader() _classLoader } - private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(virtualDirectory, parent) { + + def backticked(s: String): String = ( + (s split '.').toList map { + case "_" => "_" + case s if nme.keywords(newTermName(s)) => s"`$s`" + case s => s + } mkString "." + ) + + abstract class PhaseDependentOps { + def shift[T](op: => T): T + + def path(name: => Name): String = shift(path(symbolOfName(name))) + def path(sym: Symbol): String = backticked(shift(sym.fullName)) + def sig(sym: Symbol): String = shift(sym.defString) + } + object typerOp extends PhaseDependentOps { + def shift[T](op: => T): T = exitingTyper(op) + } + object flatOp extends PhaseDependentOps { + def shift[T](op: => T): T = exitingFlatten(op) + } + + def originalPath(name: String): String = originalPath(name: TermName) + def originalPath(name: Name): String = typerOp path name + def originalPath(sym: Symbol): String = typerOp path sym + def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName + def translatePath(path: String) = { + val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path) + sym match { + case NoSymbol => None + case _ => Some(flatPath(sym)) + } + } + + private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(replOutput.dir, parent) { /** Overridden here to try translating a simple name to the generated * class name if the original attempt fails. This method is used by * getResourceAsStream as well as findClass. */ - override protected def findAbstractFile(name: String): AbstractFile = { + override protected def findAbstractFile(name: String): AbstractFile = super.findAbstractFile(name) match { - // deadlocks on startup if we try to translate names too early - case null if isInitializeComplete => - generatedName(name) map (x => super.findAbstractFile(x)) orNull - case file => - file + case null => translatePath(name) map (super.findAbstractFile(_)) orNull + case file => file } - } } private def makeClassLoader(): AbstractFileClassLoader = new TranslatingClassLoader(parentClassLoader match { @@ -316,32 +330,11 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends case p => new URLClassLoader(compilerClasspath, p) }) - def getInterpreterClassLoader() = classLoader - // Set the current Java "context" class loader to this interpreter's class loader def setContextClassLoader() = classLoader.setAsContext() - /** Given a simple repl-defined name, returns the real name of - * the class representing it, e.g. for "Bippy" it may return - * {{{ - * $line19.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$Bippy - * }}} - */ - def generatedName(simpleName: String): Option[String] = { - if (simpleName endsWith nme.MODULE_SUFFIX_STRING) optFlatName(simpleName.init) map (_ + nme.MODULE_SUFFIX_STRING) - else optFlatName(simpleName) - } - def flatName(id: String) = optFlatName(id) getOrElse id - def optFlatName(id: String) = requestForIdent(id) map (_ fullFlatName id) - - def allDefinedNames = definedNameMap.keys.toList.sorted - def pathToType(id: String): String = pathToName(newTypeName(id)) - def pathToTerm(id: String): String = pathToName(newTermName(id)) - def pathToName(name: Name): String = { - if (definedNameMap contains name) - definedNameMap(name) fullPath name - else name.toString - } + def allDefinedNames: List[Name] = exitingTyper(replScope.toList.map(_.name).sorted) + def unqualifiedIds: List[String] = allDefinedNames map (_.decode) sorted /** Most recent tree handled which wasn't wholly synthetic. */ private def mostRecentlyHandledTree: Option[Tree] = { @@ -354,50 +347,47 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends None } - /** Stubs for work in progress. */ - def handleTypeRedefinition(name: TypeName, old: Request, req: Request) = { - for (t1 <- old.simpleNameOfType(name) ; t2 <- req.simpleNameOfType(name)) { - repldbg("Redefining type '%s'\n %s -> %s".format(name, t1, t2)) - } - } + private def updateReplScope(sym: Symbol, isDefined: Boolean) { + def log(what: String) { + val mark = if (sym.isType) "t " else "v " + val name = exitingTyper(sym.nameString) + val info = cleanTypeAfterTyper(sym) + val defn = sym defStringSeenAs info - def handleTermRedefinition(name: TermName, old: Request, req: Request) = { - for (t1 <- old.compilerTypeOf get name ; t2 <- req.compilerTypeOf get name) { - // Printing the types here has a tendency to cause assertion errors, like - // assertion failed: fatal: <refinement> has owner value x, but a class owner is required - // so DBG is by-name now to keep it in the family. (It also traps the assertion error, - // but we don't want to unnecessarily risk hosing the compiler's internal state.) - repldbg("Redefining term '%s'\n %s -> %s".format(name, t1, t2)) + scopelog(f"[$mark$what%6s] $name%-25s $defn%s") } + if (ObjectClass isSubClass sym.owner) return + // unlink previous + replScope lookupAll sym.name foreach { sym => + log("unlink") + replScope unlink sym + } + val what = if (isDefined) "define" else "import" + log(what) + replScope enter sym } def recordRequest(req: Request) { - if (req == null || referencedNameMap == null) + if (req == null) return prevRequests += req - req.referencedNames foreach (x => referencedNameMap(x) = req) // warning about serially defining companions. It'd be easy // enough to just redefine them together but that may not always // be what people want so I'm waiting until I can do it better. - for { - name <- req.definedNames filterNot (x => req.definedNames contains x.companionName) - oldReq <- definedNameMap get name.companionName - newSym <- req.definedSymbols get name - oldSym <- oldReq.definedSymbols get name.companionName - } { - afterTyper(replwarn(s"warning: previously defined $oldSym is not a companion to $newSym.")) - replwarn("Companions must be defined together; you may wish to use :paste mode for this.") - } - - // Updating the defined name map - req.definedNames foreach { name => - if (definedNameMap contains name) { - if (name.isTypeName) handleTypeRedefinition(name.toTypeName, definedNameMap(name), req) - else handleTermRedefinition(name.toTermName, definedNameMap(name), req) + exitingTyper { + req.defines filterNot (s => req.defines contains s.companionSymbol) foreach { newSym => + val companion = newSym.name.companionName + replScope lookup companion andAlso { oldSym => + replwarn(s"warning: previously defined $oldSym is not a companion to $newSym.") + replwarn("Companions must be defined together; you may wish to use :paste mode for this.") + } } - definedNameMap(name) = req + } + exitingTyper { + req.imports foreach (sym => updateReplScope(sym, isDefined = false)) + req.defines foreach (sym => updateReplScope(sym, isDefined = true)) } } @@ -406,19 +396,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends printMessage(msg) } - def isParseable(line: String): Boolean = { - beSilentDuring { - try parse(line) match { - case Some(xs) => xs.nonEmpty // parses as-is - case None => true // incomplete - } - catch { case x: Exception => // crashed the compiler - replwarn("Exception in isParseable(\"" + line + "\"): " + x) - false - } - } - } - def compileSourcesKeepingRun(sources: SourceFile*) = { val run = new Run() reporter.reset() @@ -445,18 +422,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends executingRequest } - // rewriting "5 // foo" to "val x = { 5 // foo }" creates broken code because - // the close brace is commented out. Strip single-line comments. - // ... but for error message output reasons this is not used, and rather than - // enclosing in braces it is constructed like "val x =\n5 // foo". - private def removeComments(line: String): String = { - showCodeIfDebugging(line) // as we're about to lose our // show - line.lines map (s => s indexOf "//" match { - case -1 => s - case idx => s take idx - }) mkString "\n" - } - private def safePos(t: Tree, alt: Int): Int = try t.pos.startOrPoint catch { case _: UnsupportedOperationException => alt } @@ -612,7 +577,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends */ def bind(name: String, boundType: String, value: Any, modifiers: List[String] = Nil): IR.Result = { val bindRep = new ReadEvalPrint() - val run = bindRep.compile(""" + bindRep.compile(""" |object %s { | var value: %s = _ | def set(x: Any) = value = x.asInstanceOf[%s] @@ -642,24 +607,15 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def rebind(p: NamedParam): IR.Result = { val name = p.name - val oldType = typeOfTerm(name) orElse { return IR.Error } val newType = p.tpe val tempName = freshInternalVarName() quietRun("val %s = %s".format(tempName, name)) quietRun("val %s = %s.asInstanceOf[%s]".format(name, tempName, newType)) } - def quietImport(ids: String*): IR.Result = beQuietDuring(addImports(ids: _*)) - def addImports(ids: String*): IR.Result = - if (ids.isEmpty) IR.Success - else interpret("import " + ids.mkString(", ")) - def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p)) def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value) def bind[T: ru.TypeTag : ClassTag](name: String, value: T): IR.Result = bind((name, value)) - def bindSyntheticValue(x: Any): IR.Result = bindValue(freshInternalVarName(), x) - def bindValue(x: Any): IR.Result = bindValue(freshUserVarName(), x) - def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x) /** Reset this interpreter, forgetting all user-specified requests. */ def reset() { @@ -667,9 +623,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends resetClassLoader() resetAllCreators() prevRequests.clear() - referencedNameMap.clear() - definedNameMap.clear() - virtualDirectory.clear() + resetReplScope() + replOutput.dir.clear() } /** This instance is no longer needed, so release any resources @@ -690,10 +645,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends class ReadEvalPrint(lineId: Int) { def this() = this(freshLineId()) - private var lastRun: Run = _ - private var evalCaught: Option[Throwable] = None - private var conditionalWarnings: List[ConditionalWarning] = Nil - val packageName = sessionNames.line + lineId val readName = sessionNames.read val evalName = sessionNames.eval @@ -720,7 +671,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def readPath = pathTo(readName) def evalPath = pathTo(evalName) - def printPath = pathTo(printName) def call(name: String, args: Any*): AnyRef = { val m = evalMethod(name) @@ -735,10 +685,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends try Right(call(name, args: _*)) catch { case ex: Throwable => Left(ex) } - def callOpt(name: String, args: Any*): Option[AnyRef] = - try Some(call(name, args: _*)) - catch { case ex: Throwable => bindError(ex) ; None } - class EvalException(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { } private def evalError(path: String, ex: Throwable) = @@ -750,10 +696,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } lazy val evalClass = load(evalPath) - lazy val evalValue = callEither(resultName) match { - case Left(ex) => evalCaught = Some(ex) ; None - case Right(result) => Some(result) - } def compile(source: String): Boolean = compileAndSaveRun("<console>", source) @@ -761,10 +703,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends * following accessPath into the outer one. */ def resolvePathToSymbol(accessPath: String): Symbol = { - val readRoot = getRequiredModule(readPath) // the outermost wrapper + val readRoot = getModuleIfDefined(readPath) // the outermost wrapper (accessPath split '.').foldLeft(readRoot: Symbol) { case (sym, "") => sym - case (sym, name) => afterTyper(termMember(sym, name)) + case (sym, name) => exitingTyper(termMember(sym, name)) } } /** We get a bunch of repeated warnings for reasons I haven't @@ -797,15 +739,16 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends showCodeIfDebugging(code) val (success, run) = compileSourcesKeepingRun(new BatchSourceFile(label, packaged(code))) updateRecentWarnings(run) - lastRun = run success } } /** One line of code submitted by the user for interpretation */ - // private class Request(val line: String, val trees: List[Tree]) { - val reqId = nextReqId() + def defines = defHandlers flatMap (_.definedSymbols) + def imports = importedSymbols + def value = Some(handlers.last) filter (h => h.definesValue) map (h => definedSymbols(h.definesTerm.get)) getOrElse NoSymbol + val lineRep = new ReadEvalPrint() private var _originalLine: String = null @@ -816,50 +759,31 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val handlers: List[MemberHandler] = trees map (memberHandlers chooseHandler _) def defHandlers = handlers collect { case x: MemberDefHandler => x } - /** all (public) names defined by these statements */ - val definedNames = handlers flatMap (_.definedNames) - /** list of names used by this expression */ val referencedNames: List[Name] = handlers flatMap (_.referencedNames) /** def and val names */ def termNames = handlers flatMap (_.definesTerm) def typeNames = handlers flatMap (_.definesType) - def definedOrImported = handlers flatMap (_.definedOrImported) - def definedSymbolList = defHandlers flatMap (_.definedSymbols) - - def definedTypeSymbol(name: String) = definedSymbols(newTypeName(name)) - def definedTermSymbol(name: String) = definedSymbols(newTermName(name)) + def importedSymbols = handlers flatMap { + case x: ImportHandler => x.importedSymbols + case _ => Nil + } /** Code to import bound names from previous lines - accessPath is code to * append to objectName to access anything bound by request. */ val ComputedImports(importsPreamble, importsTrailer, accessPath) = - importsCode(referencedNames.toSet) - - /** Code to access a variable with the specified name */ - def fullPath(vname: String) = ( - lineRep.readPath + accessPath + ".`%s`".format(vname) - ) - /** Same as fullpath, but after it has been flattened, so: - * $line5.$iw.$iw.$iw.Bippy // fullPath - * $line5.$iw$$iw$$iw$Bippy // fullFlatName - */ - def fullFlatName(name: String) = - lineRep.readPath + accessPath.replace('.', '$') + nme.NAME_JOIN_STRING + name - - /** The unmangled symbol name, but supplemented with line info. */ - def disambiguated(name: Name): String = name + " (in " + lineRep + ")" - - /** Code to access a variable with the specified name */ - def fullPath(vname: Name): String = fullPath(vname.toString) + exitingTyper(importsCode(referencedNames.toSet)) /** the line of code to compute */ def toCompute = line + def fullPath(vname: String) = s"${lineRep.readPath}$accessPath.`$vname`" + /** generate the source code for the object that computes this request */ private object ObjectSourceCode extends CodeAssembler[MemberHandler] { - def path = pathToTerm("$intp") + def path = originalPath("$intp") def envLines = { if (!isReplPower) Nil // power mode only for now // $intp is not bound; punt, but include the line. @@ -869,8 +793,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends ) else List( "def $line = " + tquoted(originalLine), - "def $req = %s.requestForReqId(%s).orNull".format(path, reqId), - "def $trees = if ($req eq null) Nil else $req.trees".format(lineRep.readName, path, reqId) + "def $trees = Nil" ) } @@ -886,13 +809,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** We only want to generate this code when the result * is a value which can be referred to as-is. */ - val evalResult = - if (!handlers.last.definesValue) "" - else handlers.last.definesTerm match { - case Some(vname) if typeOf contains vname => - "lazy val %s = %s".format(lineRep.resultName, fullPath(vname)) - case _ => "" - } + val evalResult = Request.this.value match { + case NoSymbol => "" + case sym => "lazy val %s = %s".format(lineRep.resultName, originalPath(sym)) + } // first line evaluates object to make sure constructor is run // initial "" so later code can uniformly be: + etc val preamble = """ @@ -914,15 +834,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val generate = (m: MemberHandler) => m resultExtractionCode Request.this } - // get it - def getEvalTyped[T] : Option[T] = getEval map (_.asInstanceOf[T]) - def getEval: Option[AnyRef] = { - // ensure it has been compiled - compile - // try to load it and call the value method - lineRep.evalValue filterNot (_ == null) - } - /** Compile the object file. Returns whether the compilation succeeded. * If all goes well, the "types" map is computed. */ lazy val compile: Boolean = { @@ -941,7 +852,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val name = dh.member.name definedSymbols get name foreach { sym => dh.member setSymbol sym - repldbg("Set symbol of " + name + " to " + sym.defString) + repldbg("Set symbol of " + name + " to " + symbolDefString(sym)) } } @@ -951,11 +862,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath) - def applyToResultMember[T](name: Name, f: Symbol => T) = afterTyper(f(resultSymbol.info.nonPrivateDecl(name))) + def applyToResultMember[T](name: Name, f: Symbol => T) = exitingTyper(f(resultSymbol.info.nonPrivateDecl(name))) /* typeOf lookup with encoding */ def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString))) - def simpleNameOfType(name: TypeName) = (compilerTypeOf get name) map (_.typeSymbol.simpleName) private def typeMap[T](f: Type => T) = mapFrom[Name, Name, T](termNames ++ typeNames)(x => f(cleanMemberDecl(resultSymbol, x))) @@ -963,14 +873,11 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** Types of variables defined by this request. */ lazy val compilerTypeOf = typeMap[Type](x => x) withDefaultValue NoType /** String representations of same. */ - lazy val typeOf = typeMap[String](tp => afterTyper(tp.toString)) + lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString)) - // lazy val definedTypes: Map[Name, Type] = { - // typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap - // } lazy val definedSymbols = ( termNames.map(x => x -> applyToResultMember(x, x => x)) ++ - typeNames.map(x => x -> compilerTypeOf(x).typeSymbol) + typeNames.map(x => x -> compilerTypeOf(x).typeSymbolDirect) ).toMap[Name, Symbol] withDefaultValue NoSymbol lazy val typesOfDefinedTerms = mapFrom[Name, Name, Type](termNames)(x => applyToResultMember(x, _.tpe)) @@ -1000,45 +907,48 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private var mostRecentWarnings: List[(global.Position, String)] = Nil def lastWarnings = mostRecentWarnings - def treesForRequestId(id: Int): List[Tree] = - requestForReqId(id).toList flatMap (_.trees) - - def requestForReqId(id: Int): Option[Request] = - if (executingRequest != null && executingRequest.reqId == id) Some(executingRequest) - else prevRequests find (_.reqId == id) + private lazy val importToGlobal = global mkImporter ru + private lazy val importToRuntime = ru mkImporter global + private lazy val javaMirror = ru.rootMirror match { + case x: ru.JavaMirror => x + case _ => null + } + private implicit def importFromRu(sym: ru.Symbol): Symbol = importToGlobal importSymbol sym + private implicit def importToRu(sym: Symbol): ru.Symbol = importToRuntime importSymbol sym - def requestForName(name: Name): Option[Request] = { - assert(definedNameMap != null, "definedNameMap is null") - definedNameMap get name + def classOfTerm(id: String): Option[JClass] = symbolOfTerm(id) match { + case NoSymbol => None + case sym => Some(javaMirror runtimeClass importToRu(sym).asClass) } - def requestForIdent(line: String): Option[Request] = - requestForName(newTermName(line)) orElse requestForName(newTypeName(line)) + def typeOfTerm(id: String): Type = symbolOfTerm(id).tpe - def requestHistoryForName(name: Name): List[Request] = - prevRequests.toList.reverse filter (_.definedNames contains name) + def valueOfTerm(id: String): Option[Any] = exitingTyper { + def value() = { + val sym0 = symbolOfTerm(id) + val sym = (importToRuntime importSymbol sym0).asTerm + val module = runtimeMirror.reflectModule(sym.owner.companionSymbol.asModule).instance + val module1 = runtimeMirror.reflect(module) + val invoker = module1.reflectField(sym) - def definitionForName(name: Name): Option[MemberHandler] = - requestForName(name) flatMap { req => - req.handlers find (_.definedNames contains name) + invoker.get } - def valueOfTerm(id: String): Option[AnyRef] = - requestForName(newTermName(id)) flatMap (_.getEval) - - def classOfTerm(id: String): Option[JClass] = - valueOfTerm(id) map (_.getClass) - - def typeOfTerm(id: String): Type = newTermName(id) match { - case nme.ROOTPKG => RootClass.tpe - case name => requestForName(name).fold(NoType: Type)(_ compilerTypeOf name) + try Some(value()) catch { case _: Exception => None } } - def symbolOfType(id: String): Symbol = - requestForName(newTypeName(id)).fold(NoSymbol: Symbol)(_ definedTypeSymbol id) + /** It's a bit of a shotgun approach, but for now we will gain in + * robustness. Try a symbol-producing operation at phase typer, and + * if that is NoSymbol, try again at phase flatten. I'll be able to + * lose this and run only from exitingTyper as soon as I figure out + * exactly where a flat name is sneaking in when calculating imports. + */ + def tryTwice(op: => Symbol): Symbol = exitingTyper(op) orElse exitingFlatten(op) - def symbolOfTerm(id: String): Symbol = - requestForIdent(newTermName(id)).fold(NoSymbol: Symbol)(_ definedTermSymbol id) + def symbolOfIdent(id: String): Symbol = symbolOfTerm(id) orElse symbolOfType(id) + def symbolOfType(id: String): Symbol = tryTwice(replScope lookup (id: TypeName)) + def symbolOfTerm(id: String): Symbol = tryTwice(replScope lookup (id: TermName)) + def symbolOfName(id: Name): Symbol = replScope lookup id def runtimeClassAndTypeOfTerm(id: String): Option[(JClass, Type)] = { classOfTerm(id) flatMap { clazz => @@ -1059,14 +969,18 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends else NoType } } - def cleanMemberDecl(owner: Symbol, member: Name): Type = afterTyper { - normalizeNonPublic { - owner.info.nonPrivateDecl(member).tpe match { - case NullaryMethodType(tp) => tp - case tp => tp - } - } + + def cleanTypeAfterTyper(sym: => Symbol): Type = { + exitingTyper( + normalizeNonPublic( + dropNullaryMethod( + sym.tpe_* + ) + ) + ) } + def cleanMemberDecl(owner: Symbol, member: Name): Type = + cleanTypeAfterTyper(owner.info nonPrivateDecl member) object exprTyper extends { val repl: IMain.this.type = imain @@ -1080,64 +994,35 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def typeOfExpression(expr: String, silent: Boolean = true): Type = exprTyper.typeOfExpression(expr, silent) - protected def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x } - protected def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x } + protected def onlyTerms(xs: List[Name]): List[TermName] = xs collect { case x: TermName => x } + protected def onlyTypes(xs: List[Name]): List[TypeName] = xs collect { case x: TypeName => x } def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName def definedTypes = onlyTypes(allDefinedNames) - def definedSymbols = prevRequestList.flatMap(_.definedSymbols.values).toSet[Symbol] - def definedSymbolList = prevRequestList flatMap (_.definedSymbolList) filterNot (s => isInternalTermName(s.name)) + def definedSymbolList = prevRequestList flatMap (_.defines) filterNot (s => isInternalTermName(s.name)) // Terms with user-given names (i.e. not res0 and not synthetic) def namedDefinedTerms = definedTerms filterNot (x => isUserVarName("" + x) || directlyBoundNames(x)) - private def findName(name: Name) = definedSymbols find (_.name == name) getOrElse NoSymbol - - /** Translate a repl-defined identifier into a Symbol. - */ - def apply(name: String): Symbol = - types(name) orElse terms(name) - - def types(name: String): Symbol = { - val tpname = newTypeName(name) - findName(tpname) orElse getClassIfDefined(tpname) - } - def terms(name: String): Symbol = { - val termname = newTypeName(name) - findName(termname) orElse getModuleIfDefined(termname) + private var _replScope: Scope = _ + private def resetReplScope() { + _replScope = newScope } - // [Eugene to Paul] possibly you could make use of TypeTags here - def types[T: ClassTag] : Symbol = types(classTag[T].runtimeClass.getName) - def terms[T: ClassTag] : Symbol = terms(classTag[T].runtimeClass.getName) - def apply[T: ClassTag] : Symbol = apply(classTag[T].runtimeClass.getName) + def replScope = { + if (_replScope eq null) + _replScope = newScope - def classSymbols = allDefSymbols collect { case x: ClassSymbol => x } - def methodSymbols = allDefSymbols collect { case x: MethodSymbol => x } + _replScope + } - /** the previous requests this interpreter has processed */ private var executingRequest: Request = _ private val prevRequests = mutable.ListBuffer[Request]() - private val referencedNameMap = mutable.Map[Name, Request]() - private val definedNameMap = mutable.Map[Name, Request]() private val directlyBoundNames = mutable.Set[Name]() - def allHandlers = prevRequestList flatMap (_.handlers) - def allDefHandlers = allHandlers collect { case x: MemberDefHandler => x } - def allDefSymbols = allDefHandlers map (_.symbol) filter (_ ne NoSymbol) - - def lastRequest = if (prevRequests.isEmpty) null else prevRequests.last - def prevRequestList = prevRequests.toList - def allSeenTypes = prevRequestList flatMap (_.typeOf.values.toList) distinct - def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames) - def importHandlers = allHandlers collect { case x: ImportHandler => x } - - def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct - - /** Another entry point for tab-completion, ids in scope */ - def unqualifiedIds = visibleTermNames map (_.toString) filterNot (_ contains "$") sorted - - /** Parse the ScalaSig to find type aliases */ - def aliasForType(path: String) = ByteCode.aliasForType(path) + def allHandlers = prevRequestList flatMap (_.handlers) + def lastRequest = if (prevRequests.isEmpty) null else prevRequests.last + def prevRequestList = prevRequests.toList + def importHandlers = allHandlers collect { case x: ImportHandler => x } def withoutUnwrapping(op: => Unit): Unit = { val saved = isettings.unwrapStrings @@ -1148,7 +1033,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def symbolDefString(sym: Symbol) = { TypeStrings.quieter( - afterTyper(sym.defString), + exitingTyper(sym.defString), sym.owner.name + ".this.", sym.owner.fullName + "." ) @@ -1158,13 +1043,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** Secret bookcase entrance for repl debuggers: end the line * with "// show" and see what's going on. */ - def isShow = code.lines exists (_.trim endsWith "// show") - def isShowRaw = code.lines exists (_.trim endsWith "// raw") - - // old style - beSilentDuring(parse(code)) foreach { ts => - ts foreach { t => - withoutUnwrapping(repldbg(asCompactString(t))) + def isShow = code.lines exists (_.trim endsWith "// show") + if (isReplDebug || isShow) { + beSilentDuring(parse(code)) foreach { ts => + ts foreach { t => + withoutUnwrapping(echo(asCompactString(t))) + } } } } diff --git a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala index a8f77afcdf..d114ca2359 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala @@ -12,13 +12,6 @@ package interpreter * @author Lex Spoon, 2007/3/24 **/ class ISettings(intp: IMain) { - /** A list of paths where :load should look */ - var loadPath = List(".") - - /** Set this to true to see repl machinery under -Yrich-exceptions. - */ - var showInternalStackTraces = false - /** The maximum length of toString to use when printing the result * of an evaluation. 0 means no maximum. If a printout requires * more than this number of characters, then the printout is @@ -44,7 +37,7 @@ class ISettings(intp: IMain) { } def deprecation: Boolean = intp.settings.deprecation.value - def allSettings = Map( + def allSettings = Map[String, Any]( "maxPrintString" -> maxPrintString, "maxAutoprintCompletion" -> maxAutoprintCompletion, "unwrapStrings" -> unwrapStrings, diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala index 73d962b5b0..ff7bfd432c 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala @@ -12,12 +12,9 @@ trait Imports { self: IMain => import global._ - import definitions.{ ScalaPackage, JavaLangPackage, PredefModule } + import definitions.{ ObjectClass, ScalaPackage, JavaLangPackage, PredefModule } import memberHandlers._ - def isNoImports = settings.noimports.value - def isNoPredef = settings.nopredef.value - /** Synthetic import handlers for the language defined imports. */ private def makeWildcardImportHandler(sym: Symbol): ImportHandler = { val hd :: tl = sym.fullName.split('.').toList map newTermName @@ -31,12 +28,9 @@ trait Imports { /** Symbols whose contents are language-defined to be imported. */ def languageWildcardSyms: List[Symbol] = List(JavaLangPackage, ScalaPackage, PredefModule) - def languageWildcards: List[Type] = languageWildcardSyms map (_.tpe) def languageWildcardHandlers = languageWildcardSyms map makeWildcardImportHandler def allImportedNames = importHandlers flatMap (_.importedNames) - def importedTerms = onlyTerms(allImportedNames) - def importedTypes = onlyTypes(allImportedNames) /** Types which have been wildcard imported, such as: * val x = "abc" ; import x._ // type java.lang.String @@ -52,17 +46,11 @@ trait Imports { def sessionWildcards: List[Type] = { importHandlers filter (_.importsWildcard) map (_.targetType) distinct } - def wildcardTypes = languageWildcards ++ sessionWildcards def languageSymbols = languageWildcardSyms flatMap membersAtPickler def sessionImportedSymbols = importHandlers flatMap (_.importedSymbols) def importedSymbols = languageSymbols ++ sessionImportedSymbols def importedTermSymbols = importedSymbols collect { case x: TermSymbol => x } - def importedTypeSymbols = importedSymbols collect { case x: TypeSymbol => x } - def implicitSymbols = importedSymbols filter (_.isImplicit) - - def importedTermNamed(name: String): Symbol = - importedTermSymbols find (_.name.toString == name) getOrElse NoSymbol /** Tuples of (source, imported symbols) in the order they were imported. */ @@ -146,44 +134,42 @@ trait Imports { code append "object %s {\n".format(impname) trailingBraces append "}\n" accessPath append ("." + impname) - - currentImps.clear + currentImps.clear() + } + def maybeWrap(names: Name*) = if (names exists currentImps) addWrapper() + def wrapBeforeAndAfter[T](op: => T): T = { + addWrapper() + try op finally addWrapper() } - - addWrapper() // loop through previous requests, adding imports for each one - for (ReqAndHandler(req, handler) <- reqsToUse) { - handler match { - // If the user entered an import, then just use it; add an import wrapping - // level if the import might conflict with some other import - case x: ImportHandler => - if (x.importsWildcard || currentImps.exists(x.importedNames contains _)) - addWrapper() - - code append (x.member + "\n") - - // give wildcard imports a import wrapper all to their own - if (x.importsWildcard) addWrapper() - else currentImps ++= x.importedNames - - // For other requests, import each defined name. - // import them explicitly instead of with _, so that - // ambiguity errors will not be generated. Also, quote - // the name of the variable, so that we don't need to - // handle quoting keywords separately. - case x => - for (imv <- x.definedNames) { - if (currentImps contains imv) addWrapper() - - code append ("import " + (req fullPath imv) + "\n") - currentImps += imv - } + wrapBeforeAndAfter { + for (ReqAndHandler(req, handler) <- reqsToUse) { + handler match { + // If the user entered an import, then just use it; add an import wrapping + // level if the import might conflict with some other import + case x: ImportHandler if x.importsWildcard => + wrapBeforeAndAfter(code append (x.member + "\n")) + case x: ImportHandler => + maybeWrap(x.importedNames: _*) + code append (x.member + "\n") + currentImps ++= x.importedNames + + // For other requests, import each defined name. + // import them explicitly instead of with _, so that + // ambiguity errors will not be generated. Also, quote + // the name of the variable, so that we don't need to + // handle quoting keywords separately. + case x => + for (sym <- x.definedSymbols) { + maybeWrap(sym.name) + code append s"import ${x.path}\n" + currentImps += sym.name + } + } } } - // add one extra wrapper, to prevent warnings in the common case of - // redefining the value bound in the last interpreter request. - addWrapper() + ComputedImports(code.toString, trailingBraces.toString, accessPath.toString) } @@ -191,5 +177,5 @@ trait Imports { prevRequestList flatMap (req => req.handlers map (req -> _)) private def membersAtPickler(sym: Symbol): List[Symbol] = - beforePickler(sym.info.nonPrivateMembers.toList) + enteringPickler(sym.info.nonPrivateMembers.toList) } diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala index 8331fddca6..28ddf2939c 100644 --- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala @@ -7,8 +7,6 @@ package scala.tools.nsc package interpreter import java.io.IOException -import java.nio.channels.ClosedByInterruptException -import scala.util.control.Exception._ import session.History import InteractiveReader._ import Properties.isMac @@ -17,22 +15,16 @@ import Properties.isMac trait InteractiveReader { val interactive: Boolean - def init(): Unit def reset(): Unit - def history: History def completion: Completion - def eraseLine(): Unit def redrawLine(): Unit - def currentLine: String def readYesOrNo(prompt: String, alt: => Boolean): Boolean = readOneKey(prompt) match { case 'y' => true case 'n' => false case _ => alt } - def readAssumingNo(prompt: String) = readYesOrNo(prompt, false) - def readAssumingYes(prompt: String) = readYesOrNo(prompt, true) protected def readOneLine(prompt: String): String protected def readOneKey(prompt: String): Int @@ -52,6 +44,6 @@ object InteractiveReader { def apply(): InteractiveReader = SimpleReader() @deprecated("Use `apply` instead.", "2.9.0") - def createDefault(): InteractiveReader = apply() + def createDefault(): InteractiveReader = apply() // used by sbt } diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala index 219cb35242..19fa562234 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -6,10 +6,9 @@ package scala.tools.nsc package interpreter -import scala.tools.jline._ -import scala.tools.jline.console.completer._ import Completion._ import scala.collection.mutable.ListBuffer +import scala.reflect.internal.util.StringOps.longestCommonPrefix // REPL completor - queries supplied interpreter for valid // completions based on current contents of buffer. @@ -29,9 +28,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput if (isModule) getModuleIfDefined(name) else getModuleIfDefined(name) ) - def getType(name: String, isModule: Boolean) = getSymbol(name, isModule).tpe - def typeOf(name: String) = getType(name, false) - def moduleOf(name: String) = getType(name, true) trait CompilerCompletion { def tp: Type @@ -47,12 +43,11 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput def anyRefMethodsToShow = Set("isInstanceOf", "asInstanceOf", "toString") def tos(sym: Symbol): String = sym.decodedName - def memberNamed(s: String) = afterTyper(effectiveTp member newTermName(s)) - def hasMethod(s: String) = memberNamed(s).isMethod + def memberNamed(s: String) = exitingTyper(effectiveTp member newTermName(s)) // XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the // compiler to crash for reasons not yet known. - def members = afterTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic)) + def members = exitingTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic)) def methods = members.toList filter (_.isMethod) def packages = members.toList filter (_.isPackage) def aliases = members.toList filter (_.isAliasType) @@ -111,7 +106,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput def excludeNames: List[String] = (anyref.methodNames filterNot anyRefMethodsToShow) :+ "_root_" def methodSignatureString(sym: Symbol) = { - IMain stripString afterTyper(new MethodSymbolOutput(sym).methodString()) + IMain stripString exitingTyper(new MethodSymbolOutput(sym).methodString()) } def exclude(name: String): Boolean = ( @@ -280,10 +275,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput if (parsed.isEmpty) xs map ("." + _) else xs } - // generic interface for querying (e.g. interpreter loop, testing) - def completions(buf: String): List[String] = - topLevelFor(Parsed.dotted(buf + ".", buf.length + 1)) - def completer(): ScalaCompleter = new JLineTabCompletion /** This gets a little bit hairy. It's no small feat delegating everything @@ -301,16 +292,6 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput def isConsecutiveTabs(buf: String, cursor: Int) = cursor == lastCursor && buf == lastBuf - // Longest common prefix - def commonPrefix(xs: List[String]): String = { - if (xs.isEmpty || xs.contains("")) "" - else xs.head.head match { - case ch => - if (xs.tail forall (_.head == ch)) "" + ch + commonPrefix(xs map (_.tail)) - else "" - } - } - // This is jline's entry point for completion. override def complete(buf: String, cursor: Int): Candidates = { verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0 @@ -324,7 +305,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput val newCursor = if (winners contains "") p.cursor else { - val advance = commonPrefix(winners) + val advance = longestCommonPrefix(winners) lastCursor = p.position + advance.length lastBuf = (buf take p.position) + advance repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format( @@ -335,8 +316,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput Some(Candidates(newCursor, winners)) } - def mkDotted = Parsed.dotted(buf, cursor) withVerbosity verbosity - def mkUndelimited = Parsed.undelimited(buf, cursor) withVerbosity verbosity + def mkDotted = Parsed.dotted(buf, cursor) withVerbosity verbosity // a single dot is special cased to completion on the previous result def lastResultCompletion = diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala index 10f972452f..a620c7c75a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala @@ -9,9 +9,7 @@ package interpreter import scala.tools.jline.console.ConsoleReader import scala.tools.jline.console.completer._ import session._ -import scala.collection.JavaConverters._ import Completion._ -import io.Streamable.slurp /** * Reads from the console using JLine. @@ -25,7 +23,6 @@ class JLineReader(_completion: => Completion) extends InteractiveReader { private def term = consoleReader.getTerminal() def reset() = term.reset() - def init() = term.init() def scalaToJline(tc: ScalaCompleter): Completer = new Completer { def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = { @@ -37,8 +34,6 @@ class JLineReader(_completion: => Completion) extends InteractiveReader { } class JLineConsoleReader extends ConsoleReader with ConsoleReaderHelper { - // working around protected/trait/java insufficiencies. - def goBack(num: Int): Unit = back(num) def readOneKey(prompt: String) = { this.print(prompt) this.flush() @@ -46,7 +41,6 @@ class JLineReader(_completion: => Completion) extends InteractiveReader { } def eraseLine() = consoleReader.resetPromptLine("", "", 0) def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() } - // override def readLine(prompt: String): String // A hook for running code after the repl is done initializing. lazy val postInit: Unit = { @@ -65,11 +59,7 @@ class JLineReader(_completion: => Completion) extends InteractiveReader { } } - def currentLine = consoleReader.getCursorBuffer.buffer.toString def redrawLine() = consoleReader.redrawLineAndFlush() - def eraseLine() = consoleReader.eraseLine() - // Alternate implementation, not sure if/when I need this. - // def eraseLine() = while (consoleReader.delete()) { } def readOneLine(prompt: String) = consoleReader readLine prompt def readOneKey(prompt: String) = consoleReader readOneKey prompt } diff --git a/src/compiler/scala/tools/nsc/interpreter/Logger.scala b/src/compiler/scala/tools/nsc/interpreter/Logger.scala index aeb25fc688..7407daf8d0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Logger.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Logger.scala @@ -11,8 +11,4 @@ trait Logger { def isDebug: Boolean def isTrace: Boolean def out: JPrintWriter - - def info(msg: => Any): Unit = if (isInfo) out println msg - def debug(msg: => Any): Unit = if (isDebug) out println msg - def trace(msg: => Any): Unit = if (isTrace) out println msg } diff --git a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala index 60325ece30..39979c8fbe 100644 --- a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala +++ b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala @@ -19,13 +19,8 @@ class ProcessResult(val line: String) { val exitCode = builder ! logger def lines = buffer.toList - def show() = lines foreach println override def toString = "`%s` (%d lines, exit %d)".format(line, buffer.size, exitCode) } -object ProcessResult { - implicit def processResultToOutputLines(pr: ProcessResult): List[String] = pr.lines - def apply(line: String): ProcessResult = new ProcessResult(line) -} trait LoopCommands { protected def out: JPrintWriter @@ -35,14 +30,6 @@ trait LoopCommands { // a single interpreter command abstract class LoopCommand(val name: String, val help: String) extends (String => Result) { - private var _longHelp: String = null - final def defaultHelp = usageMsg + " (no extended help available.)" - def hasLongHelp = _longHelp != null || longHelp != defaultHelp - def withLongHelp(text: String): this.type = { _longHelp = text ; this } - def longHelp = _longHelp match { - case null => defaultHelp - case text => text - } def usage: String = "" def usageMsg: String = ":" + name + ( if (usage == "") "" else " " + usage @@ -54,11 +41,6 @@ trait LoopCommands { "usage is " + usageMsg Result(true, None) } - - def onError(msg: String) = { - out.println("error: " + msg) - showUsage() - } } object LoopCommand { def nullary(name: String, help: String, f: () => Result): LoopCommand = @@ -67,9 +49,6 @@ trait LoopCommands { def cmd(name: String, usage: String, help: String, f: String => Result): LoopCommand = if (usage == "") new NullaryCmd(name, help, f) else new LineCmd(name, usage, help, f) - - def varargs(name: String, usage: String, help: String, f: List[String] => Result): LoopCommand = - new VarArgsCmd(name, usage, help, f) } class NullaryCmd(name: String, help: String, f: String => Result) extends LoopCommand(name, help) { diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 12fb8f1507..381dfeb261 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -7,8 +7,6 @@ package scala.tools.nsc package interpreter import scala.collection.{ mutable, immutable } -import scala.PartialFunction.cond -import scala.reflect.internal.Chars import scala.reflect.internal.Flags._ import scala.language.implicitConversions @@ -21,8 +19,6 @@ trait MemberHandlers { private def codegenln(leadingPlus: Boolean, xs: String*): String = codegen(leadingPlus, (xs ++ Array("\n")): _*) private def codegenln(xs: String*): String = codegenln(true, xs: _*) - - private def codegen(xs: String*): String = codegen(true, xs: _*) private def codegen(leadingPlus: Boolean, xs: String*): String = { val front = if (leadingPlus) "+ " else "" front + (xs map string2codeQuoted mkString " + ") @@ -55,21 +51,20 @@ trait MemberHandlers { def chooseHandler(member: Tree): MemberHandler = member match { case member: DefDef => new DefHandler(member) case member: ValDef => new ValHandler(member) - case member: Assign => new AssignHandler(member) case member: ModuleDef => new ModuleHandler(member) case member: ClassDef => new ClassHandler(member) case member: TypeDef => new TypeAliasHandler(member) + case member: Assign => new AssignHandler(member) case member: Import => new ImportHandler(member) case DocDef(_, documented) => chooseHandler(documented) case member => new GenericHandler(member) } sealed abstract class MemberDefHandler(override val member: MemberDef) extends MemberHandler(member) { - def symbol = if (member.symbol eq null) NoSymbol else member.symbol - def name: Name = member.name - def mods: Modifiers = member.mods - def keyword = member.keyword - def prettyName = name.decode + override def name: Name = member.name + def mods: Modifiers = member.mods + def keyword = member.keyword + def prettyName = name.decode override def definesImplicit = member.mods.isImplicit override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName) @@ -81,9 +76,11 @@ trait MemberHandlers { * in a single interpreter request. */ sealed abstract class MemberHandler(val member: Tree) { + def name: Name = nme.NO_NAME + def path = intp.originalPath(symbol) + def symbol = if (member.symbol eq null) NoSymbol else member.symbol def definesImplicit = false def definesValue = false - def isLegalTopLevel = false def definesTerm = Option.empty[TermName] def definesType = Option.empty[TypeName] @@ -91,7 +88,6 @@ trait MemberHandlers { lazy val referencedNames = ImportVarsTraverser(member) def importedNames = List[Name]() def definedNames = definesTerm.toList ++ definesType.toList - def definedOrImported = definedNames ++ importedNames def definedSymbols = List[Symbol]() def extraCodeToEvaluate(req: Request): String = "" @@ -114,10 +110,10 @@ trait MemberHandlers { // if this is a lazy val we avoid evaluating it here val resultString = if (mods.isLazy) codegenln(false, "<lazy>") - else any2stringOf(req fullPath name, maxStringElements) + else any2stringOf(path, maxStringElements) val vidString = - if (replProps.vids) """" + " @ " + "%%8x".format(System.identityHashCode(%s)) + " """.trim.format(req fullPath name) + if (replProps.vids) s"""" + " @ " + "%%8x".format(System.identityHashCode($path)) + " """.trim else "" """ + "%s%s: %s = " + %s""".format(prettyName, vidString, string2code(req typeOf name), resultString) @@ -136,7 +132,7 @@ trait MemberHandlers { class AssignHandler(member: Assign) extends MemberHandler(member) { val Assign(lhs, rhs) = member - val name = newTermName(freshInternalVarName()) + override lazy val name = newTermName(freshInternalVarName()) override def definesTerm = Some(name) override def definesValue = true @@ -155,15 +151,14 @@ trait MemberHandlers { class ModuleHandler(module: ModuleDef) extends MemberDefHandler(module) { override def definesTerm = Some(name) override def definesValue = true - override def isLegalTopLevel = true override def resultExtractionCode(req: Request) = codegenln("defined module ", name) } class ClassHandler(member: ClassDef) extends MemberDefHandler(member) { + override def definedSymbols = List(symbol, symbol.companionSymbol) filterNot (_ == NoSymbol) override def definesType = Some(name.toTypeName) override def definesTerm = Some(name.toTermName) filter (_ => mods.isCase) - override def isLegalTopLevel = true override def resultExtractionCode(req: Request) = codegenln("defined %s %s".format(keyword, name)) @@ -179,21 +174,11 @@ trait MemberHandlers { class ImportHandler(imp: Import) extends MemberHandler(imp) { val Import(expr, selectors) = imp - def targetType: Type = intp.typeOfExpression("" + expr) - override def isLegalTopLevel = true - - def createImportForName(name: Name): String = { - selectors foreach { - case sel @ ImportSelector(old, _, `name`, _) => return "import %s.{ %s }".format(expr, sel) - case _ => () - } - "import %s.%s".format(expr, name) + def targetType = intp.global.rootMirror.getModuleIfDefined("" + expr) match { + case NoSymbol => intp.typeOfExpression("" + expr) + case sym => sym.thisType } - // TODO: Need to track these specially to honor Predef masking attempts, - // because they must be the leading imports in the code generated for each - // line. We can use the same machinery as Contexts now, anyway. - def isPredefImport = isReferenceToPredef(expr) - + private def importableTargetMembers = importableMembers(targetType).toList // wildcard imports, e.g. import foo._ private def selectorWild = selectors filter (_.name == nme.USCOREkw) // renamed imports, e.g. import foo.{ bar => baz } @@ -202,22 +187,16 @@ trait MemberHandlers { /** Whether this import includes a wildcard import */ val importsWildcard = selectorWild.nonEmpty - /** Whether anything imported is implicit .*/ - def importsImplicit = implicitSymbols.nonEmpty - def implicitSymbols = importedSymbols filter (_.isImplicit) def importedSymbols = individualSymbols ++ wildcardSymbols - lazy val individualSymbols: List[Symbol] = - beforePickler(individualNames map (targetType nonPrivateMember _)) - - lazy val wildcardSymbols: List[Symbol] = - if (importsWildcard) beforePickler(targetType.nonPrivateMembers.toList) - else Nil + private val selectorNames = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames) toSet + lazy val individualSymbols: List[Symbol] = exitingTyper(importableTargetMembers filter (m => selectorNames(m.name))) + lazy val wildcardSymbols: List[Symbol] = exitingTyper(if (importsWildcard) importableTargetMembers else Nil) /** Complete list of names imported by a wildcard */ lazy val wildcardNames: List[Name] = wildcardSymbols map (_.name) - lazy val individualNames: List[Name] = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames) + lazy val individualNames: List[Name] = individualSymbols map (_.name) /** The names imported by this statement */ override lazy val importedNames: List[Name] = wildcardNames ++ individualNames diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala index eff0ef59c5..627a881cae 100644 --- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala +++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala @@ -14,14 +14,10 @@ import scala.reflect.{ClassTag, classTag} trait NamedParamCreator { protected def freshName: () => String - def apply(name: String, tpe: String, value: Any): NamedParam = NamedParamClass(name, tpe, value) def apply[T: ru.TypeTag : ClassTag](name: String, x: T): NamedParam = new Typed[T](name, x) def apply[T: ru.TypeTag : ClassTag](x: T): NamedParam = apply(freshName(), x) - def clazz(name: String, x: Any): NamedParam = new Untyped(name, x) - def clazz(x: Any): NamedParam = clazz(freshName(), x) - implicit def namedValue[T: ru.TypeTag : ClassTag](name: String, x: T): NamedParam = apply(name, x) implicit def tuple[T: ru.TypeTag : ClassTag](pair: (String, T)): NamedParam = apply(pair._1, pair._2) } diff --git a/src/compiler/scala/tools/nsc/interpreter/Naming.scala b/src/compiler/scala/tools/nsc/interpreter/Naming.scala index 0d03a8669a..41ddf23de4 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Naming.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Naming.scala @@ -78,7 +78,6 @@ trait Naming { private lazy val userVar = new NameCreator(sessionNames.res) // var name, like res0 private lazy val internalVar = new NameCreator(sessionNames.ires) // internal var name, like $ires0 - def isLineName(name: String) = (name startsWith sessionNames.line) && (name stripPrefix sessionNames.line forall (_.isDigit)) def isUserVarName(name: String) = userVar didGenerate name def isInternalVarName(name: String) = internalVar didGenerate name diff --git a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala b/src/compiler/scala/tools/nsc/interpreter/Parsed.scala index b0be956df8..672a6fd28f 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Parsed.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package interpreter -import scala.tools.jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList } import util.returning /** One instance of a command buffer. @@ -18,7 +17,6 @@ class Parsed private ( ) extends Delimited { def isEmpty = args.isEmpty def isUnqualified = args.size == 1 - def isQualified = args.size > 1 def isAtStart = cursor <= 0 private var _verbosity = 0 @@ -32,7 +30,6 @@ class Parsed private ( def bufferTail = new Parsed(buffer drop headLength, cursor - headLength, delimited) withVerbosity verbosity def prev = new Parsed(buffer, cursor - 1, delimited) withVerbosity verbosity - def next = new Parsed(buffer, cursor + 1, delimited) withVerbosity verbosity def currentChar = buffer(cursor) def currentArg = args.last def position = @@ -42,8 +39,6 @@ class Parsed private ( def isFirstDelimiter = !isEmpty && isDelimiterChar(buffer.head) def isLastDelimiter = !isEmpty && isDelimiterChar(buffer.last) - def firstIfDelimiter = if (isFirstDelimiter) buffer.head.toString else "" - def lastIfDelimiter = if (isLastDelimiter) buffer.last.toString else "" def isQuoted = false // TODO def isEscaped = !isAtStart && isEscapeChar(currentChar) && !isEscapeChar(prev.currentChar) @@ -57,13 +52,9 @@ object Parsed { private def onull(s: String) = if (s == null) "" else s - def apply(s: String): Parsed = apply(onull(s), onull(s).length) def apply(s: String, cursor: Int): Parsed = apply(onull(s), cursor, DefaultDelimiters) def apply(s: String, cursor: Int, delimited: Char => Boolean): Parsed = new Parsed(onull(s), cursor, delimited) - def dotted(s: String): Parsed = dotted(onull(s), onull(s).length) def dotted(s: String, cursor: Int): Parsed = new Parsed(onull(s), cursor, _ == '.') - - def undelimited(s: String, cursor: Int): Parsed = new Parsed(onull(s), cursor, _ => false) } diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/compiler/scala/tools/nsc/interpreter/Phased.scala index 638944713a..f625124e70 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Phased.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package interpreter -import scala.collection.{ mutable, immutable } +import scala.collection.immutable import scala.language.implicitConversions /** Mix this into an object and use it as a phasing @@ -24,7 +24,6 @@ trait Phased { case NoPhaseName => false case name => active = name ; true } - def getMulti = multi def setMulti(phases: Seq[PhaseName]): Boolean = { if (phases contains NoPhaseName) false else { @@ -66,16 +65,8 @@ trait Phased { try parseInternal(str) catch { case _: Exception => NoPhaseName } - def apply[T](body: => T) = immutable.SortedMap[PhaseName, T](atMap(PhaseName.all)(body): _*) - - def atCurrent[T](body: => T): T = atPhase(get)(body) + def atCurrent[T](body: => T): T = enteringPhase(get)(body) def multi[T](body: => T): Seq[T] = multi map (ph => at(ph)(body)) - def all[T](body: => T): Seq[T] = atMulti(PhaseName.all)(body) - def show[T](body: => T): Seq[T] = { - val pairs = atMap(PhaseName.all)(body) - pairs foreach { case (ph, op) => Console.println("%15s -> %s".format(ph, op.toString take 240)) } - pairs map (_._2) - } def at[T](ph: PhaseName)(body: => T): T = { val saved = get @@ -90,11 +81,6 @@ trait Phased { finally setMulti(saved) } - def showAt[T](phs: Seq[PhaseName])(body: => T): Unit = - atMap[T](phs)(body) foreach { - case (ph, op) => Console.println("%15s -> %s".format(ph, op.toString take 240)) - } - def atMap[T](phs: Seq[PhaseName])(body: => T): Seq[(PhaseName, T)] = phs zip atMulti(phs)(body) @@ -112,16 +98,12 @@ trait Phased { def apply(id: Int): PhaseName = all find (_.id == id) getOrElse NoPhaseName implicit def apply(s: String): PhaseName = nameMap(s) - implicit def defaultPhaseName: PhaseName = active } sealed abstract class PhaseName { lazy val id = phase.id lazy val name = toString.toLowerCase def phase = currentRun.phaseNamed(name) def isEmpty = this eq NoPhaseName - - // Execute some code during this phase. - def apply[T](body: => T): T = atPhase(phase)(body) } case object Parser extends PhaseName @@ -158,5 +140,4 @@ trait Phased { } implicit def phaseEnumToPhase(name: PhaseName): Phase = name.phase - implicit def phaseNameToPhase(name: String): Phase = currentRun.phaseNamed(name) } diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 5e6bf8824d..e517a16b32 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -8,8 +8,6 @@ package interpreter import scala.collection.{ mutable, immutable } import scala.util.matching.Regex -import scala.reflect.internal.util.{ BatchSourceFile } -import session.{ History } import scala.io.Codec import java.net.{ URL, MalformedURLException } import io.{ Path } @@ -48,7 +46,6 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re import intp.{ beQuietDuring, typeOfExpression, interpret, parse } import intp.global._ import definitions.{ compilerTypeFromTag, compilerSymbolFromTag} - import rootMirror.{ getClassIfDefined, getModuleIfDefined } abstract class SymSlurper { def isKeep(sym: Symbol): Boolean @@ -73,7 +70,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re pass += 1 val (repeats, unseen) = todo partition seen unseenHistory += unseen.size - if (opt.verbose) { + if (settings.verbose.value) { println("%3d %s accumulated, %s discarded. This pass: %s unseen, %s repeats".format( pass, keep.size, discarded, unseen.size, repeats.size)) } @@ -148,21 +145,10 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re // First we create the ReplVals instance and bind it to $r intp.bind("$r", replVals) // Then we import everything from $r. - intp interpret ("import " + intp.pathToTerm("$r") + "._") + intp interpret ("import " + intp.originalPath("$r") + "._") // And whatever else there is to do. init.lines foreach (intp interpret _) } - def valsDescription: String = { - def to_str(m: Symbol) = "%12s %s".format( - m.decodedName, "" + elimRefinement(m.accessedOrSelf.tpe) stripPrefix "scala.tools.nsc.") - - ( rutil.info[ReplValsImpl].membersDeclared - filter (m => m.isPublic && !m.hasModuleFlag && !m.isConstructor) - sortBy (_.decodedName) - map to_str - mkString ("Name and type of values imported into the repl in power mode.\n\n", "\n", "") - ) - } trait LowPriorityInternalInfo { implicit def apply[T: ru.TypeTag : ClassTag] : InternalInfo[T] = new InternalInfo[T](None) @@ -175,12 +161,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re * symbol, by only implicitly installing one method, "?", and the rest * of the conveniences exist on that wrapper. */ - trait LowPriorityInternalInfoWrapper { - implicit def apply[T: ru.TypeTag : ClassTag] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None) - } - object InternalInfoWrapper extends LowPriorityInternalInfoWrapper { - - } + trait LowPriorityInternalInfoWrapper { } class InternalInfoWrapper[T: ru.TypeTag : ClassTag](value: Option[T] = None) { def ? : InternalInfo[T] = new InternalInfo[T](value) } @@ -190,7 +171,6 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re * customizable symbol filter (had to hardcode no-spec to reduce noise) */ class InternalInfo[T](value: Option[T] = None)(implicit typeEvidence: ru.TypeTag[T], runtimeClassEvidence: ClassTag[T]) { - private def newInfo[U: ru.TypeTag : ClassTag](value: U): InternalInfo[U] = new InternalInfo[U](Some(value)) private def isSpecialized(s: Symbol) = s.name.toString contains "$mc" private def isImplClass(s: Symbol) = s.name.toString endsWith "$class" @@ -201,47 +181,15 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re || s.isAnonOrRefinementClass || s.isAnonymousFunction ) - def symbol = compilerSymbolFromTag(tag) - def tpe = compilerTypeFromTag(tag) - def name = symbol.name - def companion = symbol.companionSymbol - def info = symbol.info - def moduleClass = symbol.moduleClass - def owner = symbol.owner - def owners = symbol.ownerChain drop 1 - def signature = symbol.defString - - def decls = info.decls - def declsOverride = membersDeclared filter (_.isOverride) - def declsOriginal = membersDeclared filterNot (_.isOverride) - + def symbol = compilerSymbolFromTag(tag) + def tpe = compilerTypeFromTag(tag) def members = membersUnabridged filterNot excludeMember def membersUnabridged = tpe.members.toList - def membersDeclared = members filterNot excludeMember - def membersInherited = members filterNot (membersDeclared contains _) - def memberTypes = members filter (_.name.isTypeName) - def memberMethods = members filter (_.isMethod) - - def pkg = symbol.enclosingPackage - def pkgName = pkg.fullName - def pkgClass = symbol.enclosingPackageClass - def pkgMembers = pkg.info.members filterNot excludeMember - def pkgClasses = pkgMembers filter (s => s.isClass && s.isDefinedInPackage) - def pkgSymbols = new PackageSlurper(pkgClass).slurp() filterNot excludeMember - - def tag = typeEvidence - def runtimeClass = runtimeClassEvidence.runtimeClass - def shortClass = runtimeClass.getName split "[$.]" last - - def baseClasses = tpe.baseClasses - def baseClassDecls = mapFrom(baseClasses)(_.info.decls.toList.sortBy(_.name)) - def ancestors = baseClasses drop 1 - def ancestorDeclares(name: String) = ancestors filter (_.info member newTermName(name) ne NoSymbol) - def baseTypes = tpe.baseTypeSeq.toList - - def <:<[U: ru.TypeTag : ClassTag](other: U) = tpe <:< newInfo(other).tpe - def lub[U: ru.TypeTag : ClassTag](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe)) - def glb[U: ru.TypeTag : ClassTag](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe)) + def pkg = symbol.enclosingPackage + def tag = typeEvidence + def runtimeClass = runtimeClassEvidence.runtimeClass + def shortClass = runtimeClass.getName split "[$.]" last + def baseClasses = tpe.baseClasses override def toString = value match { case Some(x) => "%s (%s)".format(x, shortClass) @@ -267,7 +215,6 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re } object Prettifier extends LowPriorityPrettifier { def stringOf(x: Any): String = scala.runtime.ScalaRunTime.stringOf(x) - def prettify[T](value: T): TraversableOnce[String] = default[T] prettify value def default[T] = new Prettifier[T] { def prettify(x: T): TraversableOnce[String] = AnyPrettifier prettify x def show(x: T): Unit = AnyPrettifier show x @@ -277,45 +224,21 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re def show(x: T): Unit def prettify(x: T): TraversableOnce[String] - def show(xs: TraversableOnce[T]): Unit = prettify(xs) foreach println def prettify(xs: TraversableOnce[T]): TraversableOnce[String] = xs flatMap (x => prettify(x)) } abstract class PrettifierClass[T: Prettifier]() { val pretty = implicitly[Prettifier[T]] - import pretty._ - def value: Seq[T] def pp(f: Seq[T] => Seq[T]): Unit = pretty prettify f(value) foreach (StringPrettifier show _) def freq[U](p: T => U) = (value.toSeq groupBy p mapValues (_.size)).toList sortBy (-_._2) map (_.swap) - def ppfreq[U](p: T => U): Unit = freq(p) foreach { case (count, key) => println("%5d %s".format(count, key)) } - - def |[U](f: Seq[T] => Seq[U]): Seq[U] = f(value) - def ^^[U](f: T => U): Seq[U] = value map f - def ^?[U](pf: PartialFunction[T, U]): Seq[U] = value collect pf - def >>!(implicit ord: Ordering[T]): Unit = pp(_.sorted.distinct) def >>(implicit ord: Ordering[T]): Unit = pp(_.sorted) def >!(): Unit = pp(_.distinct) def >(): Unit = pp(identity) - - def >#(): Unit = this ># (identity[T] _) - def >#[U](p: T => U): Unit = this ppfreq p - - def >?(p: T => Boolean): Unit = pp(_ filter p) - def >?(s: String): Unit = pp(_ filter (_.toString contains s)) - def >?(r: Regex): Unit = pp(_ filter (_.toString matches fixRegex(r))) - - private def fixRegex(r: scala.util.matching.Regex): String = { - val s = r.pattern.toString - val prefix = if (s startsWith "^") "" else """^.*?""" - val suffix = if (s endsWith "$") "" else """.*$""" - - prefix + s + suffix - } } class MultiPrettifierClass[T: Prettifier](val value: Seq[T]) extends PrettifierClass[T]() { } @@ -339,17 +262,11 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re class RichReplURL(url: URL)(implicit codec: Codec) { def slurp(): String = io.Streamable.slurp(url) } - class RichSymbolList(syms: List[Symbol]) { - def sigs = syms map (_.defString) - def infos = syms map (_.info) - } trait Implicits1 { // fallback implicit def replPrinting[T](x: T)(implicit pretty: Prettifier[T] = Prettifier.default[T]) = new SinglePrettifierClass[T](x) - - implicit def liftToTypeName(s: String): TypeName = newTypeName(s) } trait Implicits2 extends Implicits1 { class RichSymbol(sym: Symbol) { @@ -374,26 +291,13 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re implicit def replInputStream(in: InputStream)(implicit codec: Codec) = new RichInputStream(in) implicit def replEnhancedURLs(url: URL)(implicit codec: Codec): RichReplURL = new RichReplURL(url)(codec) - - implicit def liftToTermName(s: String): TermName = newTermName(s) - implicit def replListOfSymbols(xs: List[Symbol]) = new RichSymbolList(xs) } trait ReplUtilities { - // [Eugene to Paul] needs review! - // def module[T: Manifest] = getModuleIfDefined(manifest[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING) - // def clazz[T: Manifest] = getClassIfDefined(manifest[T].erasure.getName) def module[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isPackage) def clazz[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isClass) def info[T: ru.TypeTag : ClassTag] = InternalInfo[T] def ?[T: ru.TypeTag : ClassTag] = InternalInfo[T] - def url(s: String) = { - try new URL(s) - catch { case _: MalformedURLException => - if (Path(s).exists) Path(s).toURL - else new URL("http://" + s) - } - } def sanitize(s: String): String = sanitize(s.getBytes()) def sanitize(s: Array[Byte]): String = (s map { case x if x.toChar.isControl => '?' @@ -411,20 +315,12 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re lazy val rutil: ReplUtilities = new ReplUtilities { } lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { } - def context(code: String) = analyzer.rootContext(unit(code)) - def source(code: String) = newSourceFile(code) - def unit(code: String) = newCompilationUnit(code) - def trees(code: String) = parse(code) getOrElse Nil - def typeOf(id: String) = intp.typeOfExpression(id) + def unit(code: String) = newCompilationUnit(code) + def trees(code: String) = parse(code) getOrElse Nil - override def toString = """ + override def toString = s""" |** Power mode status ** - |Default phase: %s - |Names: %s - |Identifiers: %s - """.stripMargin.format( - phased.get, - intp.allDefinedNames mkString " ", - intp.unqualifiedIds mkString " " - ) + |Default phase: ${phased.get} + |Names: ${intp.unqualifiedIds mkString " "} + """.stripMargin } diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala index 7cd0f436c4..3392ea0b5e 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala @@ -14,9 +14,7 @@ trait ReplConfig { lazy val replProps = new ReplProps class TapMaker[T](x: T) { - def tapInfo(msg: => String): T = tap(x => replinfo(parens(x))) def tapDebug(msg: => String): T = tap(x => repldbg(parens(x))) - def tapTrace(msg: => String): T = tap(x => repltrace(parens(x))) def tap[U](f: T => U): T = { f(x) x @@ -28,12 +26,6 @@ trait ReplConfig { try Console println msg catch { case x: AssertionError => Console.println("Assertion error printing debugging output: " + x) } - private[nsc] def repldbgex(ex: Throwable): Unit = { - if (isReplDebug) { - echo("Caught/suppressing: " + ex) - ex.printStackTrace - } - } private[nsc] def repldbg(msg: => String) = if (isReplDebug) echo(msg) private[nsc] def repltrace(msg: => String) = if (isReplTrace) echo(msg) private[nsc] def replinfo(msg: => String) = if (isReplInfo) echo(msg) @@ -45,14 +37,10 @@ trait ReplConfig { repltrace(stackTraceString(unwrap(t))) alt } - private[nsc] def substituteAndLog[T](alt: => T)(body: => T): T = - substituteAndLog("" + alt, alt)(body) private[nsc] def substituteAndLog[T](label: String, alt: => T)(body: => T): T = { try body catch logAndDiscard(label, alt) } - private[nsc] def squashAndLog(label: String)(body: => Unit): Unit = - substituteAndLog(label, ())(body) def isReplTrace: Boolean = replProps.trace def isReplDebug: Boolean = replProps.debug || isReplTrace diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala b/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala new file mode 100644 index 0000000000..9fbf64acb5 --- /dev/null +++ b/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala @@ -0,0 +1,48 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2012 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc +package interpreter + +import io.VirtualDirectory +import settings.MutableSettings +import scala.reflect.io.{ AbstractFile, PlainDirectory, Directory } +import scala.collection.generic.Clearable + +/** Directory to save .class files to. */ +trait ReplDir extends AbstractFile with Clearable { } + +private class ReplVirtualDir() extends VirtualDirectory("(memory)", None) with ReplDir { } +private class ReplRealDir(dir: Directory) extends PlainDirectory(dir) with ReplDir { + def clear() = { + dir.deleteRecursively() + dir.createDirectory() + } +} + +class ReplOutput(val dirSetting: MutableSettings#StringSetting) { + // outdir for generated classfiles - may be in-memory (the default), + // a generated temporary directory, or a specified outdir. + val dir: ReplDir = ( + if (dirSetting.isDefault) + new ReplVirtualDir() + else if (dirSetting.value == "") + new ReplRealDir(Directory.makeTemp("repl")) + else + new ReplRealDir(Directory(dirSetting.value)) + ) + + // print the contents hierarchically + def show(out: JPrintWriter) = { + def pp(root: AbstractFile, indentLevel: Int) { + val label = root.name + val spaces = " " * indentLevel + out.println(spaces + label) + if (root.isDirectory) + root.toList sortBy (_.name) foreach (x => pp(x, indentLevel + 1)) + } + pp(dir, 0) + } +} diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala index 7c698a2f3e..16b22869e7 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package interpreter -import reporters._ import typechecker.Analyzer /** A layer on top of Global so I can guarantee some extra diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala b/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala index bc3e7a10d7..2364918494 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala @@ -13,15 +13,11 @@ class ReplProps { private def bool(name: String) = BooleanProp.keyExists(name) private def int(name: String) = IntProp(name) - val jlineDebug = bool("scala.tools.jline.internal.Log.debug") - val jlineTrace = bool("scala.tools.jline.internal.Log.trace") - val info = bool("scala.repl.info") val debug = bool("scala.repl.debug") val trace = bool("scala.repl.trace") val power = bool("scala.repl.power") - val replInitCode = Prop[JFile]("scala.repl.initcode") val replAutorunCode = Prop[JFile]("scala.repl.autoruncode") val powerInitCode = Prop[JFile]("scala.repl.power.initcode") val powerBanner = Prop[JFile]("scala.repl.power.banner") diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala b/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala index f8ecc6c6fe..08472bbc64 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package interpreter -import scala.collection.{ mutable, immutable } -import scala.PartialFunction.cond import scala.reflect.internal.Chars trait ReplStrings { @@ -31,5 +29,4 @@ trait ReplStrings { "scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen) def words(s: String) = s.trim split "\\s+" filterNot (_ == "") toList - def isQuoted(s: String) = (s.length >= 2) && (s.head == s.last) && ("\"'" contains s.head) } diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index 53478bdc5d..ea100b25f2 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala @@ -57,7 +57,6 @@ object ReplVals { */ def mkCompilerTypeFromTag[T <: Global](global: T) = { import global._ - import definitions._ /** We can't use definitions.compilerTypeFromTag directly because we're passing * it to map and the compiler refuses to perform eta expansion on a method diff --git a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala index 4371f7fe05..36cdf65510 100644 --- a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala +++ b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala @@ -10,7 +10,6 @@ import scala.reflect.{ ClassTag, classTag } class RichClass[T](val clazz: Class[T]) { def toTag: ClassTag[T] = ClassTag[T](clazz) - def toTypeString: String = TypeStrings.fromClazz(clazz) // Sadly isAnonymousClass does not return true for scala anonymous // classes because our naming scheme is not doing well against the @@ -20,14 +19,12 @@ class RichClass[T](val clazz: Class[T]) { catch { case _: java.lang.InternalError => false } // good ol' "Malformed class name" ) - /** It's not easy... to be... me... */ - def supermans: List[ClassTag[_]] = supers map (_.toTag) + def supertags: List[ClassTag[_]] = supers map (_.toTag) def superNames: List[String] = supers map (_.getName) def interfaces: List[JClass] = supers filter (_.isInterface) def hasAncestorName(f: String => Boolean) = superNames exists f def hasAncestor(f: JClass => Boolean) = supers exists f - def hasAncestorInPackage(pkg: String) = hasAncestorName(_ startsWith (pkg + ".")) def supers: List[JClass] = { def loop(x: JClass): List[JClass] = x.getSuperclass match { diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala index bccd8158ec..2d0917d91f 100644 --- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala @@ -19,11 +19,8 @@ extends InteractiveReader val history = NoHistory val completion = NoCompletion - def init() = () def reset() = () - def eraseLine() = () def redrawLine() = () - def currentLine = "" def readOneLine(prompt: String): String = { if (interactive) { out.print(prompt) @@ -40,4 +37,4 @@ object SimpleReader { def apply(in: BufferedReader = defaultIn, out: JPrintWriter = defaultOut, interactive: Boolean = true): SimpleReader = new SimpleReader(in, out, interactive) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index 6abb52a649..239dbb8149 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -13,15 +13,12 @@ import NameTransformer._ import scala.reflect.runtime.{universe => ru} import scala.reflect.{ClassTag, classTag} import typechecker.DestructureTypes -import scala.reflect.internal.util.StringOps.ojoin -import scala.language.implicitConversions /** A more principled system for turning types into strings. */ trait StructuredTypeStrings extends DestructureTypes { val global: Global import global._ - import definitions._ case class LabelAndType(label: String, typeName: String) { } object LabelAndType { @@ -36,10 +33,8 @@ trait StructuredTypeStrings extends DestructureTypes { val NoGrouping = Grouping("", "", "", false) val ListGrouping = Grouping("(", ", ", ")", false) val ProductGrouping = Grouping("(", ", ", ")", true) - val ParamGrouping = Grouping("(", ", ", ")", true) val BlockGrouping = Grouping(" { ", "; ", "}", false) - private implicit def lowerName(n: Name): String = "" + n private def str(level: Int)(body: => String): String = " " * level + body private def block(level: Int, grouping: Grouping)(name: String, nodes: List[TypeNode]): String = { val l1 = str(level)(name + grouping.ldelim) @@ -49,7 +44,6 @@ trait StructuredTypeStrings extends DestructureTypes { l1 +: l2 :+ l3 mkString "\n" } private def maybeBlock(level: Int, grouping: Grouping)(name: String, nodes: List[TypeNode]): String = { - import grouping._ val threshold = 70 val try1 = str(level)(name + grouping.join(nodes map (_.show(0, grouping.labels)): _*)) @@ -57,7 +51,7 @@ trait StructuredTypeStrings extends DestructureTypes { else block(level, grouping)(name, nodes) } private def shortClass(x: Any) = { - if (opt.debug) { + if (settings.debug.value) { val name = (x.getClass.getName split '.').last val isAnon = name.reverse takeWhile (_ != '$') forall (_.isDigit) val str = if (isAnon) name else (name split '$').last @@ -194,7 +188,6 @@ trait TypeStrings { else enclClass.getName + "." + (name stripPrefix enclPre) ) } - def scalaName(ct: ClassTag[_]): String = scalaName(ct.runtimeClass) def anyClass(x: Any): JClass = if (x == null) null else x.getClass private def brackets(tps: String*): String = @@ -212,10 +205,8 @@ trait TypeStrings { } private def tparamString[T: ru.TypeTag] : String = { + import ru._ def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil } - // [Eugene to Paul] need to use not the `rootMirror`, but a mirror with the REPL's classloader - // how do I get to it? acquiring context classloader seems unreliable because of multithreading - def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => ru.rootMirror.runtimeClass(targ)) brackets(typeArguments map (jc => tvarString(List(jc))): _*) } @@ -227,7 +218,6 @@ trait TypeStrings { * practice to rely on toString for correctness) generated the VALID string * representation of the type. */ - def fromTypedValue[T: ru.TypeTag : ClassTag](x: T): String = fromTag[T] def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value)) def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz) def fromTag[T: ru.TypeTag : ClassTag] : String = scalaName(classTag[T].runtimeClass) + tparamString[T] @@ -247,13 +237,6 @@ trait TypeStrings { case (res, (k, v)) => res.replaceAll(k, v) } } - - val typeTransforms = List( - "java.lang." -> "", - "scala.collection.immutable." -> "immutable.", - "scala.collection.mutable." -> "mutable.", - "scala.collection.generic." -> "generic." - ) } object TypeStrings extends TypeStrings { } diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala index e3440c9f8b..52a085080b 100644 --- a/src/compiler/scala/tools/nsc/interpreter/package.scala +++ b/src/compiler/scala/tools/nsc/interpreter/package.scala @@ -6,6 +6,10 @@ package scala.tools.nsc import scala.language.implicitConversions +import scala.reflect.{ classTag, ClassTag } +import scala.reflect.runtime.{ universe => ru } +import scala.reflect.{ClassTag, classTag} +import scala.reflect.api.{Mirror, TypeCreator, Universe => ApiUniverse} /** The main REPL related classes and values are as follows. * In addition to standard compiler classes Global and Settings, there are: @@ -44,6 +48,110 @@ package object interpreter extends ReplConfig with ReplStrings { private[nsc] implicit def enrichClass[T](clazz: Class[T]) = new RichClass[T](clazz) private[nsc] implicit def enrichAnyRefWithTap[T](x: T) = new TapMaker(x) - private[nsc] def tracing[T](msg: String)(x: T): T = x.tapTrace(msg) private[nsc] def debugging[T](msg: String)(x: T) = x.tapDebug(msg) + + private val ourClassloader = getClass.getClassLoader + + def staticTypeTag[T: ClassTag]: ru.TypeTag[T] = ru.TypeTag[T]( + ru.runtimeMirror(ourClassloader), + new TypeCreator { + def apply[U <: ApiUniverse with Singleton](m: Mirror[U]): U # Type = + m.staticClass(classTag[T].runtimeClass.getName).toTypeConstructor.asInstanceOf[U # Type] + }) + + /** This class serves to trick the compiler into treating a var + * (intp, in ILoop) as a stable identifier. + */ + implicit class IMainOps(val intp: IMain) { + import intp._ + import global.{ reporter => _, _ } + import definitions._ + + protected def echo(msg: String) = { + Console.out println msg + Console.out.flush() + } + + def implicitsCommand(line: String): String = { + def p(x: Any) = intp.reporter.printMessage("" + x) + + // If an argument is given, only show a source with that + // in its name somewhere. + val args = line split "\\s+" + val filtered = intp.implicitSymbolsBySource filter { + case (source, syms) => + (args contains "-v") || { + if (line == "") (source.fullName.toString != "scala.Predef") + else (args exists (source.name.toString contains _)) + } + } + + if (filtered.isEmpty) + return "No implicits have been imported other than those in Predef." + + filtered foreach { + case (source, syms) => + p("/* " + syms.size + " implicit members imported from " + source.fullName + " */") + + // This groups the members by where the symbol is defined + val byOwner = syms groupBy (_.owner) + val sortedOwners = byOwner.toList sortBy { case (owner, _) => exitingTyper(source.info.baseClasses indexOf owner) } + + sortedOwners foreach { + case (owner, members) => + // Within each owner, we cluster results based on the final result type + // if there are more than a couple, and sort each cluster based on name. + // This is really just trying to make the 100 or so implicits imported + // by default into something readable. + val memberGroups: List[List[Symbol]] = { + val groups = members groupBy (_.tpe.finalResultType) toList + val (big, small) = groups partition (_._2.size > 3) + val xss = ( + (big sortBy (_._1.toString) map (_._2)) :+ + (small flatMap (_._2)) + ) + + xss map (xs => xs sortBy (_.name.toString)) + } + + val ownerMessage = if (owner == source) " defined in " else " inherited from " + p(" /* " + members.size + ownerMessage + owner.fullName + " */") + + memberGroups foreach { group => + group foreach (s => p(" " + intp.symbolDefString(s))) + p("") + } + } + p("") + } + "" + } + + /** TODO - + * -n normalize + * -l label with case class parameter names + * -c complete - leave nothing out + */ + def typeCommandInternal(expr: String, verbose: Boolean): Unit = + symbolOfLine(expr) andAlso (echoTypeSignature(_, verbose)) + + def printAfterTyper(msg: => String) = + reporter printUntruncatedMessage exitingTyper(msg) + + private def replInfo(sym: Symbol) = + if (sym.isAccessor) dropNullaryMethod(sym.info) else sym.info + + def echoTypeStructure(sym: Symbol) = + printAfterTyper("" + deconstruct.show(replInfo(sym))) + + def echoTypeSignature(sym: Symbol, verbose: Boolean) = { + if (verbose) echo("// Type signature") + printAfterTyper("" + replInfo(sym)) + + if (verbose) { + echo("\n// Internal Type structure") + echoTypeStructure(sym) + } + } + } } diff --git a/src/compiler/scala/tools/nsc/interpreter/session/History.scala b/src/compiler/scala/tools/nsc/interpreter/session/History.scala index daa05b86db..794d41adc7 100644 --- a/src/compiler/scala/tools/nsc/interpreter/session/History.scala +++ b/src/compiler/scala/tools/nsc/interpreter/session/History.scala @@ -14,15 +14,9 @@ trait History { def asStrings: List[String] def index: Int def size: Int - def grep(s: String): List[String] } object NoHistory extends History { def asStrings = Nil - def grep(s: String) = Nil def index = 0 def size = 0 } - -object History { - def empty: History = NoHistory -} diff --git a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala b/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala index 9f4e2b9df3..89998e438a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala +++ b/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala @@ -54,9 +54,5 @@ class SimpleHistory extends JLineHistory { def moveTo(idx: Int) = (idx > 0) && (idx <= lastIndex) && setTo(idx) def moveToEnd(): Unit = setTo(size) - // scala legacy interface - def asList: List[JEntry] = toEntries().toList - def asJavaList = entries() - def asStrings = buf.toList - def grep(s: String) = buf.toList filter (_ contains s) + def asStrings = buf.toList } diff --git a/src/compiler/scala/tools/nsc/io/Fileish.scala b/src/compiler/scala/tools/nsc/io/Fileish.scala deleted file mode 100644 index 7b4e385dd8..0000000000 --- a/src/compiler/scala/tools/nsc/io/Fileish.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package io - -import java.io.{ InputStream } -import java.util.jar.JarEntry - -/** A common interface for File-based things and Stream-based things. - * (In particular, io.File and JarEntry.) - */ -class Fileish(val path: Path, val input: () => InputStream) extends Streamable.Chars { - def inputStream() = input() - - def parent = path.parent - def name = path.name - def isSourceFile = path.hasExtension("java", "scala") - - private lazy val pkgLines = lines() collect { case x if x startsWith "package " => x stripPrefix "package" trim } - lazy val pkgFromPath = parent.path.replaceAll("""[/\\]""", ".") - lazy val pkgFromSource = pkgLines map (_ stripSuffix ";") mkString "." - - override def toString = path.path -} - -object Fileish { - def apply(f: File): Fileish = new Fileish(f, () => f.inputStream()) - def apply(f: JarEntry, in: () => InputStream): Fileish = new Fileish(Path(f.getName), in) - def apply(path: String, in: () => InputStream): Fileish = new Fileish(Path(path), in) -} diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala index e919621338..49a1ff114f 100644 --- a/src/compiler/scala/tools/nsc/io/Jar.scala +++ b/src/compiler/scala/tools/nsc/io/Jar.scala @@ -10,7 +10,6 @@ import java.io.{ InputStream, OutputStream, IOException, FileNotFoundException, import java.util.jar._ import scala.collection.JavaConverters._ import Attributes.Name -import util.ClassPath import scala.language.implicitConversions // Attributes.Name instances: @@ -37,9 +36,6 @@ class Jar(file: File) extends Iterable[JarEntry] { def this(jfile: JFile) = this(File(jfile)) def this(path: String) = this(File(path)) - protected def errorFn(msg: String): Unit = Console println msg - - lazy val jarFile = new JarFile(file.jfile) lazy val manifest = withJarInput(s => Option(s.getManifest)) def mainClass = manifest map (f => f(Name.MAIN_CLASS)) @@ -64,12 +60,6 @@ class Jar(file: File) extends Iterable[JarEntry] { Iterator continually in.getNextJarEntry() takeWhile (_ != null) foreach f } override def iterator: Iterator[JarEntry] = this.toList.iterator - def fileishIterator: Iterator[Fileish] = jarFile.entries.asScala map (x => Fileish(x, () => getEntryStream(x))) - - private def getEntryStream(entry: JarEntry) = jarFile getInputStream entry match { - case null => errorFn("No such entry: " + entry) ; null - case x => x - } override def toString = "" + file } @@ -131,7 +121,6 @@ object Jar { m } def apply(manifest: JManifest): WManifest = new WManifest(manifest) - implicit def unenrichManifest(x: WManifest): JManifest = x.underlying } class WManifest(manifest: JManifest) { for ((k, v) <- initialMainAttrs) @@ -148,12 +137,7 @@ object Jar { } def apply(name: Attributes.Name): String = attrs(name) - def apply(name: String): String = apply(new Attributes.Name(name)) def update(key: Attributes.Name, value: String) = attrs.put(key, value) - def update(key: String, value: String) = attrs.put(new Attributes.Name(key), value) - - def mainClass: String = apply(Name.MAIN_CLASS) - def mainClass_=(value: String) = update(Name.MAIN_CLASS, value) } // See http://download.java.net/jdk7/docs/api/java/nio/file/Path.html diff --git a/src/compiler/scala/tools/nsc/io/Lexer.scala b/src/compiler/scala/tools/nsc/io/Lexer.scala index 5ffb5b4d4f..e843f8d5ce 100644 --- a/src/compiler/scala/tools/nsc/io/Lexer.scala +++ b/src/compiler/scala/tools/nsc/io/Lexer.scala @@ -1,8 +1,6 @@ package scala.tools.nsc.io -import java.io.{Reader, Writer, StringReader, StringWriter} -import scala.collection.mutable.{Buffer, ArrayBuffer} -import scala.math.BigInt +import java.io.Reader /** Companion object of class `Lexer` which defines tokens and some utility concepts * used for tokens and lexers diff --git a/src/compiler/scala/tools/nsc/io/MsilFile.scala b/src/compiler/scala/tools/nsc/io/MsilFile.scala index 2f0a71fc60..bda13a5ed0 100644 --- a/src/compiler/scala/tools/nsc/io/MsilFile.scala +++ b/src/compiler/scala/tools/nsc/io/MsilFile.scala @@ -6,13 +6,10 @@ package scala.tools.nsc package io -import ch.epfl.lamp.compiler.msil.{ Type => MsilType, _ } +import ch.epfl.lamp.compiler.msil.{ Type => MsilType } /** This class wraps an MsilType. It exists only so * ClassPath can treat all of JVM/MSIL/bin/src files * uniformly, as AbstractFiles. */ -class MsilFile(val msilType: MsilType) extends VirtualFile(msilType.FullName, msilType.Namespace) { -} - -object NoMsilFile extends MsilFile(null) { } +class MsilFile(val msilType: MsilType) extends VirtualFile(msilType.FullName, msilType.Namespace) { } diff --git a/src/compiler/scala/tools/nsc/io/Pickler.scala b/src/compiler/scala/tools/nsc/io/Pickler.scala index b03a921e87..5d32c10143 100644 --- a/src/compiler/scala/tools/nsc/io/Pickler.scala +++ b/src/compiler/scala/tools/nsc/io/Pickler.scala @@ -1,6 +1,5 @@ package scala.tools.nsc.io -import scala.annotation.unchecked import Lexer._ import java.io.Writer import scala.language.implicitConversions @@ -71,14 +70,6 @@ abstract class Pickler[T] { */ def wrapped [U] (in: T => U)(out: U => T): Pickler[U] = wrappedPickler(this)(in)(out) - /** A pickler obtained from the current pickler by also admitting `null` as - * a handled value, represented as the token `null`. - * - * @param fromNull an implicit evidence parameter ensuring that the type of values - * handled by this pickler contains `null`. - */ - def orNull(implicit fromNull: Null <:< T): Pickler[T] = nullablePickler(this) - /** A conditional pickler obtained from the current pickler. * @param cond the condition to test to find out whether pickler can handle * some Scala value. @@ -93,9 +84,6 @@ abstract class Pickler[T] { } object Pickler { - - var picklerDebugMode = false - /** A base class representing unpickler result. It has two subclasses: * `UnpickleSucess` for successful unpicklings and `UnpickleFailure` for failures, * where a value of the given type `T` could not be unpickled from input. @@ -175,17 +163,6 @@ object Pickler { def ~ [T](y: T): S ~ T = new ~ (x, y) } - /** A converter from binary functions to functions over `~`-pairs - */ - implicit def fromTilde[T1, T2, R](f: (T1, T2) => R): T1 ~ T2 => R = { case x1 ~ x2 => f(x1, x2) } - - /** An converter from unctions returning Options over pair to functions returning `~`-pairs - * The converted function will raise a `MatchError` where the original function returned - * a `None`. This converter is useful for turning `unapply` methods of case classes - * into wrapper methods that can be passed as second argument to `wrap`. - */ - implicit def toTilde[T1, T2, S](f: S => Option[(T1, T2)]): S => T1 ~ T2 = { x => (f(x): @unchecked) match { case Some((x1, x2)) => x1 ~ x2 } } - /** Same as `p.labelled(label)`. */ def labelledPickler[T](label: String, p: Pickler[T]): Pickler[T] = new Pickler[T] { @@ -249,16 +226,6 @@ object Pickler { def unpickle(rd: Lexer) = p.unpickle(rd) orElse qq.unpickle(rd) } - /** Same as `p.orNull` - */ - def nullablePickler[T](p: Pickler[T])(implicit fromNull: Null <:< T): Pickler[T] = new Pickler[T] { - def pickle(wr: Writer, x: T) = - if (x == null) wr.write("null") else p.pickle(wr, x) - def unpickle(rd: Lexer): Unpickled[T] = - if (rd.token == NullLit) nextSuccess(rd, fromNull(null)) - else p.unpickle(rd) - } - /** A conditional pickler for singleton objects. It represents these * with the object's underlying class as a label. * Example: Object scala.None would be represented as `scala.None$()`. @@ -330,22 +297,9 @@ object Pickler { implicit val longPickler: Pickler[Long] = tokenPickler("integer literal") { case IntLit(s) => s.toLong } - /** A pickler for values of type `Double`, represented as floating point literals */ - implicit val doublePickler: Pickler[Double] = - tokenPickler("floating point literal") { case FloatLit(s) => s.toDouble } - - /** A pickler for values of type `Byte`, represented as integer literals */ - implicit val bytePickler: Pickler[Byte] = longPickler.wrapped { _.toByte } { _.toLong } - - /** A pickler for values of type `Short`, represented as integer literals */ - implicit val shortPickler: Pickler[Short] = longPickler.wrapped { _.toShort } { _.toLong } - /** A pickler for values of type `Int`, represented as integer literals */ implicit val intPickler: Pickler[Int] = longPickler.wrapped { _.toInt } { _.toLong } - /** A pickler for values of type `Float`, represented as floating point literals */ - implicit val floatPickler: Pickler[Float] = doublePickler.wrapped { _.toFloat } { _.toLong } - /** A conditional pickler for the boolean value `true` */ private val truePickler = tokenPickler("boolean literal") { case TrueLit => true } cond { _ == true } @@ -373,52 +327,15 @@ object Pickler { } } - /** A pickler for values of type `Char`, represented as string literals of length 1 */ - implicit val charPickler: Pickler[Char] = - stringPickler - .wrapped { s => require(s.length == 1, "single character string literal expected, but "+quoted(s)+" found"); s(0) } { _.toString } - - /** A pickler for pairs, represented as `~`-pairs */ - implicit def tuple2Pickler[T1: Pickler, T2: Pickler]: Pickler[(T1, T2)] = - (pkl[T1] ~ pkl[T2]) - .wrapped { case x1 ~ x2 => (x1, x2) } { case (x1, x2) => x1 ~ x2 } - .labelled ("tuple2") - /** A pickler for 3-tuples, represented as `~`-tuples */ implicit def tuple3Pickler[T1, T2, T3](implicit p1: Pickler[T1], p2: Pickler[T2], p3: Pickler[T3]): Pickler[(T1, T2, T3)] = (p1 ~ p2 ~ p3) .wrapped { case x1 ~ x2 ~ x3 => (x1, x2, x3) } { case (x1, x2, x3) => x1 ~ x2 ~ x3 } .labelled ("tuple3") - /** A pickler for 4-tuples, represented as `~`-tuples */ - implicit def tuple4Pickler[T1, T2, T3, T4](implicit p1: Pickler[T1], p2: Pickler[T2], p3: Pickler[T3], p4: Pickler[T4]): Pickler[(T1, T2, T3, T4)] = - (p1 ~ p2 ~ p3 ~ p4) - .wrapped { case x1 ~ x2 ~ x3 ~ x4 => (x1, x2, x3, x4) } { case (x1, x2, x3, x4) => x1 ~ x2 ~ x3 ~ x4 } - .labelled ("tuple4") - - /** A conditional pickler for the `scala.None` object */ - implicit val nonePickler = singletonPickler(None) - - /** A conditional pickler for instances of class `scala.Some` */ - implicit def somePickler[T: Pickler]: CondPickler[Some[T]] = - pkl[T] - .wrapped { Some(_) } { _.get } - .asClass (classOf[Some[T]]) - - /** A pickler for optional values */ - implicit def optionPickler[T: Pickler]: Pickler[Option[T]] = nonePickler | somePickler[T] - /** A pickler for list values */ implicit def listPickler[T: Pickler]: Pickler[List[T]] = iterPickler[T] .wrapped { _.toList } { _.iterator } .labelled ("scala.List") - - /** A pickler for vector values */ - implicit def vectorPickler[T: Pickler]: Pickler[Vector[T]] = - iterPickler[T] .wrapped { Vector() ++ _ } { _.iterator } .labelled ("scala.Vector") - - /** A pickler for array values */ - implicit def array[T : ClassTag : Pickler]: Pickler[Array[T]] = - iterPickler[T] .wrapped { _.toArray} { _.iterator } .labelled ("scala.Array") } /** A subclass of Pickler can indicate whether a particular value can be pickled by instances diff --git a/src/compiler/scala/tools/nsc/io/Replayer.scala b/src/compiler/scala/tools/nsc/io/Replayer.scala index 5cb61b6cb1..e3dc8939a3 100644 --- a/src/compiler/scala/tools/nsc/io/Replayer.scala +++ b/src/compiler/scala/tools/nsc/io/Replayer.scala @@ -3,7 +3,7 @@ package scala.tools.nsc.io import java.io.{Reader, Writer} import Pickler._ -import Lexer.{Token, EOF} +import Lexer.EOF abstract class LogReplay { def logreplay(event: String, x: => Boolean): Boolean diff --git a/src/compiler/scala/tools/nsc/io/Socket.scala b/src/compiler/scala/tools/nsc/io/Socket.scala index e766c1b2fd..4925c50d85 100644 --- a/src/compiler/scala/tools/nsc/io/Socket.scala +++ b/src/compiler/scala/tools/nsc/io/Socket.scala @@ -28,13 +28,10 @@ object Socket { private val optHandler = handlerFn[Option[T]](_ => None) private val eitherHandler = handlerFn[Either[Throwable, T]](x => Left(x)) - def getOrElse[T1 >: T](alt: T1): T1 = opt getOrElse alt def either: Either[Throwable, T] = try Right(f()) catch eitherHandler def opt: Option[T] = try Some(f()) catch optHandler } - def newIPv4Server(port: Int = 0) = new Box(() => preferringIPv4(new ServerSocket(0))) - def newServer(port: Int = 0) = new Box(() => new ServerSocket(0)) def localhost(port: Int) = apply(InetAddress.getLocalHost(), port) def apply(host: InetAddress, port: Int) = new Box(() => new Socket(new JSocket(host, port))) def apply(host: String, port: Int) = new Box(() => new Socket(new JSocket(host, port))) @@ -62,4 +59,4 @@ class Socket(jsocket: JSocket) extends Streamable.Bytes with Closeable { out.close() } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/io/SourceReader.scala b/src/compiler/scala/tools/nsc/io/SourceReader.scala index 569270f530..ece78db2cf 100644 --- a/src/compiler/scala/tools/nsc/io/SourceReader.scala +++ b/src/compiler/scala/tools/nsc/io/SourceReader.scala @@ -9,7 +9,7 @@ package io import java.io.{ FileInputStream, InputStream, IOException } import java.nio.{ByteBuffer, CharBuffer} -import java.nio.channels.{FileChannel, ReadableByteChannel, Channels} +import java.nio.channels.{ ReadableByteChannel, Channels } import java.nio.charset.{CharsetDecoder, CoderResult} import scala.tools.nsc.reporters._ @@ -33,9 +33,6 @@ class SourceReader(decoder: CharsetDecoder, reporter: Reporter) { "Please try specifying another one using the -encoding option") } - /** Reads the file with the specified name. */ - def read(filename: String): Array[Char]= read(new JFile(filename)) - /** Reads the specified file. */ def read(file: JFile): Array[Char] = { val c = new FileInputStream(file).getChannel diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala index 711696bb6e..0b2db115fb 100644 --- a/src/compiler/scala/tools/nsc/io/package.scala +++ b/src/compiler/scala/tools/nsc/io/package.scala @@ -7,7 +7,6 @@ package scala.tools.nsc import java.util.concurrent.{ Future, Callable } import java.util.{ Timer, TimerTask } -import java.util.jar.{ Attributes } import scala.language.implicitConversions package object io { @@ -21,14 +20,10 @@ package object io { type Path = scala.reflect.io.Path val Path = scala.reflect.io.Path type PlainFile = scala.reflect.io.PlainFile - val PlainFile = scala.reflect.io.PlainFile val Streamable = scala.reflect.io.Streamable type VirtualDirectory = scala.reflect.io.VirtualDirectory type VirtualFile = scala.reflect.io.VirtualFile - val ZipArchive = scala.reflect.io.ZipArchive type ZipArchive = scala.reflect.io.ZipArchive - - implicit def postfixOps = scala.language.postfixOps // make all postfix ops in this package compile without warning type JManifest = java.util.jar.Manifest type JFile = java.io.File @@ -39,23 +34,11 @@ package object io { def runnable(body: => Unit): Runnable = new Runnable { override def run() = body } def callable[T](body: => T): Callable[T] = new Callable[T] { override def call() = body } def spawn[T](body: => T): Future[T] = daemonThreadPool submit callable(body) - def submit(runnable: Runnable) = daemonThreadPool submit runnable - // Create, start, and return a daemon thread - def daemonize(body: => Unit): Thread = newThread(_ setDaemon true)(body) def newThread(f: Thread => Unit)(body: => Unit): Thread = { val thread = new Thread(runnable(body)) f(thread) thread.start thread } - - // Set a timer to execute the given code. - def timer(seconds: Int)(body: => Unit): Timer = { - val alarm = new Timer(true) // daemon - val tt = new TimerTask { def run() = body } - - alarm.schedule(tt, seconds * 1000) - alarm - } } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 43a8402fc7..73cbeaa6c4 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -35,7 +35,6 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { abstract class JavaParser extends ParserCommon { val in: JavaScanner - protected def posToReport: Int = in.currentPos def freshName(prefix : String): Name protected implicit def i2p(offset : Int) : Position private implicit def p2i(pos : Position): Int = if (pos.isDefined) pos.point else -1 @@ -94,11 +93,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { if (skipIt) skip() } - def warning(msg: String) : Unit = warning(in.currentPos, msg) - def errorTypeTree = TypeTree().setType(ErrorType) setPos in.currentPos - def errorTermTree = Literal(Constant(null)) setPos in.currentPos - def errorPatternTree = blankExpr setPos in.currentPos // --------- tree building ----------------------------- @@ -178,11 +173,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def accept(token: Int): Int = { val pos = in.currentPos if (in.token != token) { - val posToReport = - //if (in.currentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0)) - // in.lastPos - //else - in.currentPos + val posToReport = in.currentPos val msg = JavaScannerConfiguration.token2string(token) + " expected but " + JavaScannerConfiguration.token2string(in.token) + " found." @@ -348,46 +339,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { /** Annotation ::= TypeName [`(` AnnotationArgument {`,` AnnotationArgument} `)`] */ def annotation() { - val pos = in.currentPos - var t = qualId() + qualId() if (in.token == LPAREN) { skipAhead(); accept(RPAREN) } else if (in.token == LBRACE) { skipAhead(); accept(RBRACE) } } -/* - def annotationArg() = { - val pos = in.token - if (in.token == IDENTIFIER && in.lookaheadToken == ASSIGN) { - val name = ident() - accept(ASSIGN) - atPos(pos) { - ValDef(Modifiers(Flags.JAVA), name, TypeTree(), elementValue()) - } - } else { - elementValue() - } - } - - def elementValue(): Tree = - if (in.token == AT) annotation() - else if (in.token == LBRACE) elementValueArrayInitializer() - else expression1() - - def elementValueArrayInitializer() = { - accept(LBRACE) - val buf = new ListBuffer[Tree] - def loop() = - if (in.token != RBRACE) { - buf += elementValue() - if (in.token == COMMA) { - in.nextToken - loop() - } - } - loop() - accept(RBRACE) - buf.toList - } - */ def modifiers(inInterface: Boolean): Modifiers = { var flags: Long = Flags.JAVA diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index e230585a8b..84eee36f18 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -57,23 +57,14 @@ trait JavaScanners extends ast.parser.ScannersCommon { /** ... */ abstract class AbstractJavaScanner extends AbstractJavaTokenData { - implicit def p2g(pos: Position): ScanPosition implicit def g2p(pos: ScanPosition): Position - /** the last error position - */ - var errpos: ScanPosition - var lastPos: ScanPosition - def skipToken: ScanPosition def nextToken(): Unit def next: AbstractJavaTokenData def intVal(negated: Boolean): Long def floatVal(negated: Boolean): Double def intVal: Long = intVal(false) def floatVal: Double = floatVal(false) - //def token2string(token : Int) : String = configuration.token2string(token) - /** return recent scala doc, if any */ - def flushDoc: DocComment def currentPos: Position } @@ -227,17 +218,9 @@ trait JavaScanners extends ast.parser.ScannersCommon { abstract class JavaScanner extends AbstractJavaScanner with JavaTokenData with Cloneable with ScannerCommon { override def intVal = super.intVal// todo: needed? override def floatVal = super.floatVal - override var errpos: Int = NoPos def currentPos: Position = g2p(pos - 1) - var in: JavaCharArrayReader = _ - def dup: JavaScanner = { - val dup = clone().asInstanceOf[JavaScanner] - dup.in = in.dup - dup - } - /** character buffer for literals */ val cbuf = new StringBuilder() @@ -256,12 +239,6 @@ trait JavaScanners extends ast.parser.ScannersCommon { */ var docBuffer: StringBuilder = null - def flushDoc: DocComment = { - val ret = if (docBuffer != null) DocComment(docBuffer.toString, NoPosition) else null - docBuffer = null - ret - } - /** add the given character to the documentation buffer */ protected def putDocChar(c: Char) { @@ -277,13 +254,6 @@ trait JavaScanners extends ast.parser.ScannersCommon { // Get next token ------------------------------------------------------------ - /** read next token and return last position - */ - def skipToken: Int = { - val p = pos; nextToken - p - 1 - } - def nextToken() { if (next.token == EMPTY) { fetchToken() @@ -308,7 +278,6 @@ trait JavaScanners extends ast.parser.ScannersCommon { private def fetchToken() { if (token == EOF) return lastPos = in.cpos - 1 - //var index = bp while (true) { in.ch match { case ' ' | '\t' | CR | LF | FF => @@ -868,7 +837,6 @@ trait JavaScanners extends ast.parser.ScannersCommon { def syntaxError(pos: Int, msg: String) { error(pos, msg) token = ERROR - errpos = pos } /** generate an error at the current token position @@ -879,7 +847,6 @@ trait JavaScanners extends ast.parser.ScannersCommon { def incompleteInputError(msg: String) { incompleteInputError(pos, msg) token = EOF - errpos = pos } override def toString() = token match { @@ -913,16 +880,12 @@ trait JavaScanners extends ast.parser.ScannersCommon { } } - /** ... - */ class JavaUnitScanner(unit: CompilationUnit) extends JavaScanner { in = new JavaCharArrayReader(unit.source.content, !settings.nouescape.value, syntaxError) init - def warning(pos: Int, msg: String) = unit.warning(pos, msg) def error (pos: Int, msg: String) = unit. error(pos, msg) def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg) def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg) - implicit def p2g(pos: Position): Int = if (pos.isDefined) pos.point else -1 implicit def g2p(pos: Int): Position = new OffsetPosition(unit.source, pos) } } diff --git a/src/compiler/scala/tools/nsc/javac/JavaTokens.scala b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala index a562de291d..953a3c6d82 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaTokens.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala @@ -68,9 +68,6 @@ object JavaTokens extends ast.parser.Tokens { final val VOLATILE = 68 final val WHILE = 69 - def isKeyword(code : Int) = - code >= ABSTRACT && code <= WHILE - /** special symbols */ final val COMMA = 70 final val SEMI = 71 @@ -115,9 +112,6 @@ object JavaTokens extends ast.parser.Tokens { final val GTGTEQ = 113 final val GTGTGTEQ = 114 - def isSymbol(code : Int) = - code >= COMMA && code <= GTGTGTEQ - /** parenthesis */ final val LPAREN = 115 final val RPAREN = 116 diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index 5ca9fd5062..3c26997cfe 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -6,9 +6,6 @@ package scala.tools.nsc package matching -import transform.ExplicitOuter -import ast.{ Printers, Trees } -import java.io.{ StringWriter, PrintWriter } import scala.annotation.elidable import scala.language.postfixOps @@ -25,9 +22,6 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => def impossible: Nothing = abort("this never happens") - def treeCollect[T](tree: Tree, pf: PartialFunction[Tree, T]): List[T] = - tree filter (pf isDefinedAt _) map (x => pf(x)) - object Types { import definitions._ @@ -39,24 +33,12 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => // These tests for final classes can inspect the typeSymbol private def is(s: Symbol) = tpe.typeSymbol eq s - def isByte = is(ByteClass) - def isShort = is(ShortClass) def isInt = is(IntClass) - def isChar = is(CharClass) - def isBoolean = is(BooleanClass) def isNothing = is(NothingClass) - def isArray = is(ArrayClass) } } object Debug { - def typeToString(t: Type): String = t match { - case NoType => "x" - case x => x.toString - } - def symbolToString(s: Symbol): String = s match { - case x => x.toString - } def treeToString(t: Tree): String = treeInfo.unbind(t) match { case EmptyTree => "?" case WILD() => "_" @@ -69,10 +51,6 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => // Formatting for some error messages private val NPAD = 15 def pad(s: String): String = "%%%ds" format (NPAD-1) format s - def pad(s: Any): String = pad(s match { - case x: Tree => treeToString(x) - case x => x.toString - }) // pretty print for debugging def pp(x: Any): String = pp(x, false) @@ -120,7 +98,6 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => else x } - def indent(s: Any) = s.toString() split "\n" map (" " + _) mkString "\n" def indentAll(s: Seq[Any]) = s map (" " + _.toString() + "\n") mkString } diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index daefe4c545..ba966acf34 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -140,7 +140,6 @@ trait Matrix extends MatrixAdditions { cases: List[CaseDef], default: Tree ) { - def tvars = roots map (_.lhs) def valDefs = roots map (_.valDef) override def toString() = "MatrixInit(roots = %s, %d cases)".format(pp(roots), cases.size) } @@ -151,27 +150,12 @@ trait Matrix extends MatrixAdditions { object PatternVarGroup { def apply(xs: PatternVar*) = new PatternVarGroup(xs.toList) def apply(xs: List[PatternVar]) = new PatternVarGroup(xs) - - // XXX - transitional - def fromBindings(vlist: List[Binding], freeVars: List[Symbol] = Nil) = { - def vmap(v: Symbol): Option[Binding] = vlist find (_.pvar eq v) - val info = - if (freeVars.isEmpty) vlist - else (freeVars map vmap).flatten - - val xs = - for (Binding(lhs, rhs) <- info) yield - new PatternVar(lhs, Ident(rhs) setType lhs.tpe, !(rhs hasFlag NO_EXHAUSTIVE)) - - new PatternVarGroup(xs) - } } val emptyPatternVarGroup = PatternVarGroup() class PatternVarGroup(val pvs: List[PatternVar]) { def syms = pvs map (_.sym) def valDefs = pvs map (_.valDef) - def idents = pvs map (_.ident) def extractIndex(index: Int): (PatternVar, PatternVarGroup) = { val (t, ts) = self.extractIndex(pvs, index) @@ -180,16 +164,11 @@ trait Matrix extends MatrixAdditions { def isEmpty = pvs.isEmpty def size = pvs.size - def head = pvs.head - def ::(t: PatternVar) = PatternVarGroup(t :: pvs) def :::(ts: List[PatternVar]) = PatternVarGroup(ts ::: pvs) - def ++(other: PatternVarGroup) = PatternVarGroup(pvs ::: other.pvs) def apply(i: Int) = pvs(i) def zipWithIndex = pvs.zipWithIndex def indices = pvs.indices - def map[T](f: PatternVar => T) = pvs map f - def filter(p: PatternVar => Boolean) = PatternVarGroup(pvs filter p) override def toString() = pp(pvs) } @@ -237,17 +216,11 @@ trait Matrix extends MatrixAdditions { tracing("create")(new PatternVar(lhs, rhs, checked)) } - def createLazy(tpe: Type, f: Symbol => Tree, checked: Boolean) = { - val lhs = newVar(owner.pos, tpe, Flags.LAZY :: flags(checked)) - val rhs = f(lhs) - - tracing("createLazy")(new PatternVar(lhs, rhs, checked)) - } private def newVar( pos: Position, tpe: Type, - flags: List[Long] = Nil, + flags: List[Long], name: TermName = null): Symbol = { val n = if (name == null) cunit.freshTermName("temp") else name diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala index 7220253003..b1ca6e7b5a 100644 --- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package matching import transform.ExplicitOuter -import PartialFunction._ /** Traits which are mixed into MatchMatrix, but separated out as * (somewhat) independent components to keep them on the sidelines. @@ -17,7 +16,6 @@ trait MatrixAdditions extends ast.TreeDSL { import global.{ typer => _, _ } import symtab.Flags - import CODE._ import Debug._ import treeInfo._ import definitions.{ isPrimitiveValueClass } @@ -190,4 +188,4 @@ trait MatrixAdditions extends ast.TreeDSL { } } } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 9d01e73063..b5e25f3809 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -9,11 +9,8 @@ package matching import PartialFunction._ import scala.collection.{ mutable } -import scala.reflect.internal.util.Position import transform.ExplicitOuter -import symtab.Flags import mutable.ListBuffer -import scala.annotation.elidable import scala.language.postfixOps trait ParallelMatching extends ast.TreeDSL @@ -26,7 +23,7 @@ trait ParallelMatching extends ast.TreeDSL import global.{ typer => _, _ } import definitions.{ - AnyRefClass, IntClass, BooleanClass, SomeClass, OptionClass, + IntClass, BooleanClass, SomeClass, OptionClass, getProductArgs, productProj, Object_eq, Any_asInstanceOf } import CODE._ @@ -129,7 +126,7 @@ trait ParallelMatching extends ast.TreeDSL // for propagating "unchecked" to synthetic vars def isChecked = !(sym hasFlag NO_EXHAUSTIVE) - def flags: List[Long] = List(NO_EXHAUSTIVE) filter (sym hasFlag _) + // def flags: List[Long] = List(NO_EXHAUSTIVE) filter (sym hasFlag _) // this is probably where this actually belongs def createVar(tpe: Type, f: Symbol => Tree) = context.createVar(tpe, f, isChecked) @@ -173,7 +170,7 @@ trait ParallelMatching extends ast.TreeDSL case class PatternMatch(scrut: Scrutinee, ps: List[Pattern]) { def head = ps.head def tail = ps.tail - def size = ps.length + // def size = ps.length def headType = head.necessaryType private val dummyCount = if (head.isCaseClass) headType.typeSymbol.caseFieldAccessors.length else 0 @@ -579,7 +576,7 @@ trait ParallelMatching extends ast.TreeDSL (_ys.toList, _ns.toList) } - val moreSpecific = yeses map (_.moreSpecific) + // val moreSpecific = yeses map (_.moreSpecific) val subsumed = yeses map (x => (x.bx, x.subsumed)) val remaining = noes map (x => (x.bx, x.remaining)) diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala index 7b2fcf0e9b..c6fa6f6ba0 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package matching import transform.ExplicitOuter -import PartialFunction._ import scala.language.postfixOps trait PatternBindings extends ast.TreeDSL @@ -17,7 +16,6 @@ trait PatternBindings extends ast.TreeDSL import global.{ typer => _, _ } import definitions.{ EqualsPatternClass } import CODE._ - import Debug._ /** EqualsPattern **/ def isEquals(tpe: Type) = tpe.typeSymbol == EqualsPatternClass @@ -61,10 +59,6 @@ trait PatternBindings extends ast.TreeDSL trait PatternBindingLogic { self: Pattern => - // This is for traversing the pattern tree - pattern types which might have - // bound variables beneath them return a list of said patterns for flatMapping. - def subpatternsForVars: List[Pattern] = Nil - // The outermost Bind(x1, Bind(x2, ...)) surrounding the tree. private var _boundTree: Tree = tree def boundTree = _boundTree @@ -108,8 +102,6 @@ trait PatternBindings extends ast.TreeDSL case b @ Bind(_, pat) => b.symbol :: strip(pat) case _ => Nil } - private def deepstrip(t: Tree): List[Symbol] = - treeCollect(t, { case x: Bind => x.symbol }) } case class Binding(pvar: Symbol, tvar: Symbol) { @@ -117,9 +109,6 @@ trait PatternBindings extends ast.TreeDSL } class Bindings(private val vlist: List[Binding]) { - // if (!vlist.isEmpty) - // traceCategory("Bindings", this.toString) - def get() = vlist def toMap = vlist map (x => (x.pvar, x.tvar)) toMap diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 99b72fa26e..df536da108 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package matching -import symtab.Flags import PartialFunction._ /** Patterns are wrappers for Trees with enhanced semantics. @@ -33,9 +32,6 @@ trait Patterns extends ast.TreeDSL { // An empty pattern def NoPattern = WildcardPattern() - // The constant null pattern - def NullPattern = LiteralPattern(NULL) - // The Nil pattern def NilPattern = Pattern(gen.mkNil) @@ -61,7 +57,6 @@ trait Patterns extends ast.TreeDSL { override def covers(sym: Symbol) = newMatchesPattern(sym, tpt.tpe) override def sufficientType = tpt.tpe - override def subpatternsForVars: List[Pattern] = List(Pattern(expr)) override def simplify(pv: PatternVar) = Pattern(expr) match { case ExtractorPattern(ua) if pv.sym.tpe <:< tpt.tpe => this rebindTo expr case _ => this @@ -141,10 +136,6 @@ trait Patterns extends ast.TreeDSL { require(fn.isType && this.isCaseClass, "tree: " + tree + " fn: " + fn) def name = tpe.typeSymbol.name def cleanName = tpe.typeSymbol.decodedName - def hasPrefix = tpe.prefix.prefixString != "" - def prefixedName = - if (hasPrefix) "%s.%s".format(tpe.prefix.prefixString, cleanName) - else cleanName private def isColonColon = cleanName == "::" @@ -189,13 +180,6 @@ trait Patterns extends ast.TreeDSL { private lazy val packedType = global.typer.computeType(tpt, tpt.tpe) private lazy val consRef = appliedType(ConsClass, packedType) private lazy val listRef = appliedType(ListClass, packedType) - private lazy val seqRef = appliedType(SeqClass, packedType) - - private def thisSeqRef = { - val tc = (tree.tpe baseType SeqClass).typeConstructor - if (tc.typeParams.size == 1) appliedType(tc, List(packedType)) - else seqRef - } // Fold a list into a well-typed x :: y :: etc :: tree. private def listFolder(hd: Tree, tl: Tree): Tree = unbind(hd) match { @@ -230,15 +214,13 @@ trait Patterns extends ast.TreeDSL { // 8.1.8 (b) (literal ArrayValues) case class SequencePattern(tree: ArrayValue) extends Pattern with SequenceLikePattern { - lazy val ArrayValue(elemtpt, elems) = tree + lazy val ArrayValue(_, elems) = tree - override def subpatternsForVars: List[Pattern] = elemPatterns override def description = "Seq(%s)".format(elemPatterns mkString ", ") } // 8.1.8 (c) case class StarPattern(tree: Star) extends Pattern { - lazy val Star(elem) = tree override def description = "_*" } // XXX temporary? @@ -392,15 +374,7 @@ trait Patterns extends ast.TreeDSL { // Covers if the symbol matches the unapply method's argument type, // and the return type of the unapply is Some. override def covers(sym: Symbol) = newMatchesPattern(sym, arg.tpe) - - // TODO: for alwaysCovers: - // fn.tpe.finalResultType.typeSymbol == SomeClass - override def necessaryType = arg.tpe - override def subpatternsForVars = args match { - case List(ArrayValue(elemtpe, elems)) => toPats(elems) - case _ => toPats(args) - } def resTypes = analyzer.unapplyTypeList(unfn.symbol, unfn.tpe, args.length) def resTypesString = resTypes match { @@ -411,13 +385,7 @@ trait Patterns extends ast.TreeDSL { sealed trait ApplyPattern extends Pattern { lazy val Apply(fn, args) = tree - override def subpatternsForVars: List[Pattern] = toPats(args) - override def dummies = - if (!this.isCaseClass) Nil - else emptyPatterns(sufficientType.typeSymbol.caseFieldAccessors.size) - - def isConstructorPattern = fn.isType override def covers(sym: Symbol) = newMatchesPattern(sym, fn.tpe) } @@ -427,9 +395,6 @@ trait Patterns extends ast.TreeDSL { // returns either a simplification of this pattern or identity. def simplify(pv: PatternVar): Pattern = this - // the right number of dummies for this pattern - def dummies: List[Pattern] = Nil - // Is this a default pattern (untyped "_" or an EmptyTree inserted by the matcher) def isDefault = false @@ -459,14 +424,8 @@ trait Patterns extends ast.TreeDSL { def isModule = sym.isModule || tpe.termSymbol.isModule def isCaseClass = tpe.typeSymbol.isCase def isObject = (sym != null) && (sym != NoSymbol) && tpe.prefix.isStable // XXX not entire logic - def hasStar = false - def setType(tpe: Type): this.type = { - tree setType tpe - this - } - def equalsCheck = tracing("equalsCheck")( if (sym.isValue) singleType(NoPrefix, sym) @@ -483,7 +442,6 @@ trait Patterns extends ast.TreeDSL { final override def toString = description - def toTypeString() = "%s <: x <: %s".format(necessaryType, sufficientType) def kindString = "" } diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala index 2050ce7ffd..093f8285e1 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala @@ -6,13 +6,10 @@ package scala.tools.nsc package plugins -import io.{ File, Path, Jar } +import io.{ Path, Jar } import java.net.URLClassLoader import java.util.jar.JarFile import java.util.zip.ZipException - -import scala.collection.mutable -import mutable.ListBuffer import scala.xml.XML /** Information about a plugin loaded from a jar file. @@ -74,7 +71,7 @@ object Plugin { } /** Try to load a plugin description from the specified - * file, returning <code>None</code> if it does not work. + * file, returning `None` if it does not work. */ private def loadDescription(jarfile: Path): Option[PluginDescription] = // XXX Return to this once we have some ARM support diff --git a/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala b/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala index bd567400fb..f77123ba11 100644 --- a/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala +++ b/src/compiler/scala/tools/nsc/plugins/PluginDescription.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package plugins -import scala.xml.{Node,NodeSeq} +import scala.xml.Node /** A description of a compiler plugin, suitable for serialization * to XML for inclusion in the plugin's .jar file. @@ -26,7 +26,7 @@ abstract class PluginDescription { val classname: String /** An XML representation of this description. It can be - * read back using <code>PluginDescription.fromXML</code>. + * read back using `PluginDescription.fromXML`. * It should be stored inside the jar archive file. */ def toXML: Node = { diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala index c7ee11dec0..025fc8e068 100644 --- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala @@ -29,11 +29,7 @@ abstract class AbstractReporter extends Reporter { private def noWarnings = settings.nowarnings.value private def isPromptSet = settings.prompt.value - protected def info0(pos: Position, msg: String, _severity: Severity, force: Boolean) { - val severity = - if (settings.fatalWarnings.value && _severity == WARNING) ERROR - else _severity - + protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean) { if (severity == INFO) { if (isVerbose || force) { severity.count += 1 diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index e847fb5b86..bda195f9d3 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -34,9 +34,6 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr } /** Returns the number of errors issued totally as a string. - * - * @param severity ... - * @return ... */ private def getCountString(severity: Severity): String = StringOps.countElementsAsString((severity).count, label(severity)) @@ -52,17 +49,12 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr printMessage(pos, clabel(severity) + msg) } - /** - * @param pos ... - */ def printSourceLine(pos: Position) { printMessage(pos.lineContent.stripLineEnd) printColumnMarker(pos) } /** Prints the column marker of the given position. - * - * @param pos ... */ def printColumnMarker(pos: Position) = if (pos.isDefined) { printMessage(" " * (pos.column - 1) + "^") } @@ -94,6 +86,5 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr } } - private def abort(msg: String) = throw new Error(msg) override def flush() { writer.flush() } } diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index 8871ae6555..817ec47ab3 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package reporters import scala.reflect.internal.util._ -import scala.reflect.internal.util.StringOps._ /** * This interface provides methods to issue information, warning and diff --git a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala index 10e9982594..3aecc06b1e 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala @@ -2,9 +2,6 @@ package scala.tools.nsc.scratchpad import java.io.{FileInputStream, InputStreamReader, IOException} -import scala.runtime.ScalaRunTime.stringOf -import java.lang.reflect.InvocationTargetException -import scala.reflect.runtime.ReflectionUtils._ import scala.collection.mutable.ArrayBuffer @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") diff --git a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala index 01dccd7521..61c1717fea 100644 --- a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala +++ b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala @@ -1,8 +1,6 @@ package scala.tools.nsc package scratchpad -import java.io.Writer -import scala.reflect.internal.util.SourceFile import scala.reflect.internal.Chars._ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0") diff --git a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala index adabeb02a3..4727e6d867 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala @@ -47,8 +47,6 @@ trait AbsSettings extends scala.reflect.internal.settings.AbsSettings { } }) - implicit lazy val SettingOrdering: Ordering[Setting] = Ordering.ordered - trait AbsSetting extends Ordered[Setting] with AbsSettingValue { def name: String def helpDescription: String @@ -83,14 +81,6 @@ trait AbsSettings extends scala.reflect.internal.settings.AbsSettings { this } - /** If the appearance of the setting should halt argument processing. */ - private var isTerminatorSetting = false - def shouldStopProcessing = isTerminatorSetting - def stopProcessing(): this.type = { - isTerminatorSetting = true - this - } - /** Issue error and return */ def errorAndValue[T](msg: String, x: T): T = { errorFn(msg) ; x } @@ -110,6 +100,7 @@ trait AbsSettings extends scala.reflect.internal.settings.AbsSettings { /** Attempt to set from a properties file style property value. * Currently used by Eclipse SDT only. + * !!! Needs test. */ def tryToSetFromPropertyValue(s: String): Unit = tryToSet(s :: Nil) @@ -133,7 +124,7 @@ trait AbsSettings extends scala.reflect.internal.settings.AbsSettings { case _ => false } override def hashCode() = name.hashCode + value.hashCode - override def toString() = name + " = " + value + override def toString() = name + " = " + (if (value == "") "\"\"" else value) } trait InternalSetting extends AbsSetting { diff --git a/src/compiler/scala/tools/nsc/settings/AdvancedScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/AdvancedScalaSettings.scala deleted file mode 100644 index 0bec113743..0000000000 --- a/src/compiler/scala/tools/nsc/settings/AdvancedScalaSettings.scala +++ /dev/null @@ -1,77 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package settings - -trait AdvancedScalaSettings { - self: AbsScalaSettings => - - abstract class X extends SettingGroup("-X") { - val assemextdirs: StringSetting - val assemname: StringSetting - val assempath: StringSetting - val checkinit: BooleanSetting - val disableassertions: BooleanSetting - val elidebelow: IntSetting - val experimental: BooleanSetting - val future: BooleanSetting - val generatephasegraph: StringSetting - val logimplicits: BooleanSetting - val mainClass: StringSetting - val migration: BooleanSetting - val noforwarders: BooleanSetting - val nojline: BooleanSetting - val nouescape: BooleanSetting - val plugin: MultiStringSetting - val plugindisable: MultiStringSetting - val pluginlist: BooleanSetting - val pluginrequire: MultiStringSetting - val pluginsdir: StringSetting - val print: PhasesSetting - val printicode: BooleanSetting - val printpos: BooleanSetting - val printtypes: BooleanSetting - val prompt: BooleanSetting - val resident: BooleanSetting - val script: StringSetting - val showclass: StringSetting - val showobject: StringSetting - val showphases: BooleanSetting - val sourcedir: StringSetting - val sourcereader: StringSetting - } - // def Xexperimental = X.experimental - // def Xmigration28 = X.migration - // def Xnojline = X.nojline - // def Xprint = X.print - // def Xprintpos = X.printpos - // def Xshowcls = X.showclass - // def Xshowobj = X.showobject - // def assemextdirs = X.assemextdirs - // def assemname = X.assemname - // def assemrefs = X.assempath - // def checkInit = X.checkinit - // def disable = X.plugindisable - // def elideLevel = X.elidelevel - // def future = X.future - // def genPhaseGraph = X.generatephasegraph - // def logimplicits = X.logimplicits - // def noForwarders = X.noforwarders - // def noassertions = X.disableassertions - // def nouescape = X.nouescape - // def plugin = X.plugin - // def pluginsDir = X.pluginsdir - // def printtypes = X.printtypes - // def prompt = X.prompt - // def require = X.require - // def resident = X.resident - // def script = X.script - // def showPhases = X.showphases - // def showPlugins = X.pluginlist - // def sourceReader = X.sourcereader - // def sourcedir = X.sourcedir - // def writeICode = X.printicode -}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala deleted file mode 100644 index da2c89d707..0000000000 --- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package settings - -/** Taking flag checking to a somewhat higher level. */ -trait AestheticSettings { - def settings: Settings - - // Some(value) if setting has been set by user, None otherwise. - def optSetting[T](s: Settings#Setting): Option[T] = - if (s.isDefault) None else Some(s.value.asInstanceOf[T]) - - def script = optSetting[String](settings.script) - def encoding = optSetting[String](settings.encoding) - def sourceReader = optSetting[String](settings.sourceReader) - - def debug = settings.debug.value - def declsOnly = false - def deprecation = settings.deprecation.value - def experimental = settings.Xexperimental.value - def fatalWarnings = settings.fatalWarnings.value - def feature = settings.feature.value - def future = settings.future.value - def logClasspath = settings.Ylogcp.value - def printStats = settings.Ystatistics.value - def target = settings.target.value - def unchecked = settings.unchecked.value - def verbose = settings.verbose.value - def virtPatmat = !settings.XoldPatmat.value - - /** Derived values */ - def jvm = target startsWith "jvm" - def msil = target == "msil" - def verboseDebug = debug && verbose -} diff --git a/src/compiler/scala/tools/nsc/settings/FscSettings.scala b/src/compiler/scala/tools/nsc/settings/FscSettings.scala index 06ebc20d3e..14b398e50a 100644 --- a/src/compiler/scala/tools/nsc/settings/FscSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/FscSettings.scala @@ -8,7 +8,7 @@ package nsc package settings import util.ClassPath -import io.{ Directory, Path, AbstractFile } +import io.{ Path, AbstractFile } class FscSettings(error: String => Unit) extends Settings(error) { outer => diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index f1f289ed4d..748c6069f0 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -10,7 +10,6 @@ package settings import io.{ AbstractFile, Jar, Path, PlainFile, VirtualDirectory } import scala.reflect.internal.util.StringOps -import scala.collection.mutable.ListBuffer import scala.io.Source import scala.reflect.{ ClassTag, classTag } @@ -63,30 +62,23 @@ class MutableSettings(val errorFn: String => Unit) (checkDependencies, residualArgs) case "--" :: xs => (checkDependencies, xs) + // discard empties, sometimes they appear because of ant or etc. + // but discard carefully, because an empty string is valid as an argument + // to an option, e.g. -cp "" . So we discard them only when they appear + // where an option should be, not where an argument to an option should be. + case "" :: xs => + loop(xs, residualArgs) case x :: xs => - val isOpt = x startsWith "-" - if (isOpt) { - val newArgs = parseParams(args) - if (args eq newArgs) { - errorFn(s"bad option: '$x'") - (false, args) + if (x startsWith "-") { + parseParams(args) match { + case newArgs if newArgs eq args => errorFn(s"bad option: '$x'") ; (false, args) + case newArgs => loop(newArgs, residualArgs) } - // discard empties, sometimes they appear because of ant or etc. - // but discard carefully, because an empty string is valid as an argument - // to an option, e.g. -cp "" . So we discard them only when they appear - // in option position. - else if (x == "") { - loop(xs, residualArgs) - } - else lookupSetting(x) match { - case Some(s) if s.shouldStopProcessing => (checkDependencies, newArgs) - case _ => loop(newArgs, residualArgs) - } - } - else { - if (processAll) loop(xs, residualArgs :+ x) - else (checkDependencies, args) } + else if (processAll) + loop(xs, residualArgs :+ x) + else + (checkDependencies, args) } loop(arguments, Nil) } @@ -184,7 +176,7 @@ class MutableSettings(val errorFn: String => Unit) * The class loader defining `T` should provide resources `app.class.path` * and `boot.class.path`. These resources should contain the application * and boot classpaths in the same form as would be passed on the command line.*/ - def embeddedDefaults[T: ClassTag]: Unit = + def embeddedDefaults[T: ClassTag]: Unit = // called from sbt and repl embeddedDefaults(classTag[T].runtimeClass.getClassLoader) /** Initializes these settings for embedded use by a class from the given class loader. @@ -247,7 +239,7 @@ class MutableSettings(val errorFn: String => Unit) /** Add a destination directory for sources found under srcdir. * Both directories should exits. */ - def add(srcDir: String, outDir: String): Unit = + def add(srcDir: String, outDir: String): Unit = // used in ide? add(checkDir(AbstractFile.getDirectory(srcDir), srcDir), checkDir(AbstractFile.getDirectory(outDir), outDir)) @@ -442,7 +434,7 @@ class MutableSettings(val errorFn: String => Unit) def tryToSet(args: List[String]) = { value = true ; Some(args) } def unparse: List[String] = if (value) List(name) else Nil - override def tryToSetFromPropertyValue(s : String) { + override def tryToSetFromPropertyValue(s : String) { // used from ide value = s.equalsIgnoreCase("true") } } @@ -535,7 +527,7 @@ class MutableSettings(val errorFn: String => Unit) Some(rest) } override def tryToSetColon(args: List[String]) = tryToSet(args) - override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) + override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) // used from ide def unparse: List[String] = value map (name + ":" + _) withHelpSyntax(name + ":<" + arg + ">") @@ -569,7 +561,7 @@ class MutableSettings(val errorFn: String => Unit) } def unparse: List[String] = if (value == default) Nil else List(name + ":" + value) - override def tryToSetFromPropertyValue(s: String) = tryToSetColon(s::Nil) + override def tryToSetFromPropertyValue(s: String) = tryToSetColon(s::Nil) // used from ide withHelpSyntax(name + ":<" + helpArg + ">") } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index cfc7f14210..cf6579a696 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -52,14 +52,14 @@ trait ScalaSettings extends AbsScalaSettings val jvmargs = PrefixSetting("-J<flag>", "-J", "Pass <flag> directly to the runtime system.") val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.") - val toolcp = PathSetting("-toolcp", "Add to the runner classpath.", "") + /*val toolcp =*/ PathSetting("-toolcp", "Add to the runner classpath.", "") val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") /** * Standard settings */ // argfiles is only for the help message - val argfiles = BooleanSetting ("@<file>", "A text file containing compiler arguments (options and source files)") + /*val argfiles = */ BooleanSetting ("@<file>", "A text file containing compiler arguments (options and source files)") val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" val d = OutputSetting (outputDirs, ".") val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.") @@ -74,6 +74,7 @@ trait ScalaSettings extends AbsScalaSettings val assemextdirs = StringSetting ("-Xassem-extdirs", "dirs", "(Requires -target:msil) List of directories containing assemblies. default:lib", Defaults.scalaLibDir.path).dependsOn(target, "msil") val sourcedir = StringSetting ("-Xsourcedir", "directory", "(Requires -target:msil) Mirror source folder structure in output directory.", ".").dependsOn(target, "msil") val checkInit = BooleanSetting ("-Xcheckinit", "Wrap field accessors to throw an exception on uninitialized access.") + val developer = BooleanSetting ("-Xdev", "Indicates user is a developer - issue warnings about anything which seems amiss") val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions or assumptions.") val elidebelow = IntSetting ("-Xelide-below", "Calls to @elidable methods are omitted if method priority is lower than argument", elidable.MINIMUM, None, elidable.byName get _) @@ -114,7 +115,6 @@ trait ScalaSettings extends AbsScalaSettings /** Compatibility stubs for options whose value name did * not previously match the option name. */ - def XO = optimise def debuginfo = g def dependenciesFile = dependencyfile def nowarnings = nowarn @@ -127,6 +127,7 @@ trait ScalaSettings extends AbsScalaSettings val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.") val overrideVars = BooleanSetting ("-Yoverride-vars", "Allow vars to be overridden.") val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.") + val breakCycles = BooleanSetting ("-Ybreak-cycles", "Attempt to break cycles encountered during typing") val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after") val check = PhasesSetting ("-Ycheck", "Check the tree at the end of") val Yshow = PhasesSetting ("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after") @@ -169,6 +170,7 @@ trait ScalaSettings extends AbsScalaSettings val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none") val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup") + val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "") val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.") val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.") val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.") @@ -178,12 +180,9 @@ trait ScalaSettings extends AbsScalaSettings val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() - def stop = stopAfter - /** Area-specific debug output. */ val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") - val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.") val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.") val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.") val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.") diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index e866ad6ae0..98ef74aee3 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -48,9 +48,4 @@ trait StandardScalaSettings { val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.") val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing.") val version = BooleanSetting ("-version", "Print product version and exit.") - - /** These are @<file> and -Dkey=val style settings, which don't - * nicely map to identifiers. - */ - val argfiles: BooleanSetting // exists only to echo help message, should be done differently } diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 9f9879210c..2649a150ad 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -26,11 +26,11 @@ trait Warnings { // These warnings should be pretty quiet unless you're doing // something inadvisable. protected def lintWarnings = List( - // warnDeadCode, warnInaccessible, warnNullaryOverride, warnNullaryUnit, - warnAdaptedArgs + warnAdaptedArgs, + warnInferAny ) // Warning groups. @@ -38,9 +38,13 @@ trait Warnings { BooleanSetting("-Xlint", "Enable recommended additional warnings.") withPostSetHook (_ => lintWarnings foreach (_.value = true)) ) - val warnEverything = ( + + /*val warnEverything = */ ( BooleanSetting("-Ywarn-all", "Enable all -Y warnings.") - withPostSetHook (_ => lintWarnings foreach (_.value = true)) + withPostSetHook { _ => + lint.value = true + allWarnings foreach (_.value = true) + } ) // Individual warnings. @@ -53,9 +57,10 @@ trait Warnings { val warnInaccessible = BooleanSetting ("-Ywarn-inaccessible", "Warn about inaccessible types in method signatures.") val warnNullaryOverride = BooleanSetting ("-Ywarn-nullary-override", "Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.") + val warnInferAny = BooleanSetting ("-Ywarn-infer-any", "Warn when a type argument is inferred to be `Any`.") // Backward compatibility. - def Xwarnfatal = fatalWarnings - def Xchecknull = warnSelectNullable - def Ywarndeadcode = warnDeadCode + @deprecated("Use fatalWarnings", "2.11.0") def Xwarnfatal = fatalWarnings // used by sbt + @deprecated("Use warnSelectNullable", "2.11.0") def Xchecknull = warnSelectNullable // used by ide + @deprecated("Use warnDeadCode", "2.11.0") def Ywarndeadcode = warnDeadCode // used by ide } diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index f2aab36b51..4e4efef607 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package symtab -import scala.reflect.internal.util.BatchSourceFile import scala.tools.nsc.io.AbstractFile /** A subclass of SymbolLoaders that implements browsing behavior. @@ -28,7 +27,7 @@ abstract class BrowsingLoaders extends SymbolLoaders { override protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = { completer.sourcefile match { case Some(src) => - (if (member.isModule) member.moduleClass else member).sourceFile = src + (if (member.isModule) member.moduleClass else member).associatedFile = src case _ => } val decls = owner.info.decls diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 348c7f688f..19502f0d7e 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -10,7 +10,6 @@ import java.io.IOException import scala.compat.Platform.currentTime import scala.tools.nsc.util.{ ClassPath } import classfile.ClassfileParser -import scala.reflect.internal.Flags._ import scala.reflect.internal.MissingRequirementError import scala.reflect.internal.util.Statistics import scala.tools.nsc.io.{ AbstractFile, MsilFile } @@ -162,8 +161,8 @@ abstract class SymbolLoaders { private def setSource(sym: Symbol) { sourcefile foreach (sf => sym match { - case cls: ClassSymbol => cls.sourceFile = sf - case mod: ModuleSymbol => mod.moduleClass.sourceFile = sf + case cls: ClassSymbol => cls.associatedFile = sf + case mod: ModuleSymbol => mod.moduleClass.associatedFile = sf case _ => () }) } @@ -226,7 +225,6 @@ abstract class SymbolLoaders { assert(root.isPackageClass, root) root.setInfo(new PackageClassInfoType(newScope, root)) - val sourcepaths = classpath.sourcepaths if (!root.isRoot) { for (classRep <- classpath.classes if platform.doLoad(classRep)) { initializeFromClassPath(root, classRep) diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala index 7a84441e09..035244e421 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package symtab -import scala.collection.{ mutable, immutable } import scala.language.implicitConversions import scala.language.postfixOps @@ -17,9 +16,6 @@ trait SymbolTrackers { val global: Global import global._ - private implicit lazy val TreeOrdering: Ordering[Tree] = - Ordering by (x => (x.shortClass, x.symbol)) - private implicit lazy val SymbolOrdering: Ordering[Symbol] = Ordering by (x => (x.kindString, x.name.toString)) @@ -76,7 +72,6 @@ trait SymbolTrackers { private def isFlagsChange(sym: Symbol) = changed.flags contains sym private implicit def NodeOrdering: Ordering[Node] = Ordering by (_.root) - private def ownersString(sym: Symbol, num: Int) = sym.ownerChain drop 1 take num mkString " -> " object Node { def nodes(syms: Set[Symbol]): List[Node] = { @@ -114,7 +109,6 @@ trait SymbolTrackers { case Some(oldFlags) => val added = masked & ~oldFlags val removed = oldFlags & ~masked - val steady = masked & ~(added | removed) val all = masked | oldFlags val strs = 0 to 63 map { bit => val flag = 1L << bit @@ -181,7 +175,7 @@ trait SymbolTrackers { } def show(label: String): String = { val hierarchy = Node(current) - val Change(added, removed, symMap, owners, flags) = history.head + val Change(_, removed, symMap, _, _) = history.head def detailString(sym: Symbol) = { val ownerString = sym.ownerChain splitAt 3 match { case (front, back) => diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala index 427b5bf887..17e3b08ec2 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala @@ -29,11 +29,6 @@ class AbstractFileReader(val file: AbstractFile) { */ var bp: Int = 0 - /** return byte at offset 'pos' - */ - @throws(classOf[IndexOutOfBoundsException]) - def byteAt(pos: Int): Byte = buf(pos) - /** read a byte */ @throws(classOf[IndexOutOfBoundsException]) @@ -45,7 +40,7 @@ class AbstractFileReader(val file: AbstractFile) { /** read some bytes */ - def nextBytes(len: Int): Array[Byte] = { + def nextBytes(len: Int): Array[Byte] = { // used in ide bp += len buf.slice(bp - len, bp) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a708a262e7..6d213af2b6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -23,7 +23,6 @@ import scala.tools.nsc.io.AbstractFile abstract class ClassfileParser { val global: Global import global._ - import definitions.{ AnnotationClass, ClassfileAnnotationClass } import scala.reflect.internal.ClassfileConstants._ import Flags._ @@ -186,7 +185,7 @@ abstract class ClassfileParser { if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) val name = getExternalName(in.getChar(start + 1)) if (nme.isModuleName(name)) - c = rootMirror.getModule(nme.stripModuleSuffix(name)) + c = rootMirror.getModuleByName(nme.stripModuleSuffix(name)) else c = classNameToSymbol(name) @@ -237,7 +236,7 @@ abstract class ClassfileParser { //assert(name.endsWith("$"), "Not a module class: " + name) f = forceMangledName(name dropRight 1, true) if (f == NoSymbol) - f = rootMirror.getModule(name dropRight 1) + f = rootMirror.getModuleByName(name dropRight 1) } else { val origName = nme.originalName(name) val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol @@ -361,7 +360,7 @@ abstract class ClassfileParser { } value match { case ct: Constant => ct - case cls: Symbol => Constant(cls.tpe) + case cls: Symbol => Constant(cls.tpe_*) case arr: Type => Constant(arr) } } @@ -423,9 +422,9 @@ abstract class ClassfileParser { var sym: Symbol = rootMirror.RootClass // was "at flatten.prev" - beforeFlatten { + enteringFlatten { for (part0 <- parts; if !(part0 == ""); part = newTermName(part0)) { - val sym1 = beforeIcode { + val sym1 = enteringIcode { sym.linkedClassOfClass.info sym.info.decl(part.encode) }//.suchThat(module == _.isModule) @@ -478,7 +477,7 @@ abstract class ClassfileParser { if (name.pos('.') == name.length) definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName) else - rootMirror.getClass(name) // see tickets #2464, #3756 + rootMirror.getClassByName(name) // see tickets #2464, #3756 } catch { case _: FatalError => loadClassSymbol(name) } @@ -500,8 +499,8 @@ abstract class ClassfileParser { def parseClass() { val jflags = in.nextChar val isAnnotation = hasAnnotation(jflags) - var sflags = toScalaClassFlags(jflags) - var nameIdx = in.nextChar + val sflags = toScalaClassFlags(jflags) + val nameIdx = in.nextChar currentClass = pool.getClassName(nameIdx) /** Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled. @@ -515,9 +514,9 @@ abstract class ClassfileParser { } else raiseLoaderLevel { val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe } - else pool.getSuperClass(in.nextChar).tpe + else pool.getSuperClass(in.nextChar).tpe_* val ifaceCount = in.nextChar - var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe + var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe_* if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces superType :: ifaces } @@ -565,7 +564,7 @@ abstract class ClassfileParser { 0 until in.nextChar foreach (_ => parseMethod()) val needsConstructor = ( !sawPrivateConstructor - && instanceScope.lookup(nme.CONSTRUCTOR) == NoSymbol + && !(instanceScope containsName nme.CONSTRUCTOR) && (sflags & INTERFACE) == 0 ) if (needsConstructor) @@ -599,7 +598,7 @@ abstract class ClassfileParser { def parseField() { val jflags = in.nextChar - var sflags = toScalaFieldFlags(jflags) + val sflags = toScalaFieldFlags(jflags) if ((sflags & PRIVATE) != 0L && !global.settings.optimise.value) { in.skip(4); skipAttributes() } else { @@ -629,7 +628,7 @@ abstract class ClassfileParser { def parseMethod() { val jflags = in.nextChar.toInt - var sflags = toScalaMethodFlags(jflags) + val sflags = toScalaMethodFlags(jflags) if (isPrivate(jflags) && !global.settings.optimise.value) { val name = pool.getName(in.nextChar) if (name == nme.CONSTRUCTOR) @@ -735,17 +734,19 @@ abstract class ClassfileParser { } accept('>') assert(xs.length > 0, tp) - newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList)) - } else if (classSym.isMonomorphicType) { + logResult("new existential")(newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList))) + } + // isMonomorphicType is false if the info is incomplete, as it usually is here + // so have to check unsafeTypeParams.isEmpty before worrying about raw type case below, + // or we'll create a boatload of needless existentials. + else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) { tp - } else { + } + else { // raw type - existentially quantify all type parameters val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams) - val t = typeRef(pre, classSym, eparams.map(_.tpeHK)) - val res = newExistentialType(eparams, t) - if (settings.debug.value && settings.verbose.value) - println("raw type " + classSym + " -> " + res) - res + val t = typeRef(pre, classSym, eparams.map(_.tpeHK)) + logResult(s"raw type from $classSym")(newExistentialType(eparams, t)) } case tp => assert(sig.charAt(index) != '<', tp) @@ -754,7 +755,7 @@ abstract class ClassfileParser { val classSym = classNameToSymbol(subName(c => c == ';' || c == '<')) assert(!classSym.isOverloaded, classSym.alternatives) - var tpe = processClassType(processInner(classSym.tpe)) + var tpe = processClassType(processInner(classSym.tpe_*)) while (sig.charAt(index) == '.') { accept('.') val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName @@ -787,7 +788,7 @@ abstract class ClassfileParser { index += 1 val restype = if (sym != null && sym.isClassConstructor) { accept('V') - clazz.tpe + clazz.tpe_* } else sig2type(tparams, skiptvs) JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype) @@ -875,7 +876,7 @@ abstract class ClassfileParser { sym.setFlag(SYNTHETIC | ARTIFACT) in.skip(attrLen) case tpnme.BridgeATTR => - sym.setFlag(BRIDGE) + sym.setFlag(BRIDGE | ARTIFACT) in.skip(attrLen) case tpnme.DeprecatedATTR => val arg = Literal(Constant("see corresponding Javadoc for more information.")) @@ -1079,7 +1080,7 @@ abstract class ClassfileParser { def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) { val completer = new global.loaders.ClassfileLoader(file) val name = entry.originalName - var sflags = toScalaClassFlags(jflags) + val sflags = toScalaClassFlags(jflags) val owner = getOwner(jflags) val scope = getScope(jflags) val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer @@ -1167,21 +1168,7 @@ abstract class ClassfileParser { originalName + " in " + outerName + "(" + externalName +")" } - object innerClasses extends scala.collection.mutable.HashMap[Name, InnerClassEntry] { - /** Return the Symbol of the top level class enclosing `name`, - * or 'name's symbol if no entry found for `name`. - */ - def topLevelClass(name: Name): Symbol = { - val tlName = if (isDefinedAt(name)) { - var entry = this(name) - while (isDefinedAt(entry.outerName)) - entry = this(entry.outerName) - entry.outerName - } else - name - classNameToSymbol(tlName) - } - + object innerClasses extends mutable.HashMap[Name, InnerClassEntry] { /** Return the class symbol for `externalName`. It looks it up in its outer class. * Forces all outer class symbols to be completed. * @@ -1206,7 +1193,7 @@ abstract class ClassfileParser { // if loading during initialization of `definitions` typerPhase is not yet set. // in that case we simply load the member at the current phase if (currentRun.typerPhase != null) - beforeTyper(getMember(sym, innerName.toTypeName)) + enteringTyper(getMember(sym, innerName.toTypeName)) else getMember(sym, innerName.toTypeName) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 13c0d8993a..b5459ec773 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -9,9 +9,7 @@ package classfile import scala.collection.{ mutable, immutable } import mutable.ListBuffer -import backend.icode._ import ClassfileConstants._ -import scala.reflect.internal.Flags._ /** ICode reader from Java bytecode. * @@ -33,7 +31,6 @@ abstract class ICodeReader extends ClassfileParser { * for non-static members. */ def readClass(cls: Symbol): (IClass, IClass) = { - var classFile: io.AbstractFile = null; cls.info // ensure accurate type information isScalaModule = cls.isModule && !cls.isJavaDefined @@ -58,11 +55,9 @@ abstract class ICodeReader extends ClassfileParser { override def parseClass() { this.instanceCode = new IClass(clazz) this.staticCode = new IClass(staticModule) - val jflags = in.nextChar - val isAttribute = (jflags & JAVA_ACC_ANNOTATION) != 0 - val sflags = toScalaClassFlags(jflags) // what, this is never used?? - val c = pool getClassSymbol in.nextChar + in.nextChar + pool getClassSymbol in.nextChar parseInnerClasses() in.skip(2) // super class @@ -125,7 +120,7 @@ abstract class ICodeReader extends ClassfileParser { override def parseMethod() { val (jflags, sym) = parseMember(false) - var beginning = in.bp + val beginning = in.bp try { if (sym != NoSymbol) { this.method = new IMethod(sym) @@ -170,11 +165,11 @@ abstract class ICodeReader extends ClassfileParser { } else if (nme.isModuleName(name)) { val strippedName = nme.stripModuleSuffix(name) - forceMangledName(newTermName(strippedName.decode), true) orElse rootMirror.getModule(strippedName) + forceMangledName(newTermName(strippedName.decode), true) orElse rootMirror.getModuleByName(strippedName) } else { forceMangledName(name, false) - afterFlatten(rootMirror.getClassByName(name.toTypeName)) + exitingFlatten(rootMirror.getClassByName(name.toTypeName)) } if (sym.isModule) sym.moduleClass @@ -637,9 +632,9 @@ abstract class ICodeReader extends ClassfileParser { else instanceCode class LinearCode { - var instrs: ListBuffer[(Int, Instruction)] = new ListBuffer - var jmpTargets: mutable.Set[Int] = perRunCaches.newSet[Int]() - var locals: mutable.Map[Int, List[(Local, TypeKind)]] = perRunCaches.newMap() + val instrs: ListBuffer[(Int, Instruction)] = new ListBuffer + val jmpTargets: mutable.Set[Int] = perRunCaches.newSet[Int]() + val locals: mutable.Map[Int, List[(Local, TypeKind)]] = perRunCaches.newMap() var containsDUPX = false var containsNEW = false @@ -669,7 +664,6 @@ abstract class ICodeReader extends ClassfileParser { val blocks = makeBasicBlocks var otherBlock: BasicBlock = NoBasicBlock - var disableJmpTarget = false for ((pc, instr) <- instrs.iterator) { // Console.println("> " + pc + ": " + instr); @@ -720,11 +714,9 @@ abstract class ICodeReader extends ClassfileParser { val tfa = new analysis.MethodTFA() { import analysis._ - import analysis.typeFlowLattice.IState /** Abstract interpretation for one instruction. */ override def mutatingInterpret(out: typeFlowLattice.Elem, i: Instruction): typeFlowLattice.Elem = { - val bindings = out.vars val stack = out.stack import stack.push i match { @@ -901,7 +893,7 @@ abstract class ICodeReader extends ClassfileParser { for (bb <- method.code.blocks ; (i, idx) <- bb.toList.zipWithIndex) i match { case cm @ CALL_METHOD(m, Static(true)) if m.isClassConstructor => - def loop(bb0: BasicBlock, idx0: Int, depth: Int = 0): Unit = { + def loop(bb0: BasicBlock, idx0: Int, depth: Int): Unit = { rdef.findDefs(bb0, idx0, 1, depth) match { case ((bb1, idx1)) :: _ => bb1(idx1) match { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index b9eb1ba0cd..42ea7e61f0 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -26,15 +26,23 @@ import Flags._ abstract class Pickler extends SubComponent { import global._ - private final val showSig = false - val phaseName = "pickler" - currentRun - def newPhase(prev: Phase): StdPhase = new PicklePhase(prev) class PicklePhase(prev: Phase) extends StdPhase(prev) { + override def run() { + super.run() + // This is run here rather than after typer because I found + // some symbols - usually annotations, possibly others - had not + // yet performed the necessary symbol lookup, leading to + // spurious claims of unusedness. + if (settings.lint.value) { + log("Clearing recorded import selectors.") + analyzer.clearUnusedImports() + } + } + def apply(unit: CompilationUnit) { def pickle(tree: Tree) { def add(sym: Symbol, pickle: Pickle) = { @@ -68,17 +76,19 @@ abstract class Pickler extends SubComponent { return } - if (!t.isDef && t.hasSymbol && t.symbol.isTermMacro) { + if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) { unit.error(t.pos, t.symbol.typeParams.length match { case 0 => "macro has not been expanded" - case 1 => "type parameter not specified" - case _ => "type parameters not specified" + case 1 => "this type parameter must be specified" + case _ => "these type parameters must be specified" }) return } } pickle(unit.body) + if (settings.lint.value) + analyzer.warnUnusedImports(unit) } } @@ -139,8 +149,6 @@ abstract class Pickler extends SubComponent { } /** Store symbol in index. If symbol is local, also store everything it references. - * - * @param sym ... */ def putSymbol(sym: Symbol) { if (putEntry(sym)) { @@ -177,7 +185,7 @@ abstract class Pickler extends SubComponent { */ private def putType(tp: Type): Unit = if (putEntry(tp)) { tp match { - case NoType | NoPrefix /*| DeBruijnIndex(_, _) */ => + case NoType | NoPrefix => ; case ThisType(sym) => putSymbol(sym) @@ -235,7 +243,7 @@ abstract class Pickler extends SubComponent { private def putTree(tree: Tree): Unit = if (putEntry(tree)) { if (tree != EmptyTree) putType(tree.tpe) - if (tree.hasSymbol) + if (tree.hasSymbolField) putSymbol(tree.symbol) tree match { @@ -427,7 +435,7 @@ abstract class Pickler extends SubComponent { * argument of some Annotation */ private def putMods(mods: Modifiers) = if (putEntry(mods)) { // annotations in Modifiers are removed by the typechecker - val Modifiers(flags, privateWithin, Nil) = mods + val Modifiers(_, privateWithin, Nil) = mods putEntry(privateWithin) } @@ -568,7 +576,7 @@ abstract class Pickler extends SubComponent { tag case sym: ClassSymbol => writeSymInfo(sym) - if (sym.thisSym.tpe != sym.tpe) writeRef(sym.typeOfThis) + if (sym.thisSym.tpe_* != sym.tpe_*) writeRef(sym.typeOfThis) CLASSsym case sym: TypeSymbol => writeSymInfo(sym) @@ -609,8 +617,6 @@ abstract class Pickler extends SubComponent { writeRef(restpe); writeRefs(tparams); POLYtpe case ExistentialType(tparams, restpe) => writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe - // case DeBruijnIndex(l, i) => - // writeNat(l); writeNat(i); DEBRUIJNINDEXtpe case c @ Constant(_) => if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0) else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue) @@ -993,115 +999,6 @@ abstract class Pickler extends SubComponent { patchNat(startpos + 1, writeIndex - (startpos + 2)) } - /** Print entry for diagnostics */ - def printEntryAtIndex(idx: Int) = printEntry(entries(idx)) - def printEntry(entry: AnyRef) { - def printRef(ref: AnyRef) { - print(index(ref)+ - (if (ref.isInstanceOf[Name]) "("+ref+") " else " ")) - } - def printRefs(refs: List[AnyRef]) { refs foreach printRef } - def printSymInfo(sym: Symbol) { - var posOffset = 0 - printRef(sym.name) - printRef(localizedOwner(sym)) - print(flagsToString(sym.flags & PickledFlags)+" ") - if (sym.hasAccessBoundary) printRef(sym.privateWithin) - printRef(sym.info) - } - def printBody(entry: AnyRef) = entry match { - case name: Name => - print((if (name.isTermName) "TERMname " else "TYPEname ")+name) - case NoSymbol => - print("NONEsym") - case sym: Symbol if !isLocal(sym) => - if (sym.isModuleClass) { - print("EXTMODCLASSref "); printRef(sym.name.toTermName) - } else { - print("EXTref "); printRef(sym.name) - } - if (!sym.owner.isRoot) printRef(sym.owner) - case sym: ClassSymbol => - print("CLASSsym ") - printSymInfo(sym) - if (sym.thisSym.tpe != sym.tpe) printRef(sym.typeOfThis) - case sym: TypeSymbol => - print(if (sym.isAbstractType) "TYPEsym " else "ALIASsym ") - printSymInfo(sym) - case sym: TermSymbol => - print(if (sym.isModule) "MODULEsym " else "VALsym ") - printSymInfo(sym) - if (sym.alias != NoSymbol) printRef(sym.alias) - case NoType => - print("NOtpe") - case NoPrefix => - print("NOPREFIXtpe") - case ThisType(sym) => - print("THIStpe "); printRef(sym) - case SingleType(pre, sym) => - print("SINGLEtpe "); printRef(pre); printRef(sym); - case ConstantType(value) => - print("CONSTANTtpe "); printRef(value); - case TypeRef(pre, sym, args) => - print("TYPEREFtpe "); printRef(pre); printRef(sym); printRefs(args); - case TypeBounds(lo, hi) => - print("TYPEBOUNDStpe "); printRef(lo); printRef(hi); - case tp @ RefinedType(parents, decls) => - print("REFINEDtpe "); printRef(tp.typeSymbol); printRefs(parents); - case ClassInfoType(parents, decls, clazz) => - print("CLASSINFOtpe "); printRef(clazz); printRefs(parents); - case mt @ MethodType(formals, restpe) => - print("METHODtpe"); printRef(restpe); printRefs(formals) - case PolyType(tparams, restpe) => - print("POLYtpe "); printRef(restpe); printRefs(tparams); - case ExistentialType(tparams, restpe) => - print("EXISTENTIALtpe "); printRef(restpe); printRefs(tparams); - print("||| "+entry) - // case DeBruijnIndex(l, i) => - // print("DEBRUIJNINDEXtpe "); print(l+" "+i) - case c @ Constant(_) => - print("LITERAL ") - if (c.tag == BooleanTag) print("Boolean "+(if (c.booleanValue) 1 else 0)) - else if (c.tag == ByteTag) print("Byte "+c.longValue) - else if (c.tag == ShortTag) print("Short "+c.longValue) - else if (c.tag == CharTag) print("Char "+c.longValue) - else if (c.tag == IntTag) print("Int "+c.longValue) - else if (c.tag == LongTag) print("Long "+c.longValue) - else if (c.tag == FloatTag) print("Float "+c.floatValue) - else if (c.tag == DoubleTag) print("Double "+c.doubleValue) - else if (c.tag == StringTag) { print("String "); printRef(newTermName(c.stringValue)) } - else if (c.tag == ClazzTag) { print("Class "); printRef(c.typeValue) } - else if (c.tag == EnumTag) { print("Enum "); printRef(c.symbolValue) } - case AnnotatedType(annots, tp, selfsym) => - if (settings.selfInAnnots.value) { - print("ANNOTATEDWSELFtpe ") - printRef(tp) - printRef(selfsym) - printRefs(annots) - } else { - print("ANNOTATEDtpe ") - printRef(tp) - printRefs(annots) - } - case (target: Symbol, AnnotationInfo(atp, args, Nil)) => - print("SYMANNOT ") - printRef(target) - printRef(atp) - for (c <- args) printRef(c) - case (target: Symbol, children: List[_]) => - print("CHILDREN ") - printRef(target) - for (c <- children) printRef(c.asInstanceOf[Symbol]) - case AnnotationInfo(atp, args, Nil) => - print("ANNOTINFO") - printRef(atp) - for (c <- args) printRef(c) - case _ => - throw new FatalError("bad entry: " + entry + " " + entry.getClass) - } - printBody(entry); println() - } - /** Write byte array */ def writeArray() { assert(writeIndex == 0) diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala index 40189b9444..624db027f1 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala @@ -7,12 +7,8 @@ package scala.tools.nsc package symtab package clr -import java.io.File -import java.util.{Comparator, StringTokenizer} -import scala.util.Sorting import ch.epfl.lamp.compiler.msil._ import scala.collection.{ mutable, immutable } -import scala.reflect.internal.util.{Position, NoPosition} /** * Collects all types from all reference assemblies. @@ -21,7 +17,6 @@ abstract class CLRTypes { val global: Global import global.Symbol - import global.definitions //########################################################################## diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala index 5a0253c18b..f0e49ce500 100644 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala @@ -12,7 +12,6 @@ import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, import scala.collection.{ mutable, immutable } import scala.reflect.internal.pickling.UnPickler import ch.epfl.lamp.compiler.msil.Type.TMVarUsage -import scala.language.implicitConversions /** * @author Nikolay Mihaylov @@ -520,12 +519,12 @@ abstract class TypeParser { val delegateParamTypes: List[Type] = List(typClrType); // not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods) val forwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(delegateParamTypes), funType) - val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true); + createMethod(nme.view_, flags, forwardViewMethodType, null, true); // create the backward view: function => delegate val functionParamTypes: List[Type] = List(funType); val backwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(functionParamTypes), typClrType) - val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true); + createMethod(nme.view_, flags, backwardViewMethodType, null, true); } private def createDelegateChainers(typ: MSILType) = { diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index bacd8c39e1..5fbc15f858 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -8,8 +8,6 @@ package transform import symtab._ import Flags._ -import scala.collection.{ mutable, immutable } -import scala.collection.mutable.ListBuffer abstract class AddInterfaces extends InfoTransform { self: Erasure => import global._ // the global environment @@ -94,7 +92,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => impl.typeOfThis = iface.typeOfThis impl.thisSym setName iface.thisSym.name } - impl.sourceFile = iface.sourceFile + impl.associatedFile = iface.sourceFile if (inClass) iface.owner.info.decls enter impl @@ -111,7 +109,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => def implClass(iface: Symbol): Symbol = { iface.info - implClassMap.getOrElse(iface, atPhase(implClassPhase) { + implClassMap.getOrElse(iface, enteringPhase(implClassPhase) { if (iface.implClass eq NoSymbol) debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.") else @@ -196,7 +194,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => case PolyType(_, restpe) => implType(restpe) } - implSym setInfo implType(beforeErasure(iface.info)) + implSym setInfo implType(enteringErasure(iface.info)) } override def load(clazz: Symbol) { complete(clazz) } @@ -317,10 +315,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => // body until now, because the typer knows that Any has no // constructor and won't accept a call to super.init. assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz) - Block(List(Apply(gen.mkSuperSelect, Nil)), expr) + Block(List(Apply(gen.mkSuperInitCall, Nil)), expr) case Block(stats, expr) => - // needs `hasSymbol` check because `supercall` could be a block (named / default args) + // needs `hasSymbolField` check because `supercall` could be a block (named / default args) val (presuper, supercall :: rest) = stats span (t => t.hasSymbolWhich(_ hasFlag PRESUPER)) treeCopy.Block(tree, presuper ::: (supercall :: mixinConstructorCalls ::: rest), expr) } @@ -352,7 +350,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => val mix1 = mix if (mix == tpnme.EMPTY) mix else { - val ps = beforeErasure { + val ps = enteringErasure { sym.info.parents dropWhile (p => p.symbol.name != mix) } assert(!ps.isEmpty, tree); diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 0c9cb31d58..847ca574a9 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -15,6 +15,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { import global._ import definitions._ import CODE._ + import treeInfo.StripCast /** the following two members override abstract members in Transform */ val phaseName: String = "cleanup" @@ -45,7 +46,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { result } private def transformTemplate(tree: Tree) = { - val Template(parents, self, body) = tree + val Template(_, _, body) = tree clearStatics() val newBody = transformTrees(body) val templ = deriveTemplate(tree)(_ => transformTrees(newStaticMembers.toList) ::: newBody) @@ -437,19 +438,31 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * is a value type (int et al.) in which case it must cast to the boxed version * because invoke only returns object and erasure made sure the result is * expected to be an AnyRef. */ - val t: Tree = ad.symbol.tpe match { - case MethodType(mparams, resType) => - assert(params.length == mparams.length, mparams) - - typedPos { - val sym = currentOwner.newValue(mkTerm("qual"), ad.pos) setInfo qual0.tpe - qual = REF(sym) + val t: Tree = { + val (mparams, resType) = ad.symbol.tpe match { + case MethodType(mparams, resType) => + assert(params.length == mparams.length, ((params, mparams))) + (mparams, resType) + case tpe @ OverloadedType(pre, alts) => + unit.warning(ad.pos, s"Overloaded type reached the backend! This is a bug in scalac.\n Symbol: ${ad.symbol}\n Overloads: $tpe\n Arguments: " + ad.args.map(_.tpe)) + alts filter (_.paramss.flatten.size == params.length) map (_.tpe) match { + case mt @ MethodType(mparams, resType) :: Nil => + unit.warning(NoPosition, "Only one overload has the right arity, proceeding with overload " + mt) + (mparams, resType) + case _ => + unit.error(ad.pos, "Cannot resolve overload.") + (Nil, NoType) + } + } + typedPos { + val sym = currentOwner.newValue(mkTerm("qual"), ad.pos) setInfo qual0.tpe + qual = REF(sym) - BLOCK( - VAL(sym) === qual0, - callAsReflective(mparams map (_.tpe), resType) - ) - } + BLOCK( + VAL(sym) === qual0, + callAsReflective(mparams map (_.tpe), resType) + ) + } } /* For testing purposes, the dynamic application's condition @@ -606,14 +619,16 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } transformApply - // This transform replaces Array(Predef.wrapArray(Array(...)), <tag>) - // with just Array(...) - case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(array)), _)) - if (wrapRefArrayMeth.symbol == Predef_wrapRefArray && - appMeth.symbol == ArrayModule_overloadedApply.suchThat { - _.tpe.resultType.dealias.typeSymbol == ObjectClass - }) => - super.transform(array) + // Replaces `Array(Predef.wrapArray(ArrayValue(...).$asInstanceOf[...]), <tag>)` + // with just `ArrayValue(...).$asInstanceOf[...]` + // + // See SI-6611; we must *only* do this for literal vararg arrays. + case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ StripCast(ArrayValue(_, _)))), _)) + if wrapRefArrayMeth.symbol == Predef_wrapRefArray && appMeth.symbol == ArrayModule_genericApply => + super.transform(arg) + case Apply(appMeth, List(elem0, Apply(wrapArrayMeth, List(rest @ ArrayValue(elemtpt, _))))) + if wrapArrayMeth.symbol == Predef_wrapArray(elemtpt.tpe) && appMeth.symbol == ArrayModule_apply(elemtpt.tpe) => + super.transform(treeCopy.ArrayValue(rest, rest.elemtpt, elem0 :: rest.elems)) case _ => super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 4092d1262a..323c7c7261 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -130,7 +130,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { if (from.name != nme.OUTER || from.tpe.typeSymbol.isPrimitiveValueClass) result else localTyper.typedPos(to.pos) { - IF (from OBJ_EQ NULL) THEN Throw(NullPointerExceptionClass.tpe) ELSE result + IF (from OBJ_EQ NULL) THEN Throw(NewFromConstructor(NPEConstructor)) ELSE result } } @@ -422,7 +422,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { def ensureAccessor(sym: Symbol)(acc: => Symbol) = if (sym.owner == clazz && !sym.isMethod && sym.isPrivate) { // there's an access to a naked field of the enclosing class - var getr = acc + val getr = acc getr makeNotPrivate clazz getr } else { @@ -529,7 +529,8 @@ abstract class Constructors extends Transform with ast.TreeDSL { (pre ::: supercalls, rest) } - var (uptoSuperStats, remainingConstrStats) = splitAtSuper(constrStatBuf.toList) + val (uptoSuperStats, remainingConstrStats0) = splitAtSuper(constrStatBuf.toList) + var remainingConstrStats = remainingConstrStats0 /** XXX This is not corect: remainingConstrStats.nonEmpty excludes too much, * but excluding it includes too much. The constructor sequence being mimicked diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 7b45b3efe5..cfc3d0a377 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -172,7 +172,7 @@ abstract class Erasure extends AddInterfaces /** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return * type for constructors. */ - def javaSig(sym0: Symbol, info: Type): Option[String] = beforeErasure { + def javaSig(sym0: Symbol, info: Type): Option[String] = enteringErasure { val isTraitSignature = sym0.enclClass.isTrait def superSig(parents: List[Type]) = { @@ -206,7 +206,7 @@ abstract class Erasure extends AddInterfaces // Anything which could conceivably be a module (i.e. isn't known to be // a type parameter or similar) must go through here or the signature is // likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$. - def fullNameInSig(sym: Symbol) = "L" + beforeIcode(sym.javaBinaryName) + def fullNameInSig(sym: Symbol) = "L" + enteringIcode(sym.javaBinaryName) def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = { val tp = tp0.dealias @@ -398,7 +398,7 @@ abstract class Erasure extends AddInterfaces val bridgeTarget = mutable.HashMap[Symbol, Symbol]() var bridges = List[Tree]() - val opc = beforeExplicitOuter { + val opc = enteringExplicitOuter { new overridingPairs.Cursor(root) { override def parents = List(root.info.firstParent) override def exclude(sym: Symbol) = !sym.isMethod || sym.isPrivate || super.exclude(sym) @@ -410,7 +410,7 @@ abstract class Erasure extends AddInterfaces val member = opc.overriding val other = opc.overridden //println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG - if (beforeExplicitOuter(!member.isDeferred)) + if (enteringExplicitOuter(!member.isDeferred)) checkPair(member, other) opc.next @@ -440,11 +440,11 @@ abstract class Erasure extends AddInterfaces s"""bridge generated for member ${fulldef(member)} |which overrides ${fulldef(other)} |clashes with definition of $what; - |both have erased type ${afterPostErasure(bridge.tpe)}""".stripMargin) + |both have erased type ${exitingPostErasure(bridge.tpe)}""".stripMargin) } for (bc <- root.baseClasses) { if (settings.debug.value) - afterPostErasure(println( + exitingPostErasure(println( s"""check bridge overrides in $bc ${bc.info.nonPrivateDecl(bridge.name)} ${site.memberType(bridge)} @@ -453,13 +453,13 @@ abstract class Erasure extends AddInterfaces def overriddenBy(sym: Symbol) = sym.matchingSymbol(bc, site).alternatives filter (sym => !sym.isBridge) - for (overBridge <- afterPostErasure(overriddenBy(bridge))) { + for (overBridge <- exitingPostErasure(overriddenBy(bridge))) { if (overBridge == member) { clashError("the member itself") } else { val overMembers = overriddenBy(member) if (!overMembers.exists(overMember => - afterPostErasure(overMember.tpe =:= overBridge.tpe))) { + exitingPostErasure(overMember.tpe =:= overBridge.tpe))) { clashError(fulldef(overBridge)) } } @@ -470,7 +470,7 @@ abstract class Erasure extends AddInterfaces def checkPair(member: Symbol, other: Symbol) { val otpe = specialErasure(root)(other.tpe) - val bridgeNeeded = afterErasure ( + val bridgeNeeded = exitingErasure ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && { var e = bridgesScope.lookupEntry(member.name) @@ -482,7 +482,7 @@ abstract class Erasure extends AddInterfaces if (!bridgeNeeded) return - val newFlags = (member.flags | BRIDGE) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED) + val newFlags = (member.flags | BRIDGE | ARTIFACT) & ~(ACCESSOR | DEFERRED | LAZY | lateDEFERRED) val bridge = other.cloneSymbolImpl(root, newFlags) setPos root.pos debuglog("generating bridge from %s (%s): %s to %s: %s".format( @@ -497,9 +497,9 @@ abstract class Erasure extends AddInterfaces if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) || checkBridgeOverrides(member, other, bridge)) { - afterErasure(root.info.decls enter bridge) + exitingErasure(root.info.decls enter bridge) if (other.owner == root) { - afterErasure(root.info.decls.unlink(other)) + exitingErasure(root.info.decls.unlink(other)) toBeRemoved += other } @@ -508,7 +508,7 @@ abstract class Erasure extends AddInterfaces } } - def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = afterErasure { + def makeBridgeDefDef(bridge: Symbol, member: Symbol, other: Symbol) = exitingErasure { // type checking ensures we can safely call `other`, but unless `member.tpe <:< other.tpe`, // calling `member` is not guaranteed to succeed in general, there's // nothing we can do about this, except for an unapply: when this subtype test fails, @@ -519,7 +519,7 @@ abstract class Erasure extends AddInterfaces def maybeWrap(bridgingCall: Tree): Tree = { val guardExtractor = ( // can't statically know which member is going to be selected, so don't let this depend on member.isSynthetic (member.name == nme.unapply || member.name == nme.unapplySeq) - && !afterErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?) + && !exitingErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?) import CODE._ val _false = FALSE_typed @@ -724,19 +724,11 @@ abstract class Erasure extends AddInterfaces case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List()) if tree.symbol == Any_asInstanceOf => val qual1 = typedQualifier(qual, NOmode, ObjectClass.tpe) // need to have an expected type, see #3037 - val qualClass = qual1.tpe.typeSymbol -/* - val targClass = targ.tpe.typeSymbol - if (isNumericValueClass(qualClass) && isNumericValueClass(targClass)) - // convert numeric type casts - atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List())) - else -*/ if (isPrimitiveValueType(targ.tpe) || isErasedValueType(targ.tpe)) { val noNullCheckNeeded = targ.tpe match { case ErasedValueType(tref) => - atPhase(currentRun.erasurePhase) { + enteringPhase(currentRun.erasurePhase) { isPrimitiveValueClass(erasedValueClassArg(tref).typeSymbol) } case _ => @@ -744,7 +736,6 @@ abstract class Erasure extends AddInterfaces } if (noNullCheckNeeded) unbox(qual1, targ.tpe) else { - def nullConst = Literal(Constant(null)) setType NullClass.tpe val untyped = // util.trace("new asinstanceof test") { gen.evalOnce(qual1, context.owner, context.unit) { qual => @@ -817,7 +808,7 @@ abstract class Erasure extends AddInterfaces (tree.attachments.get[TypeRefAttachment]: @unchecked) match { case Some(itype) => val tref = itype.tpe - val argPt = atPhase(currentRun.erasurePhase)(erasedValueClassArg(tref)) + val argPt = enteringPhase(currentRun.erasurePhase)(erasedValueClassArg(tref)) log(s"transforming inject $arg -> $tref/$argPt") val result = typed(arg, mode, argPt) log(s"transformed inject $arg -> $tref/$argPt = $result:${result.tpe}") @@ -885,20 +876,20 @@ abstract class Erasure extends AddInterfaces private def checkNoDoubleDefs(root: Symbol) { def doubleDefError(sym1: Symbol, sym2: Symbol) { // the .toString must also be computed at the earlier phase - val tpe1 = afterRefchecks(root.thisType.memberType(sym1)) - val tpe2 = afterRefchecks(root.thisType.memberType(sym2)) + val tpe1 = exitingRefchecks(root.thisType.memberType(sym1)) + val tpe2 = exitingRefchecks(root.thisType.memberType(sym2)) if (!tpe1.isErroneous && !tpe2.isErroneous) unit.error( if (sym1.owner == root) sym1.pos else root.pos, (if (sym1.owner == sym2.owner) "double definition:\n" else if (sym1.owner == root) "name clash between defined and inherited member:\n" else "name clash between inherited members:\n") + - sym1 + ":" + afterRefchecks(tpe1.toString) + + sym1 + ":" + exitingRefchecks(tpe1.toString) + (if (sym1.owner == root) "" else sym1.locationString) + " and\n" + - sym2 + ":" + afterRefchecks(tpe2.toString) + + sym2 + ":" + exitingRefchecks(tpe2.toString) + (if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) + "\nhave same type" + - (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterPostErasure(sym1.tpe))) + (if (exitingRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + exitingPostErasure(sym1.tpe))) sym1.setInfo(ErrorType) } @@ -908,7 +899,7 @@ abstract class Erasure extends AddInterfaces if (e.sym.isTerm) { var e1 = decls.lookupNextEntry(e) while (e1 ne null) { - if (afterPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) + if (exitingPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) e1 = decls.lookupNextEntry(e1) } } @@ -916,16 +907,17 @@ abstract class Erasure extends AddInterfaces } val opc = new overridingPairs.Cursor(root) { - override def exclude(sym: Symbol): Boolean = - (!sym.isTerm || sym.isPrivate || super.exclude(sym) - // specialized members have no type history before 'specialize', causing double def errors for curried defs - || !sym.hasTypeAt(currentRun.refchecksPhase.id)) + override def exclude(sym: Symbol): Boolean = ( + !sym.isTerm || sym.isPrivate || super.exclude(sym) + // specialized members have no type history before 'specialize', causing double def errors for curried defs + || !sym.hasTypeAt(currentRun.refchecksPhase.id) + ) override def matches(sym1: Symbol, sym2: Symbol): Boolean = - afterPostErasure(sym1.tpe =:= sym2.tpe) + exitingPostErasure(sym1.tpe =:= sym2.tpe) } while (opc.hasNext) { - if (!afterRefchecks( + if (!exitingRefchecks( root.thisType.memberType(opc.overriding) matches root.thisType.memberType(opc.overridden))) { debuglog("" + opc.overriding.locationString + " " + @@ -944,8 +936,8 @@ abstract class Erasure extends AddInterfaces for (member <- root.info.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag BRIDGE) && - afterErasure(member.tpe =:= other.tpe) && - !afterRefchecks( + exitingErasure(member.tpe =:= other.tpe) && + !exitingRefchecks( root.thisType.memberType(member) matches root.thisType.memberType(other))) { debuglog("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString); doubleDefError(member, other) @@ -1041,17 +1033,17 @@ abstract class Erasure extends AddInterfaces Apply(Select(qual, cmpOp), List(gen.mkAttributedQualifier(targ.tpe))) } case RefinedType(parents, decls) if (parents.length >= 2) => - // Optimization: don't generate isInstanceOf tests if the static type - // conforms, because it always succeeds. (Or at least it had better.) - // At this writing the pattern matcher generates some instance tests - // involving intersections where at least one parent is statically known true. - // That needs fixing, but filtering the parents here adds an additional - // level of robustness (in addition to the short term fix.) - val parentTests = parents filterNot (qual.tpe <:< _) - - if (parentTests.isEmpty) Literal(Constant(true)) - else gen.evalOnce(qual, currentOwner, unit) { q => - atPos(tree.pos) { + gen.evalOnce(qual, currentOwner, unit) { q => + // Optimization: don't generate isInstanceOf tests if the static type + // conforms, because it always succeeds. (Or at least it had better.) + // At this writing the pattern matcher generates some instance tests + // involving intersections where at least one parent is statically known true. + // That needs fixing, but filtering the parents here adds an additional + // level of robustness (in addition to the short term fix.) + val parentTests = parents filterNot (qual.tpe <:< _) + + if (parentTests.isEmpty) Literal(Constant(true)) + else atPos(tree.pos) { parentTests map mkIsInstanceOf(q) reduceRight gen.mkAnd } } @@ -1067,6 +1059,7 @@ abstract class Erasure extends AddInterfaces } else if (fn.symbol == Any_isInstanceOf) { preEraseIsInstanceOf } else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) { + // !!! Another spot where we produce overloaded types (see test run/t6301) ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos } else if (fn.symbol.isMethodWithExtension && !fn.symbol.tpe.isErroneous) { Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) @@ -1125,7 +1118,8 @@ abstract class Erasure extends AddInterfaces SelectFromArray(qual, name, erasure(tree.symbol)(qual.tpe)).copyAttrs(fn), args) } - } else if (args.isEmpty && interceptedMethods(fn.symbol)) { + } + else if (args.isEmpty && interceptedMethods(fn.symbol)) { if (fn.symbol == Any_## || fn.symbol == Object_##) { // This is unattractive, but without it we crash here on ().## because after // erasure the ScalaRunTime.hash overload goes from Unit => Int to BoxedUnit => Int. @@ -1137,7 +1131,18 @@ abstract class Erasure extends AddInterfaces case s @ (ShortClass | ByteClass | CharClass) => numericConversion(qual, s) case BooleanClass => If(qual, LIT(true.##), LIT(false.##)) case _ => - global.typer.typed(gen.mkRuntimeCall(nme.hash_, List(qual))) + // Since we are past typer, we need to avoid creating trees carrying + // overloaded types. This logic is custom (and technically incomplete, + // although serviceable) for def hash. What is really needed is for + // the overloading logic presently hidden away in a few different + // places to be properly exposed so we can just call "resolveOverload" + // after typer. Until then: + val alts = ScalaRunTimeModule.info.member(nme.hash_).alternatives + def alt1 = alts find (_.info.paramTypes.head =:= qual.tpe) + def alt2 = ScalaRunTimeModule.info.member(nme.hash_) suchThat (_.info.paramTypes.head.typeSymbol == AnyClass) + val newTree = gen.mkRuntimeCall(nme.hash_, qual :: Nil) setSymbol (alt1 getOrElse alt2) + + global.typer.typed(newTree) } } else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) { // Rewrite 5.getClass to ScalaRunTime.anyValClass(5) @@ -1263,7 +1268,7 @@ abstract class Erasure extends AddInterfaces override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) // log("tree after pretransform: "+tree1) - afterErasure { + exitingErasure { val tree2 = mixinTransformer.transform(tree1) // debuglog("tree after addinterfaces: \n" + tree2) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 1003d417f6..01c22245cb 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -83,12 +83,6 @@ abstract class ExplicitOuter extends InfoTransform } } - /** Issue a migration warning for instance checks which might be on an Array and - * for which the type parameter conforms to Seq, because these answers changed in 2.8. - */ - def isArraySeqTest(lhs: Type, rhs: Type) = - (ArrayClass.tpe <:< lhs.widen) && (rhs.widen matchesPattern SeqClass.tpe) - def outerAccessor(clazz: Symbol): Symbol = { val firstTry = clazz.info.decl(nme.expandedName(nme.OUTER, clazz)) if (firstTry != NoSymbol && firstTry.outerSource == clazz) firstTry @@ -97,7 +91,7 @@ abstract class ExplicitOuter extends InfoTransform def newOuterAccessor(clazz: Symbol) = { val accFlags = SYNTHETIC | ARTIFACT | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 ) val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags) - val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType + val restpe = if (clazz.isTrait) clazz.outerClass.tpe_* else clazz.outerClass.thisType sym expandName clazz sym.referenced = clazz @@ -164,16 +158,13 @@ abstract class ExplicitOuter extends InfoTransform var decls1 = decls if (isInner(clazz) && !clazz.isInterface) { decls1 = decls.cloneScope - val outerAcc = clazz.newMethod(nme.OUTER, clazz.pos) // 3 - outerAcc expandName clazz - - decls1 enter newOuterAccessor(clazz) + decls1 enter newOuterAccessor(clazz) // 3 if (hasOuterField(clazz)) //2 decls1 enter newOuterField(clazz) } if (!clazz.isTrait && !parents.isEmpty) { for (mc <- clazz.mixinClasses) { - val mixinOuterAcc: Symbol = afterExplicitOuter(outerAccessor(mc)) + val mixinOuterAcc: Symbol = exitingExplicitOuter(outerAccessor(mc)) if (mixinOuterAcc != NoSymbol) { if (decls1 eq decls) decls1 = decls.cloneScope val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED) @@ -243,11 +234,6 @@ abstract class ExplicitOuter extends InfoTransform * <blockquote><pre>`base'.$outer$$C1 ... .$outer$$Cn</pre></blockquote> * which refers to the outer instance of class to of * value base. The result is typed but not positioned. - * - * @param base ... - * @param from ... - * @param to ... - * @return ... */ protected def outerPath(base: Tree, from: Symbol, to: Symbol): Tree = { //Console.println("outerPath from "+from+" to "+to+" at "+base+":"+base.tpe) @@ -341,7 +327,7 @@ abstract class ExplicitOuter extends InfoTransform */ def outerAccessorDef: Tree = { val outerAcc = outerAccessor(currentClass) - var rhs: Tree = + val rhs: Tree = if (outerAcc.isDeferred) EmptyTree else This(currentClass) DOT outerField(currentClass) @@ -553,13 +539,6 @@ abstract class ExplicitOuter extends InfoTransform } case _ => - if (settings.Xmigration28.value) tree match { - case TypeApply(fn @ Select(qual, _), args) if fn.symbol == Object_isInstanceOf || fn.symbol == Any_isInstanceOf => - if (isArraySeqTest(qual.tpe, args.head.tpe)) - unit.warning(tree.pos, "An Array will no longer match as Seq[_].") - case _ => () - } - val x = super.transform(tree) if (x.tpe eq null) x else x setType transformInfo(currentOwner, x.tpe) @@ -568,7 +547,7 @@ abstract class ExplicitOuter extends InfoTransform /** The transformation method for whole compilation units */ override def transformUnit(unit: CompilationUnit) { - afterExplicitOuter(super.transformUnit(unit)) + exitingExplicitOuter(super.transformUnit(unit)) } } diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 6f3d7932a5..521d732664 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -8,9 +8,6 @@ package transform import symtab._ import Flags._ import scala.collection.{ mutable, immutable } -import scala.collection.mutable -import scala.tools.nsc.util.FreshNameCreator -import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } /** * Perform Step 1 in the inline classes SIP: Creates extension methods for all @@ -23,7 +20,6 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { import global._ // the global environment import definitions._ // standard classes and methods - import typer.{ typed, atOwner } // methods to type trees /** the following two members override abstract members in Transform */ val phaseName: String = "extmethods" @@ -66,7 +62,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { /** Return the extension method that corresponds to given instance method `meth`. */ - def extensionMethod(imeth: Symbol): Symbol = atPhase(currentRun.refchecksPhase) { + def extensionMethod(imeth: Symbol): Symbol = enteringPhase(currentRun.refchecksPhase) { val companionInfo = imeth.owner.companionModule.info val candidates = extensionNames(imeth) map (companionInfo.decl(_)) filter (_.exists) val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe) @@ -75,32 +71,41 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { matching.head } + /** Recognize a MethodType which represents an extension method. + * + * It may have a curried parameter list with the `$this` alone in the first + * parameter list, in which case that parameter list is dropped. Or, since + * the curried lists disappear during uncurry, it may have a single parameter + * list with `$this` as the first parameter, in which case that parameter is + * removed from the list. + */ + object ExtensionMethodType { + def unapply(tp: Type) = tp match { + case MethodType(thiz :: rest, restpe) if thiz.name == nme.SELF => + Some( if (rest.isEmpty) restpe else MethodType(rest, restpe) ) + case _ => + None + } + } + /** This method removes the `$this` argument from the parameter list a method. * * A method may be a `PolyType`, in which case we tear out the `$this` and the class - * type params from its nested `MethodType`. - * It may be a `MethodType`, either with a curried parameter list in which the first argument - * is a `$this` - we just return the rest of the list. - * This means that the corresponding symbol was generated during `extmethods`. - * - * It may also be a `MethodType` in which the `$this` does not appear in a curried parameter list. - * The curried lists disappear during `uncurry`, and the methods may be duplicated afterwards, - * for instance, during `specialize`. - * In this case, the first argument is `$this` and we just get rid of it. + * type params from its nested `MethodType`. Or it may be a MethodType, as + * described at the ExtensionMethodType extractor. */ private def normalize(stpe: Type, clazz: Symbol): Type = stpe match { case PolyType(tparams, restpe) => - GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe.substSym(tparams takeRight clazz.typeParams.length, clazz.typeParams), clazz)) - case MethodType(List(thiz), restpe) if thiz.name == nme.SELF => - restpe - case MethodType(tparams, restpe) => - MethodType(tparams.drop(1), restpe) + // method type parameters, class type parameters + val (mtparams, ctparams) = tparams splitAt (tparams.length - clazz.typeParams.length) + GenPolyType(mtparams, normalize(restpe.substSym(ctparams, clazz.typeParams), clazz)) + case ExtensionMethodType(etpe) => + etpe case _ => stpe } class Extender(unit: CompilationUnit) extends TypingTransformer(unit) { - private val extensionDefs = mutable.Map[Symbol, mutable.ListBuffer[Tree]]() def checkNonCyclic(pos: Position, seen: Set[Symbol], clazz: Symbol): Unit = @@ -111,27 +116,51 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { if (unboxed.isDerivedValueClass) checkNonCyclic(pos, seen + clazz, unboxed) } + /** We will need to clone the info of the original method (which obtains clones + * of the method type parameters), clone the type parameters of the value class, + * and create a new polymethod with the union of all those type parameters, with + * their infos adjusted to be consistent with their new home. Example: + * + * class Foo[+A <: AnyRef](val xs: List[A]) extends AnyVal { + * def baz[B >: A](x: B): List[B] = x :: xs + * // baz has to be transformed into this extension method, where + * // A is cloned from class Foo and B is cloned from method baz: + * // def extension$baz[B >: A <: Any, A >: Nothing <: AnyRef]($this: Foo[A])(x: B): List[B] + * } + * + * TODO: factor out the logic for consolidating type parameters from a class + * and a method for re-use elsewhere, because nobody will get this right without + * some higher level facilities. + */ def extensionMethInfo(extensionMeth: Symbol, origInfo: Type, clazz: Symbol): Type = { - // No variance for method type parameters - var newTypeParams = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) map (_ resetFlag COVARIANT | CONTRAVARIANT) - val thisParamType = appliedType(clazz.typeConstructor, newTypeParams map (_.tpeHK)) - val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType - def transform(clonedType: Type): Type = clonedType match { - case MethodType(params, restpe) => - // I assume it was a bug that this was dropping params... [Martin]: No, it wasn't; it's curried. - MethodType(List(thisParam), clonedType) - case NullaryMethodType(restpe) => - MethodType(List(thisParam), restpe) - } - val GenPolyType(tparams, restpe) = origInfo cloneInfo extensionMeth - GenPolyType(tparams ::: newTypeParams, transform(restpe) substSym (clazz.typeParams, newTypeParams)) - } + val GenPolyType(tparamsFromMethod, methodResult) = origInfo cloneInfo extensionMeth + // Start with the class type parameters - clones will be method type parameters + // so must drop their variance. + val tparamsFromClass = cloneSymbolsAtOwner(clazz.typeParams, extensionMeth) map (_ resetFlag COVARIANT | CONTRAVARIANT) + def fix(tp: Type) = tp.substSym(clazz.typeParams, tparamsFromClass) - private def allParams(tpe: Type): List[Symbol] = tpe match { - case MethodType(params, res) => params ::: allParams(res) - case _ => List() + val thisParamType = appliedType(clazz, tparamsFromClass map (_.tpeHK): _*) + val thisParam = extensionMeth.newValueParameter(nme.SELF, extensionMeth.pos) setInfo thisParamType + val resultType = MethodType(List(thisParam), dropNullaryMethod(methodResult)) + + // We can't substitute symbols on the entire polytype because we + // need to modify the bounds of the cloned type parameters, but we + // don't want to substitute for the cloned type parameters themselves. + val tparams = tparamsFromMethod ::: tparamsFromClass + GenPolyType(tparams map (_ modifyInfo fix), fix(resultType)) + + // For reference, calling fix on the GenPolyType plays out like this: + // error: scala.reflect.internal.Types$TypeError: type arguments [B#7344,A#6966] + // do not conform to method extension$baz#16148's type parameter bounds + // + // And the difference is visible here. See how B is bounded from below by A#16149 + // in both cases, but in the failing case, the other type parameter has turned into + // a different A. (What is that A? It is a clone of the original A created in + // SubstMap during the call to substSym, but I am not clear on all the particulars.) + // + // bad: [B#16154 >: A#16149, A#16155 <: AnyRef#2189]($this#16156: Foo#6965[A#16155])(x#16157: B#16154)List#2457[B#16154] + // good: [B#16151 >: A#16149, A#16149 <: AnyRef#2189]($this#16150: Foo#6965[A#16149])(x#16153: B#16151)List#2457[B#16151] } - override def transform(tree: Tree): Tree = { tree match { case Template(_, _, _) => @@ -146,37 +175,56 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { super.transform(tree) } else tree case DefDef(_, _, tparams, vparamss, _, rhs) if tree.symbol.isMethodWithExtension => - val companion = currentOwner.companionModule - val origMeth = tree.symbol - val extensionName = extensionNames(origMeth).head - val extensionMeth = companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL) - .setAnnotations(origMeth.annotations) - companion.info.decls.enter(extensionMeth) - val newInfo = extensionMethInfo(extensionMeth, origMeth.info, currentOwner) + val origMeth = tree.symbol + val origThis = currentOwner + val origTpeParams = tparams.map(_.symbol) ::: origThis.typeParams // method type params ++ class type params + val origParams = vparamss.flatten map (_.symbol) + val companion = origThis.companionModule + + def makeExtensionMethodSymbol = { + val extensionName = extensionNames(origMeth).head + val extensionMeth = ( + companion.moduleClass.newMethod(extensionName, origMeth.pos, origMeth.flags & ~OVERRIDE & ~PROTECTED | FINAL) + setAnnotations origMeth.annotations + ) + companion.info.decls.enter(extensionMeth) + } + + val extensionMeth = makeExtensionMethodSymbol + val newInfo = extensionMethInfo(extensionMeth, origMeth.info, origThis) extensionMeth setInfo newInfo - log("Value class %s spawns extension method.\n Old: %s\n New: %s".format( - currentOwner, - origMeth.defString, - extensionMeth.defString)) // extensionMeth.defStringSeenAs(origInfo - - def thisParamRef = gen.mkAttributedIdent(extensionMeth.info.params.head setPos extensionMeth.pos) - val GenPolyType(extensionTpeParams, extensionMono) = extensionMeth.info - val origTpeParams = (tparams map (_.symbol)) ::: currentOwner.typeParams - val extensionBody = rhs + + log(s"Value class $origThis spawns extension method.\n Old: ${origMeth.defString}\n New: ${extensionMeth.defString}") + + val GenPolyType(extensionTpeParams, MethodType(thiz :: Nil, extensionMono)) = newInfo + val extensionParams = allParameters(extensionMono) + val extensionThis = gen.mkAttributedIdent(thiz setPos extensionMeth.pos) + + val extensionBody = ( + rhs .substituteSymbols(origTpeParams, extensionTpeParams) - .substituteSymbols(vparamss.flatten map (_.symbol), allParams(extensionMono).tail) - .substituteThis(currentOwner, thisParamRef) - .changeOwner((origMeth, extensionMeth)) - extensionDefs(companion) += atPos(tree.pos) { DefDef(extensionMeth, extensionBody) } - val extensionCallPrefix = Apply( - gen.mkTypeApply(gen.mkAttributedRef(companion), extensionMeth, origTpeParams map (_.tpeHK)), - List(This(currentOwner))) - val extensionCall = atOwner(origMeth) { - localTyper.typedPos(rhs.pos) { - gen.mkForwarder(extensionCallPrefix, mmap(vparamss)(_.symbol)) - } - } - deriveDefDef(tree)(_ => extensionCall) + .substituteSymbols(origParams, extensionParams) + .substituteThis(origThis, extensionThis) + .changeOwner(origMeth -> extensionMeth) + ) + + // Record the extension method ( FIXME: because... ? ) + extensionDefs(companion) += atPos(tree.pos)(DefDef(extensionMeth, extensionBody)) + + // These three lines are assembling Foo.bar$extension[T1, T2, ...]($this) + // which leaves the actual argument application for extensionCall. + val sel = Select(gen.mkAttributedRef(companion), extensionMeth) + val targs = origTpeParams map (_.tpeHK) + val callPrefix = gen.mkMethodCall(sel, targs, This(origThis) :: Nil) + + // Apply all the argument lists. + deriveDefDef(tree)(_ => + atOwner(origMeth)( + localTyper.typedPos(rhs.pos)( + gen.mkForwarder(callPrefix, mmap(vparamss)(_.symbol)) + ) + ) + ) case _ => super.transform(tree) } diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index cd26f95958..a52dadb134 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -8,28 +8,22 @@ package transform import symtab._ import Flags._ -import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer abstract class Flatten extends InfoTransform { import global._ - import definitions._ /** the following two members override abstract members in Transform */ val phaseName: String = "flatten" - /** Updates the owning scope with the given symbol; returns the old symbol. + /** Updates the owning scope with the given symbol, unlinking any others. */ - private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = afterFlatten { + private def replaceSymbolInCurrentScope(sym: Symbol): Unit = exitingFlatten { val scope = sym.owner.info.decls - val old = scope lookup sym.name andAlso scope.unlink + val old = (scope lookupUnshadowedEntries sym.name).toList + old foreach (scope unlink _) scope enter sym - - if (old eq NoSymbol) - log(s"lifted ${sym.fullLocationString}") - else - log(s"lifted ${sym.fullLocationString} after unlinking existing $old from scope.") - + log(s"lifted ${sym.fullLocationString}" + ( if (old.isEmpty) "" else " after unlinking $old from scope." )) old } @@ -53,7 +47,7 @@ abstract class Flatten extends InfoTransform { clazz.isClass && !clazz.isPackageClass && { // Cannot flatten here: class A[T] { object B } // was "at erasurePhase.prev" - beforeErasure(clazz.typeParams.isEmpty) + enteringErasure(clazz.typeParams.isEmpty) } } @@ -67,11 +61,11 @@ abstract class Flatten extends InfoTransform { val decls1 = scopeTransform(clazz) { val decls1 = newScope if (clazz.isPackageClass) { - afterFlatten { decls foreach (decls1 enter _) } + exitingFlatten { decls foreach (decls1 enter _) } } else { val oldowner = clazz.owner - afterFlatten { oldowner.info } + exitingFlatten { oldowner.info } parents1 = parents mapConserve (this) for (sym <- decls) { @@ -123,7 +117,7 @@ abstract class Flatten extends InfoTransform { liftedDefs(sym.enclosingTopLevelClass.owner) += tree EmptyTree case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) => - afterFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym))) + exitingFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym))) case _ => tree } diff --git a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala index b6dbacaa29..dc321e26ca 100644 --- a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala +++ b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala @@ -10,11 +10,11 @@ package transform * An InfoTransform contains a compiler phase that transforms trees and symbol infos -- making sure they stay consistent. * The symbol info is transformed assuming it is consistent right before this phase. * The info transformation is triggered by Symbol::rawInfo, which caches the results in the symbol's type history. - * This way sym.info (during an atPhase(p)) can look up what the symbol's info should look like at the beginning of phase p. + * This way sym.info (during an enteringPhase(p)) can look up what the symbol's info should look like at the beginning of phase p. * (If the transformed info had not been stored yet, rawInfo will compute the info by composing the info-transformers * of the most recent phase before p, up to the transformer of the phase right before p.) * - * Concretely, atPhase(p) { sym.info } yields the info *before* phase p has transformed it. Imagine you're a phase and it all makes sense. + * Concretely, enteringPhase(p) { sym.info } yields the info *before* phase p has transformed it. Imagine you're a phase and it all makes sense. */ trait InfoTransform extends Transform { import global.{Symbol, Type, InfoTransformer, infoTransformers} diff --git a/src/compiler/scala/tools/nsc/transform/InlineErasure.scala b/src/compiler/scala/tools/nsc/transform/InlineErasure.scala index 0af3cf732f..83dbc23014 100644 --- a/src/compiler/scala/tools/nsc/transform/InlineErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/InlineErasure.scala @@ -1,9 +1,11 @@ package scala.tools.nsc package transform -trait InlineErasure { self: Erasure => - +trait InlineErasure { + self: Erasure => + +/** import global._ import definitions._ - -}
\ No newline at end of file + **/ +} diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 21213cf9d9..481228fb3d 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -278,7 +278,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD bmps(n) else { val sym = meth.newVariable(nme.newBitmapName(nme.BITMAP_NORMAL, n), meth.pos).setInfo(ByteClass.tpe) - beforeTyper { + enteringTyper { sym addAnnotation VolatileAttr } diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 64bb98e2c5..ac1cdd1f46 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -68,7 +68,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * maps all other types to themselves. */ private def toInterface(tp: Type): Type = - beforeMixin(tp.typeSymbol.toInterface).tpe + enteringMixin(tp.typeSymbol.toInterface).tpe private def isFieldWithBitmap(field: Symbol) = { field.info // ensure that nested objects are transformed @@ -102,7 +102,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { private val toInterfaceMap = new TypeMap { def apply(tp: Type): Type = mapOver( tp match { case TypeRef(pre, sym, args) if sym.isImplClass => - typeRef(pre, beforeMixin(sym.toInterface), args) + typeRef(pre, enteringMixin(sym.toInterface), args) case _ => tp }) } @@ -119,7 +119,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * @param mixinClass The mixin class that produced the superaccessor */ private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol = - afterPickler { + exitingPickler { var bcs = base.info.baseClasses.dropWhile(mixinClass != _).tail var sym: Symbol = NoSymbol debuglog("starting rebindsuper " + base + " " + member + ":" + member.tpe + @@ -165,7 +165,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { addMember(clazz, cloneBeforeErasure(mixinClass, mixinMember, clazz)) def cloneBeforeErasure(mixinClass: Symbol, mixinMember: Symbol, clazz: Symbol): Symbol = { - val newSym = beforeErasure { + val newSym = enteringErasure { // since we used `mixinMember` from the interface that represents the trait that's // being mixed in, have to instantiate the interface type params (that may occur in mixinMember's // info) as they are seen from the class. We can't use the member that we get from the @@ -197,9 +197,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * - lazy fields don't get a setter. */ def addLateInterfaceMembers(clazz: Symbol) { - def makeConcrete(member: Symbol) = - member setPos clazz.pos resetFlag (DEFERRED | lateDEFERRED) - if (treatedClassInfos(clazz) != clazz.info) { treatedClassInfos(clazz) = clazz.info assert(phase == currentRun.mixinPhase, phase) @@ -292,7 +289,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { for (mixinMember <- mixinClass.info.decls) { if (isConcreteAccessor(mixinMember)) { if (isOverriddenAccessor(mixinMember, clazz.info.baseClasses)) - debugwarn("!!! is overridden val: "+mixinMember.fullLocationString) + devWarning(s"Overridden concrete accessor: ${mixinMember.fullLocationString}") else { // mixin field accessors val mixedInAccessor = cloneAndAddMixinMember(mixinClass, mixinMember) @@ -311,12 +308,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // mixinMember is a value of type unit. No field needed ; case _ => // otherwise mixin a field as well - // atPhase: the private field is moved to the implementation class by erasure, + // enteringPhase: the private field is moved to the implementation class by erasure, // so it can no longer be found in the mixinMember's owner (the trait) - val accessed = beforePickler(mixinMember.accessed) + val accessed = enteringPickler(mixinMember.accessed) // #3857, need to retain info before erasure when cloning (since cloning only // carries over the current entry in the type history) - val sym = beforeErasure { + val sym = enteringErasure { // so we have a type history entry before erasure clazz.newValue(nme.getterToLocal(mixinMember.name), mixinMember.pos).setInfo(mixinMember.tpe.resultType) } @@ -380,14 +377,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { var parents1 = parents var decls1 = decls if (!clazz.isPackageClass) { - afterMixin(clazz.owner.info) + exitingMixin(clazz.owner.info) if (clazz.isImplClass) { clazz setFlag lateMODULE var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName) if (sourceModule != NoSymbol) { sourceModule setPos sym.pos if (sourceModule.flags != MODULE) { - log("!!! Directly setting sourceModule flags from %s to MODULE".format(flagsToString(sourceModule.flags))) + log("!!! Directly setting sourceModule flags from %s to MODULE".format(sourceModule.flagString)) sourceModule.flags = MODULE } } @@ -408,7 +405,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { parents1 = parents.head :: (parents.tail map toInterface) } } - //decls1 = atPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug + //decls1 = enteringPhase(phase.next)(newScopeWith(decls1.toList: _*))//debug if ((parents1 eq parents) && (decls1 eq decls)) tp else ClassInfoType(parents1, decls1, clazz) @@ -438,7 +435,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree match { case Assign(lhs, rhs) => traverse(rhs) // assignments don't count case _ => - if (tree.hasSymbol && tree.symbol != NoSymbol) { + if (tree.hasSymbolField && tree.symbol != NoSymbol) { val sym = tree.symbol if ((sym.hasAccessorFlag || (sym.isTerm && !sym.isMethod)) && sym.isPrivate @@ -525,7 +522,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree match { case Template(parents, self, body) => localTyper = erasure.newTyper(rootContext.make(tree, currentOwner)) - afterMixin(currentOwner.owner.info)//todo: needed? + exitingMixin(currentOwner.owner.info)//todo: needed? if (!currentOwner.isTrait && !isPrimitiveValueClass(currentOwner)) addMixedinMembers(currentOwner, unit) @@ -544,7 +541,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { else EmptyTree } else { - if (currentOwner.isTrait && sym.isSetter && !beforePickler(sym.isDeferred)) { + if (currentOwner.isTrait && sym.isSetter && !enteringPickler(sym.isDeferred)) { sym.addAnnotation(TraitSetterAnnotationClass) } tree @@ -591,8 +588,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree } - /** Create a static reference to given symbol <code>sym</code> of the - * form <code>M.sym</code> where M is the symbol's implementation module. + /** Create a static reference to given symbol `sym` of the + * form `M.sym` where M is the symbol's implementation module. */ private def staticRef(sym: Symbol): Tree = { sym.owner.info //todo: needed? @@ -674,8 +671,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def addValDef(sym: Symbol, rhs: Tree = EmptyTree) = addDef(position(sym), ValDef(sym, rhs)) /** Add `newdefs` to `stats`, removing any abstract method definitions - * in <code>stats</code> that are matched by some symbol defined in - * <code>newDefs</code>. + * in `stats` that are matched by some symbol defined in + * `newDefs`. */ def add(stats: List[Tree], newDefs: List[Tree]) = { val newSyms = newDefs map (_.symbol) @@ -703,7 +700,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val rhs0 = (Super(clazz, tpnme.EMPTY) DOT stat.symbol.alias)(vparams map (v => Ident(v.symbol)): _*) val rhs1 = localTyped(stat.pos, rhs0, stat.symbol.tpe.resultType) - deriveDefDef(stat)(_ => beforeMixin(transform(rhs1))) + deriveDefDef(stat)(_ => enteringMixin(transform(rhs1))) case _ => stat } @@ -722,7 +719,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def createBitmap: Symbol = { val bitmapKind = bitmapKindForCategory(category) val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo bitmapKind.tpe - beforeTyper(sym addAnnotation VolatileAttr) + enteringTyper(sym addAnnotation VolatileAttr) category match { case nme.BITMAP_TRANSIENT | nme.BITMAP_CHECKINIT_TRANSIENT => sym addAnnotation TransientAttr @@ -804,7 +801,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ class TreeSymSubstituterWithCopying(from: List[Symbol], to: List[Symbol]) extends TreeSymSubstituter(from, to) { override def transform(tree: Tree): Tree = - if (tree.hasSymbol && from.contains(tree.symbol)) + if (tree.hasSymbolField && from.contains(tree.symbol)) super.transform(tree.duplicate) else super.transform(tree.duplicate) @@ -868,7 +865,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { rhs match { case Block(List(assign), returnTree) => val Assign(moduleVarRef, _) = assign - val cond = Apply(Select(moduleVarRef, nme.eq), List(NULL)) + val cond = Apply(Select(moduleVarRef, Object_eq), List(NULL)) mkFastPathBody(clazz, moduleSym, cond, List(assign), List(NULL), returnTree, attrThis, args) case _ => assert(false, "Invalid getter " + rhs + " for module in class " + clazz) @@ -884,7 +881,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val result = IF (mkTest(clazz, mask, bitmapSym, false, kind)) . THEN (retVal) . - ELSE (THROW(UninitializedErrorClass, LIT(msg))) + ELSE (Throw(NewFromConstructor(UninitializedFieldConstructor, LIT(msg)))) typedPos(pos)(BLOCK(result, retVal)) } @@ -980,12 +977,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def addInitBits(clazz: Symbol, rhs: Tree): Tree = new AddInitBitsTransformer(clazz) transform rhs - def isCheckInitField(field: Symbol) = - needsInitFlag(field) && !field.isDeferred - - def superClassesToCheck(clazz: Symbol) = - clazz.ancestors filterNot (_ hasFlag TRAIT | JAVA) - // begin addNewDefs /** Fill the map from fields to offset numbers. @@ -1153,9 +1144,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { qual case Apply(Select(qual, _), args) => - /** Changes <code>qual.m(args)</code> where m refers to an implementation + /** Changes `qual.m(args)` where m refers to an implementation * class method to Q.m(S, args) where Q is the implementation module of - * <code>m</code> and S is the self parameter for the call, which + * `m` and S is the self parameter for the call, which * is determined as follows: * - if qual != super, qual itself * - if qual == super, and we are in an implementation class, @@ -1166,7 +1157,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def implSym = implClass(sym.owner).info.member(sym.name) assert(target ne NoSymbol, List(sym + ":", sym.tpe, sym.owner, implClass(sym.owner), implSym, - beforePrevPhase(implSym.tpe), phase) mkString " " + enteringPrevPhase(implSym.tpe), phase) mkString " " ) typedPos(tree.pos)(Apply(staticRef(target), transformSuper(qual) :: args)) } @@ -1195,7 +1186,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { typedPos(tree.pos)((transformSuper(qual) DOT sym1)()) } else { - staticCall(beforePrevPhase(sym.overridingSymbol(implClass(sym.owner)))) + staticCall(enteringPrevPhase(sym.overridingSymbol(implClass(sym.owner)))) } } else { @@ -1213,7 +1204,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree case Select(qual, name) if sym.owner.isImplClass && !isStaticOnly(sym) => - assert(!sym.isMethod, "no method allowed here: %s%s %s".format(sym, sym.isImplOnly, flagsToString(sym.flags))) + assert(!sym.isMethod, "no method allowed here: %s%s %s".format(sym, sym.isImplOnly, sym.flagString)) // refer to fields in some implementation class via an abstract // getter in the interface. val iface = toInterface(sym.owner.tpe).typeSymbol @@ -1245,7 +1236,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val tree1 = super.transform(preTransform(tree)) // localTyper needed when not flattening inner classes. parts after an // inner class will otherwise be typechecked with a wrong scope - try afterMixin(postTransform(tree1)) + try exitingMixin(postTransform(tree1)) finally localTyper = saved } } diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala index 67be81bd3c..28e6e3be26 100644 --- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala +++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala @@ -31,11 +31,11 @@ abstract class OverridingPairs { private val self = base.thisType /** Symbols to exclude: Here these are constructors, private locals, - * and bridges. But it may be refined in subclasses. + * and hidden symbols, including bridges. But it may be refined in subclasses. * */ protected def exclude(sym: Symbol): Boolean = - sym.isConstructor || sym.isPrivateLocal || sym.hasFlag(BRIDGE) + sym.isConstructor || sym.isPrivateLocal || sym.isArtifact /** The parents of base (may also be refined). */ diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala index 3ef32caa2c..a8dc47046b 100644 --- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala +++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala @@ -24,7 +24,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { case ConstantType(Constant(tp: Type)) => ConstantType(Constant(apply(tp))) case ErasedValueType(tref) => - atPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref)) + enteringPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref)) case _ => mapOver(tp) } } @@ -39,7 +39,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { Apply(sel @ Select( Apply(Select(New(tpt), nme.CONSTRUCTOR), List(arg)), acc), List()) - if atPhase(currentRun.erasurePhase) { + if enteringPhase(currentRun.erasurePhase) { tpt.tpe.typeSymbol.isDerivedValueClass && sel.symbol == tpt.tpe.typeSymbol.derivedValueClassUnbox } => @@ -50,7 +50,7 @@ trait PostErasure extends InfoTransform with TypingTransformers { Apply(Select(New(tpt1), nme.CONSTRUCTOR), List(arg1)), cmp), List(Apply(Select(New(tpt2), nme.CONSTRUCTOR), List(arg2)))) - if atPhase(currentRun.erasurePhase) { + if enteringPhase(currentRun.erasurePhase) { tpt1.tpe.typeSymbol.isDerivedValueClass && (sel.symbol == Object_== || sel.symbol == Object_!=) && tpt2.tpe.typeSymbol == tpt1.tpe.typeSymbol diff --git a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala index 44d8860916..cffb483072 100644 --- a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala +++ b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala @@ -11,9 +11,8 @@ package transform abstract class SampleTransform extends Transform { // inherits abstract value `global` and class `Phase` from Transform - import global._ // the global environment - import definitions._ // standard classes and methods - import typer.{typed, atOwner} // methods to type trees + import global._ // the global environment + import typer.typed // method to type trees /** the following two members override abstract members in Transform */ val phaseName: String = "sample-phase" diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 2f79472cfb..2574644727 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -101,7 +101,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Concrete methods that use a specialized type, or override such methods. */ private val concreteSpecMethods = perRunCaches.newWeakSet[Symbol]() - private def specializedTypes(tps: List[Symbol]) = tps filter (_.isSpecialized) private def specializedOn(sym: Symbol): List[Symbol] = { sym getAnnotation SpecializedClass match { case Some(AnnotationInfo(_, Nil, _)) => specializableTypes.map(_.typeSymbol) @@ -119,6 +118,22 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } + @annotation.tailrec private def findSymbol[T](candidates: List[T], f: T => Symbol): Symbol = { + if (candidates.isEmpty) NoSymbol + else f(candidates.head) match { + case NoSymbol => findSymbol(candidates.tail, f) + case sym => sym + } + } + private def hasNewParents(tree: Tree) = { + val parents = tree.symbol.info.parents + val prev = enteringPrevPhase(tree.symbol.info.parents) + (parents != prev) && { + debuglog(s"$tree parents changed from: $prev to: $parents") + true + } + } + // If we replace `isBoundedGeneric` with (tp <:< AnyRefClass.tpe), // then pos/spec-List.scala fails - why? Does this kind of check fail // for similar reasons? Does `sym.isAbstractType` make a difference? @@ -169,15 +184,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - /** Returns the generic class that was specialized to 'sClass', or - * 'sClass' itself if sClass is not a specialized subclass. - */ - def genericClass(sClass: Symbol): Symbol = - if (sClass.isSpecialized) sClass.superClass - else sClass - case class Overload(sym: Symbol, env: TypeEnv) { override def toString = "specialized overload " + sym + " in " + env + def matchesSym(sym1: Symbol) = sym.info =:= sym1.info + def matchesEnv(env1: TypeEnv) = TypeEnv.includes(env, env1) + } + private def newOverload(method: Symbol, specializedMethod: Symbol, env: TypeEnv) = { + assert(!specializedMethod.isOverloaded, specializedMethod.defString) + val om = Overload(specializedMethod, env) + overloads(method) ::= om + om } /** Just to mark uncheckable */ @@ -199,8 +215,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * type bounds of other @specialized type parameters (and not in its result type). */ def degenerate = false - - def isAccessor = false } /** Symbol is a special overloaded method of 'original', in the environment env. */ @@ -218,11 +232,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def target = t } - /** Symbol is a specialized accessor for the `target` field. */ - case class SpecializedAccessor(target: Symbol) extends SpecializedInfo { - override def isAccessor = true + /** Symbol is a special overload of the super accessor. */ + case class SpecialSuperAccessor(t: Symbol) extends SpecializedInfo { + def target = t } + /** Symbol is a specialized accessor for the `target` field. */ + case class SpecializedAccessor(target: Symbol) extends SpecializedInfo { } + /** Symbol is a specialized method whose body should be the target's method body. */ case class Implementation(target: Symbol) extends SpecializedInfo @@ -260,9 +277,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def specializedParams(sym: Symbol): List[Symbol] = sym.info.typeParams filter (_.isSpecialized) - def splitParams(tps: List[Symbol]) = - tps partition (_.isSpecialized) - /** Given an original class symbol and a list of types its type parameters are instantiated at * returns a list of type parameters that should remain in the TypeRef when instantiating a * specialized type. @@ -289,10 +303,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - /** Return the specialized overload of sym in the given env, if any. */ - def overload(sym: Symbol, env: TypeEnv) = - overloads(sym).find(ov => TypeEnv.includes(ov.env, env)) - /** Return the specialized name of 'sym' in the given environment. It * guarantees the same result regardless of the map order by sorting * type variables alphabetically. @@ -397,7 +407,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { tpes foreach (tp => buf ++= specializedTypeVars(tp)) buf.result } - def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = beforeTyper(specializedTypeVars(sym.info)) + def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = enteringTyper(specializedTypeVars(sym.info)) /** Return the set of @specialized type variables mentioned by the given type. * It only counts type variables that appear: @@ -521,7 +531,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long, newName: Name = null) = member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED), newName) - sClass.sourceFile = clazz.sourceFile + sClass.associatedFile = clazz.sourceFile currentRun.symSource(sClass) = clazz.sourceFile // needed later on by mixin val env = mapAnyRefsInSpecSym(env0, clazz, sClass) @@ -533,7 +543,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { var newClassTParams: List[Symbol] = Nil // unspecialized type parameters of 'specializedClass' (cloned) // has to be a val in order to be computed early. It is later called - // within 'atPhase(next)', which would lead to an infinite cycle otherwise + // within 'enteringPhase(next)', which would lead to an infinite cycle otherwise val specializedInfoType: Type = { oldClassTParams = survivingParams(clazz.info.typeParams, env) newClassTParams = produceTypeParameters(oldClassTParams, sClass, env) map subst(env) @@ -553,7 +563,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { var res: List[Type] = Nil // log(specializedClass + ": seeking specialized parents of class with parents: " + parents.map(_.typeSymbol)) for (p <- parents) { - val stp = afterSpecialize(specializedType(p)) + val stp = exitingSpecialize(specializedType(p)) if (stp != p) if (p.typeSymbol.isTrait) res ::= stp else if (currentRun.compiles(clazz)) @@ -563,7 +573,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { res } - var parents = List(applyContext(beforeTyper(clazz.tpe))) + var parents = List(applyContext(enteringTyper(clazz.tpe_*))) // log("!!! Parents: " + parents + ", sym: " + parents.map(_.typeSymbol)) if (parents.head.typeSymbol.isTrait) parents = parents.head.parents.head :: parents @@ -585,7 +595,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { GenPolyType(newClassTParams, ClassInfoType(parents ::: extraSpecializedMixins, decls1, sClass)) } - afterSpecialize(sClass setInfo specializedInfoType) + exitingSpecialize(sClass setInfo specializedInfoType) val fullEnv = outerEnv ++ env /** Enter 'sym' in the scope of the current specialized class. It's type is @@ -628,7 +638,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { info(om) = if (original.isDeferred) Forward(original) else Implementation(original) typeEnv(om) = env ++ typeEnv(m) // add the environment for any method tparams - overloads(specMember) ::= Overload(om, typeEnv(om)) + newOverload(specMember, om, typeEnv(om)) enterMember(om) } @@ -773,7 +783,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (existing != NoSymbol) clazz.owner.info.decls.unlink(existing) - afterSpecialize(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes + exitingSpecialize(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes } if (subclasses.nonEmpty) clazz.resetFlag(FINAL) cleanAnyRefSpecCache(clazz, decls1) @@ -791,7 +801,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { */ private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = { sym :: ( - if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil + if (!sym.isMethod || enteringTyper(sym.typeParams.isEmpty)) Nil else { // debuglog("normalizeMember: " + sym.fullNameAsName('.').decode) var specializingOn = specializedParams(sym) @@ -835,7 +845,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("%s expands to %s in %s".format(sym, specMember.name.decode, pp(env))) info(specMember) = NormalizedMember(sym) - overloads(sym) ::= Overload(specMember, env) + newOverload(sym, specMember, env) owner.info.decls.enter(specMember) specMember } @@ -870,6 +880,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec)) + owner.info.decls.enter(specMember) typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s } @@ -877,9 +888,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (wasSpec.nonEmpty) debuglog("specialized overload for %s in %s".format(specMember, pp(typeEnv(specMember)))) - overloads(sym) ::= Overload(specMember, spec) + newOverload(sym, specMember, spec) info(specMember) = SpecialOverload(sym, typeEnv(specMember)) - specMember } @@ -899,10 +909,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } /** Return the specialized overload of `m`, in the given environment. */ - private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = { + private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv, nameSymbol: Symbol = NoSymbol): Symbol = { val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR) // this method properly duplicates the symbol's info - ( sym.cloneSymbol(owner, newFlags, newName = specializedName(sym, env)) + val specname = specializedName(nameSymbol orElse sym, env) + ( sym.cloneSymbol(owner, newFlags, newName = specname) modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner))) ) } @@ -949,7 +960,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { checkOverriddenTParams(overridden) val env = unify(overridden.info, overriding.info, emptyEnv, false, true) - def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env))) + def atNext = exitingSpecialize(overridden.owner.info.decl(specializedName(overridden, env))) if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) { debuglog(" " + pp(env) + " found " + atNext) @@ -962,14 +973,32 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } (clazz.info.decls flatMap { overriding => needsSpecialOverride(overriding) match { - case (NoSymbol, _) => None + case (NoSymbol, _) => + if (overriding.isSuperAccessor) { + val alias = overriding.alias + debuglog("checking special overload for super accessor: %s, alias for %s".format(overriding.fullName, alias.fullName)) + needsSpecialOverride(alias) match { + case nope @ (NoSymbol, _) => None + case (overridden, env) => + val om = specializedOverload(clazz, overriding, env, overridden) + om.setName(nme.superName(om.name)) + om.asInstanceOf[TermSymbol].setAlias(info(alias).target) + om.owner.info.decls.enter(om) + info(om) = SpecialSuperAccessor(om) + om.makeNotPrivate(om.owner) + newOverload(overriding, om, env) + Some(om) + } + } else None case (overridden, env) => val om = specializedOverload(clazz, overridden, env) + clazz.info.decls.enter(om) debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info)) + if (overriding.isAbstractOverride) om.setFlag(ABSOVERRIDE) typeEnv(om) = env addConcreteSpecMethod(overriding) info(om) = ( - if (overriding.isDeferred) { // abstract override + if (overriding.isDeferred) { // abstract override debuglog("abstract override " + overriding.fullName + " with specialized " + om.fullName) Forward(overriding) } @@ -989,8 +1018,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { SpecialOverride(impl) } ) - overloads(overriding) ::= Overload(om, env) - ifDebug(afterSpecialize(assert( + newOverload(overriding, om, env) + ifDebug(exitingSpecialize(assert( overridden.owner.info.decl(om.name) != NoSymbol, "Could not find " + om.name + " in " + overridden.owner.info.decls)) ) @@ -1019,7 +1048,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1)) env + ((sym1, tp2)) else if (isSpecializedAnyRefSubtype(tp2, sym1)) - env + ((sym1, tp2)) // env + ((sym1, AnyRefClass.tpe)) + env + ((sym1, tp2)) else if (strict) unifyError(tp1, tp2) else @@ -1076,10 +1105,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - /** Apply type bindings in the given environment `env` to all declarations. */ - private def subst(env: TypeEnv, decls: List[Symbol]): List[Symbol] = - decls map subst(env) - /** Apply the type environment 'env' to the given type. All type * bindings are supposed to be to primitive types. A type variable * that is annotated with 'uncheckedVariance' is mapped to the corresponding @@ -1106,33 +1131,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def subst(env: TypeEnv)(decl: Symbol): Symbol = decl modifyInfo (info => - if (decl.isConstructor) MethodType(subst(env, info).params, decl.owner.tpe) + if (decl.isConstructor) MethodType(subst(env, info).params, decl.owner.tpe_*) else subst(env, info) ) - /** Checks if the type parameter symbol is not specialized - * and is used as type parameters when extending a class with a specialized - * type parameter. - * At some point we may remove this restriction. - * - * Example: - * - * class Base[@specialized T] - * class Derived[T] extends Base[T] // a non-specialized T is - * // used as a type param for Base - * // -> returning true - */ - private def notSpecializedIn(tsym: Symbol, supertpe: Type) = supertpe match { - case TypeRef(_, supersym, supertargs) => - val tspec = specializedOn(tsym).toSet - for (supt <- supersym.typeParams) { - val supspec = specializedOn(supt).toSet - if (tspec != supspec && tspec.subsetOf(supspec)) - reporter.error(tsym.pos, "Type parameter has to be specialized at least for the same types as in the superclass. Missing types: " + (supspec.diff(tspec)).mkString(", ")) - } - case _ => //log("nope") - } - private def unspecializableClass(tp: Type) = ( definitions.isRepeatedParamType(tp) // ??? || tp.typeSymbol.isJavaDefined @@ -1148,7 +1150,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case cinfo @ ClassInfoType(parents, decls, clazz) if !unspecializableClass(cinfo) => val tparams = tpe.typeParams if (tparams.isEmpty) - afterSpecialize(parents map (_.typeSymbol.info)) + exitingSpecialize(parents map (_.typeSymbol.info)) val parents1 = parents mapConserve specializedType if (parents ne parents1) { @@ -1169,7 +1171,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * * A conflicting type environment could still be satisfiable. */ - def conflicting(env: TypeEnv) = !nonConflicting(env) def nonConflicting(env: TypeEnv) = env forall { case (tvar, tpe) => (subst(env, tvar.info.bounds.lo) <:< tpe) && (tpe <:< subst(env, tvar.info.bounds.hi)) } @@ -1292,7 +1293,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (sym.isPrivate) debuglog( "seeing private member %s, currentClass: %s, owner: %s, isAccessible: %b, isLocalName: %b".format( sym, currentClass, sym.owner.enclClass, isAccessible(sym), nme.isLocalName(sym.name)) - ) + ) if (shouldMakePublic(sym) && !isAccessible(sym)) { debuglog("changing private flag of " + sym) sym.makeNotPrivate(sym.owner) @@ -1377,59 +1378,72 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { def transform1(tree: Tree) = { val symbol = tree.symbol - /** The specialized symbol of 'tree.symbol' for tree.tpe, if there is one */ - def specSym(qual: Tree): Option[Symbol] = { + def specSym(qual: Tree): Symbol = { val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) - debuglog("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s" - .format(tree, symbol.tpe, tree.tpe, env, specializedName(symbol, env))) - if (!env.isEmpty) { // a method? - val specCandidates = qual.tpe.member(specializedName(symbol, env)) - val specMember = specCandidates suchThat { s => - doesConform(symbol, tree.tpe, qual.tpe.memberType(s), env) - } + def isMatch(member: Symbol) = ( + doesConform(symbol, tree.tpe, qual.tpe memberType member, env) + && TypeEnv.includes(typeEnv(member), env) + ) + if (env.isEmpty) NoSymbol + else qual.tpe member specializedName(symbol, env) suchThat isMatch + } - debuglog("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe) - debuglog("[specSym] found specMember: " + specMember) - if (specMember ne NoSymbol) - if (TypeEnv.includes(typeEnv(specMember), env)) Some(specMember) - else { - debuglog("wrong environments for specialized member: \n\ttypeEnv(%s) = %s\n\tenv = %s".format(specMember, typeEnv(specMember), env)) - None - } - else None - } else None + def matchingSymbolInPrefix(pre: Type, member: Symbol, env: TypeEnv): Symbol = { + pre member specializedName(member, env) suchThat (_.tpe matches subst(env, member.tpe)) + } + + def transformSelect(sel: Select) = { + val Select(qual, name) = sel + debuglog(s"specializing Select(sym=${symbol.defString}, tree.tpe=${tree.tpe})") + + val qual1 = transform(qual) + def copySelect = treeCopy.Select(tree, qual1, name) + def newSelect(member: Symbol) = atPos(tree.pos)(Select(qual1, member)) + def typedOp(member: Symbol) = localTyper typedOperator newSelect(member) + def typedTree(member: Symbol) = localTyper typed newSelect(member) + + val ignoreEnv = specializedTypeVars(symbol.info).isEmpty || name == nme.CONSTRUCTOR + if (ignoreEnv) overloads(symbol) find (_ matchesSym symbol) match { + case Some(Overload(member, _)) => typedOp(member) + case _ => copySelect + } + else { + val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) + overloads(symbol) find (_ matchesEnv env) match { + case Some(Overload(member, _)) => typedOp(member) + case _ => + matchingSymbolInPrefix(qual1.tpe, symbol, env) match { + case NoSymbol => copySelect + case member if member.isMethod => typedOp(member) + case member => typedTree(member) + } + } + } } curTree = tree tree match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => def transformNew = { - debuglog("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", "))) - val found = findSpec(tpt.tpe) - if (found.typeSymbol ne tpt.tpe.typeSymbol) { - // the ctor can be specialized - debuglog("** instantiated specialized type: " + found) - reportError { - localTyper.typedPos(tree.pos)(New(found, transformTrees(args): _*)) - } { - _ => super.transform(tree) + debuglog("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", "))) + val found = specializedType(tpt.tpe) + if (found.typeSymbol ne tpt.tpe.typeSymbol) { // the ctor can be specialized + val inst = New(found, transformTrees(args): _*) + reportError(localTyper.typedPos(tree.pos)(inst))(_ => super.transform(tree)) } - } else super.transform(tree) + else + super.transform(tree) } transformNew - case Apply(sel @ Select(sup @ Super(qual, name), name1), args) - if (sup.symbol.info.parents != beforePrevPhase(sup.symbol.info.parents)) => + case Apply(sel @ Select(sup @ Super(qual, name), name1), args) if hasNewParents(sup) => def transformSuperApply = { - - def parents = sup.symbol.info.parents - debuglog(tree + " parents changed from: " + beforePrevPhase(parents) + " to: " + parents) - - val res = localTyper.typed( - Apply(Select(Super(qual, name) setPos sup.pos, name1) setPos sel.pos, transformTrees(args)) setPos tree.pos) - debuglog("retyping call to super, from: " + symbol + " to " + res.symbol) - res + val sup1 = Super(qual, name) setPos sup.pos + val tree1 = Apply(Select(sup1, name1) setPos sel.pos, transformTrees(args)) + val res = localTyper.typedPos(tree.pos)(tree1) + debuglog(s"retyping call to super, from: $symbol to ${res.symbol}") + res } transformSuperApply @@ -1440,7 +1454,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val qual1 = transform(qual) // log(">>> TypeApply: " + tree + ", qual1: " + qual1) specSym(qual1) match { - case Some(specMember) => + case NoSymbol => + // See pos/exponential-spec.scala - can't call transform on the whole tree again. + treeCopy.TypeApply(tree, treeCopy.Select(sel, qual1, name), transformTrees(targs)) + case specMember => debuglog("found " + specMember.fullName) ifDebug(assert(symbol.info.typeParams.length == targs.length, symbol.info.typeParams + " / " + targs)) @@ -1450,7 +1467,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } // See SI-5583. Don't know why it happens now if it didn't before. if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) { - log("!!! Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs))) + devWarning("Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs))) localTyper.typed(sel) } else { @@ -1462,63 +1479,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { debuglog("rewrote " + tree + " to " + tree1) localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method } - - case None => - treeCopy.TypeApply(tree, treeCopy.Select(sel, qual1, name), super.transformTrees(targs)) - // See pos/exponential-spec.scala - can't call transform on the whole tree again. - // super.transform(tree) } } transformTypeApply - case Select(qual, name) => - def transformSelect = { - qual match { - case _: Super if illegalSpecializedInheritance(currentClass) => - val pos = tree.pos - debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.") - debuglog(pos.lineContent) - tree - case _ => + case Select(Super(_, _), _) if illegalSpecializedInheritance(currentClass) => + val pos = tree.pos + debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.\n" + pos.lineContent) + tree - debuglog("specializing Select %s [tree.tpe: %s]".format(symbol.defString, tree.tpe)) - - //log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info)) - if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) { - // log("!!! unifying " + (symbol, symbol.tpe) + " and " + (tree, tree.tpe)) - val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) - // log("!!! found env: " + env + "; overloads: " + overloads(symbol)) - if (!env.isEmpty) { - // debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env) - val specMember = overload(symbol, env) - if (specMember.isDefined) { - localTyper.typedOperator(atPos(tree.pos)(Select(transform(qual), specMember.get.sym.name))) - } - else { - val qual1 = transform(qual) - val specMember = qual1.tpe.member(specializedName(symbol, env)).suchThat(_.tpe matches subst(env, symbol.tpe)) - if (specMember ne NoSymbol) { - val tree1 = atPos(tree.pos)(Select(qual1, specMember)) - if (specMember.isMethod) - localTyper.typedOperator(tree1) - else - localTyper.typed(tree1) - } else - treeCopy.Select(tree, qual1, name) - } - } else - super.transform(tree) - } else overloads(symbol).find(_.sym.info =:= symbol.info) match { - case Some(specMember) => - val qual1 = transform(qual) - debuglog("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym)) - localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym))) - case None => - super.transform(tree) - } - } - } - transformSelect + case sel @ Select(_, _) => + transformSelect(sel) case PackageDef(pid, stats) => tree.symbol.info // make sure specializations have been performed @@ -1543,47 +1514,37 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { transformTemplate case ddef @ DefDef(_, _, _, vparamss, _, _) if info.isDefinedAt(symbol) => - def transformDefDef = { - // log("--> method: " + ddef + " in " + ddef.symbol.owner + ", " + info(symbol)) - def reportTypeError(body: =>Tree) = reportError(body)(_ => ddef) - + def transformDefDef = { if (symbol.isConstructor) { - - val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperSelect, vparamss, symbol.owner)) - + val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperInitCall, vparamss, symbol.owner)) if (symbol.isPrimaryConstructor) localTyper.typedPos(symbol.pos)(deriveDefDef(tree)(_ => Block(List(t), Literal(Constant())))) else // duplicate the original constructor - reportTypeError(duplicateBody(ddef, info(symbol).target)) + reportError(duplicateBody(ddef, info(symbol).target))(_ => ddef) } else info(symbol) match { case Implementation(target) => assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName) // we have an rhs, specialize it - val tree1 = reportTypeError { - duplicateBody(ddef, target) - } + val tree1 = reportError(duplicateBody(ddef, target))(_ => ddef) debuglog("implementation: " + tree1) deriveDefDef(tree1)(transform) case NormalizedMember(target) => - val constraints = satisfiabilityConstraints(typeEnv(symbol)) - log("constraints: " + constraints) - if (target.isDeferred || constraints == None) { - deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called.")) - } else { - // we have an rhs, specialize it - val tree1 = reportTypeError { - duplicateBody(ddef, target, constraints.get) - } - debuglog("implementation: " + tree1) - deriveDefDef(tree1)(transform) + logResult("constraints")(satisfiabilityConstraints(typeEnv(symbol))) match { + case Some(constraint) if !target.isDeferred => + // we have an rhs, specialize it + val tree1 = reportError(duplicateBody(ddef, target, constraint))(_ => ddef) + debuglog("implementation: " + tree1) + deriveDefDef(tree1)(transform) + case _ => + deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called.")) } case SpecialOverride(target) => assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName) //debuglog("moving implementation, body of target " + target + ": " + body(target)) - debuglog("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor)) + log("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor)) // we have an rhs, specialize it val tree1 = addBody(ddef, target) (new ChangeOwnerTraverser(target, tree1.symbol))(tree1.rhs) @@ -1631,6 +1592,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case Abstract(targ) => debuglog("abstract: " + targ) localTyper.typed(deriveDefDef(tree)(rhs => rhs)) + + case SpecialSuperAccessor(targ) => + debuglog("special super accessor: " + targ + " for " + tree) + localTyper.typed(deriveDefDef(tree)(rhs => rhs)) } } transformDefDef @@ -1652,7 +1617,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { deriveValDef(newValDef)(transform) } transformValDef - case _ => super.transform(tree) } @@ -1689,7 +1653,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val symbol = tree.symbol debuglog("specializing body of" + symbol.defString) val DefDef(_, _, tparams, vparams :: Nil, tpt, _) = tree -// val (_, origtparams) = splitParams(source.typeParams) val env = typeEnv(symbol) val boundTvars = env.keySet val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isPrimitiveValueType(env(tparam))) @@ -1824,6 +1787,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * }} */ private def forwardCtorCall(pos: scala.reflect.internal.util.Position, receiver: Tree, paramss: List[List[ValDef]], clazz: Symbol): Tree = { + log(s"forwardCtorCall($pos, $receiver, $paramss, $clazz)") /** A constructor parameter `f` initializes a specialized field * iff: @@ -1860,16 +1824,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { //! TODO: make sure the param types are seen from the right prefix map2(fun.info.paramTypes, vparams)((tp, arg) => gen.maybeMkAsInstanceOf(Ident(arg), tp, arg.tpe)) ) - private def findSpec(tp: Type): Type = tp match { - case TypeRef(pre, sym, _ :: _) => specializedType(tp) - case _ => tp - } class SpecializationTransformer(unit: CompilationUnit) extends Transformer { informProgress("specializing " + unit) override def transform(tree: Tree) = { val resultTree = if (settings.nospecialization.value) tree - else afterSpecialize(specializeCalls(unit).transform(tree)) + else exitingSpecialize(specializeCalls(unit).transform(tree)) // Remove the final modifier and @inline annotation from anything in the // original class (since it's being overridden in at least onesubclass). @@ -1889,11 +1849,4 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { resultTree } } - - def printSpecStats() { - println(" concreteSpecMembers: %7d".format(concreteSpecMethods.size)) - println(" overloads: %7d".format(overloads.size)) - println(" typeEnv: %7d".format(typeEnv.size)) - println(" info: %7d".format(info.size)) - } } diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 95cb052fda..6ab99eaec6 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -17,7 +17,7 @@ import Flags.SYNTHETIC abstract class TailCalls extends Transform { import global._ // the global environment import definitions._ // standard classes and methods - import typer.{ typed, typedPos } // methods to type trees + import typer.typedPos // methods to type trees val phaseName: String = "tailcalls" @@ -82,7 +82,7 @@ abstract class TailCalls extends Transform { * that label. * </p> * <p> - * Assumes: <code>Uncurry</code> has been run already, and no multiple + * Assumes: `Uncurry` has been run already, and no multiple * parameter lists exit. * </p> */ @@ -147,7 +147,6 @@ abstract class TailCalls extends Transform { } def enclosingType = method.enclClass.typeOfThis - def methodTypeParams = method.tpe.typeParams def isEligible = method.isEffectivelyFinal // @tailrec annotation indicates mandatory transformation def isMandatory = method.hasAnnotation(TailrecClass) && !forMSIL diff --git a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala index c7bc16f249..73f39225bd 100644 --- a/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala +++ b/src/compiler/scala/tools/nsc/transform/TypingTransformers.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package transform -import scala.collection.{ mutable, immutable } - /** A base class for transforms. * A transform contains a compiler phase which applies a tree transformer. */ @@ -23,13 +21,11 @@ trait TypingTransformers { else analyzer.newTyper(analyzer.rootContext(unit, EmptyTree, true)) protected var curTree: Tree = _ - protected def typedPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) } override final def atOwner[A](owner: Symbol)(trans: => A): A = atOwner(curTree, owner)(trans) def atOwner[A](tree: Tree, owner: Symbol)(trans: => A): A = { val savedLocalTyper = localTyper -// println("transformer atOwner: " + owner + " isPackage? " + owner.isPackage) localTyper = localTyper.atOwner(tree, if (owner.isModule) owner.moduleClass else owner) val result = super.atOwner(owner)(trans) localTyper = savedLocalTyper diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index f6b55b6606..4f889a1d86 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -112,8 +112,6 @@ abstract class UnCurry extends InfoTransform private lazy val serialVersionUIDAnnotation = AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List()) - private var nprinted = 0 - // I don't have a clue why I'm catching TypeErrors here, but it's better // than spewing stack traces at end users for internal errors. Examples // which hit at this point should not be hard to come by, but the immediate @@ -134,7 +132,7 @@ abstract class UnCurry extends InfoTransform def isByNameRef(tree: Tree) = ( tree.isTerm && !byNameArgs(tree) - && tree.hasSymbolWhich(s => isByNameParamType(s.tpe)) + && tree.hasSymbolWhich(isByName) ) /** Uncurry a type of a tree node. @@ -205,6 +203,9 @@ abstract class UnCurry extends InfoTransform val keyDef = ValDef(key, New(ObjectClass.tpe)) val tryCatch = Try(body, pat -> rhs) + for (Try(t, catches, _) <- body ; cdef <- catches ; if treeInfo catchesThrowable cdef) + unit.warning(body.pos, "catch block may intercept non-local return from " + meth) + Block(List(keyDef), tryCatch) } } @@ -296,7 +297,8 @@ abstract class UnCurry extends InfoTransform * If there's a default case, the original match is used for applyOrElse, and isDefinedAt returns `true` */ def synthPartialFunction(fun: Function) = { - if (!settings.XoldPatmat.value) debugwarn("Under the new pattern matching scheme, PartialFunction should have been synthesized during typers.") + if (!settings.XoldPatmat.value) + devWarning("Under the new pattern matching scheme, PartialFunction should have been synthesized during typers.") val targs = fun.tpe.typeArgs val (formals, restpe) = (targs.init, targs.last) @@ -335,7 +337,7 @@ abstract class UnCurry extends InfoTransform // def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 = val applyOrElseMethodDef = { - val methSym = anonClass.newMethod(fun.pos, nme.applyOrElse) setFlag (FINAL | OVERRIDE) + val methSym = anonClass.newMethod(nme.applyOrElse, fun.pos, newFlags = FINAL | OVERRIDE | SYNTHETIC) val List(argtpe) = formals val A1 = methSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argtpe) @@ -405,7 +407,7 @@ abstract class UnCurry extends InfoTransform // when calling into scala varargs, make sure it's a sequence. def arrayToSequence(tree: Tree, elemtp: Type) = { - afterUncurry { + exitingUncurry { localTyper.typedPos(pos) { val pt = arrayType(elemtp) val adaptedTree = // might need to cast to Array[elemtp], as arrays are not covariant @@ -435,7 +437,7 @@ abstract class UnCurry extends InfoTransform case _ => EmptyTree } } - afterUncurry { + exitingUncurry { localTyper.typedPos(pos) { gen.mkMethodCall(tree, toArraySym, Nil, List(traversableClassTag(tree.tpe))) } @@ -459,7 +461,7 @@ abstract class UnCurry extends InfoTransform else arrayToSequence(mkArray, varargsElemType) } - afterUncurry { + exitingUncurry { if (isJava && !isReferenceArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) { // The array isn't statically known to be a reference array, so call ScalaRuntime.toObjectArray. suffix = localTyper.typedPos(pos) { @@ -624,7 +626,7 @@ abstract class UnCurry extends InfoTransform treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals))) } - case Assign(Select(_, _), _) => + case Assign(_: RefTree, _) => withNeedLift(true) { super.transform(tree) } case Assign(lhs, _) if lhs.symbol.owner != currentMethod || lhs.symbol.hasFlag(LAZY | ACCESSOR) => @@ -670,7 +672,7 @@ abstract class UnCurry extends InfoTransform result setType uncurryTreeType(result.tpe) } - def postTransform(tree: Tree): Tree = afterUncurry { + def postTransform(tree: Tree): Tree = exitingUncurry { def applyUnary(): Tree = { // TODO_NMT: verify that the inner tree of a type-apply also gets parens if the // whole tree is a polymorphic nullary method application @@ -701,9 +703,9 @@ abstract class UnCurry extends InfoTransform val body = tree.block val catches = tree.catches val finalizer = tree.finalizer - if (opt.virtPatmat) { + if (!settings.XoldPatmat.value) { if (catches exists (cd => !treeInfo.isCatchCase(cd))) - debugwarn("VPM BUG! illegal try/catch " + catches) + devWarning("VPM BUG - illegal try/catch " + catches) tree } else if (catches forall treeInfo.isCatchCase) { tree @@ -799,10 +801,6 @@ abstract class UnCurry extends InfoTransform if (!dd.symbol.hasAnnotation(VarargsClass) || !repeatedParams.contains(dd.symbol)) return flatdd - def toSeqType(tp: Type): Type = { - val arg = elementType(ArrayClass, tp) - seqType(arg) - } def toArrayType(tp: Type): Type = { val arg = elementType(SeqClass, tp) // to prevent generation of an `Object` parameter from `Array[T]` parameter later diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index 78175f393a..5e8bb3e424 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -87,22 +87,25 @@ trait Analyzer extends AnyRef override def run() { val start = if (Statistics.canEnable) Statistics.startTimer(typerNanos) else null global.echoPhaseSummary(this) - currentRun.units foreach applyPhase - undoLog.clear() - // need to clear it after as well or 10K+ accumulated entries are - // uncollectable the rest of the way. + for (unit <- currentRun.units) { + applyPhase(unit) + undoLog.clear() + } if (Statistics.canEnable) Statistics.stopTimer(typerNanos, start) } def apply(unit: CompilationUnit) { try { - unit.body = newTyper(rootContext(unit)).typed(unit.body) + val typer = newTyper(rootContext(unit)) + unit.body = typer.typed(unit.body) if (global.settings.Yrangepos.value && !global.reporter.hasErrors) global.validatePositions(unit.body) for (workItem <- unit.toCheck) workItem() - } finally { + if (settings.lint.value) + typer checkUnused unit + } + finally { unit.toCheck.clear() } } } } } - diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala index d30b5c2601..9efa3f36b0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala @@ -6,12 +6,8 @@ package scala.tools.nsc package typechecker -import scala.collection.{ mutable, immutable } -import scala.collection.mutable.ListBuffer -import scala.util.control.ControlThrowable -import symtab.Flags._ -import scala.annotation.tailrec import Checkability._ +import scala.language.postfixOps /** On pattern matcher checkability: * @@ -134,7 +130,7 @@ trait Checkable { else if (P3) RuntimeCheckable else if (uncheckableType == NoType) { // Avoid warning (except ourselves) if we can't pinpoint the uncheckable type - debugwarn("Checkability checker says 'Uncheckable', but uncheckable type cannot be found:\n" + summaryString) + debuglog("Checkability checker says 'Uncheckable', but uncheckable type cannot be found:\n" + summaryString) CheckabilityError } else Uncheckable @@ -154,6 +150,7 @@ trait Checkable { def neverSubClass = isNeverSubClass(Xsym, Psym) def neverMatches = result == StaticallyFalse def isUncheckable = result == Uncheckable + def isCheckable = !isUncheckable def uncheckableMessage = uncheckableType match { case NoType => "something" case tp @ RefinedType(_, _) => "refinement " + tp @@ -232,6 +229,17 @@ trait Checkable { trait InferCheckable { self: Inferencer => + def isUncheckable(P0: Type) = !isCheckable(P0) + + def isCheckable(P0: Type): Boolean = ( + uncheckedOk(P0) || (P0.widen match { + case TypeRef(_, NothingClass | NullClass | AnyValClass, _) => false + case RefinedType(_, decls) if !decls.isEmpty => false + case p => + new CheckabilityChecker(AnyClass.tpe, p) isCheckable + }) + ) + /** TODO: much better error positions. * Kind of stuck right now because they just pass us the one tree. * TODO: Eliminate inPattern, canRemedy, which have no place here. diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala index 89e2ee44be..65bfd8e34e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package typechecker - import java.lang.ArithmeticException /** This class ... @@ -18,7 +17,6 @@ abstract class ConstantFolder { val global: Global import global._ - import definitions._ /** If tree is a constant operation, replace with result. */ def apply(tree: Tree): Tree = fold(tree, tree match { @@ -29,9 +27,6 @@ abstract class ConstantFolder { /** If tree is a constant value that can be converted to type `pt`, perform * the conversion. - * - * @param tree ... - * @param pt ... */ def apply(tree: Tree, pt: Type): Tree = fold(apply(tree), tree.tpe match { case ConstantType(x) => x convertTo pt diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 9e9b8b995b..bfc9f08553 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -6,9 +6,8 @@ package scala.tools.nsc package typechecker -import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.StringOps.{ countElementsAsString, countAsString } -import symtab.Flags.{ PRIVATE, PROTECTED, IS_ERROR } +import symtab.Flags.IS_ERROR import scala.compat.Platform.EOL import scala.reflect.runtime.ReflectionUtils import scala.reflect.macros.runtime.AbortMacroException @@ -157,7 +156,6 @@ trait ContextErrors { case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass => val retyped = typed (tree.duplicate setType null) val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic) - if (foundDecls.isEmpty || (found.typeSymbol eq NoSymbol)) found else { // The members arrive marked private, presumably because there was no @@ -171,11 +169,11 @@ trait ContextErrors { case _ => found } - assert(!found.isErroneous && !req.isErroneous, (found, req)) + assert(!foundType.isErroneous && !req.isErroneous, (foundType, req)) - issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req))) ) + issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(foundType, req, infer.isPossiblyMissingArgs(foundType, req))) ) if (settings.explaintypes.value) - explainTypes(found, req) + explainTypes(foundType, req) } def WithFilterError(tree: Tree, ex: AbsTypeError) = { @@ -269,9 +267,6 @@ trait ContextErrors { def VolatileValueError(vdef: Tree) = issueNormalTypeError(vdef, "values cannot be volatile") - def FinalVolatileVarError(vdef: Tree) = - issueNormalTypeError(vdef, "final vars cannot be volatile") - def LocalVarUninitializedError(vdef: Tree) = issueNormalTypeError(vdef, "local variables must be initialized") @@ -660,8 +655,8 @@ trait ContextErrors { def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) = issueTypeError(PosAndMsgTypeError(errPos, "cyclic aliasing or subtyping involving "+sym0)) - def CyclicReferenceError(errPos: Position, lockedSym: Symbol) = - issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym)) + def CyclicReferenceError(errPos: Position, tp: Type, lockedSym: Symbol) = + issueTypeError(PosAndMsgTypeError(errPos, s"illegal cyclic reference involving $tp and $lockedSym")) // macro-related errors (also see MacroErrors below) @@ -673,10 +668,9 @@ trait ContextErrors { // same reason as for MacroBodyTypecheckException case object MacroExpansionException extends Exception with scala.util.control.ControlThrowable - private def macroExpansionError(expandee: Tree, msg: String = null, pos: Position = NoPosition) = { + private def macroExpansionError(expandee: Tree, msg: String, pos: Position = NoPosition) = { def msgForLog = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg macroLogLite("macro expansion has failed: %s".format(msgForLog)) - val errorPos = if (pos != NoPosition) pos else (if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition) if (msg != null) context.error(pos, msg) // issueTypeError(PosAndMsgTypeError(..)) won't work => swallows positions setError(expandee) throw MacroExpansionException @@ -805,7 +799,10 @@ trait ContextErrors { ) } - def AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String) = { + def AccessError(tree: Tree, sym: Symbol, ctx: Context, explanation: String): AbsTypeError = + AccessError(tree, sym, ctx.enclClass.owner.thisType, ctx.enclClass.owner, explanation) + + def AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String): AbsTypeError = { def errMsg = { val location = if (sym.isClassConstructor) owner0 else pre.widen.directObjectString diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 507825ff15..1af61d31ec 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -6,8 +6,7 @@ package scala.tools.nsc package typechecker -import symtab.Flags._ -import scala.collection.mutable.{LinkedHashSet, Set} +import scala.collection.mutable import scala.annotation.tailrec /** @@ -16,6 +15,7 @@ import scala.annotation.tailrec */ trait Contexts { self: Analyzer => import global._ + import definitions.{ JavaLangPackage, ScalaPackage, PredefModule } object NoContext extends Context { outer = this @@ -28,13 +28,17 @@ trait Contexts { self: Analyzer => override def toString = "NoContext" } private object RootImports { - import definitions._ // Possible lists of root imports val javaList = JavaLangPackage :: Nil val javaAndScalaList = JavaLangPackage :: ScalaPackage :: Nil val completeList = JavaLangPackage :: ScalaPackage :: PredefModule :: Nil } + def ambiguousImports(imp1: ImportInfo, imp2: ImportInfo) = + LookupAmbiguous(s"it is imported twice in the same scope by\n$imp1\nand $imp2") + def ambiguousDefnAndImport(owner: Symbol, imp: ImportInfo) = + LookupAmbiguous(s"it is both defined in $owner and imported subsequently by \n$imp") + private val startContext = { NoContext.make( Template(List(), emptyValDef, List()) setSymbol global.NoSymbol setType global.NoType, @@ -42,6 +46,28 @@ trait Contexts { self: Analyzer => rootMirror.RootClass.info.decls) } + private lazy val allUsedSelectors = + mutable.Map[ImportInfo, Set[ImportSelector]]() withDefaultValue Set() + private lazy val allImportInfos = + mutable.Map[CompilationUnit, List[ImportInfo]]() withDefaultValue Nil + + def clearUnusedImports() { + allUsedSelectors.clear() + allImportInfos.clear() + } + def warnUnusedImports(unit: CompilationUnit) = { + val imps = allImportInfos(unit).reverse.distinct + + for (imp <- imps) { + val used = allUsedSelectors(imp) + def isMask(s: ImportSelector) = s.name != nme.WILDCARD && s.rename == nme.WILDCARD + + imp.tree.selectors filterNot (s => isMask(s) || used(s)) foreach { sel => + unit.warning(imp posOf sel, "Unused import") + } + } + } + var lastAccessCheckDetails: String = "" /** List of symbols to import from in a root context. Typically that @@ -64,7 +90,6 @@ trait Contexts { self: Analyzer => def rootContext(unit: CompilationUnit): Context = rootContext(unit, EmptyTree, false) def rootContext(unit: CompilationUnit, tree: Tree): Context = rootContext(unit, tree, false) def rootContext(unit: CompilationUnit, tree: Tree, erasedTypes: Boolean): Context = { - import definitions._ var sc = startContext for (sym <- rootImports(unit)) { sc = sc.makeNewImport(sym) @@ -143,7 +168,7 @@ trait Contexts { self: Analyzer => var typingIndentLevel: Int = 0 def typingIndent = " " * typingIndentLevel - var buffer: Set[AbsTypeError] = _ + var buffer: mutable.Set[AbsTypeError] = _ def enclClassOrMethod: Context = if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this @@ -182,20 +207,18 @@ trait Contexts { self: Analyzer => def setThrowErrors() = mode &= (~AllMask) def setAmbiguousErrors(report: Boolean) = if (report) mode |= AmbiguousErrors else mode &= notThrowMask - def updateBuffer(errors: Set[AbsTypeError]) = buffer ++= errors + def updateBuffer(errors: mutable.Set[AbsTypeError]) = buffer ++= errors def condBufferFlush(removeP: AbsTypeError => Boolean) { val elems = buffer.filter(removeP) buffer --= elems } def flushBuffer() { buffer.clear() } - def flushAndReturnBuffer(): Set[AbsTypeError] = { + def flushAndReturnBuffer(): mutable.Set[AbsTypeError] = { val current = buffer.clone() buffer.clear() current } - def logError(err: AbsTypeError) = buffer += err - def withImplicitsEnabled[T](op: => T): T = { val saved = implicitsEnabled implicitsEnabled = true @@ -281,26 +304,22 @@ trait Contexts { self: Analyzer => c.checking = this.checking c.retyping = this.retyping c.openImplicits = this.openImplicits - c.buffer = if (this.buffer == null) LinkedHashSet[AbsTypeError]() else this.buffer // need to initialize + c.buffer = if (this.buffer == null) mutable.LinkedHashSet[AbsTypeError]() else this.buffer // need to initialize registerContext(c.asInstanceOf[analyzer.Context]) debuglog("[context] ++ " + c.unit + " / " + tree.summaryString) c } - // TODO: remove? Doesn't seem to be used - def make(unit: CompilationUnit): Context = { - val c = make(unit, EmptyTree, owner, scope, imports) - c.setReportErrors() - c.implicitsEnabled = true - c.macrosEnabled = true - c - } - def makeNewImport(sym: Symbol): Context = makeNewImport(gen.mkWildcardImport(sym)) - def makeNewImport(imp: Import): Context = - make(unit, imp, owner, scope, new ImportInfo(imp, depth) :: imports) + def makeNewImport(imp: Import): Context = { + val impInfo = new ImportInfo(imp, depth) + if (settings.lint.value && imp.pos.isDefined) // pos.isDefined excludes java.lang/scala/Predef imports + allImportInfos(unit) ::= impInfo + + make(unit, imp, owner, scope, impInfo :: imports) + } def make(tree: Tree, owner: Symbol, scope: Scope): Context = if (tree == this.tree && owner == this.owner && scope == this.scope) this @@ -323,7 +342,7 @@ trait Contexts { self: Analyzer => val c = make(newtree) c.setBufferErrors() c.setAmbiguousErrors(reportAmbiguousErrors) - c.buffer = new LinkedHashSet[AbsTypeError]() + c.buffer = mutable.LinkedHashSet[AbsTypeError]() c } @@ -368,8 +387,10 @@ trait Contexts { self: Analyzer => unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg) @inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) { - debugwarn("issue error: " + err.errMsg) - if (settings.Yissuedebug.value) (new Exception).printStackTrace() + if (settings.Yissuedebug.value) { + log("issue error: " + err.errMsg) + (new Exception).printStackTrace() + } if (pf isDefinedAt err) pf(err) else if (bufferErrors) { buffer += err } else throw new TypeError(err.errPos, err.errMsg) @@ -459,17 +480,6 @@ trait Contexts { self: Analyzer => sub.isNonBottomSubClass(base) || sub.isModuleClass && sub.linkedClassOfClass.isNonBottomSubClass(base) - /** Return closest enclosing context that defines a superclass of `clazz`, or a - * companion module of a superclass of `clazz`, or NoContext if none exists */ - def enclosingSuperClassContext(clazz: Symbol): Context = { - var c = this.enclClass - while (c != NoContext && - !clazz.isNonBottomSubClass(c.owner) && - !(c.owner.isModuleClass && clazz.isNonBottomSubClass(c.owner.companionClass))) - c = c.outer.enclClass - c - } - /** Return the closest enclosing context that defines a subclass of `clazz` * or a companion object thereof, or `NoContext` if no such context exists. */ @@ -480,8 +490,7 @@ trait Contexts { self: Analyzer => c } - /** Is `sym` accessible as a member of tree `site` with type - * `pre` in current context? + /** Is `sym` accessible as a member of `pre` in current context? */ def isAccessible(sym: Symbol, pre: Type, superAccess: Boolean = false): Boolean = { lastAccessCheckDetails = "" @@ -507,20 +516,6 @@ trait Contexts { self: Analyzer => } else (owner hasTransOwner ab) } -/* - var c = this - while (c != NoContext && c.owner != owner) { - if (c.outer eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug - if (c.outer.enclClass eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug - c = c.outer.enclClass - } - c != NoContext - } -*/ - /** Is `clazz` a subclass of an enclosing class? */ - def isSubClassOfEnclosing(clazz: Symbol): Boolean = - enclosingSuperClassContext(clazz) != NoContext - def isSubThisType(pre: Type, clazz: Symbol): Boolean = pre match { case ThisType(pclazz) => pclazz isNonBottomSubClass clazz case _ => false @@ -632,7 +627,7 @@ trait Contexts { self: Analyzer => case ImportSelector(from, _, to, _) :: sels1 => var impls = collect(sels1) filter (info => info.name != from) if (to != nme.WILDCARD) { - for (sym <- imp.importedSymbol(to).alternatives) + for (sym <- importedAccessibleSymbol(imp, to).alternatives) if (isQualifyingImplicit(to, sym, pre, imported = true)) impls = new ImplicitInfo(to, pre, sym) :: impls } @@ -678,6 +673,259 @@ trait Contexts { self: Analyzer => implicitsCache } + /** It's possible that seemingly conflicting identifiers are + * identifiably the same after type normalization. In such cases, + * allow compilation to proceed. A typical example is: + * package object foo { type InputStream = java.io.InputStream } + * import foo._, java.io._ + */ + private def resolveAmbiguousImport(name: Name, imp1: ImportInfo, imp2: ImportInfo): Option[ImportInfo] = { + val imp1Explicit = imp1 isExplicitImport name + val imp2Explicit = imp2 isExplicitImport name + val ambiguous = if (imp1.depth == imp2.depth) imp1Explicit == imp2Explicit else !imp1Explicit && imp2Explicit + val imp1Symbol = (imp1 importedSymbol name).initialize filter (s => isAccessible(s, imp1.qual.tpe, superAccess = false)) + val imp2Symbol = (imp2 importedSymbol name).initialize filter (s => isAccessible(s, imp2.qual.tpe, superAccess = false)) + + // The types of the qualifiers from which the ambiguous imports come. + // If the ambiguous name is a value, these must be the same. + def t1 = imp1.qual.tpe + def t2 = imp2.qual.tpe + // The types of the ambiguous symbols, seen as members of their qualifiers. + // If the ambiguous name is a monomorphic type, we can relax this far. + def mt1 = t1 memberType imp1Symbol + def mt2 = t2 memberType imp2Symbol + + def characterize = List( + s"types: $t1 =:= $t2 ${t1 =:= t2} members: ${mt1 =:= mt2}", + s"member type 1: $mt1", + s"member type 2: $mt2" + ).mkString("\n ") + + if (!ambiguous || !imp2Symbol.exists) Some(imp1) + else if (!imp1Symbol.exists) Some(imp2) + else ( + // The symbol names are checked rather than the symbols themselves because + // each time an overloaded member is looked up it receives a new symbol. + // So foo.member("x") != foo.member("x") if x is overloaded. This seems + // likely to be the cause of other bugs too... + if (t1 =:= t2 && imp1Symbol.name == imp2Symbol.name) { + log(s"Suppressing ambiguous import: $t1 =:= $t2 && $imp1Symbol == $imp2Symbol") + Some(imp1) + } + // Monomorphism restriction on types is in part because type aliases could have the + // same target type but attach different variance to the parameters. Maybe it can be + // relaxed, but doesn't seem worth it at present. + else if (mt1 =:= mt2 && name.isTypeName && imp1Symbol.isMonomorphicType && imp2Symbol.isMonomorphicType) { + log(s"Suppressing ambiguous import: $mt1 =:= $mt2 && $imp1Symbol and $imp2Symbol are equivalent") + Some(imp1) + } + else { + log(s"Import is genuinely ambiguous:\n " + characterize) + None + } + ) + } + + /** The symbol with name `name` imported via the import in `imp`, + * if any such symbol is accessible from this context. + */ + def importedAccessibleSymbol(imp: ImportInfo, name: Name): Symbol = + importedAccessibleSymbol(imp, name, requireExplicit = false) + + private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean): Symbol = + imp.importedSymbol(name, requireExplicit) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) + + /** Is `sym` defined in package object of package `pkg`? + * Since sym may be defined in some parent of the package object, + * we cannot inspect its owner only; we have to go through the + * info of the package object. However to avoid cycles we'll check + * what other ways we can before pushing that way. + */ + def isInPackageObject(sym: Symbol, pkg: Symbol): Boolean = { + def uninitialized(what: String) = { + log(s"Cannot look for $sym in package object of $pkg; $what is not initialized.") + false + } + def pkgClass = if (pkg.isTerm) pkg.moduleClass else pkg + def matchesInfo = ( + // need to be careful here to not get a cyclic reference during bootstrap + if (pkg.isInitialized) { + val module = pkg.info member nme.PACKAGEkw + if (module.isInitialized) + module.info.member(sym.name).alternatives contains sym + else + uninitialized("" + module) + } + else uninitialized("" + pkg) + ) + def inPackageObject(sym: Symbol) = ( + // To be in the package object, one of these must be true: + // 1) sym.owner is a package object class, and sym.owner.owner is the package class for `pkg` + // 2) sym.owner is inherited by the correct package object class + // We try to establish 1) by inspecting the owners directly, and then we try + // to rule out 2), and only if both those fail do we resort to looking in the info. + !sym.isPackage && (sym.owner ne NoSymbol) && ( + if (sym.owner.isPackageObjectClass) + sym.owner.owner == pkgClass + else + !sym.owner.isPackageClass && matchesInfo + ) + ) + + // An overloaded symbol might not have the expected owner! + // The alternatives must be inspected directly. + pkgClass.isPackageClass && ( + if (sym.isOverloaded) + sym.alternatives forall (isInPackageObject(_, pkg)) + else + inPackageObject(sym) + ) + } + + /** Find the symbol of a simple name starting from this context. + * All names are filtered through the "qualifies" predicate, + * the search continuing as long as no qualifying name is found. + */ + def lookupSymbol(name: Name, qualifies: Symbol => Boolean): NameLookup = { + var lookupError: NameLookup = null // set to non-null if a definite error is encountered + var inaccessible: NameLookup = null // records inaccessible symbol for error reporting in case none is found + var defSym: Symbol = NoSymbol // the directly found symbol + var pre: Type = NoPrefix // the prefix type of defSym, if a class member + var cx: Context = this // the context under consideration + var symbolDepth: Int = -1 // the depth of the directly found symbol + + def finish(qual: Tree, sym: Symbol): NameLookup = ( + if (lookupError ne null) lookupError + else sym match { + case NoSymbol if inaccessible ne null => inaccessible + case NoSymbol => LookupNotFound + case _ => LookupSucceeded(qual, sym) + } + ) + def isPackageOwnedInDifferentUnit(s: Symbol) = ( + s.isDefinedInPackage && ( + !currentRun.compiles(s) + || unit.exists && s.sourceFile != unit.source.file + ) + ) + def requiresQualifier(s: Symbol) = ( + s.owner.isClass + && !s.owner.isPackageClass + && !s.isTypeParameterOrSkolem + ) + def lookupInPrefix(name: Name) = pre member name filter qualifies + def accessibleInPrefix(s: Symbol) = isAccessible(s, pre, superAccess = false) + + def searchPrefix = { + cx = cx.enclClass + val found0 = lookupInPrefix(name) + val found1 = found0 filter accessibleInPrefix + if (found0.exists && !found1.exists && inaccessible == null) + inaccessible = LookupInaccessible(found0, analyzer.lastAccessCheckDetails) + + found1 + } + // cx.scope eq null arises during FixInvalidSyms in Duplicators + while (defSym == NoSymbol && (cx ne NoContext) && (cx.scope ne null)) { + pre = cx.enclClass.prefix + val entries = (cx.scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList + defSym = entries match { + case Nil => searchPrefix + case hd :: tl => + // we have a winner: record the symbol depth + symbolDepth = (cx.depth - cx.scope.nestingLevel) + hd.depth + if (tl.isEmpty) hd.sym + else logResult(s"!!! lookup overloaded")(cx.owner.newOverloaded(pre, entries map (_.sym))) + } + if (!defSym.exists) + cx = cx.outer // push further outward + } + if (symbolDepth < 0) + symbolDepth = cx.depth + + var impSym: Symbol = NoSymbol + var imports = Context.this.imports + def imp1 = imports.head + def imp2 = imports.tail.head + def sameDepth = imp1.depth == imp2.depth + def imp1Explicit = imp1 isExplicitImport name + def imp2Explicit = imp2 isExplicitImport name + + def lookupImport(imp: ImportInfo, requireExplicit: Boolean) = + importedAccessibleSymbol(imp, name, requireExplicit) filter qualifies + + while (!impSym.exists && imports.nonEmpty && imp1.depth > symbolDepth) { + impSym = lookupImport(imp1, requireExplicit = false) + if (!impSym.exists) + imports = imports.tail + } + + if (defSym.exists && impSym.exists) { + // imported symbols take precedence over package-owned symbols in different compilation units. + if (isPackageOwnedInDifferentUnit(defSym)) + defSym = NoSymbol + // Defined symbols take precedence over erroneous imports. + else if (impSym.isError || impSym.name == nme.CONSTRUCTOR) + impSym = NoSymbol + // Otherwise they are irreconcilably ambiguous + else + return ambiguousDefnAndImport(defSym.owner, imp1) + } + + // At this point only one or the other of defSym and impSym might be set. + if (defSym.exists) { + if (requiresQualifier(defSym)) + finish(gen.mkAttributedQualifier(pre), defSym) + else + finish(EmptyTree, defSym) + } + else if (impSym.exists) { + // We continue walking down the imports as long as the tail is non-empty, which gives us: + // imports == imp1 :: imp2 :: _ + // And at least one of the following is true: + // - imp1 and imp2 are at the same depth + // - imp1 is a wildcard import, so all explicit imports from outer scopes must be checked + def keepLooking = ( + lookupError == null + && imports.tail.nonEmpty + && (sameDepth || !imp1Explicit) + ) + // If we find a competitor imp2 which imports the same name, possible outcomes are: + // + // - same depth, imp1 wild, imp2 explicit: imp2 wins, drop imp1 + // - same depth, imp1 wild, imp2 wild: ambiguity check + // - same depth, imp1 explicit, imp2 explicit: ambiguity check + // - differing depth, imp1 wild, imp2 explicit: ambiguity check + // - all others: imp1 wins, drop imp2 + // + // The ambiguity check is: if we can verify that both imports refer to the same + // symbol (e.g. import foo.X followed by import foo._) then we discard imp2 + // and proceed. If we cannot, issue an ambiguity error. + while (keepLooking) { + // If not at the same depth, limit the lookup to explicit imports. + // This is desirable from a performance standpoint (compare to + // filtering after the fact) but also necessary to keep the unused + // import check from being misled by symbol lookups which are not + // actually used. + val other = lookupImport(imp2, requireExplicit = !sameDepth) + def imp1wins = { imports = imp1 :: imports.tail.tail } + def imp2wins = { impSym = other ; imports = imports.tail } + + if (!other.exists) // imp1 wins; drop imp2 and continue. + imp1wins + else if (sameDepth && !imp1Explicit && imp2Explicit) // imp2 wins; drop imp1 and continue. + imp2wins + else resolveAmbiguousImport(name, imp1, imp2) match { + case Some(imp) => if (imp eq imp1) imp1wins else imp2wins + case _ => lookupError = ambiguousImports(imp1, imp2) + } + } + // optimization: don't write out package prefixes + finish(resetPos(imp1.qual.duplicate), impSym) + } + else finish(EmptyTree, NoSymbol) + } + /** * Find a symbol in this context or one of its outers. * @@ -702,11 +950,14 @@ trait Contexts { self: Analyzer => } //class Context class ImportInfo(val tree: Import, val depth: Int) { + def pos = tree.pos + def posOf(sel: ImportSelector) = tree.pos withPoint sel.namePos + /** The prefix expression */ def qual: Tree = tree.symbol.info match { case ImportType(expr) => expr - case ErrorType => tree setType NoType // fix for #2870 - case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info) //debug + case ErrorType => tree setType NoType // fix for #2870 + case _ => throw new FatalError("symbol " + tree.symbol + " has bad type: " + tree.symbol.info) //debug } /** Is name imported explicitly, not via wildcard? */ @@ -715,25 +966,46 @@ trait Contexts { self: Analyzer => /** The symbol with name `name` imported from import clause `tree`. */ - def importedSymbol(name: Name): Symbol = { + def importedSymbol(name: Name): Symbol = importedSymbol(name, requireExplicit = false) + + private def recordUsage(sel: ImportSelector, result: Symbol) { + def posstr = pos.source.file.name + ":" + posOf(sel).safeLine + def resstr = if (tree.symbol.hasCompleteInfo) s"(qual=$qual, $result)" else s"(expr=${tree.expr}, ${result.fullLocationString})" + debuglog(s"In $this at $posstr, selector '${selectorString(sel)}' resolved to $resstr") + allUsedSelectors(this) += sel + } + + /** If requireExplicit is true, wildcard imports are not considered. */ + def importedSymbol(name: Name, requireExplicit: Boolean): Symbol = { var result: Symbol = NoSymbol var renamed = false var selectors = tree.selectors - while (selectors != Nil && result == NoSymbol) { - if (selectors.head.rename == name.toTermName) + def current = selectors.head + while (selectors.nonEmpty && result == NoSymbol) { + if (current.rename == name.toTermName) result = qual.tpe.nonLocalMember( // new to address #2733: consider only non-local members for imports - if (name.isTypeName) selectors.head.name.toTypeName else selectors.head.name) - else if (selectors.head.name == name.toTermName) + if (name.isTypeName) current.name.toTypeName else current.name) + else if (current.name == name.toTermName) renamed = true - else if (selectors.head.name == nme.WILDCARD && !renamed) + else if (current.name == nme.WILDCARD && !renamed && !requireExplicit) result = qual.tpe.nonLocalMember(name) - selectors = selectors.tail + + if (result == NoSymbol) + selectors = selectors.tail } + if (settings.lint.value && selectors.nonEmpty && result != NoSymbol && pos != NoPosition) + recordUsage(current, result) + result } + private def selectorString(s: ImportSelector): String = { + if (s.name == nme.WILDCARD && s.rename == null) "_" + else if (s.name == s.rename) "" + s.name + else s.name + " => " + s.rename + } def allImportedSymbols: Iterable[Symbol] = - qual.tpe.members flatMap (transformImport(tree.selectors, _)) + importableMembers(qual.tpe) flatMap (transformImport(tree.selectors, _)) private def transformImport(selectors: List[ImportSelector], sym: Symbol): List[Symbol] = selectors match { case List() => List() @@ -744,7 +1016,12 @@ trait Contexts { self: Analyzer => case _ :: rest => transformImport(rest, sym) } - override def toString() = tree.toString() + override def hashCode = tree.## + override def equals(other: Any) = other match { + case that: ImportInfo => (tree == that.tree) + case _ => false + } + override def toString = tree.toString } case class ImportType(expr: Tree) extends Type { diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala index 3e249e57bb..73572bcae9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package typechecker -import scala.language.implicitConversions - /** A generic means of breaking down types into their subcomponents. * Types are decomposed top down, and recognizable substructure is * dispatched via self-apparently named methods. Those methods can @@ -37,8 +35,6 @@ trait DestructureTypes { def wrapSequence(nodes: List[Node]): Node def wrapAtom[U](value: U): Node - private implicit def liftToTerm(name: String): TermName = newTermName(name) - private val openSymbols = scala.collection.mutable.Set[Symbol]() private def nodeList[T](elems: List[T], mkNode: T => Node): Node = @@ -68,15 +64,6 @@ trait DestructureTypes { }, tree.productPrefix ) - def wrapSymbol(label: String, sym: Symbol): Node = { - if (sym eq NoSymbol) wrapEmpty - else atom(label, sym) - } - def wrapInfo(sym: Symbol) = sym.info match { - case TypeBounds(lo, hi) => typeBounds(lo, hi) - case PolyType(tparams, restpe) => polyFunction(tparams, restpe) - case _ => wrapEmpty - } def wrapSymbolInfo(sym: Symbol): Node = { if ((sym eq NoSymbol) || openSymbols(sym)) wrapEmpty else { @@ -99,7 +86,6 @@ trait DestructureTypes { def constant(label: String, const: Constant): Node = atom(label, const) def scope(decls: Scope): Node = node("decls", scopeMemberList(decls.toList)) - def const[T](named: (String, T)): Node = constant(named._1, Constant(named._2)) def resultType(restpe: Type): Node = this("resultType", restpe) def typeParams(tps: List[Symbol]): Node = node("typeParams", symbolList(tps)) @@ -188,7 +174,6 @@ trait DestructureTypes { case AntiPolyType(pre, targs) => product(tp, prefix(pre), typeArgs(targs)) case ClassInfoType(parents, decls, clazz) => product(tp, parentList(parents), scope(decls), wrapAtom(clazz)) case ConstantType(const) => product(tp, constant("value", const)) - case DeBruijnIndex(level, index, args) => product(tp, const("level" -> level), const("index" -> index), typeArgs(args)) case OverloadedType(pre, alts) => product(tp, prefix(pre), node("alts", typeList(alts map pre.memberType))) case RefinedType(parents, decls) => product(tp, parentList(parents), scope(decls)) case SingleType(pre, sym) => product(tp, prefix(pre), wrapAtom(sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index df753ba53c..9c23b8663c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -19,11 +19,6 @@ abstract class Duplicators extends Analyzer { import global._ import definitions.{ AnyRefClass, AnyValClass } - def retyped(context: Context, tree: Tree): Tree = { - resetClassOwners - (newBodyDuplicator(context)).typed(tree) - } - /** Retype the given tree in the given context. Use this method when retyping * a method in a different class. The typer will replace references to the this of * the old class with the new class, and map symbols through the given 'env'. The @@ -42,9 +37,6 @@ abstract class Duplicators extends Analyzer { protected def newBodyDuplicator(context: Context) = new BodyDuplicator(context) - def retypedMethod(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol): Tree = - (newBodyDuplicator(context)).retypedMethod(tree.asInstanceOf[DefDef], oldThis, newThis) - /** Return the special typer for duplicate method bodies. */ override def newTyper(context: Context): Typer = newBodyDuplicator(context) @@ -186,31 +178,6 @@ abstract class Duplicators extends Analyzer { stats.foreach(invalidate(_, owner)) } - def retypedMethod(ddef: DefDef, oldThis: Symbol, newThis: Symbol): Tree = { - oldClassOwner = oldThis - newClassOwner = newThis - invalidateAll(ddef.tparams) - mforeach(ddef.vparamss) { vdef => - invalidate(vdef) - vdef.tpe = null - } - ddef.symbol = NoSymbol - enterSym(context, ddef) - debuglog("remapping this of " + oldClassOwner + " to " + newClassOwner) - typed(ddef) - } - - private def inspectTpe(tpe: Type) = { - tpe match { - case MethodType(_, res) => - res + ", " + res.bounds.hi + ", " + (res.bounds.hi match { - case TypeRef(_, _, args) if (args.length > 0) => args(0) + ", " + args(0).bounds.hi - case _ => "non-tref: " + res.bounds.hi.getClass - }) - case _ => - } - } - /** Optionally cast this tree into some other type, if required. * Unless overridden, just returns the tree. */ @@ -233,7 +200,7 @@ abstract class Duplicators extends Analyzer { override def typed(tree: Tree, mode: Int, pt: Type): Tree = { debuglog("typing " + tree + ": " + tree.tpe + ", " + tree.getClass) val origtreesym = tree.symbol - if (tree.hasSymbol && tree.symbol != NoSymbol + if (tree.hasSymbolField && tree.symbol != NoSymbol && !tree.symbol.isLabel // labels cannot be retyped by the type checker as LabelDef has no ValDef/return type trees && invalidSyms.isDefinedAt(tree.symbol)) { debuglog("removed symbol " + tree.symbol) @@ -317,15 +284,39 @@ abstract class Duplicators extends Analyzer { super.typed(tree, mode, pt) case Select(th @ This(_), sel) if (oldClassOwner ne null) && (th.symbol == oldClassOwner) => - // log("selection on this, no type ascription required") - // we use the symbol name instead of the tree name because the symbol may have been - // name mangled, rendering the tree name obsolete - // log(tree) - val t = super.typedPos(tree.pos, mode, pt) { - Select(This(newClassOwner), tree.symbol.name) - } - // log("typed to: " + t + "; tpe = " + t.tpe + "; " + inspectTpe(t.tpe)) - t + // We use the symbol name instead of the tree name because the symbol + // may have been name mangled, rendering the tree name obsolete. + // ...but you can't just do a Select on a name because if the symbol is + // overloaded, you will crash in the backend. + val memberByName = newClassOwner.thisType.member(tree.symbol.name) + def nameSelection = Select(This(newClassOwner), tree.symbol.name) + val newTree = ( + if (memberByName.isOverloaded) { + // Find the types of the overload alternatives as seen in the new class, + // and filter the list down to those which match the old type (after + // fixing the old type so it is seen as if from the new class.) + val typeInNewClass = fixType(oldClassOwner.info memberType tree.symbol) + val alts = memberByName.alternatives + val memberTypes = alts map (newClassOwner.info memberType _) + val memberString = memberByName.defString + alts zip memberTypes filter (_._2 =:= typeInNewClass) match { + case ((alt, tpe)) :: Nil => + log(s"Arrested overloaded type in Duplicators, narrowing to ${alt.defStringSeenAs(tpe)}\n Overload was: $memberString") + Select(This(newClassOwner), alt) + case xs => + alts filter (alt => (alt.paramss corresponds tree.symbol.paramss)(_.size == _.size)) match { + case alt :: Nil => + log(s"Resorted to parameter list arity to disambiguate to $alt\n Overload was: $memberString") + Select(This(newClassOwner), alt) + case _ => + log(s"Could not disambiguate $memberTypes. Attempting name-based selection, but we may crash later.") + nameSelection + } + } + } + else nameSelection + ) + super.typed(atPos(tree.pos)(newTree), mode, pt) case This(_) if (oldClassOwner ne null) && (tree.symbol == oldClassOwner) => // val tree1 = Typed(This(newClassOwner), TypeTree(fixType(tree.tpe.widen))) @@ -379,7 +370,7 @@ abstract class Duplicators extends Analyzer { case _ => debuglog("Duplicators default case: " + tree.summaryString) debuglog(" ---> " + tree) - if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) { + if (tree.hasSymbolField && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) { tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==) } val ntree = castType(tree, pt) diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index bbba7e0435..2806d7b2d9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -33,7 +33,7 @@ trait EtaExpansion { self: Analyzer => } /** <p> - * Expand partial function applications of type <code>type</code>. + * Expand partial function applications of type `type`. * </p><pre> * p.f(es_1)...(es_n) * ==> { @@ -56,11 +56,8 @@ trait EtaExpansion { self: Analyzer => } val defs = new ListBuffer[Tree] - /** Append to <code>defs</code> value definitions for all non-stable - * subexpressions of the function application <code>tree</code>. - * - * @param tree ... - * @return ... + /** Append to `defs` value definitions for all non-stable + * subexpressions of the function application `tree`. */ def liftoutPrefix(tree: Tree): Tree = { def liftout(tree: Tree, byName: Boolean): Tree = @@ -118,7 +115,7 @@ trait EtaExpansion { self: Analyzer => val origTpe = sym.tpe val isRepeated = definitions.isRepeatedParamType(origTpe) // SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala - val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropRepeatedParamType(origTpe) + val droppedStarTpe = if (settings.etaExpandKeepsStar.value) origTpe else dropIllegalStarTypes(origTpe) val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree) (valDef, isRepeated) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 547d756888..eb45f9b847 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -30,7 +30,7 @@ trait Implicits { import global._ import definitions._ import ImplicitsStats._ - import typeDebug.{ ptTree, ptBlock, ptLine } + import typeDebug.{ ptBlock, ptLine } import global.typer.{ printTyping, deindentTyping, indentTyping, printInference } def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult = @@ -82,7 +82,7 @@ trait Implicits { val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit if (saveAmbiguousDivergent && implicitSearchContext.hasErrors) { context.updateBuffer(implicitSearchContext.errBuffer.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent)) - debugwarn("update buffer: " + implicitSearchContext.errBuffer) + debuglog("update buffer: " + implicitSearchContext.errBuffer) } printInference("[infer implicit] inferred " + result) context.undetparams = context.undetparams filterNot result.subst.from.contains @@ -132,7 +132,7 @@ trait Implicits { } /* Map a polytype to one in which all type parameters and argument-dependent types are replaced by wildcards. - * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate DebruijnIndex types + * Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate debruijn index types * when checking whether `b` is a valid implicit, as we haven't even searched a value for the implicit arg `x`, * so we have to approximate (otherwise it is excluded a priori). */ @@ -233,10 +233,6 @@ trait Implicits { object HasMember { private val hasMemberCache = perRunCaches.newMap[Name, Type]() def apply(name: Name): Type = hasMemberCache.getOrElseUpdate(name, memberWildcardType(name, WildcardType)) - def unapply(pt: Type): Option[Name] = pt match { - case RefinedType(List(WildcardType), Scope(sym)) if sym.tpe == WildcardType => Some(sym.name) - case _ => None - } } /** An extractor for types of the form ? { name: (? >: argtpe <: Any*)restp } @@ -664,10 +660,6 @@ trait Implicits { // duplicating the code here, but this is probably a // hotspot (and you can't just call typed, need to force // re-typecheck) - // TODO: the return tree is ignored. This seems to make - // no difference, but it's bad practice regardless. - - val checked = itree2 match { case TypeApply(fun, args) => typedTypeApply(itree2, EXPRmode, fun, args) case Apply(TypeApply(fun, args), _) => typedTypeApply(itree2, EXPRmode, fun, args) // t2421c @@ -677,7 +669,7 @@ trait Implicits { if (context.hasErrors) fail("typing TypeApply reported errors for the implicit tree: " + context.errBuffer.head.errMsg) else { - val result = new SearchResult(itree2, subst) + val result = new SearchResult(checked, subst) if (Statistics.canEnable) Statistics.incCounter(foundImplicits) printInference("[success] found %s for pt %s".format(result, ptInstantiated)) result @@ -997,7 +989,7 @@ trait Implicits { case Some(imap) => imap case None => val result = new InfoMap - getClassParts(sym.tpe)(result, new mutable.HashSet(), pending + sym) + getClassParts(sym.tpeHK)(result, new mutable.HashSet(), pending + sym) infoMapCache(sym) = result result } @@ -1205,7 +1197,7 @@ trait Implicits { } ) // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros - var materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List())) + val materializer = atPos(pos.focus)(gen.mkMethodCall(TagMaterializers(tagClass), List(tp), if (prefix != EmptyTree) List(prefix) else List())) if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer)) if (context.macrosEnabled) success(materializer) // don't call `failure` here. if macros are disabled, we just fail silently @@ -1472,7 +1464,6 @@ trait Implicits { interpolate(msg, Map((typeParamNames zip typeArgs): _*)) // TODO: give access to the name and type of the implicit argument, etc? def validate: Option[String] = { - import scala.util.matching.Regex; import scala.collection.breakOut // is there a shorter way to avoid the intermediate toList? val refs = """\$\{([^}]+)\}""".r.findAllIn(msg).matchData.map(_ group 1).toSet val decls = typeParamNames.toSet @@ -1498,9 +1489,7 @@ object ImplicitsStats { val subtypeImpl = Statistics.newSubCounter(" of which in implicit", subtypeCount) val findMemberImpl = Statistics.newSubCounter(" of which in implicit", findMemberCount) val subtypeAppInfos = Statistics.newSubCounter(" of which in app impl", subtypeCount) - val subtypeImprovCount = Statistics.newSubCounter(" of which in improves", subtypeCount) val implicitSearchCount = Statistics.newCounter ("#implicit searches", "typer") - val triedImplicits = Statistics.newSubCounter(" #tried", implicitSearchCount) val plausiblyCompatibleImplicits = Statistics.newSubCounter(" #plausibly compatible", implicitSearchCount) val matchingImplicits = Statistics.newSubCounter(" #matching", implicitSearchCount) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 5deed4ffee..be3c027259 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -6,11 +6,10 @@ package scala.tools.nsc package typechecker -import scala.collection.{ mutable, immutable } +import scala.collection.immutable import scala.collection.mutable.ListBuffer import scala.util.control.ControlThrowable import symtab.Flags._ -import scala.annotation.tailrec /** This trait ... * @@ -30,8 +29,8 @@ trait Infer extends Checkable { private def assertNonCyclic(tvar: TypeVar) = assert(tvar.constr.inst != tvar, tvar.origin) - /** The formal parameter types corresponding to <code>formals</code>. - * If <code>formals</code> has a repeated last parameter, a list of + /** The formal parameter types corresponding to `formals`. + * If `formals` has a repeated last parameter, a list of * (nargs - params.length + 1) copies of its type is returned. * By-name types are replaced with their underlying type. * @@ -49,6 +48,24 @@ trait Infer extends Checkable { } else formals1 } + /** Sorts the alternatives according to the given comparison function. + * Returns a list containing the best alternative as well as any which + * the best fails to improve upon. + */ + private def bestAlternatives(alternatives: List[Symbol])(isBetter: (Symbol, Symbol) => Boolean): List[Symbol] = { + def improves(sym1: Symbol, sym2: Symbol) = ( + sym2 == NoSymbol + || sym2.isError + || sym2.hasAnnotation(BridgeClass) + || isBetter(sym1, sym2) + ) + + alternatives sortWith improves match { + case best :: rest if rest.nonEmpty => best :: rest.filterNot(alt => improves(best, alt)) + case bests => bests + } + } + /** Returns `(formals, formalsExpanded)` where `formalsExpanded` are the expected types * for the `nbSubPats` sub-patterns of an extractor pattern, of which the corresponding * unapply[Seq] call is assumed to have result type `resTp`. @@ -112,21 +129,7 @@ trait Infer extends Checkable { else (formals, formalsExpanded) } - def actualTypes(actuals: List[Type], nformals: Int): List[Type] = - if (nformals == 1 && !hasLength(actuals, 1)) - List(if (actuals.isEmpty) UnitClass.tpe else tupleType(actuals)) - else actuals - - def actualArgs(pos: Position, actuals: List[Tree], nformals: Int): List[Tree] = { - val inRange = nformals == 1 && !hasLength(actuals, 1) && actuals.lengthCompare(MaxTupleArity) <= 0 - if (inRange && !phase.erasedTypes) List(atPos(pos)(gen.mkTuple(actuals))) - else actuals - } - /** A fresh type variable with given type parameter as origin. - * - * @param tparam ... - * @return ... */ def freshVar(tparam: Symbol): TypeVar = TypeVar(tparam) @@ -149,14 +152,13 @@ trait Infer extends Checkable { case tv @ TypeVar(origin, constr) if !tv.untouchable => if (constr.inst == NoType) { throw new DeferredNoInstance(() => - "no unique instantiation of type variable " + origin + " could be found") + s"no unique instantiation of type variable $origin could be found") } else if (excludedVars(tv)) { throw new NoInstance("cyclic instantiation") } else { excludedVars += tv - val res = apply(constr.inst) - excludedVars -= tv - res + try apply(constr.inst) + finally excludedVars -= tv } case _ => mapOver(tp) @@ -164,9 +166,6 @@ trait Infer extends Checkable { } /** Is type fully defined, i.e. no embedded anytypes or wildcards in it? - * - * @param tp ... - * @return ... */ private[typechecker] def isFullyDefined(tp: Type): Boolean = tp match { case WildcardType | BoundedWildcardType(_) | NoType => @@ -270,7 +269,7 @@ trait Infer extends Checkable { def errorValue = if (context.reportErrors) context.owner.newErrorValue(name) else stdErrorValue def errorSym = if (tree.isType) errorClass else errorValue - if (tree.hasSymbol) + if (tree.hasSymbolField) tree setSymbol errorSym tree setType ErrorType @@ -296,8 +295,8 @@ trait Infer extends Checkable { /* -- Tests & Checks---------------------------------------------------- */ - /** Check that <code>sym</code> is defined and accessible as a member of - * tree <code>site</code> with type <code>pre</code> in current context. + /** Check that `sym` is defined and accessible as a member of + * tree `site` with type `pre` in current context. * * Note: pre is not refchecked -- moreover, refchecking the resulting tree may not refcheck pre, * since pre may not occur in its type (callers should wrap the result in a TypeTreeWithDeferredRefCheck) @@ -306,7 +305,6 @@ trait Infer extends Checkable { if (sym.isError) { tree setSymbol sym setType ErrorType } else { - val topClass = context.owner.enclosingTopLevelClass if (context.unit.exists) context.unit.depends += sym.enclosingTopLevelClass @@ -404,8 +402,19 @@ trait Infer extends Checkable { /** Like weakly compatible but don't apply any implicit conversions yet. * Used when comparing the result type of a method with its prototype. + * * [Martin] I think Infer is also created by Erasure, with the default * implementation of isCoercible + * [Paulp] (Assuming the above must refer to my comment on isCoercible) + * Nope, I examined every occurrence of Inferencer in trunk. It + * appears twice as a self-type, once at its definition, and once + * where it is instantiated in Typers. There are no others. + * + % ack -A0 -B0 --no-filename '\bInferencer\b' src + self: Inferencer => + self: Inferencer => + class Inferencer(context: Context) extends InferencerContextErrors with InferCheckable { + val infer = new Inferencer(context0) { */ def isConservativelyCompatible(tp: Type, pt: Type): Boolean = context.withImplicitsDisabled(isWeaklyCompatible(tp, pt)) @@ -439,14 +448,9 @@ trait Infer extends Checkable { } /** Return inferred type arguments of polymorphic expression, given - * its type parameters and result type and a prototype <code>pt</code>. + * its type parameters and result type and a prototype `pt`. * If no minimal type variables exist that make the - * instantiated type a subtype of <code>pt</code>, return null. - * - * @param tparams ... - * @param restpe ... - * @param pt ... - * @return ... + * instantiated type a subtype of `pt`, return null. */ private def exprTypeArgs(tparams: List[Symbol], restpe: Type, pt: Type, useWeaklyCompatible: Boolean = false): (List[Type], List[TypeVar]) = { val tvars = tparams map freshVar @@ -473,18 +477,12 @@ trait Infer extends Checkable { /** Return inferred proto-type arguments of function, given * its type and value parameters and result type, and a - * prototype <code>pt</code> for the function result. + * prototype `pt` for the function result. * Type arguments need to be either determined precisely by * the prototype, or they are maximized, if they occur only covariantly * in the value parameter list. * If instantiation of a type parameter fails, * take WildcardType for the proto-type argument. - * - * @param tparams ... - * @param formals ... - * @param restype ... - * @param pt ... - * @return ... */ def protoTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type, pt: Type): List[Type] = { @@ -566,7 +564,7 @@ trait Infer extends Checkable { * * Rewrite for repeated param types: Map T* entries to Seq[T]. * @return map from tparams to inferred arg, if inference was successful, tparams that map to None are considered left undetermined - * type parameters that are inferred as `scala.Nothing` and that are not covariant in <code>restpe</code> are taken to be undetermined + * type parameters that are inferred as `scala.Nothing` and that are not covariant in `restpe` are taken to be undetermined */ def adjustTypeArgs(tparams: List[Symbol], tvars: List[TypeVar], targs: List[Type], restpe: Type = WildcardType): AdjustedTypeArgs.Result = { val buf = AdjustedTypeArgs.Result.newBuilder[Symbol, Option[Type]] @@ -577,14 +575,14 @@ trait Infer extends Checkable { && (restpe.isWildcard || (varianceInType(restpe)(tparam) & COVARIANT) == 0) // don't retract covariant occurrences ) - // checks opt.virtPatmat directly so one need not run under -Xexperimental to use virtpatmat + // checks !settings.XoldPatmat.value directly so one need not run under -Xexperimental to use virtpatmat buf += ((tparam, if (retract) None else Some( if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass) else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass) // this infers Foo.type instead of "object Foo" (see also widenIfNecessary) - else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ + else if (targ.typeSymbol.isModuleClass || ((settings.Xexperimental.value || !settings.XoldPatmat.value) && tvar.constr.avoidWiden)) targ else targ.widen ) )) @@ -594,7 +592,7 @@ trait Infer extends Checkable { /** Return inferred type arguments, given type parameters, formal parameters, * argument types, result type and expected result type. - * If this is not possible, throw a <code>NoInstance</code> exception. + * If this is not possible, throw a `NoInstance` exception. * Undetermined type arguments are represented by `definitions.NothingClass.tpe`. * No check that inferred parameters conform to their bounds is made here. * @@ -651,9 +649,57 @@ trait Infer extends Checkable { tvars, tparams, tparams map varianceInTypes(formals), false, lubDepth(formals) max lubDepth(argtpes) ) + // Can warn about inferring Any/AnyVal as long as they don't appear + // explicitly anywhere amongst the formal, argument, result, or expected type. + def canWarnAboutAny = !(pt :: restpe :: formals ::: argtpes exists (t => (t contains AnyClass) || (t contains AnyValClass))) + def argumentPosition(idx: Int): Position = context.tree match { + case x: ValOrDefDef => x.rhs match { + case Apply(fn, args) if idx < args.size => args(idx).pos + case _ => context.tree.pos + } + case _ => context.tree.pos + } + if (settings.warnInferAny.value && context.reportErrors && canWarnAboutAny) { + foreachWithIndex(targs) ((targ, idx) => + targ.typeSymbol match { + case sym @ (AnyClass | AnyValClass) => + context.unit.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") + case _ => + } + ) + } adjustTypeArgs(tparams, tvars, targs, restpe) } + /** One must step carefully when assessing applicability due to + * complications from varargs, tuple-conversion, named arguments. + * This method is used to filter out inapplicable methods, + * its behavior slightly configurable based on what stage of + * overloading resolution we're at. + * + * This method has boolean parameters, which is usually suboptimal + * but I didn't work out a better way. They don't have defaults, + * and the method's scope is limited. + */ + private[typechecker] def isApplicableBasedOnArity(tpe: Type, argsCount: Int, varargsStar: Boolean, tuplingAllowed: Boolean): Boolean = followApply(tpe) match { + case OverloadedType(pre, alts) => + alts exists (alt => isApplicableBasedOnArity(pre memberType alt, argsCount, varargsStar, tuplingAllowed)) + case _ => + val paramsCount = tpe.params.length + val simpleMatch = paramsCount == argsCount + val varargsTarget = isVarArgsList(tpe.params) + def varargsMatch = varargsTarget && (paramsCount - 1) <= argsCount + def tuplingMatch = tuplingAllowed && eligibleForTupleConversion(paramsCount, argsCount, varargsTarget) + + // A varargs star call, e.g. (x, y:_*) can only match a varargs method + // with the same number of parameters. See SI-5859 for an example of what + // would fail were this not enforced before we arrived at isApplicable. + if (varargsStar) + varargsTarget && simpleMatch + else + simpleMatch || varargsMatch || tuplingMatch + } + private[typechecker] def followApply(tp: Type): Type = tp match { case NullaryMethodType(restp) => val restp1 = followApply(restp) @@ -670,14 +716,6 @@ trait Infer extends Checkable { else OverloadedType(tp, appmeth.alternatives) } - def hasExactlyNumParams(tp: Type, n: Int): Boolean = tp match { - case OverloadedType(pre, alts) => - alts exists (alt => hasExactlyNumParams(pre.memberType(alt), n)) - case _ => - val len = tp.params.length - len == n || isVarArgsList(tp.params) && len <= n + 1 - } - /** * Verifies whether the named application is valid. The logic is very * similar to the one in NamesDefaults.removeNames. @@ -723,17 +761,54 @@ trait Infer extends Checkable { (argtpes1, argPos, namesOK) } - /** don't do a () to (()) conversion for methods whose second parameter - * is a varargs. This is a fairly kludgey way to address #3224. - * We'll probably find a better way to do this by identifying - * tupled and n-ary methods, but thiws is something for a future major revision. + /** True if the given parameter list can accept a tupled argument list, + * and the argument list can be tupled (based on its length.) + */ + def eligibleForTupleConversion(paramsCount: Int, argsCount: Int, varargsTarget: Boolean): Boolean = { + def canSendTuple = argsCount match { + case 0 => !varargsTarget // avoid () to (()) conversion - SI-3224 + case 1 => false // can't tuple a single argument + case n => n <= MaxTupleArity // <= 22 arguments + } + def canReceiveTuple = paramsCount match { + case 1 => true + case 2 => varargsTarget + case _ => false + } + canSendTuple && canReceiveTuple + } + def eligibleForTupleConversion(formals: List[Type], argsCount: Int): Boolean = formals match { + case p :: Nil => eligibleForTupleConversion(1, argsCount, varargsTarget = isScalaRepeatedParamType(p)) + case _ :: p :: Nil if isScalaRepeatedParamType(p) => eligibleForTupleConversion(2, argsCount, varargsTarget = true) + case _ => false + } + + /** The type of an argument list after being coerced to a tuple. + * @pre: the argument list is eligible for tuple conversion. */ - def isUnitForVarArgs(args: List[AnyRef], params: List[Symbol]): Boolean = - args.isEmpty && hasLength(params, 2) && isVarArgsList(params) + private def typeAfterTupleConversion(argtpes: List[Type]): Type = ( + if (argtpes.isEmpty) UnitClass.tpe // aka "Tuple0" + else tupleType(argtpes map { + case NamedType(name, tp) => UnitClass.tpe // not a named arg - only assignments here + case RepeatedType(tp) => tp // but probably shouldn't be tupling a call containing :_* + case tp => tp + }) + ) - /** Is there an instantiation of free type variables <code>undetparams</code> - * such that function type <code>ftpe</code> is applicable to - * <code>argtpes</code> and its result conform to <code>pt</code>? + /** If the argument list needs to be tupled for the parameter list, + * a list containing the type of the tuple. Otherwise, the original + * argument list. + */ + def tupleIfNecessary(formals: List[Type], argtpes: List[Type]): List[Type] = { + if (eligibleForTupleConversion(formals, argtpes.size)) + typeAfterTupleConversion(argtpes) :: Nil + else + argtpes + } + + /** Is there an instantiation of free type variables `undetparams` + * such that function type `ftpe` is applicable to + * `argtpes` and its result conform to `pt`? * * @param undetparams ... * @param ftpe the type of the function (often a MethodType) @@ -748,23 +823,16 @@ trait Infer extends Checkable { argtpes0: List[Type], pt: Type): Boolean = ftpe match { case OverloadedType(pre, alts) => - alts exists (alt => isApplicable(undetparams, pre.memberType(alt), argtpes0, pt)) + alts exists (alt => isApplicable(undetparams, pre memberType alt, argtpes0, pt)) case ExistentialType(tparams, qtpe) => isApplicable(undetparams, qtpe, argtpes0, pt) case mt @ MethodType(params, _) => - val formals = formalTypes(mt.paramTypes, argtpes0.length, removeByName = false) - - def tryTupleApply: Boolean = { - // if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0 - val tupleArgTpes = actualTypes(argtpes0 map { - // no assignment is treated as named argument here - case NamedType(name, tp) => UnitClass.tpe - case tp => tp - }, formals.length) - - !sameLength(argtpes0, tupleArgTpes) && - !isUnitForVarArgs(argtpes0, params) && - isApplicable(undetparams, ftpe, tupleArgTpes, pt) + val argslen = argtpes0.length + val formals = formalTypes(mt.paramTypes, argslen, removeByName = false) + + def tryTupleApply = { + val tupled = tupleIfNecessary(mt.paramTypes, argtpes0) + (tupled ne argtpes0) && isApplicable(undetparams, ftpe, tupled, pt) } def typesCompatible(argtpes: List[Type]) = { val restpe = ftpe.resultType(argtpes) @@ -786,17 +854,16 @@ trait Infer extends Checkable { val lencmp = compareLengths(argtpes0, formals) if (lencmp > 0) tryTupleApply else if (lencmp == 0) { - if (!argtpes0.exists(_.isInstanceOf[NamedType])) { - // fast track if no named arguments are used + // fast track if no named arguments are used + if (!containsNamedType(argtpes0)) typesCompatible(argtpes0) - } else { // named arguments are used val (argtpes1, argPos, namesOK) = checkNames(argtpes0, params) // when using named application, the vararg param has to be specified exactly once - ( namesOK && (isIdentity(argPos) || sameLength(formals, params)) && - // nb. arguments and names are OK, check if types are compatible - typesCompatible(reorderArgs(argtpes1, argPos)) + ( namesOK + && (isIdentity(argPos) || sameLength(formals, params)) + && typesCompatible(reorderArgs(argtpes1, argPos)) // nb. arguments and names are OK, check if types are compatible ) } } @@ -840,17 +907,13 @@ trait Infer extends Checkable { } else res1 } - /** Is type <code>ftpe1</code> strictly more specific than type <code>ftpe2</code> + /** Is type `ftpe1` strictly more specific than type `ftpe2` * when both are alternatives in an overloaded function? * @see SLS (sec:overloading-resolution) - * - * @param ftpe1 ... - * @param ftpe2 ... - * @return ... */ def isAsSpecific(ftpe1: Type, ftpe2: Type): Boolean = ftpe1 match { case OverloadedType(pre, alts) => - alts exists (alt => isAsSpecific(pre.memberType(alt), ftpe2)) + alts exists (alt => isAsSpecific(pre memberType alt, ftpe2)) case et: ExistentialType => isAsSpecific(ftpe1.skolemizeExistential, ftpe2) //et.withTypeVars(isAsSpecific(_, ftpe2)) @@ -877,7 +940,7 @@ trait Infer extends Checkable { case _ => ftpe2 match { case OverloadedType(pre, alts) => - alts forall (alt => isAsSpecific(ftpe1, pre.memberType(alt))) + alts forall (alt => isAsSpecific(ftpe1, pre memberType alt)) case et: ExistentialType => et.withTypeVars(isAsSpecific(ftpe1, _)) case mt: MethodType => @@ -1089,25 +1152,20 @@ trait Infer extends Checkable { /** Substitute free type variables `undetparams` of polymorphic argument * expression `tree` to `targs`, Error if `targs` is null. - * - * @param tree ... - * @param undetparams ... - * @param targs ... - * @param pt ... */ - private def substExpr(tree: Tree, undetparams: List[Symbol], - targs: List[Type], pt: Type) { + private def substExpr(tree: Tree, undetparams: List[Symbol], targs: List[Type], pt: Type) { if (targs eq null) { if (!tree.tpe.isErroneous && !pt.isErroneous) PolymorphicExpressionInstantiationError(tree, undetparams, pt) - } else { + } + else { new TreeTypeSubstituter(undetparams, targs).traverse(tree) notifyUndetparamsInferred(undetparams, targs) } } - /** Substitute free type variables <code>undetparams</code> of application - * <code>fn(args)</code>, given prototype <code>pt</code>. + /** Substitute free type variables `undetparams` of application + * `fn(args)`, given prototype `pt`. * * @param fn fn: the function that needs to be instantiated. * @param undetparams the parameters that need to be determined @@ -1120,10 +1178,10 @@ trait Infer extends Checkable { args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match { case mt @ MethodType(params0, _) => try { - val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0 - val formals = formalTypes(mt.paramTypes, args.length) - val argtpes = actualTypes(args map (x => elimAnonymousClass(x.tpe.deconst)), formals.length) - val restpe = fn.tpe.resultType(argtpes) + val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0 + val formals = formalTypes(mt.paramTypes, args.length) + val argtpes = tupleIfNecessary(formals, args map (x => elimAnonymousClass(x.tpe.deconst))) + val restpe = fn.tpe.resultType(argtpes) val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) = methTypeArgs(undetparams, formals, restpe, argtpes, pt) @@ -1160,8 +1218,8 @@ trait Infer extends Checkable { def widen(tp: Type): Type = abstractTypesToBounds(tp) - /** Substitute free type variables <code>undetparams</code> of type constructor - * <code>tree</code> in pattern, given prototype <code>pt</code>. + /** Substitute free type variables `undetparams` of type constructor + * `tree` in pattern, given prototype `pt`. * * @param tree the constuctor that needs to be instantiated * @param undetparams the undetermined type parameters @@ -1228,17 +1286,20 @@ trait Infer extends Checkable { } } else None - (inferFor(pt) orElse inferForApproxPt) map { targs => - new TreeTypeSubstituter(undetparams, targs).traverse(tree) - notifyUndetparamsInferred(undetparams, targs) - } getOrElse { - debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)")) - // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt) - ConstrInstantiationError(tree, resTp, pt) + val inferred = inferFor(pt) orElse inferForApproxPt + + inferred match { + case Some(targs) => + new TreeTypeSubstituter(undetparams, targs).traverse(tree) + notifyUndetparamsInferred(undetparams, targs) + case _ => + def full = if (isFullyDefined(pt)) "(fully defined)" else "(not fully defined)" + devWarning(s"failed inferConstructorInstance for $tree: ${tree.tpe} undet=$undetparams, pt=$pt $full") + // if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt) + ConstrInstantiationError(tree, resTp, pt) } } - def instBounds(tvar: TypeVar): (Type, Type) = { val tparam = tvar.origin.typeSymbol val instType = toOrigin(tvar.constr.inst) @@ -1286,51 +1347,6 @@ trait Infer extends Checkable { } } - /** Does `tp` contain any types that cannot be checked at run-time (i.e., after erasure, will isInstanceOf[erased(tp)] imply conceptualIsInstanceOf[tp]?) - * we should find a way to ask erasure: hey, is `tp` going to make it through you with all of its isInstanceOf resolving powers intact? - * TODO: at the very least, reduce duplication wrt checkCheckable - */ - def containsUnchecked(tp: Type): Boolean = { - def check(tp: Type, bound: List[Symbol]): Boolean = { - def isSurroundingTypeParam(sym: Symbol) = { - val e = context.scope.lookupEntry(sym.name) - ( (e ne null) - && (e.sym == sym ) - && !e.sym.isTypeParameterOrSkolem - && (e.owner == context.scope) - ) - } - def isLocalBinding(sym: Symbol) = ( - sym.isAbstractType && ( - (bound contains sym) - || (sym.name == tpnme.WILDCARD) - || isSurroundingTypeParam(sym) - ) - ) - tp.normalize match { - case SingleType(pre, _) => - check(pre, bound) - case TypeRef(_, ArrayClass, arg :: _) => - check(arg, bound) - case tp @ TypeRef(pre, sym, args) => - ( (sym.isAbstractType && !isLocalBinding(sym)) - || (args exists (x => !isLocalBinding(x.typeSymbol))) - || check(pre, bound) - ) - // case RefinedType(_, decls) if decls.nonEmpty => - // patternWarning(tp, "refinement ") - case RefinedType(parents, _) => - parents exists (p => check(p, bound)) - case ExistentialType(quantified, tp1) => - check(tp1, bound ::: quantified) - case _ => - false - } - } - check(tp, Nil) - } - - /** Type intersection of simple type tp1 with general type tp2. * The result eliminates some redundancies. */ @@ -1469,52 +1485,30 @@ trait Infer extends Checkable { } */ - /** Assign <code>tree</code> the symbol and type of the alternative which - * matches prototype <code>pt</code>, if it exists. + /** Assign `tree` the symbol and type of the alternative which + * matches prototype `pt`, if it exists. * If several alternatives match `pt`, take parameterless one. * If no alternative matches `pt`, take the parameterless one anyway. */ def inferExprAlternative(tree: Tree, pt: Type) = tree.tpe match { case OverloadedType(pre, alts) => tryTwice { isSecondTry => - val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt)) - val noAlternatives = alts0.isEmpty - val alts1 = if (noAlternatives) alts else alts0 - - //println("trying "+alts1+(alts1 map (_.tpe))+(alts1 map (_.locationString))+" for "+pt) - def improves(sym1: Symbol, sym2: Symbol): Boolean = - sym2 == NoSymbol || sym2.hasAnnotation(BridgeClass) || - { val tp1 = pre.memberType(sym1) - val tp2 = pre.memberType(sym2) - (tp2 == ErrorType || - !global.typer.infer.isWeaklyCompatible(tp2, pt) && global.typer.infer.isWeaklyCompatible(tp1, pt) || - isStrictlyMoreSpecific(tp1, tp2, sym1, sym2)) } + val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt)) + val alts1 = if (alts0.isEmpty) alts else alts0 - val best = ((NoSymbol: Symbol) /: alts1) ((best, alt) => - if (improves(alt, best)) alt else best) + val bests = bestAlternatives(alts1) { (sym1, sym2) => + val tp1 = pre.memberType(sym1) + val tp2 = pre.memberType(sym2) - val competing = alts1 dropWhile (alt => best == alt || improves(best, alt)) - - if (best == NoSymbol) { - if (settings.debug.value) { - tree match { - case Select(qual, _) => - Console.println("qual: " + qual + ":" + qual.tpe + - " with decls " + qual.tpe.decls + - " with members " + qual.tpe.members + - " with members " + qual.tpe.member(newTermName("$minus"))) - case _ => - } - } - // todo: missing test case - NoBestExprAlternativeError(tree, pt, isSecondTry) - } else if (!competing.isEmpty) { - if (noAlternatives) NoBestExprAlternativeError(tree, pt, isSecondTry) - else if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt, isSecondTry) - } else { -// val applicable = alts1 filter (alt => -// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt)) -// checkNotShadowed(tree.pos, pre, best, applicable) - tree.setSymbol(best).setType(pre.memberType(best)) + ( tp2 == ErrorType + || (!isWeaklyCompatible(tp2, pt) && isWeaklyCompatible(tp1, pt)) + || isStrictlyMoreSpecific(tp1, tp2, sym1, sym2) + ) + } + // todo: missing test case for bests.isEmpty + bests match { + case best :: Nil => tree setSymbol best setType (pre memberType best) + case best :: competing :: _ if alts0.nonEmpty => if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing, pt, isSecondTry) + case _ => if (bests.isEmpty || alts0.isEmpty) NoBestExprAlternativeError(tree, pt, isSecondTry) } } } @@ -1533,48 +1527,47 @@ trait Infer extends Checkable { private def paramMatchesName(param: Symbol, name: Name) = param.name == name || param.deprecatedParamName.exists(_ == name) - // Check the first parameter list the same way. - private def methodMatchesName(method: Symbol, name: Name) = method.paramss match { - case ps :: _ => ps exists (p => paramMatchesName(p, name)) - case _ => false + private def containsNamedType(argtpes: List[Type]): Boolean = argtpes match { + case Nil => false + case NamedType(_, _) :: _ => true + case _ :: rest => containsNamedType(rest) } - - private def resolveOverloadedMethod(argtpes: List[Type], eligible: List[Symbol]) = { + private def namesOfNamedArguments(argtpes: List[Type]) = + argtpes collect { case NamedType(name, _) => name } + + /** Given a list of argument types and eligible method overloads, whittle the + * list down to the methods which should be considered for specificity + * testing, taking into account here: + * - named arguments at the call site (keep only methods with name-matching parameters) + * - if multiple methods are eligible, drop any methods which take default arguments + * - drop any where arity cannot match under any conditions (allowing for + * overloaded applies, varargs, and tupling conversions) + * This method is conservative; it can tolerate some varieties of false positive, + * but no false negatives. + * + * @param eligible the overloaded method symbols + * @param argtpes the argument types at the call site + * @param varargsStar true if the call site has a `: _*` attached to the last argument + */ + private def overloadsToConsiderBySpecificity(eligible: List[Symbol], argtpes: List[Type], varargsStar: Boolean): List[Symbol] = { // If there are any foo=bar style arguments, and any of the overloaded // methods has a parameter named `foo`, then only those methods are considered. - val namesOfArgs = argtpes collect { case NamedType(name, _) => name } - val namesMatch = ( - if (namesOfArgs.isEmpty) Nil - else eligible filter { m => - namesOfArgs forall { name => - methodMatchesName(m, name) - } - } - ) - - if (namesMatch.nonEmpty) namesMatch - else if (eligible.isEmpty || eligible.tail.isEmpty) eligible - else eligible filter { alt => - // for functional values, the `apply` method might be overloaded - val mtypes = followApply(alt.tpe) match { - case OverloadedType(_, alts) => alts map (_.tpe) - case t => t :: Nil - } - // Drop those that use a default; keep those that use vararg/tupling conversion. - mtypes exists (t => - !t.typeSymbol.hasDefaultFlag && { - compareLengths(t.params, argtpes) < 0 || // tupling (*) - hasExactlyNumParams(t, argtpes.length) // same nb or vararg - } - ) - // (*) more arguments than parameters, but still applicable: tupling conversion works. - // todo: should not return "false" when paramTypes = (Unit) no argument is given - // (tupling would work) + val namesMatch = namesOfNamedArguments(argtpes) match { + case Nil => Nil + case names => eligible filter (m => names forall (name => m.info.params exists (p => paramMatchesName(p, name)))) } + if (namesMatch.nonEmpty) + namesMatch + else if (eligible.isEmpty || eligible.tail.isEmpty) + eligible + else + eligible filter (alt => + !alt.hasDefault && isApplicableBasedOnArity(alt.tpe, argtpes.length, varargsStar, tuplingAllowed = true) + ) } - /** Assign <code>tree</code> the type of an alternative which is applicable - * to <code>argtpes</code>, and whose result type is compatible with `pt`. + /** Assign `tree` the type of an alternative which is applicable + * to `argtpes`, and whose result type is compatible with `pt`. * If several applicable alternatives exist, drop the alternatives which use * default arguments, then select the most specialized one. * If no applicable alternative exists, and pt != WildcardType, try again @@ -1586,49 +1579,42 @@ trait Infer extends Checkable { * of some NamedType does not exist in an alternative's parameter names, * the type is replaces by `Unit`, i.e. the argument is treated as an * assignment expression. + * + * @pre tree.tpe is an OverloadedType. */ - def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], - argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false, lastInferAttempt: Boolean = true): Unit = tree.tpe match { - case OverloadedType(pre, alts) => - val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0 - tryTwice { isSecondTry => - debuglog("infer method alt "+ tree.symbol +" with alternatives "+ - (alts map pre.memberType) +", argtpes = "+ argtpes +", pt = "+ pt) - - val applicable = resolveOverloadedMethod(argtpes, { - alts filter { alt => - inSilentMode(context)(isApplicable(undetparams, followApply(pre.memberType(alt)), argtpes, pt)) && - (!varArgsOnly || isVarArgsList(alt.tpe.params)) - } - }) - - def improves(sym1: Symbol, sym2: Symbol) = { - // util.trace("improve "+sym1+sym1.locationString+" on "+sym2+sym2.locationString) - sym2 == NoSymbol || sym2.isError || sym2.hasAnnotation(BridgeClass) || - isStrictlyMoreSpecific(followApply(pre.memberType(sym1)), - followApply(pre.memberType(sym2)), sym1, sym2) - } - - val best = ((NoSymbol: Symbol) /: applicable) ((best, alt) => - if (improves(alt, best)) alt else best) - val competing = applicable.dropWhile(alt => best == alt || improves(best, alt)) - if (best == NoSymbol) { - if (pt == WildcardType) NoBestMethodAlternativeError(tree, argtpes, pt, isSecondTry && lastInferAttempt) - else inferMethodAlternative(tree, undetparams, argtpes, WildcardType, lastInferAttempt = isSecondTry) - } else if (!competing.isEmpty) { - AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt, isSecondTry && lastInferAttempt) - } else { -// checkNotShadowed(tree.pos, pre, best, applicable) - tree.setSymbol(best).setType(pre.memberType(best)) - } + def inferMethodAlternative(tree: Tree, undetparams: List[Symbol], argtpes0: List[Type], pt0: Type): Unit = { + val OverloadedType(pre, alts) = tree.tpe + var varargsStar = false + val argtpes = argtpes0 mapConserve { + case RepeatedType(tp) => varargsStar = true ; tp + case tp => tp + } + def followType(sym: Symbol) = followApply(pre memberType sym) + def bestForExpectedType(pt: Type, isLastTry: Boolean): Unit = { + val applicable0 = alts filter (alt => inSilentMode(context)(isApplicable(undetparams, followType(alt), argtpes, pt))) + val applicable = overloadsToConsiderBySpecificity(applicable0, argtpes, varargsStar) + val ranked = bestAlternatives(applicable)((sym1, sym2) => + isStrictlyMoreSpecific(followType(sym1), followType(sym2), sym1, sym2) + ) + ranked match { + case best :: competing :: _ => AmbiguousMethodAlternativeError(tree, pre, best, competing, argtpes, pt, isLastTry) // ambiguous + case best :: Nil => tree setSymbol best setType (pre memberType best) // success + case Nil if pt eq WildcardType => NoBestMethodAlternativeError(tree, argtpes, pt, isLastTry) // failed + case Nil => bestForExpectedType(WildcardType, isLastTry) // failed, but retry with WildcardType } - case _ => + } + // This potentially makes up to four attempts: tryTwice may execute + // with and without views enabled, and bestForExpectedType will try again + // with pt = WildcardType if it fails with pt != WildcardType. + tryTwice { isLastTry => + val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0 + debuglog(s"infer method alt ${tree.symbol} with alternatives ${alts map pre.memberType} argtpes=$argtpes pt=$pt") + bestForExpectedType(pt, isLastTry) + } } /** Try inference twice, once without views and once with views, * unless views are already disabled. - * - * @param infer ... */ def tryTwice(infer: Boolean => Unit): Unit = { if (context.implicitsEnabled) { @@ -1663,12 +1649,9 @@ trait Infer extends Checkable { else infer(true) } - /** Assign <code>tree</code> the type of all polymorphic alternatives - * with <code>nparams</code> as the number of type parameters, if it exists. + /** Assign `tree` the type of all polymorphic alternatives + * with `nparams` as the number of type parameters, if it exists. * If no such polymorphic alternative exist, error. - * - * @param tree ... - * @param nparams ... */ def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Unit = { val OverloadedType(pre, alts) = tree.tpe diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index bcc37e8b37..4b534b0d2e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -3,15 +3,10 @@ package typechecker import symtab.Flags._ import scala.tools.nsc.util._ -import scala.tools.nsc.util.ClassPath._ import scala.reflect.runtime.ReflectionUtils import scala.collection.mutable.ListBuffer -import scala.compat.Platform.EOL import scala.reflect.internal.util.Statistics import scala.reflect.macros.util._ -import java.lang.{Class => jClass} -import java.lang.reflect.{Array => jArray, Method => jMethod} -import scala.reflect.internal.util.Collections._ import scala.util.control.ControlThrowable import scala.reflect.macros.runtime.AbortMacroException @@ -300,53 +295,51 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { private def macroImplSig(macroDef: Symbol, tparams: List[TypeDef], vparamss: List[List[ValDef]], retTpe: Type): (List[List[Symbol]], Type) = { // had to move method's body to an object because of the recursive dependencies between sigma and param object SigGenerator { - def sigma(tpe: Type): Type = { - class SigmaTypeMap extends TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) => - val pre1 = pre match { - case ThisType(sym) if sym == macroDef.owner => - SingleType(SingleType(SingleType(NoPrefix, ctxParam), MacroContextPrefix), ExprValue) - case SingleType(NoPrefix, sym) => - mfind(vparamss)(_.symbol == sym) match { - case Some(macroDefParam) => SingleType(SingleType(NoPrefix, param(macroDefParam)), ExprValue) - case _ => pre - } - case _ => - pre - } - TypeRef(pre1, sym, args map mapOver) - case _ => - mapOver(tp) - } + def WeakTagClass = getMember(MacroContextClass, tpnme.WeakTypeTag) + def ExprClass = getMember(MacroContextClass, tpnme.Expr) + val cache = scala.collection.mutable.Map[Symbol, Symbol]() + val ctxParam = makeParam(nme.macroContext, macroDef.pos, MacroContextClass.tpe, SYNTHETIC) + val paramss = List(ctxParam) :: mmap(vparamss)(param) + val implReturnType = typeRef(singleType(NoPrefix, ctxParam), ExprClass, List(sigma(retTpe))) + + object SigmaTypeMap extends TypeMap { + def mapPrefix(pre: Type) = pre match { + case ThisType(sym) if sym == macroDef.owner => + singleType(singleType(singleType(NoPrefix, ctxParam), MacroContextPrefix), ExprValue) + case SingleType(NoPrefix, sym) => + mfind(vparamss)(_.symbol == sym).fold(pre)(p => singleType(singleType(NoPrefix, param(p)), ExprValue)) + case _ => + mapOver(pre) + } + def apply(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) => + val pre1 = mapPrefix(pre) + val args1 = mapOverArgs(args, sym.typeParams) + if ((pre eq pre1) && (args eq args1)) tp + else typeRef(pre1, sym, args1) + case _ => + mapOver(tp) } - - new SigmaTypeMap() apply tpe } + def sigma(tpe: Type): Type = SigmaTypeMap(tpe) - def makeParam(name: Name, pos: Position, tpe: Type, flags: Long = 0L) = + def makeParam(name: Name, pos: Position, tpe: Type, flags: Long) = macroDef.newValueParameter(name, pos, flags) setInfo tpe - val ctxParam = makeParam(nme.macroContext, macroDef.pos, MacroContextClass.tpe, SYNTHETIC) - def implType(isType: Boolean, origTpe: Type): Type = + def implType(isType: Boolean, origTpe: Type): Type = { + def tsym = if (isType) WeakTagClass else ExprClass + def targ = origTpe.typeArgs.headOption getOrElse NoType + if (isRepeatedParamType(origTpe)) - appliedType( - RepeatedParamClass.typeConstructor, - List(implType(isType, sigma(origTpe.typeArgs.head)))) - else { - val tsym = getMember(MacroContextClass, if (isType) tpnme.WeakTypeTag else tpnme.Expr) + scalaRepeatedType(implType(isType, sigma(targ))) + else typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(origTpe))) - } - val paramCache = scala.collection.mutable.Map[Symbol, Symbol]() - def param(tree: Tree): Symbol = - paramCache.getOrElseUpdate(tree.symbol, { + } + def param(tree: Tree): Symbol = ( + cache.getOrElseUpdate(tree.symbol, { val sym = tree.symbol - val sigParam = makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe)) - if (sym.isSynthetic) sigParam.flags |= SYNTHETIC - sigParam + makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym getFlag SYNTHETIC) }) - - val paramss = List(ctxParam) :: mmap(vparamss)(param) - val implRetTpe = typeRef(singleType(NoPrefix, ctxParam), getMember(MacroContextClass, tpnme.Expr), List(sigma(retTpe))) + ) } import SigGenerator._ @@ -354,7 +347,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { macroTraceVerbose("tparams are: ")(tparams) macroTraceVerbose("vparamss are: ")(vparamss) macroTraceVerbose("retTpe is: ")(retTpe) - macroTraceVerbose("macroImplSig is: ")((paramss, implRetTpe)) + macroTraceVerbose("macroImplSig is: ")((paramss, implReturnType)) } /** Verifies that the body of a macro def typechecks to a reference to a static public non-overloaded method, @@ -727,16 +720,15 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { /** Does the same as `macroExpand`, but without typechecking the expansion * Meant for internal use within the macro infrastructure, don't use it elsewhere. */ - private def macroExpand1(typer: Typer, expandee: Tree): MacroExpansionResult = + private def macroExpand1(typer: Typer, expandee: Tree): MacroExpansionResult = { // verbose printing might cause recursive macro expansions, so I'm shutting it down here withInfoLevel(nodePrinters.InfoLevel.Quiet) { if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) { val reason = if (expandee.symbol.isErroneous) "not found or incompatible macro implementation" else "erroneous arguments" macroTraceVerbose("cancelled macro expansion because of %s: ".format(reason))(expandee) - return Cancel(typer.infer.setError(expandee)) + Cancel(typer.infer.setError(expandee)) } - - try { + else try { val runtime = macroRuntime(expandee.symbol) if (runtime != null) macroExpandWithRuntime(typer, expandee, runtime) else macroExpandWithoutRuntime(typer, expandee) @@ -744,6 +736,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case typer.TyperErrorGen.MacroExpansionException => Failure(expandee) } } + } /** Expands a macro when a runtime (i.e. the macro implementation) can be successfully loaded * Meant for internal use within the macro infrastructure, don't use it elsewhere. diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index acc4f7ff67..3ac5d388d3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package typechecker import symtab.Flags._ -import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.StringOps.{ ojoin } import scala.reflect.ClassTag import scala.reflect.runtime.{ universe => ru } @@ -30,61 +29,23 @@ trait MethodSynthesis { if (sym.isLazy) ValDef(sym, body) else DefDef(sym, body) - def applyTypeInternal(tags: List[TT[_]]): Type = { - val symbols = tags map compilerSymbolFromTag - val container :: args = symbols - val tparams = container.typeConstructor.typeParams - - // Conservative at present - if manifests were more usable this could do a lot more. - // [Eugene to Paul] all right, they are now. what do you have in mind? - require(symbols forall (_ ne NoSymbol), "Must find all tags: " + symbols) - require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container) - require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args) - - appliedType(container, args map (_.tpe): _*) - } - - def companionType[T](implicit ct: CT[T]) = - rootMirror.getRequiredModule(ct.runtimeClass.getName).tpe - - // Use these like `applyType[List, Int]` or `applyType[Map, Int, String]` - def applyType[CC](implicit t1: TT[CC]): Type = - applyTypeInternal(List(t1)) - - def applyType[CC[X1], X1](implicit t1: TT[CC[_]], t2: TT[X1]): Type = - applyTypeInternal(List(t1, t2)) - - def applyType[CC[X1, X2], X1, X2](implicit t1: TT[CC[_,_]], t2: TT[X1], t3: TT[X2]): Type = - applyTypeInternal(List(t1, t2, t3)) - - def applyType[CC[X1, X2, X3], X1, X2, X3](implicit t1: TT[CC[_,_,_]], t2: TT[X1], t3: TT[X2], t4: TT[X3]): Type = - applyTypeInternal(List(t1, t2, t3, t4)) - - def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = { - val fnSymbol = compilerSymbolFromTag(t) - val formals = compilerTypeFromTag(t).typeArguments - assert(fnSymbol isSubClass FunctionClass(formals.size - 1), (owner, t)) - val params = owner newSyntheticValueParams formals - MethodType(params, formals.last) - } - - /** The annotations amongst those found on the original symbol which - * should be propagated to this kind of accessor. - */ - def deriveAnnotations(initial: List[AnnotationInfo], category: Symbol, keepClean: Boolean): List[AnnotationInfo] = { - initial filter { ann => - // There are no meta-annotation arguments attached to `ann` - if (ann.metaAnnotations.isEmpty) { - // A meta-annotation matching `annotKind` exists on `ann`'s definition. - (ann.defaultTargets contains category) || - // `ann`'s definition has no meta-annotations, and `keepClean` is true. - (ann.defaultTargets.isEmpty && keepClean) - } - // There are meta-annotation arguments, and one of them matches `annotKind` - else ann.metaAnnotations exists (_ matches category) + /** The annotations amongst those found on the original symbol which + * should be propagated to this kind of accessor. + */ + def deriveAnnotations(initial: List[AnnotationInfo], category: Symbol, keepClean: Boolean): List[AnnotationInfo] = { + initial filter { ann => + // There are no meta-annotation arguments attached to `ann` + if (ann.metaAnnotations.isEmpty) { + // A meta-annotation matching `annotKind` exists on `ann`'s definition. + (ann.defaultTargets contains category) || + // `ann`'s definition has no meta-annotations, and `keepClean` is true. + (ann.defaultTargets.isEmpty && keepClean) } + // There are meta-annotation arguments, and one of them matches `annotKind` + else ann.metaAnnotations exists (_ matches category) } - } + } + } import synthesisUtil._ class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) { @@ -119,22 +80,9 @@ trait MethodSynthesis { finishMethod(clazz.info.decls enter m, f) } - private def cloneInternal(original: Symbol, f: Symbol => Tree): Tree = - cloneInternal(original, f, original.name) - def clazzMember(name: Name) = clazz.info nonPrivateMember name def typeInClazz(sym: Symbol) = clazz.thisType memberType sym - /** Function argument takes the newly created method symbol of - * the same type as `name` in clazz, and returns the tree to be - * added to the template. - */ - def overrideMethod(name: Name)(f: Symbol => Tree): Tree = - overrideMethod(clazzMember(name))(f) - - def overrideMethod(original: Symbol)(f: Symbol => Tree): Tree = - cloneInternal(original, sym => f(sym setFlag OVERRIDE)) - def deriveMethod(original: Symbol, nameFn: Name => Name)(f: Symbol => Tree): Tree = cloneInternal(original, f, nameFn(original.name)) @@ -312,7 +260,6 @@ trait MethodSynthesis { // Final methods to make the rest easier to reason about. final def mods = tree.mods final def basisSym = tree.symbol - final def derivedFlags: Long = basisSym.flags & flagsMask | flagsExtra } trait DerivedFromClassDef extends DerivedFromMemberDef { @@ -457,7 +404,7 @@ trait MethodSynthesis { case class LazyValGetter(tree: ValDef) extends BaseGetter(tree) { class ChangeOwnerAndModuleClassTraverser(oldowner: Symbol, newowner: Symbol) extends ChangeOwnerTraverser(oldowner, newowner) { - + override def traverse(tree: Tree) { tree match { case _: DefTree => change(tree.symbol.moduleClass) @@ -557,7 +504,7 @@ trait MethodSynthesis { // No Symbols available. private def beanAccessorsFromNames(tree: ValDef) = { - val ValDef(mods, name, tpt, _) = tree + val ValDef(mods, _, _, _) = tree val hasBP = mods hasAnnotationNamed tpnme.BeanPropertyAnnot val hasBoolBP = mods hasAnnotationNamed tpnme.BooleanBeanPropertyAnnot diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/compiler/scala/tools/nsc/typechecker/Modes.scala index d650762ac1..e1ee3c482a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Modes.scala @@ -109,6 +109,7 @@ trait Modes { final def inFunMode(mode: Int) = (mode & FUNmode) != 0 final def inPolyMode(mode: Int) = (mode & POLYmode) != 0 final def inPatternMode(mode: Int) = (mode & PATTERNmode) != 0 + final def inPatternNotFunMode(mode: Int) = inPatternMode(mode) && !inFunMode(mode) final def inExprModeOr(mode: Int, others: Int) = (mode & (EXPRmode | others)) != 0 final def inExprModeButNot(mode: Int, prohibited: Int) = (mode & (EXPRmode | prohibited)) == EXPRmode diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index f5d4df14fe..79fc0e0081 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -8,9 +8,7 @@ package typechecker import scala.collection.mutable import scala.annotation.tailrec -import scala.ref.WeakReference import symtab.Flags._ -import scala.tools.nsc.io.AbstractFile /** This trait declares methods to create symbols and to enter them into scopes. * @@ -159,6 +157,9 @@ trait Namers extends MethodSynthesis { else innerNamer } + // FIXME - this logic needs to be thoroughly explained + // and justified. I know it's wrong with repect to package + // objects, but I think it's also wrong in other ways. protected def conflict(newS: Symbol, oldS: Symbol) = ( ( !oldS.isSourceMethod || nme.isSetterName(newS.name) @@ -186,6 +187,19 @@ trait Namers extends MethodSynthesis { /** Enter symbol into given scope and return symbol itself */ def enterInScope(sym: Symbol, scope: Scope): Symbol = { + // FIXME - this is broken in a number of ways. + // + // 1) If "sym" allows overloading, that is not itself sufficient to skip + // the check, because "prev.sym" also must allow overloading. + // + // 2) There is nothing which reconciles a package's scope with + // the package object's scope. This is the source of many bugs + // with e.g. defining a case class in a package object. When + // compiling against classes, the class symbol is created in the + // package and in the package object, and the conflict is undetected. + // There is also a non-deterministic outcome for situations like + // an object with the same name as a method in the package object. + // allow for overloaded methods if (!allowsOverload(sym)) { val prev = scope.lookupEntry(sym.name) @@ -321,11 +335,10 @@ trait Namers extends MethodSynthesis { } private def enterClassSymbol(tree: ClassDef, clazz: ClassSymbol): Symbol = { - val file = contextFile if (clazz.sourceFile != null && clazz.sourceFile != contextFile) - debugwarn("!!! Source mismatch in " + clazz + ": " + clazz.sourceFile + " vs. " + contextFile) + devWarning(s"Source file mismatch in $clazz: ${clazz.sourceFile} vs. $contextFile") - clazz.sourceFile = contextFile + clazz.associatedFile = contextFile if (clazz.sourceFile != null) { assert(currentRun.canRedefine(clazz) || clazz.sourceFile == currentRun.symSource(clazz), clazz.sourceFile) currentRun.symSource(clazz) = clazz.sourceFile @@ -365,8 +378,8 @@ trait Namers extends MethodSynthesis { if (sym eq NoSymbol) return val ctx = if (context.owner.isPackageObjectClass) context.outer else context - val module = if (sym.isModule) sym else ctx.scope lookup tree.name.toTermName - val clazz = if (sym.isClass) sym else ctx.scope lookup tree.name.toTypeName + val module = if (sym.isModule) sym else ctx.scope lookupModule tree.name + val clazz = if (sym.isClass) sym else ctx.scope lookupClass tree.name val fails = ( module.isModule && clazz.isClass @@ -413,7 +426,7 @@ trait Namers extends MethodSynthesis { setPrivateWithin(tree, m.moduleClass) } if (m.owner.isPackageClass && !m.isPackage) { - m.moduleClass.sourceFile = contextFile + m.moduleClass.associatedFile = contextFile currentRun.symSource(m) = m.moduleClass.sourceFile registerTopLevelSym(m) } @@ -596,7 +609,7 @@ trait Namers extends MethodSynthesis { // via "x$lzy" as can be seen in test #3927. val sym = ( if (owner.isClass) createFieldSymbol(tree) - else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, tree.mods.flags & ~IMPLICIT) + else owner.newValue(tree.name append nme.LAZY_LOCAL, tree.pos, (tree.mods.flags | ARTIFACT) & ~IMPLICIT) ) enterValSymbol(tree, sym setFlag MUTABLE setLazyAccessor lazyAccessor) } @@ -617,7 +630,7 @@ trait Namers extends MethodSynthesis { case DefDef(_, nme.CONSTRUCTOR, _, _, _, _) => assignAndEnterFinishedSymbol(tree) case DefDef(mods, name, tparams, _, _, _) => - val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE else 0 + val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0 val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag if (name == nme.copy && sym.isSynthetic) @@ -627,7 +640,7 @@ trait Namers extends MethodSynthesis { } def enterClassDef(tree: ClassDef) { - val ClassDef(mods, name, tparams, impl) = tree + val ClassDef(mods, _, _, impl) = tree val primaryConstructorArity = treeInfo.firstConstructorArgs(impl.body).size tree.symbol = enterClassSymbol(tree) tree.symbol setInfo completerOf(tree) @@ -691,41 +704,55 @@ trait Namers extends MethodSynthesis { // --- Lazy Type Assignment -------------------------------------------------- - def initializeLowerBounds(tp: Type): Type = { + def findCyclicalLowerBound(tp: Type): Symbol = { tp match { case TypeBounds(lo, _) => // check that lower bound is not an F-bound - for (TypeRef(_, sym, _) <- lo) - sym.initialize + // but carefully: class Foo[T <: Bar[_ >: T]] should be allowed + for (tp1 @ TypeRef(_, sym, _) <- lo) { + if (settings.breakCycles.value) { + if (!sym.maybeInitialize) { + log(s"Cycle inspecting $lo for possible f-bounds: ${sym.fullLocationString}") + return sym + } + } + else sym.initialize + } case _ => } - tp + NoSymbol } def monoTypeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => + // this early test is there to avoid infinite baseTypes when + // adding setters and getters --> bug798 + // It is a def in an attempt to provide some insulation against + // uninitialized symbols misleading us. It is not a certainty + // this accomplishes anything, but performance is a non-consideration + // on these flag checks so it can't hurt. + def needsCycleCheck = sym.isNonClassType && !sym.isParameter && !sym.isExistential logAndValidate(sym) { - val tp = initializeLowerBounds(typeSig(tree)) + val tp = typeSig(tree) + + findCyclicalLowerBound(tp) andAlso { sym => + if (needsCycleCheck) { + // neg/t1224: trait C[T] ; trait A { type T >: C[T] <: C[C[T]] } + // To avoid an infinite loop on the above, we cannot break all cycles + log(s"Reinitializing info of $sym to catch any genuine cycles") + sym reset sym.info + sym.initialize + } + } sym setInfo { if (sym.isJavaDefined) RestrictJavaArraysMap(tp) else tp } - // this early test is there to avoid infinite baseTypes when - // adding setters and getters --> bug798 - val needsCycleCheck = (sym.isAliasType || sym.isAbstractType) && !sym.isParameter - if (needsCycleCheck && !typer.checkNonCyclic(tree.pos, tp)) - sym setInfo ErrorType + if (needsCycleCheck) { + log(s"Needs cycle check: ${sym.debugLocationString}") + if (!typer.checkNonCyclic(tree.pos, tp)) + sym setInfo ErrorType + } } - // tree match { - // case ClassDef(_, _, _, impl) => - // val parentsOK = ( - // treeInfo.isInterface(sym, impl.body) - // || (sym eq ArrayClass) - // || (sym isSubClass AnyValClass) - // ) - // if (!parentsOK) - // ensureParent(sym, AnyRefClass) - // case _ => () - // } } def moduleClassTypeCompleter(tree: ModuleDef) = { @@ -784,7 +811,7 @@ trait Namers extends MethodSynthesis { false } - val tpe1 = dropRepeatedParamType(tpe.deconst) + val tpe1 = dropIllegalStarTypes(tpe.deconst) val tpe2 = tpe1.widen // This infers Foo.type instead of "object Foo" @@ -832,7 +859,7 @@ trait Namers extends MethodSynthesis { val sym = ( if (hasType || hasName) { - owner.typeOfThis = if (hasType) selfTypeCompleter(tpt) else owner.tpe + owner.typeOfThis = if (hasType) selfTypeCompleter(tpt) else owner.tpe_* val selfSym = owner.thisSym setPos self.pos if (hasName) selfSym setName name else selfSym } @@ -882,11 +909,10 @@ trait Namers extends MethodSynthesis { val modClass = companionSymbolOf(clazz, context).moduleClass modClass.attachments.get[ClassForCaseCompanionAttachment] foreach { cma => val cdef = cma.caseClass - def hasCopy(decls: Scope) = (decls lookup nme.copy) != NoSymbol + def hasCopy = (decls containsName nme.copy) || parents.exists(_ member nme.copy exists) + // SI-5956 needs (cdef.symbol == clazz): there can be multiple class symbols with the same name - if (cdef.symbol == clazz && !hasCopy(decls) && - !parents.exists(p => hasCopy(p.typeSymbol.info.decls)) && - !parents.flatMap(_.baseClasses).distinct.exists(bc => hasCopy(bc.info.decls))) + if (cdef.symbol == clazz && !hasCopy) addCopyMethod(cdef, templateNamer) } } @@ -918,7 +944,7 @@ trait Namers extends MethodSynthesis { // DEPMETTODO: do we need to skolemize value parameter symbols? if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) { - tpt defineType context.enclClass.owner.tpe + tpt defineType context.enclClass.owner.tpe_* tpt setPos meth.pos.focus } var resultPt = if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe @@ -1170,9 +1196,9 @@ trait Namers extends MethodSynthesis { // same local block several times (which can happen in interactive mode) we might // otherwise not find the default symbol, because the second time it the method // symbol will be re-entered in the scope but the default parameter will not. - val att = meth.attachments.get[DefaultsOfLocalMethodAttachment] match { + meth.attachments.get[DefaultsOfLocalMethodAttachment] match { case Some(att) => att.defaultGetters += default - case None => meth.updateAttachment(new DefaultsOfLocalMethodAttachment(default)) + case None => meth.updateAttachment(new DefaultsOfLocalMethodAttachment(default)) } } } else if (baseHasDefault) { @@ -1259,8 +1285,8 @@ trait Namers extends MethodSynthesis { if (!annotated.isInitialized) tree match { case defn: MemberDef => val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann => - // need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892. - AnnotationInfo lazily beforeTyper(typer typedAnnotation ann) + // need to be lazy, #1782. enteringTyper to allow inferView in annotation args, SI-5892. + AnnotationInfo lazily enteringTyper(typer typedAnnotation ann) } if (ainfos.nonEmpty) { annotated setAnnotations ainfos @@ -1289,7 +1315,8 @@ trait Namers extends MethodSynthesis { if (clazz.isDerivedValueClass) { log("Ensuring companion for derived value class " + name + " at " + cdef.pos.show) clazz setFlag FINAL - enclosingNamerWithScope(clazz.owner.info.decls).ensureCompanionObject(cdef) + // Don't force the owner's info lest we create cycles as in SI-6357. + enclosingNamerWithScope(clazz.owner.rawInfo.decls).ensureCompanionObject(cdef) } result @@ -1361,12 +1388,6 @@ trait Namers extends MethodSynthesis { tpe } - def ensureParent(clazz: Symbol, parent: Symbol) = { - val info0 = clazz.info - val info1 = includeParent(info0, parent) - if (info0 ne info1) clazz setInfo info1 - } - class LogTransitions[S](onEnter: S => String, onExit: S => String) { val enabled = settings.debug.value @inline final def apply[T](entity: S)(body: => T): T = { diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index be218fcb02..14c8d85836 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -8,7 +8,6 @@ package typechecker import symtab.Flags._ import scala.collection.mutable -import scala.ref.WeakReference import scala.reflect.ClassTag /** @@ -42,8 +41,6 @@ trait NamesDefaults { self: Analyzer => blockTyper: Typer ) { } - val noApplyInfo = NamedApplyInfo(None, Nil, Nil, null) - def nameOf(arg: Tree) = arg match { case AssignOrNamedArg(Ident(name), rhs) => Some(name) case _ => None @@ -164,14 +161,14 @@ trait NamesDefaults { self: Analyzer => // never used for constructor calls, they always have a stable qualifier def blockWithQualifier(qual: Tree, selected: Name) = { - val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe + val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo qual.tpe blockTyper.context.scope enter sym val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType) // it stays in Vegas: SI-5720, SI-5727 qual changeOwner (blockTyper.context.owner -> sym) val newQual = atPos(qual.pos.focus)(blockTyper.typedQualifier(Ident(sym.name))) - var baseFunTransformed = atPos(baseFun.pos.makeTransparent) { + val baseFunTransformed = atPos(baseFun.pos.makeTransparent) { // setSymbol below is important because the 'selected' function might be overloaded. by // assigning the correct method symbol, typedSelect will just assign the type. the reason // to still call 'typed' is to correctly infer singleton types, SI-5259. @@ -281,7 +278,7 @@ trait NamesDefaults { self: Analyzer => } else arg.tpe ).widen // have to widen or types inferred from literal defaults will be singletons - val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos) setInfo ( + val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo ( if (byName) functionType(Nil, argTpe) else argTpe ) (context.scope.enter(s), byName, repeated) @@ -319,7 +316,7 @@ trait NamesDefaults { self: Analyzer => assert(isNamedApplyBlock(transformedFun), transformedFun) val NamedApplyInfo(qual, targs, vargss, blockTyper) = context.namedApplyBlockInfo.get._2 - val existingBlock @ Block(stats, funOnly) = transformedFun + val Block(stats, funOnly) = transformedFun // type the application without names; put the arguments in definition-site order val typedApp = doTypedApply(tree, funOnly, reorderArgs(namelessArgs, argPos), mode, pt) diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 2b6b82f0ab..c5245c4e9e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -37,13 +37,11 @@ import scala.reflect.internal.Types * - recover exhaustivity/unreachability of user-defined extractors by partitioning the types they match on using an HList or similar type-level structure */ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL { // self: Analyzer => - import Statistics._ import PatternMatchingStats._ val global: Global // need to repeat here because otherwise last mixin defines global as // SymbolTable. If we had DOT this would not be an issue import global._ // the global environment - import definitions._ // standard classes and methods val phaseName: String = "patmat" @@ -70,7 +68,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL } def newTransformer(unit: CompilationUnit): Transformer = - if (opt.virtPatmat) new MatchTransformer(unit) + if (!settings.XoldPatmat.value) new MatchTransformer(unit) else noopTransformer // duplicated from CPSUtils (avoid dependency from compiler -> cps plugin...) @@ -192,7 +190,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL trait MatchTranslation extends MatchMonadInterface { self: TreeMakers with CodegenCore => import typer.{typed, context, silent, reallyExists} - // import typer.infer.containsUnchecked // Why is it so difficult to say "here's a name and a context, give me any // matching symbol in scope" ? I am sure this code is wrong, but attempts to @@ -274,7 +271,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // we don't transform after uncurry // (that would require more sophistication when generating trees, // and the only place that emits Matches after typers is for exception handling anyway) - if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ selector +" match "+ cases) + if (phase.id >= currentRun.uncurryPhase.id) + devWarning(s"running translateMatch past uncurry (at $phase) on $selector match $cases") + patmatDebug("translating "+ cases.mkString("{", "\n", "}")) val start = if (Statistics.canEnable) Statistics.startTimer(patmatNanos) else null @@ -294,8 +293,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // pt is the skolemized version val pt = repeatedToSeq(ptUnCPS) - // val packedPt = repeatedToSeq(typer.packedType(match_, context.owner)) - // the alternative to attaching the default case override would be to simply // append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...) val matchFailGenOverride = match_.attachments.get[DefaultOverrideMatchAttachment].map{case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)} @@ -560,54 +557,55 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL def fromCaseClass(fun: Tree, args: List[Tree]): Option[ExtractorCall] = Some(new ExtractorCallProd(fun, args)) // THE PRINCIPLED SLOW PATH -- NOT USED + // !!! Use it, test it, or delete it, else it is unlikely to be an asset. // generate a call to the (synthetically generated) extractor of a case class // NOTE: it's an apply, not a select, since in general an extractor call may have multiple argument lists (including an implicit one) // that we need to preserve, so we supply the scrutinee as Ident(nme.SELECTOR_DUMMY), // and replace that dummy by a reference to the actual binder in translateExtractorPattern - def fromCaseClassUnapply(fun: Tree, args: List[Tree]): Option[ExtractorCall] = { - // TODO: can we rework the typer so we don't have to do all this twice? - // undo rewrite performed in (5) of adapt - val orig = fun match {case tpt: TypeTree => tpt.original case _ => fun} - val origSym = orig.symbol - val extractor = unapplyMember(origSym.filter(sym => reallyExists(unapplyMember(sym.tpe))).tpe) - - if((fun.tpe eq null) || fun.tpe.isError || (extractor eq NoSymbol)) { - None - } else { - // this is a tricky balance: pos/t602.scala, pos/sudoku.scala, run/virtpatmat_alts.scala must all be happy - // bypass typing at own risk: val extractorCall = Select(orig, extractor) setType caseClassApplyToUnapplyTp(fun.tpe) - // can't always infer type arguments (pos/t602): - /* case class Span[K <: Ordered[K]](low: Option[K]) { - override def equals(x: Any): Boolean = x match { - case Span((low0 @ _)) if low0 equals low => true - } - }*/ - // so... leave undetermined type params floating around if we have to - // (if we don't infer types, uninstantiated type params show up later: pos/sudoku.scala) - // (see also run/virtpatmat_alts.scala) - val savedUndets = context.undetparams - val extractorCall = try { - context.undetparams = Nil - silent(_.typed(Apply(Select(orig, extractor), List(Ident(nme.SELECTOR_DUMMY) setType fun.tpe.finalResultType)), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { - case SilentResultValue(extractorCall) => extractorCall // if !extractorCall.containsError() - case _ => - // this fails to resolve overloading properly... - // Apply(typedOperator(Select(orig, extractor)), List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway - - // patmatDebug("funtpe after = "+ fun.tpe.finalResultType) - // patmatDebug("orig: "+(orig, orig.tpe)) - val tgt = typed(orig, EXPRmode | QUALmode | POLYmode, HasMember(extractor.name)) // can't specify fun.tpe.finalResultType as the type for the extractor's arg, - // as it may have been inferred incorrectly (see t602, where it's com.mosol.sl.Span[Any], instead of com.mosol.sl.Span[?K]) - // patmatDebug("tgt = "+ (tgt, tgt.tpe)) - val oper = typed(Select(tgt, extractor.name), EXPRmode | FUNmode | POLYmode | TAPPmode, WildcardType) - // patmatDebug("oper: "+ (oper, oper.tpe)) - Apply(oper, List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway - } - } finally context.undetparams = savedUndets - - Some(this(extractorCall, args)) // TODO: simplify spliceApply? - } - } + // def fromCaseClassUnapply(fun: Tree, args: List[Tree]): Option[ExtractorCall] = { + // // TODO: can we rework the typer so we don't have to do all this twice? + // // undo rewrite performed in (5) of adapt + // val orig = fun match {case tpt: TypeTree => tpt.original case _ => fun} + // val origSym = orig.symbol + // val extractor = unapplyMember(origSym.filter(sym => reallyExists(unapplyMember(sym.tpe))).tpe) + + // if((fun.tpe eq null) || fun.tpe.isError || (extractor eq NoSymbol)) { + // None + // } else { + // // this is a tricky balance: pos/t602.scala, pos/sudoku.scala, run/virtpatmat_alts.scala must all be happy + // // bypass typing at own risk: val extractorCall = Select(orig, extractor) setType caseClassApplyToUnapplyTp(fun.tpe) + // // can't always infer type arguments (pos/t602): + // /* case class Span[K <: Ordered[K]](low: Option[K]) { + // override def equals(x: Any): Boolean = x match { + // case Span((low0 @ _)) if low0 equals low => true + // } + // }*/ + // // so... leave undetermined type params floating around if we have to + // // (if we don't infer types, uninstantiated type params show up later: pos/sudoku.scala) + // // (see also run/virtpatmat_alts.scala) + // val savedUndets = context.undetparams + // val extractorCall = try { + // context.undetparams = Nil + // silent(_.typed(Apply(Select(orig, extractor), List(Ident(nme.SELECTOR_DUMMY) setType fun.tpe.finalResultType)), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { + // case SilentResultValue(extractorCall) => extractorCall // if !extractorCall.containsError() + // case _ => + // // this fails to resolve overloading properly... + // // Apply(typedOperator(Select(orig, extractor)), List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway + + // // patmatDebug("funtpe after = "+ fun.tpe.finalResultType) + // // patmatDebug("orig: "+(orig, orig.tpe)) + // val tgt = typed(orig, EXPRmode | QUALmode | POLYmode, HasMember(extractor.name)) // can't specify fun.tpe.finalResultType as the type for the extractor's arg, + // // as it may have been inferred incorrectly (see t602, where it's com.mosol.sl.Span[Any], instead of com.mosol.sl.Span[?K]) + // // patmatDebug("tgt = "+ (tgt, tgt.tpe)) + // val oper = typed(Select(tgt, extractor.name), EXPRmode | FUNmode | POLYmode | TAPPmode, WildcardType) + // // patmatDebug("oper: "+ (oper, oper.tpe)) + // Apply(oper, List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway + // } + // } finally context.undetparams = savedUndets + + // Some(this(extractorCall, args)) // TODO: simplify spliceApply? + // } + // } } abstract class ExtractorCall(val args: List[Tree]) { @@ -1426,10 +1424,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // local / context-free def _asInstanceOf(b: Symbol, tp: Type): Tree - def _asInstanceOf(t: Tree, tp: Type): Tree def _equals(checker: Tree, binder: Symbol): Tree def _isInstanceOf(b: Symbol, tp: Type): Tree - def and(a: Tree, b: Tree): Tree def drop(tgt: Tree)(n: Int): Tree def index(tgt: Tree)(i: Int): Tree def mkZero(tp: Type): Tree @@ -1443,7 +1439,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL def flatMap(prev: Tree, b: Symbol, next: Tree): Tree def flatMapCond(cond: Tree, res: Tree, nextBinder: Symbol, next: Tree): Tree def flatMapGuard(cond: Tree, next: Tree): Tree - def ifThenElseZero(c: Tree, then: Tree): Tree = IF (c) THEN then ELSE zero + def ifThenElseZero(c: Tree, thenp: Tree): Tree = IF (c) THEN thenp ELSE zero protected def zero: Tree } @@ -1471,12 +1467,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL abstract class CommonCodegen extends AbsCodegen { import CODE._ def fun(arg: Symbol, body: Tree): Tree = Function(List(ValDef(arg)), body) - def genTypeApply(tfun: Tree, args: Type*): Tree = if(args contains NoType) tfun else TypeApply(tfun, args.toList map TypeTree) def tupleSel(binder: Symbol)(i: Int): Tree = (REF(binder) DOT nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder def index(tgt: Tree)(i: Int): Tree = tgt APPLY (LIT(i)) def drop(tgt: Tree)(n: Int): Tree = (tgt DOT vpmName.drop) (LIT(n)) def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya - def and(a: Tree, b: Tree): Tree = a AND b // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree @@ -1484,10 +1478,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp) // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly) - def _asInstanceOf(t: Tree, tp: Type): Tree = if (t.tpe != NoType && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp) def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp) def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false) - // if (typesConform(b.info, tpX)) { patmatDebug("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE } // duplicated out of frustration with cast generation def mkZero(tp: Type): Tree = { @@ -1536,7 +1528,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // __match.zero protected def zero: Tree = _match(vpmName.zero) // __match.guard(`c`, `then`) - def guard(c: Tree, then: Tree): Tree = _match(vpmName.guard) APPLY (c, then) + def guard(c: Tree, thenp: Tree): Tree = _match(vpmName.guard) APPLY (c, thenp) //// methods in the monad instance -- used directly in translation // `prev`.flatMap(`b` => `next`) @@ -1829,9 +1821,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL def toString(x: AnyRef) = if (x eq null) "" else x.toString if (cols.isEmpty || cols.tails.isEmpty) cols map toString else { - val (colStrs, colLens) = cols map {c => val s = toString(c); (s, s.length)} unzip - val maxLen = max(colLens) - val avgLen = colLens.sum/colLens.length + val colLens = cols map (c => toString(c).length) + val maxLen = max(colLens) + val avgLen = colLens.sum/colLens.length val goalLen = maxLen min avgLen*2 def pad(s: String) = { val toAdd = ((goalLen - s.length) max 0) + 2 @@ -2065,7 +2057,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // throws an AnalysisBudget.Exception when the prop results in a CNF that's too big // TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding) def eqFreePropToSolvable(p: Prop): Formula = { - def negationNormalFormNot(p: Prop, budget: Int = AnalysisBudget.max): Prop = + def negationNormalFormNot(p: Prop, budget: Int): Prop = if (budget <= 0) throw AnalysisBudget.exceeded else p match { case And(a, b) => Or(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1)) @@ -2274,9 +2266,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL private[this] val id: Int = Var.nextId // private[this] var canModify: Option[Array[StackTraceElement]] = None - private[this] def ensureCanModify = {} //if (canModify.nonEmpty) patmatDebug("BUG!"+ this +" modified after having been observed: "+ canModify.get.mkString("\n")) + private[this] def ensureCanModify() = {} //if (canModify.nonEmpty) patmatDebug("BUG!"+ this +" modified after having been observed: "+ canModify.get.mkString("\n")) - private[this] def observed = {} //canModify = Some(Thread.currentThread.getStackTrace) + private[this] def observed() = {} //canModify = Some(Thread.currentThread.getStackTrace) // don't access until all potential equalities have been registered using registerEquality private[this] val symForEqualsTo = new scala.collection.mutable.HashMap[Const, Sym] @@ -2429,7 +2421,13 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL private lazy val equalitySyms = {observed; symForEqualsTo.values.toList} // don't call until all equalities have been registered and registerNull has been called (if needed) - def describe = toString + ": " + staticTp + domain.map(_.mkString(" ::= ", " | ", "// "+ symForEqualsTo.keys)).getOrElse(symForEqualsTo.keys.mkString(" ::= ", " | ", " | ...")) + " // = " + path + def describe = { + def domain_s = domain match { + case Some(d) => d mkString (" ::= ", " | ", "// "+ symForEqualsTo.keys) + case _ => symForEqualsTo.keys mkString (" ::= ", " | ", " | ...") + } + s"$this: ${staticTp}${domain_s} // = $path" + } override def toString = "V"+ id } @@ -2515,7 +2513,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // corresponds to a type test that does not imply any value-equality (well, except for outer checks, which we don't model yet) sealed class TypeConst(val tp: Type) extends Const { assert(!(tp =:= NullTp)) - private[this] val id: Int = Const.nextTypeId + /*private[this] val id: Int = */ Const.nextTypeId val wideTp = widenToClass(tp) def isValue = false @@ -2553,7 +2551,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL } val toString = - if (p.hasSymbol && p.symbol.isStable) p.symbol.name.toString // tp.toString + if (p.hasSymbolField && p.symbol.isStable) p.symbol.name.toString // tp.toString else p.toString //+"#"+ id Const.unique(narrowTp, new ValueConst(narrowTp, checkableType(wideTp), toString)) // must make wide type checkable so that it is comparable to types from TypeConst @@ -2563,7 +2561,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const { // patmatDebug("VC"+(tp, wideTp, toString)) assert(!(tp =:= NullTp)) // TODO: assert(!tp.isStable) - private[this] val id: Int = Const.nextValueId + /*private[this] val id: Int = */Const.nextValueId def isValue = true } @@ -2789,7 +2787,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // when does the match fail? val matchFails = Not(\/(symbolicCases)) - val vars = gatherVariables(matchFails) // debug output: patmatDebug("analysing:") @@ -2887,8 +2884,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL v +"(="+ v.path +": "+ v.staticTpCheckable +") "+ assignment }.mkString("\n") - def modelString(model: Model) = varAssignmentString(modelToVarAssignment(model)) - // return constructor call when the model is a true counter example // (the variables don't take into account type information derived from other variables, // so, naively, you might try to construct a counter example like _ :: Nil(_ :: _, _ :: _), @@ -3546,7 +3541,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // for the catch-cases in a try/catch private object typeSwitchMaker extends SwitchMaker { val unchecked = false - def switchableTpe(tp: Type) = true val alternativesSupported = false // TODO: needs either back-end support of flattening of alternatives during typers val canJump = false @@ -3592,11 +3586,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL trait OptimizedCodegen extends CodegenCore with TypedSubstitution with OptimizedMatchMonadInterface { override def codegen: AbsCodegen = optimizedCodegen - // trait AbsOptimizedCodegen extends AbsCodegen { - // def flatMapCondStored(cond: Tree, condSym: Symbol, res: Tree, nextBinder: Symbol, next: Tree): Tree - // } - // def optimizedCodegen: AbsOptimizedCodegen - // when we know we're targetting Option, do some inlining the optimizer won't do // for example, `o.flatMap(f)` becomes `if(o == None) None else f(o.get)`, similarly for orElse and guard // this is a special instance of the advanced inlining optimization that takes a method call on diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index ee7805cb3d..7a7c7c7d25 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -60,23 +60,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans super.transformInfo(sym, tp) } - val toJavaRepeatedParam = new TypeMap { - def apply(tp: Type) = tp match { - case TypeRef(pre, RepeatedParamClass, args) => - typeRef(pre, JavaRepeatedParamClass, args) - case _ => - mapOver(tp) - } - } - - val toScalaRepeatedParam = new TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(pre, JavaRepeatedParamClass, args) => - typeRef(pre, RepeatedParamClass, args) - case _ => - mapOver(tp) - } - } + val toJavaRepeatedParam = new SubstSymMap(RepeatedParamClass -> JavaRepeatedParamClass) + val toScalaRepeatedParam = new SubstSymMap(JavaRepeatedParamClass -> RepeatedParamClass) def accessFlagsToString(sym: Symbol) = flagsToString( sym getFlag (PRIVATE | PROTECTED), @@ -145,7 +130,17 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } } } - if (settings.lint.value) { + + // Check for doomed attempt to overload applyDynamic + if (clazz isSubClass DynamicClass) { + clazz.info member nme.applyDynamic match { + case sym if sym.isOverloaded => unit.error(sym.pos, "implementation restriction: applyDynamic cannot be overloaded") + case _ => + } + } + + // This has become noisy with implicit classes. + if (settings.lint.value && settings.developer.value) { clazz.info.decls filter (x => x.isImplicit && x.typeParams.nonEmpty) foreach { sym => val alts = clazz.info.decl(sym.name).alternatives if (alts.size > 1) @@ -156,27 +151,22 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // Override checking ------------------------------------------------------------ - def isJavaVarargsAncestor(clazz: Symbol) = ( - clazz.isClass - && clazz.isJavaDefined - && (clazz.info.nonPrivateDecls exists isJavaVarArgsMethod) - ) - /** Add bridges for vararg methods that extend Java vararg methods */ def addVarargBridges(clazz: Symbol): List[Tree] = { // This is quite expensive, so attempt to skip it completely. // Insist there at least be a java-defined ancestor which // defines a varargs method. TODO: Find a cheaper way to exclude. - if (clazz.thisType.baseClasses exists isJavaVarargsAncestor) { + if (inheritsJavaVarArgsMethod(clazz)) { log("Found java varargs ancestor in " + clazz.fullLocationString + ".") val self = clazz.thisType val bridges = new ListBuffer[Tree] def varargBridge(member: Symbol, bridgetpe: Type): Tree = { - log("Generating varargs bridge for " + member.fullLocationString + " of type " + bridgetpe) + log(s"Generating varargs bridge for ${member.fullLocationString} of type $bridgetpe") - val bridge = member.cloneSymbolImpl(clazz, member.flags | VBRIDGE) setPos clazz.pos + val newFlags = (member.flags | VBRIDGE | ARTIFACT) & ~PRIVATE + val bridge = member.cloneSymbolImpl(clazz, newFlags) setPos clazz.pos bridge.setInfo(bridgetpe.cloneInfo(bridge)) clazz.info.decls enter bridge @@ -189,26 +179,35 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans localTyper typed DefDef(bridge, body) } - // For all concrete non-private members that have a (Scala) repeated parameter: - // compute the corresponding method type `jtpe` with a Java repeated parameter + // For all concrete non-private members (but: see below) that have a (Scala) repeated + // parameter: compute the corresponding method type `jtpe` with a Java repeated parameter // if a method with type `jtpe` exists and that method is not a varargs bridge // then create a varargs bridge of type `jtpe` that forwards to the // member method with the Scala vararg type. - for (member <- clazz.info.nonPrivateMembers) { + // + // @PP: Can't call nonPrivateMembers because we will miss refinement members, + // which have been marked private. See SI-4729. + for (member <- nonTrivialMembers(clazz)) { + log(s"Considering $member for java varargs bridge in $clazz") if (!member.isDeferred && member.isMethod && hasRepeatedParam(member.info)) { val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) + // Delaying calling memberType as long as possible if (inherited ne NoSymbol) { - val jtpe = toJavaRepeatedParam(self.memberType(member)) + val jtpe = toJavaRepeatedParam(self memberType member) // this is a bit tortuous: we look for non-private members or bridges // if we find a bridge everything is OK. If we find another member, // we need to create a bridge - if (inherited filter (sym => (self.memberType(sym) matches jtpe) && !(sym hasFlag VBRIDGE)) exists) + val inherited1 = inherited filter (sym => !(sym hasFlag VBRIDGE) && (self memberType sym matches jtpe)) + if (inherited1.exists) bridges += varargBridge(member, jtpe) } } } + if (bridges.size > 0) + log(s"Adding ${bridges.size} bridges for methods extending java varargs.") + bridges.toList } else Nil @@ -248,7 +247,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case class MixinOverrideError(member: Symbol, msg: String) - var mixinOverrideErrors = new ListBuffer[MixinOverrideError]() + val mixinOverrideErrors = new ListBuffer[MixinOverrideError]() def printMixinOverrideErrors() { mixinOverrideErrors.toList match { @@ -556,13 +555,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) - afterErasure(tp1 matches tp2) + exitingErasure(tp1 matches tp2) }) def ignoreDeferred(member: Symbol) = ( (member.isAbstractType && !member.isFBounded) || ( member.isJavaDefined && - // the test requires afterErasure so shouldn't be + // the test requires exitingErasure so shouldn't be // done if the compiler has no erasure phase available (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol) ) @@ -845,7 +844,6 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // Variance Checking -------------------------------------------------------- - private val ContraVariance = -1 private val NoVariance = 0 private val CoVariance = 1 private val AnyVariance = 2 @@ -905,13 +903,14 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans * the type occurs itself at variance position given by `variance` */ def validateVariance(tp: Type, variance: Int): Unit = tp match { - case ErrorType => ; - case WildcardType => ; - case NoType => ; - case NoPrefix => ; - case ThisType(_) => ; - case ConstantType(_) => ; - // case DeBruijnIndex(_, _) => ; + case ErrorType => + case WildcardType => + case BoundedWildcardType(bounds) => + validateVariance(bounds, variance) + case NoType => + case NoPrefix => + case ThisType(_) => + case ConstantType(_) => case SingleType(pre, sym) => validateVariance(pre, variance) case TypeRef(pre, sym, args) => @@ -1062,6 +1061,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def apply(tp: Type) = mapOver(tp).normalize } + def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.lint.value) (fn, args) match { + case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == Option_apply => + unit.warning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.") // SI-6567 + case _ => + } + def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 => def isReferenceOp = name == nme.eq || name == nme.ne @@ -1118,8 +1123,6 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def isMaybeAnyValue(s: Symbol) = isPrimitiveValueClass(unboxedValueClass(s)) || isMaybeValue(s) // used to short-circuit unrelatedTypes check if both sides are special def isSpecial(s: Symbol) = isMaybeAnyValue(s) || isAnyNumber(s) - // unused - def possibleNumericCount = onSyms(_ filter (x => isNumeric(x) || isMaybeValue(x)) size) val nullCount = onSyms(_ filter (_ == NullClass) size) def nonSensibleWarning(what: String, alwaysEqual: Boolean) = { @@ -1230,7 +1233,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans /* Convert a reference to a case factory of type `tpe` to a new of the class it produces. */ def toConstructor(pos: Position, tpe: Type): Tree = { - var rtpe = tpe.finalResultType + val rtpe = tpe.finalResultType assert(rtpe.typeSymbol hasFlag CASE, tpe); localTyper.typedOperator { atPos(pos) { @@ -1272,7 +1275,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case vsym => ValDef(vsym) } } - def createStaticModuleAccessor() = afterRefchecks { + def createStaticModuleAccessor() = exitingRefchecks { val method = ( sym.owner.newMethod(sym.name.toTermName, sym.pos, (sym.flags | STABLE) & ~MODULE) setInfoAndEnter NullaryMethodType(sym.moduleClass.tpe) @@ -1283,7 +1286,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans vdef, localTyper.typedPos(tree.pos) { val vsym = vdef.symbol - afterRefchecks { + exitingRefchecks { val rhs = gen.newModule(sym, vsym.tpe) val body = if (sym.owner.isTrait) rhs else gen.mkAssignAndReturn(vsym, rhs) DefDef(sym, body.changeOwner(vsym -> sym)) @@ -1311,7 +1314,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } case ModuleDef(_, _, _) => eliminateModuleDefs(tree) case ValDef(_, _, _, _) => - val tree1 @ ValDef(_, _, _, rhs) = transform(tree) // important to do before forward reference check + val tree1 = transform(tree) // important to do before forward reference check if (tree1.symbol.isLazy) tree1 :: Nil else { val lazySym = tree.symbol.lazyAccessorOrSelf @@ -1465,8 +1468,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } private def isRepeatedParamArg(tree: Tree) = currentApplication match { case Apply(fn, args) => - !args.isEmpty && (args.last eq tree) && - fn.tpe.params.length == args.length && isRepeatedParamType(fn.tpe.params.last.tpe) + ( args.nonEmpty + && (args.last eq tree) + && (fn.tpe.params.length == args.length) + && isRepeatedParamType(fn.tpe.params.last.tpe) + ) case _ => false } @@ -1555,12 +1561,15 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case Apply(fn, args) => // sensicality should be subsumed by the unreachability/exhaustivity/irrefutability analyses in the pattern matcher - if (!inPattern) checkSensible(tree.pos, fn, args) + if (!inPattern) { + checkImplicitViewOptionApply(tree.pos, fn, args) + checkSensible(tree.pos, fn, args) + } currentApplication = tree tree } private def transformSelect(tree: Select): Tree = { - val Select(qual, name) = tree + val Select(qual, _) = tree val sym = tree.symbol /** Note: if a symbol has both @deprecated and @migration annotations and both diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index c9e45b6348..5fb9a5e67e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -60,8 +60,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val clazz = qual.symbol val supername = nme.superName(name) val superAcc = clazz.info.decl(supername).suchThat(_.alias == sym) orElse { - debuglog("add super acc " + sym + sym.locationString + " to `" + clazz);//debug - val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE) setAlias sym + debuglog(s"add super acc ${sym.fullLocationString} to $clazz") + val acc = clazz.newMethod(supername, sel.pos, SUPERACCESSOR | PRIVATE | ARTIFACT) setAlias sym val tpe = clazz.thisType memberType sym match { case t if sym.isModule && !sym.isMethod => NullaryMethodType(t) case t => t @@ -291,7 +291,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT && !sym.owner.isTrait && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) && (qual.symbol.info.member(sym.name) ne NoSymbol) - && !needsProtectedAccessor(sym, tree.pos)) + && !needsProtectedAccessor(sym, tree.pos) + ) if (shouldEnsureAccessor) { log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass) ensureAccessor(sel) @@ -387,7 +388,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT * typed. */ private def makeAccessor(tree: Select, targs: List[Tree]): Tree = { - val Select(qual, name) = tree + val Select(qual, _) = tree val sym = tree.symbol val clazz = hostForAccessorOf(sym, currentClass) @@ -412,7 +413,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT } val protAcc = clazz.info.decl(accName).suchThat(s => s == NoSymbol || s.tpe =:= accType(s)) orElse { - val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos) + val newAcc = clazz.newMethod(nme.protName(sym.originalName), tree.pos, newFlags = ARTIFACT) newAcc setInfoAndEnter accType(newAcc) val code = DefDef(newAcc, { @@ -423,7 +424,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT args.foldLeft(base)(Apply(_, _)) }) - debuglog("" + code) + debuglog("created protected accessor: " + code) storeAccessorDefinition(clazz, code) newAcc } @@ -435,7 +436,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case _ => mkApply(TypeApply(selection, targs)) } } - debuglog("Replaced " + tree + " with " + res) + debuglog(s"Replaced $tree with $res") if (hasArgs) localTyper.typedOperator(res) else localTyper.typed(res) } @@ -474,7 +475,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val accName = nme.protSetterName(field.originalName) val protectedAccessor = clazz.info decl accName orElse { - val protAcc = clazz.newMethod(accName, field.pos) + val protAcc = clazz.newMethod(accName, field.pos, newFlags = ARTIFACT) val paramTypes = List(clazz.typeOfThis, field.tpe) val params = protAcc newSyntheticValueParams paramTypes val accessorType = MethodType(params, UnitClass.tpe) @@ -506,9 +507,6 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT def accessibleThroughSubclassing = validCurrentOwner && clazz.thisSym.isSubClass(sym.owner) && !clazz.isTrait - def packageAccessBoundry(sym: Symbol) = - sym.accessBoundary(sym.enclosingPackageClass) - val isCandidate = ( sym.isProtected && sym.isJavaDefined diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 17e67e6429..07135c3af9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -6,9 +6,7 @@ package scala.tools.nsc package typechecker -import symtab.Flags import symtab.Flags._ -import scala.collection.mutable import scala.collection.mutable.ListBuffer /** Synthetic method implementations for case classes and case objects. @@ -97,7 +95,7 @@ trait SyntheticMethods extends ast.TreeDSL { // like Tags and Arrays which are not robust and infer things // which they shouldn't. val accessorLub = ( - if (opt.experimental) { + if (settings.Xexperimental.value) { global.weakLub(accessors map (_.tpe.finalResultType))._1 match { case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents) case tp => tp @@ -124,20 +122,11 @@ trait SyntheticMethods extends ast.TreeDSL { (m0 ne meth) && !m0.isDeferred && !m0.isSynthetic && (m0.owner != AnyValClass) && (typeInClazz(m0) matches typeInClazz(meth)) } } - def readConstantValue[T](name: String, default: T = null.asInstanceOf[T]): T = { - clazzMember(newTermName(name)).info match { - case NullaryMethodType(ConstantType(Constant(value))) => value.asInstanceOf[T] - case _ => default - } - } def productIteratorMethod = { createMethod(nme.productIterator, iteratorOfType(accessorLub))(_ => gen.mkMethodCall(ScalaRunTimeModule, nme.typedProductIterator, List(accessorLub), List(mkThis)) ) } - def projectionMethod(accessor: Symbol, num: Int) = { - createMethod(nme.productAccessorName(num), accessor.tpe.resultType)(_ => REF(accessor)) - } /** Common code for productElement and (currently disabled) productElementName */ @@ -229,10 +218,15 @@ trait SyntheticMethods extends ast.TreeDSL { /** The _1, _2, etc. methods to implement ProductN, disabled * until we figure out how to introduce ProductN without cycles. */ - def productNMethods = { + /**** + def productNMethods = { val accs = accessors.toIndexedSeq 1 to arity map (num => productProj(arity, num) -> (() => projectionMethod(accs(num - 1), num))) } + def projectionMethod(accessor: Symbol, num: Int) = { + createMethod(nme.productAccessorName(num), accessor.tpe.resultType)(_ => REF(accessor)) + } + ****/ // methods for both classes and objects def productMethods = { @@ -370,7 +364,6 @@ trait SyntheticMethods extends ast.TreeDSL { def isRewrite(sym: Symbol) = sym.isCaseAccessorMethod && !sym.isPublic for (ddef @ DefDef(_, _, _, _, _, _) <- templ.body ; if isRewrite(ddef.symbol)) { - val original = ddef.symbol val newAcc = deriveMethod(ddef.symbol, name => context.unit.freshTermName(name + "$")) { newAcc => newAcc.makePublic newAcc resetFlag (ACCESSOR | PARAMACCESSOR) diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index d82fbd7c77..45aa1bcbdb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -10,7 +10,7 @@ trait Tags { trait Tag { self: Typer => - private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = beforeTyper { + private def resolveTag(pos: Position, taggedTp: Type, allowMaterialization: Boolean) = enteringTyper { def wrapper (tree: => Tree): Tree = if (allowMaterialization) (context.withMacrosEnabled[Tree](tree)) else (context.withMacrosDisabled[Tree](tree)) wrapper(inferImplicit( EmptyTree, diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index b4cdad70e2..be7554abe2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package typechecker -import scala.tools.nsc.symtab.Flags._ import scala.collection.mutable import mutable.ListBuffer import util.returning @@ -143,13 +142,6 @@ abstract class TreeCheckers extends Analyzer { currentRun.units foreach (x => wrap(x)(check(x))) } - def printingTypings[T](body: => T): T = { - val saved = global.printTypings - global.printTypings = true - val result = body - global.printTypings = saved - result - } def runWithUnit[T](unit: CompilationUnit)(body: => Unit): Unit = { val unit0 = currentUnit currentRun.currentUnit = unit @@ -186,10 +178,6 @@ abstract class TreeCheckers extends Analyzer { errorFn(t1.pos, "trees differ\n old: " + treestr(t1) + "\n new: " + treestr(t2)) private def typesDiffer(tree: Tree, tp1: Type, tp2: Type) = errorFn(tree.pos, "types differ\n old: " + tp1 + "\n new: " + tp2 + "\n tree: " + tree) - private def ownersDiffer(tree: Tree, shouldBe: Symbol) = { - val sym = tree.symbol - errorFn(tree.pos, sym + " has wrong owner: " + ownerstr(sym.owner) + ", should be: " + ownerstr(shouldBe)) - } /** XXX Disabled reporting of position errors until there is less noise. */ private def noPos(t: Tree) = @@ -278,7 +266,7 @@ abstract class TreeCheckers extends Analyzer { def cond(s: Symbol) = !s.isTerm || s.isMethod || s == sym.owner if (sym.owner != currentOwner) { - val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse fail("DefTree can't find owner: ") + val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse { fail("DefTree can't find owner: ") ; NoSymbol } if (sym.owner != expected) fail("""| | currentOwner chain: %s diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 4233bde770..19f0b56e94 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -8,7 +8,6 @@ package typechecker import scala.collection.mutable import scala.collection.mutable.ListBuffer -import scala.util.control.ControlThrowable import scala.util.control.Exception.ultimately import symtab.Flags._ import PartialFunction._ @@ -37,15 +36,6 @@ trait TypeDiagnostics { import global._ import definitions._ - import global.typer.{ infer, context } - - /** The common situation of making sure nothing is erroneous could be - * nicer if Symbols, Types, and Trees all implemented some common interface - * in which isErroneous and similar would be placed. - */ - def noErroneousTypes(tps: Type*) = tps forall (x => !x.isErroneous) - def noErroneousSyms(syms: Symbol*) = syms forall (x => !x.isErroneous) - def noErroneousTrees(trees: Tree*) = trees forall (x => !x.isErroneous) /** For errors which are artifacts of the implementation: such messages * indicate that the restriction may be lifted in the future. @@ -58,7 +48,7 @@ trait TypeDiagnostics { /** A map of Positions to addendums - if an error involves a position in * the map, the addendum should also be printed. */ - private var addendums = perRunCaches.newMap[Position, () => String]() + private val addendums = perRunCaches.newMap[Position, () => String]() private var isTyperInPattern = false /** Devising new ways of communicating error info out of @@ -296,7 +286,6 @@ trait TypeDiagnostics { // distinguished from the other types in the same error message private val savedName = sym.name def restoreName() = sym.name = savedName - def isAltered = sym.name != savedName def modifyName(f: String => String) = sym setName newTypeName(f(sym.name.toString)) /** Prepend java.lang, scala., or Predef. if this type originated @@ -426,6 +415,120 @@ trait TypeDiagnostics { def permanentlyHiddenWarning(pos: Position, hidden: Name, defn: Symbol) = contextWarning(pos, "imported `%s' is permanently hidden by definition of %s".format(hidden, defn.fullLocationString)) + object checkUnused { + val ignoreNames = Set[TermName]("readResolve", "readObject", "writeObject", "writeReplace") + + class UnusedPrivates extends Traverser { + val defnTrees = ListBuffer[MemberDef]() + val targets = mutable.Set[Symbol]() + val setVars = mutable.Set[Symbol]() + val treeTypes = mutable.Set[Type]() + + def defnSymbols = defnTrees.toList map (_.symbol) + def localVars = defnSymbols filter (t => t.isLocal && t.isVar) + + def qualifiesTerm(sym: Symbol) = ( + (sym.isModule || sym.isMethod || sym.isPrivateLocal || sym.isLocal) + && !nme.isLocalName(sym.name) + && !sym.isParameter + && !sym.isParamAccessor // could improve this, but it's a pain + && !sym.isEarlyInitialized // lots of false positives in the way these are encoded + && !(sym.isGetter && sym.accessed.isEarlyInitialized) + ) + def qualifiesType(sym: Symbol) = !sym.isDefinedInPackage + def qualifies(sym: Symbol) = ( + (sym ne null) + && (sym.isTerm && qualifiesTerm(sym) || sym.isType && qualifiesType(sym)) + ) + + override def traverse(t: Tree): Unit = { + t match { + case t: MemberDef if qualifies(t.symbol) => defnTrees += t + case t: RefTree if t.symbol ne null => targets += t.symbol + case Assign(lhs, _) if lhs.symbol != null => setVars += lhs.symbol + case _ => + } + // Only record type references which don't originate within the + // definition of the class being referenced. + if (t.tpe ne null) { + for (tp <- t.tpe ; if !treeTypes(tp) && !currentOwner.ownerChain.contains(tp.typeSymbol)) { + tp match { + case NoType | NoPrefix => + case NullaryMethodType(_) => + case MethodType(_, _) => + case _ => + log(s"$tp referenced from $currentOwner") + treeTypes += tp + } + } + // e.g. val a = new Foo ; new a.Bar ; don't let a be reported as unused. + t.tpe.prefix foreach { + case SingleType(_, sym) => targets += sym + case _ => + } + } + super.traverse(t) + } + def isUnusedType(m: Symbol): Boolean = ( + m.isType + && !m.isTypeParameterOrSkolem // would be nice to improve this + && (m.isPrivate || m.isLocal) + && !(treeTypes.exists(tp => tp exists (t => t.typeSymbolDirect == m))) + ) + def isUnusedTerm(m: Symbol): Boolean = ( + (m.isTerm) + && (m.isPrivate || m.isLocal) + && !targets(m) + && !(m.name == nme.WILDCARD) // e.g. val _ = foo + && !ignoreNames(m.name) // serialization methods + && !isConstantType(m.info.resultType) // subject to constant inlining + && !treeTypes.exists(_ contains m) // e.g. val a = new Foo ; new a.Bar + ) + def unusedTypes = defnTrees.toList filter (t => isUnusedType(t.symbol)) + def unusedTerms = defnTrees.toList filter (v => isUnusedTerm(v.symbol)) + // local vars which are never set, except those already returned in unused + def unsetVars = localVars filter (v => !setVars(v) && !isUnusedTerm(v)) + } + + def apply(unit: CompilationUnit) = { + val p = new UnusedPrivates + p traverse unit.body + val unused = p.unusedTerms + unused foreach { defn: DefTree => + val sym = defn.symbol + val isDefaultGetter = sym.name containsName nme.DEFAULT_GETTER_STRING + val pos = ( + if (defn.pos.isDefined) defn.pos + else if (sym.pos.isDefined) sym.pos + else sym match { + case sym: TermSymbol => sym.referenced.pos + case _ => NoPosition + } + ) + val why = if (sym.isPrivate) "private" else "local" + val what = ( + if (isDefaultGetter) "default argument" + else if (sym.isConstructor) "constructor" + else if (sym.isVar || sym.isGetter && sym.accessed.isVar) "var" + else if (sym.isVal || sym.isGetter && sym.accessed.isVal) "val" + else if (sym.isSetter) "setter" + else if (sym.isMethod) "method" + else if (sym.isModule) "object" + else "term" + ) + unit.warning(pos, s"$why $what in ${sym.owner} is never used") + } + p.unsetVars foreach { v => + unit.warning(v.pos, s"local var ${v.name} in ${v.owner} is never set - it could be a val") + } + p.unusedTypes foreach { t => + val sym = t.symbol + val why = if (sym.isPrivate) "private" else "local" + unit.warning(t.pos, s"$why ${sym.fullLocationString} is never used") + } + } + } + object checkDead { private var expr: Symbol = NoSymbol diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a2aca45e8f..42c7d4a6b8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -53,22 +53,25 @@ trait Typers extends Modes with Adaptations with Tags { object UnTyper extends Traverser { override def traverse(tree: Tree) = { if (tree != EmptyTree) tree.tpe = null - if (tree.hasSymbol) tree.symbol = NoSymbol + if (tree.hasSymbolField) tree.symbol = NoSymbol super.traverse(tree) } } -/* needed for experimental version where early types can be type arguments - class EarlyMap(clazz: Symbol) extends TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(NoPrefix, sym, List()) if (sym hasFlag PRESUPER) => - TypeRef(ThisType(clazz), sym, List()) - case _ => - mapOver(tp) + + sealed abstract class SilentResult[+T] { + @inline final def map[U](f: T => U): SilentResult[U] = this match { + case SilentResultValue(value) => SilentResultValue(f(value)) + case x: SilentTypeError => x + } + @inline final def filter(p: T => Boolean): SilentResult[T] = this match { + case SilentResultValue(value) if !p(value) => SilentTypeError(TypeErrorWrapper(new TypeError(NoPosition, "!p"))) + case _ => this + } + @inline final def orElse[T1 >: T](f: AbsTypeError => T1): T1 = this match { + case SilentResultValue(value) => value + case SilentTypeError(err) => f(err) } } -*/ - - sealed abstract class SilentResult[+T] case class SilentTypeError(err: AbsTypeError) extends SilentResult[Nothing] { } case class SilentResultValue[+T](value: T) extends SilentResult[T] { } @@ -91,7 +94,7 @@ trait Typers extends Modes with Adaptations with Tags { // - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope) // - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction // this is disabled by: -Xoldpatmat or interactive compilation (we run it for scaladoc due to SI-5933) - private def newPatternMatching = opt.virtPatmat && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) + private def newPatternMatching = !settings.XoldPatmat.value && !forInteractive //&& !forScaladoc && (phase.id < currentRun.uncurryPhase.id) abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tag with TyperContextErrors { import context0.unit @@ -194,7 +197,7 @@ trait Typers extends Modes with Adaptations with Tags { case PolyType(_, _) => EmptyTree case _ => def wrapImplicit(from: Type): Tree = { - val result = inferImplicit(tree, functionType(from :: Nil, to), reportAmbiguous, true, context, saveErrors) + val result = inferImplicit(tree, functionType(from.withoutAnnotations :: Nil, to), reportAmbiguous, true, context, saveErrors) if (result.subst != EmptyTreeTypeSubstituter) { result.subst traverse tree notifyUndetparamsInferred(result.subst.from, result.subst.to) @@ -227,10 +230,7 @@ trait Typers extends Modes with Adaptations with Tags { case _ => tp } - /** Check that <code>tree</code> is a stable expression. - * - * @param tree ... - * @return ... + /** Check that `tree` is a stable expression. */ def checkStable(tree: Tree): Tree = ( if (treeInfo.isExprSafeToInline(tree)) tree @@ -242,7 +242,7 @@ trait Typers extends Modes with Adaptations with Tags { * of its symbol was not volatile? */ protected def isStableExceptVolatile(tree: Tree) = { - tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile && + tree.hasSymbolField && tree.symbol != NoSymbol && tree.tpe.isVolatile && { val savedTpe = tree.symbol.info val savedSTABLE = tree.symbol getFlag STABLE tree.symbol setInfo AnyRefClass.tpe @@ -284,16 +284,11 @@ trait Typers extends Modes with Adaptations with Tags { ) } - /** Check that type <code>tp</code> is not a subtype of itself. - * - * @param pos ... - * @param tp ... - * @return <code>true</code> if <code>tp</code> is not a subtype of itself. + /** Check that type `tp` is not a subtype of itself. */ def checkNonCyclic(pos: Position, tp: Type): Boolean = { def checkNotLocked(sym: Symbol) = { - sym.initialize - sym.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false } + sym.initialize.lockOK || { CyclicAliasingOrSubtypingError(pos, sym); false } } tp match { case TypeRef(pre, sym, args) => @@ -304,12 +299,6 @@ trait Typers extends Modes with Adaptations with Tags { case SingleType(pre, sym) => checkNotLocked(sym) -/* - case TypeBounds(lo, hi) => - var ok = true - for (t <- lo) ok = ok & checkNonCyclic(pos, t) - ok -*/ case st: SubType => checkNonCyclic(pos, st.supertype) case ct: CompoundType => @@ -320,14 +309,14 @@ trait Typers extends Modes with Adaptations with Tags { } def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Boolean = try { - if (!lockedSym.lock(CyclicReferenceError(pos, lockedSym))) false + if (!lockedSym.lock(CyclicReferenceError(pos, tp, lockedSym))) false else checkNonCyclic(pos, tp) } finally { lockedSym.unlock() } def checkNonCyclic(sym: Symbol) { - if (!checkNonCyclic(sym.pos, sym.tpe)) sym.setInfo(ErrorType) + if (!checkNonCyclic(sym.pos, sym.tpe_*)) sym.setInfo(ErrorType) } def checkNonCyclic(defn: Tree, tpt: Tree) { @@ -363,28 +352,13 @@ trait Typers extends Modes with Adaptations with Tags { private var scope: Scope = _ private var hiddenSymbols: List[Symbol] = _ - /** Check that type <code>tree</code> does not refer to private + /** Check that type `tree` does not refer to private * components unless itself is wrapped in something private - * (<code>owner</code> tells where the type occurs). - * - * @param owner ... - * @param tree ... - * @return ... + * (`owner` tells where the type occurs). */ def privates[T <: Tree](owner: Symbol, tree: T): T = check(owner, EmptyScope, WildcardType, tree) - /** Check that type <code>tree</code> does not refer to entities - * defined in scope <code>scope</code>. - * - * @param scope ... - * @param pt ... - * @param tree ... - * @return ... - */ - def locals[T <: Tree](scope: Scope, pt: Type, tree: T): T = - check(NoSymbol, scope, pt, tree) - private def check[T <: Tree](owner: Symbol, scope: Scope, pt: Type, tree: T): T = { this.owner = owner this.scope = scope @@ -460,7 +434,7 @@ trait Typers extends Modes with Adaptations with Tags { } /** The qualifying class - * of a this or super with prefix <code>qual</code>. + * of a this or super with prefix `qual`. * packageOk is equal false when qualifying class symbol */ def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean) = @@ -546,7 +520,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - /** Does the context of tree <code>tree</code> require a stable type? + /** Does the context of tree `tree` require a stable type? */ private def isStableContext(tree: Tree, mode: Int, pt: Type) = isNarrowable(tree.tpe) && ((mode & (EXPRmode | LHSmode)) == EXPRmode) && @@ -565,11 +539,13 @@ trait Typers extends Modes with Adaptations with Tags { * @return modified tree and new prefix type */ private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): (Tree, Type) = - if (isInPackageObject(sym, pre.typeSymbol)) { + if (context.isInPackageObject(sym, pre.typeSymbol)) { if (pre.typeSymbol == ScalaPackageClass && sym.isTerm) { // short cut some aliases. It seems pattern matching needs this // to notice exhaustiveness and to generate good code when // List extractors are mixed with :: patterns. See Test5 in lists.scala. + // + // TODO SI-6609 Eliminate this special case once the old pattern matcher is removed. def dealias(sym: Symbol) = (atPos(tree.pos.makeTransparent) {gen.mkAttributedRef(sym)} setPos tree.pos, sym.owner.thisType) sym.name match { @@ -598,26 +574,6 @@ trait Typers extends Modes with Adaptations with Tags { (checkAccessible(tree, sym, pre, site), pre) } - /** Is `sym` defined in package object of package `pkg`? - */ - private def isInPackageObject(sym: Symbol, pkg: Symbol) = { - def isInPkgObj(sym: Symbol) = - !sym.owner.isPackage && { - sym.owner.isPackageObjectClass && - sym.owner.owner == pkg || - pkg.isInitialized && { - // need to be careful here to not get a cyclic reference during bootstrap - val pkgobj = pkg.info.member(nme.PACKAGEkw) - pkgobj.isInitialized && - (pkgobj.info.member(sym.name).alternatives contains sym) - } - } - pkg.isPackageClass && { - if (sym.isOverloaded) sym.alternatives forall isInPkgObj - else isInPkgObj(sym) - } - } - /** Post-process an identifier or selection node, performing the following: * 1. Check that non-function pattern expressions are stable * 2. Check that packages and static modules are not used as values @@ -632,7 +588,7 @@ trait Typers extends Modes with Adaptations with Tags { def fail() = NotAValueError(tree, sym) if (tree.isErrorTyped) tree - else if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) { // (1) + else if (inPatternNotFunMode(mode) && tree.isTerm) { // (1) if (sym.isValue) { val tree1 = checkStable(tree) // A module reference in a pattern has type Foo.type, not "object Foo" @@ -666,12 +622,6 @@ trait Typers extends Modes with Adaptations with Tags { case _ => !phase.erasedTypes } - /** - * @param tree ... - * @param mode ... - * @param pt ... - * @return ... - */ def stabilizeFun(tree: Tree, mode: Int, pt: Type): Tree = { val sym = tree.symbol val pre = tree match { @@ -847,26 +797,27 @@ trait Typers extends Modes with Adaptations with Tags { // avoid throwing spurious DivergentImplicit errors if (context.hasErrors) - return setError(tree) - - withCondConstrTyper(treeInfo.isSelfOrSuperConstrCall(tree)){ typer1 => - if (original != EmptyTree && pt != WildcardType) - typer1.silent(tpr => { - val withImplicitArgs = tpr.applyImplicitArgs(tree) - if (tpr.context.hasErrors) tree // silent will wrap it in SilentTypeError anyway - else tpr.typed(withImplicitArgs, mode, pt) - }) match { - case SilentResultValue(result) => - result - case _ => + setError(tree) + else + withCondConstrTyper(treeInfo.isSelfOrSuperConstrCall(tree))(typer1 => + if (original != EmptyTree && pt != WildcardType) ( + typer1 silent { tpr => + val withImplicitArgs = tpr.applyImplicitArgs(tree) + if (tpr.context.hasErrors) tree // silent will wrap it in SilentTypeError anyway + else tpr.typed(withImplicitArgs, mode, pt) + } + orElse { _ => debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original)) val tree1 = typed(resetAllAttrs(original), mode, WildcardType) + // Q: `typed` already calls `addAnnotations` and `adapt`. the only difference here is that + // we pass `EmptyTree` as the `original`. intended? added in 2009 (53d98e7d42) by martin. tree1.tpe = addAnnotations(tree1, tree1.tpe) if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, EmptyTree) - } - else - typer1.typed(typer1.applyImplicitArgs(tree), mode, pt) - } + } + ) + else + typer1.typed(typer1.applyImplicitArgs(tree), mode, pt) + ) } def instantiateToMethodType(mt: MethodType): Tree = { @@ -879,7 +830,6 @@ trait Typers extends Modes with Adaptations with Tags { debuglog("eta-expanding " + tree + ":" + tree.tpe + " to " + pt) checkParamsConvertible(tree, tree.tpe) val tree0 = etaExpand(context.unit, tree, this) - // println("eta "+tree+" ---> "+tree0+":"+tree0.tpe+" undet: "+context.undetparams+ " mode: "+Integer.toHexString(mode)) if (context.undetparams.nonEmpty) { // #2624: need to infer type arguments for eta expansion of a polymorphic method @@ -907,7 +857,7 @@ trait Typers extends Modes with Adaptations with Tags { // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else // tree setType tree.tpe.normalize tree - } else if (tree.hasSymbol && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) && + } else if (tree.hasSymbolField && !tree.symbol.typeParams.isEmpty && !inHKMode(mode) && !(tree.symbol.isJavaDefined && context.unit.isJava)) { // (7) // @M When not typing a higher-kinded type ((mode & HKmode) == 0) // or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *, @@ -915,7 +865,7 @@ trait Typers extends Modes with Adaptations with Tags { // @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't? MissingTypeParametersError(tree) } else if ( // (7.1) @M: check kind-arity - // @M: removed check for tree.hasSymbol and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol) + // @M: removed check for tree.hasSymbolField and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol) (inHKMode(mode)) && // @M: don't check tree.tpe.symbol.typeParams. check tree.tpe.typeParams!!! // (e.g., m[Int] --> tree.tpe.symbol.typeParams.length == 1, tree.tpe.typeParams.length == 0!) @@ -965,9 +915,11 @@ trait Typers extends Modes with Adaptations with Tags { def adaptConstrPattern(): Tree = { // (5) def hasUnapplyMember(tp: Type) = reallyExists(unapplyMember(tp)) val overloadedExtractorOfObject = tree.symbol filter (sym => hasUnapplyMember(sym.tpe)) - // if the tree's symbol's type does not define an extractor, maybe the tree's type does - // this is the case when we encounter an arbitrary tree as the target of an unapply call (rather than something that looks like a constructor call) - // (for now, this only happens due to wrapClassTagUnapply, but when we support parameterized extractors, it will become more common place) + // if the tree's symbol's type does not define an extractor, maybe the tree's type does. + // this is the case when we encounter an arbitrary tree as the target of an unapply call + // (rather than something that looks like a constructor call.) (for now, this only happens + // due to wrapClassTagUnapply, but when we support parameterized extractors, it will become + // more common place) val extractor = overloadedExtractorOfObject orElse unapplyMember(tree.tpe) if (extractor != NoSymbol) { // if we did some ad-hoc overloading resolution, update the tree's symbol @@ -1037,15 +989,21 @@ trait Typers extends Modes with Adaptations with Tags { def insertApply(): Tree = { assert(!inHKMode(mode), modeString(mode)) //@M - val qual = adaptToName(tree, nme.apply) match { - case id @ Ident(_) => - val pre = if (id.symbol.owner.isPackageClass) id.symbol.owner.thisType - else if (id.symbol.owner.isClass) - context.enclosingSubClassContext(id.symbol.owner).prefix - else NoPrefix - stabilize(id, pre, EXPRmode | QUALmode, WildcardType) - case sel @ Select(qualqual, _) => - stabilize(sel, qualqual.tpe, EXPRmode | QUALmode, WildcardType) + val adapted = adaptToName(tree, nme.apply) + def stabilize0(pre: Type): Tree = stabilize(adapted, pre, EXPRmode | QUALmode, WildcardType) + // TODO reconcile the overlap between Typers#stablize and TreeGen.stabilize + val qual = adapted match { + case This(_) => + gen.stabilize(adapted) + case Ident(_) => + val owner = adapted.symbol.owner + val pre = + if (owner.isPackageClass) owner.thisType + else if (owner.isClass) context.enclosingSubClassContext(owner).prefix + else NoPrefix + stabilize0(pre) + case Select(qualqual, _) => + stabilize0(qualqual.tpe) case other => other } @@ -1120,7 +1078,7 @@ trait Typers extends Modes with Adaptations with Tags { tree.symbol != null && tree.symbol.isTermMacro && // of a macro !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined) macroExpand(this, tree, mode, pt) - else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) + else if (inAllModes(mode, PATTERNmode | FUNmode)) adaptConstrPattern() else if (shouldInsertApply(tree)) insertApply() @@ -1200,9 +1158,9 @@ trait Typers extends Modes with Adaptations with Tags { val found = tree.tpe if (!found.isErroneous && !pt.isErroneous) { if ((!context.reportErrors && isPastTyper) || tree.attachments.get[MacroExpansionAttachment].isDefined) { - val (bound, req) = pt match { - case ExistentialType(qs, tpe) => (qs, tpe) - case _ => (Nil, pt) + val bound = pt match { + case ExistentialType(qs, _) => qs + case _ => Nil } val boundOrSkolems = bound ++ pt.skolemsExceptMethodTypeParams if (boundOrSkolems.nonEmpty) { @@ -1268,12 +1226,10 @@ trait Typers extends Modes with Adaptations with Tags { */ def instantiateExpectingUnit(tree: Tree, mode: Int): Tree = { val savedUndetparams = context.undetparams - silent(_.instantiate(tree, mode, UnitClass.tpe)) match { - case SilentResultValue(t) => t - case _ => - context.undetparams = savedUndetparams - val valueDiscard = atPos(tree.pos)(Block(List(instantiate(tree, mode, WildcardType)), Literal(Constant()))) - typed(valueDiscard, mode, UnitClass.tpe) + silent(_.instantiate(tree, mode, UnitClass.tpe)) orElse { _ => + context.undetparams = savedUndetparams + val valueDiscard = atPos(tree.pos)(Block(List(instantiate(tree, mode, WildcardType)), Literal(Constant()))) + typed(valueDiscard, mode, UnitClass.tpe) } } @@ -1330,16 +1286,12 @@ trait Typers extends Modes with Adaptations with Tags { def doAdapt(restpe: Type) = //util.trace("adaptToArgs "+qual+", name = "+name+", argtpes = "+(args map (_.tpe))+", pt = "+pt+" = ") adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), restpe), reportAmbiguous, saveErrors) - if (pt != WildcardType) { - silent(_ => doAdapt(pt)) match { - case SilentResultValue(result) if result != qual => - result - case _ => - debuglog("fallback on implicits in adaptToArguments: "+qual+" . "+name) - doAdapt(WildcardType) - } - } else + + if (pt == WildcardType) doAdapt(pt) + else silent(_ => doAdapt(pt)) filter (_ != qual) orElse (_ => + logResult(s"fallback on implicits in adaptToArguments: $qual.$name")(doAdapt(WildcardType)) + ) } /** Try to apply an implicit conversion to `qual` so that it contains @@ -1347,27 +1299,24 @@ trait Typers extends Modes with Adaptations with Tags { * account using `adaptToArguments`. */ def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = { - def onError(reportError: => Tree): Tree = { - context.tree match { - case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => - silent(_.typedArgs(args, mode)) match { - case SilentResultValue(xs) => - val args = xs.asInstanceOf[List[Tree]] - if (args exists (_.isErrorTyped)) - reportError - else - adaptToArguments(qual, name, args, WildcardType, reportAmbiguous, saveErrors) - case _ => - reportError - } - case _ => - reportError - } - } - silent(_.adaptToMember(qual, HasMember(name), false)) match { - case SilentResultValue(res) => res - case SilentTypeError(err) => onError({if (reportAmbiguous) { context.issue(err) }; setError(tree)}) + def onError(reportError: => Tree): Tree = context.tree match { + case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => + ( silent (_.typedArgs(args, mode)) + map (_.asInstanceOf[List[Tree]]) + filter (xs => !(xs exists (_.isErrorTyped))) + map (xs => adaptToArguments(qual, name, xs, WildcardType, reportAmbiguous, saveErrors)) + orElse ( _ => reportError) + ) + case _ => + reportError } + + silent(_.adaptToMember(qual, HasMember(name), false)) orElse (err => + onError { + if (reportAmbiguous) context issue err + setError(tree) + } + ) } /** Try to apply an implicit conversion to `qual` to that it contains a @@ -1508,10 +1457,10 @@ trait Typers extends Modes with Adaptations with Tags { // Determine // - supertparams: Missing type parameters from supertype // - supertpe: Given supertype, polymorphic in supertparams - val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List() + val supertparams = if (supertpt.hasSymbolField) supertpt.symbol.typeParams else List() var supertpe = supertpt.tpe if (!supertparams.isEmpty) - supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (_.tpeHK))) + supertpe = PolyType(supertparams, appliedType(supertpe.typeConstructor, supertparams map (_.tpeHK))) // A method to replace a super reference by a New in a supercall def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match { @@ -1531,7 +1480,6 @@ trait Typers extends Modes with Adaptations with Tags { val (stats, rest) = cstats span (x => !treeInfo.isSuperConstrCall(x)) (stats map (_.duplicate), if (rest.isEmpty) EmptyTree else rest.head.duplicate) } - val cstats1 = if (superCall == EmptyTree) preSuperStats else preSuperStats :+ superCall val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall match { case Apply(_, _) if supertparams.nonEmpty => transformSuperCall(superCall) case _ => cunit.duplicate @@ -1558,7 +1506,7 @@ trait Typers extends Modes with Adaptations with Tags { val preSuperVals = treeInfo.preSuperFields(templ.body) if (preSuperVals.isEmpty && preSuperStats.nonEmpty) - debugwarn("Wanted to zip empty presuper val list with " + preSuperStats) + devWarning("Wanted to zip empty presuper val list with " + preSuperStats) else map2(preSuperStats, preSuperVals)((ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe) @@ -1566,16 +1514,6 @@ trait Typers extends Modes with Adaptations with Tags { if (!supertparams.isEmpty) MissingTypeArgumentsParentTpeError(supertpt) } -/* experimental: early types as type arguments - val hasEarlyTypes = templ.body exists (treeInfo.isEarlyTypeDef) - val earlyMap = new EarlyMap(clazz) - List.mapConserve(supertpt :: mixins){ tpt => - val tpt1 = checkNoEscaping.privates(clazz, tpt) - if (hasEarlyTypes) tpt1 else tpt1 setType earlyMap(tpt1.tpe) - } -*/ - - //Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG // Certain parents are added in the parser before it is known whether // that class also declared them as parents. For instance, this is an @@ -1663,9 +1601,6 @@ trait Typers extends Modes with Adaptations with Tags { !selfType.isErroneous && !parent.tpe.isErroneous) { - //Console.println(context.owner);//DEBUG - //Console.println(context.owner.unsafeTypeParams);//DEBUG - //Console.println(List.fromArray(context.owner.info.closure));//DEBUG pending += ParentSelfTypeConformanceError(parent, selfType) if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis) } @@ -1681,13 +1616,6 @@ trait Typers extends Modes with Adaptations with Tags { for (p <- parents) validateParentClass(p, superclazz) } -/* - if (settings.Xshowcls.value != "" && - settings.Xshowcls.value == context.owner.fullName) - println("INFO "+context.owner+ - ", baseclasses = "+(context.owner.info.baseClasses map (_.fullName))+ - ", lin = "+(context.owner.info.baseClasses map (context.owner.thisType.baseType))) -*/ pending.foreach(ErrorUtils.issueTypeError) } @@ -1711,12 +1639,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - /** - * @param cdef ... - * @return ... - */ def typedClassDef(cdef: ClassDef): Tree = { -// attributes(cdef) val clazz = cdef.symbol val typedMods = typedModifiers(cdef.mods) assert(clazz != NoSymbol, cdef) @@ -1745,10 +1668,6 @@ trait Typers extends Modes with Adaptations with Tags { .setType(NoType) } - /** - * @param mdef ... - * @return ... - */ def typedModuleDef(mdef: ModuleDef): Tree = { // initialize all constructors of the linked class: the type completer (Namer.methodSig) // might add default getters to this object. example: "object T; class T(x: Int = 1)" @@ -1806,18 +1725,12 @@ trait Typers extends Modes with Adaptations with Tags { if (txt eq context) namer.enterSym(tree) else newNamer(txt).enterSym(tree) - /** - * @param templ ... - * @param parents1 ... - * <li> <!-- 2 --> - * Check that inner classes do not inherit from Annotation - * </li> - * @return ... + /** <!-- 2 --> Check that inner classes do not inherit from Annotation */ def typedTemplate(templ: Template, parents1: List[Tree]): Template = { val clazz = context.owner // complete lazy annotations - val annots = clazz.annotations + clazz.annotations if (templ.symbol == NoSymbol) templ setSymbol clazz.newLocalDummy(templ.pos) val self1 = templ.self match { @@ -1869,7 +1782,7 @@ trait Typers extends Modes with Adaptations with Tags { } } - treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe + treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe_* } /** Remove definition annotations from modifiers (they have been saved @@ -1887,27 +1800,19 @@ trait Typers extends Modes with Adaptations with Tags { def typedModifiers(mods: Modifiers): Modifiers = mods.copy(annotations = Nil) setPositions mods.positions - /** - * @param vdef ... - * @return ... - */ def typedValDef(vdef: ValDef): ValDef = { -// attributes(vdef) val sym = vdef.symbol.initialize val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor) val typedMods = typedModifiers(vdef.mods) // complete lazy annotations - val annots = sym.annotations - var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt)) + sym.annotations + val tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt)) checkNonCyclic(vdef, tpt1) - if (sym.hasAnnotation(definitions.VolatileAttr)) { - if (!sym.isMutable) + if (sym.hasAnnotation(definitions.VolatileAttr) && !sym.isMutable) VolatileValueError(vdef) - else if (sym.isFinal) - FinalVolatileVarError(vdef) - } + val rhs1 = if (vdef.rhs.isEmpty) { if (sym.isVariable && sym.owner.isTerm && !sym.isLazy && !isPastTyper) @@ -1936,10 +1841,6 @@ trait Typers extends Modes with Adaptations with Tags { } /** Enter all aliases of local parameter accessors. - * - * @param clazz ... - * @param vparamss ... - * @param rhs ... */ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) { debuglog(s"computing param aliases for $clazz:${clazz.primaryConstructor.tpe}:$rhs") @@ -2034,7 +1935,7 @@ trait Typers extends Modes with Adaptations with Tags { f(subTree) } - /** Check if a structurally defined method violates implementation restrictions. + /** Check if a structurally defined method violates implementation restrictions. * A method cannot be called if it is a non-private member of a refinement type * and if its parameter's types are any of: * - the self-type of the refinement @@ -2092,18 +1993,14 @@ trait Typers extends Modes with Adaptations with Tags { val enclClass = context.enclClass.owner def defineAlias(name: Name) = if (context.scope.lookup(name) == NoSymbol) { - lookupVariable(name.toString.substring(1), enclClass) match { - case Some(repl) => - silent(_.typedTypeConstructor(stringParser(repl).typ())) match { - case SilentResultValue(tpt) => - val alias = enclClass.newAliasType(name.toTypeName, useCase.pos) - val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias) - val newInfo = genPolyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe))) - alias setInfo newInfo - context.scope.enter(alias) - case _ => - } - case _ => + lookupVariable(name.toString.substring(1), enclClass) foreach { repl => + silent(_.typedTypeConstructor(stringParser(repl).typ())) map { tpt => + val alias = enclClass.newAliasType(name.toTypeName, useCase.pos) + val tparams = cloneSymbolsAtOwner(tpt.tpe.typeSymbol.typeParams, alias) + val newInfo = genPolyType(tparams, appliedType(tpt.tpe, tparams map (_.tpe))) + alias setInfo newInfo + context.scope.enter(alias) + } } } for (tree <- trees; t <- tree) @@ -2119,10 +2016,6 @@ trait Typers extends Modes with Adaptations with Tags { useCase.defined foreach (sym => println("defined use cases: %s:%s".format(sym, sym.tpe))) } - /** - * @param ddef ... - * @return ... - */ def typedDefDef(ddef: DefDef): DefDef = { val meth = ddef.symbol.initialize @@ -2142,13 +2035,13 @@ trait Typers extends Modes with Adaptations with Tags { val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef) // complete lazy annotations - val annots = meth.annotations + meth.annotations for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1) if (isRepeatedParamType(vparam1.symbol.tpe)) StarParamNotLastError(vparam1) - var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt)) + val tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt)) checkNonCyclic(ddef, tpt1) ddef.tpt.setType(tpt1.tpe) val typedMods = typedModifiers(ddef.mods) @@ -2218,7 +2111,7 @@ trait Typers extends Modes with Adaptations with Tags { val tparams1 = tdef.tparams mapConserve typedTypeDef val typedMods = typedModifiers(tdef.mods) // complete lazy annotations - val annots = tdef.symbol.annotations + tdef.symbol.annotations // @specialized should not be pickled when compiling with -no-specialize if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) { @@ -2275,12 +2168,6 @@ trait Typers extends Modes with Adaptations with Tags { } } - /** - * @param block ... - * @param mode ... - * @param pt ... - * @return ... - */ def typedBlock(block: Block, mode: Int, pt: Type): Block = { val syntheticPrivates = new ListBuffer[Symbol] try { @@ -2353,12 +2240,6 @@ trait Typers extends Modes with Adaptations with Tags { } } - /** - * @param cdef ... - * @param pattpe ... - * @param pt ... - * @return ... - */ def typedCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = { // verify no _* except in last position for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x) @@ -2432,7 +2313,7 @@ trait Typers extends Modes with Adaptations with Tags { val casesTyped = typedCases(cases, selectorTp, pt) val (resTp, needAdapt) = - if (opt.virtPatmat) ptOrLubPacked(casesTyped, pt) + if (!settings.XoldPatmat.value) ptOrLubPacked(casesTyped, pt) else ptOrLub(casesTyped map (_.tpe), pt) val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, resTp)) @@ -2444,15 +2325,12 @@ trait Typers extends Modes with Adaptations with Tags { // (virtualized matches are expanded during type checking so they have the full context available) // otherwise, do nothing: matches are translated during phase `patmat` (unless -Xoldpatmat) def virtualizedMatch(match_ : Match, mode: Int, pt: Type) = { - import patmat.{vpmName, PureMatchTranslator, OptimizingMatchTranslator} + import patmat.{ vpmName, PureMatchTranslator } // TODO: add fallback __match sentinel to predef val matchStrategy: Tree = - if (!(newPatternMatching && opt.experimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen - else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match { - case SilentResultValue(ms) => ms - case _ => null - } + if (!(newPatternMatching && settings.Xexperimental.value && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen + else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) orElse (_ => null) if (matchStrategy ne null) // virtualize typed((new PureMatchTranslator(this.asInstanceOf[patmat.global.analyzer.Typer] /*TODO*/, matchStrategy)).translateMatch(match_), mode, pt) @@ -2478,7 +2356,6 @@ trait Typers extends Modes with Adaptations with Tags { assert(isPartial) private val anonClass = context.owner.newAnonymousFunctionClass(tree.pos) - private val funThis = This(anonClass) anonClass addAnnotation AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List()) @@ -2628,12 +2505,6 @@ trait Typers extends Modes with Adaptations with Tags { override def mkSel(params: List[Symbol]) = sel.duplicate } - /** - * @param fun ... - * @param mode ... - * @param pt ... - * @return ... - */ private def typedFunction(fun: Function, mode: Int, pt: Type): Tree = { val numVparams = fun.vparams.length if (numVparams > definitions.MaxFunctionArity) @@ -2659,15 +2530,13 @@ trait Typers extends Modes with Adaptations with Tags { else { fun match { case etaExpansion(vparams, fn, args) => - silent(_.typed(fn, forFunMode(mode), pt)) match { - case SilentResultValue(fn1) if context.undetparams.isEmpty => - // if context,undetparams is not empty, the function was polymorphic, - // so we need the missing arguments to infer its type. See #871 - //println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams) - val ftpe = normalize(fn1.tpe) baseType FunctionClass(numVparams) - if (isFunctionType(ftpe) && isFullyDefined(ftpe)) - return typedFunction(fun, mode, ftpe) - case _ => + silent(_.typed(fn, forFunMode(mode), pt)) filter (_ => context.undetparams.isEmpty) map { fn1 => + // if context,undetparams is not empty, the function was polymorphic, + // so we need the missing arguments to infer its type. See #871 + //println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams) + val ftpe = normalize(fn1.tpe) baseType FunctionClass(numVparams) + if (isFunctionType(ftpe) && isFullyDefined(ftpe)) + return typedFunction(fun, mode, ftpe) } case _ => } @@ -2693,16 +2562,13 @@ trait Typers extends Modes with Adaptations with Tags { if (context.retyping) context.scope enter vparam.symbol vparam.symbol } - val vparams = fun.vparams mapConserve (typedValDef) - // for (vparam <- vparams) { - // checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); () - // } + val vparams = fun.vparams mapConserve typedValDef val formals = vparamSyms map (_.tpe) - val body1 = typed(fun.body, respt) - val restpe = packedType(body1, fun.symbol).deconst.resultType - val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) - // body = checkNoEscaping.locals(context.scope, restpe, body) - treeCopy.Function(fun, vparams, body1).setType(funtpe) + val body1 = typed(fun.body, respt) + val restpe = packedType(body1, fun.symbol).deconst.resultType + val funtpe = appliedType(clazz, formals :+ restpe: _*) + + treeCopy.Function(fun, vparams, body1) setType funtpe } } } @@ -2733,17 +2599,6 @@ trait Typers extends Modes with Adaptations with Tags { case Some(imp1: Import) => imp1 case _ => log("unhandled import: "+imp+" in "+unit); imp } - private def isWarnablePureExpression(tree: Tree) = tree match { - case EmptyTree | Literal(Constant(())) => false - case _ => - !tree.isErrorTyped && (treeInfo isExprSafeToInline tree) && { - val sym = tree.symbol - (sym == null) || !(sym.isModule || sym.isLazy) || { - debuglog("'Pure' but side-effecting expression in statement position: " + tree) - false - } - } - } def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { val inBlock = exprOwner == context.owner @@ -2780,7 +2635,7 @@ trait Typers extends Modes with Adaptations with Tags { ConstructorsOrderError(stat) } - if (isWarnablePureExpression(result)) context.warning(stat.pos, + if (treeInfo.isPureExprForWarningPurposes(result)) context.warning(stat.pos, "a pure expression does nothing in statement position; " + "you may be omitting necessary parentheses" ) @@ -2964,21 +2819,20 @@ trait Typers extends Modes with Adaptations with Tags { def duplErrorTree(err: AbsTypeError) = { issue(err); duplErrTree } def preSelectOverloaded(fun: Tree): Tree = { - if (fun.hasSymbol && fun.symbol.isOverloaded) { + if (fun.hasSymbolField && fun.symbol.isOverloaded) { // remove alternatives with wrong number of parameters without looking at types. - // less expensive than including them in inferMethodAlternatvie (see below). + // less expensive than including them in inferMethodAlternative (see below). def shapeType(arg: Tree): Type = arg match { case Function(vparams, body) => - functionType(vparams map (vparam => AnyClass.tpe), shapeType(body)) + functionType(vparams map (_ => AnyClass.tpe), shapeType(body)) case AssignOrNamedArg(Ident(name), rhs) => NamedType(name, shapeType(rhs)) case _ => NothingClass.tpe } val argtypes = args map shapeType - val pre = fun.symbol.tpe.prefix - - var sym = fun.symbol filter { alt => + val pre = fun.symbol.tpe.prefix + var sym = fun.symbol filter { alt => // must use pt as expected type, not WildcardType (a tempting quick fix to #2665) // now fixed by using isWeaklyCompatible in exprTypeArgs // TODO: understand why exactly -- some types were not inferred anymore (`ant clean quick.bin` failed) @@ -2989,16 +2843,15 @@ trait Typers extends Modes with Adaptations with Tags { // Types: "refs = Array(Map(), Map())". I determined that inference fails if there are at // least two invariant type parameters. See the test case I checked in to help backstop: // pos/isApplicableSafe.scala. - isApplicableSafe(context.undetparams, followApply(pre.memberType(alt)), argtypes, pt) + isApplicableSafe(context.undetparams, followApply(pre memberType alt), argtypes, pt) } if (sym.isOverloaded) { - val sym1 = sym filter (alt => { - // eliminate functions that would result from tupling transforms - // keeps alternatives with repeated params - hasExactlyNumParams(followApply(alt.tpe), argtypes.length) || - // also keep alts which define at least one default - alt.tpe.paramss.exists(_.exists(_.hasDefault)) - }) + // eliminate functions that would result from tupling transforms + // keeps alternatives with repeated params + val sym1 = sym filter (alt => + isApplicableBasedOnArity(pre memberType alt, argtypes.length, varargsStar = false, tuplingAllowed = false) + || alt.tpe.params.exists(_.hasDefault) + ) if (sym1 != NoSymbol) sym = sym1 } if (sym == NoSymbol) fun @@ -3012,16 +2865,19 @@ trait Typers extends Modes with Adaptations with Tags { case OverloadedType(pre, alts) => def handleOverloaded = { val undetparams = context.extractUndetparams() - - val argtpes = new ListBuffer[Type] - val amode = forArgMode(fun, mode) + val argtpes = new ListBuffer[Type] + val amode = forArgMode(fun, mode) val args1 = args map { case arg @ AssignOrNamedArg(Ident(name), rhs) => // named args: only type the righthand sides ("unknown identifier" errors otherwise) val rhs1 = typedArg(rhs, amode, BYVALmode, WildcardType) argtpes += NamedType(name, rhs1.tpe.deconst) // the assign is untyped; that's ok because we call doTypedApply - atPos(arg.pos) { new AssignOrNamedArg(arg.lhs, rhs1) } + treeCopy.AssignOrNamedArg(arg, arg.lhs, rhs1) + case arg @ Typed(repeated, Ident(tpnme.WILDCARD_STAR)) => + val arg1 = typedArg(arg, amode, BYVALmode, WildcardType) + argtpes += RepeatedType(arg1.tpe.deconst) + arg1 case arg => val arg1 = typedArg(arg, amode, BYVALmode, WildcardType) argtpes += arg1.tpe.deconst @@ -3031,7 +2887,7 @@ trait Typers extends Modes with Adaptations with Tags { if (context.hasErrors) setError(tree) else { - inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args)) + inferMethodAlternative(fun, undetparams, argtpes.toList, pt) doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt) } } @@ -3040,22 +2896,20 @@ trait Typers extends Modes with Adaptations with Tags { case mt @ MethodType(params, _) => val paramTypes = mt.paramTypes // repeat vararg as often as needed, remove by-name - val formals = formalTypes(paramTypes, args.length) + val argslen = args.length + val formals = formalTypes(paramTypes, argslen) /** Try packing all arguments into a Tuple and apply `fun` * to that. This is the last thing which is tried (after * default arguments) */ - def tryTupleApply: Option[Tree] = { - // if 1 formal, 1 arg (a tuple), otherwise unmodified args - val tupleArgs = actualArgs(tree.pos.makeTransparent, args, formals.length) - - if (!sameLength(tupleArgs, args) && !isUnitForVarArgs(args, params)) { + def tryTupleApply: Option[Tree] = ( + if (eligibleForTupleConversion(paramTypes, argslen) && !phase.erasedTypes) { + val tupleArgs = List(atPos(tree.pos.makeTransparent)(gen.mkTuple(args))) // expected one argument, but got 0 or >1 ==> try applying to tuple // the inner "doTypedApply" does "extractUndetparams" => restore when it fails val savedUndetparams = context.undetparams - silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) match { - case SilentResultValue(t) => + silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) map { t => // Depending on user options, may warn or error here if // a Unit or tuple was inserted. Some(t) filter (tupledTree => @@ -3063,12 +2917,10 @@ trait Typers extends Modes with Adaptations with Tags { || tupledTree.symbol == null || checkValidAdaptation(tupledTree, args) ) - case _ => - context.undetparams = savedUndetparams - None - } - } else None - } + } orElse { _ => context.undetparams = savedUndetparams ; None } + } + else None + ) /** Treats an application which uses named or default arguments. * Also works if names + a vararg used: when names are used, the vararg @@ -3245,15 +3097,14 @@ trait Typers extends Modes with Adaptations with Tags { } else arg1 } val args1 = map2(args, formals)(typedArgToPoly) - if (args1 exists { _.isErrorTyped }) duplErrTree + if (args1 exists {_.isErrorTyped}) duplErrTree else { - debuglog("infer method inst " + fun + ", tparams = " + tparams + ", args = " + args1.map(_.tpe) + ", pt = " + pt + ", lobounds = " + tparams.map(_.tpe.bounds.lo) + ", parambounds = " + tparams.map(_.info)) //debug + debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug // define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun" // returns those undetparams which have not been instantiated. val undetparams = inferMethodInstance(fun, tparams, args1, pt) - val result = doTypedApply(tree, fun, args1, mode, pt) - context.undetparams = undetparams - result + try doTypedApply(tree, fun, args1, mode, pt) + finally context.undetparams = undetparams } } handlePolymorphicCall @@ -3336,10 +3187,7 @@ trait Typers extends Modes with Adaptations with Tags { if (formals == null) duplErrorTree(WrongNumberOfArgsError(tree, fun)) else { val args1 = typedArgs(args, mode, formals, formalsExpanded) - // This used to be the following (failing) assert: - // assert(isFullyDefined(pt), tree+" ==> "+UnApply(fun1, args1)+", pt = "+pt) - // I modified as follows. See SI-1048. - val pt1 = if (isFullyDefined(pt)) pt else makeFullyDefined(pt) + val pt1 = if (isFullyDefined(pt)) pt else makeFullyDefined(pt) // SI-1048 val itype = glb(List(pt1, arg.tpe)) arg.tpe = pt1 // restore type (arg is a dummy tree, just needs to pass typechecking) @@ -3367,25 +3215,26 @@ trait Typers extends Modes with Adaptations with Tags { // println(util.Position.formatMessage(uncheckedPattern.pos, "made unchecked type test into a checked one", true)) val args = List(uncheckedPattern) + val app = atPos(uncheckedPattern.pos)(Apply(classTagExtractor, args)) // must call doTypedUnapply directly, as otherwise we get undesirable rewrites // and re-typechecks of the target of the unapply call in PATTERNmode, // this breaks down when the classTagExtractor (which defineds the unapply member) is not a simple reference to an object, // but an arbitrary tree as is the case here - doTypedUnapply(Apply(classTagExtractor, args), classTagExtractor, classTagExtractor, args, PATTERNmode, pt) - } + doTypedUnapply(app, classTagExtractor, classTagExtractor, args, PATTERNmode, pt) + } // if there's a ClassTag that allows us to turn the unchecked type test for `pt` into a checked type test // return the corresponding extractor (an instance of ClassTag[`pt`]) - def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (!opt.virtPatmat || isPastTyper) None else { + def extractorForUncheckedType(pos: Position, pt: Type): Option[Tree] = if (settings.XoldPatmat.value || isPastTyper) None else { // only look at top-level type, can't (reliably) do anything about unchecked type args (in general) pt.normalize.typeConstructor match { // if at least one of the types in an intersection is checkable, use the checkable ones // this avoids problems as in run/matchonseq.scala, where the expected type is `Coll with scala.collection.SeqLike` // Coll is an abstract type, but SeqLike of course is not - case RefinedType(parents, _) if (parents.length >= 2) && (parents.exists(tp => !infer.containsUnchecked(tp))) => + case RefinedType(ps, _) if ps.length > 1 && (ps exists infer.isCheckable) => None - case ptCheckable if infer.containsUnchecked(ptCheckable) => + case ptCheckable if infer isUncheckable ptCheckable => val classTagExtractor = resolveClassTag(pos, ptCheckable) if (classTagExtractor != EmptyTree && unapplyMember(classTagExtractor.tpe) != NoSymbol) @@ -3549,35 +3398,23 @@ trait Typers extends Modes with Adaptations with Tags { // local dummy fixes SI-5544 val localTyper = newTyper(context.make(ann, context.owner.newLocalDummy(ann.pos))) localTyper.typed(ann, mode, annClass.tpe) - } else { - // Since a selfsym is supplied, the annotation should have - // an extra "self" identifier in scope for type checking. - // This is implemented by wrapping the rhs - // in a function like "self => rhs" during type checking, - // and then stripping the "self =>" and substituting - // in the supplied selfsym. + } + else { + // Since a selfsym is supplied, the annotation should have an extra + // "self" identifier in scope for type checking. This is implemented + // by wrapping the rhs in a function like "self => rhs" during type + // checking, and then stripping the "self =>" and substituting in + // the supplied selfsym. val funcparm = ValDef(NoMods, nme.self, TypeTree(selfsym.info), EmptyTree) - val func = Function(List(funcparm), ann.duplicate) - // The .duplicate of annot.constr - // deals with problems that - // accur if this annotation is - // later typed again, which - // the compiler sometimes does. - // The problem is that "self" - // ident's within annot.constr - // will retain the old symbol - // from the previous typing. - val fun1clazz = FunctionClass(1) - val funcType = typeRef(fun1clazz.tpe.prefix, - fun1clazz, - List(selfsym.info, annClass.tpe)) - - (typed(func, mode, funcType): @unchecked) match { - case t @ Function(List(arg), rhs) => - val subs = - new TreeSymSubstituter(List(arg.symbol),List(selfsym)) - subs(rhs) - } + // The .duplicate of annot.constr deals with problems that accur + // if this annotation is later typed again, which the compiler + // sometimes does. The problem is that "self" ident's within + // annot.constr will retain the old symbol from the previous typing. + val func = Function(funcparm :: Nil, ann.duplicate) + val funcType = appliedType(FunctionClass(1), selfsym.info, annClass.tpe_*) + val Function(arg :: Nil, rhs) = typed(func, mode, funcType) + + rhs.substituteSymbols(arg.symbol :: Nil, selfsym :: Nil) } def annInfo(t: Tree): AnnotationInfo = t match { @@ -3798,11 +3635,11 @@ trait Typers extends Modes with Adaptations with Tags { if (wc.symbol == NoSymbol) { namer.enterSym(wc); wc.symbol setFlag EXISTENTIAL } else context.scope enter wc.symbol val whereClauses1 = typedStats(tree.whereClauses, context.owner) - for (vd @ ValDef(_, _, _, _) <- tree.whereClauses) + for (vd @ ValDef(_, _, _, _) <- whereClauses1) if (vd.symbol.tpe.isVolatile) AbstractionFromVolatileTypeError(vd) val tpt1 = typedType(tree.tpt, mode) - existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) => + existentialTransform(whereClauses1 map (_.symbol), tpt1.tpe)((tparams, tp) => TypeTree(newExistentialType(tparams, tp)) setOriginal tree ) } @@ -3926,7 +3763,7 @@ trait Typers extends Modes with Adaptations with Tags { * */ def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = { - debuglog(s"mkInvoke($cxTree, $tree, $qual, $name)") + debuglog(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)") acceptsApplyDynamicWithType(qual, name) map { tp => // tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user) // in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct) @@ -3977,12 +3814,8 @@ trait Typers extends Modes with Adaptations with Tags { } } - def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = { - silent(typeTree) match { - case SilentResultValue(r) => r - case SilentTypeError(err) => DynamicRewriteError(tree, err) - } - } + def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = + silent(typeTree) orElse (err => DynamicRewriteError(tree, err)) } final def deindentTyping() = context.typingIndentLevel -= 2 @@ -3998,14 +3831,24 @@ trait Typers extends Modes with Adaptations with Tags { def typed1(tree: Tree, mode: Int, pt: Type): Tree = { def isPatternMode = inPatternMode(mode) - - //Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")") - //@M! get the type of the qualifier in a Select tree, otherwise: NoType - def prefixType(fun: Tree): Type = fun match { - case Select(qualifier, _) => qualifier.tpe -// case Ident(name) => ?? - case _ => NoType - } + def inPatternConstructor = inAllModes(mode, PATTERNmode | FUNmode) + def isQualifierMode = (mode & QUALmode) != 0 + + // Lookup in the given class using the root mirror. + def lookupInOwner(owner: Symbol, name: Name): Symbol = + if (isQualifierMode) rootMirror.missingHook(owner, name) else NoSymbol + + // Lookup in the given qualifier. Used in last-ditch efforts by typedIdent and typedSelect. + def lookupInRoot(name: Name): Symbol = lookupInOwner(rootMirror.RootClass, name) + def lookupInEmpty(name: Name): Symbol = lookupInOwner(rootMirror.EmptyPackageClass, name) + def lookupInQualifier(qual: Tree, name: Name): Symbol = ( + if (name == nme.ERROR || qual.tpe.widen.isErroneous) + NoSymbol + else lookupInOwner(qual.tpe.typeSymbol, name) orElse { + NotAMemberError(tree, qual, name) + NoSymbol + } + ) def typedAnnotated(atd: Annotated): Tree = { val ann = atd.annot @@ -4105,7 +3948,7 @@ trait Typers extends Modes with Adaptations with Tags { if (name != tpnme.WILDCARD) namer.enterInScope(sym) else context.scope.enter(sym) - tree setSymbol sym setType sym.tpe + tree setSymbol sym setType sym.tpeHK case name: TermName => val sym = @@ -4201,7 +4044,7 @@ trait Typers extends Modes with Adaptations with Tags { // in the special (though common) case where the types are equal, it pays to pack before comparing // especially virtpatmat needs more aggressive unification of skolemized types // this breaks src/library/scala/collection/immutable/TrieIterator.scala - if ( opt.virtPatmat && !isPastTyper + if ( !settings.XoldPatmat.value && !isPastTyper && thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this) && thenTp =:= elseTp ) (thenp1.tpe.deconst, false) // use unpacked type. Important to deconst, as is done in ptOrLub, otherwise `if (???) 0 else 0` evaluates to 0 (SI-6331) @@ -4274,7 +4117,7 @@ trait Typers extends Modes with Adaptations with Tags { val tpt1 = { val tpt0 = typedTypeConstructor(tpt) if (checkStablePrefixClassType(tpt0)) - if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) { + if (tpt0.hasSymbolField && !tpt0.symbol.typeParams.isEmpty) { context.undetparams = cloneSymbols(tpt0.symbol.typeParams) notifyUndetparamsAdded(context.undetparams) TypeTree().setOriginal(tpt0) @@ -4304,7 +4147,7 @@ trait Typers extends Modes with Adaptations with Tags { NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR) setError(tpt) } - else if (!( tp == sym.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable + else if (!( tp == sym.thisSym.tpe_* // when there's no explicit self type -- with (#3612) or without self variable // sym.thisSym.tpe == tp.typeOfThis (except for objects) || narrowRhs(tp) <:< tp.typeOfThis || phase.erasedTypes @@ -4352,10 +4195,6 @@ trait Typers extends Modes with Adaptations with Tags { UnderscoreEtaError(expr1) } - /** - * @param args ... - * @return ... - */ def tryTypedArgs(args: List[Tree], mode: Int): Option[List[Tree]] = { val c = context.makeSilent(false) c.retyping = true @@ -4429,12 +4268,7 @@ trait Typers extends Modes with Adaptations with Tags { setError(treeCopy.Apply(tree, fun, args)) } - silent(_.doTypedApply(tree, fun, args, mode, pt)) match { - case SilentResultValue(t) => - t - case SilentTypeError(err) => - onError(err) - } + silent(_.doTypedApply(tree, fun, args, mode, pt)) orElse onError } def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = { @@ -4485,15 +4319,6 @@ trait Typers extends Modes with Adaptations with Tags { if (useTry) tryTypedApply(fun2, args) else doTypedApply(tree, fun2, args, mode, pt) - /* - if (fun2.hasSymbol && fun2.symbol.isConstructor && (mode & EXPRmode) != 0) { - res.tpe = res.tpe.notNull - } - */ - // TODO: In theory we should be able to call: - //if (fun2.hasSymbol && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) { - // But this causes cyclic reference for Array class in Cleanup. It is easy to overcome this - // by calling ArrayClass.info here (or some other place before specialize). if (fun2.symbol == Array_apply && !res.isErrorTyped) { val checked = gen.mkCheckInit(res) // this check is needed to avoid infinite recursion in Duplicators @@ -4508,38 +4333,36 @@ trait Typers extends Modes with Adaptations with Tags { } } - def typedApply(tree: Apply) = { - val fun = tree.fun - val args = tree.args - fun match { - case Block(stats, expr) => - typed1(atPos(tree.pos)(Block(stats, Apply(expr, args) setPos tree.pos.makeTransparent)), mode, pt) - case _ => - normalTypedApply(tree, fun, args) match { - case Apply(Select(New(tpt), name), args) - if (tpt.tpe != null && - tpt.tpe.typeSymbol == ArrayClass && - args.length == 1 && - erasure.GenericArray.unapply(tpt.tpe).isDefined) => // !!! todo simplify by using extractor - // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len) - // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len), where Array HK gets applied (N-1) times - // [Eugene] no more MaxArrayDims. ClassTags are flexible enough to allow creation of arrays of arbitrary dimensionality (w.r.t JVM restrictions) - val Some((level, componentType)) = erasure.GenericArray.unapply(tpt.tpe) - val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.toTypeConstructor, List(tpe))).last - val newArrayApp = atPos(tree.pos) { - val tag = resolveClassTag(tree.pos, tagType) - if (tag.isEmpty) MissingClassTagError(tree, tagType) - else new ApplyToImplicitArgs(Select(tag, nme.newArray), args) + // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len) + // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len) + // where Array HK gets applied (N-1) times + object ArrayInstantiation { + def unapply(tree: Apply) = tree match { + case Apply(Select(New(tpt), name), arg :: Nil) if tpt.tpe != null && tpt.tpe.typeSymbol == ArrayClass => + Some(tpt.tpe) collect { + case erasure.GenericArray(level, componentType) => + val tagType = (1 until level).foldLeft(componentType)((res, _) => arrayType(res)) + + resolveClassTag(tree.pos, tagType) match { + case EmptyTree => MissingClassTagError(tree, tagType) + case tag => atPos(tree.pos)(new ApplyToImplicitArgs(Select(tag, nme.newArray), arg :: Nil)) } - typed(newArrayApp, mode, pt) - case Apply(Select(fun, nme.apply), _) if treeInfo.isSuperConstrCall(fun) => //SI-5696 - TooManyArgumentListsForConstructor(tree) - case tree1 => - tree1 } + case _ => None } } + def typedApply(tree: Apply) = tree match { + case Apply(Block(stats, expr), args) => + typed1(atPos(tree.pos)(Block(stats, Apply(expr, args) setPos tree.pos.makeTransparent)), mode, pt) + case Apply(fun, args) => + normalTypedApply(tree, fun, args) match { + case ArrayInstantiation(tree1) => typed(tree1, mode, pt) + case Apply(Select(fun, nme.apply), _) if treeInfo.isSuperConstrCall(fun) => TooManyArgumentListsForConstructor(tree) //SI-5696 + case tree1 => tree1 + } + } + def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = { val prefix = name.toTermName stripSuffix nme.EQL def mkAssign(vble: Tree): Tree = @@ -4593,8 +4416,6 @@ trait Typers extends Modes with Adaptations with Tags { case This(_) => qual1.symbol case _ => qual1.tpe.typeSymbol } - //println(clazz+"/"+qual1.tpe.typeSymbol+"/"+qual1) - def findMixinSuper(site: Type): Type = { var ps = site.parents filter (_.typeSymbol.name == mix) if (ps.isEmpty) @@ -4602,11 +4423,6 @@ trait Typers extends Modes with Adaptations with Tags { if (ps.isEmpty) { debuglog("Fatal: couldn't find site " + site + " in " + site.parents.map(_.typeSymbol.name)) if (phase.erasedTypes && context.enclClass.owner.isImplClass) { - // println(qual1) - // println(clazz) - // println(site) - // println(site.parents) - // println(mix) // the reference to super class got lost during erasure restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class") ErrorType @@ -4638,14 +4454,28 @@ trait Typers extends Modes with Adaptations with Tags { if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree } - /** Attribute a selection where <code>tree</code> is <code>qual.name</code>. - * <code>qual</code> is already attributed. - * - * @param qual ... - * @param name ... - * @return ... + /** Attribute a selection where `tree` is `qual.name`. + * `qual` is already attributed. */ def typedSelect(tree: Tree, qual: Tree, name: Name): Tree = { + val t = typedSelectInternal(tree, qual, name) + // Checking for OverloadedTypes being handed out after overloading + // resolution has already happened. + if (isPastTyper) t.tpe match { + case OverloadedType(pre, alts) => + if (alts forall (s => (s.owner == ObjectClass) || (s.owner == AnyClass) || isPrimitiveValueClass(s.owner))) () + else if (settings.debug.value) printCaller( + s"""|Select received overloaded type during $phase, but typer is over. + |If this type reaches the backend, we are likely doomed to crash. + |$t has these overloads: + |${alts map (s => " " + s.defStringSeenAs(pre memberType s)) mkString "\n"} + |""".stripMargin + )("") + case _ => + } + t + } + def typedSelectInternal(tree: Tree, qual: Tree, name: Name): Tree = { def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map { t => dyna.wrapErrors(t, (_.typed1(t, mode, pt))) } @@ -4666,45 +4496,43 @@ trait Typers extends Modes with Adaptations with Tags { if (!reallyExists(sym)) { def handleMissing: Tree = { - if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) { - val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) } - if (tree1 != EmptyTree) return typed1(tree1, mode, pt) - } - - // try to expand according to Dynamic rules. - asDynamicCall foreach (x => return x) - - debuglog( - "qual = " + qual + ":" + qual.tpe + - "\nSymbol=" + qual.tpe.termSymbol + "\nsymbol-info = " + qual.tpe.termSymbol.info + - "\nscope-id = " + qual.tpe.termSymbol.info.decls.hashCode() + "\nmembers = " + qual.tpe.members + - "\nname = " + name + "\nfound = " + sym + "\nowner = " + context.enclClass.owner) - - def makeInteractiveErrorTree = { - val tree1 = tree match { - case Select(_, _) => treeCopy.Select(tree, qual, name) - case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name) - } - setError(tree1) + def errorTree = tree match { + case _ if !forInteractive => tree + case Select(_, _) => treeCopy.Select(tree, qual, name) + case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name) } - - if (name == nme.ERROR && forInteractive) - return makeInteractiveErrorTree - - if (!qual.tpe.widen.isErroneous) { - if ((mode & QUALmode) != 0) { - val lastTry = rootMirror.missingHook(qual.tpe.typeSymbol, name) - if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt) + def asTypeSelection = ( + if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) { + atPos(tree.pos)(gen.convertToSelectFromType(qual, name)) match { + case EmptyTree => None + case tree1 => Some(typed1(tree1, mode, pt)) + } } - NotAMemberError(tree, qual, name) - } - - if (forInteractive) makeInteractiveErrorTree else setError(tree) + else None + ) + debuglog(s""" + |qual=$qual:${qual.tpe} + |symbol=${qual.tpe.termSymbol.defString} + |scope-id=${qual.tpe.termSymbol.info.decls.hashCode} + |members=${qual.tpe.members mkString ", "} + |name=$name + |found=$sym + |owner=${context.enclClass.owner} + """.stripMargin) + + // 1) Try converting a term selection on a java class into a type selection. + // 2) Try expanding according to Dynamic rules. + // 3) Try looking up the name in the qualifier. + asTypeSelection orElse asDynamicCall getOrElse (lookupInQualifier(qual, name) match { + case NoSymbol => setError(errorTree) + case found => typed1(tree setSymbol found, mode, pt) + }) } handleMissing - } else { + } + else { val tree1 = tree match { - case Select(_, _) => treeCopy.Select(tree, qual, name) + case Select(_, _) => treeCopy.Select(tree, qual, name) case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name) } val (result, accessibleError) = silent(_.makeAccessible(tree1, sym, qual.tpe, qual)) match { @@ -4773,19 +4601,16 @@ trait Typers extends Modes with Adaptations with Tags { val tree1 = // temporarily use `filter` and an alternative for `withFilter` if (name == nme.withFilter) - silent(_ => typedSelect(tree, qual1, name)) match { - case SilentResultValue(result) => - result - case _ => - silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match { - case SilentResultValue(result2) => - unit.deprecationWarning( - tree.pos, "`withFilter' method does not yet exist on " + qual1.tpe.widen + - ", using `filter' method instead") - result2 - case SilentTypeError(err) => - WithFilterError(tree, err) - } + silent(_ => typedSelect(tree, qual1, name)) orElse { _ => + silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match { + case SilentResultValue(result2) => + unit.deprecationWarning( + tree.pos, "`withFilter' method does not yet exist on " + qual1.tpe.widen + + ", using `filter' method instead") + result2 + case SilentTypeError(err) => + WithFilterError(tree, err) + } } else typedSelect(tree, qual1, name) @@ -4800,6 +4625,18 @@ trait Typers extends Modes with Adaptations with Tags { } } + /** A symbol qualifies if: + * - it exists + * - it is not stale (stale symbols are made to disappear here) + * - if we are in a pattern constructor, method definitions do not qualify + * unless they are stable. Otherwise, 'case x :: xs' would find the :: method. + */ + def qualifies(sym: Symbol) = ( + sym.hasRawInfo + && reallyExists(sym) + && !(inPatternConstructor && sym.isMethod && !sym.isStable) + ) + /** Attribute an identifier consisting of a simple name or an outer reference. * * @param tree The tree representing the identifier. @@ -4808,243 +4645,48 @@ trait Typers extends Modes with Adaptations with Tags { * (2) Change imported symbols to selections */ def typedIdent(tree: Tree, name: Name): Tree = { - var errorContainer: AbsTypeError = null - def ambiguousError(msg: String) = { - assert(errorContainer == null, "Cannot set ambiguous error twice for identifier") - errorContainer = AmbiguousIdentError(tree, name, msg) - } - def identError(tree: AbsTypeError) = { - assert(errorContainer == null, "Cannot set ambiguous error twice for identifier") - errorContainer = tree - } + // setting to enable unqualified idents in empty package + def inEmptyPackage = if (settings.exposeEmptyPackage.value) lookupInEmpty(name) else NoSymbol + + def issue(err: AbsTypeError) = { + // Avoiding some spurious error messages: see SI-2388. + val suppress = reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME) + if (!suppress) + ErrorUtils.issueTypeError(err) - var defSym: Symbol = tree.symbol // the directly found symbol - var pre: Type = NoPrefix // the prefix type of defSym, if a class member - var qual: Tree = EmptyTree // the qualifier tree if transformed tree is a select - var inaccessibleSym: Symbol = NoSymbol // the first symbol that was found but that was discarded - // for being inaccessible; used for error reporting - var inaccessibleExplanation: String = "" - - // If a special setting is given, the empty package will be checked as a - // last ditch effort before failing. This method sets defSym and returns - // true if a member of the given name exists. - def checkEmptyPackage(): Boolean = { - defSym = rootMirror.EmptyPackageClass.tpe.nonPrivateMember(name) - defSym != NoSymbol + setError(tree) } - def startingIdentContext = ( - // ignore current variable scope in patterns to enforce linearity - if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context - else context.outer - ) - // A symbol qualifies if it exists and is not stale. Stale symbols - // are made to disappear here. In addition, - // if we are in a constructor of a pattern, we ignore all definitions - // which are methods (note: if we don't do that - // case x :: xs in class List would return the :: method) - // unless they are stable or are accessors (the latter exception is for better error messages). - def qualifies(sym: Symbol): Boolean = { - sym.hasRawInfo && // this condition avoids crashing on self-referential pattern variables - reallyExists(sym) && - ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR)) + // ignore current variable scope in patterns to enforce linearity + val startContext = if (inNoModes(mode, PATTERNmode | TYPEPATmode)) context else context.outer + val nameLookup = tree.symbol match { + case NoSymbol => startContext.lookupSymbol(name, qualifies) + case sym => LookupSucceeded(EmptyTree, sym) } - - if (defSym == NoSymbol) { - var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope - - var cx = startingIdentContext - while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators - pre = cx.enclClass.prefix - defEntry = cx.scope.lookupEntry(name) - if ((defEntry ne null) && qualifies(defEntry.sym)) { - // Right here is where SI-1987, overloading in package objects, can be - // seen to go wrong. There is an overloaded symbol, but when referring - // to the unqualified identifier from elsewhere in the package, only - // the last definition is visible. So overloading mis-resolves and is - // definition-order dependent, bad things. See run/t1987.scala. - // - // I assume the actual problem involves how/where these symbols are entered - // into the scope. But since I didn't figure out how to fix it that way, I - // catch it here by looking up package-object-defined symbols in the prefix. - if (isInPackageObject(defEntry.sym, pre.typeSymbol)) { - defSym = pre.member(defEntry.sym.name) - if (defSym ne defEntry.sym) { - qual = gen.mkAttributedQualifier(pre) - log(s""" - | !!! Overloaded package object member resolved incorrectly. - | prefix: $pre - | Discarded: ${defEntry.sym.defString} - | Using: ${defSym.defString} - """.stripMargin) - } - } - else - defSym = defEntry.sym - } - else { - cx = cx.enclClass - val foundSym = pre.member(name) filter qualifies - defSym = foundSym filter (context.isAccessible(_, pre, false)) - if (defSym == NoSymbol) { - if ((foundSym ne NoSymbol) && (inaccessibleSym eq NoSymbol)) { - inaccessibleSym = foundSym - inaccessibleExplanation = analyzer.lastAccessCheckDetails - } - cx = cx.outer - } - } - } - - val symDepth = if (defEntry eq null) cx.depth - else cx.depth - (cx.scope.nestingLevel - defEntry.owner.nestingLevel) - var impSym: Symbol = NoSymbol // the imported symbol - var imports = context.imports // impSym != NoSymbol => it is imported from imports.head - while (!reallyExists(impSym) && !imports.isEmpty && imports.head.depth > symDepth) { - impSym = imports.head.importedSymbol(name) - if (!impSym.exists) imports = imports.tail - } - - // detect ambiguous definition/import, - // update `defSym` to be the final resolved symbol, - // update `pre` to be `sym`s prefix type in case it is an imported member, - // and compute value of: - - if (defSym.exists && impSym.exists) { - // imported symbols take precedence over package-owned symbols in different - // compilation units. Defined symbols take precedence over erroneous imports. - if (defSym.isDefinedInPackage && - (!currentRun.compiles(defSym) || - context.unit.exists && defSym.sourceFile != context.unit.source.file)) - defSym = NoSymbol - else if (impSym.isError || impSym.name == nme.CONSTRUCTOR) - impSym = NoSymbol - } - if (defSym.exists) { - if (impSym.exists) - ambiguousError( - "it is both defined in "+defSym.owner + - " and imported subsequently by \n"+imports.head) - else if (!defSym.owner.isClass || defSym.owner.isPackageClass || defSym.isTypeParameterOrSkolem) - pre = NoPrefix - else - qual = atPos(tree.pos.focusStart)(gen.mkAttributedQualifier(pre)) - } else { - if (impSym.exists) { - var impSym1: Symbol = NoSymbol - var imports1 = imports.tail - - /** It's possible that seemingly conflicting identifiers are - * identifiably the same after type normalization. In such cases, - * allow compilation to proceed. A typical example is: - * package object foo { type InputStream = java.io.InputStream } - * import foo._, java.io._ - */ - def ambiguousImport() = { - // The types of the qualifiers from which the ambiguous imports come. - // If the ambiguous name is a value, these must be the same. - def t1 = imports.head.qual.tpe - def t2 = imports1.head.qual.tpe - // The types of the ambiguous symbols, seen as members of their qualifiers. - // If the ambiguous name is a monomorphic type, we can relax this far. - def mt1 = t1 memberType impSym - def mt2 = t2 memberType impSym1 - def characterize = List( - s"types: $t1 =:= $t2 ${t1 =:= t2} members: ${mt1 =:= mt2}", - s"member type 1: $mt1", - s"member type 2: $mt2", - s"$impSym == $impSym1 ${impSym == impSym1}", - s"${impSym.debugLocationString} ${impSym.getClass}", - s"${impSym1.debugLocationString} ${impSym1.getClass}" - ).mkString("\n ") - - // The symbol names are checked rather than the symbols themselves because - // each time an overloaded member is looked up it receives a new symbol. - // So foo.member("x") != foo.member("x") if x is overloaded. This seems - // likely to be the cause of other bugs too... - if (t1 =:= t2 && impSym.name == impSym1.name) - log(s"Suppressing ambiguous import: $t1 =:= $t2 && $impSym == $impSym1") - // Monomorphism restriction on types is in part because type aliases could have the - // same target type but attach different variance to the parameters. Maybe it can be - // relaxed, but doesn't seem worth it at present. - else if (mt1 =:= mt2 && name.isTypeName && impSym.isMonomorphicType && impSym1.isMonomorphicType) - log(s"Suppressing ambiguous import: $mt1 =:= $mt2 && $impSym and $impSym1 are equivalent") - else { - log(s"Import is genuinely ambiguous:\n " + characterize) - ambiguousError(s"it is imported twice in the same scope by\n${imports.head}\nand ${imports1.head}") - } - } - while (errorContainer == null && !imports1.isEmpty && - (!imports.head.isExplicitImport(name) || - imports1.head.depth == imports.head.depth)) { - impSym1 = imports1.head.importedSymbol(name) - if (reallyExists(impSym1)) { - if (imports1.head.isExplicitImport(name)) { - if (imports.head.isExplicitImport(name) || - imports1.head.depth != imports.head.depth) ambiguousImport() - impSym = impSym1 - imports = imports1 - } else if (!imports.head.isExplicitImport(name) && - imports1.head.depth == imports.head.depth) ambiguousImport() - } - imports1 = imports1.tail - } - defSym = impSym - val qual0 = imports.head.qual - if (!(shortenImports && qual0.symbol.isPackage)) // optimization: don't write out package prefixes - qual = atPos(tree.pos.focusStart)(resetPos(qual0.duplicate)) - pre = qual.tpe + import InferErrorGen._ + nameLookup match { + case LookupAmbiguous(msg) => issue(AmbiguousIdentError(tree, name, msg)) + case LookupInaccessible(sym, msg) => issue(AccessError(tree, sym, context, msg)) + case LookupNotFound => + inEmptyPackage orElse lookupInRoot(name) match { + case NoSymbol => issue(SymbolNotFoundError(tree, name, context.owner, startContext)) + case sym => typed1(tree setSymbol sym, mode, pt) } - else if (settings.exposeEmptyPackage.value && checkEmptyPackage()) - log("Allowing empty package member " + name + " due to settings.") + case LookupSucceeded(qual, sym) => + // this -> Foo.this + if (sym.isThisSym) + typed1(This(sym.owner) setPos tree.pos, mode, pt) + // Inferring classOf type parameter from expected type. Otherwise an + // actual call to the stubbed classOf method is generated, returning null. + else if (isPredefMemberNamed(sym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) + typedClassOf(tree, TypeTree(pt.typeArgs.head)) else { - if ((mode & QUALmode) != 0) { - val lastTry = rootMirror.missingHook(rootMirror.RootClass, name) - if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt) - } - if (settings.debug.value) { - log(context.imports)//debug - } - if (inaccessibleSym eq NoSymbol) { - // Avoiding some spurious error messages: see SI-2388. - if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) () - else identError(SymbolNotFoundError(tree, name, context.owner, startingIdentContext)) - } else - identError(InferErrorGen.AccessError( - tree, inaccessibleSym, context.enclClass.owner.thisType, context.enclClass.owner, - inaccessibleExplanation - )) - defSym = context.owner.newErrorSymbol(name) + val pre1 = if (sym.owner.isPackageClass) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe + val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name)) + val (tree2, pre2) = makeAccessible(tree1, sym, pre1, qual) + // SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid + // inference errors in pattern matching. + stabilize(tree2, pre2, mode, pt) modifyType dropIllegalStarTypes } - } - } - if (errorContainer != null) { - ErrorUtils.issueTypeError(errorContainer) - setError(tree) - } else { - if (defSym.owner.isPackageClass) - pre = defSym.owner.thisType - - // Inferring classOf type parameter from expected type. - if (defSym.isThisSym) { - typed1(This(defSym.owner) setPos tree.pos, mode, pt) - } - // Inferring classOf type parameter from expected type. Otherwise an - // actual call to the stubbed classOf method is generated, returning null. - else if (isPredefMemberNamed(defSym, nme.classOf) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) - typedClassOf(tree, TypeTree(pt.typeArgs.head)) - else { - val tree1 = ( - if (qual == EmptyTree) tree - // atPos necessary because qualifier might come from startContext - else atPos(tree.pos)(Select(qual, name)) - ) - val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual) - // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right? - val tree3 = stabilize(tree2, pre2, mode, pt) - // SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid - // inference errors in pattern matching. - tree3 setType dropRepeatedParamType(tree3.tpe) - } } } @@ -5078,7 +4720,7 @@ trait Typers extends Modes with Adaptations with Tags { val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType) if (tpt1.isErrorTyped) { tpt1 - } else if (!tpt1.hasSymbol) { + } else if (!tpt1.hasSymbolField) { AppliedTypeNoParametersError(tree, tpt1.tpe) } else { val tparams = tpt1.symbol.typeParams @@ -5132,7 +4774,7 @@ trait Typers extends Modes with Adaptations with Tags { val pid1 = typedQualifier(pdef.pid).asInstanceOf[RefTree] assert(sym.moduleClass ne NoSymbol, sym) // complete lazy annotations - val annots = sym.annotations + sym.annotations val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls)) .typedStats(pdef.stats, NoSymbol) treeCopy.PackageDef(tree, pid1, stats1) setType NoType @@ -5187,14 +4829,12 @@ trait Typers extends Modes with Adaptations with Tags { var block1 = typed(tree.block, pt) var catches1 = typedCases(tree.catches, ThrowableClass.tpe, pt) - for (cdef <- catches1 if cdef.guard.isEmpty) { - def warn(name: Name) = context.warning(cdef.pat.pos, s"This catches all Throwables. If this is really intended, use `case ${name.decoded} : Throwable` to clear this warning.") - def unbound(t: Tree) = t.symbol == null || t.symbol == NoSymbol - cdef.pat match { - case Bind(name, i @ Ident(_)) if unbound(i) => warn(name) - case i @ Ident(name) if unbound(i) => warn(name) - case _ => - } + for (cdef <- catches1; if treeInfo catchesThrowable cdef) { + val name = (treeInfo assignedNameOfPattern cdef).decoded + context.warning(cdef.pat.pos, + s"""|This catches all Throwables, which often has undesirable consequences. + |If intentional, use `case $name : Throwable` to clear this warning.""".stripMargin + ) } val finalizer1 = @@ -5439,28 +5079,21 @@ trait Typers extends Modes with Adaptations with Tags { } } - /** - * @param tree ... - * @param mode ... - * @param pt ... - * @return ... - */ def typed(tree: Tree, mode: Int, pt: Type): Tree = { lastTreeToTyper = tree indentTyping() - var alreadyTyped = false val startByType = if (Statistics.canEnable) Statistics.pushTimer(byTypeStack, byTypeNanos(tree.getClass)) else null if (Statistics.canEnable) Statistics.incCounter(visitsByType, tree.getClass) try { if (context.retyping && (tree.tpe ne null) && (tree.tpe.isErroneous || !(tree.tpe <:< pt))) { tree.tpe = null - if (tree.hasSymbol) tree.symbol = NoSymbol + if (tree.hasSymbolField) tree.symbol = NoSymbol } - alreadyTyped = tree.tpe ne null - var tree1: Tree = if (alreadyTyped) tree else { + val alreadyTyped = tree.tpe ne null + val tree1: Tree = if (alreadyTyped) tree else { printTyping( ptLine("typing %s: pt = %s".format(ptTree(tree), pt), "undetparams" -> context.undetparams, @@ -5516,10 +5149,7 @@ trait Typers extends Modes with Adaptations with Tags { def atOwner(tree: Tree, owner: Symbol): Typer = newTyper(context.make(tree, owner)) - /** Types expression or definition <code>tree</code>. - * - * @param tree ... - * @return ... + /** Types expression or definition `tree`. */ def typed(tree: Tree): Tree = { val ret = typed(tree, EXPRmode, WildcardType) @@ -5532,23 +5162,19 @@ trait Typers extends Modes with Adaptations with Tags { // it makes for a lot less casting. // def typedPos[T <: Tree](pos: Position)(tree: T): T = typed(atPos(pos)(tree)).asInstanceOf[T] - /** Types expression <code>tree</code> with given prototype <code>pt</code>. - * - * @param tree ... - * @param pt ... - * @return ... + /** Types expression `tree` with given prototype `pt`. */ def typed(tree: Tree, pt: Type): Tree = typed(tree, EXPRmode, pt) - /** Types qualifier <code>tree</code> of a select node. - * E.g. is tree occurs in a context like <code>tree.m</code>. + /** Types qualifier `tree` of a select node. + * E.g. is tree occurs in a context like `tree.m`. */ def typedQualifier(tree: Tree, mode: Int, pt: Type): Tree = typed(tree, EXPRmode | QUALmode | POLYmode | mode & TYPEPATmode, pt) // TR: don't set BYVALmode, since qualifier might end up as by-name param to an implicit - /** Types qualifier <code>tree</code> of a select node. - * E.g. is tree occurs in a context like <code>tree.m</code>. + /** Types qualifier `tree` of a select node. + * E.g. is tree occurs in a context like `tree.m`. */ def typedQualifier(tree: Tree, mode: Int): Tree = typedQualifier(tree, mode, WildcardType) @@ -5559,7 +5185,7 @@ trait Typers extends Modes with Adaptations with Tags { def typedOperator(tree: Tree): Tree = typed(tree, EXPRmode | FUNmode | POLYmode | TAPPmode, WildcardType) - /** Types a pattern with prototype <code>pt</code> */ + /** Types a pattern with prototype `pt` */ def typedPattern(tree: Tree, pt: Type): Tree = { // We disable implicits because otherwise some constructs will // type check which should not. The pattern matcher does not @@ -5597,8 +5223,6 @@ trait Typers extends Modes with Adaptations with Tags { def typedHigherKindedType(tree: Tree, mode: Int): Tree = typed(tree, HKmode, WildcardType) - def typedHigherKindedType(tree: Tree): Tree = typedHigherKindedType(tree, NOmode) - /** Types a type constructor tree used in a new or supertype */ def typedTypeConstructor(tree: Tree, mode: Int): Tree = { val result = typed(tree, forTypeMode(mode) | FUNmode, WildcardType) @@ -5673,28 +5297,17 @@ trait Typers extends Modes with Adaptations with Tags { case Some(tree1) => transformed -= tree; tree1 case None => typed(tree, mode, pt) } - -/* - def convertToTypeTree(tree: Tree): Tree = tree match { - case TypeTree() => tree - case _ => TypeTree(tree.tpe) - } -*/ } } object TypersStats { import scala.reflect.internal.TypesStats._ - import scala.reflect.internal.BaseTypeSeqsStats._ val typedIdentCount = Statistics.newCounter("#typechecked identifiers") val typedSelectCount = Statistics.newCounter("#typechecked selections") val typedApplyCount = Statistics.newCounter("#typechecked applications") val rawTypeFailed = Statistics.newSubCounter (" of which in failed", rawTypeCount) val subtypeFailed = Statistics.newSubCounter(" of which in failed", subtypeCount) val findMemberFailed = Statistics.newSubCounter(" of which in failed", findMemberCount) - val compoundBaseTypeSeqCount = Statistics.newSubCounter(" of which for compound types", baseTypeSeqCount) - val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount) - val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount) val failedSilentNanos = Statistics.newSubTimer("time spent in failed", typerNanos) val failedApplyNanos = Statistics.newSubTimer(" failed apply", typerNanos) val failedOpEqNanos = Statistics.newSubTimer(" failed op=", typerNanos) diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index bf44b65406..061c6679da 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -23,7 +23,6 @@ trait Unapplies extends ast.TreeDSL private val unapplyParamName = nme.x_0 - // In the typeCompleter (templateSig) of a case class (resp it's module), // synthetic `copy` (reps `apply`, `unapply`) methods are added. To compute // their signatures, the corresponding ClassDef is needed. During naming (in @@ -46,17 +45,6 @@ trait Unapplies extends ast.TreeDSL } } - /** returns type of the unapply method returning T_0...T_n - * for n == 0, boolean - * for n == 1, Some[T0] - * else Some[Product[Ti]] - */ - def unapplyReturnTypeExpected(argsLength: Int) = argsLength match { - case 0 => BooleanClass.tpe - case 1 => optionType(WildcardType) - case n => optionType(productType((List fill n)(WildcardType))) - } - /** returns unapply or unapplySeq if available */ def unapplyMember(tp: Type): Symbol = (tp member nme.unapply) match { case NoSymbol => tp member nme.unapplySeq diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala index 7d97b0c782..aa66a8d00a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala @@ -40,7 +40,7 @@ trait Variances { (VARIANCES /: tps) ((v, tp) => v & varianceInType(tp)(tparam)) /** Compute variance of type parameter `tparam` in all type arguments - * <code>tps</code> which correspond to formal type parameters `tparams1`. + * `tps` which correspond to formal type parameters `tparams1`. */ def varianceInArgs(tps: List[Type], tparams1: List[Symbol])(tparam: Symbol): Int = { var v: Int = VARIANCES; @@ -63,10 +63,12 @@ trait Variances { varianceInType(annot.atp)(tparam) } - /** Compute variance of type parameter <code>tparam</code> in type <code>tp</code>. */ + /** Compute variance of type parameter `tparam` in type `tp`. */ def varianceInType(tp: Type)(tparam: Symbol): Int = tp match { case ErrorType | WildcardType | NoType | NoPrefix | ThisType(_) | ConstantType(_) => VARIANCES + case BoundedWildcardType(bounds) => + varianceInType(bounds)(tparam) case SingleType(pre, sym) => varianceInType(pre)(tparam) case TypeRef(pre, sym, args) => diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala index 8732e06502..ee66801c45 100644 --- a/src/compiler/scala/tools/nsc/util/ClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -11,7 +11,6 @@ import java.net.URL import scala.collection.{ mutable, immutable } import io.{ File, Directory, Path, Jar, AbstractFile } import scala.reflect.internal.util.StringOps.splitWhere -import scala.reflect.ClassTag import Jar.isJarOrZip import File.pathSeparator import java.net.MalformedURLException @@ -32,10 +31,6 @@ object ClassPath { def lsDir(dir: Directory, filt: String => Boolean = _ => true) = dir.list filter (x => filt(x.name) && (x.isDirectory || isJarOrZip(x))) map (_.path) toList - def basedir(s: String) = - if (s contains File.separator) s.substring(0, s.lastIndexOf(File.separator)) - else "." - if (pattern == "*") lsDir(Directory(".")) else if (pattern endsWith wildSuffix) lsDir(Directory(pattern dropRight 2)) else if (pattern contains '*') { @@ -54,22 +49,6 @@ object ClassPath { /** Split the classpath, apply a transformation function, and reassemble it. */ def map(cp: String, f: String => String): String = join(split(cp) map f: _*) - /** Split the classpath, filter according to predicate, and reassemble. */ - def filter(cp: String, p: String => Boolean): String = join(split(cp) filter p: _*) - - /** Split the classpath and map them into Paths */ - def toPaths(cp: String): List[Path] = split(cp) map (x => Path(x).toAbsolute) - - /** Make all classpath components absolute. */ - def makeAbsolute(cp: String): String = fromPaths(toPaths(cp): _*) - - /** Join the paths as a classpath */ - def fromPaths(paths: Path*): String = join(paths map (_.path): _*) - def fromURLs(urls: URL*): String = fromPaths(urls map (x => Path(x.getPath)) : _*) - - /** Split the classpath and map them into URLs */ - def toURLs(cp: String): List[URL] = toPaths(cp) map (_.toURL) - /** Expand path and possibly expanding stars */ def expandPath(path: String, expandStar: Boolean = true): List[String] = if (expandStar) split(path) flatMap expandS @@ -129,13 +108,6 @@ object ClassPath { for (dir <- expandPath(path, false) ; name <- expandDir(dir) ; entry <- Option(AbstractFile getDirectory name)) yield newClassPath(entry) - def classesAtAllURLS(path: String): List[ClassPath[T]] = - (path split " ").toList flatMap classesAtURL - - def classesAtURL(spec: String) = - for (url <- specToURL(spec).toList ; location <- Option(AbstractFile getURL url)) yield - newClassPath(location) - def classesInExpandedPath(path: String): IndexedSeq[ClassPath[T]] = classesInPathImpl(path, true).toIndexedSeq @@ -404,15 +376,3 @@ class JavaClassPath( containers: IndexedSeq[ClassPath[AbstractFile]], context: JavaContext) extends MergedClassPath[AbstractFile](containers, context) { } - -object JavaClassPath { - def fromURLs(urls: Seq[URL], context: JavaContext): JavaClassPath = { - val containers = { - for (url <- urls ; f = AbstractFile getURL url ; if f != null) yield - new DirectoryClassPath(f, context) - } - new JavaClassPath(containers.toIndexedSeq, context) - } - def fromURLs(urls: Seq[URL]): JavaClassPath = - fromURLs(urls, ClassPath.DefaultJavaContext) -} diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala index 9cf2c535df..e8f962a9e2 100644 --- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala +++ b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package util import scala.util.parsing.combinator._ -import scala.util.parsing.input.{ Reader } import scala.util.parsing.input.CharArrayReader.EofCh import scala.collection.mutable.ListBuffer @@ -22,7 +21,6 @@ import scala.collection.mutable.ListBuffer trait ParserUtil extends Parsers { protected implicit class ParserPlus[+T](underlying: Parser[T]) { def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b } - def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a } } } @@ -38,7 +36,6 @@ case class CommandLine( def withUnaryArgs(xs: List[String]) = copy(unaryArguments = xs) def withBinaryArgs(xs: List[String]) = copy(binaryArguments = xs) - def originalArgs = args def assumeBinary = true def enforceArity = true def onlyKnownOptions = false @@ -106,7 +103,6 @@ case class CommandLine( def isSet(arg: String) = args contains arg def get(arg: String) = argMap get arg - def getOrElse(arg: String, orElse: => String) = if (isSet(arg)) apply(arg) else orElse def apply(arg: String) = argMap(arg) override def toString() = "CommandLine(\n%s)\n" format (args map (" " + _ + "\n") mkString) @@ -116,7 +112,6 @@ object CommandLineParser extends RegexParsers with ParserUtil { override def skipWhitespace = false def elemExcept(xs: Elem*): Parser[Elem] = elem("elemExcept", x => x != EofCh && !(xs contains x)) - def elemOf(xs: Elem*): Parser[Elem] = elem("elemOf", xs contains _) def escaped(ch: Char): Parser[String] = "\\" + ch def mkQuoted(ch: Char): Parser[String] = ( elem(ch) !~> rep(escaped(ch) | elemExcept(ch)) <~ ch ^^ (_.mkString) diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala index 34344263e8..1608ffa425 100644 --- a/src/compiler/scala/tools/nsc/util/Exceptional.scala +++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala @@ -3,8 +3,6 @@ package util import java.util.concurrent.ExecutionException import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } -import scala.reflect.internal.util.StringOps._ -import scala.language.implicitConversions object Exceptional { def unwrap(x: Throwable): Throwable = x match { diff --git a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala index 5421843438..e877c990f0 100644 --- a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala +++ b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala @@ -14,11 +14,6 @@ trait FreshNameCreator { */ def newName(): String def newName(prefix: String): String - - @deprecated("use newName(prefix)", "2.9.0") - def newName(pos: scala.reflect.internal.util.Position, prefix: String): String = newName(prefix) - @deprecated("use newName()", "2.9.0") - def newName(pos: scala.reflect.internal.util.Position): String = newName() } object FreshNameCreator { diff --git a/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala b/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala index b7ed7903bc..fc3dd2bac2 100644 --- a/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala +++ b/src/compiler/scala/tools/nsc/util/JavaCharArrayReader.scala @@ -14,74 +14,32 @@ class JavaCharArrayReader(buf: IndexedSeq[Char], start: Int, /* startline: int, def this(buf: IndexedSeq[Char], decodeUni: Boolean, error: String => Unit) = this(buf, 0, /* 1, 1, */ decodeUni, error) - /** produce a duplicate of this char array reader which starts reading - * at current position, independent of what happens to original reader - */ - def dup: JavaCharArrayReader = clone().asInstanceOf[JavaCharArrayReader] - - /** layout constant - */ - val tabinc = 8 - /** the line and column position of the current character */ var ch: Char = _ var bp = start - var oldBp = -1 - var oldCh: Char = _ - - //private var cline: Int = _ - //private var ccol: Int = _ def cpos = bp var isUnicode: Boolean = _ - var lastLineStartPos: Int = 0 - var lineStartPos: Int = 0 - var lastBlankLinePos: Int = 0 - - private var onlyBlankChars = false - //private var nextline = startline - //private var nextcol = startcol - - private def markNewLine() { - lastLineStartPos = lineStartPos - if (onlyBlankChars) lastBlankLinePos = lineStartPos - lineStartPos = bp - onlyBlankChars = true - //nextline += 1 - //nextcol = 1 - } - - def hasNext: Boolean = if (bp < buf.length) true - else { - false - } - def last: Char = if (bp > start + 2) buf(bp - 2) else ' ' // XML literals + def hasNext = bp < buf.length def next(): Char = { - //cline = nextline - //ccol = nextcol val buf = this.buf.asInstanceOf[collection.mutable.WrappedArray[Char]].array if(!hasNext) { ch = SU return SU // there is an endless stream of SU's at the end } - oldBp = bp - oldCh = ch ch = buf(bp) isUnicode = false bp = bp + 1 ch match { case '\t' => - // nextcol = ((nextcol - 1) / tabinc * tabinc) + tabinc + 1; case CR => if (bp < buf.size && buf(bp) == LF) { ch = LF bp += 1 } - markNewLine() case LF | FF => - markNewLine() case '\\' => def evenSlashPrefix: Boolean = { var p = bp - 2 @@ -90,11 +48,10 @@ class JavaCharArrayReader(buf: IndexedSeq[Char], start: Int, /* startline: int, } def udigit: Int = { val d = digit2int(buf(bp), 16) - if (d >= 0) { bp += 1; /* nextcol = nextcol + 1 */ } + if (d >= 0) bp += 1 else error("error in unicode escape"); d } - // nextcol += 1 if (buf(bp) == 'u' && decodeUni && evenSlashPrefix) { do { bp += 1 //; nextcol += 1 @@ -104,20 +61,10 @@ class JavaCharArrayReader(buf: IndexedSeq[Char], start: Int, /* startline: int, isUnicode = true } case _ => - if (ch > ' ') onlyBlankChars = false - // nextcol += 1 } ch } - def rewind() { - if (oldBp == -1) throw new IllegalArgumentException - bp = oldBp - ch = oldCh - oldBp = -1 - oldCh = 'x' - } - def copy: JavaCharArrayReader = new JavaCharArrayReader(buf, bp, /* nextcol, nextline, */ decodeUni, error) } diff --git a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala index aa3b7c286d..2f209c550d 100644 --- a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala +++ b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala @@ -8,9 +8,6 @@ package scala.tools.nsc package util -import java.io.File -import java.net.URL -import java.util.StringTokenizer import scala.util.Sorting import scala.collection.mutable import scala.tools.nsc.io.{ AbstractFile, MsilFile } @@ -166,4 +163,4 @@ class AssemblyClassPath(types: Array[MSILType], namespace: String, val context: * MSILType values. */ class MsilClassPath(ext: String, user: String, source: String, context: MsilContext) -extends MergedClassPath[MsilFile](MsilClassPath.assembleEntries(ext, user, source, context), context) { }
\ No newline at end of file +extends MergedClassPath[MsilFile](MsilClassPath.assembleEntries(ext, user, source, context), context) { } diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala index 1f6fa68f57..1d2cc73c6b 100644 --- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala +++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala @@ -46,9 +46,6 @@ trait ScalaClassLoader extends JClassLoader { def create(path: String): AnyRef = tryToInitializeClass[AnyRef](path) map (_.newInstance()) orNull - def constructorsOf[T <: AnyRef : ClassTag]: List[Constructor[T]] = - classTag[T].runtimeClass.getConstructors.toList map (_.asInstanceOf[Constructor[T]]) - /** The actual bytes for a class file, or an empty array if it can't be found. */ def classBytes(className: String): Array[Byte] = classAsStream(className) match { case null => Array() @@ -71,14 +68,6 @@ trait ScalaClassLoader extends JClassLoader { try asContext(method.invoke(null, Array(arguments.toArray: AnyRef): _*)) // !!! : AnyRef shouldn't be necessary catch unwrapHandler({ case ex => throw ex }) } - - /** A list comprised of this classloader followed by all its - * (non-null) parent classloaders, if any. - */ - def loaderChain: List[ScalaClassLoader] = this :: (getParent match { - case null => Nil - case p => p.loaderChain - }) } /** Methods for obtaining various classloaders. @@ -99,35 +88,6 @@ object ScalaClassLoader { } def contextLoader = apply(Thread.currentThread.getContextClassLoader) def appLoader = apply(JClassLoader.getSystemClassLoader) - def extLoader = apply(appLoader.getParent) - def bootLoader = apply(null) - def contextChain = loaderChain(contextLoader) - - def pathToErasure[T: ClassTag] = pathToClass(classTag[T].runtimeClass) - def pathToClass(clazz: Class[_]) = clazz.getName.replace('.', JFile.separatorChar) + ".class" - def locate[T: ClassTag] = contextLoader getResource pathToErasure[T] - - /** Tries to guess the classpath by type matching the context classloader - * and its parents, looking for any classloaders which will reveal their - * classpath elements as urls. It it can't find any, creates a classpath - * from the supplied string. - */ - def guessClassPathString(default: String = ""): String = { - val classpathURLs = contextChain flatMap { - case x: HasClassPath => x.classPathURLs - case x: JURLClassLoader => x.getURLs.toSeq - case _ => Nil - } - if (classpathURLs.isEmpty) default - else JavaClassPath.fromURLs(classpathURLs).asClasspathString - } - - def loaderChain(head: JClassLoader) = { - def loop(cl: JClassLoader): List[JClassLoader] = - if (cl == null) Nil else cl :: loop(cl.getParent) - - loop(head) - } def setContext(cl: JClassLoader) = Thread.currentThread.setContextClassLoader(cl) def savingContextLoader[T](body: => T): T = { @@ -142,16 +102,13 @@ object ScalaClassLoader { with HasClassPath { private var classloaderURLs: Seq[URL] = urls - private def classpathString = ClassPath.fromURLs(urls: _*) def classPathURLs: Seq[URL] = classloaderURLs - def classPath: ClassPath[_] = JavaClassPath fromURLs classPathURLs /** Override to widen to public */ override def addURL(url: URL) = { classloaderURLs :+= url super.addURL(url) } - def toLongString = urls.mkString("URLClassLoader(\n ", "\n ", "\n)\n") } def fromURLs(urls: Seq[URL], parent: ClassLoader = null): URLClassLoader = @@ -162,7 +119,6 @@ object ScalaClassLoader { fromURLs(urls) tryToLoadClass name isDefined /** Finding what jar a clazz or instance came from */ - def origin(x: Any): Option[URL] = originOfClass(x.getClass) def originOfClass(x: Class[_]): Option[URL] = Option(x.getProtectionDomain.getCodeSource) flatMap (x => Option(x.getLocation)) } diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala index 2b87280c24..759c06dc0f 100644 --- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala +++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala @@ -7,7 +7,7 @@ package scala.tools package nsc package util -import java.io.{File, FileInputStream, PrintStream} +import java.io.PrintStream import java.lang.Long.toHexString import java.lang.Float.intBitsToFloat import java.lang.Double.longBitsToDouble @@ -94,7 +94,6 @@ object ShowPickled extends Names { case ANNOTATEDtpe => "ANNOTATEDtpe" case ANNOTINFO => "ANNOTINFO" case ANNOTARGARRAY => "ANNOTARGARRAY" - // case DEBRUIJNINDEXtpe => "DEBRUIJNINDEXtpe" case EXISTENTIALtpe => "EXISTENTIALtpe" case TREE => "TREE" case MODIFIERS => "MODIFIERS" diff --git a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala index b103ae9cb0..a33af1754d 100644 --- a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala +++ b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala @@ -14,6 +14,5 @@ class SimpleTracer(out: PrintStream, enabled: Boolean = true) { if (enabled) out.println(msg+value) value } - def withOutput(out: PrintStream) = new SimpleTracer(out, enabled) def when(enabled: Boolean): SimpleTracer = new SimpleTracer(out, enabled) } diff --git a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala index b1f4696d3e..4f7a9ff878 100644 --- a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala +++ b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala @@ -7,9 +7,9 @@ class WorkScheduler { type Action = () => Unit - private var todo = new mutable.Queue[Action] - private var throwables = new mutable.Queue[Throwable] - private var interruptReqs = new mutable.Queue[InterruptReq] + private val todo = new mutable.Queue[Action] + private val throwables = new mutable.Queue[Throwable] + private val interruptReqs = new mutable.Queue[InterruptReq] /** Called from server: block until one of todo list, throwables or interruptReqs is nonempty */ def waitForMoreWork() = synchronized { diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala index d34d4ee092..792a659ad6 100644 --- a/src/compiler/scala/tools/nsc/util/package.scala +++ b/src/compiler/scala/tools/nsc/util/package.scala @@ -18,16 +18,9 @@ package object util { type HashSet[T >: Null <: AnyRef] = scala.reflect.internal.util.HashSet[T] val HashSet = scala.reflect.internal.util.HashSet - def onull[T](value: T, orElse: => T): T = if (value == null) orElse else value - /** Apply a function and return the passed value */ def returning[T](x: T)(f: T => Unit): T = { f(x) ; x } - /** Frequency counter */ - def freq[T](xs: Traversable[T]): Map[T, Int] = xs groupBy identity mapValues (_.size) - - def freqrank[T](xs: Traversable[(T, Int)]): List[(Int, T)] = xs.toList map (_.swap) sortBy (-_._1) - /** Execute code and then wait for all non-daemon Threads * created and begun during its execution to complete. */ @@ -54,18 +47,6 @@ package object util { (result, ts2 filterNot (ts1 contains _)) } - /** Given a function and a block of code, evaluates code block, - * calls function with milliseconds elapsed, and returns block result. - */ - def millisElapsedTo[T](f: Long => Unit)(body: => T): T = { - val start = System.currentTimeMillis - val result = body - val end = System.currentTimeMillis - - f(end - start) - result - } - /** Generate a string using a routine that wants to write on a stream. */ def stringFromWriter(writer: PrintWriter => Unit): String = { val stringWriter = new StringWriter() @@ -83,8 +64,19 @@ package object util { } def stackTraceString(ex: Throwable): String = stringFromWriter(ex printStackTrace _) + /** A one line string which contains the class of the exception, the + * message if any, and the first non-Predef location in the stack trace + * (to exclude assert, require, etc.) + */ + def stackTraceHeadString(ex: Throwable): String = { + val frame = ex.getStackTrace.dropWhile(_.getClassName contains "Predef").head + val msg = ex.getMessage match { case null | "" => "" ; case s => s"""("$s")""" } + val clazz = ex.getClass.getName.split('.').last + + s"$clazz$msg @ $frame" + } + lazy val trace = new SimpleTracer(System.out) - lazy val errtrace = new SimpleTracer(System.err) @deprecated("Moved to scala.reflect.internal.util.StringOps", "2.10.0") val StringOps = scala.reflect.internal.util.StringOps diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala index 86cd845c54..d7c50504a8 100644 --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala @@ -1,6 +1,5 @@ package scala.tools.reflect -import scala.reflect.macros.{ReificationException, UnexpectedReificationException} import scala.reflect.macros.runtime.Context import scala.collection.mutable.ListBuffer import scala.collection.mutable.Stack @@ -147,4 +146,4 @@ abstract class MacroImplementations { Block(evals.toList, atPos(origApplyPos.focus)(expr)) setPos origApplyPos.makeTransparent } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/reflect/ReflectMain.scala b/src/compiler/scala/tools/reflect/ReflectMain.scala index 116ae24cdd..3ae21b6b98 100644 --- a/src/compiler/scala/tools/reflect/ReflectMain.scala +++ b/src/compiler/scala/tools/reflect/ReflectMain.scala @@ -4,7 +4,6 @@ package reflect import scala.tools.nsc.Driver import scala.tools.nsc.Global import scala.tools.nsc.Settings -import scala.tools.nsc.util.ClassPath.DefaultJavaContext import scala.tools.nsc.util.ScalaClassLoader import scala.tools.util.PathResolver @@ -16,4 +15,4 @@ object ReflectMain extends Driver { } override def newCompiler(): Global = new ReflectGlobal(settings, reporter, classloaderFromSettings(settings)) -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/reflect/StdTags.scala b/src/compiler/scala/tools/reflect/StdTags.scala index a3bc9b9bd1..5c62819f04 100644 --- a/src/compiler/scala/tools/reflect/StdTags.scala +++ b/src/compiler/scala/tools/reflect/StdTags.scala @@ -1,7 +1,6 @@ package scala.tools package reflect -import java.lang.{Class => jClass} import scala.reflect.{ClassTag, classTag} import scala.reflect.api.{Mirror, TypeCreator, Universe => ApiUniverse} diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 95135b84e0..b1d343cee9 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -3,12 +3,8 @@ package reflect import scala.tools.nsc.reporters._ import scala.tools.nsc.CompilerCommand -import scala.tools.nsc.Global -import scala.tools.nsc.typechecker.Modes import scala.tools.nsc.io.VirtualDirectory import scala.tools.nsc.interpreter.AbstractFileClassLoader -import scala.tools.nsc.util.FreshNameCreator -import scala.reflect.internal.Flags import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, NoFile} import java.lang.{Class => jClass} import scala.compat.Platform.EOL @@ -29,8 +25,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, factorySelf.mirror.classLoader) lazy val mirror: u.Mirror = u.runtimeMirror(classLoader) - class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter: Reporter) - extends ReflectGlobal(settings, reporter, toolBoxSelf.classLoader) { + class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter0: Reporter) + extends ReflectGlobal(settings, reporter0, toolBoxSelf.classLoader) { import definitions._ private val trace = scala.tools.nsc.util.trace when settings.debug.value @@ -73,13 +69,14 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val typed = expr filter (t => t.tpe != null && t.tpe != NoType && !t.isInstanceOf[TypeTree]) if (!typed.isEmpty) throw ToolBoxError("reflective toolbox has failed: cannot operate on trees that are already typed") - val freeTypes = expr.freeTypes - if (freeTypes.length > 0) { - var msg = "reflective toolbox has failed:" + EOL - msg += "unresolved free type variables (namely: " + (freeTypes map (ft => "%s %s".format(ft.name, ft.origin)) mkString ", ") + "). " - msg += "have you forgot to use TypeTag annotations for type parameters external to a reifee? " - msg += "if you have troubles tracking free type variables, consider using -Xlog-free-types" - throw ToolBoxError(msg) + if (expr.freeTypes.nonEmpty) { + val ft_s = expr.freeTypes map (ft => s" ${ft.name} ${ft.origin}") mkString "\n " + throw ToolBoxError(s""" + |reflective toolbox failed due to unresolved free type variables: + |$ft_s + |have you forgotten to use TypeTag annotations for type parameters external to a reifee? + |if you have troubles tracking free type variables, consider using -Xlog-free-types + """.stripMargin.trim) } } @@ -100,9 +97,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => if (namesakes.length > 0) name += ("$" + (namesakes.length + 1)) freeTermNames += (ft -> newTermName(name + nme.REIFY_FREE_VALUE_SUFFIX)) }) - var expr = new Transformer { + val expr = new Transformer { override def transform(tree: Tree): Tree = - if (tree.hasSymbol && tree.symbol.isFreeTerm) { + if (tree.hasSymbolField && tree.symbol.isFreeTerm) { tree match { case Ident(_) => val freeTermRef = Ident(freeTermNames(tree.symbol.asFreeTerm)) @@ -132,7 +129,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val ownerClass = rootMirror.EmptyPackageClass.newClassSymbol(newTypeName("<expression-owner>")) build.setTypeSignature(ownerClass, ClassInfoType(List(ObjectClass.tpe), newScope, ownerClass)) val owner = ownerClass.newLocalDummy(expr.pos) - var currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr, owner)) + val currentTyper = analyzer.newTyper(analyzer.rootContext(NoCompilationUnit, EmptyTree).make(expr, owner)) val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _) val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _) def wrapper (tree: => Tree) = wrapper1(wrapper2(tree)) @@ -146,7 +143,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => case Block(dummies, unwrapped) => (dummies, unwrapped) case unwrapped => (Nil, unwrapped) } - var invertedIndex = freeTerms map (_.swap) + val invertedIndex = freeTerms map (_.swap) // todo. also fixup singleton types unwrapped = new Transformer { override def transform(tree: Tree): Tree = @@ -202,7 +199,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def wrap(expr0: Tree): ModuleDef = { val (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = true) - val (obj, mclazz) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol( + val (obj, _) = rootMirror.EmptyPackageClass.newModuleAndClassSymbol( nextWrapperModuleName()) val minfo = ClassInfoType(List(ObjectClass.tpe), newScope, obj.moduleClass) @@ -235,7 +232,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => NoPosition)) trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value)) - var cleanedUp = resetLocalAttrs(moduledef) + val cleanedUp = resetLocalAttrs(moduledef) trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value)) cleanedUp.asInstanceOf[ModuleDef] } @@ -312,11 +309,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => // reporter doesn't accumulate errors, but the front-end does def throwIfErrors() = { - if (frontEnd.hasErrors) { - var msg = "reflective compilation has failed: " + EOL + EOL - msg += frontEnd.infos map (_.msg) mkString EOL - throw ToolBoxError(msg) - } + if (frontEnd.hasErrors) throw ToolBoxError( + "reflective compilation has failed: " + EOL + EOL + (frontEnd.infos map (_.msg) mkString EOL) + ) } } @@ -336,15 +331,15 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => command.settings.outputDirs setSingleOutput virtualDirectory val instance = new ToolBoxGlobal(command.settings, frontEndToReporter(frontEnd, command.settings)) if (frontEnd.hasErrors) { - var msg = "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL - msg += frontEnd.infos map (_.msg) mkString EOL - throw ToolBoxError(msg) + throw ToolBoxError( + "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL + + (frontEnd.infos map (_.msg) mkString EOL) + ) } instance } catch { case ex: Throwable => - var msg = "reflective compilation has failed: cannot initialize the compiler due to %s".format(ex.toString) - throw ToolBoxError(msg, ex) + throw ToolBoxError(s"reflective compilation has failed: cannot initialize the compiler due to $ex", ex) } } @@ -353,8 +348,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = compiler.withCleanupCaches { if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType) - var ctree: compiler.Tree = importer.importTree(tree) - var cexpectedType: compiler.Type = importer.importType(expectedType) + val ctree: compiler.Tree = importer.importTree(tree) + val cexpectedType: compiler.Type = importer.importType(expectedType) if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType) val ttree: compiler.Tree = compiler.typeCheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) @@ -373,9 +368,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = compiler.withCleanupCaches { if (compiler.settings.verbose.value) println("importing "+pt, ", tree = "+tree+", pos = "+pos) - var ctree: compiler.Tree = importer.importTree(tree) - var cpt: compiler.Type = importer.importType(pt) - var cpos: compiler.Position = importer.importPosition(pos) + val ctree: compiler.Tree = importer.importTree(tree) + val cpt: compiler.Type = importer.importType(pt) + val cpos: compiler.Position = importer.importPosition(pos) if (compiler.settings.verbose.value) println("inferring implicit %s of type %s, macros = %s".format(if (isView) "view" else "value", pt, !withMacrosDisabled)) val itree: compiler.Tree = compiler.inferImplicit(ctree, cpt, isView = isView, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = cpos) @@ -397,9 +392,6 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => uttree } - def showAttributed(tree: u.Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = - compiler.showAttributed(importer.importTree(tree), printTypes, printIds, printKinds) - def parse(code: String): u.Tree = { if (compiler.settings.verbose.value) println("parsing "+code) val ctree: compiler.Tree = compiler.parse(code) @@ -409,7 +401,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def compile(tree: u.Tree): () => Any = { if (compiler.settings.verbose.value) println("importing "+tree) - var ctree: compiler.Tree = importer.importTree(tree) + val ctree: compiler.Tree = importer.importTree(tree) if (compiler.settings.verbose.value) println("compiling "+ctree) compiler.compile(ctree) diff --git a/src/compiler/scala/tools/reflect/package.scala b/src/compiler/scala/tools/reflect/package.scala index 3f880bf7f8..bf533766d0 100644 --- a/src/compiler/scala/tools/reflect/package.scala +++ b/src/compiler/scala/tools/reflect/package.scala @@ -76,7 +76,6 @@ package object reflect { private[reflect] def frontEndToReporter(frontEnd: FrontEnd, settings0: Settings): Reporter = new AbstractReporter { val settings = settings0 - import frontEnd.{Severity => ApiSeverity} val API_INFO = frontEnd.INFO val API_WARNING = frontEnd.WARNING val API_ERROR = frontEnd.ERROR diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala index c3264d0787..381dbd1d87 100644 --- a/src/compiler/scala/tools/util/Javap.scala +++ b/src/compiler/scala/tools/util/Javap.scala @@ -6,10 +6,8 @@ package scala.tools package util -import java.lang.reflect.{ GenericSignatureFormatError, Method, Constructor } -import java.lang.{ ClassLoader => JavaClassLoader } import scala.tools.nsc.util.ScalaClassLoader -import java.io.{ InputStream, PrintWriter, ByteArrayInputStream, FileNotFoundException } +import java.io.{ InputStream, PrintWriter, ByteArrayInputStream } import scala.tools.nsc.io.File import Javap._ import scala.language.reflectiveCalls @@ -109,19 +107,11 @@ object Javap { type FakeEnvironment = AnyRef type FakePrinter = AnyRef - def apply(path: String): Unit = apply(Seq(path)) - def apply(args: Seq[String]): Unit = new JavapClass() apply args foreach (_.show()) - sealed trait JpResult { type ResultType def isError: Boolean def value: ResultType def show(): Unit - // todo - // def header(): String - // def fields(): List[String] - // def methods(): List[String] - // def signatures(): List[String] } class JpError(msg: String) extends JpResult { type ResultType = String diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 0af1011bda..5d79a7d6cd 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -6,7 +6,6 @@ package scala.tools package util -import java.net.{ URL, MalformedURLException } import scala.tools.reflect.WrappedProperties.AccessControl import nsc.{ Settings, GenericRunnerSettings } import nsc.util.{ ClassPath, JavaClassPath, ScalaClassLoader } @@ -19,16 +18,9 @@ import scala.language.postfixOps // https://wiki.scala-lang.org/display/SW/Classpath object PathResolver { - // Imports property/environment functions which suppress - // security exceptions. + // Imports property/environment functions which suppress security exceptions. import AccessControl._ - def firstNonEmpty(xs: String*) = xs find (_ != "") getOrElse "" - - /** Map all classpath elements to absolute paths and reconstruct the classpath. - */ - def makeAbsolute(cp: String) = ClassPath.map(cp, x => Path(x).toAbsolute.path) - /** pretty print class path */ def ppcp(s: String) = split(s) match { case Nil => "" @@ -46,7 +38,6 @@ object PathResolver { /** Environment variables which java pays attention to so it * seems we do as well. */ - def classPathEnv = envOrElse("CLASSPATH", "") def sourcePathEnv = envOrElse("SOURCEPATH", "") def javaBootClassPath = propOrElse("sun.boot.class.path", searchForBootClasspath) @@ -86,7 +77,6 @@ object PathResolver { def scalaHome = Environment.scalaHome def scalaHomeDir = Directory(scalaHome) - def scalaHomeExists = scalaHomeDir.isDirectory def scalaLibDir = Directory(scalaHomeDir / "lib") def scalaClassesDir = Directory(scalaHomeDir / "classes") @@ -109,15 +99,7 @@ object PathResolver { // classpath as set up by the runner (or regular classpath under -nobootcp) // and then again here. def scalaBootClassPath = "" - // scalaLibDirFound match { - // case Some(dir) if scalaHomeExists => - // val paths = ClassPath expandDir dir.path - // join(paths: _*) - // case _ => "" - // } - def scalaExtDirs = Environment.scalaExtDirs - def scalaPluginPath = (scalaHomeDir / "misc" / "scala-devel" / "plugins").path override def toString = """ @@ -136,7 +118,7 @@ object PathResolver { ) } - def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = { + def fromPathString(path: String, context: JavaContext = DefaultJavaContext): JavaClassPath = { // called from scalap val s = new Settings() s.classpath.value = path new PathResolver(s, context) result @@ -161,7 +143,7 @@ object PathResolver { } } } -import PathResolver.{ Defaults, Environment, firstNonEmpty, ppcp } +import PathResolver.{ Defaults, Environment, ppcp } class PathResolver(settings: Settings, context: JavaContext) { def this(settings: Settings) = this(settings, if (settings.inline.value) new JavaContext else DefaultJavaContext) diff --git a/src/continuations/library/scala/util/continuations/ControlContext.scala b/src/continuations/library/scala/util/continuations/ControlContext.scala index 44a5b537b6..c196809da9 100644 --- a/src/continuations/library/scala/util/continuations/ControlContext.scala +++ b/src/continuations/library/scala/util/continuations/ControlContext.scala @@ -183,7 +183,7 @@ final class ControlContext[+A,-B,+C](val fun: (A => B, Exception => B) => C, val // need filter or other functions? - final def flatMapCatch[A1>:A,B1<:B,C1>:C<:B1](pf: PartialFunction[Exception, ControlContext[A1,B1,C1]]): ControlContext[A1,B1,C1] = { + final def flatMapCatch[A1>:A,B1<:B,C1>:C<:B1](pf: PartialFunction[Exception, ControlContext[A1,B1,C1]]): ControlContext[A1,B1,C1] = { // called by codegen from SelectiveCPSTransform if (fun eq null) this else { @@ -209,7 +209,7 @@ final class ControlContext[+A,-B,+C](val fun: (A => B, Exception => B) => C, val } } - final def mapFinally(f: () => Unit): ControlContext[A,B,C] = { + final def mapFinally(f: () => Unit): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform if (fun eq null) { try { f() diff --git a/src/continuations/library/scala/util/continuations/package.scala b/src/continuations/library/scala/util/continuations/package.scala index 90bab56805..573fae85e7 100644 --- a/src/continuations/library/scala/util/continuations/package.scala +++ b/src/continuations/library/scala/util/continuations/package.scala @@ -166,8 +166,8 @@ package object continuations { throw new NoSuchMethodException("this code has to be compiled with the Scala continuations plugin enabled") } - def shiftUnitR[A,B](x: A): ControlContext[A,B,B] = { - new ControlContext(null, x) + def shiftUnitR[A,B](x: A): ControlContext[A,B,B] = { // called in code generated by SelectiveCPSTransform + new ControlContext[A, B, B](null, x) } /** @@ -176,11 +176,11 @@ package object continuations { * a final result. * @see shift */ - def shiftR[A,B,C](fun: (A => B) => C): ControlContext[A,B,C] = { + def shiftR[A,B,C](fun: (A => B) => C): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform new ControlContext((f:A=>B,g:Exception=>B) => fun(f), null.asInstanceOf[A]) } - def reifyR[A,B,C](ctx: => ControlContext[A,B,C]): ControlContext[A,B,C] = { + def reifyR[A,B,C](ctx: => ControlContext[A,B,C]): ControlContext[A,B,C] = { // called in code generated by SelectiveCPSTransform ctx } diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala index 15025f85e3..c147dc483d 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala @@ -96,7 +96,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { if (!cpsEnabled) return bounds val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe) - if (isFunctionType(tparams.head.owner.tpe) || isPartialFunctionType(tparams.head.owner.tpe)) { + if (isFunctionType(tparams.head.owner.tpe_*) || isPartialFunctionType(tparams.head.owner.tpe_*)) { vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs) if (hasCpsParamTypes(targs.last)) bounds.reverse match { @@ -356,7 +356,7 @@ abstract class CPSAnnotationChecker extends CPSUtils with Modes { global.globalError("not a single cps annotation: " + xs) xs(0) } - + def emptyOrSingleList(xs: List[AnnotationInfo]) = if (xs.isEmpty) Nil else List(single(xs)) def transChildrenInOrder(tree: Tree, tpe: Type, childTrees: List[Tree], byName: List[Tree]) = { diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala index 46c644bcd6..c591030bce 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala @@ -7,7 +7,6 @@ import scala.tools.nsc.Global trait CPSUtils { val global: Global import global._ - import definitions._ var cpsEnabled = false val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true" @@ -57,7 +56,7 @@ trait CPSUtils { protected def newMarker(sym: Symbol): AnnotationInfo = AnnotationInfo marker sym.tpe protected def newCpsParamsMarker(tp1: Type, tp2: Type) = - newMarker(appliedType(MarkerCPSTypes.tpe, List(tp1, tp2))) + newMarker(appliedType(MarkerCPSTypes, tp1, tp2)) // annotation checker diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala index 8b39bf3961..f62eebaaa0 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala @@ -2,13 +2,10 @@ package scala.tools.selectivecps -import scala.tools.nsc._ import scala.tools.nsc.transform._ import scala.tools.nsc.symtab._ import scala.tools.nsc.plugins._ -import scala.tools.nsc.ast._ - /** * In methods marked @cps, explicitly name results of calls to other @cps methods */ @@ -172,7 +169,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with debuglog("transforming valdef " + vd.symbol) if (getExternalAnswerTypeAnn(tpt.tpe).isEmpty) { - + atOwner(vd.symbol) { val rhs1 = transExpr(rhs, None, None) @@ -471,7 +468,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with val sym: Symbol = ( currentOwner.newValue(newTermName(unit.fresh.newName("tmp")), tree.pos, Flags.SYNTHETIC) setInfo valueTpe - setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil)) + setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil)) ) expr.changeOwner(currentOwner -> sym) @@ -503,9 +500,7 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with // TODO: better yet: do without annotations on symbols val spcVal = getAnswerTypeAnn(anfRhs.tpe) - if (spcVal.isDefined) { - tree.symbol.setAnnotations(List(AnnotationInfo(MarkerCPSSym.tpe, Nil, Nil))) - } + spcVal foreach (_ => tree.symbol setAnnotations List(AnnotationInfo(MarkerCPSSym.tpe_*, Nil, Nil))) (stms:::List(treeCopy.ValDef(tree, mods, name, tpt, anfRhs)), linearize(spc, spcVal)(unit, tree.pos)) diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala index 8a500d6c4d..90e64d8171 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala @@ -3,15 +3,11 @@ package scala.tools.selectivecps import scala.tools.nsc -import scala.tools.nsc.typechecker._ import nsc.Global -import nsc.Phase import nsc.plugins.Plugin import nsc.plugins.PluginComponent class SelectiveCPSPlugin(val global: Global) extends Plugin { - import global._ - val name = "continuations" val description = "applies selective cps conversion" @@ -26,7 +22,6 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin { override val runsBefore = List("uncurry") } - val components = List[PluginComponent](anfPhase, cpsPhase) val checker = new CPSAnnotationChecker { diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala index 4482bf2b7c..f16cfb10f8 100644 --- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala +++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala @@ -2,13 +2,8 @@ package scala.tools.selectivecps -import scala.collection._ - -import scala.tools.nsc._ import scala.tools.nsc.transform._ import scala.tools.nsc.plugins._ - -import scala.tools.nsc.ast.TreeBrowsers import scala.tools.nsc.ast._ /** @@ -56,7 +51,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with case _ => getExternalAnswerTypeAnn(tp) match { case Some((res, outer)) => - appliedType(Context.tpe, List(removeAllCPSAnnotations(tp), res, outer)) + appliedType(Context.tpeHK, List(removeAllCPSAnnotations(tp), res, outer)) case _ => removeAllCPSAnnotations(tp) } @@ -107,7 +102,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with TypeApply(funR, List(targs(0), targs(1))).setType(appliedType(funR.tpe, List(targs(0).tpe, targs(1).tpe))), args.map(transform(_)) - ).setType(appliedType(Context.tpe, List(targs(0).tpe,targs(1).tpe,targs(1).tpe))) + ).setType(appliedType(Context.tpeHK, List(targs(0).tpe,targs(1).tpe,targs(1).tpe))) } case Apply(TypeApply(fun, targs), args) @@ -192,7 +187,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with val targettp = transformCPSType(tree.tpe) val pos = catches.head.pos - val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp))) + val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass, ThrowableClass.tpe, targettp)) val funDef = localTyper.typedPos(pos) { ValDef(funSym, Match(EmptyTree, catches1)) } diff --git a/src/detach/plugin/scala/tools/detach/Detach.scala b/src/detach/plugin/scala/tools/detach/Detach.scala index f9a3d80da4..499a97b761 100644 --- a/src/detach/plugin/scala/tools/detach/Detach.scala +++ b/src/detach/plugin/scala/tools/detach/Detach.scala @@ -73,7 +73,7 @@ abstract class Detach extends PluginComponent } private val serializableAnnotationInfo = - AnnotationInfo(SerializableAttr.tpe, List(), List()) + AnnotationInfo(requiredClass[scala.annotation.serializable].tpe, List(), List()) /* private val throwsAnnotationInfo = { val RemoteExceptionClass = definitions.getClass("java.rmi.RemoteException") @@ -206,7 +206,7 @@ abstract class Detach extends PluginComponent symSet(capturedObjects, owner) += qsym case Select(qual, name) - if (qual.hasSymbol && + if (qual.hasSymbolField && (sym.owner != owner) && !(sym.ownerChain contains ScalaPackageClass) && !(sym.owner hasFlag JAVA)) => @@ -284,7 +284,7 @@ abstract class Detach extends PluginComponent def isOuter(sym: Symbol): Boolean = sym.isOuterAccessor || sym.name.endsWith(nme.OUTER/*, nme.OUTER.length*/) - if (tree.hasSymbol && isOuter(tree.symbol)) subst(from, to) + if (tree.hasSymbolField && isOuter(tree.symbol)) subst(from, to) super.traverse(tree) } } @@ -293,7 +293,7 @@ abstract class Detach extends PluginComponent private class TreeTypeRefSubstituter(clazz: Symbol) extends Traverser { override def traverse(tree: Tree) { val sym = tree.symbol - if (tree.hasSymbol && isRefClass(sym.tpe) && + if (tree.hasSymbolField && isRefClass(sym.tpe) && (sym.owner.enclClass == clazz) && (sym.isValueParameter || sym.hasFlag(PARAMACCESSOR))) { sym setInfo mkRemoteRefClass(sym.tpe) @@ -329,7 +329,7 @@ abstract class Detach extends PluginComponent } val map = new mutable.HashMap[Symbol, Symbol] override def traverse(tree: Tree) { - if (tree.hasSymbol && tree.symbol != NoSymbol) { + if (tree.hasSymbolField && tree.symbol != NoSymbol) { val sym = tree.symbol if (sym.owner == from) { val sym1 = map get sym match { @@ -369,7 +369,7 @@ abstract class Detach extends PluginComponent def removeAccessors(tree: Tree): Tree = tree match { case Apply(fun, _) => removeAccessors(fun) - case Select(qual, _) if tree.hasSymbol && tree.symbol.isOuterAccessor => + case Select(qual, _) if tree.hasSymbolField && tree.symbol.isOuterAccessor => removeAccessors(qual) case _ => tree @@ -382,7 +382,7 @@ abstract class Detach extends PluginComponent // transforms field assignment $outer.i$1.elem=.. // into setter $outer.i$1_=(..) case Assign(lhs @ Select(qual1 @ Select(qual, name), name1), rhs) - if qual1.hasSymbol && !qual1.symbol.isPrivateLocal && + if qual1.hasSymbolField && !qual1.symbol.isPrivateLocal && isRemoteRefClass(qual1.tpe) => if (DEBUG) println("\nTreeAccessorSubstituter: Assign1\n\tqual1="+qual1+", sel.tpe="+lhs.tpe+ @@ -398,7 +398,7 @@ abstract class Detach extends PluginComponent // transforms local assignment this.x$1.elem=.. // into setter method this.x$1_=(..) case Assign(lhs @ Select(qual, name), rhs) - if qual.hasSymbol && qual.symbol.isPrivateLocal && + if qual.hasSymbolField && qual.symbol.isPrivateLocal && isRemoteRefClass(qual.tpe) => if (DEBUG) println("\nTreeAccessorSubstituter: Assign2"+ @@ -412,7 +412,7 @@ abstract class Detach extends PluginComponent Apply(fun, List(super.transform(rhs))) setType lhs.tpe case Assign(Select(qual, name), rhs) - if qual.hasSymbol && (objs contains qual.symbol) => + if qual.hasSymbolField && (objs contains qual.symbol) => val sym = qual.symbol val proxy = proxySyms(objs indexOf sym) if (DEBUG) @@ -461,7 +461,7 @@ abstract class Detach extends PluginComponent // transforms field $outer.name$1 into getter method $outer.name$1() case Select(qual @ Select(_, name1), name) - if qual.hasSymbol && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) && + if qual.hasSymbolField && name1.endsWith(nme.OUTER/*, nme.OUTER.length*/) && !tree.symbol.isMethod => if (DEBUG) println("\nTreeAccessorSubstituter: Select0\n\tqual="+qual+ @@ -500,7 +500,7 @@ abstract class Detach extends PluginComponent // transforms field access $outer.i$1.elem // into invocation of getter method $outer.i$1() case Select(qual @ Select(qual1, name1), name) - if qual.hasSymbol && !qual.symbol.isPrivateLocal && + if qual.hasSymbolField && !qual.symbol.isPrivateLocal && isRemoteRefClass(qual.tpe) => if (DEBUG) println("\nTreeAccessorSubstituter: Select2\n\tqual="+qual+ @@ -513,7 +513,7 @@ abstract class Detach extends PluginComponent // transforms local access this.i$1.elem // into invocation of getter method this.i$1() case Select(qual, name) - if qual.hasSymbol && qual.symbol.isPrivateLocal && + if qual.hasSymbolField && qual.symbol.isPrivateLocal && isRemoteRefClass(qual.tpe) => if (DEBUG) println("\nTreeAccessorSubstituter: Select3\n\tqual="+qual+ @@ -523,7 +523,7 @@ abstract class Detach extends PluginComponent Apply(fun, List()) setType tree.tpe case Select(qual, name) - if qual.hasSymbol && (objs contains qual.symbol) => + if qual.hasSymbolField && (objs contains qual.symbol) => if (DEBUG) println("\nTreeAccessorSubstituter: Select4\n\tqual="+qual+ ", qual.tpe="+qual.tpe+", name="+name)//debug diff --git a/src/library/scala/Application.scala b/src/library/scala/Application.scala deleted file mode 100644 index e7db0d2db8..0000000000 --- a/src/library/scala/Application.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -import scala.compat.Platform.currentTime - -/** The `Application` trait can be used to quickly turn objects - * into executable programs, but is ''not recommended''. - * Here is an example: - * {{{ - * object Main extends Application { - * Console.println("Hello World!") - * } - * }}} - * Here, object `Main` inherits the `main` method of `Application`. - * The body of the `Main` object defines the main program. This technique - * does not work if the main program depends on command-line arguments - * (which are not accessible with the technique presented here). - * - * It is possible to time the execution of objects that inherit from class - * `Application` by setting the global `scala.time` - * property. Here is an example for benchmarking object `Main`: - * {{{ - * java -Dscala.time Main - * }}} - * In practice the `Application` trait has a number of serious pitfalls: - * - * - Threaded code that references the object will block until static - * initialization is complete. However, because the entire execution - * of an `object` extending `Application` takes place during - * static initialization, concurrent code will ''always'' deadlock if - * it must synchronize with the enclosing object. - * - As described above, there is no way to obtain the - * command-line arguments because all code in body of an `object` - * extending `Application` is run as part of the static initialization - * which occurs before `Application`'s `main` method - * even begins execution. - * - Static initializers are run only once during program execution, and - * JVM authors usually assume their execution to be relatively short. - * Therefore, certain JVM configurations may become confused, or simply - * fail to optimize or JIT the code in the body of an `object` extending - * `Application`. This can lead to a significant performance degradation. - * - * It is recommended to use the [[scala.App]] trait instead. - * {{{ - * object Main { - * def main(args: Array[String]) { - * //.. - * } - * } - * }}} - * - * @author Matthias Zenger - * @version 1.0, 10/09/2003 - */ -@deprecated("use App instead", "2.9.0") -trait Application { - - /** The time when the execution of this program started, - * in milliseconds since 1 January 1970 UTC. */ - val executionStart: Long = currentTime - - /** The default main method. - * - * @param args the arguments passed to the main method - */ - def main(args: Array[String]) { - if (util.Properties propIsSet "scala.time") { - val total = currentTime - executionStart - Console.println("[total " + total + "ms]") - } - } -} diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index 90684b5fdd..b9f51803ec 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -115,6 +115,8 @@ object Array extends FallbackArrayBuilding { * @param xs the elements to put in the array * @return an array containing all elements from xs. */ + // Subject to a compiler optimization in Cleanup. + // Array(e0, ..., en) is translated to { val a = new Array(3); a(i) = ei; a } def apply[T: ClassTag](xs: T*): Array[T] = { val array = new Array[T](xs.length) var i = 0 @@ -123,6 +125,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Boolean` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Boolean, xs: Boolean*): Array[Boolean] = { val array = new Array[Boolean](xs.length + 1) array(0) = x @@ -132,6 +135,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Byte` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Byte, xs: Byte*): Array[Byte] = { val array = new Array[Byte](xs.length + 1) array(0) = x @@ -141,6 +145,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Short` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Short, xs: Short*): Array[Short] = { val array = new Array[Short](xs.length + 1) array(0) = x @@ -150,6 +155,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Char` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Char, xs: Char*): Array[Char] = { val array = new Array[Char](xs.length + 1) array(0) = x @@ -159,6 +165,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Int` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Int, xs: Int*): Array[Int] = { val array = new Array[Int](xs.length + 1) array(0) = x @@ -168,6 +175,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Long` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Long, xs: Long*): Array[Long] = { val array = new Array[Long](xs.length + 1) array(0) = x @@ -177,6 +185,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Float` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Float, xs: Float*): Array[Float] = { val array = new Array[Float](xs.length + 1) array(0) = x @@ -186,6 +195,7 @@ object Array extends FallbackArrayBuilding { } /** Creates an array of `Double` objects */ + // Subject to a compiler optimization in Cleanup, see above. def apply(x: Double, xs: Double*): Array[Double] = { val array = new Array[Double](xs.length + 1) array(0) = x diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 3873df99e9..4b071166c7 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -209,6 +209,15 @@ sealed abstract class Option[+A] extends Product with Serializable { def withFilter(q: A => Boolean): WithFilter = new WithFilter(x => p(x) && q(x)) } + /** Tests whether the option contains a given value as an element. + * + * @param elem the element to test. + * @return `true` if the option has an element that is equal (as + * determined by `==`) to `elem`, `false` otherwise. + */ + final def contains[A1 >: A](elem: A1): Boolean = + !isEmpty && this.get == elem + /** Returns true if this option is nonempty '''and''' the predicate * $p returns true when applied to this $option's value. * Otherwise, returns false. @@ -247,7 +256,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * value (if possible), or $none. */ @inline final def collect[B](pf: PartialFunction[A, B]): Option[B] = - if (!isEmpty && pf.isDefinedAt(this.get)) Some(pf(this.get)) else None + if (!isEmpty) pf.lift(this.get) else None /** Returns this $option if it is nonempty, * otherwise return the result of evaluating `alternative`. diff --git a/src/library/scala/UninitializedFieldError.scala b/src/library/scala/UninitializedFieldError.scala index 10c6cccf15..0dfba2a187 100644 --- a/src/library/scala/UninitializedFieldError.scala +++ b/src/library/scala/UninitializedFieldError.scala @@ -18,8 +18,6 @@ package scala * * @since 2.7 */ -final case class UninitializedFieldError(msg: String) - extends RuntimeException(msg) { - def this(obj: Any) = - this(if (null != obj) obj.toString() else "null") +final case class UninitializedFieldError(msg: String) extends RuntimeException(msg) { + def this(obj: Any) = this("" + obj) } diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala index 4a1c0beaa6..d0f4e323c7 100644 --- a/src/library/scala/collection/BitSetLike.scala +++ b/src/library/scala/collection/BitSetLike.scala @@ -11,7 +11,6 @@ package scala.collection import BitSetLike._ -import generic._ import mutable.StringBuilder /** A template trait for bitsets. diff --git a/src/library/scala/collection/DefaultMap.scala b/src/library/scala/collection/DefaultMap.scala index 5c91183891..cbd7e3f8b9 100644 --- a/src/library/scala/collection/DefaultMap.scala +++ b/src/library/scala/collection/DefaultMap.scala @@ -6,12 +6,8 @@ ** |/ ** \* */ - - package scala.collection -import generic._ - /** A default map which implements the `+` and `-` methods of maps. * * Instances that inherit from `DefaultMap[A, B]` still have to define: @@ -27,7 +23,7 @@ import generic._ * @since 2.8 */ trait DefaultMap[A, +B] extends Map[A, B] { self => - + /** A default implementation which creates a new immutable map. */ override def +[B1 >: B](kv: (A, B1)): Map[A, B1] = { diff --git a/src/library/scala/collection/GenIterableLike.scala b/src/library/scala/collection/GenIterableLike.scala index 2ba9a7283d..ceb97707e1 100644 --- a/src/library/scala/collection/GenIterableLike.scala +++ b/src/library/scala/collection/GenIterableLike.scala @@ -8,7 +8,7 @@ package scala.collection -import generic.{ CanBuildFrom => CBF, _ } +import generic.{ CanBuildFrom => CBF } /** A template trait for all iterable collections which may possibly * have their operations implemented in parallel. diff --git a/src/library/scala/collection/GenIterableView.scala b/src/library/scala/collection/GenIterableView.scala index ca0332e9ad..5ab48efdf3 100644 --- a/src/library/scala/collection/GenIterableView.scala +++ b/src/library/scala/collection/GenIterableView.scala @@ -8,11 +8,4 @@ package scala.collection - -import generic._ - - - trait GenIterableView[+A, +Coll] extends GenIterableViewLike[A, Coll, GenIterableView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenIterableViewLike.scala b/src/library/scala/collection/GenIterableViewLike.scala index 4e4ceb4cea..e8d264cdd4 100644 --- a/src/library/scala/collection/GenIterableViewLike.scala +++ b/src/library/scala/collection/GenIterableViewLike.scala @@ -8,13 +8,6 @@ package scala.collection - - -import generic._ -import TraversableView.NoBuilder - - - trait GenIterableViewLike[+A, +Coll, +This <: GenIterableView[A, Coll] with GenIterableViewLike[A, Coll, This]] diff --git a/src/library/scala/collection/GenSeqView.scala b/src/library/scala/collection/GenSeqView.scala index 92c8b779e9..423f8e305e 100644 --- a/src/library/scala/collection/GenSeqView.scala +++ b/src/library/scala/collection/GenSeqView.scala @@ -8,11 +8,4 @@ package scala.collection - -import generic._ - - - trait GenSeqView[+A, +Coll] extends GenSeqViewLike[A, Coll, GenSeqView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala index 093db2a972..afaced4264 100644 --- a/src/library/scala/collection/GenTraversableOnce.scala +++ b/src/library/scala/collection/GenTraversableOnce.scala @@ -261,11 +261,12 @@ trait GenTraversableOnce[+A] extends Any { * @tparam B the type of accumulated results * @param z the initial value for the accumulated result of the partition - this * will typically be the neutral element for the `seqop` operator (e.g. - * `Nil` for list concatenation or `0` for summation) + * `Nil` for list concatenation or `0` for summation) and may be evaluated + * more than once * @param seqop an operator used to accumulate results within a partition * @param combop an associative operator used to combine results from different partitions */ - def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B + def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B /** Applies a binary operator to all elements of this $coll, going right to left. * $willNotTerminateInf diff --git a/src/library/scala/collection/GenTraversableView.scala b/src/library/scala/collection/GenTraversableView.scala index cceb06882e..1d98eff8c1 100644 --- a/src/library/scala/collection/GenTraversableView.scala +++ b/src/library/scala/collection/GenTraversableView.scala @@ -8,11 +8,4 @@ package scala.collection - -import generic._ - - - trait GenTraversableView[+A, +Coll] extends GenTraversableViewLike[A, Coll, GenTraversableView[A, Coll]] { } - - diff --git a/src/library/scala/collection/GenTraversableViewLike.scala b/src/library/scala/collection/GenTraversableViewLike.scala index 77fe0802bf..8c9607663b 100644 --- a/src/library/scala/collection/GenTraversableViewLike.scala +++ b/src/library/scala/collection/GenTraversableViewLike.scala @@ -11,8 +11,6 @@ package scala.collection import generic._ import mutable.{ Builder, ArrayBuffer } -import TraversableView.NoBuilder - trait GenTraversableViewLike[+A, +Coll, diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala index 63e5adf428..0b6e640537 100644 --- a/src/library/scala/collection/IndexedSeq.scala +++ b/src/library/scala/collection/IndexedSeq.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.collection import generic._ @@ -38,4 +36,3 @@ object IndexedSeq extends IndexedSeqFactory[IndexedSeq] { implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] } - diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala index 9d0e9cbaea..1d8e2b1583 100644 --- a/src/library/scala/collection/IndexedSeqLike.scala +++ b/src/library/scala/collection/IndexedSeqLike.scala @@ -8,7 +8,6 @@ package scala.collection -import generic._ import mutable.ArrayBuffer import scala.annotation.tailrec @@ -53,7 +52,6 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] { // pre: start >= 0, end <= self.length @SerialVersionUID(1756321872811029277L) protected class Elements(start: Int, end: Int) extends AbstractIterator[A] with BufferedIterator[A] with Serializable { - private def initialSize = if (end <= start) 0 else end - start private var index = start private def available = (end - index) max 0 diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala index 5b73d720a8..09c9ce122c 100644 --- a/src/library/scala/collection/Iterable.scala +++ b/src/library/scala/collection/Iterable.scala @@ -11,7 +11,6 @@ package scala.collection import generic._ -import scala.util.control.Breaks._ import mutable.Builder /** A base trait for iterable collections. diff --git a/src/library/scala/collection/IterableProxy.scala b/src/library/scala/collection/IterableProxy.scala index 2d041928cc..ddb2502965 100644 --- a/src/library/scala/collection/IterableProxy.scala +++ b/src/library/scala/collection/IterableProxy.scala @@ -8,8 +8,6 @@ package scala.collection -import generic._ - /** This trait implements a proxy for iterable objects. It forwards all calls * to a different iterable object. * diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala index 3a81a3422f..b195ae4bc7 100644 --- a/src/library/scala/collection/IterableViewLike.scala +++ b/src/library/scala/collection/IterableViewLike.scala @@ -9,7 +9,6 @@ package scala.collection import generic._ -import TraversableView.NoBuilder import immutable.Stream import scala.language.implicitConversions diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index cbf8cc4931..d7dc202fad 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -562,7 +562,6 @@ trait Iterator[+A] extends TraversableOnce[A] { * handling of structural calls. It's not what's intended here. */ class Leading extends AbstractIterator[A] { - private var isDone = false val lookahead = new mutable.Queue[A] def advance() = { self.hasNext && p(self.head) && { @@ -572,7 +571,6 @@ trait Iterator[+A] extends TraversableOnce[A] { } def finish() = { while (advance()) () - isDone = true } def hasNext = lookahead.nonEmpty || advance() def next() = { diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala index 59d4259c70..7ff29650fa 100644 --- a/src/library/scala/collection/JavaConversions.scala +++ b/src/library/scala/collection/JavaConversions.scala @@ -8,7 +8,6 @@ package scala.collection -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } import convert._ /** A collection of implicit conversions supporting interoperability between @@ -91,42 +90,6 @@ object JavaConversions extends WrapAsScala with WrapAsJava { @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSeqWrapper = Wrappers.MutableSeqWrapper @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val MutableSetWrapper = Wrappers.MutableSetWrapper @deprecated("Use a member of scala.collection.convert.Wrappers", "2.10.0") val SeqWrapper = Wrappers.SeqWrapper - - // Note to implementors: the cavalcade of deprecated methods herein should - // serve as a warning to any who follow: don't overload implicit methods. - - @deprecated("use bufferAsJavaList instead", "2.9.0") - def asJavaList[A](b : mutable.Buffer[A]): ju.List[A] = bufferAsJavaList[A](b) - - @deprecated("use mutableSeqAsJavaList instead", "2.9.0") - def asJavaList[A](b : mutable.Seq[A]): ju.List[A] = mutableSeqAsJavaList[A](b) - - @deprecated("use seqAsJavaList instead", "2.9.0") - def asJavaList[A](b : Seq[A]): ju.List[A] = seqAsJavaList[A](b) - - @deprecated("use mutableSetAsJavaSet instead", "2.9.0") - def asJavaSet[A](s : mutable.Set[A]): ju.Set[A] = mutableSetAsJavaSet[A](s) - - @deprecated("use setAsJavaSet instead", "2.9.0") - def asJavaSet[A](s: Set[A]): ju.Set[A] = setAsJavaSet[A](s) - - @deprecated("use mutableMapAsJavaMap instead", "2.9.0") - def asJavaMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = mutableMapAsJavaMap[A, B](m) - - @deprecated("use mapAsJavaMap instead", "2.9.0") - def asJavaMap[A, B](m : Map[A, B]): ju.Map[A, B] = mapAsJavaMap[A, B](m) - - @deprecated("use iterableAsScalaIterable instead", "2.9.0") - def asScalaIterable[A](i : jl.Iterable[A]): Iterable[A] = iterableAsScalaIterable[A](i) - - @deprecated("use collectionAsScalaIterable instead", "2.9.0") - def asScalaIterable[A](i : ju.Collection[A]): Iterable[A] = collectionAsScalaIterable[A](i) - - @deprecated("use mapAsScalaMap instead", "2.9.0") - def asScalaMap[A, B](m: ju.Map[A, B]): mutable.Map[A, B] = mapAsScalaMap[A, B](m) - - @deprecated("use propertiesAsScalaMap instead", "2.9.0") - def asScalaMap(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p) } diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala index ab3ac8925c..439991708e 100755 --- a/src/library/scala/collection/JavaConverters.scala +++ b/src/library/scala/collection/JavaConverters.scala @@ -8,14 +8,12 @@ package scala.collection -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } import convert._ // TODO: I cleaned all this documentation up in JavaConversions, but the // documentation in here is basically the pre-cleaned-up version with minor // additions. Would be nice to have in one place. - /** A collection of decorators that allow converting between * Scala and Java collections using `asScala` and `asJava` methods. * @@ -67,37 +65,4 @@ object JavaConverters extends DecorateAsJava with DecorateAsScala { type AsJavaEnumeration[A] = Decorators.AsJavaEnumeration[A] @deprecated("Don't access these decorators directly.", "2.10.0") type AsJavaDictionary[A, B] = Decorators.AsJavaDictionary[A, B] - - @deprecated("Use bufferAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : mutable.Buffer[A]): AsJava[ju.List[A]] = bufferAsJavaListConverter(b) - - @deprecated("Use mutableSeqAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : mutable.Seq[A]): AsJava[ju.List[A]] = mutableSeqAsJavaListConverter(b) - - @deprecated("Use seqAsJavaListConverter instead", "2.9.0") - def asJavaListConverter[A](b : Seq[A]): AsJava[ju.List[A]] = seqAsJavaListConverter(b) - - @deprecated("Use mutableSetAsJavaSetConverter instead", "2.9.0") - def asJavaSetConverter[A](s : mutable.Set[A]): AsJava[ju.Set[A]] = mutableSetAsJavaSetConverter(s) - - @deprecated("Use setAsJavaSetConverter instead", "2.9.0") - def asJavaSetConverter[A](s : Set[A]): AsJava[ju.Set[A]] = setAsJavaSetConverter(s) - - @deprecated("use mutableMapAsJavaMapConverter instead", "2.9.0") - def asJavaMapConverter[A, B](m : mutable.Map[A, B]): AsJava[ju.Map[A, B]] = mutableMapAsJavaMapConverter(m) - - @deprecated("Use mapAsJavaMapConverter instead", "2.9.0") - def asJavaMapConverter[A, B](m : Map[A, B]): AsJava[ju.Map[A, B]] = mapAsJavaMapConverter(m) - - @deprecated("Use iterableAsScalaIterableConverter instead", "2.9.0") - def asScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] = iterableAsScalaIterableConverter(i) - - @deprecated("Use collectionAsScalaIterableConverter instead", "2.9.0") - def asScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] = collectionAsScalaIterableConverter(i) - - @deprecated("Use mapAsScalaMapConverter instead", "2.9.0") - def asScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] = mapAsScalaMapConverter(m) - - @deprecated("Use propertiesAsScalaMapConverter instead", "2.9.0") - def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] = propertiesAsScalaMapConverter(p) } diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala index 78108a9c0f..2a824bcff3 100644 --- a/src/library/scala/collection/LinearSeqLike.scala +++ b/src/library/scala/collection/LinearSeqLike.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - package scala.collection -import generic._ -import mutable.ListBuffer import immutable.List -import scala.util.control.Breaks._ import scala.annotation.tailrec /** A template trait for linear sequences of type `LinearSeq[A]`. diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala index 0f0a405a85..f71fd227cd 100755 --- a/src/library/scala/collection/LinearSeqOptimized.scala +++ b/src/library/scala/collection/LinearSeqOptimized.scala @@ -8,10 +8,8 @@ package scala.collection -import generic._ import mutable.ListBuffer import immutable.List -import scala.util.control.Breaks._ /** A template trait for linear sequences of type `LinearSeq[A]` which optimizes * the implementation of several methods under the assumption of fast linear access. @@ -83,7 +81,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } override /*SeqLike*/ - def contains(elem: Any): Boolean = { + def contains[A1 >: A](elem: A1): Boolean = { var these = this while (!these.isEmpty) { if (these.head == elem) return true @@ -91,7 +89,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } false } - + override /*IterableLike*/ def find(p: A => Boolean): Option[A] = { var these = this @@ -112,7 +110,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea } acc } - + override /*IterableLike*/ def foldRight[B](z: B)(f: (A, B) => B): B = if (this.isEmpty) z diff --git a/src/library/scala/collection/MapProxyLike.scala b/src/library/scala/collection/MapProxyLike.scala index 44b39f65da..ad09f7b970 100644 --- a/src/library/scala/collection/MapProxyLike.scala +++ b/src/library/scala/collection/MapProxyLike.scala @@ -8,8 +8,6 @@ package scala.collection -import generic._ - // Methods could be printed by cat MapLike.scala | egrep '^ (override )?def' /** This trait implements a proxy for Map objects. It forwards diff --git a/src/library/scala/collection/Searching.scala b/src/library/scala/collection/Searching.scala new file mode 100644 index 0000000000..33e50365ee --- /dev/null +++ b/src/library/scala/collection/Searching.scala @@ -0,0 +1,116 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.collection + +import scala.annotation.tailrec +import scala.collection.generic.IsSeqLike +import scala.math.Ordering + +/** A collection of wrappers that provide sequence classes with search functionality. + * + * Example usage: + * {{{ + * import scala.collection.Searching._ + * val l = List(1, 2, 3, 4, 5) + * l.search(3) + * // == Found(2) + * }}} + */ +object Searching { + sealed abstract class SearchResult { + def insertionPoint: Int + } + + case class Found(foundIndex: Int) extends SearchResult { + override def insertionPoint = foundIndex + } + case class InsertionPoint(insertionPoint: Int) extends SearchResult + + class SearchImpl[A, Repr](val coll: SeqLike[A, Repr]) { + /** Search the sorted sequence for a specific element. If the sequence is an + * `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. + * + * The sequence should be sorted with the same `Ordering` before calling; otherwise, + * the results are undefined. + * + * @see [[scala.collection.IndexedSeq]] + * @see [[scala.math.Ordering]] + * @see [[scala.collection.SeqLike]], method `sorted` + * + * @param elem the element to find. + * @param ord the ordering to be used to compare elements. + * + * @return a `Found` value containing the index corresponding to the element in the + * sequence, or the `InsertionPoint` where the element would be inserted if + * the element is not in the sequence. + */ + final def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult = + coll match { + case _: IndexedSeq[A] => binarySearch(elem, -1, coll.length)(ord) + case _ => linearSearch(coll.view, elem, 0)(ord) + } + + /** Search within an interval in the sorted sequence for a specific element. If the + * sequence is an IndexedSeq, a binary search is used. Otherwise, a linear search + * is used. + * + * The sequence should be sorted with the same `Ordering` before calling; otherwise, + * the results are undefined. + * + * @see [[scala.collection.IndexedSeq]] + * @see [[scala.math.Ordering]] + * @see [[scala.collection.SeqLike]], method `sorted` + * + * @param elem the element to find. + * @param from the index where the search starts. + * @param to the index following where the search ends. + * @param ord the ordering to be used to compare elements. + * + * @return a `Found` value containing the index corresponding to the element in the + * sequence, or the `InsertionPoint` where the element would be inserted if + * the element is not in the sequence. + */ + final def search[B >: A](elem: B, from: Int, to: Int) + (implicit ord: Ordering[B]): SearchResult = + coll match { + case _: IndexedSeq[A] => binarySearch(elem, from-1, to)(ord) + case _ => linearSearch(coll.view(from, to), elem, from)(ord) + } + + @tailrec + private def binarySearch[B >: A](elem: B, from: Int, to: Int) + (implicit ord: Ordering[B]): SearchResult = { + if ((to-from) == 1) InsertionPoint(from) else { + val idx = from+(to-from)/2 + math.signum(ord.compare(elem, coll(idx))) match { + case -1 => binarySearch(elem, from, idx)(ord) + case 1 => binarySearch(elem, idx, to)(ord) + case _ => Found(idx) + } + } + } + + private def linearSearch[B >: A](c: SeqView[A, Repr], elem: B, offset: Int) + (implicit ord: Ordering[B]): SearchResult = { + var idx = offset + val it = c.iterator + while (it.hasNext) { + val cur = it.next() + if (ord.equiv(elem, cur)) return Found(idx) + else if (ord.lt(elem, cur)) return InsertionPoint(idx-1) + idx += 1 + } + InsertionPoint(idx) + } + + } + + implicit def search[Repr, A](coll: Repr) + (implicit fr: IsSeqLike[Repr]): SearchImpl[fr.A, Repr] = new SearchImpl(fr.conversion(coll)) +} diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala index 6871a3cb73..603e0b6497 100644 --- a/src/library/scala/collection/SeqLike.scala +++ b/src/library/scala/collection/SeqLike.scala @@ -103,7 +103,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def segmentLength(p: A => Boolean, from: Int): Int = { var i = 0 - var it = iterator.drop(from) + val it = iterator.drop(from) while (it.hasNext && p(it.next())) i += 1 i @@ -111,7 +111,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ def indexWhere(p: A => Boolean, from: Int): Int = { var i = from - var it = iterator.drop(from) + val it = iterator.drop(from) while (it.hasNext) { if (p(it.next())) return i else i += 1 @@ -177,10 +177,10 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ result } private def swap(i: Int, j: Int) { - var tmpI = idxs(i) + val tmpI = idxs(i) idxs(i) = idxs(j) idxs(j) = tmpI - var tmpE = elms(i) + val tmpE = elms(i) elms(i) = elms(j) elms(j) = tmpE } @@ -386,7 +386,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[ * @return `true` if this $coll has an element that is equal (as * determined by `==`) to `elem`, `false` otherwise. */ - def contains(elem: Any): Boolean = exists (_ == elem) + def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem) /** Produces a new sequence which contains all elements of this $coll and also all elements of * a given sequence. `xs union ys` is equivalent to `xs ++ ys`. @@ -776,7 +776,7 @@ object SeqLike { val iter = S.iterator.drop(m0) val Wopt = kmpOptimizeWord(W, n0, n1, true) val T = kmpJumpTable(Wopt, n1-n0) - var cache = new Array[AnyRef](n1-n0) // Ring buffer--need a quick way to do a look-behind + val cache = new Array[AnyRef](n1-n0) // Ring buffer--need a quick way to do a look-behind var largest = 0 var i, m = 0 var answer = -1 diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala index 5e8030d1e4..ee88ee3da3 100644 --- a/src/library/scala/collection/SeqProxyLike.scala +++ b/src/library/scala/collection/SeqProxyLike.scala @@ -50,7 +50,7 @@ trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A, override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = self.lastIndexOfSlice(that) override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = self.lastIndexOfSlice(that, end) override def containsSlice[B](that: GenSeq[B]): Boolean = self.indexOfSlice(that) != -1 - override def contains(elem: Any): Boolean = self.contains(elem) + override def contains[A1 >: A](elem: A1): Boolean = self.contains(elem) override def union[B >: A, That](that: GenSeq[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = self.union(that)(bf) override def diff[B >: A](that: GenSeq[B]): Repr = self.diff(that) override def intersect[B >: A](that: GenSeq[B]): Repr = self.intersect(that) diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala index 5f2bf902b1..27536791a2 100644 --- a/src/library/scala/collection/SeqViewLike.scala +++ b/src/library/scala/collection/SeqViewLike.scala @@ -10,7 +10,6 @@ package scala.collection import generic._ import Seq.fill -import TraversableView.NoBuilder /** A template trait for non-strict views of sequences. * $seqViewInfo diff --git a/src/library/scala/collection/Sequentializable.scala.disabled b/src/library/scala/collection/Sequentializable.scala.disabled deleted file mode 100644 index df457671a6..0000000000 --- a/src/library/scala/collection/Sequentializable.scala.disabled +++ /dev/null @@ -1,10 +0,0 @@ -package scala.collection - - - - -trait Sequentializable[+T, +Repr] { - - def seq: Repr - -} diff --git a/src/library/scala/collection/SetProxyLike.scala b/src/library/scala/collection/SetProxyLike.scala index 5196f39917..265d1c4806 100644 --- a/src/library/scala/collection/SetProxyLike.scala +++ b/src/library/scala/collection/SetProxyLike.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - package scala.collection -import generic._ - // Methods could be printed by cat SetLike.scala | egrep '^ (override )?def' /** This trait implements a proxy for sets. It forwards diff --git a/src/library/scala/collection/Traversable.scala b/src/library/scala/collection/Traversable.scala index 36ef230a42..4ca2095f4c 100644 --- a/src/library/scala/collection/Traversable.scala +++ b/src/library/scala/collection/Traversable.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - - package scala.collection import generic._ -import mutable.{Builder, Buffer, ArrayBuffer, ListBuffer} +import mutable.Builder import scala.util.control.Breaks /** A trait for traversable collections. diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala index 5f193eb211..c1a68b6b16 100644 --- a/src/library/scala/collection/TraversableLike.scala +++ b/src/library/scala/collection/TraversableLike.scala @@ -86,7 +86,7 @@ trait TraversableLike[+A, +Repr] extends Any def repr: Repr = this.asInstanceOf[Repr] final def isTraversableAgain: Boolean = true - + /** The underlying collection seen as an instance of `$Coll`. * By default this is implemented as the current collection object itself, * but this can be overridden. @@ -174,7 +174,7 @@ trait TraversableLike[+A, +Repr] extends Any * * @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B] * @inheritdoc - * + * * Example: * {{{ * scala> val x = List(1) @@ -275,7 +275,7 @@ trait TraversableLike[+A, +Repr] extends Any def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { val b = bf(repr) - for (x <- this) if (pf.isDefinedAt(x)) b += pf(x) + foreach(pf.runWith(b += _)) b.result } diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala index d53d000e90..82cf1d1198 100644 --- a/src/library/scala/collection/TraversableOnce.scala +++ b/src/library/scala/collection/TraversableOnce.scala @@ -128,10 +128,8 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { * @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)` */ def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = { - for (x <- self.toIterator) { // make sure to use an iterator or `seq` - if (pf isDefinedAt x) - return Some(pf(x)) - } + // make sure to use an iterator or `seq` + self.toIterator.foreach(pf.runWith(b => return Some(b))) None } @@ -184,7 +182,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] { def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op) - def aggregate[B](z: B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop) + def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop) def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) diff --git a/src/library/scala/collection/TraversableView.scala b/src/library/scala/collection/TraversableView.scala index cce6b72257..af219084b8 100644 --- a/src/library/scala/collection/TraversableView.scala +++ b/src/library/scala/collection/TraversableView.scala @@ -10,7 +10,6 @@ package scala.collection import generic._ import mutable.Builder -import TraversableView.NoBuilder /** A base trait for non-strict views of traversable collections. * $traversableViewInfo diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala index 14f865c2f0..36f6210ef4 100644 --- a/src/library/scala/collection/TraversableViewLike.scala +++ b/src/library/scala/collection/TraversableViewLike.scala @@ -10,7 +10,6 @@ package scala.collection import generic._ import mutable.{ Builder, ArrayBuffer } -import TraversableView.NoBuilder import scala.annotation.migration import scala.language.implicitConversions @@ -59,7 +58,7 @@ trait ViewMkString[+A] { * $viewInfo * * All views for traversable collections are defined by creating a new `foreach` method. - * + * * @author Martin Odersky * @version 2.8 * @since 2.8 @@ -162,7 +161,7 @@ trait TraversableViewLike[+A, // if (b.isInstanceOf[NoBuilder[_]]) newFlatMapped(f).asInstanceOf[That] // else super.flatMap[B, That](f)(bf) } - override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = + override def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]) = newFlatMapped(asTraversable) private[this] implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 6c11c5bcb5..14b475dd1f 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -545,7 +545,7 @@ private[collection] final class CNode[K, V](val bitmap: Int, val array: Array[Ba // removed (those existing when the op began) // - if there are only null-i-nodes below, returns null def toCompressed(ct: TrieMap[K, V], lev: Int, gen: Gen) = { - var bmp = bitmap + val bmp = bitmap var i = 0 val arr = array val tmparray = new Array[BasicNode](arr.length) @@ -920,8 +920,8 @@ object TrieMap extends MutableMapFactory[TrieMap] { private[collection] class TrieMapIterator[K, V](var level: Int, private var ct: TrieMap[K, V], mustInit: Boolean = true) extends Iterator[(K, V)] { - private var stack = new Array[Array[BasicNode]](7) - private var stackpos = new Array[Int](7) + private val stack = new Array[Array[BasicNode]](7) + private val stackpos = new Array[Int](7) private var depth = -1 private var subiter: Iterator[(K, V)] = null private var current: KVNode[K, V] = null diff --git a/src/library/scala/collection/convert/Decorators.scala b/src/library/scala/collection/convert/Decorators.scala index e2c46c1e4f..f004e4712b 100644 --- a/src/library/scala/collection/convert/Decorators.scala +++ b/src/library/scala/collection/convert/Decorators.scala @@ -9,7 +9,7 @@ package scala.collection package convert -import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc } +import java.{ util => ju } private[collection] trait Decorators { /** Generic class containing the `asJava` converter method */ diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala index a43862abaf..b36dd3ccaf 100644 --- a/src/library/scala/collection/generic/GenTraversableFactory.scala +++ b/src/library/scala/collection/generic/GenTraversableFactory.scala @@ -249,4 +249,3 @@ extends GenericCompanion[CC] { b.result } } - diff --git a/src/library/scala/collection/generic/IsSeqLike.scala b/src/library/scala/collection/generic/IsSeqLike.scala new file mode 100644 index 0000000000..9467510a2c --- /dev/null +++ b/src/library/scala/collection/generic/IsSeqLike.scala @@ -0,0 +1,57 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.collection +package generic + +/** Type class witnessing that a collection representation type `Repr` has + * elements of type `A` and has a conversion to `SeqLike[A, Repr]`. + * + * This type enables simple enrichment of `Seq`s with extension methods which + * can make full use of the mechanics of the Scala collections framework in + * their implementation. + * + * Example usage: + * {{{ + * class FilterMapImpl[A, Repr](val r: SeqLike[A, Repr]) { + * final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = + * r.flatMap(f(_)) + * } + * implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsSeqLike[Repr]): FilterMapImpl[fr.A,Repr] = + * new FilterMapImpl(fr.conversion(r)) + * + * val l = List(1, 2, 3, 4, 5) + * List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None) + * // == List(2, 4) + * }}} + * + * @see [[scala.collection.Seq]] + * @see [[scala.collection.generic.IsTraversableLike]] + */ +trait IsSeqLike[Repr] { + /** The type of elements we can traverse over. */ + type A + /** A conversion from the representation type `Repr` to a `SeqLike[A,Repr]`. */ + val conversion: Repr => SeqLike[A, Repr] +} + +object IsSeqLike { + import language.higherKinds + + implicit val stringRepr: IsSeqLike[String] { type A = Char } = + new IsSeqLike[String] { + type A = Char + val conversion = implicitly[String => SeqLike[Char, String]] + } + + implicit def seqLikeRepr[C[_], A0](implicit conv: C[A0] => SeqLike[A0,C[A0]]): IsSeqLike[C[A0]] { type A = A0 } = + new IsSeqLike[C[A0]] { + type A = A0 + val conversion = conv + } +} diff --git a/src/library/scala/collection/generic/IterableForwarder.scala b/src/library/scala/collection/generic/IterableForwarder.scala index 90ebcace84..8feace3f8b 100644 --- a/src/library/scala/collection/generic/IterableForwarder.scala +++ b/src/library/scala/collection/generic/IterableForwarder.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - - package scala.collection.generic -import scala.collection._ -import scala.collection.mutable.Buffer +import scala.collection._ /** This trait implements a forwarder for iterable objects. It forwards * all calls to a different iterable object, except for diff --git a/src/library/scala/collection/generic/SeqForwarder.scala b/src/library/scala/collection/generic/SeqForwarder.scala index e8b15ec450..aafaffc159 100644 --- a/src/library/scala/collection/generic/SeqForwarder.scala +++ b/src/library/scala/collection/generic/SeqForwarder.scala @@ -50,7 +50,7 @@ trait SeqForwarder[+A] extends Seq[A] with IterableForwarder[A] { override def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = underlying lastIndexOfSlice that override def lastIndexOfSlice[B >: A](that: GenSeq[B], end: Int): Int = underlying.lastIndexOfSlice(that, end) override def containsSlice[B](that: GenSeq[B]): Boolean = underlying containsSlice that - override def contains(elem: Any): Boolean = underlying contains elem + override def contains[A1 >: A](elem: A1): Boolean = underlying contains elem override def corresponds[B](that: GenSeq[B])(p: (A,B) => Boolean): Boolean = underlying.corresponds(that)(p) override def indices: Range = underlying.indices } diff --git a/src/library/scala/collection/immutable/DefaultMap.scala b/src/library/scala/collection/immutable/DefaultMap.scala index 4a0503adfd..620baec9a8 100755 --- a/src/library/scala/collection/immutable/DefaultMap.scala +++ b/src/library/scala/collection/immutable/DefaultMap.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - - package scala.collection package immutable -import generic._ - /** A default map which implements the `+` and `-` * methods of maps. It does so using the default builder for * maps defined in the `Map` object. diff --git a/src/library/scala/collection/immutable/GenIterable.scala.disabled b/src/library/scala/collection/immutable/GenIterable.scala.disabled deleted file mode 100644 index d34f7fd856..0000000000 --- a/src/library/scala/collection/immutable/GenIterable.scala.disabled +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A base trait for iterable collections that can be mutated. - * - * $possiblyparinfo - * - * $iterableInfo - */ -trait GenIterable[+A] extends GenTraversable[A] - with scala.collection.GenIterable[A] - with scala.collection.GenIterableLike[A, GenIterable[A]] -// with GenericTraversableTemplate[A, GenIterable] -{ - def seq: Iterable[A] - //override def companion: GenericCompanion[GenIterable] = GenIterable -} - - -// object GenIterable extends TraversableFactory[GenIterable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder -// } - diff --git a/src/library/scala/collection/immutable/GenMap.scala.disabled b/src/library/scala/collection/immutable/GenMap.scala.disabled deleted file mode 100644 index 73557a4a66..0000000000 --- a/src/library/scala/collection/immutable/GenMap.scala.disabled +++ /dev/null @@ -1,36 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package immutable - -import generic._ - - -/** A base trait for maps that can be mutated. - * $possiblyparinfo - * $mapNote - * $mapTags - * @since 1.0 - * @author Matthias Zenger - */ -trait GenMap[A, +B] -extends GenIterable[(A, B)] - with scala.collection.GenMap[A, B] - with scala.collection.GenMapLike[A, B, GenMap[A, B]] -{ - def seq: Map[A, B] -} - - -// object GenMap extends MapFactory[GenMap] { -// def empty[A, B]: Map[A, B] = Map.empty - -// /** $mapCanBuildFromInfo */ -// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] -// } diff --git a/src/library/scala/collection/immutable/GenSeq.scala.disabled b/src/library/scala/collection/immutable/GenSeq.scala.disabled deleted file mode 100644 index 713529f3db..0000000000 --- a/src/library/scala/collection/immutable/GenSeq.scala.disabled +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A subtrait of `collection.GenSeq` which represents sequences - * that can be mutated. - * - * $possiblyparinfo - * - * $seqInfo - * - * The class adds an `update` method to `collection.Seq`. - * - * @define Coll `mutable.Seq` - * @define coll mutable sequence - */ -trait GenSeq[+A] extends GenIterable[A] - with scala.collection.GenSeq[A] - with scala.collection.GenSeqLike[A, GenSeq[A]] -// with GenericTraversableTemplate[A, GenSeq] -{ - def seq: Seq[A] - //override def companion: GenericCompanion[GenSeq] = GenSeq -} - - -// object GenSeq extends SeqFactory[GenSeq] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder -// } - - - - - diff --git a/src/library/scala/collection/immutable/GenSet.scala.disabled b/src/library/scala/collection/immutable/GenSet.scala.disabled deleted file mode 100644 index 56bd2738fd..0000000000 --- a/src/library/scala/collection/immutable/GenSet.scala.disabled +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A generic trait for mutable sets. - * - * $possiblyparinfo - * $setNote - * $setTags - * - * @since 1.0 - * @author Matthias Zenger - * @define Coll `mutable.Set` - * @define coll mutable set - */ -trait GenSet[A] extends GenIterable[A] - with scala.collection.GenSet[A] - with scala.collection.GenSetLike[A, GenSet[A]] -// with GenericSetTemplate[A, GenSet] -{ - //override def companion: GenericCompanion[GenSet] = GenSet - def seq: Set[A] -} - - -// object GenSet extends TraversableFactory[GenSet] { -// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A] = Set.newBuilder -// } diff --git a/src/library/scala/collection/immutable/GenTraversable.scala.disabled b/src/library/scala/collection/immutable/GenTraversable.scala.disabled deleted file mode 100644 index e5b609f9ed..0000000000 --- a/src/library/scala/collection/immutable/GenTraversable.scala.disabled +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package immutable - - -import generic._ -import mutable.Builder - - -/** A trait for traversable collections that can be mutated. - * - * $possiblyparinfo - * - * $traversableInfo - * @define mutability mutable - */ -trait GenTraversable[+A] extends scala.collection.GenTraversable[A] - with scala.collection.GenTraversableLike[A, GenTraversable[A]] -// with GenericTraversableTemplate[A, GenTraversable] - with Mutable -{ - def seq: Traversable[A] - //override def companion: GenericCompanion[GenTraversable] = GenTraversable -} - - -// object GenTraversable extends TraversableFactory[GenTraversable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenTraversable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenTraversable[A]] = Traversable.newBuilder -// } - - diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 84416a62d2..29267f22dc 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -471,9 +471,6 @@ time { mNew.iterator.foreach( p => ()) } // condition below is due to 2 things: // 1) no unsigned int compare on JVM // 2) 0 (no lsb) should always be greater in comparison - val a = thislsb - 1 - val b = thatlsb - 1 - if (unsignedCompare(thislsb - 1, thatlsb - 1)) { val m = thiselems(thisi) totalelems += m.size diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala index bf4ba3a381..9316ff5e72 100644 --- a/src/library/scala/collection/immutable/IndexedSeq.scala +++ b/src/library/scala/collection/immutable/IndexedSeq.scala @@ -37,6 +37,7 @@ object IndexedSeq extends IndexedSeqFactory[IndexedSeq] { def apply(idx: Int) = buf.apply(idx) } def newBuilder[A]: Builder[A, IndexedSeq[A]] = Vector.newBuilder[A] + implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] } diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 56e386ad67..aeaa479e2f 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -152,7 +152,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] * @usecase def mapConserve(f: A => A): List[A] * @inheritdoc */ - def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = { + @inline final def mapConserve[B >: A <: AnyRef](f: A => B): List[B] = { @tailrec def loop(mapped: ListBuffer[B], unchanged: List[A], pending: List[A]): List[B] = if (pending.isEmpty) { @@ -257,7 +257,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] (b.toList, these) } - override def takeWhile(p: A => Boolean): List[A] = { + @inline final override def takeWhile(p: A => Boolean): List[A] = { val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { @@ -267,7 +267,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] b.toList } - override def dropWhile(p: A => Boolean): List[A] = { + @inline final override def dropWhile(p: A => Boolean): List[A] = { @tailrec def loop(xs: List[A]): List[A] = if (xs.isEmpty || !p(xs.head)) xs @@ -276,7 +276,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] loop(this) } - override def span(p: A => Boolean): (List[A], List[A]) = { + @inline final override def span(p: A => Boolean): (List[A], List[A]) = { val b = new ListBuffer[A] var these = this while (!these.isEmpty && p(these.head)) { @@ -286,6 +286,16 @@ sealed abstract class List[+A] extends AbstractSeq[A] (b.toList, these) } + // Overridden with an implementation identical to the inherited one (at this time) + // solely so it can be finalized and thus inlinable. + @inline final override def foreach[U](f: A => U) { + var these = this + while (!these.isEmpty) { + f(these.head) + these = these.tail + } + } + override def reverse: List[A] = { var result: List[A] = Nil var these = this @@ -301,18 +311,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] override def toStream : Stream[A] = if (isEmpty) Stream.Empty else new Stream.Cons(head, tail.toStream) - - @inline override final - def foreach[B](f: A => B) { - var these = this - while (!these.isEmpty) { - f(these.head) - these = these.tail - } - } - - @deprecated("use `distinct` instead", "2.8.0") - def removeDuplicates: List[A] = distinct } /** The empty list. @@ -381,12 +379,6 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend current = list } } - - private def oldWriteObject(out: ObjectOutputStream) { - var xs: List[B] = this - while (!xs.isEmpty) { out.writeObject(xs.head); xs = xs.tail } - out.writeObject(ListSerializeEnd) - } } /** $factoryInfo @@ -394,9 +386,6 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend * @define Coll `List` */ object List extends SeqFactory[List] { - - import scala.collection.{Iterable, Seq, IndexedSeq} - /** $genericCanBuildFromInfo */ implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, List[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] @@ -406,248 +395,6 @@ object List extends SeqFactory[List] { override def empty[A]: List[A] = Nil override def apply[A](xs: A*): List[A] = xs.toList - - /** Create a sorted list with element values `v,,>n+1,, = step(v,,n,,)` - * where `v,,0,, = start` and elements are in the range between `start` - * (inclusive) and `end` (exclusive). - * - * @param start the start value of the list - * @param end the end value of the list - * @param step the increment function of the list, which given `v,,n,,`, - * computes `v,,n+1,,`. Must be monotonically increasing - * or decreasing. - * @return the sorted list of all integers in range `[start;end)`. - */ - @deprecated("use `iterate` instead", "2.8.0") - def range(start: Int, end: Int, step: Int => Int): List[Int] = { - val up = step(start) > start - val down = step(start) < start - val b = new ListBuffer[Int] - var i = start - while ((!up || i < end) && (!down || i > end)) { - b += i - val next = step(i) - if (i == next) - throw new IllegalArgumentException("the step function did not make any progress on "+ i) - i = next - } - b.toList - } - - /** Create a list containing several copies of an element. - * - * @param n the length of the resulting list - * @param elem the element composing the resulting list - * @return a list composed of `n` elements all equal to `elem` - */ - @deprecated("use `fill` instead", "2.8.0") - def make[A](n: Int, elem: A): List[A] = { - val b = new ListBuffer[A] - var i = 0 - while (i < n) { - b += elem - i += 1 - } - b.toList - } - - /** Concatenate all the elements of a given list of lists. - * - * @param xss the list of lists that are to be concatenated - * @return the concatenation of all the lists - */ - @deprecated("use `xss.flatten` instead of `List.flatten(xss)`", "2.8.0") - def flatten[A](xss: List[List[A]]): List[A] = { - val b = new ListBuffer[A] - for (xs <- xss) { - var xc = xs - while (!xc.isEmpty) { - b += xc.head - xc = xc.tail - } - } - b.toList - } - - /** Transforms a list of pairs into a pair of lists. - * - * @param xs the list of pairs to unzip - * @return a pair of lists. - */ - @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") - def unzip[A,B](xs: List[(A,B)]): (List[A], List[B]) = { - val b1 = new ListBuffer[A] - val b2 = new ListBuffer[B] - var xc = xs - while (!xc.isEmpty) { - b1 += xc.head._1 - b2 += xc.head._2 - xc = xc.tail - } - (b1.toList, b2.toList) - } - - /** Transforms an iterable of pairs into a pair of lists. - * - * @param xs the iterable of pairs to unzip - * @return a pair of lists. - */ - @deprecated("use `xs.unzip` instead of `List.unzip(xs)`", "2.8.0") - def unzip[A,B](xs: Iterable[(A,B)]): (List[A], List[B]) = - xs.foldRight[(List[A], List[B])]((Nil, Nil)) { - case ((x, y), (xs, ys)) => (x :: xs, y :: ys) - } - - /** - * Returns the `Left` values in the given `Iterable` of `Either`s. - */ - @deprecated("use `xs collect { case Left(x: A) => x }` instead of `List.lefts(xs)`", "2.8.0") - def lefts[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[A]](Nil)((e, as) => e match { - case Left(a) => a :: as - case Right(_) => as - }) - - /** - * Returns the `Right` values in the given `Iterable` of `Either`s. - */ - @deprecated("use `xs collect { case Right(x: B) => x }` instead of `List.rights(xs)`", "2.8.0") - def rights[A, B](es: Iterable[Either[A, B]]) = - es.foldRight[List[B]](Nil)((e, bs) => e match { - case Left(_) => bs - case Right(b) => b :: bs - }) - - /** Transforms an Iterable of Eithers into a pair of lists. - * - * @param es the iterable of Eithers to separate - * @return a pair of lists. - */ - @deprecated("use `(for (Left(x) <- es) yield x, for (Right(x) <- es) yield x)` instead", "2.8.0") - def separate[A,B](es: Iterable[Either[A, B]]): (List[A], List[B]) = - es.foldRight[(List[A], List[B])]((Nil, Nil)) { - case (Left(a), (lefts, rights)) => (a :: lefts, rights) - case (Right(b), (lefts, rights)) => (lefts, b :: rights) - } - - /** Converts an iterator to a list. - * - * @param it the iterator to convert - * @return a list that contains the elements returned by successive - * calls to `it.next` - */ - @deprecated("use `it.toList` instead of `List.toList(it)`", "2.8.0") - def fromIterator[A](it: Iterator[A]): List[A] = it.toList - - /** Converts an array into a list. - * - * @param arr the array to convert - * @return a list that contains the same elements than `arr` - * in the same order - */ - @deprecated("use `array.toList` instead of `List.fromArray(array)`", "2.8.0") - def fromArray[A](arr: Array[A]): List[A] = fromArray(arr, 0, arr.length) - - /** Converts a range of an array into a list. - * - * @param arr the array to convert - * @param start the first index to consider - * @param len the length of the range to convert - * @return a list that contains the same elements than `arr` - * in the same order - */ - @deprecated("use `array.view(start, end).toList` instead of `List.fromArray(array, start, end)`", "2.8.0") - def fromArray[A](arr: Array[A], start: Int, len: Int): List[A] = { - var res: List[A] = Nil - var i = start + len - while (i > start) { - i -= 1 - res = arr(i) :: res - } - res - } - - /** Returns the list resulting from applying the given function `f` - * to corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `[f(a,,0,,,b,,0,,), ..., f(a,,n,,,b,,n,,)]` if the lists are - * `[a,,0,,, ..., a,,k,,]`, `[b,,0,,, ..., b,,l,,]` and - * `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.map(f)` instead of `List.map2(xs, ys)(f)`", "2.8.0") - def map2[A,B,C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C] = { - val b = new ListBuffer[C] - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - b += f(xc.head, yc.head) - xc = xc.tail - yc = yc.tail - } - b.toList - } - - /** Tests whether the given predicate `p` holds - * for all corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `(p(a<sub>0</sub>,b<sub>0</sub>) && - * ... && p(a<sub>n</sub>,b<sub>n</sub>))]` - * if the lists are `[a<sub>0</sub>, ..., a<sub>k</sub>]`; - * `[b<sub>0</sub>, ..., b<sub>l</sub>]` - * and `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.forall(f)` instead of `List.forall2(xs, ys)(f)`", "2.8.0") - def forall2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (!f(xc.head, yc.head)) return false - xc = xc.tail - yc = yc.tail - } - true - } - - /** Tests whether the given predicate `p` holds - * for some corresponding elements of the argument lists. - * - * @param f function to apply to each pair of elements. - * @return `n != 0 && (p(a<sub>0</sub>,b<sub>0</sub>) || - * ... || p(a<sub>n</sub>,b<sub>n</sub>))]` if the lists are - * `[a<sub>0</sub>, ..., a<sub>k</sub>]`, - * `[b<sub>0</sub>, ..., b<sub>l</sub>]` and - * `n = min(k,l)` - */ - @deprecated("use `(xs, ys).zipped.exists(f)` instead of `List.exists2(xs, ys)(f)`", "2.8.0") - def exists2[A,B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean = { - var xc = xs - var yc = ys - while (!xc.isEmpty && !yc.isEmpty) { - if (f(xc.head, yc.head)) return true - xc = xc.tail - yc = yc.tail - } - false - } - - /** Transposes a list of lists. - * pre: All element lists have the same length. - * - * @param xss the list of lists - * @return the transposed list of lists - */ - @deprecated("use `xss.transpose` instead of `List.transpose(xss)`", "2.8.0") - def transpose[A](xss: List[List[A]]): List[List[A]] = { - val buf = new ListBuffer[List[A]] - var yss = xss - while (!yss.head.isEmpty) { - buf += (yss map (_.head)) - yss = (yss map (_.tail)) - } - buf.toList - } } /** Only used for list serialization */ diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index 2a2910439a..fab1b7f00b 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -77,8 +77,6 @@ object LongMap { } } -import LongMap._ - // Iterator over a non-empty LongMap. private[immutable] abstract class LongMapIterator[V, T](it: LongMap[V]) extends AbstractIterator[T] { diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala index d3be299f89..195aeed281 100644 --- a/src/library/scala/collection/immutable/NumericRange.scala +++ b/src/library/scala/collection/immutable/NumericRange.scala @@ -6,12 +6,10 @@ ** |/ ** \* */ - package scala.collection package immutable import mutable.{ Builder, ListBuffer } -import generic._ /** `NumericRange` is a more generic version of the * `Range` class which works with arbitrary types. @@ -81,17 +79,6 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { // to guard against any (most likely illusory) performance drop. They should // be eliminated one way or another. - // Counts how many elements from the start meet the given test. - private def skipCount(p: T => Boolean): Int = { - var current = start - var counted = 0 - - while (counted < length && p(current)) { - counted += 1 - current += step - } - counted - } // Tests whether a number is within the endpoints, without testing // whether it is a member of the sequence (i.e. when step > 1.) private def isWithinBoundaries(elem: T) = !isEmpty && ( @@ -124,21 +111,21 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { if (idx < 0 || idx >= length) throw new IndexOutOfBoundsException(idx.toString) else locationAfterN(idx) } - + import NumericRange.defaultOrdering - + override def min[T1 >: T](implicit ord: Ordering[T1]): T = if (ord eq defaultOrdering(num)) { if (num.signum(step) > 0) start else last } else super.min(ord) - - override def max[T1 >: T](implicit ord: Ordering[T1]): T = + + override def max[T1 >: T](implicit ord: Ordering[T1]): T = if (ord eq defaultOrdering(num)) { if (num.signum(step) > 0) last else start } else super.max(ord) - + // Motivated by the desire for Double ranges with BigDecimal precision, // we need some way to map a Range and get another Range. This can't be // done in any fully general way because Ranges are not arbitrary @@ -182,12 +169,11 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { def containsTyped(x: T): Boolean = isWithinBoundaries(x) && (((x - start) % step) == zero) - override def contains(x: Any): Boolean = + override def contains[A1 >: T](x: A1): Boolean = try containsTyped(x.asInstanceOf[T]) catch { case _: ClassCastException => false } final override def sum[B >: T](implicit num: Numeric[B]): B = { - import num.Ops if (isEmpty) this.num fromInt 0 else if (numRangeElements == 1) head else ((this.num fromInt numRangeElements) * (head + last) / (this.num fromInt 2)) @@ -213,7 +199,7 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable { /** A companion object for numeric ranges. */ object NumericRange { - + /** Calculates the number of elements in a range given start, end, step, and * whether or not it is inclusive. Throws an exception if step == 0 or * the number of elements exceeds the maximum Int. @@ -272,7 +258,7 @@ object NumericRange { new Exclusive(start, end, step) def inclusive[T](start: T, end: T, step: T)(implicit num: Integral[T]): Inclusive[T] = new Inclusive(start, end, step) - + private[collection] val defaultOrdering = Map[Numeric[_], Ordering[_]]( Numeric.BigIntIsIntegral -> Ordering.BigInt, Numeric.IntIsIntegral -> Ordering.Int, @@ -284,6 +270,6 @@ object NumericRange { Numeric.DoubleAsIfIntegral -> Ordering.Double, Numeric.BigDecimalAsIfIntegral -> Ordering.BigDecimal ) - + } diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 3b6ab81146..e1aba20fdb 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -78,6 +78,7 @@ extends scala.collection.AbstractSeq[Int] final val terminalElement = start + numRangeElements * step override def last = if (isEmpty) Nil.last else lastElement + override def head = if (isEmpty) Nil.head else start override def min[A1 >: Int](implicit ord: Ordering[A1]): Int = if (ord eq Ordering.Int) { diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index 0254e9ca3a..99f8d95517 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -18,7 +18,7 @@ import scala.annotation.meta.getter /** An object containing the RedBlack tree implementation used by for `TreeMaps` and `TreeSets`. * * Implementation note: since efficiency is important for data structures this implementation - * uses <code>null</code> to represent empty trees. This also means pattern matching cannot + * uses `null` to represent empty trees. This also means pattern matching cannot * easily be used. The API represented by the RedBlackTree object tries to hide these * optimizations behind a reasonably clean API. * @@ -74,15 +74,21 @@ object RedBlackTree { result } - def foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U): Unit = if (tree ne null) { - if (tree.left ne null) foreach(tree.left, f) + + def foreach[A,B,U](tree:Tree[A,B], f:((A,B)) => U):Unit = if (tree ne null) _foreach(tree,f) + + private[this] def _foreach[A, B, U](tree: Tree[A, B], f: ((A, B)) => U) { + if (tree.left ne null) _foreach(tree.left, f) f((tree.key, tree.value)) - if (tree.right ne null) foreach(tree.right, f) + if (tree.right ne null) _foreach(tree.right, f) } - def foreachKey[A, U](tree: Tree[A, _], f: A => U): Unit = if (tree ne null) { - if (tree.left ne null) foreachKey(tree.left, f) - f(tree.key) - if (tree.right ne null) foreachKey(tree.right, f) + + def foreachKey[A, U](tree:Tree[A,_], f: A => U):Unit = if (tree ne null) _foreachKey(tree,f) + + private[this] def _foreachKey[A, U](tree: Tree[A, _], f: A => U) { + if (tree.left ne null) _foreachKey(tree.left, f) + f((tree.key)) + if (tree.right ne null) _foreachKey(tree.right, f) } def iterator[A, B](tree: Tree[A, B]): Iterator[(A, B)] = new EntriesIterator(tree) diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index be2cd91c68..3f7d27981b 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -181,6 +181,7 @@ import scala.language.implicitConversions * @define coll stream * @define orderDependent * @define orderDependentFold + * @define willTerminateInf Note: lazily evaluated; will terminate for infinite-sized collections. */ abstract class Stream[+A] extends AbstractSeq[A] with LinearSeq[A] @@ -286,9 +287,8 @@ self => len } - /** It's an imperfect world, but at least we can bottle up the - * imperfection in a capsule. - */ + // It's an imperfect world, but at least we can bottle up the + // imperfection in a capsule. @inline private def asThat[That](x: AnyRef): That = x.asInstanceOf[That] @inline private def asStream[B](x: AnyRef): Stream[B] = x.asInstanceOf[Stream[B]] @inline private def isStreamBuilder[B, That](bf: CanBuildFrom[Stream[A], B, That]) = @@ -385,12 +385,17 @@ self => // 1) stackoverflows (could be achieved with tailrec, too) // 2) out of memory errors for big streams (`this` reference can be eliminated from the stack) var rest: Stream[A] = this - while (rest.nonEmpty && !pf.isDefinedAt(rest.head)) rest = rest.tail + + // Avoids calling both `pf.isDefined` and `pf.apply`. + var newHead: B = null.asInstanceOf[B] + val runWith = pf.runWith((b: B) => newHead = b) + + while (rest.nonEmpty && !runWith(rest.head)) rest = rest.tail // without the call to the companion object, a thunk is created for the tail of the new stream, // and the closure of the thunk will reference `this` if (rest.isEmpty) Stream.Empty.asInstanceOf[That] - else Stream.collectedTail(rest, pf, bf).asInstanceOf[That] + else Stream.collectedTail(newHead, rest, pf, bf).asInstanceOf[That] } } @@ -725,10 +730,15 @@ self => * // produces: "5, 6, 7, 8, 9" * }}} */ - override def take(n: Int): Stream[A] = + override def take(n: Int): Stream[A] = ( + // Note that the n == 1 condition appears redundant but is not. + // It prevents "tail" from being referenced (and its head being evaluated) + // when obtaining the last element of the result. Such are the challenges + // of working with a lazy-but-not-really sequence. if (n <= 0 || isEmpty) Stream.empty else if (n == 1) cons(head, Stream.empty) else cons(head, tail take n-1) + ) @tailrec final override def drop(n: Int): Stream[A] = if (n <= 0 || isEmpty) this @@ -784,8 +794,23 @@ self => these } - // there's nothing we can do about dropRight, so we just keep the definition - // in LinearSeq + /** + * @inheritdoc + * $willTerminateInf + */ + override def dropRight(n: Int): Stream[A] = { + // We make dropRight work for possibly infinite streams by carrying + // a buffer of the dropped size. As long as the buffer is full and the + // rest is non-empty, we can feed elements off the buffer head. When + // the rest becomes empty, the full buffer is the dropped elements. + def advance(stub0: List[A], stub1: List[A], rest: Stream[A]): Stream[A] = { + if (rest.isEmpty) Stream.empty + else if (stub0.isEmpty) advance(stub1.reverse, Nil, rest) + else cons(stub0.head, advance(stub0.tail, rest.head :: stub1, rest.tail)) + } + if (n <= 0) this + else advance((this take n).toList, Nil, this drop n) + } /** Returns the longest prefix of this `Stream` whose elements satisfy the * predicate `p`. @@ -841,9 +866,16 @@ self => * // produces: "1, 2, 3, 4, 5, 6" * }}} */ - override def distinct: Stream[A] = - if (isEmpty) this - else cons(head, tail.filter(head != _).distinct) + override def distinct: Stream[A] = { + // This should use max memory proportional to N, whereas + // recursively calling distinct on the tail is N^2. + def loop(seen: Set[A], rest: Stream[A]): Stream[A] = { + if (rest.isEmpty) rest + else if (seen(rest.head)) loop(seen, rest.tail) + else cons(rest.head, loop(seen + rest.head, rest.tail)) + } + loop(Set(), this) + } /** Returns a new sequence of given length containing the elements of this * sequence followed by zero or more occurrences of given elements. @@ -1142,8 +1174,8 @@ object Stream extends SeqFactory[Stream] { cons(stream.head, stream.tail filter p) } - private[immutable] def collectedTail[A, B, That](stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = { - cons(pf(stream.head), stream.tail.collect(pf)(bf).asInstanceOf[Stream[B]]) + private[immutable] def collectedTail[A, B, That](head: B, stream: Stream[A], pf: PartialFunction[A, B], bf: CanBuildFrom[Stream[A], B, That]) = { + cons(head, stream.tail.collect(pf)(bf).asInstanceOf[Stream[B]]) } } diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index edea89b555..663318330c 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -9,7 +9,6 @@ package scala.collection package immutable -import generic._ import mutable.Builder import scala.util.matching.Regex import scala.math.ScalaNumber @@ -19,12 +18,11 @@ import scala.reflect.ClassTag * @since 2.8 */ object StringLike { - // just statics for companion class. - private final val LF: Char = 0x0A - private final val FF: Char = 0x0C - private final val CR: Char = 0x0D - private final val SU: Char = 0x1A + private final val LF = 0x0A + private final val FF = 0x0C + private final val CR = 0x0D + private final val SU = 0x1A } import StringLike._ diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala index a650d98697..16c1f96cc2 100644 --- a/src/library/scala/collection/immutable/StringOps.scala +++ b/src/library/scala/collection/immutable/StringOps.scala @@ -6,8 +6,6 @@ ** |/ ** \* */ - - package scala.collection package immutable diff --git a/src/library/scala/collection/immutable/TrieIterator.scala b/src/library/scala/collection/immutable/TrieIterator.scala index ae427852d4..f117bddb8c 100644 --- a/src/library/scala/collection/immutable/TrieIterator.scala +++ b/src/library/scala/collection/immutable/TrieIterator.scala @@ -177,7 +177,6 @@ private[collection] abstract class TrieIterator[+T](elems: Array[Iterable[T]]) e if (depth > 0) { // 2) topmost comes before (is not) arrayD // steal a portion of top to create a new iterator - val topmost = arrayStack(0) if (posStack(0) == arrayStack(0).length - 1) { // 2a) only a single entry left on top // this means we have to modify this iterator - pop topmost diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index f083e80175..abaffd9d6a 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -139,7 +139,7 @@ override def companion: GenericCompanion[Vector] = Vector if (bf eq IndexedSeq.ReusableCBF) appendFront(elem).asInstanceOf[That] // just ignore bf else super.+:(elem)(bf) - override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = + override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = if (bf eq IndexedSeq.ReusableCBF) appendBack(elem).asInstanceOf[That] // just ignore bf else super.:+(elem)(bf) @@ -242,8 +242,8 @@ override def companion: GenericCompanion[Vector] = Vector private[immutable] def appendFront[B>:A](value: B): Vector[B] = { if (endIndex != startIndex) { - var blockIndex = (startIndex - 1) & ~31 - var lo = (startIndex - 1) & 31 + val blockIndex = (startIndex - 1) & ~31 + val lo = (startIndex - 1) & 31 if (startIndex != blockIndex + 32) { val s = new Vector(startIndex - 1, endIndex, blockIndex) @@ -339,8 +339,8 @@ override def companion: GenericCompanion[Vector] = Vector // //println("------- append " + value) // debug() if (endIndex != startIndex) { - var blockIndex = endIndex & ~31 - var lo = endIndex & 31 + val blockIndex = endIndex & ~31 + val lo = endIndex & 31 if (endIndex != blockIndex) { //println("will make writable block (from "+focus+") at: " + blockIndex) @@ -574,9 +574,7 @@ override def companion: GenericCompanion[Vector] = Vector } private def dropFront0(cutIndex: Int): Vector[A] = { - var blockIndex = cutIndex & ~31 - var lo = cutIndex & 31 - + val blockIndex = cutIndex & ~31 val xor = cutIndex ^ (endIndex - 1) val d = requiredDepth(xor) val shift = (cutIndex & ~((1 << (5*d))-1)) @@ -606,9 +604,7 @@ override def companion: GenericCompanion[Vector] = Vector } private def dropBack0(cutIndex: Int): Vector[A] = { - var blockIndex = (cutIndex - 1) & ~31 - var lo = ((cutIndex - 1) & 31) + 1 - + val blockIndex = (cutIndex - 1) & ~31 val xor = startIndex ^ (cutIndex - 1) val d = requiredDepth(xor) val shift = (startIndex & ~((1 << (5*d))-1)) @@ -630,14 +626,13 @@ override def companion: GenericCompanion[Vector] = Vector } -class VectorIterator[+A](_startIndex: Int, _endIndex: Int) +class VectorIterator[+A](_startIndex: Int, endIndex: Int) extends AbstractIterator[A] with Iterator[A] with VectorPointer[A @uncheckedVariance] { private var blockIndex: Int = _startIndex & ~31 private var lo: Int = _startIndex & 31 - private var endIndex: Int = _endIndex private var endLo = math.min(endIndex - blockIndex, 32) @@ -667,13 +662,13 @@ extends AbstractIterator[A] res } - private[collection] def remainingElementCount: Int = (_endIndex - (blockIndex + lo)) max 0 + private[collection] def remainingElementCount: Int = (endIndex - (blockIndex + lo)) max 0 /** Creates a new vector which consists of elements remaining in this iterator. * Such a vector can then be split into several vectors using methods like `take` and `drop`. */ private[collection] def remainingVector: Vector[A] = { - val v = new Vector(blockIndex + lo, _endIndex, blockIndex + lo) + val v = new Vector(blockIndex + lo, endIndex, blockIndex + lo) v.initFrom(this) v } diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index 0ce2cda32c..2fe3e91d68 100644 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime diff --git a/src/library/scala/collection/mutable/ArrayLike.scala b/src/library/scala/collection/mutable/ArrayLike.scala index 31f3d2a497..40017aa08e 100644 --- a/src/library/scala/collection/mutable/ArrayLike.scala +++ b/src/library/scala/collection/mutable/ArrayLike.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ /** A common supertrait of `ArrayOps` and `WrappedArray` that factors out most * operations on arrays and wrapped arrays. diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala index 37aa1862fa..ade0b94230 100644 --- a/src/library/scala/collection/mutable/BufferProxy.scala +++ b/src/library/scala/collection/mutable/BufferProxy.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ import script._ /** This is a simple proxy class for <a href="Buffer.html" diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index c0299479f3..94242260a1 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -266,7 +266,7 @@ trait FlatHashTable[A] extends FlatHashTable.HashUtils[A] { val totalbuckets = totalSizeMapBuckets var bucketidx = 0 var tableidx = 0 - var tbl = table + val tbl = table var tableuntil = sizeMapBucketSize min tbl.length while (bucketidx < totalbuckets) { var currbucketsz = 0 diff --git a/src/library/scala/collection/mutable/GenIterable.scala.disabled b/src/library/scala/collection/mutable/GenIterable.scala.disabled deleted file mode 100644 index 9acfccdae8..0000000000 --- a/src/library/scala/collection/mutable/GenIterable.scala.disabled +++ /dev/null @@ -1,37 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala.collection -package mutable - - -import generic._ - - -/** A base trait for iterable collections that can be mutated. - * - * $possiblyparinfo - * - * $iterableInfo - */ -trait GenIterable[A] extends GenTraversable[A] - with scala.collection.GenIterable[A] - with scala.collection.GenIterableLike[A, GenIterable[A]] -// with GenericTraversableTemplate[A, GenIterable] -{ - def seq: Iterable[A] - //override def companion: GenericCompanion[GenIterable] = GenIterable -} - - -// object GenIterable extends TraversableFactory[GenIterable] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenIterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenIterable[A]] = Iterable.newBuilder -// } - - diff --git a/src/library/scala/collection/mutable/GenMap.scala.disabled b/src/library/scala/collection/mutable/GenMap.scala.disabled deleted file mode 100644 index e4fd1dad64..0000000000 --- a/src/library/scala/collection/mutable/GenMap.scala.disabled +++ /dev/null @@ -1,40 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A base trait for maps that can be mutated. - * $possiblyparinfo - * $mapNote - * $mapTags - * @since 1.0 - * @author Matthias Zenger - */ -trait GenMap[A, B] -extends GenIterable[(A, B)] - with scala.collection.GenMap[A, B] - with scala.collection.GenMapLike[A, B, GenMap[A, B]] -{ - def seq: Map[A, B] -} - - -// object GenMap extends MapFactory[GenMap] { -// def empty[A, B]: Map[A, B] = Map.empty - -// /** $mapCanBuildFromInfo */ -// implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), GenMap[A, B]] = new MapCanBuildFrom[A, B] -// } - diff --git a/src/library/scala/collection/mutable/GenSeq.scala.disabled b/src/library/scala/collection/mutable/GenSeq.scala.disabled deleted file mode 100644 index ec904723a5..0000000000 --- a/src/library/scala/collection/mutable/GenSeq.scala.disabled +++ /dev/null @@ -1,44 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A subtrait of `collection.GenSeq` which represents sequences - * that can be mutated. - * - * $possiblyparinfo - * - * $seqInfo - * - * The class adds an `update` method to `collection.Seq`. - * - * @define Coll `mutable.Seq` - * @define coll mutable sequence - */ -trait GenSeq[A] extends GenIterable[A] - with scala.collection.GenSeq[A] - with scala.collection.GenSeqLike[A, GenSeq[A]] -// with GenericTraversableTemplate[A, GenSeq] -{ - //override def companion: GenericCompanion[GenSeq] = GenSeq - def seq: Seq[A] -} - - -// object GenSeq extends SeqFactory[GenSeq] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSeq[A]] = Seq.newBuilder -// } - diff --git a/src/library/scala/collection/mutable/GenSet.scala.disabled b/src/library/scala/collection/mutable/GenSet.scala.disabled deleted file mode 100644 index dec20e2a46..0000000000 --- a/src/library/scala/collection/mutable/GenSet.scala.disabled +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - - -import generic._ - - -/** A generic trait for mutable sets. - * - * $possiblyparinfo - * $setNote - * $setTags - * - * @since 1.0 - * @author Matthias Zenger - * @define Coll `mutable.Set` - * @define coll mutable set - */ -trait GenSet[A] extends GenIterable[A] - with Growable[A] - with scala.collection.GenSet[A] - with scala.collection.GenSetLike[A, GenSet[A]] -// with GenericSetTemplate[A, GenSet] -{ - //override def companion: GenericCompanion[GenSet] = GenSet - def seq: Set[A] -} - - -// object GenSet extends TraversableFactory[GenSet] { -// implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, GenSet[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A]: Builder[A, GenSet[A]] = Set.newBuilder -// } - - diff --git a/src/library/scala/collection/mutable/GenTraversable.scala.disabled b/src/library/scala/collection/mutable/GenTraversable.scala.disabled deleted file mode 100644 index 2453e2ce87..0000000000 --- a/src/library/scala/collection/mutable/GenTraversable.scala.disabled +++ /dev/null @@ -1,38 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - - -package scala.collection -package mutable - - -import generic._ - - -/** A trait for traversable collections that can be mutated. - * - * $possiblyparinfo - * - * $traversableInfo - * @define mutability mutable - */ -trait GenTraversable[A] extends scala.collection.GenTraversable[A] - with scala.collection.GenTraversableLike[A, GenTraversable[A]] -// with GenericTraversableTemplate[A, GenTraversable] - with Mutable -{ - def seq: Traversable[A] - //override def companion: GenericCompanion[GenTraversable] = GenTraversable -} - -// object GenTraversable extends TraversableFactory[GenTraversable] { -// implicit def canBuildFrom[A] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] -// def newBuilder[A] = Traversable.newBuilder -// } - diff --git a/src/library/scala/collection/mutable/IndexedSeqLike.scala b/src/library/scala/collection/mutable/IndexedSeqLike.scala index f0c31ec7fb..7b582eb5cb 100644 --- a/src/library/scala/collection/mutable/IndexedSeqLike.scala +++ b/src/library/scala/collection/mutable/IndexedSeqLike.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ /** A subtrait of scala.collection.IndexedSeq which represents sequences * that can be mutated. diff --git a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala index cb7e8efdc7..80b527a7b9 100755 --- a/src/library/scala/collection/mutable/IndexedSeqOptimized.scala +++ b/src/library/scala/collection/mutable/IndexedSeqOptimized.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ /** A subtrait of scala.collection.IndexedSeq which represents sequences * that can be mutated. diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala index cf5166eea8..a88ed8f123 100644 --- a/src/library/scala/collection/mutable/IndexedSeqView.scala +++ b/src/library/scala/collection/mutable/IndexedSeqView.scala @@ -82,8 +82,6 @@ self => protected override def newTakenWhile(p: A => Boolean): Transformed[A] = new { val pred = p } with AbstractTransformed[A] with TakenWhile protected override def newReversed: Transformed[A] = new AbstractTransformed[A] with Reversed - private implicit def asThis(xs: Transformed[A]): This = xs.asInstanceOf[This] - override def filter(p: A => Boolean): This = newFiltered(p) override def init: This = newSliced(SliceInterval(0, self.length - 1)) override def drop(n: Int): This = newSliced(SliceInterval(n, self.length)) diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala index 4f63ede7ca..b3470ed3cd 100644 --- a/src/library/scala/collection/mutable/LinkedListLike.scala +++ b/src/library/scala/collection/mutable/LinkedListLike.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - - package scala.collection package mutable -import generic._ import scala.annotation.tailrec /** This extensible class may be used as a basis for implementing linked diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala index 67af4a6bd6..b7b487964c 100644 --- a/src/library/scala/collection/mutable/ListBuffer.scala +++ b/src/library/scala/collection/mutable/ListBuffer.scala @@ -56,12 +56,18 @@ final class ListBuffer[A] import scala.collection.Traversable import scala.collection.immutable.ListSerializeEnd + /** Expected invariants: + * If start.isEmpty, last0 == null + * If start.nonEmpty, last0 != null + * If len == 0, start.isEmpty + * If len > 0, start.nonEmpty + */ private var start: List[A] = Nil private var last0: ::[A] = _ private var exported: Boolean = false private var len = 0 - protected def underlying: immutable.Seq[A] = start + protected def underlying: List[A] = start private def writeObject(out: ObjectOutputStream) { // write start @@ -160,7 +166,7 @@ final class ListBuffer[A] */ def += (x: A): this.type = { if (exported) copy() - if (start.isEmpty) { + if (isEmpty) { last0 = new :: (x, Nil) start = last0 } else { @@ -182,6 +188,7 @@ final class ListBuffer[A] */ def clear() { start = Nil + last0 = null exported = false len = 0 } @@ -195,7 +202,7 @@ final class ListBuffer[A] def +=: (x: A): this.type = { if (exported) copy() val newElem = new :: (x, start) - if (start.isEmpty) last0 = newElem + if (isEmpty) last0 = newElem start = newElem len += 1 this @@ -238,6 +245,15 @@ final class ListBuffer[A] } } + /** Reduce the length of the buffer, and null out last0 + * if this reduces the length to 0. + */ + private def reduceLengthBy(num: Int) { + len -= num + if (len <= 0) // obviously shouldn't be < 0, but still better not to leak + last0 = null + } + /** Removes a given number of elements on a given index position. May take * time linear in the buffer size. * @@ -253,7 +269,6 @@ final class ListBuffer[A] if (exported) copy() val n1 = n max 0 val count1 = count min (len - n1) - var old = start.head if (n1 == 0) { var c = count1 while (c > 0) { @@ -274,7 +289,7 @@ final class ListBuffer[A] c -= 1 } } - len -= count1 + reduceLengthBy(count1) } // Implementation of abstract method in Builder @@ -285,7 +300,7 @@ final class ListBuffer[A] * copied lazily, the first time it is mutated. */ override def toList: List[A] = { - exported = !start.isEmpty + exported = !isEmpty start } @@ -296,7 +311,7 @@ final class ListBuffer[A] * @param xs the list to which elements are prepended */ def prependToList(xs: List[A]): List[A] = { - if (start.isEmpty) xs + if (isEmpty) xs else { if (exported) copy() last0.tl = xs @@ -331,7 +346,7 @@ final class ListBuffer[A] if (last0 eq cursor.tail) last0 = cursor.asInstanceOf[::[A]] cursor.asInstanceOf[::[A]].tl = cursor.tail.tail } - len -= 1 + reduceLengthBy(1) old } @@ -343,11 +358,12 @@ final class ListBuffer[A] */ override def -= (elem: A): this.type = { if (exported) copy() - if (start.isEmpty) {} + if (isEmpty) {} else if (start.head == elem) { start = start.tail - len -= 1 - } else { + reduceLengthBy(1) + } + else { var cursor = start while (!cursor.tail.isEmpty && cursor.tail.head != elem) { cursor = cursor.tail @@ -357,7 +373,7 @@ final class ListBuffer[A] if (z.tl == last0) last0 = z z.tl = cursor.tail.tail - len -= 1 + reduceLengthBy(1) } } this @@ -397,6 +413,7 @@ final class ListBuffer[A] /** Copy contents of this buffer */ private def copy() { + if (isEmpty) return var cursor = start val limit = last0.tail clear() diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala index a53aa3b76a..49d1e039f0 100644 --- a/src/library/scala/collection/mutable/MapLike.scala +++ b/src/library/scala/collection/mutable/MapLike.scala @@ -11,7 +11,7 @@ package scala.collection package mutable import generic._ -import scala.annotation.{migration, bridge} +import scala.annotation.migration import parallel.mutable.ParMap /** A template trait for mutable maps. @@ -50,8 +50,6 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]] with Parallelizable[(A, B), ParMap[A, B]] { self => - import scala.collection.Traversable - /** A common implementation of `newBuilder` for all mutable maps * in terms of `empty`. * diff --git a/src/library/scala/collection/mutable/SeqLike.scala b/src/library/scala/collection/mutable/SeqLike.scala index 447100cf4c..ddfde536c9 100644 --- a/src/library/scala/collection/mutable/SeqLike.scala +++ b/src/library/scala/collection/mutable/SeqLike.scala @@ -9,7 +9,6 @@ package scala.collection package mutable -import generic._ import parallel.mutable.ParSeq /** A template trait for mutable sequences of type `mutable.Seq[A]`. diff --git a/src/library/scala/collection/mutable/SetBuilder.scala b/src/library/scala/collection/mutable/SetBuilder.scala index 42fd651d41..40f0b8932c 100644 --- a/src/library/scala/collection/mutable/SetBuilder.scala +++ b/src/library/scala/collection/mutable/SetBuilder.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - package scala.collection package mutable -import generic._ - /** The canonical builder for mutable Sets. * * @tparam A The type of the elements that will be contained in this set. diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala index 01f87447ae..4a907e7dc4 100644 --- a/src/library/scala/collection/mutable/SetLike.scala +++ b/src/library/scala/collection/mutable/SetLike.scala @@ -11,7 +11,7 @@ package mutable import generic._ import script._ -import scala.annotation.{ migration, bridge } +import scala.annotation.migration import parallel.mutable.ParSet /** A template trait for mutable sets of type `mutable.Set[A]`. diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala index 8dfc40b9c8..0065d4c556 100644 --- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala @@ -73,14 +73,6 @@ class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQu */ override def head: A = synchronized { super.head } - /** Returns the element with the highest priority in the queue, - * or throws an error if there is no element contained in the queue. - * - * @return the element with the highest priority. - */ - @deprecated("Use `head` instead.", "2.9.0") - override def max: A = synchronized { super.max } - /** Removes all elements from the queue. After this operation is completed, * the queue will be empty. */ diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala index 9559d5eaa5..c5f133eec7 100644 --- a/src/library/scala/collection/mutable/SynchronizedQueue.scala +++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala @@ -25,8 +25,6 @@ package mutable * @define coll synchronized queue */ class SynchronizedQueue[A] extends Queue[A] { - import scala.collection.Traversable - /** Checks if the queue is empty. * * @return true, iff there is no element in the queue. diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala index e4a44993ff..bc9873880c 100644 --- a/src/library/scala/collection/mutable/SynchronizedSet.scala +++ b/src/library/scala/collection/mutable/SynchronizedSet.scala @@ -24,8 +24,6 @@ import script._ * @define coll synchronized set */ trait SynchronizedSet[A] extends Set[A] { - import scala.collection.Traversable - abstract override def size: Int = synchronized { super.size } diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala index 7e0210311c..55328a5d3d 100644 --- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala +++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala @@ -11,7 +11,6 @@ package scala.collection package mutable -import generic._ import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ diff --git a/src/library/scala/collection/parallel/ParIterable.scala b/src/library/scala/collection/parallel/ParIterable.scala index 2b24c88139..f170b944eb 100644 --- a/src/library/scala/collection/parallel/ParIterable.scala +++ b/src/library/scala/collection/parallel/ParIterable.scala @@ -11,7 +11,6 @@ package scala.collection.parallel import scala.collection.GenIterable import scala.collection.generic._ import scala.collection.parallel.mutable.ParArrayCombiner -import scala.collection.parallel.mutable.ParArray /** A template trait for parallel iterable collections. * diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala index 0f06ff37af..d77e5a6744 100644 --- a/src/library/scala/collection/parallel/ParIterableLike.scala +++ b/src/library/scala/collection/parallel/ParIterableLike.scala @@ -171,9 +171,9 @@ self: ParIterableLike[T, Repr, Sequential] => /** The task support object which is responsible for scheduling and * load-balancing tasks to processors. - * + * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport = { val ts = _tasksupport if (ts eq null) { @@ -188,18 +188,18 @@ self: ParIterableLike[T, Repr, Sequential] => * A task support object can be changed in a parallel collection after it * has been created, but only during a quiescent period, i.e. while there * are no concurrent invocations to parallel collection methods. - * - * Here is a way to change the task support of a parallel collection: - * - * {{{ - * import scala.collection.parallel._ - * val pc = mutable.ParArray(1, 2, 3) - * pc.tasksupport = new ForkJoinTaskSupport( - * new scala.concurrent.forkjoin.ForkJoinPool(2)) - * }}} + * + * Here is a way to change the task support of a parallel collection: + * + * {{{ + * import scala.collection.parallel._ + * val pc = mutable.ParArray(1, 2, 3) + * pc.tasksupport = new ForkJoinTaskSupport( + * new scala.concurrent.forkjoin.ForkJoinPool(2)) + * }}} * * @see [[scala.collection.parallel.TaskSupport]] - */ + */ def tasksupport_=(ts: TaskSupport) = _tasksupport = ts def seq: Sequential @@ -433,12 +433,13 @@ self: ParIterableLike[T, Repr, Sequential] => * @tparam S the type of accumulated results * @param z the initial value for the accumulated result of the partition - this * will typically be the neutral element for the `seqop` operator (e.g. - * `Nil` for list concatenation or `0` for summation) + * `Nil` for list concatenation or `0` for summation) and may be evaluated + * more than once * @param seqop an operator used to accumulate results within a partition * @param combop an associative operator used to combine results from different partitions */ - def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = { - tasksupport.executeAndWaitResult(new Aggregate(z, seqop, combop, splitter)) + def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = { + tasksupport.executeAndWaitResult(new Aggregate(() => z, seqop, combop, splitter)) } def foldLeft[S](z: S)(op: (S, T) => S): S = seq.foldLeft(z)(op) @@ -877,13 +878,13 @@ self: ParIterableLike[T, Repr, Sequential] => override def toSet[U >: T]: immutable.ParSet[U] = toParCollection[U, immutable.ParSet[U]](() => immutable.ParSet.newCombiner[U]) override def toMap[K, V](implicit ev: T <:< (K, V)): immutable.ParMap[K, V] = toParMap[K, V, immutable.ParMap[K, V]](() => immutable.ParMap.newCombiner[K, V]) - + override def toVector: Vector[T] = to[Vector] override def to[Col[_]](implicit cbf: CanBuildFrom[Nothing, T, Col[T @uncheckedVariance]]): Col[T @uncheckedVariance] = if (cbf().isCombiner) { toParCollection[T, Col[T]](() => cbf().asCombiner) } else seq.to(cbf) - + /* tasks */ protected trait StrictSplitterCheckTask[R, Tp] extends Task[R, Tp] { @@ -935,8 +936,8 @@ self: ParIterableLike[T, Repr, Sequential] => (f: First, s: Second) extends Composite[FR, SR, R, First, Second](f, s) { def leaf(prevr: Option[R]) = { - tasksupport.executeAndWaitResult(ft) - tasksupport.executeAndWaitResult(st) + tasksupport.executeAndWaitResult(ft) : Any + tasksupport.executeAndWaitResult(st) : Any mergeSubtasks } } @@ -946,8 +947,8 @@ self: ParIterableLike[T, Repr, Sequential] => (f: First, s: Second) extends Composite[FR, SR, R, First, Second](f, s) { def leaf(prevr: Option[R]) = { - val ftfuture = tasksupport.execute(ft) - tasksupport.executeAndWaitResult(st) + val ftfuture: () => Any = tasksupport.execute(ft) + tasksupport.executeAndWaitResult(st) : Any ftfuture() mergeSubtasks } @@ -1005,10 +1006,10 @@ self: ParIterableLike[T, Repr, Sequential] => override def merge(that: Fold[U]) = result = op(result, that.result) } - protected[this] class Aggregate[S](z: S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T]) + protected[this] class Aggregate[S](z: () => S, seqop: (S, T) => S, combop: (S, S) => S, protected[this] val pit: IterableSplitter[T]) extends Accessor[S, Aggregate[S]] { @volatile var result: S = null.asInstanceOf[S] - def leaf(prevr: Option[S]) = result = pit.foldLeft(z)(seqop) + def leaf(prevr: Option[S]) = result = pit.foldLeft(z())(seqop) protected[this] def newSubtask(p: IterableSplitter[T]) = new Aggregate(z, seqop, combop, p) override def merge(that: Aggregate[S]) = result = combop(result, that.result) } @@ -1504,31 +1505,3 @@ self: ParIterableLike[T, Repr, Sequential] => }) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/library/scala/collection/parallel/ParSeq.scala b/src/library/scala/collection/parallel/ParSeq.scala index b905d1d41f..dee523ad89 100644 --- a/src/library/scala/collection/parallel/ParSeq.scala +++ b/src/library/scala/collection/parallel/ParSeq.scala @@ -18,9 +18,6 @@ import scala.collection.generic.ParFactory import scala.collection.generic.CanCombineFrom import scala.collection.GenSeq import scala.collection.parallel.mutable.ParArrayCombiner -import scala.collection.parallel.mutable.ParArray - - /** A template trait for parallel sequences. * diff --git a/src/library/scala/collection/parallel/ParSeqView.scala b/src/library/scala/collection/parallel/ParSeqView.scala index 3e3c497352..9acc4b0b73 100644 --- a/src/library/scala/collection/parallel/ParSeqView.scala +++ b/src/library/scala/collection/parallel/ParSeqView.scala @@ -6,10 +6,9 @@ ** |/ ** \* */ - package scala.collection.parallel -import scala.collection.{ TraversableView, SeqView, Parallel, Iterator } +import scala.collection.{ SeqView, Parallel, Iterator } import scala.collection.generic.CanCombineFrom /** A template view of a non-strict view of a parallel sequence. diff --git a/src/library/scala/collection/parallel/ParSet.scala b/src/library/scala/collection/parallel/ParSet.scala index 6e5e9b4387..bc6d5c6245 100644 --- a/src/library/scala/collection/parallel/ParSet.scala +++ b/src/library/scala/collection/parallel/ParSet.scala @@ -17,14 +17,8 @@ package scala.collection.parallel import scala.collection.Set import scala.collection.GenSet -import scala.collection.mutable.Builder import scala.collection.generic._ - - - - - /** A template trait for parallel sets. * * $sideeffects diff --git a/src/library/scala/collection/parallel/ParSetLike.scala b/src/library/scala/collection/parallel/ParSetLike.scala index c80b5ded26..20a5f693ce 100644 --- a/src/library/scala/collection/parallel/ParSetLike.scala +++ b/src/library/scala/collection/parallel/ParSetLike.scala @@ -15,14 +15,6 @@ import scala.collection.SetLike import scala.collection.GenSetLike import scala.collection.GenSet import scala.collection.Set -import scala.collection.mutable.Builder - - - - - - - /** A template trait for parallel sets. This trait is mixed in with concrete * parallel sets to override the representation type. diff --git a/src/library/scala/collection/parallel/RemainsIterator.scala b/src/library/scala/collection/parallel/RemainsIterator.scala index 3150b0d763..732ebc3709 100644 --- a/src/library/scala/collection/parallel/RemainsIterator.scala +++ b/src/library/scala/collection/parallel/RemainsIterator.scala @@ -123,9 +123,10 @@ private[collection] trait AugmentedIterableIterator[+T] extends RemainsIterator[ def collect2combiner[S, That](pf: PartialFunction[T, S], cb: Combiner[S, That]): Combiner[S, That] = { //val cb = pbf(repr) + val runWith = pf.runWith(cb += _) while (hasNext) { val curr = next - if (pf.isDefinedAt(curr)) cb += pf(curr) + runWith(curr) } cb } diff --git a/src/library/scala/collection/parallel/Tasks.scala b/src/library/scala/collection/parallel/Tasks.scala index cec9e294c1..12f8012a5b 100644 --- a/src/library/scala/collection/parallel/Tasks.scala +++ b/src/library/scala/collection/parallel/Tasks.scala @@ -66,20 +66,10 @@ trait Task[R, +Tp] { private[parallel] def tryMerge(t: Tp @uncheckedVariance) { val that = t.asInstanceOf[Task[R, Tp]] - val local = result // ensure that any effects of modifying `result` are detected - // checkMerge(that) if (this.throwable == null && that.throwable == null) merge(t) mergeThrowables(that) } - private def checkMerge(that: Task[R, Tp] @uncheckedVariance) { - if (this.throwable == null && that.throwable == null && (this.result == null || that.result == null)) { - println("This: " + this + ", thr=" + this.throwable + "; merged with " + that + ", thr=" + that.throwable) - } else if (this.throwable != null || that.throwable != null) { - println("merging this: " + this + " with thr: " + this.throwable + " with " + that + ", thr=" + that.throwable) - } - } - private[parallel] def mergeThrowables(that: Task[_, _]) { if (this.throwable != null && that.throwable != null) { // merge exceptions, since there were multiple exceptions @@ -176,7 +166,6 @@ trait AdaptiveWorkStealingTasks extends Tasks { while (last.next != null) { // val lastresult = Option(last.body.result) - val beforelast = last last = last.next if (last.tryCancel()) { // println("Done with " + beforelast.body + ", next direct is " + last.body) diff --git a/src/library/scala/collection/parallel/immutable/ParIterable.scala b/src/library/scala/collection/parallel/immutable/ParIterable.scala index 142f07ff26..ec07e44c4d 100644 --- a/src/library/scala/collection/parallel/immutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/immutable/ParIterable.scala @@ -15,8 +15,6 @@ import scala.collection.generic._ import scala.collection.parallel.ParIterableLike import scala.collection.parallel.Combiner -import scala.collection.GenIterable - /** A template trait for immutable parallel iterable collections. * diff --git a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled deleted file mode 100644 index 5f9c9c3d3d..0000000000 --- a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled +++ /dev/null @@ -1,128 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.collection.parallel.immutable - - - -import scala.collection.immutable.NumericRange -import scala.collection.parallel.Combiner -import scala.collection.generic.CanCombineFrom -import scala.collection.parallel.ParIterableIterator - - - -/** Parallel ranges for numeric types. - * - * $paralleliterableinfo - * - * $sideeffects - * - * @param range the sequential range this parallel range was obtained from - * - * @author Aleksandar Prokopec - * @since 2.9 - * - * @define Coll `immutable.ParRange` - * @define coll immutable parallel range - */ -@SerialVersionUID(1L) -class ParNumericRange[T](val range: NumericRange[T])(implicit num: Integral[T]) -extends ParSeq[T] - with Serializable -{ -self => - - def seq = range - - @inline final def length = range.length - - @inline final def apply(idx: Int) = range.apply(idx); - - def parallelIterator = new ParNumericRangeIterator with SCPI - - type SCPI = SignalContextPassingIterator[ParNumericRangeIterator] - - class ParNumericRangeIterator(range: NumericRange[T] = self.range, num: Integral[T] = self.num) - extends ParIterator { - me: SignalContextPassingIterator[ParNumericRangeIterator] => - override def toString = "ParNumericRangeIterator(over: " + range + ")" - private var ind = 0 - private val len = range.length - - final def remaining = len - ind - - final def hasNext = ind < len - - final def next = if (hasNext) { - val r = range.apply(ind) - ind += 1 - r - } else Iterator.empty.next - - private def rangeleft: NumericRange[T] = range.drop(ind) - - def dup = new ParNumericRangeIterator(rangeleft) with SCPI - - def split = { - val rleft = rangeleft - val elemleft = rleft.length - if (elemleft < 2) Seq(new ParNumericRangeIterator(rleft) with SCPI) - else Seq( - new ParNumericRangeIterator(rleft.take(elemleft / 2)) with SCPI, - new ParNumericRangeIterator(rleft.drop(elemleft / 2)) with SCPI - ) - } - - def psplit(sizes: Int*) = { - var rleft = rangeleft - for (sz <- sizes) yield { - val fronttaken = rleft.take(sz) - rleft = rleft.drop(sz) - new ParNumericRangeIterator(fronttaken) with SCPI - } - } - - /* accessors */ - - override def foreach[U](f: T => U): Unit = { - rangeleft.foreach(f) - ind = len - } - - override def reduce[U >: T](op: (U, U) => U): U = { - val r = rangeleft.reduceLeft(op) - ind = len - r - } - - /* transformers */ - - override def map2combiner[S, That](f: T => S, cb: Combiner[S, That]): Combiner[S, That] = { - while (hasNext) { - cb += f(next) - } - cb - } - } - -} - - -object ParNumericRange { - def apply[T](start: T, end: T, step: T, inclusive: Boolean)(implicit num: Integral[T]) = new ParNumericRange[T]( - if (inclusive) NumericRange.inclusive(start, end, step)(num) - else NumericRange.apply(start, end, step)(num) - ) -} - - - - - diff --git a/src/library/scala/collection/parallel/immutable/ParSeq.scala b/src/library/scala/collection/parallel/immutable/ParSeq.scala index aa19307387..b54a5f0205 100644 --- a/src/library/scala/collection/parallel/immutable/ParSeq.scala +++ b/src/library/scala/collection/parallel/immutable/ParSeq.scala @@ -18,9 +18,6 @@ import scala.collection.generic.CanCombineFrom import scala.collection.generic.ParFactory import scala.collection.parallel.ParSeqLike import scala.collection.parallel.Combiner -import scala.collection.GenSeq - - /** An immutable variant of `ParSeq`. * diff --git a/src/library/scala/collection/parallel/immutable/ParSet.scala b/src/library/scala/collection/parallel/immutable/ParSet.scala index 3622377a55..aba8486ab5 100644 --- a/src/library/scala/collection/parallel/immutable/ParSet.scala +++ b/src/library/scala/collection/parallel/immutable/ParSet.scala @@ -9,7 +9,6 @@ package scala.collection package parallel.immutable -import scala.collection.GenSet import scala.collection.generic._ import scala.collection.parallel.ParSetLike import scala.collection.parallel.Combiner diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala index e4c8e5fae2..db4a59f6ba 100644 --- a/src/library/scala/collection/parallel/mutable/ParArray.scala +++ b/src/library/scala/collection/parallel/mutable/ParArray.scala @@ -181,10 +181,10 @@ self => override def fold[U >: T](z: U)(op: (U, U) => U): U = foldLeft[U](z)(op) - override def aggregate[S](z: S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop) + override def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = foldLeft[S](z)(seqop) override def sum[U >: T](implicit num: Numeric[U]): U = { - var s = sum_quick(num, arr, until, i, num.zero) + val s = sum_quick(num, arr, until, i, num.zero) i = until s } @@ -200,7 +200,7 @@ self => } override def product[U >: T](implicit num: Numeric[U]): U = { - var p = product_quick(num, arr, until, i, num.one) + val p = product_quick(num, arr, until, i, num.one) i = until p } @@ -405,9 +405,10 @@ self => private def collect2combiner_quick[S, That](pf: PartialFunction[T, S], a: Array[Any], cb: Builder[S, That], ntil: Int, from: Int) { var j = from + val runWith = pf.runWith(b => cb += b) while (j < ntil) { val curr = a(j).asInstanceOf[T] - if (pf.isDefinedAt(curr)) cb += pf(curr) + runWith(curr) j += 1 } } @@ -432,7 +433,7 @@ self => private def filter2combiner_quick[U >: T, This](pred: T => Boolean, cb: Builder[U, This], a: Array[Any], ntil: Int, from: Int) { var j = i while(j < ntil) { - var curr = a(j).asInstanceOf[T] + val curr = a(j).asInstanceOf[T] if (pred(curr)) cb += curr j += 1 } @@ -447,7 +448,7 @@ self => private def filterNot2combiner_quick[U >: T, This](pred: T => Boolean, cb: Builder[U, This], a: Array[Any], ntil: Int, from: Int) { var j = i while(j < ntil) { - var curr = a(j).asInstanceOf[T] + val curr = a(j).asInstanceOf[T] if (!pred(curr)) cb += curr j += 1 } @@ -579,8 +580,6 @@ self => /* operations */ - private def asTask[R, Tp](t: Any) = t.asInstanceOf[Task[R, Tp]] - private def buildsArray[S, That](c: Builder[S, That]) = c.isInstanceOf[ParArrayCombiner[_]] override def map[S, That](f: T => S)(implicit bf: CanBuildFrom[ParArray[T], S, That]) = if (buildsArray(bf(repr))) { diff --git a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala index 8bc108a738..b151e45d65 100644 --- a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala +++ b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala @@ -38,10 +38,6 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] { } } - private def checkbounds() = if (idx >= itertable.length) { - throw new IndexOutOfBoundsException(idx.toString) - } - def newIterator(index: Int, until: Int, totalsize: Int): IterableSplitter[T] def remaining = totalsize - traversed @@ -102,11 +98,5 @@ trait ParFlatHashTable[T] extends scala.collection.mutable.FlatHashTable[T] { } count } - - private def check() = if (table.slice(idx, until).count(_ != null) != remaining) { - println("Invariant broken: " + debugInformation) - assert(false) - } } - } diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala index 11588e555b..541d75290b 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -166,9 +166,8 @@ private[mutable] abstract class ParHashMapCombiner[K, V](private val tableLoadFa extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], DefaultEntry[K, V], ParHashMapCombiner[K, V]](ParHashMapCombiner.numblocks) with scala.collection.mutable.HashTable.HashUtils[K] { - private var mask = ParHashMapCombiner.discriminantmask - private var nonmasklen = ParHashMapCombiner.nonmasklength - private var seedvalue = 27 + private val nonmasklen = ParHashMapCombiner.nonmasklength + private val seedvalue = 27 def +=(elem: (K, V)) = { sz += 1 @@ -232,8 +231,7 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau def setSize(sz: Int) = tableSize = sz def insertEntry(/*block: Int, */e: DefaultEntry[K, V]) = { var h = index(elemHashCode(e.key)) - // assertCorrectBlock(h, block) - var olde = table(h).asInstanceOf[DefaultEntry[K, V]] + val olde = table(h).asInstanceOf[DefaultEntry[K, V]] // check if key already exists var ce = olde @@ -252,13 +250,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau true } else false } - private def assertCorrectBlock(h: Int, block: Int) { - val blocksize = table.length / (1 << ParHashMapCombiner.discriminantbits) - if (!(h >= block * blocksize && h < (block + 1) * blocksize)) { - println("trying to put " + h + " into block no.: " + block + ", range: [" + block * blocksize + ", " + (block + 1) * blocksize + ">") - assert(h >= block * blocksize && h < (block + 1) * blocksize) - } - } protected def createNewEntry[X](key: K, x: X) = ??? } @@ -288,7 +279,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau val chunksz = unrolled.size while (i < chunksz) { val elem = chunkarr(i) - // assertCorrectBlock(block, elem.key) if (t.insertEntry(elem)) insertcount += 1 i += 1 } @@ -297,13 +287,6 @@ extends scala.collection.parallel.BucketCombiner[(K, V), ParHashMap[K, V], Defau } insertcount } - private def assertCorrectBlock(block: Int, k: K) { - val hc = improve(elemHashCode(k), seedvalue) - if ((hc >>> nonmasklen) != block) { - println(hc + " goes to " + (hc >>> nonmasklen) + ", while expected block is " + block) - assert((hc >>> nonmasklen) == block) - } - } def split = { val fp = howmany / 2 List(new FillBlocks(buckets, table, offset, fp), new FillBlocks(buckets, table, offset + fp, howmany - fp)) diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala index 3b1278f3be..f1377fb0a7 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala @@ -120,9 +120,8 @@ private[mutable] abstract class ParHashSetCombiner[T](private val tableLoadFacto extends scala.collection.parallel.BucketCombiner[T, ParHashSet[T], Any, ParHashSetCombiner[T]](ParHashSetCombiner.numblocks) with scala.collection.mutable.FlatHashTable.HashUtils[T] { //self: EnvironmentPassingCombiner[T, ParHashSet[T]] => - private var mask = ParHashSetCombiner.discriminantmask - private var nonmasklen = ParHashSetCombiner.nonmasklength - private var seedvalue = 27 + private val nonmasklen = ParHashSetCombiner.nonmasklength + private val seedvalue = 27 def +=(elem: T) = { sz += 1 @@ -264,12 +263,12 @@ with scala.collection.mutable.FlatHashTable.HashUtils[T] { (elemsIn + leftoversIn, elemsLeft concat leftoversLeft) } private def insertAll(atPos: Int, beforePos: Int, elems: UnrolledBuffer[Any]): (Int, UnrolledBuffer[Any]) = { - var leftovers = new UnrolledBuffer[Any] + val leftovers = new UnrolledBuffer[Any] var inserted = 0 var unrolled = elems.headPtr var i = 0 - var t = table + val t = table while (unrolled ne null) { val chunkarr = unrolled.array val chunksz = unrolled.size diff --git a/src/library/scala/collection/parallel/mutable/ParHashTable.scala b/src/library/scala/collection/parallel/mutable/ParHashTable.scala index 66ddef6a1e..5aa1dba17c 100644 --- a/src/library/scala/collection/parallel/mutable/ParHashTable.scala +++ b/src/library/scala/collection/parallel/mutable/ParHashTable.scala @@ -110,7 +110,7 @@ trait ParHashTable[K, Entry >: Null <: HashEntry[K, Entry]] extends scala.collec } else Seq(this.asInstanceOf[IterRepr]) private def convertToArrayBuffer(chainhead: Entry): mutable.ArrayBuffer[T] = { - var buff = mutable.ArrayBuffer[Entry]() + val buff = mutable.ArrayBuffer[Entry]() var curr = chainhead while (curr ne null) { buff += curr diff --git a/src/library/scala/collection/parallel/mutable/ParIterable.scala b/src/library/scala/collection/parallel/mutable/ParIterable.scala index 7090c510a0..d76e4b1745 100644 --- a/src/library/scala/collection/parallel/mutable/ParIterable.scala +++ b/src/library/scala/collection/parallel/mutable/ParIterable.scala @@ -12,8 +12,6 @@ package scala.collection.parallel.mutable import scala.collection.generic._ import scala.collection.parallel.ParIterableLike import scala.collection.parallel.Combiner -import scala.collection.GenIterable - /** A template trait for mutable parallel iterable collections. * diff --git a/src/library/scala/collection/parallel/mutable/ParMapLike.scala b/src/library/scala/collection/parallel/mutable/ParMapLike.scala index cdcfc59f8f..08bc706c8a 100644 --- a/src/library/scala/collection/parallel/mutable/ParMapLike.scala +++ b/src/library/scala/collection/parallel/mutable/ParMapLike.scala @@ -12,13 +12,10 @@ package mutable import scala.collection.generic._ -import scala.collection.mutable.Builder import scala.collection.mutable.Cloneable import scala.collection.generic.Growable import scala.collection.generic.Shrinkable - - /** A template trait for mutable parallel maps. This trait is to be mixed in * with concrete parallel maps to override the representation type. * diff --git a/src/library/scala/collection/parallel/mutable/ParSeq.scala b/src/library/scala/collection/parallel/mutable/ParSeq.scala index 95a4d4a13a..8a55ab83f1 100644 --- a/src/library/scala/collection/parallel/mutable/ParSeq.scala +++ b/src/library/scala/collection/parallel/mutable/ParSeq.scala @@ -17,12 +17,6 @@ import scala.collection.generic.CanCombineFrom import scala.collection.generic.ParFactory import scala.collection.parallel.ParSeqLike import scala.collection.parallel.Combiner -import scala.collection.GenSeq - - - - - /** A mutable variant of `ParSeq`. * diff --git a/src/library/scala/collection/parallel/mutable/ParSet.scala b/src/library/scala/collection/parallel/mutable/ParSet.scala index d8f821746c..ca41852512 100644 --- a/src/library/scala/collection/parallel/mutable/ParSet.scala +++ b/src/library/scala/collection/parallel/mutable/ParSet.scala @@ -13,11 +13,6 @@ package scala.collection.parallel.mutable import scala.collection.generic._ import scala.collection.parallel.Combiner -import scala.collection.GenSet - - - - /** A mutable variant of `ParSet`. * diff --git a/src/library/scala/collection/parallel/mutable/ParSetLike.scala b/src/library/scala/collection/parallel/mutable/ParSetLike.scala index 609888f1a9..0941229124 100644 --- a/src/library/scala/collection/parallel/mutable/ParSetLike.scala +++ b/src/library/scala/collection/parallel/mutable/ParSetLike.scala @@ -10,17 +10,11 @@ package scala.collection package parallel.mutable - - -import scala.collection.mutable.Set -import scala.collection.mutable.Builder import scala.collection.mutable.Cloneable import scala.collection.GenSetLike import scala.collection.generic.Growable import scala.collection.generic.Shrinkable - - /** A template trait for mutable parallel sets. This trait is mixed in with concrete * parallel sets to override the representation type. * diff --git a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala index dc31d1bc25..0b9b51bc5b 100644 --- a/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala +++ b/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala @@ -26,7 +26,7 @@ trait ResizableParArrayCombiner[T] extends LazyCombiner[T, ParArray[T], ExposedA override def sizeHint(sz: Int) = if (chain.length == 1) chain(0).sizeHint(sz) // public method with private[mutable] type ExposedArrayBuffer in parameter type; cannot be overridden. - def newLazyCombiner(c: ArrayBuffer[ExposedArrayBuffer[T]]) = ResizableParArrayCombiner(c) + final def newLazyCombiner(c: ArrayBuffer[ExposedArrayBuffer[T]]) = ResizableParArrayCombiner(c) def allocateAndCopy = if (chain.size > 1) { val arrayseq = new ArraySeq[T](size) diff --git a/src/library/scala/collection/script/Message.scala b/src/library/scala/collection/script/Message.scala index 2ab7ea726a..7428cd2b81 100644 --- a/src/library/scala/collection/script/Message.scala +++ b/src/library/scala/collection/script/Message.scala @@ -69,7 +69,7 @@ class Script[A] extends ArrayBuffer[Message[A]] with Message[A] { override def toString(): String = { var res = "Script(" - var it = this.iterator + val it = this.iterator var i = 1 while (it.hasNext) { if (i > 1) diff --git a/src/library/scala/concurrent/FutureTaskRunner.scala b/src/library/scala/concurrent/FutureTaskRunner.scala index eeadaddb5e..cb4f8687f3 100644 --- a/src/library/scala/concurrent/FutureTaskRunner.scala +++ b/src/library/scala/concurrent/FutureTaskRunner.scala @@ -10,7 +10,7 @@ package scala.concurrent import scala.language.{implicitConversions, higherKinds} -/** The `FutureTaskRunner</code> trait is a base trait of task runners +/** The `FutureTaskRunner` trait is a base trait of task runners * that provide some sort of future abstraction. * * @author Philipp Haller diff --git a/src/library/scala/concurrent/JavaConversions.scala b/src/library/scala/concurrent/JavaConversions.scala index d6a7c1f1bb..573882ee34 100644 --- a/src/library/scala/concurrent/JavaConversions.scala +++ b/src/library/scala/concurrent/JavaConversions.scala @@ -41,10 +41,6 @@ object JavaConversions { exec.execute(task) } - def managedBlock(blocker: ManagedBlocker) { - blocker.block() - } - def shutdown() { // do nothing } diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala index 8c2a77c75f..055ce6e4fa 100644 --- a/src/library/scala/concurrent/impl/Future.scala +++ b/src/library/scala/concurrent/impl/Future.scala @@ -12,7 +12,7 @@ package scala.concurrent.impl import scala.concurrent.ExecutionContext import scala.util.control.NonFatal -import scala.util.{Try, Success, Failure} +import scala.util.{ Success, Failure } private[concurrent] object Future { diff --git a/src/library/scala/io/Position.scala b/src/library/scala/io/Position.scala index daa4e103be..b96349803d 100644 --- a/src/library/scala/io/Position.scala +++ b/src/library/scala/io/Position.scala @@ -68,14 +68,6 @@ abstract class Position { } object Position extends Position { - /** The undefined position */ - @deprecated("This will be removed", "2.9.0") - final val NOPOS = 0 - - /** The first position in a source file */ - @deprecated("This will be removed", "2.9.0") - final val FIRSTPOS = encode(1, 1) - def checkInput(line: Int, column: Int) { if (line < 0) throw new IllegalArgumentException(line + " < 0") diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 7c14ed3a9e..f3aabc2974 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -25,12 +25,6 @@ object BigDecimal { private val maxCached = 512 val defaultMathContext = MathContext.DECIMAL128 - @deprecated("Use Long.MinValue", "2.9.0") - val MinLong = new BigDecimal(BigDec valueOf Long.MinValue, defaultMathContext) - - @deprecated("Use Long.MaxValue", "2.9.0") - val MaxLong = new BigDecimal(BigDec valueOf Long.MaxValue, defaultMathContext) - /** Cache ony for defaultMathContext using BigDecimals in a small range. */ private lazy val cache = new Array[BigDecimal](maxCached - minCached + 1) diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala index 441bf5aa4d..0cddd71721 100644 --- a/src/library/scala/math/BigInt.scala +++ b/src/library/scala/math/BigInt.scala @@ -23,12 +23,6 @@ object BigInt { private val cache = new Array[BigInt](maxCached - minCached + 1) private val minusOne = BigInteger.valueOf(-1) - @deprecated("Use Long.MinValue", "2.9.0") - val MinLong = BigInt(Long.MinValue) - - @deprecated("Use Long.MaxValue", "2.9.0") - val MaxLong = BigInt(Long.MaxValue) - /** Constructs a `BigInt` whose value is equal to that of the * specified integer value. * diff --git a/src/library/scala/math/ScalaNumericConversions.scala b/src/library/scala/math/ScalaNumericConversions.scala index 6ddf48d03b..59fc7f27b2 100644 --- a/src/library/scala/math/ScalaNumericConversions.scala +++ b/src/library/scala/math/ScalaNumericConversions.scala @@ -8,8 +8,6 @@ package scala.math -import java.{ lang => jl } - /** A slightly more specific conversion trait for classes which * extend ScalaNumber (which excludes value classes.) */ diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index d3f8df9110..15d6dce8a7 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -34,9 +34,6 @@ package object scala { override def toString = "object AnyRef" } - @deprecated("instead of `@serializable class C`, use `class C extends Serializable`", "2.9.0") - type serializable = annotation.serializable - @deprecated("instead of `@cloneable class C`, use `class C extends Cloneable`", "2.10.0") type cloneable = annotation.cloneable @@ -129,9 +126,8 @@ package object scala { type deprecatedName = annotation.deprecatedName type inline = annotation.inline type native = annotation.native - type noinline = noannotation.inline + type noinline = annotation.noinline type remote = annotation.remote - type serializable = annotation.serializable type specialized = annotation.specialized type transient = annotation.transient type throws = annotation.throws diff --git a/src/library/scala/parallel/package.scala.disabled b/src/library/scala/parallel/package.scala.disabled deleted file mode 100644 index 45f5470d03..0000000000 --- a/src/library/scala/parallel/package.scala.disabled +++ /dev/null @@ -1,178 +0,0 @@ -package scala - - - -import scala.concurrent.forkjoin._ - - -/** This package object contains various parallel operations. - * - * @define invokingPar - * Invoking a parallel computation creates a future which will - * hold the result of the computation once it completes. Querying - * the result of a future before its parallel computation has completed - * will block the caller. For all practical concerns, the dependency - * chain obtained by querying results of unfinished futures can have - * arbitrary lengths. However, care must be taken not to create a - * circular dependency, as this will result in a deadlock. - * - * Additionally, if the parallel computation performs a blocking call - * (e.g. an I/O operation or waiting for a lock) other than waiting for a future, - * it should do so by invoking the `block` method. This is another - * form of waiting that could potentially create a circular dependency, - * an the user should take care not to do this. - * - * Users should be aware that invoking a parallel computation has a - * certain overhead. Parallel computations should not be invoked for - * small computations, as this can lead to bad performance. A rule of the - * thumb is having parallel computations equivalent to a loop - * with 50000 arithmetic operations (at least). If a parallel computation - * is invoked within another parallel computation, then it should be - * computationally equivalent to a loop with 10000 arithmetic operations. - */ -package object parallel { - - private[scala] val forkjoinpool = new ForkJoinPool() - - private class Task[T](body: =>T) extends RecursiveTask[T] with Future[T] { - def compute = body - def apply() = join() - } - - private final def newTask[T](body: =>T) = new Task[T](body) - - private final def executeTask[T](task: RecursiveTask[T]) { - if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) task.fork - else forkjoinpool.execute(task) - } - - /* public methods */ - - /** Performs a call which can potentially block execution. - * - * Example: - * {{{ - * val lock = new ReentrantLock - * - * // ... do something ... - * - * blocking { - * if (!lock.hasLock) lock.lock() - * } - * }}} - * - * '''Note:''' calling methods that wait arbitrary amounts of time - * (e.g. for I/O operations or locks) may severely decrease performance - * or even result in deadlocks. This does not include waiting for - * results of futures. - */ - def blocking[T](body: =>T): T = { - if (Thread.currentThread().isInstanceOf[ForkJoinWorkerThread]) { - val blocker = new ForkJoinPool.ManagedBlocker { - @volatile var done = false - @volatile var result: Any = _ - def block() = { - result = body - done = true - true - } - def isReleasable() = done - } - ForkJoinPool.managedBlock(blocker, true) - blocker.result.asInstanceOf[T] - } else body - } - - /** Starts a parallel computation and returns a future. - * - * $invokingPar - * - * @tparam T the type of the result of the parallel computation - * @param body the computation to be invoked in parallel - * @return a future with the result - */ - def par[T](body: =>T): Future[T] = { - val task = newTask(body) - executeTask(task) - task - } - - /** Starts 2 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2](b1: =>T1, b2: =>T2): (Future[T1], Future[T2]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - (t1, t2) - } - - /** Starts 3 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @tparam T3 the type of the result of 3rd the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @param b3 the 3rd computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2, T3](b1: =>T1, b2: =>T2, b3: =>T3): (Future[T1], Future[T2], Future[T3]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - val t3 = newTask(b3) - executeTask(t3) - (t1, t2, t3) - } - - /** Starts 4 parallel computations and returns a future. - * - * $invokingPar - * - * @tparam T1 the type of the result of 1st the parallel computation - * @tparam T2 the type of the result of 2nd the parallel computation - * @tparam T3 the type of the result of 3rd the parallel computation - * @tparam T4 the type of the result of 4th the parallel computation - * @param b1 the 1st computation to be invoked in parallel - * @param b2 the 2nd computation to be invoked in parallel - * @param b3 the 3rd computation to be invoked in parallel - * @param b4 the 4th computation to be invoked in parallel - * @return a tuple of futures corresponding to parallel computations - */ - def par[T1, T2, T3, T4](b1: =>T1, b2: =>T2, b3: =>T3, b4: =>T4): (Future[T1], Future[T2], Future[T3], Future[T4]) = { - val t1 = newTask(b1) - executeTask(t1) - val t2 = newTask(b2) - executeTask(t2) - val t3 = newTask(b3) - executeTask(t3) - val t4 = newTask(b4) - executeTask(t4) - (t1, t2, t3, t4) - } - -} - - - - - - - - - - - - diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 1d8fe5e9ad..1a79e6da73 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -26,8 +26,7 @@ import java.lang.reflect.{ Modifier, Method => JMethod } * outside the API and subject to change or removal without notice. */ object ScalaRunTime { - def isArray(x: AnyRef): Boolean = isArray(x, 1) - def isArray(x: Any, atLevel: Int): Boolean = + def isArray(x: Any, atLevel: Int = 1): Boolean = x != null && isArrayClass(x.getClass, atLevel) private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean = diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala index da9adb3dc2..294be5cd71 100644 --- a/src/library/scala/sys/SystemProperties.scala +++ b/src/library/scala/sys/SystemProperties.scala @@ -64,7 +64,6 @@ object SystemProperties { propertyHelp(p.key) = helpText p } - private def str(key: String, helpText: String) = addHelp(Prop[String](key), helpText) private def bool(key: String, helpText: String): BooleanProp = addHelp[BooleanProp]( if (key startsWith "java.") BooleanProp.valueIsTrue(key) else BooleanProp.keyExists(key), helpText diff --git a/src/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala index 12448f595d..2f4625da44 100644 --- a/src/library/scala/util/automata/WordBerrySethi.scala +++ b/src/library/scala/util/automata/WordBerrySethi.scala @@ -21,7 +21,7 @@ import scala.util.regexp.WordExp abstract class WordBerrySethi extends BaseBerrySethi { override val lang: WordExp - import lang.{ Alt, Eps, Letter, Meta, RegExp, Sequ, Star, _labelT } + import lang.{ Alt, Eps, Letter, RegExp, Sequ, Star, _labelT } protected var labels: mutable.HashSet[_labelT] = _ // don't let this fool you, only labelAt is a real, surjective mapping @@ -140,7 +140,6 @@ abstract class WordBerrySethi extends BaseBerrySethi { val delta1 = immutable.Map(deltaq.zipWithIndex map (_.swap): _*) val finalsArr = (0 until pos map (k => finals.getOrElse(k, 0))).toArray // 0 == not final - val initialsArr = initials.toArray val deltaArr: Array[mutable.Map[_labelT, immutable.BitSet]] = (0 until pos map { x => @@ -152,7 +151,6 @@ abstract class WordBerrySethi extends BaseBerrySethi { new NondetWordAutom[_labelT] { val nstates = pos val labels = WordBerrySethi.this.labels.toList - val initials = initialsArr val finals = finalsArr val delta = deltaArr val default = defaultArr diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index 716d746552..830710432c 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -131,7 +131,7 @@ import java.util.regex.{ Pattern, Matcher } * @author Martin Odersky * @version 1.1, 29/01/2008 * - * @param regex A string representing a regular expression + * @param pattern The compiled pattern * @param groupNames A mapping from names to indices in capture groups * * @define replacementString @@ -144,41 +144,67 @@ import java.util.regex.{ Pattern, Matcher } * to automatically escape these characters. */ @SerialVersionUID(-2094783597747625537L) -class Regex(regex: String, groupNames: String*) extends Serializable { +class Regex private[matching](val pattern: Pattern, groupNames: String*) extends Serializable { outer => import Regex._ - /** The compiled pattern */ - val pattern = Pattern.compile(regex) + /** + * @param regex A string representing a regular expression + * @param groupNames A mapping from names to indices in capture groups + */ + def this(regex: String, groupNames: String*) = this(Pattern.compile(regex), groupNames: _*) - /** Tries to match target (whole match) and returns the matching subgroups. - * if the pattern has no subgroups, then it returns an empty list on a - * successful match. - * - * Note, however, that if some subgroup has not been matched, a `null` will - * be returned for that subgroup. + /** Tries to match a [[java.lang.CharSequence]]. + * If the match succeeds, the result is a list of the matching + * groups (or a `null` element if a group did not match any input). + * If the pattern specifies no groups, then the result will be an empty list + * on a successful match. * + * This method attempts to match the entire input by default; to find the next + * matching subsequence, use an unanchored Regex. + * For example: * * {{{ * val p1 = "ab*c".r - * val p2 = "a(b*)c".r - * * val p1Matches = "abbbc" match { * case p1() => true * case _ => false * } - * + * val p2 = "a(b*)c".r * val numberOfB = "abbbc" match { * case p2(b) => Some(b.length) * case _ => None * } + * val p3 = "b*".r.unanchored + * val p3Matches = "abbbc" match { + * case p3() => true + * case _ => false + * } * }}} * - * @param target The string to match + * @param s The string to match * @return The matches */ + def unapplySeq(s: CharSequence): Option[Seq[String]] = { + val m = pattern matcher s + if (runMatcher(m)) Some(1 to m.groupCount map m.group) + else None + } + + /** Tries to match on a [[scala.util.matching.Regex.Match]]. + * A previously failed match results in None. + * If a successful match was made against the current pattern, then that result is used. + * Otherwise, this Regex is applied to the previously matched input, + * and the result of that match is used. + */ + def unapplySeq(m: Match): Option[Seq[String]] = + if (m.matched == null) None + else if (m.matcher.pattern == this.pattern) Some(1 to m.groupCount map m.group) + else unapplySeq(m.matched) + + @deprecated("Extracting a match result from anything but a CharSequence or Match is deprecated", "2.10.0") def unapplySeq(target: Any): Option[List[String]] = target match { case s: CharSequence => val m = pattern matcher s @@ -187,6 +213,8 @@ class Regex(regex: String, groupNames: String*) extends Serializable { case m: Match => unapplySeq(m.matched) case _ => None } + + // @see UnanchoredRegex protected def runMatcher(m: Matcher) = m.matches() /** Return all matches of this regexp in given character sequence as a [[scala.util.matching.Regex.MatchIterator]], @@ -200,7 +228,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.util.matching.Regex.MatchIterator]] of all matches. * @example {{{for (words <- """\w+""".r findAllIn "A simple example.") yield words}}} */ - def findAllIn(source: java.lang.CharSequence) = new Regex.MatchIterator(source, this, groupNames) + def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames) /** Return all matches of this regexp in given character sequence as a @@ -210,7 +238,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]] for all matches. * @example {{{for (words <- """\w+""".r findAllMatchIn "A simple example.") yield words.start}}} */ - def findAllMatchIn(source: java.lang.CharSequence): Iterator[Match] = { + def findAllMatchIn(source: CharSequence): Iterator[Match] = { val matchIterator = findAllIn(source) new Iterator[Match] { def hasNext = matchIterator.hasNext @@ -228,7 +256,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return An [[scala.Option]] of the first matching string in the text. * @example {{{"""\w+""".r findFirstIn "A simple example." foreach println // prints "A"}}} */ - def findFirstIn(source: java.lang.CharSequence): Option[String] = { + def findFirstIn(source: CharSequence): Option[String] = { val m = pattern.matcher(source) if (m.find) Some(m.group) else None } @@ -245,7 +273,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of [[scala.util.matching.Regex.Match]] of the first matching string in the text. * @example {{{("""[a-z]""".r findFirstMatchIn "A simple example.") map (_.start) // returns Some(2), the index of the first match in the text}}} */ - def findFirstMatchIn(source: java.lang.CharSequence): Option[Match] = { + def findFirstMatchIn(source: CharSequence): Option[Match] = { val m = pattern.matcher(source) if (m.find) Some(new Match(source, m, groupNames)) else None } @@ -262,7 +290,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of the matched prefix. * @example {{{"""[a-z]""".r findPrefixOf "A simple example." // returns None, since the text does not begin with a lowercase letter}}} */ - def findPrefixOf(source: java.lang.CharSequence): Option[String] = { + def findPrefixOf(source: CharSequence): Option[String] = { val m = pattern.matcher(source) if (m.lookingAt) Some(m.group) else None } @@ -279,7 +307,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return A [[scala.Option]] of the [[scala.util.matching.Regex.Match]] of the matched string. * @example {{{"""\w+""".r findPrefixMatchOf "A simple example." map (_.after) // returns Some(" simple example.")}}} */ - def findPrefixMatchOf(source: java.lang.CharSequence): Option[Match] = { + def findPrefixMatchOf(source: CharSequence): Option[Match] = { val m = pattern.matcher(source) if (m.lookingAt) Some(new Match(source, m, groupNames)) else None } @@ -293,7 +321,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return The resulting string * @example {{{"""\d+""".r replaceAllIn ("July 15", "<NUMBER>") // returns "July <NUMBER>"}}} */ - def replaceAllIn(target: java.lang.CharSequence, replacement: String): String = { + def replaceAllIn(target: CharSequence, replacement: String): String = { val m = pattern.matcher(target) m.replaceAll(replacement) } @@ -316,7 +344,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacer The function which maps a match to another string. * @return The target string after replacements. */ - def replaceAllIn(target: java.lang.CharSequence, replacer: Match => String): String = { + def replaceAllIn(target: CharSequence, replacer: Match => String): String = { val it = new Regex.MatchIterator(target, this, groupNames).replacementData it foreach (md => it replace replacer(md)) it.replaced @@ -343,7 +371,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacer The function which optionally maps a match to another string. * @return The target string after replacements. */ - def replaceSomeIn(target: java.lang.CharSequence, replacer: Match => Option[String]): String = { + def replaceSomeIn(target: CharSequence, replacer: Match => Option[String]): String = { val it = new Regex.MatchIterator(target, this, groupNames).replacementData for (matchdata <- it ; replacement <- replacer(matchdata)) it replace replacement @@ -359,7 +387,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @param replacement The string that will replace the match * @return The resulting string */ - def replaceFirstIn(target: java.lang.CharSequence, replacement: String): String = { + def replaceFirstIn(target: CharSequence, replacement: String): String = { val m = pattern.matcher(target) m.replaceFirst(replacement) } @@ -370,7 +398,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * @return The array of strings computed by splitting the * input around matches of this regexp */ - def split(toSplit: java.lang.CharSequence): Array[String] = + def split(toSplit: CharSequence): Array[String] = pattern.split(toSplit) /** Create a new Regex with the same pattern, but no requirement that @@ -390,9 +418,11 @@ class Regex(regex: String, groupNames: String*) extends Serializable { * * @return The new unanchored regex */ - def unanchored: UnanchoredRegex = new Regex(regex, groupNames: _*) with UnanchoredRegex { override def anchored = outer } + def unanchored: UnanchoredRegex = new Regex(pattern, groupNames: _*) with UnanchoredRegex { override def anchored = outer } def anchored: Regex = this + def regex: String = pattern.pattern + /** The string defining the regular expression */ override def toString = regex } @@ -421,7 +451,7 @@ object Regex { trait MatchData { /** The source from where the match originated */ - val source: java.lang.CharSequence + val source: CharSequence /** The names of the groups, or some empty sequence if one defined */ val groupNames: Seq[String] @@ -459,25 +489,25 @@ object Regex { /** The char sequence before first character of match, * or `null` if nothing was matched */ - def before: java.lang.CharSequence = + def before: CharSequence = if (start >= 0) source.subSequence(0, start) else null /** The char sequence before first character of match in group `i`, * or `null` if nothing was matched for that group */ - def before(i: Int): java.lang.CharSequence = + def before(i: Int): CharSequence = if (start(i) >= 0) source.subSequence(0, start(i)) else null /** Returns char sequence after last character of match, * or `null` if nothing was matched */ - def after: java.lang.CharSequence = + def after: CharSequence = if (end >= 0) source.subSequence(end, source.length) else null /** The char sequence after last character of match in group `i`, * or `null` if nothing was matched for that group */ - def after(i: Int): java.lang.CharSequence = + def after(i: Int): CharSequence = if (end(i) >= 0) source.subSequence(end(i), source.length) else null @@ -501,8 +531,8 @@ object Regex { /** Provides information about a succesful match. */ - class Match(val source: java.lang.CharSequence, - matcher: Matcher, + class Match(val source: CharSequence, + private[matching] val matcher: Matcher, val groupNames: Seq[String]) extends MatchData { /** The index of the first matched character */ @@ -563,7 +593,7 @@ object Regex { /** A class to step through a sequence of regex matches */ - class MatchIterator(val source: java.lang.CharSequence, val regex: Regex, val groupNames: Seq[String]) + class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String]) extends AbstractIterator[String] with Iterator[String] with MatchData { self => protected[Regex] val matcher = regex.pattern.matcher(source) @@ -620,7 +650,7 @@ object Regex { private[matching] trait Replacement { protected def matcher: Matcher - private var sb = new java.lang.StringBuffer + private val sb = new java.lang.StringBuffer def replaced = { val newsb = new java.lang.StringBuffer(sb) diff --git a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala b/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala index 78817cfb67..89832d3fb2 100644 --- a/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala +++ b/src/library/scala/util/parsing/combinator/JavaTokenParsers.scala @@ -21,11 +21,12 @@ import scala.annotation.migration * - `floatingPointNumber` */ trait JavaTokenParsers extends RegexParsers { - /** Anything starting with an ASCII alphabetic character or underscore, - * followed by zero or more repetitions of regex's `\w`. + /** Anything that is a valid Java identifier, according to + * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8">The Java Language Spec</a>. + * Generally, this means a letter, followed by zero or more letters or numbers. */ def ident: Parser[String] = - """[a-zA-Z_]\w*""".r + """\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*""".r /** An integer, without sign or with a negative sign. */ def wholeNumber: Parser[String] = """-?\d+""".r diff --git a/src/library/scala/util/parsing/combinator/PackratParsers.scala b/src/library/scala/util/parsing/combinator/PackratParsers.scala index 16705d45f9..cd0907e40f 100644 --- a/src/library/scala/util/parsing/combinator/PackratParsers.scala +++ b/src/library/scala/util/parsing/combinator/PackratParsers.scala @@ -8,7 +8,6 @@ package scala.util.parsing.combinator -import scala.util.parsing.combinator._ import scala.util.parsing.input.{ Reader, Position } import scala.collection.mutable import scala.language.implicitConversions diff --git a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala b/src/library/scala/util/parsing/combinator/lexical/Scanners.scala index 5c23ad70cd..f6a8daabd9 100644 --- a/src/library/scala/util/parsing/combinator/lexical/Scanners.scala +++ b/src/library/scala/util/parsing/combinator/lexical/Scanners.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - - package scala.util.parsing package combinator package lexical -import token._ import input._ /** This component provides core functionality for lexical parsers. diff --git a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala b/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala index f3491c096f..2fbc1ec136 100644 --- a/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala +++ b/src/library/scala/util/parsing/combinator/lexical/StdLexical.scala @@ -50,7 +50,7 @@ class StdLexical extends Lexical with StdTokens { def identChar = letter | elem('_') // see `whitespace in `Scanners` - def whitespace: Parser[Any] = rep( + def whitespace: Parser[Any] = rep[Any]( whitespaceChar | '/' ~ '*' ~ comment | '/' ~ '/' ~ rep( chrExcept(EofCh, '\n') ) diff --git a/src/library/scala/util/parsing/combinator/testing/Tester.scala b/src/library/scala/util/parsing/combinator/testing/Tester.scala index 95730ee292..3cdab2a885 100644 --- a/src/library/scala/util/parsing/combinator/testing/Tester.scala +++ b/src/library/scala/util/parsing/combinator/testing/Tester.scala @@ -7,7 +7,6 @@ \* */ package scala.util.parsing.combinator.testing -import scala.util.parsing.combinator._ import scala.util.parsing.combinator.lexical.Lexical import scala.util.parsing.combinator.syntactical.TokenParsers diff --git a/src/library/scala/util/parsing/input/OffsetPosition.scala b/src/library/scala/util/parsing/input/OffsetPosition.scala index 01d9ea5cb8..6b00af4ce2 100644 --- a/src/library/scala/util/parsing/input/OffsetPosition.scala +++ b/src/library/scala/util/parsing/input/OffsetPosition.scala @@ -22,7 +22,7 @@ case class OffsetPosition(source: java.lang.CharSequence, offset: Int) extends P /** An index that contains all line starts, including first line, and eof. */ private lazy val index: Array[Int] = { - var lineStarts = new ArrayBuffer[Int] + val lineStarts = new ArrayBuffer[Int] lineStarts += 0 for (i <- 0 until source.length) if (source.charAt(i) == '\n') lineStarts += (i + 1) diff --git a/src/library/scala/util/parsing/json/JSON.scala b/src/library/scala/util/parsing/json/JSON.scala index 2f450ed864..8f951d519a 100644 --- a/src/library/scala/util/parsing/json/JSON.scala +++ b/src/library/scala/util/parsing/json/JSON.scala @@ -7,9 +7,6 @@ \* */ package scala.util.parsing.json -import scala.util.parsing.combinator._ -import scala.util.parsing.combinator.syntactical._ -import scala.util.parsing.combinator.lexical._ /** * This object provides a simple interface to the JSON parser class. diff --git a/src/library/scala/util/parsing/json/Lexer.scala b/src/library/scala/util/parsing/json/Lexer.scala index 991b5d5c6c..762c1352a7 100644 --- a/src/library/scala/util/parsing/json/Lexer.scala +++ b/src/library/scala/util/parsing/json/Lexer.scala @@ -11,7 +11,6 @@ package scala.util.parsing.json import scala.util.parsing.combinator._ -import scala.util.parsing.combinator.syntactical._ import scala.util.parsing.combinator.lexical._ import scala.util.parsing.input.CharArrayReader.EofCh diff --git a/src/library/scala/util/parsing/json/Parser.scala b/src/library/scala/util/parsing/json/Parser.scala index cb87866f07..bf1162000b 100644 --- a/src/library/scala/util/parsing/json/Parser.scala +++ b/src/library/scala/util/parsing/json/Parser.scala @@ -12,7 +12,6 @@ package scala.util.parsing.json import scala.util.parsing.combinator._ import scala.util.parsing.combinator.syntactical._ -import scala.util.parsing.combinator.lexical._ /** * A marker class for the JSON result types. diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala index b9e665e292..fc32e45a5e 100755 --- a/src/library/scala/xml/Elem.scala +++ b/src/library/scala/xml/Elem.scala @@ -17,7 +17,7 @@ package scala.xml * @author Burak Emir <bqe@google.com> */ object Elem { - /** Build an Elem, setting its minimizeEmpty property to <code>true</code> if it has no children. Note that this + /** Build an Elem, setting its minimizeEmpty property to `true` if it has no children. Note that this * default may not be exactly what you want, as some XML dialects don't permit some elements to be minimized. * * @deprecated This factory method is retained for backward compatibility; please use the other one, with which you diff --git a/src/library/scala/xml/Node.scala b/src/library/scala/xml/Node.scala index 6b6c962692..dcd4c15969 100755 --- a/src/library/scala/xml/Node.scala +++ b/src/library/scala/xml/Node.scala @@ -55,7 +55,7 @@ abstract class Node extends NodeSeq { def scope: NamespaceBinding = TopScope /** - * convenience, same as <code>getNamespace(this.prefix)</code> + * convenience, same as `getNamespace(this.prefix)` */ def namespace = getNamespace(this.prefix) @@ -64,8 +64,8 @@ abstract class Node extends NodeSeq { * checks if scope is `'''null'''`. * * @param pre the prefix whose namespace name we would like to obtain - * @return the namespace if <code>scope != null</code> and prefix was - * found, else <code>null</code> + * @return the namespace if `scope != null` and prefix was + * found, else `null` */ def getNamespace(pre: String): String = if (scope eq null) null else scope.getURI(pre) @@ -74,8 +74,8 @@ abstract class Node extends NodeSeq { * Same as `attributes.getValue(key)` * * @param key of queried attribute. - * @return value of <code>UnprefixedAttribute</code> with given key - * in attributes, if it exists, otherwise <code>null</code>. + * @return value of `UnprefixedAttribute` with given key + * in attributes, if it exists, otherwise `null`. */ final def attribute(key: String): Option[Seq[Node]] = attributes.get(key) diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala index 39ff8c35ec..f9157802c6 100755 --- a/src/library/scala/xml/PrettyPrinter.scala +++ b/src/library/scala/xml/PrettyPrinter.scala @@ -47,7 +47,6 @@ class PrettyPrinter(width: Int, step: Int) { val tmp = width - cur if (s.length <= tmp) return List(Box(ind, s)) - val sb = new StringBuilder() var i = s indexOf ' ' if (i > tmp || i == -1) throw new BrokenException() // cannot break diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala index d101684459..ec5e5e9e1c 100755 --- a/src/library/scala/xml/XML.scala +++ b/src/library/scala/xml/XML.scala @@ -45,8 +45,6 @@ object MinimizeMode extends Enumeration { val Never = Value } -import Source._ - /** The object `XML` provides constants, and functions to load * and save XML elements. Use this when data binding is not desired, i.e. * when XML is handled using `Symbol` nodes. diff --git a/src/library/scala/xml/dtd/DocType.scala b/src/library/scala/xml/dtd/DocType.scala index 79f8f9fe8b..ce067bee79 100644 --- a/src/library/scala/xml/dtd/DocType.scala +++ b/src/library/scala/xml/dtd/DocType.scala @@ -15,7 +15,7 @@ package dtd * @author Burak Emir * * @param name name of this DOCTYPE - * @param extID None, or Some(external ID of this doctype) + * @param extID NoExternalID or the external ID of this doctype * @param intSubset sequence of internal subset declarations */ case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl]) @@ -32,3 +32,9 @@ case class DocType(name: String, extID: ExternalID, intSubset: Seq[dtd.Decl]) """<!DOCTYPE %s %s%s>""".format(name, extID.toString, intString) } } + +object DocType +{ + /** Creates a doctype with no external id, nor internal subset declarations. */ + def apply(name: String): DocType = apply(name, NoExternalID, Nil) +} diff --git a/src/library/scala/xml/dtd/ElementValidator.scala b/src/library/scala/xml/dtd/ElementValidator.scala index bfc85f48a9..66951bf390 100644 --- a/src/library/scala/xml/dtd/ElementValidator.scala +++ b/src/library/scala/xml/dtd/ElementValidator.scala @@ -61,7 +61,7 @@ class ElementValidator() extends Function1[Node,Boolean] { */ def check(md: MetaData): Boolean = { val len: Int = exc.length - var ok = new mutable.BitSet(adecls.length) + val ok = new mutable.BitSet(adecls.length) for (attr <- md) { def attrStr = attr.value.toString diff --git a/src/library/scala/xml/dtd/ExternalID.scala b/src/library/scala/xml/dtd/ExternalID.scala index 7a7463569e..e346f89d0a 100644 --- a/src/library/scala/xml/dtd/ExternalID.scala +++ b/src/library/scala/xml/dtd/ExternalID.scala @@ -73,3 +73,14 @@ case class PublicID(publicId: String, systemId: String) extends ExternalID { /** always empty */ def child = Nil } + +/** A marker used when a `DocType` contains no external id. + * + * @author Michael Bayne + */ +object NoExternalID extends ExternalID { + val publicId = null + val systemId = null + + override def toString = "" +} diff --git a/src/library/scala/xml/factory/XMLLoader.scala b/src/library/scala/xml/factory/XMLLoader.scala index 72e4c51b11..efa241e388 100644 --- a/src/library/scala/xml/factory/XMLLoader.scala +++ b/src/library/scala/xml/factory/XMLLoader.scala @@ -12,7 +12,7 @@ package factory import javax.xml.parsers.SAXParserFactory import parsing.{ FactoryAdapter, NoBindingFactoryAdapter } -import java.io.{ InputStream, Reader, StringReader, File, FileDescriptor, FileInputStream } +import java.io.{ InputStream, Reader, File, FileDescriptor } import java.net.URL /** Presents collection of XML loading methods which use the parser diff --git a/src/library/scala/xml/include/sax/EncodingHeuristics.scala b/src/library/scala/xml/include/sax/EncodingHeuristics.scala index 1340689cae..8d8ce5b290 100644 --- a/src/library/scala/xml/include/sax/EncodingHeuristics.scala +++ b/src/library/scala/xml/include/sax/EncodingHeuristics.scala @@ -6,10 +6,8 @@ ** |/ ** \* */ - package scala.xml package include.sax -import scala.xml.include._ import java.io.InputStream import scala.util.matching.Regex diff --git a/src/library/scala/xml/include/sax/XIncludeFilter.scala b/src/library/scala/xml/include/sax/XIncludeFilter.scala index 729769366e..103cddcb11 100644 --- a/src/library/scala/xml/include/sax/XIncludeFilter.scala +++ b/src/library/scala/xml/include/sax/XIncludeFilter.scala @@ -275,7 +275,7 @@ class XIncludeFilter extends XMLFilterImpl { try { val uc = source.openConnection() val in = new BufferedInputStream(uc.getInputStream()) - var encodingFromHeader = uc.getContentEncoding() + val encodingFromHeader = uc.getContentEncoding() var contentType = uc.getContentType() if (encodingFromHeader != null) encoding = encodingFromHeader diff --git a/src/library/scala/xml/include/sax/XIncluder.scala b/src/library/scala/xml/include/sax/XIncluder.scala index 5064d6b3d8..81c5613541 100644 --- a/src/library/scala/xml/include/sax/XIncluder.scala +++ b/src/library/scala/xml/include/sax/XIncluder.scala @@ -6,11 +6,9 @@ ** |/ ** \* */ - package scala.xml package include.sax -import scala.xml.include._ import scala.collection.mutable import org.xml.sax.{ ContentHandler, XMLReader, Locator, Attributes } import org.xml.sax.ext.LexicalHandler diff --git a/src/library/scala/xml/parsing/MarkupParser.scala b/src/library/scala/xml/parsing/MarkupParser.scala index f9ff54d054..6b8f58dca3 100755 --- a/src/library/scala/xml/parsing/MarkupParser.scala +++ b/src/library/scala/xml/parsing/MarkupParser.scala @@ -154,7 +154,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests var info_enc: Option[String] = None var info_stdl: Option[Boolean] = None - var m = xmlProcInstr() + val m = xmlProcInstr() var n = 0 if (isProlog) @@ -303,10 +303,8 @@ trait MarkupParser extends MarkupParserCommon with TokenTests var scope: NamespaceBinding = pscope var aMap: MetaData = Null while (isNameStart(ch)) { - val pos = this.pos - val qname = xName - val _ = xEQ + xEQ // side effect val value = xAttributeValue() Utility.prefix(qname) match { @@ -423,7 +421,7 @@ trait MarkupParser extends MarkupParserCommon with TokenTests * content1 ::= '<' content1 | '&' charref ... * }}} */ def content(pscope: NamespaceBinding): NodeSeq = { - var ts = new NodeBuffer + val ts = new NodeBuffer var exit = eof // todo: optimize seq repr. def done = new NodeSeq { val theSeq = ts.toList } @@ -582,7 +580,6 @@ trait MarkupParser extends MarkupParserCommon with TokenTests var exit = false while (! exit) { putChar(ch) - val opos = pos nextch exit = eof || ( ch == '<' ) || ( ch == '&' ) @@ -828,7 +825,6 @@ trait MarkupParser extends MarkupParserCommon with TokenTests * }}} */ def entityDecl() = { var isParameterEntity = false - var entdef: EntityDef = null xToken("NTITY") xSpace if ('%' == ch) { diff --git a/src/library/scala/xml/parsing/MarkupParserCommon.scala b/src/library/scala/xml/parsing/MarkupParserCommon.scala index da640484e0..43ec539931 100644 --- a/src/library/scala/xml/parsing/MarkupParserCommon.scala +++ b/src/library/scala/xml/parsing/MarkupParserCommon.scala @@ -10,7 +10,6 @@ package scala.xml package parsing import scala.io.Source -import scala.xml.dtd._ import scala.annotation.switch import Utility.Escapes.{ pairs => unescape } diff --git a/src/library/scala/xml/persistent/SetStorage.scala b/src/library/scala/xml/persistent/SetStorage.scala index 20a5bb6767..d16c71c9f7 100644 --- a/src/library/scala/xml/persistent/SetStorage.scala +++ b/src/library/scala/xml/persistent/SetStorage.scala @@ -20,16 +20,14 @@ import java.io.File */ class SetStorage(file: File) extends CachedFileStorage(file) { - private var theSet: mutable.HashSet[Node] = new mutable.HashSet[Node] + private val theSet = mutable.HashSet[Node]() // initialize { val it = super.initialNodes dirty = it.hasNext - for(x <- it) { - theSet += x; - } + theSet ++= it } /* forwarding methods to hashset*/ diff --git a/src/library/scala/xml/transform/RewriteRule.scala b/src/library/scala/xml/transform/RewriteRule.scala index 1dca495a10..13210a6fd2 100644 --- a/src/library/scala/xml/transform/RewriteRule.scala +++ b/src/library/scala/xml/transform/RewriteRule.scala @@ -11,8 +11,8 @@ package scala.xml package transform -/** a RewriteRule, when applied to a term, yields either - * the resulting of rewriting or the term itself it the rule +/** A RewriteRule, when applied to a term, yields either + * the result of rewriting the term or the term itself if the rule * is not applied. * * @author Burak Emir diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala index 3110ccd1ce..6bf4c7d1da 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala @@ -75,9 +75,6 @@ class AssemblyBuilder(name: AssemblyName) //########################################################################## // protected members - // the access properties - Save, Run, RunAndSave - private var access : Int = _ - // all extern assemblies used in this assembly builder protected var externAssemblies = scala.collection.mutable.Set.empty[Assembly] diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala index 2aa9a99054..63ecbfd353 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala @@ -452,7 +452,7 @@ import ILGenerator._ private var locals: Int = 0 // stack of label for exception mechanism - private var excStack: ExceptionStack = new ExceptionStack() + private val excStack: ExceptionStack = new ExceptionStack() // the method info owner of this ILGenerator var owner: MethodBase = _owner diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala index 0ed5e3f3bb..413b08ddd8 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala @@ -96,7 +96,7 @@ abstract class ILPrinterVisitor extends Visitor { protected def println(s: String){ print(s); println() } protected def println(o: Object){ print(o); println() } protected def printName(name: String) { - var ch = name.charAt(0) + val ch = name.charAt(0) //if (Character.isLetter(ch) && Character.isLowerCase(ch)) { if ((ch != '.') && (ch != '!')) { print('\''); print(name); print('\'') @@ -174,7 +174,6 @@ abstract class ILPrinterVisitor extends Visitor { print(constraintFlags(tVar)) if(tVar.Constraints.length > 0) { print('(') - val lastCnstrtIdx = tVar.Constraints.length - 1 for (ic <- 0 until tVar.Constraints.length) { val cnstrt = tVar.Constraints(ic) printReference(cnstrt) @@ -211,7 +210,7 @@ abstract class ILPrinterVisitor extends Visitor { print(" extends ") printReference(`type`.BaseType()) } - var ifaces: Array[Type] = `type`.getInterfaces() + val ifaces: Array[Type] = `type`.getInterfaces() if (ifaces.length > 0) { println() print(" implements ") @@ -331,7 +330,7 @@ abstract class ILPrinterVisitor extends Visitor { def msilSyntaxDouble(valDou: java.lang.Double) : String = { // !!! check if encoding is correct - var bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue()) + val bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue()) /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */ /* Note: no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. */ val res = if (valDou.isNaN) "0xffffffffffffffff /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */ @@ -452,7 +451,7 @@ abstract class ILPrinterVisitor extends Visitor { */ @throws(classOf[IOException]) def caseOpCode(opCode: OpCode) { - var opString = opCode.toString() + val opString = opCode.toString() print(opString) pad(14 - opString.length()) @@ -661,7 +660,7 @@ abstract class ILPrinterVisitor extends Visitor { print(' '); printReference(method.DeclaringType) print("::"); printName(method.Name) - var params = method.GetParameters() + val params = method.GetParameters() print("(") for (i <- 0 until params.length) { if (i > 0) print(", ") @@ -744,7 +743,7 @@ abstract class ILPrinterVisitor extends Visitor { } def printAttributes(icap: ICustomAttributeProvider) { - var attrs = icap.GetCustomAttributes(false) + val attrs = icap.GetCustomAttributes(false) for (i <- 0 until attrs.length) { print(".custom ") printSignature((attrs(i).asInstanceOf[Attribute]).getConstructor()) @@ -767,7 +766,7 @@ object ILPrinterVisitor { def hasControlChars(str: String): Boolean = { for(i <- 0 until str.length()) { - var ch = str.charAt(i) + val ch = str.charAt(i) ch match { case '\b' => case '\t' => @@ -789,7 +788,7 @@ object ILPrinterVisitor { case e : java.io.UnsupportedEncodingException => throw new RuntimeException(e) } } - var str = new StringBuffer(s) + val str = new StringBuffer(s) var ss = EMPTY var i = 0 while(i < str.length()) { @@ -834,7 +833,7 @@ object ILPrinterVisitor { final var primitive = scala.collection.mutable.Map.empty[Type, String] def addPrimitive(name: String, sig: String) { - var `type` = + val `type` = Type.GetType(name) assert(`type` != null, "Cannot lookup primitive type " + `type`) primitive.put(`type`, sig) diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala index 22c1b1150b..a80ea72323 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/Label.scala @@ -107,16 +107,15 @@ object Label { //######################################################################## // Special Labels - final class SpecialLabel(_kind: Label.Kind) extends Label { - private final var kind: Label.Kind = _kind + final class SpecialLabel(kind: Label.Kind) extends Label { def isInitialized() = true - def getAddress(): Int = { throw new RuntimeException("" + kind.toString()) } - def getStacksize(): Int = { throw new RuntimeException("" + kind.toString()) } - def setStacksize(stacksize: Int) { throw new RuntimeException(kind.toString()) } - def incStacksize() { throw new RuntimeException(kind.toString()) } + def getAddress(): Int = { throw new RuntimeException("" + kind) } + def getStacksize(): Int = { throw new RuntimeException("" + kind) } + def setStacksize(stacksize: Int) { throw new RuntimeException("" + kind) } + def incStacksize() { throw new RuntimeException("" + kind) } def getKind(): Kind = kind - def mergeWith(that: Label) { throw new RuntimeException(kind.toString()) } - override def toString(): String = "Label(" + kind.toString() + ")" + def mergeWith(that: Label) { throw new RuntimeException("" + kind) } + override def toString() = s"Label($kind)" } final val NewScope: Label = new SpecialLabel(Kind.NewScope) diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala index 981e855e0e..2319d5ca27 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala @@ -73,7 +73,7 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly: baseType: Type, interfaces: Array[Type]): TypeBuilder = { - var t: Type = GetType(typeName) // Module.GetType(String) + val t: Type = GetType(typeName) // Module.GetType(String) if (t != null) throw new RuntimeException ("Type [" + Assembly + "]" + typeName + "' already exists!") diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala index 55c52109b6..bbbbf40508 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala @@ -41,7 +41,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator) // print each module - var m: Array[Module] = assemblyBuilder.GetModules() + val m: Array[Module] = assemblyBuilder.GetModules() nomembers = true for(i <- 0 until m.length) { print(m(i).asInstanceOf[ModuleBuilder]) @@ -68,10 +68,10 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str if (!module.globalsCreated) module.CreateGlobalFunctions() - var m: Array[MethodInfo] = module.GetMethods() + val m: Array[MethodInfo] = module.GetMethods() // "Types" contain all the classes - var t: Array[Type] = module.GetTypes() + val t: Array[Type] = module.GetTypes() for(i <- 0 until t.length) { val tBuilder = t(i).asInstanceOf[TypeBuilder] val sourceFilename = tBuilder.sourceFilename @@ -108,7 +108,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str // now write the global methods (typically contains the "main" method) if(!nomembers) { - var globalMethods: File = new File(destPath, ILPrinterVisitor.currAssembly.GetName().Name + ".msil") + val globalMethods: File = new File(destPath, ILPrinterVisitor.currAssembly.GetName().Name + ".msil") val append = assemblyBuilder.generatedFiles.contains(globalMethods.getPath) out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append))) diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala index 5d59d4d25a..50e9f45373 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala @@ -48,7 +48,7 @@ final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisit printAssemblyBoilerplate() // print each module - var m: Array[Module] = assemblyBuilder.GetModules() + val m: Array[Module] = assemblyBuilder.GetModules() nomembers = true for(i <- 0 until m.length) { print(m(i).asInstanceOf[ModuleBuilder]) @@ -78,12 +78,12 @@ final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisit if (!module.globalsCreated) module.CreateGlobalFunctions() - var m: Array[MethodInfo] = module.GetMethods() + val m: Array[MethodInfo] = module.GetMethods() for(i <- 0 until m.length) { print(m(i).asInstanceOf[MethodBuilder]) } - var t: Array[Type] = module.GetTypes() + val t: Array[Type] = module.GetTypes() for(i <- 0 until t.length) { print(t(i).asInstanceOf[TypeBuilder]) } diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala index 57dc883898..0b0b16da65 100644 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala @@ -221,7 +221,7 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType: object TypeBuilder { def types2String(types: Array[Type]): String = { - var s = new StringBuffer("(") + val s = new StringBuffer("(") for(i <- 0 until types.length) { if (i > 0) s.append(", ") s.append(types(i)) diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala index d73d99bc89..bb0732dcc6 100644 --- a/src/partest/scala/tools/partest/CompilerTest.scala +++ b/src/partest/scala/tools/partest/CompilerTest.scala @@ -21,7 +21,7 @@ abstract class CompilerTest extends DirectTest { lazy val global: Global = newCompiler() lazy val units = compilationUnits(global)(sources: _ *) import global._ - import definitions._ + import definitions.{ compilerTypeFromTag } override def extraSettings = "-usejavacp -d " + testOutput.path @@ -32,7 +32,6 @@ abstract class CompilerTest extends DirectTest { def sources: List[String] = List(code) // Utility functions - class MkType(sym: Symbol) { def apply[M](implicit t: ru.TypeTag[M]): Type = if (sym eq NoSymbol) NoType diff --git a/src/partest/scala/tools/partest/PartestDefaults.scala b/src/partest/scala/tools/partest/PartestDefaults.scala index b27ce6ff75..e3f1cb8bd9 100644 --- a/src/partest/scala/tools/partest/PartestDefaults.scala +++ b/src/partest/scala/tools/partest/PartestDefaults.scala @@ -8,8 +8,6 @@ import java.lang.Runtime.getRuntime object PartestDefaults { import nsc.Properties._ - private def wrapAccessControl[T](body: => Option[T]): Option[T] = - try body catch { case _: java.security.AccessControlException => None } def testRootName = propOrNone("partest.root") def srcDirName = propOrElse("partest.srcdir", "files") diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala index d9f2bfe765..41d69a5448 100644 --- a/src/partest/scala/tools/partest/PartestTask.scala +++ b/src/partest/scala/tools/partest/PartestTask.scala @@ -182,7 +182,6 @@ class PartestTask extends Task with CompilationPathProperty { private var javaccmd: Option[File] = None private var showDiff: Boolean = false private var showLog: Boolean = false - private var runFailed: Boolean = false private var posFiles: Option[FileSet] = None private var negFiles: Option[FileSet] = None private var runFiles: Option[FileSet] = None @@ -345,7 +344,6 @@ class PartestTask extends Task with CompilationPathProperty { antFileManager.showDiff = showDiff antFileManager.showLog = showLog - antFileManager.failed = runFailed antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*) antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath antFileManager.LATEST_REFLECT = scalaReflect.getAbsolutePath diff --git a/src/partest/scala/tools/partest/ScaladocModelTest.scala b/src/partest/scala/tools/partest/ScaladocModelTest.scala index e7134d0271..acaddff944 100644 --- a/src/partest/scala/tools/partest/ScaladocModelTest.scala +++ b/src/partest/scala/tools/partest/ScaladocModelTest.scala @@ -5,8 +5,6 @@ package scala.tools.partest -import scala.tools.partest._ -import java.io._ import scala.tools.nsc._ import scala.tools.nsc.util.CommandLineParser import scala.tools.nsc.doc.{Settings, DocFactory, Universe} @@ -87,7 +85,7 @@ abstract class ScaladocModelTest extends DirectTest { settings = new Settings(_ => ()) settings.scaladocQuietRun = true // yaay, no more "model contains X documentable templates"! val args = extraSettings + " " + scaladocSettings - val command = new ScalaDoc.Command((CommandLineParser tokenize (args)), settings) + new ScalaDoc.Command((CommandLineParser tokenize (args)), settings) // side-effecting, I think val docFact = new DocFactory(new ConsoleReporter(settings), settings) docFact } diff --git a/src/partest/scala/tools/partest/SecurityTest.scala b/src/partest/scala/tools/partest/SecurityTest.scala index 2d6f61d0b1..1f1c8a95ea 100644 --- a/src/partest/scala/tools/partest/SecurityTest.scala +++ b/src/partest/scala/tools/partest/SecurityTest.scala @@ -10,23 +10,10 @@ import java.util._ abstract class SecurityTest extends App { def throwIt(x: Any) = throw new AccessControlException("" + x) - - def readPerm(p: PropertyPermission) = p.getActions contains "read" - def writePerm(p: PropertyPermission) = p.getActions contains "write" def propertyCheck(p: PropertyPermission): Unit = throwIt(p) def check(perm: Permission): Unit = perm match { case p: PropertyPermission => propertyCheck(p) case _ => () } - - lazy val sm = new SecurityManager { - // these two are the choke points for all permissions checks - override def checkPermission(perm: Permission): Unit = check(perm) - override def checkPermission(perm: Permission, context: Object): Unit = check(perm) - } - def securityOn(): Boolean = { - try { System.setSecurityManager(sm) ; true } - catch { case _: SecurityException => false } - } } diff --git a/src/partest/scala/tools/partest/TestUtil.scala b/src/partest/scala/tools/partest/TestUtil.scala index 9bfd444180..5c177ac962 100644 --- a/src/partest/scala/tools/partest/TestUtil.scala +++ b/src/partest/scala/tools/partest/TestUtil.scala @@ -24,14 +24,6 @@ trait TestUtil { } def nanos(body: => Unit): Long = alsoNanos(body)._1 - def verifySpeed(body1: => Unit, body2: => Unit, acceptableMultiple: Double) = { - val t1 = nanos(body1).toDouble - val t2 = nanos(body2).toDouble - val mult = if (t1 > t2) t1 / t2 else t2 / t1 - - assert(mult <= acceptableMultiple, "Performance difference too great: multiple = " + mult) - } - def intercept[T <: Exception : ClassTag](code: => Unit): Unit = try { code @@ -41,6 +33,6 @@ trait TestUtil { } } +// Used in tests. object TestUtil extends TestUtil { - } diff --git a/src/partest/scala/tools/partest/instrumented/Instrumentation.scala b/src/partest/scala/tools/partest/instrumented/Instrumentation.scala index 8a284b313b..18dd740208 100644 --- a/src/partest/scala/tools/partest/instrumented/Instrumentation.scala +++ b/src/partest/scala/tools/partest/instrumented/Instrumentation.scala @@ -78,6 +78,7 @@ object Instrumentation { !t.className.startsWith("scala/util/DynamicVariable") } + // Used in tests. def printStatistics(stats: Statistics = getStatistics, filter: MethodCallTrace => Boolean = standardFilter): Unit = { val stats = getStatistics println("Method call statistics:") diff --git a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java index 494a5a99be..b6bec2f598 100644 --- a/src/partest/scala/tools/partest/javaagent/ASMTransformer.java +++ b/src/partest/scala/tools/partest/javaagent/ASMTransformer.java @@ -26,9 +26,35 @@ public class ASMTransformer implements ClassFileTransformer { className.startsWith("instrumented/")); } - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { + public byte[] transform(final ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { if (shouldTransform(className)) { - ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) { + // this is copied verbatim from the superclass, + // except that we use the outer class loader + @Override protected String getCommonSuperClass(final String type1, final String type2) { + Class<?> c, d; + try { + c = Class.forName(type1.replace('/', '.'), false, classLoader); + d = Class.forName(type2.replace('/', '.'), false, classLoader); + } catch (Exception e) { + throw new RuntimeException(e.toString()); + } + if (c.isAssignableFrom(d)) { + return type1; + } + if (d.isAssignableFrom(c)) { + return type2; + } + if (c.isInterface() || d.isInterface()) { + return "java/lang/Object"; + } else { + do { + c = c.getSuperclass(); + } while (!c.isAssignableFrom(d)); + return c.getName().replace('.', '/'); + } + } + }; ProfilerVisitor visitor = new ProfilerVisitor(writer); ClassReader reader = new ClassReader(classfileBuffer); reader.accept(visitor, 0); diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index 188ebf66ed..3f005d143e 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -71,7 +71,6 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler { } private def updatePluginPath(options: String): String = { - val dir = fileManager.testRootDir def absolutize(path: String) = Path(path) match { case x if x.isAbsolute => x.path case x => (fileManager.testRootDir / x).toAbsolute.path diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala index 08e709de90..7000e8280b 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala @@ -18,8 +18,6 @@ import io.{ Path, Directory } import File.pathSeparator import ClassPath.{ join } import PathResolver.{ Environment, Defaults } -import RunnerUtils._ - class ConsoleFileManager extends FileManager { var testBuild: Option[String] = PartestDefaults.testBuild @@ -81,7 +79,6 @@ class ConsoleFileManager extends FileManager { testClassesDir = Path(testClasses.get).toCanonical.toDirectory NestUI.verbose("Running with classes in "+testClassesDir) - latestFile = testClassesDir.parent / "bin" latestLibFile = testClassesDir / "library" latestActorsFile = testClassesDir / "library" / "actors" latestReflectFile = testClassesDir / "reflect" @@ -92,7 +89,6 @@ class ConsoleFileManager extends FileManager { else if (testBuild.isDefined) { val dir = Path(testBuild.get) NestUI.verbose("Running on "+dir) - latestFile = dir / "bin" latestLibFile = dir / "lib/scala-library.jar" latestActorsFile = dir / "lib/scala-actors.jar" latestReflectFile = dir / "lib/scala-reflect.jar" @@ -103,7 +99,6 @@ class ConsoleFileManager extends FileManager { else { def setupQuick() { NestUI.verbose("Running build/quick") - latestFile = prefixFile("build/quick/bin") latestLibFile = prefixFile("build/quick/classes/library") latestActorsFile = prefixFile("build/quick/classes/library/actors") latestReflectFile = prefixFile("build/quick/classes/reflect") @@ -114,7 +109,6 @@ class ConsoleFileManager extends FileManager { def setupInst() { NestUI.verbose("Running dist (installed)") val p = testParent.getParentFile - latestFile = prefixFileWith(p, "bin") latestLibFile = prefixFileWith(p, "lib/scala-library.jar") latestActorsFile = prefixFileWith(p, "lib/scala-actors.jar") latestReflectFile = prefixFileWith(p, "lib/scala-reflect.jar") @@ -124,7 +118,6 @@ class ConsoleFileManager extends FileManager { def setupDist() { NestUI.verbose("Running dists/latest") - latestFile = prefixFile("dists/latest/bin") latestLibFile = prefixFile("dists/latest/lib/scala-library.jar") latestActorsFile = prefixFile("dists/latest/lib/scala-actors.jar") latestReflectFile = prefixFile("dists/latest/lib/scala-reflect.jar") @@ -134,7 +127,6 @@ class ConsoleFileManager extends FileManager { def setupPack() { NestUI.verbose("Running build/pack") - latestFile = prefixFile("build/pack/bin") latestLibFile = prefixFile("build/pack/lib/scala-library.jar") latestActorsFile = prefixFile("build/pack/lib/scala-actors.jar") latestReflectFile = prefixFile("build/pack/lib/scala-reflect.jar") @@ -142,11 +134,6 @@ class ConsoleFileManager extends FileManager { latestPartestFile = prefixFile("build/pack/lib/scala-partest.jar") } - val dists = testParent / "dists" - val build = testParent / "build" - // in case of an installed dist, testRootDir is one level deeper - val bin = testParent.parent / "bin" - def mostRecentOf(base: String, names: String*) = names map (x => prefixFile(base + "/" + x).lastModified) reduceLeft (_ max _) @@ -182,7 +169,6 @@ class ConsoleFileManager extends FileManager { var LATEST_PARTEST: String = "" var LATEST_ACTORS: String = "" - var latestFile: File = _ var latestLibFile: File = _ var latestActorsFile: File = _ var latestReflectFile: File = _ @@ -194,8 +180,6 @@ class ConsoleFileManager extends FileManager { // initialize above fields findLatest() - var testFiles: List[io.Path] = Nil - def getFiles(kind: String, cond: Path => Boolean): List[File] = { def ignoreDir(p: Path) = List("svn", "obj") exists (p hasExtension _) @@ -204,9 +188,7 @@ class ConsoleFileManager extends FileManager { if (dir.isDirectory) NestUI.verbose("look in %s for tests" format dir) else NestUI.failure("Directory '%s' not found" format dir) - val files = - if (testFiles.nonEmpty) testFiles filter (_.parent isSame dir) - else dir.list filterNot ignoreDir filter cond toList + val files = dir.list filterNot ignoreDir filter cond toList ( if (failed) files filter (x => logFileExists(x, kind)) else files ) map (_.jfile) } diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index e016fb7c92..d146618d0e 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -11,7 +11,6 @@ package nest import java.io.{File, PrintStream, FileOutputStream, BufferedReader, InputStreamReader, StringWriter, PrintWriter} import utils.Properties._ -import RunnerUtils._ import scala.tools.nsc.Properties.{ versionMsg, setProp } import scala.tools.nsc.util.CommandLineParser import scala.tools.nsc.io @@ -26,8 +25,6 @@ class ConsoleRunner extends DirectRunner { private def antFilter(p: Path) = p.isFile && (p endsWith "build.xml") val testSets = { - val pathFilter: Path => Boolean = x => x.isDirectory || (x hasExtension "scala") - List( TestSet("pos", stdFilter, "Testing compiler (on files whose compilation should succeed)"), TestSet("neg", stdFilter, "Testing compiler (on files whose compilation should fail)"), @@ -54,8 +51,6 @@ class ConsoleRunner extends DirectRunner { private val testSetArgs = testSets map ("--" + _.kind) private val testSetArgMap = testSetArgs zip testSets toMap - def denotesTestSet(arg: String) = testSetArgs contains arg - private def printVersion() { NestUI outline (versionMsg + "\n") } private val unaryArgs = List( @@ -70,10 +65,11 @@ class ConsoleRunner extends DirectRunner { // true if a test path matches the --grep expression. private def pathMatchesExpr(path: Path, expr: String) = { def pred(p: Path) = file2String(p.toFile) contains expr - def srcs = path.toDirectory.deepList() filter (_.hasExtension("scala", "java")) + def greppable(f: Path) = f.isFile && (f hasExtension ("scala", "java")) + def any(d: Path) = d.toDirectory.deepList() exists (f => greppable(f) && pred(f)) (path.isFile && pred(path)) || - (path.isDirectory && srcs.exists(pred)) || + (path.isDirectory && any(path)) || (pred(path changeExtension "check")) } @@ -94,8 +90,6 @@ class ConsoleRunner extends DirectRunner { else if (parsed isSet "--pack") new ConsoleFileManager("build/pack") else new ConsoleFileManager // auto detection, see ConsoleFileManager.findLatest - def argNarrowsTests(x: String) = denotesTestSet(x) || denotesTestPath(x) - NestUI._verbose = parsed isSet "--verbose" fileManager.showDiff = true // parsed isSet "--show-diff" @@ -121,7 +115,7 @@ class ConsoleRunner extends DirectRunner { val grepOption = parsed get "--grep" val grepPaths = grepOption.toList flatMap { expr => val subjectDirs = testSetKinds map (srcDir / _ toDirectory) - val testPaths = subjectDirs flatMap (_.files filter stdFilter) + val testPaths = subjectDirs flatMap (_.list filter stdFilter) val paths = testPaths filter (p => pathMatchesExpr(p, expr)) if (paths.isEmpty) diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala index 32ef8b41ea..3aaf784cad 100644 --- a/src/partest/scala/tools/partest/nest/DirectRunner.scala +++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala @@ -14,7 +14,6 @@ import scala.tools.nsc.util.ScalaClassLoader import scala.tools.nsc.io.Path import scala.collection.{ mutable, immutable } import java.util.concurrent._ -import scala.collection.convert.decorateAll._ case class TestRunParams(val scalaCheckParentClassLoader: ScalaClassLoader) diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index 2823967ecf..a4c4e7e6a6 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -13,7 +13,6 @@ import java.io.{File, FilenameFilter, IOException, StringWriter, FileReader, PrintWriter, FileWriter} import java.net.URI import scala.tools.nsc.io.{ Path, Directory, File => SFile } -import scala.sys.process._ import scala.collection.mutable trait FileUtil { @@ -73,17 +72,11 @@ trait FileManager extends FileUtil { var SCALAC_OPTS = PartestDefaults.scalacOpts.split(' ').toSeq var JAVA_OPTS = PartestDefaults.javaOpts var timeout = PartestDefaults.timeout - // how can 15 minutes not be enough? What are you doing, run/lisp.scala? - // You complete in 11 seconds on my machine. - var oneTestTimeout = 60 * 60 * 1000 /** Only when --debug is given. */ lazy val testTimings = new mutable.HashMap[String, Long] def recordTestTiming(name: String, milliseconds: Long) = synchronized { testTimings(name) = milliseconds } - def showTestTimings() { - testTimings.toList sortBy (-_._2) foreach { case (k, v) => println("%s: %s".format(k, v)) } - } def getLogFile(dir: File, fileBase: String, kind: String): File = new File(dir, fileBase + "-" + kind + ".log") diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala index 70db6d0ed1..ab90d387d0 100644 --- a/src/partest/scala/tools/partest/nest/NestUI.scala +++ b/src/partest/scala/tools/partest/nest/NestUI.scala @@ -54,9 +54,6 @@ object NestUI { } def warning(msg: String) = print(_warning + msg + _default) - def warning(msg: String, wr: PrintWriter) = synchronized { - wr.print(_warning + msg + _default) - } def normal(msg: String) = print(_default + msg) def normal(msg: String, wr: PrintWriter) = synchronized { @@ -104,7 +101,6 @@ object NestUI { } var _verbose = false - var _debug = false def verbose(msg: String) { if (_verbose) { @@ -112,10 +108,4 @@ object NestUI { println(msg) } } - def debug(msg: String) { - if (isPartestDebug) { - outline("debug: ") - println(msg) - } - } } diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala index a42c2219b1..02651c527b 100644 --- a/src/partest/scala/tools/partest/nest/PathSettings.scala +++ b/src/partest/scala/tools/partest/nest/PathSettings.scala @@ -9,7 +9,6 @@ import scala.tools.nsc.Properties.{ setProp, propOrEmpty, propOrNone, propOrElse import scala.tools.nsc.util.ClassPath import scala.tools.nsc.io import io.{ Path, File, Directory } -import RunnerUtils._ object PathSettings { import PartestDefaults.{ testRootDir, srcDirName } diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index 5cb8589d66..4b0ed1f82a 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -3,8 +3,6 @@ * @author Philipp Haller */ -// $Id$ - package scala.tools.partest package nest @@ -12,7 +10,6 @@ import scala.tools.nsc.Properties.{ setProp, propOrEmpty } import scala.tools.nsc.util.ClassPath import scala.tools.nsc.io import io.Path -import RunnerUtils._ import java.net.URLClassLoader /* This class is used to load an instance of DirectRunner using @@ -28,6 +25,12 @@ class ReflectiveRunner { // was used to start the runner. val sepRunnerClassName = "scala.tools.partest.nest.ConsoleRunner" + private def searchPath(option: String, as: List[String]): Option[String] = as match { + case `option` :: r :: _ => Some(r) + case _ :: rest => searchPath(option, rest) + case Nil => None + } + def main(args: String) { val argList = (args.split("\\s")).toList diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala index c5e944fbc0..f2ce19a950 100644 --- a/src/partest/scala/tools/partest/nest/RunnerManager.scala +++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala @@ -260,13 +260,12 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP runCommand(cmd, logFile) } - private def getCheckFilePath(dir: File, suffix: String = "") = { + private def getCheckFilePath(dir: File, suffix: String) = { def chkFile(s: String) = (Directory(dir) / "%s%s.check".format(fileBase, s)).toFile if (chkFile("").isFile || suffix == "") chkFile("") else chkFile("-" + suffix) } - private def getCheckFile(dir: File) = Some(getCheckFilePath(dir, kind)) filter (_.canRead) private def compareOutput(dir: File, logFile: File): String = { val checkFile = getCheckFilePath(dir, kind) @@ -287,15 +286,10 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP def newTestWriters() = { val swr = new StringWriter val wr = new PrintWriter(swr, true) - // diff = "" ((swr, wr)) } - def fail(what: Any) = { - NestUI.verbose("scalac: compilation of "+what+" failed\n") - false - } def diffCheck(testFile: File, diff: String) = { testDiff = diff testDiff == "" @@ -341,10 +335,34 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP val (scalaFiles, javaFiles) = g partition isScala val allFiles = javaFiles ++ scalaFiles + /* The test can contain both java and scala files, each of which should be compiled with the corresponding + * compiler. Since the source files can reference each other both ways (java referencing scala classes and + * vice versa, the partest compilation routine attempts to reach a "bytecode fixpoint" between the two + * compilers -- that's when bytecode generated by each compiler implements the signatures expected by the other. + * + * In theory this property can't be guaranteed, as neither compiler can know what signatures the other + * compiler expects and how to implement them. (see SI-1240 for the full story) + * + * In practice, this happens in 3 steps: + * STEP1: feed all the files to scalac + * it will parse java files and obtain their expected signatures and generate bytecode for scala files + * STEP2: feed the java files to javac + * it will generate the bytecode for the java files and link to the scalac-generated bytecode for scala + * STEP3: only if there are both scala and java files, recompile the scala sources so they link to the correct + * java signatures, in case the signatures deduced by scalac from the source files were wrong. Since the + * bytecode for java is already in place, we only feed the scala files to scalac so it will take the + * java signatures from the existing javac-generated bytecode + */ List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) { - case (CompileSuccess, 1) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) // java + scala - case (CompileSuccess, 2) if javaFiles.nonEmpty => javac(outDir, javaFiles, logFile) // java - case (CompileSuccess, 3) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) // scala + case (CompileSuccess, 1) if scalaFiles.nonEmpty => + compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) + case (CompileSuccess, 2) if javaFiles.nonEmpty => + javac(outDir, javaFiles, logFile) + case (CompileSuccess, 3) if scalaFiles.nonEmpty && javaFiles.nonEmpty => + // TODO: Do we actually need this? SI-1240 is known to require this, but we don't know if other tests + // require it: https://groups.google.com/forum/?fromgroups#!topic/scala-internals/rFDKAcOKciU + compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) + case (outcome, _) => outcome } } @@ -832,9 +850,8 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP if (fileManager.failed && !runner.logFile.canRead) return TestState.Ok - // sys addShutdownHook cleanup() - val ((success, ctx), elapsed) = timed(runner.run()) - val state = if (success) TestState.Ok else TestState.Fail + val (success, ctx) = runner.run() + val state = if (success) TestState.Ok else TestState.Fail runner.reportResult(ctx.writers) state diff --git a/src/partest/scala/tools/partest/nest/RunnerUtils.scala b/src/partest/scala/tools/partest/nest/RunnerUtils.scala deleted file mode 100644 index 6707a9338a..0000000000 --- a/src/partest/scala/tools/partest/nest/RunnerUtils.scala +++ /dev/null @@ -1,29 +0,0 @@ -/* NEST (New Scala Test) - * Copyright 2007-2013 LAMP/EPFL - * @author Philipp Haller - */ - -// $Id$ - -package scala.tools.partest -package nest - -object RunnerUtils { - def splitArgs(str: String) = str split "\\s" filterNot (_ == "") toList - - def searchPath(option: String, as: List[String]): Option[String] = as match { - case `option` :: r :: _ => Some(r) - case _ :: rest => searchPath(option, rest) - case Nil => None - } - - def searchAndRemovePath(option: String, as: List[String]) = (as indexOf option) match { - case -1 => (None, as) - case idx => (Some(as(idx + 1)), (as take idx) ::: (as drop (idx + 2))) - } - - def searchAndRemoveOption(option: String, as: List[String]) = (as indexOf option) match { - case -1 => (false, as) - case idx => (true, (as take idx) ::: (as drop (idx + 1))) - } -} diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index d38ce692d7..2b2ce2e435 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -12,11 +12,7 @@ import scala.sys.process.javaVmArguments import java.util.concurrent.Callable package partest { - class TestState { - def isOk = this eq TestState.Ok - def isFail = this eq TestState.Fail - def isTimeout = this eq TestState.Timeout - } + class TestState { } object TestState { val Ok = new TestState val Fail = new TestState @@ -43,9 +39,8 @@ package object partest { def callable[T](body: => T): Callable[T] = new Callable[T] { override def call() = body } - def path2String(path: String) = file2String(new JFile(path)) def file2String(f: JFile) = - try SFile(f).slurp() + try SFile(f).slurp(scala.io.Codec.UTF8) catch { case _: FileNotFoundException => "" } def basename(name: String): String = Path(name).stripExtension @@ -74,7 +69,6 @@ package object partest { def isPartestDebug: Boolean = propOrEmpty("partest.debug") == "true" - import scala.language.experimental.macros /** diff --git a/src/partest/scala/tools/partest/utils/PrintMgr.scala b/src/partest/scala/tools/partest/utils/PrintMgr.scala deleted file mode 100644 index d25be87c1e..0000000000 --- a/src/partest/scala/tools/partest/utils/PrintMgr.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala Parallel Testing ** -** / __/ __// _ | / / / _ | (c) 2007-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.tools.partest -package utils - -/** - * @author Thomas Hofer - */ -object PrintMgr { - - val NONE = 0 - val SOME = 1 - val MANY = 2 - - var outline = "" - var success = "" - var failure = "" - var warning = "" - var default = "" - - def initialization(number: Int) = number match { - case MANY => - outline = Console.BOLD + Console.BLACK - success = Console.BOLD + Console.GREEN - failure = Console.BOLD + Console.RED - warning = Console.BOLD + Console.YELLOW - default = Console.RESET - case SOME => - outline = Console.BOLD + Console.BLACK - success = Console.RESET - failure = Console.BOLD + Console.BLACK - warning = Console.BOLD + Console.BLACK - default = Console.RESET - case _ => - } - - def printOutline(msg: String) = print(outline + msg + default) - - def printSuccess(msg: String) = print(success + msg + default) - - def printFailure(msg: String) = print(failure + msg + default) - - def printWarning(msg: String) = print(warning + msg + default) -} diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index 85ddcc6523..76df76cdc8 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -166,7 +166,7 @@ trait Printers { self: Universe => protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = { val buffer = new StringWriter() val writer = new PrintWriter(buffer) - var printer = mkPrinter(writer) + val printer = mkPrinter(writer) printTypes.value.map(printTypes => if (printTypes) printer.withTypes else printer.withoutTypes) printIds.value.map(printIds => if (printIds) printer.withIds else printer.withoutIds) printKinds.value.map(printKinds => if (printKinds) printer.withKinds else printer.withoutKinds) diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 7c12b5979d..da50c55fe1 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -6,7 +6,6 @@ package scala.reflect package internal -import util._ import pickling.ByteCodecs import scala.annotation.tailrec import scala.collection.immutable.ListMap @@ -288,10 +287,6 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => /** Check whether any of the arguments mention a symbol */ def refsSymbol(sym: Symbol) = hasArgWhich(_.symbol == sym) - /** Change all ident's with Symbol "from" to instead use symbol "to" */ - def substIdentSyms(from: Symbol, to: Symbol) = - AnnotationInfo(atp, args map (_ substituteSymbols (List(from), List(to))), assocs) setPos pos - def stringArg(index: Int) = constantAtIndex(index) map (_.stringValue) def intArg(index: Int) = constantAtIndex(index) map (_.intValue) def symbolArg(index: Int) = argAtIndex(index) collect { @@ -325,14 +320,14 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => implicit val AnnotationTag = ClassTag[AnnotationInfo](classOf[AnnotationInfo]) object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil) - + /** Extracts symbol of thrown exception from AnnotationInfo. - * + * * Supports both “old-style” `@throws(classOf[Exception])` * as well as “new-stye” `@throws[Exception]("cause")` annotations. */ object ThrownException { - def unapply(ann: AnnotationInfo): Option[Symbol] = + def unapply(ann: AnnotationInfo): Option[Symbol] = ann match { case AnnotationInfo(tpe, _, _) if tpe.typeSymbol != ThrowsClass => None diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index d72f08674e..6bf12f06de 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -115,7 +115,7 @@ trait BaseTypeSeqs { def map(f: Type => Type): BaseTypeSeq = { // inlined `elems map f` for performance val len = length - var arr = new Array[Type](len) + val arr = new Array[Type](len) var i = 0 while (i < len) { arr(i) = f(elems(i)) @@ -158,7 +158,7 @@ trait BaseTypeSeqs { val parents = tp.parents // Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG val buf = new mutable.ListBuffer[Type] - buf += tsym.tpe + buf += tsym.tpe_* var btsSize = 1 if (parents.nonEmpty) { val nparents = parents.length diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 9f41f0336e..9da6ad652a 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -1,8 +1,6 @@ package scala.reflect package internal -import Flags._ - trait BuildUtils { self: SymbolTable => class BuildImpl extends BuildApi { diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala index 7ccb661426..2ab3caa19d 100644 --- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala +++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala @@ -342,7 +342,7 @@ object ClassfileConstants { case JAVA_ACC_PRIVATE => PRIVATE case JAVA_ACC_PROTECTED => PROTECTED case JAVA_ACC_FINAL => FINAL - case JAVA_ACC_SYNTHETIC => SYNTHETIC + case JAVA_ACC_SYNTHETIC => SYNTHETIC | ARTIFACT // maybe should be just artifact? case JAVA_ACC_STATIC => STATIC case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT @@ -372,7 +372,7 @@ object ClassfileConstants { } def methodFlags(jflags: Int): Long = { initFields(jflags) - translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE else 0) + translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0) } } object FlagTranslation extends FlagTranslation { } @@ -380,11 +380,4 @@ object ClassfileConstants { def toScalaMethodFlags(flags: Int): Long = FlagTranslation methodFlags flags def toScalaClassFlags(flags: Int): Long = FlagTranslation classFlags flags def toScalaFieldFlags(flags: Int): Long = FlagTranslation fieldFlags flags - - @deprecated("Use another method in this object", "2.10.0") - def toScalaFlags(flags: Int, isClass: Boolean = false, isField: Boolean = false): Long = ( - if (isClass) toScalaClassFlags(flags) - else if (isField) toScalaFieldFlags(flags) - else toScalaMethodFlags(flags) - ) } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 2a7b55cb5a..9a846179b9 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -9,7 +9,6 @@ package internal import scala.annotation.{ switch, meta } import scala.collection.{ mutable, immutable } import Flags._ -import PartialFunction._ import scala.reflect.api.{Universe => ApiUniverse} trait Definitions extends api.StandardDefinitions { @@ -31,7 +30,7 @@ trait Definitions extends api.StandardDefinitions { val clazz = owner.newClassSymbol(name, NoPosition, flags) clazz setInfoAndEnter ClassInfoType(parents, newScope, clazz) } - private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): MethodSymbol = { + private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long): MethodSymbol = { val msym = owner.newMethod(name.encode, NoPosition, flags) val params = msym.newSyntheticValueParams(formals) msym setInfo MethodType(params, restpe) @@ -149,7 +148,6 @@ trait Definitions extends api.StandardDefinitions { FloatClass, DoubleClass ) - def ScalaValueClassCompanions: List[Symbol] = ScalaValueClasses map (_.companionSymbol) def ScalaPrimitiveValueClasses: List[ClassSymbol] = ScalaValueClasses } @@ -157,9 +155,6 @@ trait Definitions extends api.StandardDefinitions { private var isInitialized = false def isDefinitionsInitialized = isInitialized - // symbols related to packages - var emptypackagescope: Scope = null //debug - @deprecated("Moved to rootMirror.RootPackage", "2.10.0") val RootPackage: ModuleSymbol = rootMirror.RootPackage @@ -181,8 +176,6 @@ trait Definitions extends api.StandardDefinitions { lazy val RuntimePackage = getRequiredPackage("scala.runtime") lazy val RuntimePackageClass = RuntimePackage.moduleClass.asClass - lazy val JavaLangEnumClass = requiredClass[java.lang.Enum[_]] - // convenient one-argument parameter lists lazy val anyparam = List(AnyClass.tpe) lazy val anyvalparam = List(AnyValClass.typeConstructor) @@ -223,7 +216,7 @@ trait Definitions extends api.StandardDefinitions { def fullyInitializeSymbol(sym: Symbol): Symbol = { sym.initialize fullyInitializeType(sym.info) - fullyInitializeType(sym.tpe) + fullyInitializeType(sym.tpe_*) sym } def fullyInitializeType(tp: Type): Type = { @@ -235,14 +228,32 @@ trait Definitions extends api.StandardDefinitions { scope.sorted foreach fullyInitializeSymbol scope } + /** Is this symbol a member of Object or Any? */ + def isUniversalMember(sym: Symbol) = ( + (sym ne NoSymbol) + && (ObjectClass isSubClass sym.owner) + ) + + /** Is this symbol unimportable? Unimportable symbols include: + * - constructors, because <init> is not a real name + * - private[this] members, which cannot be referenced from anywhere else + * - members of Any or Object, because every instance will inherit a + * definition which supersedes the imported one + */ + def isUnimportable(sym: Symbol) = ( + (sym eq NoSymbol) + || sym.isConstructor + || sym.isPrivateLocal + || isUniversalMember(sym) + ) + def isImportable(sym: Symbol) = !isUnimportable(sym) + /** Is this type equivalent to Any, AnyVal, or AnyRef? */ def isTrivialTopType(tp: Type) = ( tp =:= AnyClass.tpe || tp =:= AnyValClass.tpe || tp =:= AnyRefClass.tpe ) - /** Does this type have a parent which is none of Any, AnyVal, or AnyRef? */ - def hasNonTrivialParent(tp: Type) = tp.parents exists (t => !isTrivialTopType(tp)) private def fixupAsAnyTrait(tpe: Type): Type = tpe match { case ClassInfoType(parents, decls, clazz) => @@ -253,7 +264,6 @@ trait Definitions extends api.StandardDefinitions { } case PolyType(tparams, restpe) => PolyType(tparams, fixupAsAnyTrait(restpe)) -// case _ => tpe } // top types @@ -312,6 +322,9 @@ trait Definitions extends api.StandardDefinitions { lazy val ThrowableClass = getClassByName(sn.Throwable) lazy val UninitializedErrorClass = requiredClass[UninitializedFieldError] + lazy val NPEConstructor = getMemberMethod(NullPointerExceptionClass, nme.CONSTRUCTOR) suchThat (_.paramss.flatten.isEmpty) + lazy val UninitializedFieldConstructor = UninitializedErrorClass.primaryConstructor + // fundamental reference classes lazy val PartialFunctionClass = requiredClass[PartialFunction[_,_]] lazy val AbstractPartialFunctionClass = requiredClass[scala.runtime.AbstractPartialFunction[_,_]] @@ -335,14 +348,11 @@ trait Definitions extends api.StandardDefinitions { lazy val UnqualifiedOwners = UnqualifiedModules.toSet ++ UnqualifiedModules.map(_.moduleClass) lazy val PredefModule = requiredModule[scala.Predef.type] - lazy val PredefModuleClass = PredefModule.moduleClass - - def Predef_classOf = getMemberMethod(PredefModule, nme.classOf) - def Predef_identity = getMemberMethod(PredefModule, nme.identity) - def Predef_conforms = getMemberMethod(PredefModule, nme.conforms) - def Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) - def Predef_??? = getMemberMethod(PredefModule, nme.???) - def Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) + def Predef_classOf = getMemberMethod(PredefModule, nme.classOf) + def Predef_wrapRefArray = getMemberMethod(PredefModule, nme.wrapRefArray) + def Predef_wrapArray(tp: Type) = getMemberMethod(PredefModule, wrapArrayMethodName(tp)) + def Predef_??? = getMemberMethod(PredefModule, nme.???) + def Predef_implicitly = getMemberMethod(PredefModule, nme.implicitly) /** Is `sym` a member of Predef with the given name? * Note: DON't replace this by sym == Predef_conforms/etc, as Predef_conforms is a `def` @@ -358,7 +368,6 @@ trait Definitions extends api.StandardDefinitions { lazy val SpecializableModule = requiredModule[Specializable] lazy val GroupOfSpecializable = getMemberClass(SpecializableModule, tpnme.Group) - lazy val ConsoleModule = requiredModule[scala.Console.type] lazy val ScalaRunTimeModule = requiredModule[scala.runtime.ScalaRunTime.type] lazy val SymbolModule = requiredModule[scala.Symbol.type] lazy val Symbol_apply = getMemberMethod(SymbolModule, nme.apply) @@ -368,9 +377,7 @@ trait Definitions extends api.StandardDefinitions { def arrayLengthMethod = getMemberMethod(ScalaRunTimeModule, nme.array_length) def arrayCloneMethod = getMemberMethod(ScalaRunTimeModule, nme.array_clone) def ensureAccessibleMethod = getMemberMethod(ScalaRunTimeModule, nme.ensureAccessible) - def scalaRuntimeSameElements = getMemberMethod(ScalaRunTimeModule, nme.sameElements) def arrayClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayClass) - def arrayElementClassMethod = getMemberMethod(ScalaRunTimeModule, nme.arrayElementClass) // classes with special meanings lazy val StringAddClass = requiredClass[scala.runtime.StringAdd] @@ -381,11 +388,6 @@ trait Definitions extends api.StandardDefinitions { lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter] lazy val DelayedInitClass = requiredClass[scala.DelayedInit] def delayedInitMethod = getMemberMethod(DelayedInitClass, nme.delayedInit) - // a dummy value that communicates that a delayedInit call is compiler-generated - // from phase UnCurry to phase Constructors - // !!! This is not used anywhere (it was checked in that way.) - // def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg) - // .setInfo(UnitClass.tpe) lazy val TypeConstraintClass = requiredClass[scala.annotation.TypeConstraint] lazy val SingletonClass = enterNewClass(ScalaPackageClass, tpnme.Singleton, anyparam, ABSTRACT | TRAIT | FINAL) @@ -407,7 +409,8 @@ trait Definitions extends api.StandardDefinitions { def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass def isJavaRepeatedParamType(tp: Type) = tp.typeSymbol == JavaRepeatedParamClass def isRepeatedParamType(tp: Type) = isScalaRepeatedParamType(tp) || isJavaRepeatedParamType(tp) - def isRepeated(param: Symbol) = isRepeatedParamType(param.tpe) + def isRepeated(param: Symbol) = isRepeatedParamType(param.tpe_*) + def isByName(param: Symbol) = isByNameParamType(param.tpe_*) def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params) @@ -432,10 +435,6 @@ trait Definitions extends api.StandardDefinitions { case _ => tp } - def isPrimitiveArray(tp: Type) = tp match { - case TypeRef(_, ArrayClass, arg :: Nil) => isPrimitiveValueClass(arg.typeSymbol) - case _ => false - } def isReferenceArray(tp: Type) = tp match { case TypeRef(_, ArrayClass, arg :: Nil) => arg <:< AnyRefClass.tpe case _ => false @@ -445,11 +444,8 @@ trait Definitions extends api.StandardDefinitions { case _ => false } - lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy") - // collections classes lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]] - lazy val IterableClass = requiredClass[scala.collection.Iterable[_]] lazy val IteratorClass = requiredClass[scala.collection.Iterator[_]] lazy val ListClass = requiredClass[scala.collection.immutable.List[_]] lazy val SeqClass = requiredClass[scala.collection.Seq[_]] @@ -460,12 +456,12 @@ trait Definitions extends api.StandardDefinitions { lazy val List_apply = getMemberMethod(ListModule, nme.apply) lazy val NilModule = requiredModule[scala.collection.immutable.Nil.type] lazy val SeqModule = requiredModule[scala.collection.Seq.type] - lazy val IteratorModule = requiredModule[scala.collection.Iterator.type] - lazy val Iterator_apply = getMemberMethod(IteratorModule, nme.apply) // arrays and their members lazy val ArrayModule = requiredModule[scala.Array.type] lazy val ArrayModule_overloadedApply = getMemberMethod(ArrayModule, nme.apply) + def ArrayModule_genericApply = ArrayModule_overloadedApply.suchThat(_.paramss.flatten.last.tpe.typeSymbol == ClassTagClass) // [T: ClassTag](xs: T*): Array[T] + def ArrayModule_apply(tp: Type) = ArrayModule_overloadedApply.suchThat(_.tpe.resultType =:= arrayType(tp)) // (p1: AnyVal1, ps: AnyVal1*): Array[AnyVal1] lazy val ArrayClass = getRequiredClass("scala.Array") // requiredClass[scala.Array[_]] lazy val Array_apply = getMemberMethod(ArrayClass, nme.apply) lazy val Array_update = getMemberMethod(ArrayClass, nme.update) @@ -474,9 +470,7 @@ trait Definitions extends api.StandardDefinitions { // reflection / structural types lazy val SoftReferenceClass = requiredClass[java.lang.ref.SoftReference[_]] - lazy val WeakReferenceClass = requiredClass[java.lang.ref.WeakReference[_]] lazy val MethodClass = getClassByName(sn.MethodAsObject) - def methodClass_setAccessible = getMemberMethod(MethodClass, nme.setAccessible) lazy val EmptyMethodCacheClass = requiredClass[scala.runtime.EmptyMethodCache] lazy val MethodCacheClass = requiredClass[scala.runtime.MethodCache] def methodCache_find = getMemberMethod(MethodCacheClass, nme.find_) @@ -500,7 +494,6 @@ trait Definitions extends api.StandardDefinitions { lazy val ExprClass = if (ExprsClass != NoSymbol) getMemberClass(ExprsClass, tpnme.Expr) else NoSymbol def ExprSplice = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.splice) else NoSymbol def ExprValue = if (ExprsClass != NoSymbol) getMemberMethod(ExprClass, nme.value) else NoSymbol - lazy val ExprModule = if (ExprsClass != NoSymbol) getMemberModule(ExprsClass, nme.Expr) else NoSymbol lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]] lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]] @@ -526,7 +519,6 @@ trait Definitions extends api.StandardDefinitions { def MacroContextPrefix = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.prefix) else NoSymbol def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getTypeMember(MacroContextClass, tpnme.PrefixType) else NoSymbol def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol - def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl] lazy val StringContextClass = requiredClass[scala.StringContext] @@ -536,17 +528,19 @@ trait Definitions extends api.StandardDefinitions { lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature] // Option classes - lazy val OptionClass: ClassSymbol = requiredClass[Option[_]] - lazy val SomeClass: ClassSymbol = requiredClass[Some[_]] - lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type] - lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type] + lazy val OptionClass: ClassSymbol = requiredClass[Option[_]] + lazy val OptionModule: ModuleSymbol = requiredModule[scala.Option.type] + lazy val Option_apply = getMemberMethod(OptionModule, nme.apply) + lazy val SomeClass: ClassSymbol = requiredClass[Some[_]] + lazy val NoneModule: ModuleSymbol = requiredModule[scala.None.type] + lazy val SomeModule: ModuleSymbol = requiredModule[scala.Some.type] def compilerTypeFromTag(tt: ApiUniverse # WeakTypeTag[_]): Type = tt.in(rootMirror).tpe def compilerSymbolFromTag(tt: ApiUniverse # WeakTypeTag[_]): Symbol = tt.in(rootMirror).tpe.typeSymbol // The given symbol represents either String.+ or StringAdd.+ def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+ - def isArrowAssoc(sym: Symbol) = ArrowAssocClass.tpe.decls.toList contains sym + def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass // The given symbol is a method with the right name and signature to be a runnable java program. def isJavaMainMethod(sym: Symbol) = (sym.name == nme.main) && (sym.info match { @@ -556,12 +550,6 @@ trait Definitions extends api.StandardDefinitions { // The given class has a main method. def hasJavaMainMethod(sym: Symbol): Boolean = (sym.tpe member nme.main).alternatives exists isJavaMainMethod - def hasJavaMainMethod(path: String): Boolean = - hasJavaMainMethod(getModuleIfDefined(path)) - - def isOptionType(tp: Type) = tp.typeSymbol isSubClass OptionClass - def isSomeType(tp: Type) = tp.typeSymbol eq SomeClass - def isNoneType(tp: Type) = tp.typeSymbol eq NoneModule // Product, Tuple, Function, AbstractFunction private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = { @@ -584,7 +572,6 @@ trait Definitions extends api.StandardDefinitions { /** Creators for TupleN, ProductN, FunctionN. */ def tupleType(elems: List[Type]) = aritySpecificType(TupleClass, elems) - def productType(elems: List[Type]) = aritySpecificType(ProductClass, elems) def functionType(formals: List[Type], restpe: Type) = aritySpecificType(FunctionClass, formals, restpe) def abstractFunctionType(formals: List[Type], restpe: Type) = aritySpecificType(AbstractFunctionClass, formals, restpe) @@ -603,10 +590,6 @@ trait Definitions extends api.StandardDefinitions { else nme.genericWrapArray } - @deprecated("Use isTupleType", "2.10.0") - def isTupleTypeOrSubtype(tp: Type) = isTupleType(tp) - - def tupleField(n: Int, j: Int) = getMemberValue(TupleClass(n), nme.productAccessorName(j)) // NOTE: returns true for NoSymbol since it's included in the TupleClass array -- is this intensional? def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym) def isProductNClass(sym: Symbol) = ProductClass contains sym @@ -652,13 +635,8 @@ trait Definitions extends api.StandardDefinitions { def Product_iterator = getMemberMethod(ProductRootClass, nme.productIterator) def Product_productPrefix = getMemberMethod(ProductRootClass, nme.productPrefix) def Product_canEqual = getMemberMethod(ProductRootClass, nme.canEqual_) - // def Product_productElementName = getMemberMethod(ProductRootClass, nme.productElementName) def productProj(z:Symbol, j: Int): TermSymbol = getMemberValue(z, nme.productAccessorName(j)) - def productProj(n: Int, j: Int): TermSymbol = productProj(ProductClass(n), j) - - /** returns true if this type is exactly ProductN[T1,...,Tn], not some subclass */ - def isExactProductType(tp: Type): Boolean = isProductNClass(tp.typeSymbol) /** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */ def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNClass match { @@ -666,13 +644,16 @@ trait Definitions extends api.StandardDefinitions { case _ => Nil } + def dropNullaryMethod(tp: Type) = tp match { + case NullaryMethodType(restpe) => restpe + case _ => tp + } + def unapplyUnwrap(tpe:Type) = tpe.finalResultType.normalize match { case RefinedType(p :: _, _) => p.normalize case tp => tp } - def functionApply(n: Int) = getMemberMethod(FunctionClass(n), nme.apply) - def abstractFunctionForFunctionType(tp: Type) = if (isFunctionType(tp)) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last) else NoType @@ -690,8 +671,6 @@ trait Definitions extends api.StandardDefinitions { (sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass) } - def isSeqType(tp: Type) = elementType(SeqClass, tp.normalize) != NoType - def elementType(container: Symbol, tp: Type): Type = tp match { case TypeRef(_, `container`, arg :: Nil) => arg case _ => NoType @@ -704,10 +683,6 @@ trait Definitions extends api.StandardDefinitions { def optionType(tp: Type) = appliedType(OptionClass, tp) def scalaRepeatedType(arg: Type) = appliedType(RepeatedParamClass, arg) def seqType(arg: Type) = appliedType(SeqClass, arg) - def someType(tp: Type) = appliedType(SomeClass, tp) - - def StringArray = arrayType(StringClass.tpe) - lazy val ObjectArray = arrayType(ObjectClass.tpe) def ClassType(arg: Type) = if (phase.erasedTypes || forMSIL) ClassClass.tpe @@ -720,9 +695,6 @@ trait Definitions extends api.StandardDefinitions { // - .linkedClassOfClass: the ClassSymbol of the enumeration (class E) sym.owner.linkedClassOfClass.tpe - def vmClassType(arg: Type): Type = ClassType(arg) - def vmSignature(sym: Symbol, info: Type): String = signature(info) // !!! - /** Given a class symbol C with type parameters T1, T2, ... Tn * which have upper/lower bounds LB1/UB1, LB1/UB2, ..., LBn/UBn, * returns an existential type of the form @@ -730,26 +702,13 @@ trait Definitions extends api.StandardDefinitions { * C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... en >: LBn <: UBn }. */ def classExistentialType(clazz: Symbol): Type = - newExistentialType(clazz.typeParams, clazz.tpe) - - /** Given type U, creates a Type representing Class[_ <: U]. - */ - def boundedClassType(upperBound: Type) = - appliedTypeAsUpperBounds(ClassClass.typeConstructor, List(upperBound)) - - /** To avoid unchecked warnings on polymorphic classes, translate - * a Foo[T] into a Foo[_] for use in the pattern matcher. - */ - @deprecated("Use classExistentialType", "2.10.0") - def typeCaseType(clazz: Symbol): Type = classExistentialType(clazz) + newExistentialType(clazz.typeParams, clazz.tpe_*) // // .NET backend // lazy val ComparatorClass = getRequiredClass("scala.runtime.Comparator") - // System.ValueType - lazy val ValueTypeClass: ClassSymbol = getClassByName(sn.ValueType) // System.MulticastDelegate lazy val DelegateClass: ClassSymbol = getClassByName(sn.Delegate) var Delegate_scalaCallers: List[Symbol] = List() // Syncnote: No protection necessary yet as only for .NET where reflection is not supported. @@ -841,12 +800,7 @@ trait Definitions extends api.StandardDefinitions { else x :: removeRedundantObjects(xs) } - /** Order a list of types with non-trait classes before others. */ - def classesFirst(tps: List[Type]): List[Type] = { - val (classes, others) = tps partition (t => t.typeSymbol.isClass && !t.typeSymbol.isTrait) - if (classes.isEmpty || others.isEmpty || (tps startsWith classes)) tps - else classes ::: others - } + /** The following transformations applied to a list of parents. * If any parent is a class/trait, all parents which normalize to * Object are discarded. Otherwise, all parents which normalize @@ -859,6 +813,12 @@ trait Definitions extends api.StandardDefinitions { removeRedundantObjects(parents) } + /** Flatten curried parameter lists of a method type. */ + def allParameters(tpe: Type): List[Symbol] = tpe match { + case MethodType(params, res) => params ::: allParameters(res) + case _ => Nil + } + def typeStringNoPackage(tp: Type) = "" + tp stripPrefix tp.typeSymbol.enclosingPackage.fullName + "." @@ -868,10 +828,6 @@ trait Definitions extends api.StandardDefinitions { def parentsString(parents: List[Type]) = normalizedParents(parents) mkString " with " - def typeParamsString(tp: Type) = tp match { - case PolyType(tparams, _) => tparams map (_.defString) mkString ("[", ",", "]") - case _ => "" - } def valueParamsString(tp: Type) = tp match { case MethodType(params, _) => params map (_.defString) mkString ("(", ",", ")") case _ => "" @@ -883,8 +839,8 @@ trait Definitions extends api.StandardDefinitions { lazy val Object_!= = enterNewMethod(ObjectClass, nme.NE, anyrefparam, booltype, FINAL) lazy val Object_eq = enterNewMethod(ObjectClass, nme.eq, anyrefparam, booltype, FINAL) lazy val Object_ne = enterNewMethod(ObjectClass, nme.ne, anyrefparam, booltype, FINAL) - lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC)(_ => booltype) - lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC)(_.typeConstructor) + lazy val Object_isInstanceOf = newT1NoParamsMethod(ObjectClass, nme.isInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_ => booltype) + lazy val Object_asInstanceOf = newT1NoParamsMethod(ObjectClass, nme.asInstanceOf_Ob, FINAL | SYNTHETIC | ARTIFACT)(_.typeConstructor) lazy val Object_synchronized = newPolyMethod(1, ObjectClass, nme.synchronized_, FINAL)(tps => (Some(List(tps.head.typeConstructor)), tps.head.typeConstructor) ) @@ -908,12 +864,6 @@ trait Definitions extends api.StandardDefinitions { lazy val BoxedNumberClass = getClassByName(sn.BoxedNumber) lazy val BoxedCharacterClass = getClassByName(sn.BoxedCharacter) lazy val BoxedBooleanClass = getClassByName(sn.BoxedBoolean) - lazy val BoxedByteClass = requiredClass[java.lang.Byte] - lazy val BoxedShortClass = requiredClass[java.lang.Short] - lazy val BoxedIntClass = requiredClass[java.lang.Integer] - lazy val BoxedLongClass = requiredClass[java.lang.Long] - lazy val BoxedFloatClass = requiredClass[java.lang.Float] - lazy val BoxedDoubleClass = requiredClass[java.lang.Double] lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean) lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber) @@ -934,7 +884,6 @@ trait Definitions extends api.StandardDefinitions { lazy val ImplicitNotFoundClass = requiredClass[scala.annotation.implicitNotFound] lazy val MigrationAnnotationClass = requiredClass[scala.annotation.migration] lazy val ScalaStrictFPAttr = requiredClass[scala.annotation.strictfp] - lazy val SerializableAttr = requiredClass[scala.annotation.serializable] // @serializable is deprecated lazy val SwitchClass = requiredClass[scala.annotation.switch] lazy val TailrecClass = requiredClass[scala.annotation.tailrec] lazy val VarargsClass = requiredClass[scala.annotation.varargs] @@ -969,7 +918,6 @@ trait Definitions extends api.StandardDefinitions { lazy val ParamTargetClass = requiredClass[meta.param] lazy val SetterTargetClass = requiredClass[meta.setter] lazy val ClassTargetClass = requiredClass[meta.companionClass] - lazy val ObjectTargetClass = requiredClass[meta.companionObject] lazy val MethodTargetClass = requiredClass[meta.companionMethod] // TODO: module, moduleClass? package, packageObject? lazy val LanguageFeatureAnnot = requiredClass[meta.languageFeature] @@ -1014,7 +962,6 @@ trait Definitions extends api.StandardDefinitions { def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule): Symbol = getMember(owner, newTypeName(name)) def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name)) - def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name)) def findNamedMember(fullName: Name, root: Symbol): Symbol = { val segs = nme.segments(fullName.toString, fullName.isTermName) @@ -1054,7 +1001,6 @@ trait Definitions extends api.StandardDefinitions { } } def getMemberClass(owner: Symbol, name: Name): ClassSymbol = { - val y = getMember(owner, name.toTypeName) getMember(owner, name.toTypeName) match { case x: ClassSymbol => x case _ => fatalMissingSymbol(owner, name, "member class") @@ -1082,9 +1028,6 @@ trait Definitions extends api.StandardDefinitions { def getDeclIfDefined(owner: Symbol, name: Name): Symbol = owner.info.nonPrivateDecl(name) - def packageExists(packageName: String): Boolean = - getModuleIfDefined(packageName).isPackage - private def newAlias(owner: Symbol, name: TypeName, alias: Type): AliasTypeSymbol = owner.newAliasType(name) setInfoAndEnter alias @@ -1116,7 +1059,6 @@ trait Definitions extends api.StandardDefinitions { newPolyMethod(1, owner, name, flags)(tparams => (Some(Nil), createFn(tparams.head))) } - lazy val boxedClassValues = boxedClass.values.toSet[Symbol] lazy val isUnbox = unboxMethod.values.toSet[Symbol] lazy val isBox = boxMethod.values.toSet[Symbol] @@ -1176,8 +1118,6 @@ trait Definitions extends api.StandardDefinitions { /** Is symbol a value class? */ def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym - def isNonUnitValueClass(sym: Symbol) = isPrimitiveValueClass(sym) && (sym != UnitClass) - def isSpecializableClass(sym: Symbol) = isPrimitiveValueClass(sym) || (sym == AnyRefClass) def isPrimitiveValueType(tp: Type) = isPrimitiveValueClass(tp.typeSymbol) /** Is symbol a boxed value class, e.g. java.lang.Integer? */ @@ -1218,21 +1158,10 @@ trait Definitions extends api.StandardDefinitions { else flatNameString(etp.typeSymbol, '.') } - /** Surgery on the value classes. Without this, AnyVals defined in source - * files end up with an AnyRef parent. It is likely there is a better way - * to evade that AnyRef. - */ - private def setParents(sym: Symbol, parents: List[Type]): Symbol = sym.rawInfo match { - case ClassInfoType(_, scope, clazz) => - sym setInfo ClassInfoType(parents, scope, clazz) - case _ => - sym - } - def init() { if (isInitialized) return // force initialization of every symbol that is synthesized or hijacked by the compiler - val forced = symbolsNotPresentInBytecode + val _ = symbolsNotPresentInBytecode isInitialized = true } //init @@ -1253,11 +1182,6 @@ trait Definitions extends api.StandardDefinitions { newCaller } - // def addScalaCallerInfo(scalaCaller: Symbol, methSym: Symbol, delType: Type) { - // assert(Delegate_scalaCallers contains scalaCaller) - // Delegate_scalaCallerInfos += (scalaCaller -> (methSym, delType)) - // } - def addScalaCallerInfo(scalaCaller: Symbol, methSym: Symbol) { assert(Delegate_scalaCallers contains scalaCaller) Delegate_scalaCallerTargets += (scalaCaller -> methSym) diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index 59c027868e..2a0fe9d19a 100644 --- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala @@ -7,7 +7,6 @@ package scala.reflect package internal import scala.collection.{ mutable, immutable } -import util._ /** The name of this trait defines the eventual intent better than * it does the initial contents. diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index 30dd9c3e49..61906740a0 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -116,6 +116,20 @@ class ModifierFlags { final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer final val PRESUPER = 1L << 37 // value is evaluated before super call final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit + final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode + + /** Symbols which are marked ARTIFACT. (Expand this list?) + * + * - $outer fields and accessors + * - super accessors + * - protected accessors + * - lazy local accessors + * - bridge methods + * - default argument getters + * - evaluation-order preserving locals for right-associative and out-of-order named arguments + * - catch-expression storing vals + * - anything else which feels a setFlag(ARTIFACT) + */ // Overridden. def flagToString(flag: Long): String = "" @@ -165,7 +179,6 @@ class Flags extends ModifierFlags { // A Java method's type is ``cooked'' by transforming raw types to existentials final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED - final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode // ------- shift definitions ------------------------------------------------------- @@ -248,7 +261,7 @@ class Flags extends ModifierFlags { /** These modifiers appear in TreePrinter output. */ final val PrintableFlags = ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO | - ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED + ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED | ARTIFACT /** When a symbol for a field is created, only these flags survive * from Modifiers. Others which may be applied at creation time are: @@ -420,7 +433,7 @@ class Flags extends ModifierFlags { case VARARGS => "<varargs>" // (1L << 43) case TRIEDCOOKING => "<triedcooking>" // (1L << 44) case SYNCHRONIZED => "<synchronized>" // (1L << 45) - case 0x400000000000L => "" // (1L << 46) + case ARTIFACT => "<artifact>" // (1L << 46) case 0x800000000000L => "" // (1L << 47) case 0x1000000000000L => "" // (1L << 48) case 0x2000000000000L => "" // (1L << 49) diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index 4a3663b8ea..6f8befd23e 100644 --- a/src/reflect/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -158,13 +158,14 @@ trait HasFlags { else nonAccess + " " + access } + // Guess this can't be deprecated seeing as it's in the reflect API. + def isParameter = hasFlag(PARAM) + // Backward compat section @deprecated( "Use isTrait", "2.10.0") def hasTraitFlag = hasFlag(TRAIT) @deprecated("Use hasDefault", "2.10.0") def hasDefaultFlag = hasFlag(DEFAULTPARAM) - @deprecated("Use isValueParameter or isTypeParameter", "2.10.0") - def isParameter = hasFlag(PARAM) @deprecated("Use flagString", "2.10.0") def defaultFlagString = flagString @deprecated("Use flagString(mask)", "2.10.0") diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 43902c1930..6ad9a63822 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -316,7 +316,6 @@ trait Importers extends api.Importers { self: SymbolTable => def importName(name: from.Name): Name = if (name.isTypeName) newTypeName(name.toString) else newTermName(name.toString) def importTypeName(name: from.TypeName): TypeName = importName(name).toTypeName - def importTermName(name: from.TermName): TermName = importName(name).toTermName def importModifiers(mods: from.Modifiers): Modifiers = new Modifiers(mods.flags, importName(mods.privateWithin), mods.annotations map importTree) @@ -427,17 +426,17 @@ trait Importers extends api.Importers { self: SymbolTable => } addFixup({ if (mytree != null) { - val mysym = if (tree.hasSymbol) importSymbol(tree.symbol) else NoSymbol + val mysym = if (tree.hasSymbolField) importSymbol(tree.symbol) else NoSymbol val mytpe = importType(tree.tpe) mytree match { case mytt: TypeTree => val tt = tree.asInstanceOf[from.TypeTree] - if (mytree.hasSymbol) mytt.symbol = mysym + if (mytree.hasSymbolField) mytt.symbol = mysym if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe) if (tt.original != null) mytt.setOriginal(importTree(tt.original)) case _ => - if (mytree.hasSymbol) mytree.symbol = importSymbol(tree.symbol) + if (mytree.hasSymbolField) mytree.symbol = importSymbol(tree.symbol) mytree.tpe = importType(tree.tpe) } } diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala index 0beb8e368f..80aa06d020 100644 --- a/src/reflect/scala/reflect/internal/Mirrors.scala +++ b/src/reflect/scala/reflect/internal/Mirrors.scala @@ -19,6 +19,8 @@ trait Mirrors extends api.Mirrors { trait RootSymbol extends Symbol { def mirror: Mirror } abstract class RootsBase(rootOwner: Symbol) extends scala.reflect.api.Mirror[Mirrors.this.type] { thisMirror => + private[this] var initialized = false + def isMirrorInitialized = initialized protected[scala] def rootLoader: LazyType @@ -40,7 +42,7 @@ trait Mirrors extends api.Mirrors { if (point > 0) getModuleOrClass(path.toTermName, point) else RootClass val name = path subName (point + 1, len) - var sym = owner.info member name + val sym = owner.info member name val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym if (result != NoSymbol) result else { @@ -76,7 +78,9 @@ trait Mirrors extends api.Mirrors { protected def universeMissingHook(owner: Symbol, name: Name): Symbol = thisUniverse.missingHook(owner, name) - private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name) + private[scala] def missingHook(owner: Symbol, name: Name): Symbol = logResult(s"missingHook($owner, $name)")( + mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name) + ) // todo: get rid of most the methods here and keep just staticClass/Module/Package @@ -228,6 +232,7 @@ trait Mirrors extends api.Mirrors { // } def init() { + if (initialized) return // Still fiddling with whether it's cleaner to do some of this setup here // or from constructors. The latter approach tends to invite init order issues. @@ -239,6 +244,8 @@ trait Mirrors extends api.Mirrors { RootClass.info.decls enter EmptyPackage RootClass.info.decls enter RootPackage + + initialized = true } } diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index c78ba72dfb..333651162e 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -135,9 +135,6 @@ trait Names extends api.Names with LowPriorityNames { def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName = newTermName(bs, offset, len).toTypeName - def nameChars: Array[Char] = chrs - @deprecated("", "2.9.0") def view(s: String): TermName = newTermName(s) - // Classes ---------------------------------------------------------------------- /** The name class. @@ -186,28 +183,20 @@ trait Names extends api.Names with LowPriorityNames { scala.compat.Platform.arraycopy(chrs, index, cs, offset, len) /** @return the ascii representation of this name */ - final def toChars: Array[Char] = { + final def toChars: Array[Char] = { // used by ide val cs = new Array[Char](len) copyChars(cs, 0) cs } - /** Write to UTF8 representation of this name to given character array. - * Start copying to index `to`. Return index of next free byte in array. - * Array must have enough remaining space for all bytes - * (i.e. maximally 3*length bytes). - */ - final def copyUTF8(bs: Array[Byte], offset: Int): Int = { - val bytes = Codec.toUTF8(chrs, index, len) - scala.compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length) - offset + bytes.length - } - /** @return the hash value of this name */ final override def hashCode(): Int = index - // Presently disabled. - // override def equals(other: Any) = paranoidEquals(other) + /**** + * This has been quite useful to find places where people are comparing + * a TermName and a TypeName, or a Name and a String. + + override def equals(other: Any) = paranoidEquals(other) private def paranoidEquals(other: Any): Boolean = { val cmp = this eq other.asInstanceOf[AnyRef] if (cmp || !nameDebug) @@ -215,7 +204,7 @@ trait Names extends api.Names with LowPriorityNames { other match { case x: String => - Console.println("Compared " + debugString + " and String '" + x + "'") + Console.println(s"Compared $debugString and String '$x'") case x: Name => if (this.isTermName != x.isTermName) { val panic = this.toTermName == x.toTermName @@ -228,6 +217,7 @@ trait Names extends api.Names with LowPriorityNames { } false } + ****/ /** @return the i'th Char of this name */ final def charAt(i: Int): Char = chrs(index + i) @@ -279,8 +269,6 @@ trait Names extends api.Names with LowPriorityNames { */ final def lastPos(c: Char): Int = lastPos(c, len - 1) - final def lastPos(s: String): Int = lastPos(s, len - s.length) - /** Returns the index of the last occurrence of char c in this * name from start, -1 if not found. * @@ -294,26 +282,6 @@ trait Names extends api.Names with LowPriorityNames { i } - /** Returns the index of the last occurrence of string s in this - * name from start, -1 if not found. - * - * @param s the string - * @param start ... - * @return the index of the last occurrence of s - */ - final def lastPos(s: String, start: Int): Int = { - var i = lastPos(s.charAt(0), start) - while (i >= 0) { - var j = 1; - while (s.charAt(j) == chrs(index + i + j)) { - j += 1 - if (j == s.length()) return i; - } - i = lastPos(s.charAt(0), i - 1) - } - -s.length() - } - /** Does this name start with prefix? */ final def startsWith(prefix: Name): Boolean = startsWith(prefix, 0) @@ -375,7 +343,6 @@ trait Names extends api.Names with LowPriorityNames { if (idx == length) -1 else idx } def lastIndexOf(ch: Char) = lastPos(ch) - def lastIndexOf(ch: Char, fromIndex: Int) = lastPos(ch, fromIndex) /** Replace all occurrences of `from` by `to` in * name; result is always a term name. @@ -424,12 +391,10 @@ trait Names extends api.Names with LowPriorityNames { def append(ch: Char) = newName("" + this + ch) def append(suffix: String) = newName("" + this + suffix) def append(suffix: Name) = newName("" + this + suffix) - def prepend(ch: Char) = newName("" + ch + this) def prepend(prefix: String) = newName("" + prefix + this) - def prepend(prefix: Name) = newName("" + prefix + this) def decodedName: ThisNameType = newName(decode) - def isOperatorName: Boolean = decode != toString + def isOperatorName: Boolean = decode != toString // used by ide def longString: String = nameKind + " " + decode def debugString = { val s = decode ; if (isTypeName) s + "!" else s } } @@ -441,7 +406,6 @@ trait Names extends api.Names with LowPriorityNames { def stripSuffix(suffix: Name): T = if (name endsWith suffix) dropRight(suffix.length) else name def dropRight(n: Int): T = name.subName(0, name.length - n).asInstanceOf[T] def drop(n: Int): T = name.subName(n, name.length).asInstanceOf[T] - def nonEmpty: Boolean = name.length > 0 } implicit val NameTag = ClassTag[Name](classOf[Name]) @@ -485,7 +449,7 @@ trait Names extends api.Names with LowPriorityNames { type ThisNameType = TermName protected[this] def thisName: TermName = this - var next: TermName = termHashtable(hash) + val next: TermName = termHashtable(hash) termHashtable(hash) = this def isTermName: Boolean = true def isTypeName: Boolean = false @@ -514,7 +478,7 @@ trait Names extends api.Names with LowPriorityNames { type ThisNameType = TypeName protected[this] def thisName: TypeName = this - var next: TypeName = typeHashtable(hash) + val next: TypeName = typeHashtable(hash) typeHashtable(hash) = this def isTermName: Boolean = false def isTypeName: Boolean = true diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 80d247c0ea..c36724e388 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -168,7 +168,7 @@ trait Printers extends api.Printers { self: SymbolTable => ) def printFlags(flags: Long, privateWithin: String) { - var mask: Long = if (settings.debug.value) -1L else PrintableFlags + val mask: Long = if (settings.debug.value) -1L else PrintableFlags val s = flagsToString(flags & mask, privateWithin) if (s != "") print(s + " ") } @@ -475,8 +475,6 @@ trait Printers extends api.Printers { self: SymbolTable => } def newRawTreePrinter(writer: PrintWriter): RawTreePrinter = new RawTreePrinter(writer) - def newRawTreePrinter(stream: OutputStream): RawTreePrinter = newRawTreePrinter(new PrintWriter(stream)) - def newRawTreePrinter(): RawTreePrinter = newRawTreePrinter(new PrintWriter(ConsoleWriter)) // provides footnotes for types and mirrors import scala.collection.mutable.{Map, WeakHashMap, SortedSet} @@ -525,7 +523,7 @@ trait Printers extends api.Printers { self: SymbolTable => private var depth = 0 private var printTypesInFootnotes = true private var printingFootnotes = false - private var footnotes = footnoteIndex.mkFootnotes() + private val footnotes = footnoteIndex.mkFootnotes() def print(args: Any*): Unit = { // don't print type footnotes if the argument is a mere type @@ -545,8 +543,8 @@ trait Printers extends api.Printers { self: SymbolTable => case emptyValDef: AnyRef if emptyValDef eq self.emptyValDef => print("emptyValDef") case tree: Tree => - val hasSymbol = tree.hasSymbol && tree.symbol != NoSymbol - val isError = hasSymbol && tree.symbol.name.toString == nme.ERROR.toString + val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol + val isError = hasSymbolField && tree.symbol.name.toString == nme.ERROR.toString printProduct( tree, preamble = _ => { @@ -559,7 +557,7 @@ trait Printers extends api.Printers { self: SymbolTable => if (isError) print("<") print(name) if (isError) print(": error>") - } else if (hasSymbol) { + } else if (hasSymbolField) { tree match { case refTree: RefTree => if (tree.symbol.name != refTree.name) print("[", tree.symbol, " aka ", refTree.name, "]") diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index ab3b9b7ed7..04f1d73360 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -8,6 +8,14 @@ package internal trait Scopes extends api.Scopes { self: SymbolTable => + /** An ADT to represent the results of symbol name lookups. + */ + sealed trait NameLookup { def symbol: Symbol } + case class LookupSucceeded(qualifier: Tree, symbol: Symbol) extends NameLookup + case class LookupAmbiguous(msg: String) extends NameLookup { def symbol = NoSymbol } + case class LookupInaccessible(symbol: Symbol, msg: String) extends NameLookup + case object LookupNotFound extends NameLookup { def symbol = NoSymbol } + class ScopeEntry(val sym: Symbol, val owner: Scope) { /** the next entry in the hash bucket */ @@ -17,15 +25,11 @@ trait Scopes extends api.Scopes { self: SymbolTable => */ var next: ScopeEntry = null + def depth = owner.nestingLevel override def hashCode(): Int = sym.name.start - override def toString(): String = sym.toString() + override def toString() = s"$sym (depth=$depth)" } - /** - * @param sym ... - * @param owner ... - * @return ... - */ private def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = { val e = new ScopeEntry(sym, owner) e.next = owner.elems @@ -92,8 +96,6 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** enter a scope entry - * - * @param e ... */ protected def enterEntry(e: ScopeEntry) { elemsCache = null @@ -110,8 +112,6 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** enter a symbol - * - * @param sym ... */ def enter[T <: Symbol](sym: T): T = { enterEntry(newScopeEntry(sym, this)) @@ -119,8 +119,6 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** enter a symbol, asserting that no symbol with same name exists in scope - * - * @param sym ... */ def enterUnique(sym: Symbol) { assert(lookup(sym.name) == NoSymbol, (sym.fullLocationString, lookup(sym.name).fullLocationString)) @@ -175,8 +173,6 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** remove entry - * - * @param e ... */ def unlink(e: ScopeEntry) { if (elems == e) { @@ -208,14 +204,48 @@ trait Scopes extends api.Scopes { self: SymbolTable => } } - /** lookup a symbol - * - * @param name ... - * @return ... + /** Lookup a module or a class, filtering out matching names in scope + * which do not match that requirement. + */ + def lookupModule(name: Name): Symbol = lookupAll(name.toTermName) find (_.isModule) getOrElse NoSymbol + def lookupClass(name: Name): Symbol = lookupAll(name.toTypeName) find (_.isClass) getOrElse NoSymbol + + /** True if the name exists in this scope, false otherwise. */ + def containsName(name: Name) = lookupEntry(name) != null + + /** Lookup a symbol. */ def lookup(name: Name): Symbol = { val e = lookupEntry(name) - if (e eq null) NoSymbol else e.sym + if (e eq null) NoSymbol + else if (lookupNextEntry(e) eq null) e.sym + else { + // We shouldn't get here: until now this method was picking a random + // symbol when there was more than one with the name, so this should + // only be called knowing that there are 0-1 symbols of interest. So, we + // can safely return an overloaded symbol rather than throwing away the + // rest of them. Most likely we still break, but at least we will break + // in an understandable fashion (unexpectedly overloaded symbol) rather + // than a non-deterministic bizarre one (see any bug involving overloads + // in package objects.) + val alts = lookupAll(name).toList + def alts_s = alts map (s => s.defString) mkString " <and> " + devWarning(s"scope lookup of $name found multiple symbols: $alts_s") + // FIXME - how is one supposed to create an overloaded symbol without + // knowing the correct owner? Using the symbol owner is not correct; + // say for instance this is List's scope and the symbols are its three + // mkString members. Those symbols are owned by TraversableLike, which + // is no more meaningful an owner than NoSymbol given that we're in + // List. Maybe it makes no difference who owns the overloaded symbol, in + // which case let's establish that and have a canonical creation method. + // + // FIXME - a similar question for prefix, although there are more + // clues from the symbols on that one, as implemented here. In general + // the distinct list is one type and lub becomes the identity. + // val prefix = lub(alts map (_.info.prefix) distinct) + // Now using NoSymbol and NoPrefix always to avoid forcing info (SI-6664) + NoSymbol.newOverloaded(NoPrefix, alts) + } } /** Returns an iterator yielding every symbol with given name in this scope. @@ -223,7 +253,20 @@ trait Scopes extends api.Scopes { self: SymbolTable => def lookupAll(name: Name): Iterator[Symbol] = new Iterator[Symbol] { var e = lookupEntry(name) def hasNext: Boolean = e ne null - def next(): Symbol = { val r = e.sym; e = lookupNextEntry(e); r } + def next(): Symbol = try e.sym finally e = lookupNextEntry(e) + } + + def lookupAllEntries(name: Name): Iterator[ScopeEntry] = new Iterator[ScopeEntry] { + var e = lookupEntry(name) + def hasNext: Boolean = e ne null + def next(): ScopeEntry = try e finally e = lookupNextEntry(e) + } + + def lookupUnshadowedEntries(name: Name): Iterator[ScopeEntry] = { + lookupEntry(name) match { + case null => Iterator.empty + case e => lookupAllEntries(name) filter (e1 => (e eq e1) || (e.depth == e1.depth && e.sym != e1.sym)) + } } /** lookup a symbol entry matching given name. @@ -287,36 +330,16 @@ trait Scopes extends api.Scopes { self: SymbolTable => */ def iterator: Iterator[Symbol] = toList.iterator -/* - /** Does this scope contain an entry for `sym`? - */ - def contains(sym: Symbol): Boolean = lookupAll(sym.name) contains sym - - /** A scope that contains all symbols of this scope and that also contains `sym`. - */ - def +(sym: Symbol): Scope = - if (contains(sym)) this - else { - val result = cloneScope - result enter sym - result - } - - /** A scope that contains all symbols of this scope except `sym`. - */ - def -(sym: Symbol): Scope = - if (!contains(sym)) this - else { - val result = cloneScope - result unlink sym - result - } -*/ override def foreach[U](p: Symbol => U): Unit = toList foreach p - override def filter(p: Symbol => Boolean): Scope = - if (!(toList forall p)) newScopeWith(toList filter p: _*) else this - + override def filterNot(p: Symbol => Boolean): Scope = ( + if (toList exists p) newScopeWith(toList filterNot p: _*) + else this + ) + override def filter(p: Symbol => Boolean): Scope = ( + if (toList forall p) this + else newScopeWith(toList filter p: _*) + ) @deprecated("Use `toList.reverse` instead", "2.10.0") def reverse: List[Symbol] = toList.reverse diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 5e7f5777b2..a5810c9c83 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -104,7 +104,6 @@ trait StdNames { val IMPORT: NameType = "<import>" val MODULE_SUFFIX_NAME: NameType = MODULE_SUFFIX_STRING val MODULE_VAR_SUFFIX: NameType = "$module" - val NAME_JOIN_NAME: NameType = NAME_JOIN_STRING val PACKAGE: NameType = "package" val ROOT: NameType = "<root>" val SPECIALIZED_SUFFIX: NameType = "$sp" @@ -121,16 +120,12 @@ trait StdNames { final val Short: NameType = "Short" final val Unit: NameType = "Unit" - final val ScalaValueNames: scala.List[NameType] = - scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit) - // some types whose companions we utilize final val AnyRef: NameType = "AnyRef" final val Array: NameType = "Array" final val List: NameType = "List" final val Seq: NameType = "Seq" final val Symbol: NameType = "Symbol" - final val ClassTag: NameType = "ClassTag" final val WeakTypeTag: NameType = "WeakTypeTag" final val TypeTag : NameType = "TypeTag" final val Expr: NameType = "Expr" @@ -220,12 +215,10 @@ trait StdNames { final val Any: NameType = "Any" final val AnyVal: NameType = "AnyVal" - final val ExprApi: NameType = "ExprApi" final val Mirror: NameType = "Mirror" final val Nothing: NameType = "Nothing" final val Null: NameType = "Null" final val Object: NameType = "Object" - final val PartialFunction: NameType = "PartialFunction" final val PrefixType: NameType = "PrefixType" final val Product: NameType = "Product" final val Serializable: NameType = "Serializable" @@ -239,7 +232,6 @@ trait StdNames { final val Group: NameType = "Group" final val Tree: NameType = "Tree" final val Type : NameType = "Type" - final val TypeTree: NameType = "TypeTree" // Annotation simple names, used in Namer final val BeanPropertyAnnot: NameType = "BeanProperty" @@ -249,13 +241,11 @@ trait StdNames { // Classfile Attributes final val AnnotationDefaultATTR: NameType = "AnnotationDefault" final val BridgeATTR: NameType = "Bridge" - final val ClassfileAnnotationATTR: NameType = "RuntimeInvisibleAnnotations" // RetentionPolicy.CLASS. Currently not used (Apr 2009). final val CodeATTR: NameType = "Code" final val ConstantValueATTR: NameType = "ConstantValue" final val DeprecatedATTR: NameType = "Deprecated" final val ExceptionsATTR: NameType = "Exceptions" final val InnerClassesATTR: NameType = "InnerClasses" - final val LineNumberTableATTR: NameType = "LineNumberTable" final val LocalVariableTableATTR: NameType = "LocalVariableTable" final val RuntimeAnnotationATTR: NameType = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME final val RuntimeParamAnnotationATTR: NameType = "RuntimeVisibleParameterAnnotations" // RetentionPolicy.RUNTIME (annotations on parameters) @@ -284,9 +274,6 @@ trait StdNames { val EXCEPTION_RESULT_PREFIX = "exceptionResult" val EXPAND_SEPARATOR_STRING = "$$" val INTERPRETER_IMPORT_WRAPPER = "$iw" - val INTERPRETER_LINE_PREFIX = "line" - val INTERPRETER_VAR_PREFIX = "res" - val INTERPRETER_WRAPPER_SUFFIX = "$object" val LOCALDUMMY_PREFIX = "<local " // owner of local blocks val PROTECTED_PREFIX = "protected$" val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set" @@ -304,7 +291,6 @@ trait StdNames { val LAZY_SLOW_SUFFIX: NameType = "$lzycompute" val LOCAL_SUFFIX_STRING = " " val UNIVERSE_BUILD_PREFIX: NameType = "$u.build." - val UNIVERSE_BUILD: NameType = "$u.build" val UNIVERSE_PREFIX: NameType = "$u." val UNIVERSE_SHORT: NameType = "$u" val MIRROR_PREFIX: NameType = "$m." @@ -339,7 +325,6 @@ trait StdNames { def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX) def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX - def isSuperAccessorName(name: Name) = name startsWith SUPER_PREFIX_STRING def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER def isSetterName(name: Name) = name endsWith SETTER_SUFFIX def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING) @@ -356,11 +341,6 @@ trait StdNames { ) } - def isDeprecatedIdentifierName(name: Name) = name.toTermName match { - case nme.`then` | nme.`macro` => true - case _ => false - } - def isOpAssignmentName(name: Name) = name match { case raw.NE | raw.LE | raw.GE | EMPTY => false case _ => @@ -395,18 +375,6 @@ trait StdNames { else name ) - /* - def anonNumberSuffix(name: Name): Name = { - ("" + name) lastIndexOf '$' match { - case -1 => nme.EMPTY - case idx => - val s = name drop idx - if (s.toString forall (_.isDigit)) s - else nme.EMPTY - } - } - */ - /** Return the original name and the types on which this name * is specialized. For example, * {{{ @@ -458,18 +426,6 @@ trait StdNames { } else name.toTermName } - // If the name ends with $nn where nn are - // all digits, strip the $ and the digits. - // Otherwise return the argument. - def stripAnonNumberSuffix(name: Name): Name = { - var pos = name.length - while (pos > 0 && name.charAt(pos - 1).isDigit) - pos -= 1 - - if (pos <= 0 || pos == name.length || name.charAt(pos - 1) != '$') name - else name.subName(0, pos - 1) - } - def stripModuleSuffix(name: Name): Name = ( if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name ) @@ -484,8 +440,6 @@ trait StdNames { final val Nil: NameType = "Nil" final val Predef: NameType = "Predef" - final val ScalaRunTime: NameType = "ScalaRunTime" - final val Some: NameType = "Some" val _1 : NameType = "_1" val _2 : NameType = "_2" @@ -581,14 +535,10 @@ trait StdNames { val Annotation: NameType = "Annotation" val Any: NameType = "Any" val AnyVal: NameType = "AnyVal" - val AppliedTypeTree: NameType = "AppliedTypeTree" - val Apply: NameType = "Apply" val ArrayAnnotArg: NameType = "ArrayAnnotArg" - val Constant: NameType = "Constant" val ConstantType: NameType = "ConstantType" val EmptyPackage: NameType = "EmptyPackage" val EmptyPackageClass: NameType = "EmptyPackageClass" - val ExistentialTypeTree: NameType = "ExistentialTypeTree" val Flag : NameType = "Flag" val Ident: NameType = "Ident" val Import: NameType = "Import" @@ -597,10 +547,8 @@ trait StdNames { val Modifiers: NameType = "Modifiers" val NestedAnnotArg: NameType = "NestedAnnotArg" val NoFlags: NameType = "NoFlags" - val NoPrefix: NameType = "NoPrefix" val NoSymbol: NameType = "NoSymbol" val Nothing: NameType = "Nothing" - val NoType: NameType = "NoType" val Null: NameType = "Null" val Object: NameType = "Object" val RootPackage: NameType = "RootPackage" @@ -609,17 +557,14 @@ trait StdNames { val StringContext: NameType = "StringContext" val This: NameType = "This" val ThisType: NameType = "ThisType" - val Tree : NameType = "Tree" val Tuple2: NameType = "Tuple2" val TYPE_ : NameType = "TYPE" - val TypeApply: NameType = "TypeApply" val TypeRef: NameType = "TypeRef" val TypeTree: NameType = "TypeTree" val UNIT : NameType = "UNIT" val add_ : NameType = "add" val annotation: NameType = "annotation" val anyValClass: NameType = "anyValClass" - val append: NameType = "append" val apply: NameType = "apply" val applyDynamic: NameType = "applyDynamic" val applyDynamicNamed: NameType = "applyDynamicNamed" @@ -627,34 +572,24 @@ trait StdNames { val args : NameType = "args" val argv : NameType = "argv" val arrayClass: NameType = "arrayClass" - val arrayElementClass: NameType = "arrayElementClass" - val arrayValue: NameType = "arrayValue" val array_apply : NameType = "array_apply" val array_clone : NameType = "array_clone" val array_length : NameType = "array_length" val array_update : NameType = "array_update" - val arraycopy: NameType = "arraycopy" - val asTerm: NameType = "asTerm" val asModule: NameType = "asModule" - val asMethod: NameType = "asMethod" val asType: NameType = "asType" - val asClass: NameType = "asClass" val asInstanceOf_ : NameType = "asInstanceOf" val asInstanceOf_Ob : NameType = "$asInstanceOf" - val assert_ : NameType = "assert" - val assume_ : NameType = "assume" val box: NameType = "box" val build : NameType = "build" val bytes: NameType = "bytes" val canEqual_ : NameType = "canEqual" val checkInitialized: NameType = "checkInitialized" - val ClassManifestFactory: NameType = "ClassManifestFactory" val classOf: NameType = "classOf" val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure val conforms: NameType = "conforms" val copy: NameType = "copy" val currentMirror: NameType = "currentMirror" - val definitions: NameType = "definitions" val delayedInit: NameType = "delayedInit" val delayedInitArg: NameType = "delayedInit$body" val drop: NameType = "drop" @@ -667,7 +602,6 @@ trait StdNames { val equalsNumObject : NameType = "equalsNumObject" val equals_ : NameType = if (forMSIL) "Equals" else "equals" val error: NameType = "error" - val eval: NameType = "eval" val ex: NameType = "ex" val experimental: NameType = "experimental" val f: NameType = "f" @@ -678,17 +612,11 @@ trait StdNames { val flagsFromBits : NameType = "flagsFromBits" val flatMap: NameType = "flatMap" val foreach: NameType = "foreach" - val genericArrayOps: NameType = "genericArrayOps" val get: NameType = "get" - val getOrElse: NameType = "getOrElse" - val hasNext: NameType = "hasNext" val hashCode_ : NameType = if (forMSIL) "GetHashCode" else "hashCode" val hash_ : NameType = "hash" - val head: NameType = "head" - val identity: NameType = "identity" val implicitly: NameType = "implicitly" val in: NameType = "in" - val info: NameType = "info" val inlinedEquals: NameType = "inlinedEquals" val isArray: NameType = "isArray" val isDefinedAt: NameType = "isDefinedAt" @@ -700,57 +628,42 @@ trait StdNames { val lang: NameType = "lang" val length: NameType = "length" val lengthCompare: NameType = "lengthCompare" - val liftedTree: NameType = "liftedTree" - val `macro` : NameType = "macro" - val macroThis : NameType = "_this" val macroContext : NameType = "c" val main: NameType = "main" - val manifest: NameType = "manifest" - val ManifestFactory: NameType = "ManifestFactory" val manifestToTypeTag: NameType = "manifestToTypeTag" val map: NameType = "map" val materializeClassTag: NameType = "materializeClassTag" val materializeWeakTypeTag: NameType = "materializeWeakTypeTag" val materializeTypeTag: NameType = "materializeTypeTag" - val mirror : NameType = "mirror" val moduleClass : NameType = "moduleClass" - val name: NameType = "name" val ne: NameType = "ne" val newArray: NameType = "newArray" val newFreeTerm: NameType = "newFreeTerm" val newFreeType: NameType = "newFreeType" val newNestedSymbol: NameType = "newNestedSymbol" val newScopeWith: NameType = "newScopeWith" - val next: NameType = "next" val nmeNewTermName: NameType = "newTermName" val nmeNewTypeName: NameType = "newTypeName" - val normalize: NameType = "normalize" val notifyAll_ : NameType = "notifyAll" val notify_ : NameType = "notify" val null_ : NameType = "null" - val ofDim: NameType = "ofDim" - val origin: NameType = "origin" val prefix : NameType = "prefix" val productArity: NameType = "productArity" val productElement: NameType = "productElement" val productIterator: NameType = "productIterator" val productPrefix: NameType = "productPrefix" val readResolve: NameType = "readResolve" - val reflect : NameType = "reflect" val reify : NameType = "reify" val rootMirror : NameType = "rootMirror" - val runOrElse: NameType = "runOrElse" val runtime: NameType = "runtime" val runtimeClass: NameType = "runtimeClass" val runtimeMirror: NameType = "runtimeMirror" - val sameElements: NameType = "sameElements" val scala_ : NameType = "scala" val selectDynamic: NameType = "selectDynamic" val selectOverloadedMethod: NameType = "selectOverloadedMethod" val selectTerm: NameType = "selectTerm" val selectType: NameType = "selectType" val self: NameType = "self" - val setAccessible: NameType = "setAccessible" val setAnnotations: NameType = "setAnnotations" val setSymbol: NameType = "setSymbol" val setType: NameType = "setType" @@ -760,15 +673,10 @@ trait StdNames { val staticModule : NameType = "staticModule" val staticPackage : NameType = "staticPackage" val synchronized_ : NameType = "synchronized" - val tail: NameType = "tail" - val `then` : NameType = "then" val this_ : NameType = "this" val thisPrefix : NameType = "thisPrefix" - val throw_ : NameType = "throw" val toArray: NameType = "toArray" - val toList: NameType = "toList" val toObjectArray : NameType = "toObjectArray" - val toSeq: NameType = "toSeq" val toString_ : NameType = if (forMSIL) "ToString" else "toString" val toTypeConstructor: NameType = "toTypeConstructor" val tpe : NameType = "tpe" @@ -788,14 +696,9 @@ trait StdNames { val view_ : NameType = "view" val wait_ : NameType = "wait" val withFilter: NameType = "withFilter" - val wrap: NameType = "wrap" - val zip: NameType = "zip" - - val synthSwitch: NameType = "$synthSwitch" // unencoded operators object raw { - final val AMP : NameType = "&" final val BANG : NameType = "!" final val BAR : NameType = "|" final val DOLLAR: NameType = "$" @@ -804,7 +707,6 @@ trait StdNames { final val MINUS: NameType = "-" final val NE: NameType = "!=" final val PLUS : NameType = "+" - final val SLASH: NameType = "/" final val STAR : NameType = "*" final val TILDE: NameType = "~" @@ -860,14 +762,7 @@ trait StdNames { // Grouped here so Cleanup knows what tests to perform. val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) - val ConversionNames = Set[Name](toByte, toChar, toDouble, toFloat, toInt, toLong, toShort) val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames - val NumberOpNames = ( - Set[Name](ADD, SUB, MUL, DIV, MOD, LSL, LSR, ASR, LT, LE, GE, GT) - ++ Set(UNARY_+, UNARY_-, UNARY_!) - ++ ConversionNames - ++ CommonOpNames - ) val add: NameType = "add" val complement: NameType = "complement" @@ -999,7 +894,6 @@ trait StdNames { object fulltpnme extends TypeNames { val RuntimeNothing: NameType = "scala.runtime.Nothing$" val RuntimeNull: NameType = "scala.runtime.Null$" - val JavaLangEnum: NameType = "java.lang.Enum" } /** Java binary names, like scala/runtime/Nothing$. @@ -1014,16 +908,11 @@ trait StdNames { val javanme = nme.javaKeywords object nme extends TermNames { - - def isModuleVarName(name: Name): Boolean = - stripAnonNumberSuffix(name) endsWith MODULE_VAR_SUFFIX - def moduleVarName(name: TermName): TermName = newTermNameCached("" + name + MODULE_VAR_SUFFIX) def getCause = sn.GetCause def getClass_ = sn.GetClass - def getComponentType = sn.GetComponentType def getMethod_ = sn.GetMethod def invoke_ = sn.Invoke @@ -1036,15 +925,6 @@ trait StdNames { val reflMethodCacheName: NameType = "reflMethod$Cache" val reflMethodName: NameType = "reflMethod$Method" - private val reflectionCacheNames = Set[NameType]( - reflPolyCacheName, - reflClassCacheName, - reflParamsCacheName, - reflMethodCacheName, - reflMethodName - ) - def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) - @deprecated("Use a method in tpnme", "2.10.0") def dropSingletonName(name: Name): TypeName = tpnme.dropSingletonName(name) @deprecated("Use a method in tpnme", "2.10.0") def singletonName(name: Name): TypeName = tpnme.singletonName(name) @deprecated("Use a method in tpnme", "2.10.0") def implClassName(name: Name): TypeName = tpnme.implClassName(name) @@ -1056,28 +936,21 @@ trait StdNames { protected val stringToTypeName = null protected implicit def createNameType(s: String): TypeName = newTypeNameCached(s) - val BeanProperty : TypeName - val BooleanBeanProperty : TypeName val BoxedBoolean : TypeName val BoxedCharacter : TypeName val BoxedNumber : TypeName - val Class : TypeName val Delegate : TypeName val IOOBException : TypeName // IndexOutOfBoundsException val InvTargetException : TypeName // InvocationTargetException - val JavaSerializable : TypeName val MethodAsObject : TypeName val NPException : TypeName // NullPointerException val Object : TypeName - val String : TypeName val Throwable : TypeName val ValueType : TypeName - val ForName : TermName val GetCause : TermName val GetClass : TermName val GetClassLoader : TermName - val GetComponentType : TermName val GetMethod : TermName val Invoke : TermName val JavaLang : TermName @@ -1152,22 +1025,18 @@ trait StdNames { final val BoxedLong: TypeName = "java.lang.Long" final val BoxedNumber: TypeName = "java.lang.Number" final val BoxedShort: TypeName = "java.lang.Short" - final val Class: TypeName = "java.lang.Class" final val Delegate: TypeName = tpnme.NO_NAME final val IOOBException: TypeName = "java.lang.IndexOutOfBoundsException" final val InvTargetException: TypeName = "java.lang.reflect.InvocationTargetException" final val MethodAsObject: TypeName = "java.lang.reflect.Method" final val NPException: TypeName = "java.lang.NullPointerException" final val Object: TypeName = "java.lang.Object" - final val String: TypeName = "java.lang.String" final val Throwable: TypeName = "java.lang.Throwable" final val ValueType: TypeName = tpnme.NO_NAME - final val ForName: TermName = newTermName("forName") final val GetCause: TermName = newTermName("getCause") final val GetClass: TermName = newTermName("getClass") final val GetClassLoader: TermName = newTermName("getClassLoader") - final val GetComponentType: TermName = newTermName("getComponentType") final val GetMethod: TermName = newTermName("getMethod") final val Invoke: TermName = newTermName("invoke") final val JavaLang: TermName = newTermName("java.lang") @@ -1185,28 +1054,21 @@ trait StdNames { } private class MSILNames extends SymbolNames { - final val BeanProperty: TypeName = tpnme.NO_NAME - final val BooleanBeanProperty: TypeName = tpnme.NO_NAME final val BoxedBoolean: TypeName = "System.IConvertible" final val BoxedCharacter: TypeName = "System.IConvertible" final val BoxedNumber: TypeName = "System.IConvertible" - final val Class: TypeName = "System.Type" final val Delegate: TypeName = "System.MulticastDelegate" final val IOOBException: TypeName = "System.IndexOutOfRangeException" final val InvTargetException: TypeName = "System.Reflection.TargetInvocationException" - final val JavaSerializable: TypeName = tpnme.NO_NAME final val MethodAsObject: TypeName = "System.Reflection.MethodInfo" final val NPException: TypeName = "System.NullReferenceException" final val Object: TypeName = "System.Object" - final val String: TypeName = "System.String" final val Throwable: TypeName = "System.Exception" final val ValueType: TypeName = "System.ValueType" - final val ForName: TermName = newTermName("GetType") final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */ final val GetClass: TermName = newTermName("GetType") final lazy val GetClassLoader: TermName = throw new UnsupportedOperationException("Scala reflection is not supported on this platform"); - final val GetComponentType: TermName = newTermName("GetElementType") final val GetMethod: TermName = newTermName("GetMethod") final val Invoke: TermName = newTermName("Invoke") final val JavaLang: TermName = newTermName("System") @@ -1223,13 +1085,7 @@ trait StdNames { ) } - private class J2SENames extends JavaNames { - final val BeanProperty: TypeName = "scala.beans.BeanProperty" - final val BooleanBeanProperty: TypeName = "scala.beans.BooleanBeanProperty" - final val JavaSerializable: TypeName = "java.io.Serializable" - } - lazy val sn: SymbolNames = if (forMSIL) new MSILNames - else new J2SENames + else new JavaNames { } } diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 554acf9c0b..a0e5851a6e 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -49,24 +49,28 @@ abstract class SymbolTable extends macros.Universe def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg)) def shouldLogAtThisPhase = false + def isPastTyper = false @deprecated("Give us a reason", "2.10.0") def abort(): Nothing = abort("unknown error") + @deprecated("Use devWarning if this is really a warning; otherwise use log", "2.11.0") + def debugwarn(msg: => String): Unit = devWarning(msg) + /** Override with final implementation for inlining. */ def debuglog(msg: => String): Unit = if (settings.debug.value) log(msg) - def debugwarn(msg: => String): Unit = if (settings.debug.value) Console.err.println(msg) + def devWarning(msg: => String): Unit = if (settings.debug.value) Console.err.println(msg) def throwableAsString(t: Throwable): String = "" + t /** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */ - def debugStack(t: Throwable): Unit = debugwarn(throwableAsString(t)) + def debugStack(t: Throwable): Unit = devWarning(throwableAsString(t)) /** Overridden when we know more about what was happening during a failure. */ def supplementErrorMessage(msg: String): String = msg private[scala] def printCaller[T](msg: String)(result: T) = { Console.err.println("%s: %s\nCalled from: %s".format(msg, result, - (new Throwable).getStackTrace.drop(2).take(15).mkString("\n"))) + (new Throwable).getStackTrace.drop(2).take(50).mkString("\n"))) result } @@ -139,7 +143,7 @@ abstract class SymbolTable extends macros.Universe type RunId = Int final val NoRunId = 0 - // sigh, this has to be public or atPhase doesn't inline. + // sigh, this has to be public or enteringPhase doesn't inline. var phStack: List[Phase] = Nil private[this] var ph: Phase = NoPhase private[this] var per = NoPeriod @@ -182,9 +186,6 @@ abstract class SymbolTable extends macros.Universe /** The phase identifier of the given period. */ final def phaseId(period: Period): Phase#Id = period & 0xFF - /** The period at the start of run that includes `period`. */ - final def startRun(period: Period): Period = period & 0xFFFFFF00 - /** The current period. */ final def currentPeriod: Period = { //assert(per == (currentRunId << 8) + phase.id) @@ -202,23 +203,17 @@ abstract class SymbolTable extends macros.Universe p != NoPhase && phase.id > p.id /** Perform given operation at given phase. */ - @inline final def atPhase[T](ph: Phase)(op: => T): T = { + @inline final def enteringPhase[T](ph: Phase)(op: => T): T = { val saved = pushPhase(ph) try op finally popPhase(saved) } + @inline final def exitingPhase[T](ph: Phase)(op: => T): T = enteringPhase(ph.next)(op) + @inline final def enteringPrevPhase[T](op: => T): T = enteringPhase(phase.prev)(op) - /** Since when it is to be "at" a phase is inherently ambiguous, - * a couple unambiguously named methods. - */ - @inline final def beforePhase[T](ph: Phase)(op: => T): T = atPhase(ph)(op) - @inline final def afterPhase[T](ph: Phase)(op: => T): T = atPhase(ph.next)(op) - @inline final def afterCurrentPhase[T](op: => T): T = atPhase(phase.next)(op) - @inline final def beforePrevPhase[T](op: => T): T = atPhase(phase.prev)(op) - - @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = - if (isAtPhaseAfter(target)) atPhase(target)(op) else op + @inline final def enteringPhaseNotLaterThan[T](target: Phase)(op: => T): T = + if (isAtPhaseAfter(target)) enteringPhase(target)(op) else op final def isValid(period: Period): Boolean = period != 0 && runId(period) == currentRunId && { @@ -303,7 +298,6 @@ abstract class SymbolTable extends macros.Universe object perRunCaches { import java.lang.ref.WeakReference - import scala.runtime.ScalaRunTime.stringOf import scala.collection.generic.Clearable // Weak references so the garbage collector will take care of @@ -345,6 +339,11 @@ abstract class SymbolTable extends macros.Universe /** Is this symbol table a part of a compiler universe? */ def isCompilerUniverse = false + + @deprecated("Use enteringPhase", "2.10.0") + @inline final def atPhase[T](ph: Phase)(op: => T): T = enteringPhase(ph)(op) + @deprecated("Use enteringPhaseNotLaterThan", "2.10.0") + @inline final def atPhaseNotLaterThan[T](target: Phase)(op: => T): T = enteringPhaseNotLaterThan(target)(op) } object SymbolTableStats { diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index c42cc1cea8..ad7dbe5ef1 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -8,7 +8,7 @@ package internal import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer -import util.Statistics +import util.{ Statistics, shortClassOfInstance } import Flags._ import scala.annotation.tailrec import scala.reflect.io.AbstractFile @@ -19,8 +19,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => protected var ids = 0 - val emptySymbolArray = new Array[Symbol](0) - protected def nextId() = { ids += 1; ids } /** Used for deciding in the IDE whether we can interrupt the compiler */ @@ -182,7 +180,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (isGADTSkolem) " (this is a GADT skolem)" else "" - def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$") + def shortSymbolClass = shortClassOfInstance(this) def symbolCreationString: String = ( "%s%25s | %-40s | %s".format( if (settings.uniqid.value) "%06d | ".format(id) else "", @@ -256,9 +254,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => (m, c) } - final def newPackageSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = - newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol] - final def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol = newClassSymbol(name, pos, newFlags).asInstanceOf[ModuleClassSymbol] @@ -321,11 +316,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => () => { cnt += 1; nme.syntheticParamName(cnt) } } - /** Synthetic value parameters when parameter symbols are not available - */ - final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[TermSymbol]] = - argtypess map (xs => newSyntheticValueParams(xs, freshNamer)) - /** Synthetic value parameters when parameter symbols are not available. * Calling this method multiple times will re-use the same parameter names. */ @@ -341,7 +331,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newSyntheticValueParam(argtype: Type, name: TermName = nme.syntheticParamName(1)): TermSymbol = newValueParameter(name, owner.pos.focus, SYNTHETIC) setInfo argtype - def newSyntheticTypeParam(): TypeSymbol = newSyntheticTypeParam("T0", 0L) def newSyntheticTypeParam(name: String, newFlags: Long): TypeSymbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty def newSyntheticTypeParams(num: Int): List[TypeSymbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L)) @@ -405,14 +394,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newRefinementClass(pos: Position): RefinementClassSymbol = createRefinementClassSymbol(pos, 0L) - /** Create a new getter for current symbol (which must be a field) - */ - final def newGetter: MethodSymbol = ( - owner.newMethod(nme.getterName(name.toTermName), NoPosition, getterFlags(flags)) - setPrivateWithin privateWithin - setInfo MethodType(Nil, tpe) - ) - final def newErrorSymbol(name: Name): Symbol = name match { case x: TypeName => newErrorClass(x) case x: TermName => newErrorValue(x) @@ -528,14 +509,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def isContravariant = false def isCovariant = false - def isExistentialQuantified = false def isExistentialSkolem = false def isExistentiallyBound = false def isGADTSkolem = false def isTypeParameter = false def isTypeParameterOrSkolem = false def isTypeSkolem = false - def isTypeMacro = false def isInvariant = !isCovariant && !isContravariant /** Qualities of Terms, always false for TypeSymbols. @@ -642,7 +621,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isStaticModule = isModule && isStatic && !isMethod final def isThisSym = isTerm && owner.thisSym == this final def isError = hasFlag(IS_ERROR) - final def isErroneous = isError || isInitialized && tpe.isErroneous + final def isErroneous = isError || isInitialized && tpe_*.isErroneous def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem @@ -709,10 +688,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr) - def isSerializable = ( - info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) - || hasAnnotation(SerializableAttr) // last part can be removed, @serializable annotation is deprecated - ) + def isSerializable = info.baseClasses.exists(p => p == SerializableClass || p == JavaSerializableClass) def hasBridgeAnnotation = hasAnnotation(BridgeClass) def isDeprecated = hasAnnotation(DeprecatedAttr) def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0) @@ -722,14 +698,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => = hasAnnotation(DeprecatedInheritanceAttr) def deprecatedInheritanceMessage = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 0) - def deprecatedInheritanceVersion - = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 1) def hasDeprecatedOverridingAnnotation = hasAnnotation(DeprecatedOverridingAttr) def deprecatedOverridingMessage = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 0) - def deprecatedOverridingVersion - = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 1) // !!! when annotation arguments are not literal strings, but any sort of // assembly of strings, there is a fair chance they will turn up here not as @@ -809,7 +781,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isStaticOwner: Boolean = isPackageClass || isModuleClass && isStatic - def isTopLevelModule = hasFlag(MODULE) && owner.isPackageClass + /** A helper function for isEffectivelyFinal. */ + private def isNotOverridden = ( + owner.isClass && ( + owner.isEffectivelyFinal + || owner.isSealed && owner.children.forall(c => c.isEffectivelyFinal && (overridingSymbol(c) == NoSymbol)) + ) + ) /** Is this symbol effectively final? I.e, it cannot be overridden */ final def isEffectivelyFinal: Boolean = ( @@ -818,8 +796,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => || isTerm && ( isPrivate || isLocal - || owner.isClass && owner.isEffectivelyFinal - ) + || isNotOverridden + ) ) /** Is this symbol locally defined? I.e. not accessed from outside `this` instance */ @@ -839,12 +817,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def isLocalClass = false - def isStableClass = false - -/* code for fixing nested objects - override final def isModuleClass: Boolean = - super.isModuleClass && !isExpandedModuleClass -*/ /** Is this class or type defined as a structural refinement type? */ final def isStructuralRefinement: Boolean = @@ -863,17 +835,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isStructuralRefinementMember = owner.isStructuralRefinement && isPossibleInRefinement && isPublic final def isPossibleInRefinement = !isConstructor && !isOverridingSymbol - /** Is this symbol a member of class `clazz`? */ - def isMemberOf(clazz: Symbol) = - clazz.info.member(name).alternatives contains this - /** A a member of class `base` is incomplete if * (1) it is declared deferred or * (2) it is abstract override and its super symbol in `base` is * nonexistent or incomplete. - * - * @param base ... - * @return ... */ final def isIncompleteIn(base: Symbol): Boolean = this.isDeferred || @@ -967,6 +932,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => def ownerChain: List[Symbol] = this :: owner.ownerChain def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain + // All the symbols overridden by this symbol and this symbol at the head, + // or Nil if this is NoSymbol. + def overrideChain = ( + if (this eq NoSymbol) Nil + else if (!owner.isClass) this :: Nil + else this :: allOverriddenSymbols + ) + // Non-classes skip self and return rest of owner chain; overridden in ClassSymbol. def enclClassChain: List[Symbol] = owner.enclClassChain @@ -1076,9 +1049,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol = new ClassSymbol(this, pos, name) with ImplClassSymbol initFlags newFlags - protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = - new TermSymbol(this, pos, name) initFlags newFlags - protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol = new MethodSymbol(this, pos, name) initFlags newFlags @@ -1181,16 +1151,57 @@ trait Symbols extends api.Symbols { self: SymbolTable => } } - /** Get type. The type of a symbol is: - * for a type symbol, the type corresponding to the symbol itself, - * @M you should use tpeHK for a type symbol with type parameters if - * the kind of the type need not be *, as tpe introduces dummy arguments - * to generate a type of kind * - * for a term symbol, its usual type. - * See the tpe/tpeHK overrides in TypeSymbol for more. + /** The "type" of this symbol. The type of a term symbol is its usual + * type. A TypeSymbol is more complicated; see that class for elaboration. + * Since tpe forwards to tpe_*, if you call it on a type symbol with unapplied + * type parameters, the type returned will contain dummies types. These will + * hide legitimate errors or create spurious ones if used as normal types. */ - def tpe: Type = info - def tpeHK: Type = tpe + final def tpe: Type = tpe_* + + /** typeConstructor throws an exception when called on term + * symbols; this is a more forgiving alternative. Calls + * typeConstructor on TypeSymbols, returns info otherwise. + */ + def tpeHK: Type = info + + /** Only applicable to TypeSymbols, it is the type corresponding + * to the symbol itself. For instance, the type of a List might + * be List[Int] - the same symbol's typeConstructor is simply List. + * One might be tempted to write that as List[_], and in some + * contexts this is possible, but it is discouraged because it is + * syntactically indistinguishable from and easily confused with the + * type List[T] forSome { type T; }, which can also be written List[_]. + */ + def typeConstructor: Type = ( + // Avoiding a third override in NoSymbol to preserve bimorphism + if (this eq NoSymbol) + abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)") + else + abort("typeConstructor inapplicable for " + this) + ) + + /** The type of this symbol, guaranteed to be of kind *. + * If there are unapplied type parameters, they will be + * substituted with dummy type arguments derived from the + * type parameters. Such types are not valid in a general + * sense and will cause difficult-to-find bugs if allowed + * to roam free. + * + * If you call tpe_* explicitly to obtain these types, + * you are responsible for them as if it they were your own + * minor children. + */ + def tpe_* : Type = info + + // Alternate implementation of def tpe for warning about misuse, + // disabled to keep the method maximally hotspot-friendly: + // def tpe: Type = { + // val result = tpe_* + // if (settings.debug.value && result.typeArgs.nonEmpty) + // printCaller(s"""Call to ${this.tpe} created $result: call tpe_* or tpeHK""")("") + // result + // } /** Get type info associated with symbol at current phase, after * ensuring that symbol is initialized (i.e. type is completed). @@ -1226,13 +1237,13 @@ trait Symbols extends api.Symbols { self: SymbolTable => cnt += 1 // allow for two completions: // one: sourceCompleter to LazyType, two: LazyType to completed type - if (cnt == 3) abort("no progress in completing " + this + ":" + tp) + if (cnt == 3) abort(s"no progress in completing $this: $tp") } rawInfo } catch { case ex: CyclicReference => - debugwarn("... hit cycle trying to complete " + this.fullLocationString) + devWarning("... hit cycle trying to complete " + this.fullLocationString) throw ex } @@ -1244,9 +1255,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => } /** Set initial info. */ - def setInfo(info: Type): this.type = { info_=(info); this } + def setInfo(info: Type): this.type = { info_=(info); this } /** Modifies this symbol's info in place. */ - def modifyInfo(f: Type => Type): this.type = setInfo(f(info)) + def modifyInfo(f: Type => Type): this.type = setInfo(f(info)) /** Substitute second list of symbols for first in current info. */ def substInfo(syms0: List[Symbol], syms1: List[Symbol]): this.type = if (syms0.isEmpty) this @@ -1357,6 +1368,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (!isInitialized) info this } + def maybeInitialize = { + try { initialize ; true } + catch { case _: CyclicReference => debuglog("Hit cycle in maybeInitialize of $this") ; false } + } /** Called when the programmer requests information that might require initialization of the underlying symbol. * @@ -1399,14 +1414,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => !isInitialized && (flags & LOCKED) == 0 && shouldTriggerCompleter(this, if (infos ne null) infos.info else null, isFlagRelated, mask) /** Was symbol's type updated during given phase? */ - final def isUpdatedAt(pid: Phase#Id): Boolean = { - assert(isCompilerUniverse) - var infos = this.infos - while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev - infos ne null - } - - /** Was symbol's type updated during given phase? */ final def hasTypeAt(pid: Phase#Id): Boolean = { assert(isCompilerUniverse) var infos = this.infos @@ -1419,21 +1426,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => * This is done in checkAccessible and overriding checks in refchecks * We can't do this on class loading because it would result in infinite cycles. */ - final def cookJavaRawInfo() { - if (hasFlag(TRIEDCOOKING)) return else setFlag(TRIEDCOOKING) // only try once... - val oldInfo = info - doCookJavaRawInfo() - } + def cookJavaRawInfo(): Unit = { + // only try once... + if (this hasFlag TRIEDCOOKING) + return - protected def doCookJavaRawInfo(): Unit - - /** The type constructor of a symbol is: - * For a type symbol, the type corresponding to the symbol itself, - * excluding parameters. - * Not applicable for term symbols. - */ - def typeConstructor: Type = - abort("typeConstructor inapplicable for " + this) + this setFlag TRIEDCOOKING + info // force the current info + if (isJavaDefined || isType && owner.isJavaDefined) + this modifyInfo rawToExistential + else if (isOverloaded) + alternatives withFilter (_.isJavaDefined) foreach (_ modifyInfo rawToExistential) + } /** The logic approximately boils down to finding the most recent phase * which immediately follows any of parser, namer, typer, or erasure. @@ -1457,7 +1461,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def unsafeTypeParams: List[Symbol] = if (isMonomorphicType) Nil - else atPhase(unsafeTypeParamPhase)(rawInfo.typeParams) + else enteringPhase(unsafeTypeParamPhase)(rawInfo.typeParams) /** The type parameters of this symbol. * assumption: if a type starts out as monomorphic, it will not acquire @@ -1469,9 +1473,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => // analogously to the "info" getter, here we allow for two completions: // one: sourceCompleter to LazyType, two: LazyType to completed type if (validTo == NoPeriod) - atPhase(phaseOf(infos.validFrom))(rawInfo load this) + enteringPhase(phaseOf(infos.validFrom))(rawInfo load this) if (validTo == NoPeriod) - atPhase(phaseOf(infos.validFrom))(rawInfo load this) + enteringPhase(phaseOf(infos.validFrom))(rawInfo load this) rawInfo.typeParams } @@ -1633,12 +1637,23 @@ trait Symbols extends api.Symbols { self: SymbolTable => def filter(cond: Symbol => Boolean): Symbol = if (isOverloaded) { - val alts = alternatives - val alts1 = alts filter cond - if (alts1 eq alts) this + var changed = false + var alts0: List[Symbol] = alternatives + var alts1: List[Symbol] = Nil + + while (alts0.nonEmpty) { + if (cond(alts0.head)) + alts1 ::= alts0.head + else + changed = true + + alts0 = alts0.tail + } + + if (!changed) this else if (alts1.isEmpty) NoSymbol else if (alts1.tail.isEmpty) alts1.head - else owner.newOverloaded(info.prefix, alts1) + else owner.newOverloaded(info.prefix, alts1.reverse) } else if (cond(this)) this else NoSymbol @@ -1717,10 +1732,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => def thisSym: Symbol = this /** The type of `this` in a class, or else the type of the symbol itself. */ - def typeOfThis = thisSym.tpe + def typeOfThis = thisSym.tpe_* - /** If symbol is a class, the type <code>this.type</code> in this class, - * otherwise <code>NoPrefix</code>. + /** If symbol is a class, the type `this.type` in this class, + * otherwise `NoPrefix`. * We always have: thisType <:< typeOfThis */ def thisType: Type = NoPrefix @@ -1889,11 +1904,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => (this.rawInfo ne NoType) && (this.effectiveOwner == that.effectiveOwner) && ( !this.effectiveOwner.isPackageClass - || (this.sourceFile eq null) - || (that.sourceFile eq null) - || (this.sourceFile.path == that.sourceFile.path) // Cheap possibly wrong check, then expensive normalization - || (this.sourceFile.canonicalPath == that.sourceFile.canonicalPath) - ) + || (this.associatedFile eq null) + || (that.associatedFile eq null) + || (this.associatedFile.path == that.associatedFile.path) // Cheap possibly wrong check, then expensive normalization + || (this.associatedFile.canonicalPath == that.associatedFile.canonicalPath) + ) ) /** The internal representation of classes and objects: @@ -2019,9 +2034,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => if (isClassConstructor) NoSymbol else matchingSymbol(ofclazz, ofclazz.thisType) /** Returns all symbols overriden by this symbol. */ - final def allOverriddenSymbols: List[Symbol] = - if (!owner.isClass) Nil + final def allOverriddenSymbols: List[Symbol] = ( + if ((this eq NoSymbol) || !owner.isClass) Nil else owner.ancestors map overriddenSymbol filter (_ != NoSymbol) + ) /** Equivalent to allOverriddenSymbols.nonEmpty, but more efficient. */ // !!! When if ever will this answer differ from .isOverride? @@ -2032,7 +2048,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) /** Equivalent to allOverriddenSymbols.head (or NoSymbol if no overrides) but more efficient. */ def nextOverriddenSymbol: Symbol = { - if (owner.isClass) owner.ancestors foreach { base => + if ((this ne NoSymbol) && owner.isClass) owner.ancestors foreach { base => val sym = overriddenSymbol(base) if (sym != NoSymbol) return sym @@ -2137,13 +2153,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => case p :: _ => p case _ => NoSymbol } -/* code for fixing nested objects - def expandModuleClassName() { - name = newTypeName(name.toString + "$") - } - - def isExpandedModuleClass: Boolean = name(name.length - 1) == '$' -*/ /** Desire to re-use the field in ClassSymbol which stores the source * file to also store the classfile, but without changing the behavior @@ -2153,10 +2162,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def sourceFileOnly(file: AbstractFile): AbstractFile = if ((file eq null) || (file.path endsWith ".class")) null else file - private def binaryFileOnly(file: AbstractFile): AbstractFile = - if ((file eq null) || !(file.path endsWith ".class")) null else file - - final def binaryFile: AbstractFile = binaryFileOnly(associatedFile) final def sourceFile: AbstractFile = sourceFileOnly(associatedFile) /** Overridden in ModuleSymbols to delegate to the module class. */ @@ -2180,9 +2185,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ toString ------------------------------------------------------------------- - /** A tag which (in the ideal case) uniquely identifies class symbols */ - final def tag: Int = fullName.## - /** The simple name of this Symbol */ final def simpleName: Name = name @@ -2413,6 +2415,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def isMethod = this hasFlag METHOD override def isModule = this hasFlag MODULE override def isOverloaded = this hasFlag OVERLOADED + /*** !!! TODO: shouldn't we do something like the following: + override def isOverloaded = ( + if (this.isInitialized) + this hasFlag OVERLOADED + else + (infos ne null) && infos.info.isInstanceOf[OverloadedType] + ) + ***/ override def isPackage = this hasFlag PACKAGE override def isValueParameter = this hasFlag PARAM @@ -2509,36 +2519,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => name = nme.expandedName(name.toTermName, base) } } - - protected def doCookJavaRawInfo() { - def cook(sym: Symbol) { - require(sym.isJavaDefined, sym) - // @M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible - // object rawToExistentialInJava extends TypeMap { - // def apply(tp: Type): Type = tp match { - // // any symbol that occurs in a java sig, not just java symbols - // // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14 - // case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty => - // val eparams = typeParamsToExistentials(sym, sym.typeParams) - // existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe))) - // case _ => - // mapOver(tp) - // } - // } - val tpe1 = rawToExistential(sym.tpe) - // println("cooking: "+ sym +": "+ sym.tpe +" to "+ tpe1) - if (tpe1 ne sym.tpe) { - sym.setInfo(tpe1) - } - } - - if (isJavaDefined) - cook(this) - else if (isOverloaded) - for (sym2 <- alternatives) - if (sym2.isJavaDefined) - cook(sym2) - } } implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol]) @@ -2630,6 +2610,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => owner.newNonClassSymbol(name, pos, newFlags) } + /** Let's say you have a type definition + * + * {{{ + * type T <: Number + * }}} + * + * and tsym is the symbol corresponding to T. Then + * + * {{{ + * tsym is an instance of AbstractTypeSymbol + * tsym.info = TypeBounds(Nothing, Number) + * tsym.tpe = TypeRef(NoPrefix, T, List()) + * }}} + */ class AbstractTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends TypeSymbol(initOwner, initPos, initName) { type TypeOfClonedSymbol = TypeSymbol @@ -2658,7 +2652,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def asNameType(n: Name) = n.toTypeName override def isNonClassType = true - override def isTypeMacro = hasFlag(MACRO) override def resolveOverloadedFlag(flag: Long) = flag match { case TRAIT => "<trait>" // DEFAULTPARAM @@ -2676,7 +2669,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def isAbstractType = this hasFlag DEFERRED override def isContravariant = this hasFlag CONTRAVARIANT override def isCovariant = this hasFlag COVARIANT - override def isExistentialQuantified = isExistentiallyBound && !isSkolem override def isExistentiallyBound = this hasFlag EXISTENTIAL override def isTypeParameter = isTypeParameterOrSkolem && !isSkolem override def isTypeParameterOrSkolem = this hasFlag PARAM @@ -2698,63 +2690,57 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def newPrefix = if (this hasFlag EXISTENTIAL | PARAM) NoPrefix else owner.thisType private def newTypeRef(targs: List[Type]) = typeRef(newPrefix, this, targs) - /** Let's say you have a type definition - * - * {{{ - * type T <: Number - * }}} + /** A polymorphic type symbol has two distinct "types": * - * and tsym is the symbol corresponding to T. Then + * tpe_* a TypeRef with: dummy type args, no unapplied type parameters, and kind * + * tpeHK a TypeRef with: no type args, unapplied type parameters, and + * kind (*,*,...,*) => * depending on the number of tparams. * - * {{{ - * tsym.info = TypeBounds(Nothing, Number) - * tsym.tpe = TypeRef(NoPrefix, T, List()) - * }}} - */ - override def tpe: Type = { - if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor) - if (tpePeriod != currentPeriod) { - if (isValid(tpePeriod)) { - tpePeriod = currentPeriod - } else { - if (isInitialized) tpePeriod = currentPeriod - tpeCache = NoType - val targs = - if (phase.erasedTypes && this != ArrayClass) List() - else unsafeTypeParams map (_.typeConstructor) - //@M! use typeConstructor to generate dummy type arguments, - // sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type - // memberType should be used instead, that's why it uses tpeHK and not tpe - tpeCache = newTypeRef(targs) - } - } - assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug + * The dummy type args in tpe_* are created by wrapping a TypeRef + * around the type parameter symbols. Types containing dummies will + * hide errors or introduce spurious ones if they are passed around + * as if normal types. They should only be used in local operations + * where they will either be discarded immediately after, or will + * undergo substitution in which the dummies are replaced by actual + * type arguments. + */ + override def tpe_* : Type = { + maybeUpdateTypeCache() tpeCache } - - /** @M -- tpe vs tpeHK: - * - * tpe: creates a TypeRef with dummy type arguments and kind * - * tpeHK: creates a TypeRef with no type arguments but with type parameters - * - * If typeParams is nonEmpty, calling tpe may hide errors or - * introduce spurious ones. (For example, when deriving a type from - * the symbol of a type argument that may be higher-kinded.) As far - * as I can tell, it only makes sense to call tpe in conjunction - * with a substitution that replaces the generated dummy type - * arguments by their actual types. - * - * TODO: the above conditions desperately need to be enforced by code. - */ - override def tpeHK = typeConstructor // @M! used in memberType - override def typeConstructor: Type = { + maybeUpdateTyconCache() + tyconCache + } + override def tpeHK: Type = typeConstructor + + private def maybeUpdateTyconCache() { if ((tyconCache eq null) || tyconRunId != currentRunId) { tyconCache = newTypeRef(Nil) tyconRunId = currentRunId } assert(tyconCache ne null) - tyconCache + } + private def maybeUpdateTypeCache() { + if (tpePeriod != currentPeriod) { + if (isValid(tpePeriod)) + tpePeriod = currentPeriod + else + updateTypeCache() // perform the actual update + } + } + private def updateTypeCache() { + if (tpeCache eq NoType) + throw CyclicReference(this, typeConstructor) + + if (isInitialized) + tpePeriod = currentPeriod + + tpeCache = NoType // cycle marker + tpeCache = newTypeRef( + if (phase.erasedTypes && this != ArrayClass || unsafeTypeParams.isEmpty) Nil + else unsafeTypeParams map (_.typeConstructor) + ) } override def info_=(tp: Type) { @@ -2780,15 +2766,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => * public class Test1<T extends Test3> {} * info for T in Test1 should be >: Nothing <: Test3[_] */ - protected def doCookJavaRawInfo() { - if (isJavaDefined || owner.isJavaDefined) { - val tpe1 = rawToExistential(info) - // println("cooking type: "+ this +": "+ info +" to "+ tpe1) - if (tpe1 ne info) { - setInfo(tpe1) - } - } - } if (Statistics.hotEnabled) Statistics.incCounter(typeSymbolCount) } @@ -2822,7 +2799,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def isTypeSkolem = this hasFlag PARAM override def isAbstractType = this hasFlag DEFERRED - override def isExistentialQuantified = false override def existentialBound = if (isAbstractType) this.info else super.existentialBound /** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */ @@ -2908,21 +2884,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => || isLocal || !owner.isPackageClass && owner.isLocalClass ) - override def isStableClass = (this hasFlag STABLE) || checkStable() - - private def checkStable() = { - def hasNoAbstractTypeMember(clazz: Symbol): Boolean = - (clazz hasFlag STABLE) || { - var e = clazz.info.decls.elems - while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym)) - e = e.next - e == null - } - (info.baseClasses forall hasNoAbstractTypeMember) && { - setFlag(STABLE) - true - } - } override def enclClassChain = this :: owner.enclClassChain @@ -3108,6 +3069,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) } trait StubSymbol extends Symbol { + devWarning("creating stub symbol to defer error: " + missingMessage) + protected def missingMessage: String /** Fail the stub by throwing a [[scala.reflect.internal.MissingRequirementError]]. */ @@ -3135,8 +3098,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def info = fail(NoType) override def rawInfo = fail(NoType) override def companionSymbol = fail(NoSymbol) - - debugwarn("creating stub symbol to defer error: " + missingMessage) } class StubClassSymbol(owner0: Symbol, name0: TypeName, protected val missingMessage: String) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol class StubTermSymbol(owner0: Symbol, name0: TermName, protected val missingMessage: String) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol @@ -3194,15 +3155,12 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def info: Type = NoType override def existentialBound: Type = NoType override def rawInfo: Type = NoType - protected def doCookJavaRawInfo() {} override def accessBoundary(base: Symbol): Symbol = enclosingRootClass def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()") override def originalEnclosingMethod = this override def owner: Symbol = abort("no-symbol does not have an owner") - override def typeConstructor: Type = - abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)") } protected def makeNoSymbol: NoSymbol = new NoSymbol diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index ebf0998573..072e94e069 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -11,10 +11,7 @@ abstract class TreeGen extends macros.TreeBuilder { def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name) def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name) def scalaAnnotationDot(name: Name) = Select(scalaDot(nme.annotation), name) - def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass - def scalaUnitConstr = scalaDot(tpnme.Unit) setSymbol UnitClass - def productConstr = scalaDot(tpnme.Product) setSymbol ProductRootClass - def serializableConstr = scalaDot(tpnme.Serializable) setSymbol SerializableClass + def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass // used in ide def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = { val cls = if (abstractFun) @@ -165,17 +162,36 @@ abstract class TreeGen extends macros.TreeBuilder { This(sym.name.toTypeName) setSymbol sym setType sym.thisType def mkAttributedIdent(sym: Symbol): Tree = - Ident(sym.name) setSymbol sym setType sym.tpe + Ident(sym.name) setSymbol sym setType sym.tpeHK def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = { // Tests involving the repl fail without the .isEmptyPackage condition. if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage)) mkAttributedIdent(sym) else { + // Have to recognize anytime a selection is made on a package + // so it can be rewritten to foo.bar.`package`.name rather than + // foo.bar.name if name is in the package object. + // TODO - factor out the common logic between this and + // the Typers method "isInPackageObject", used in typedIdent. + val qualsym = ( + if (qual.tpe ne null) qual.tpe.typeSymbol + else if (qual.symbol ne null) qual.symbol + else NoSymbol + ) + val needsPackageQualifier = ( + (sym ne null) + && qualsym.isPackage + && !sym.isDefinedInPackage + ) val pkgQualifier = - if (sym != null && sym.owner.isPackageObjectClass && sym.effectiveOwner == qual.tpe.typeSymbol) { - val obj = sym.owner.sourceModule - Select(qual, nme.PACKAGE) setSymbol obj setType singleType(qual.tpe, obj) + if (needsPackageQualifier) { + // The owner of a symbol which requires package qualification may be the + // package object iself, but it also could be any superclass of the package + // object. In the latter case, we must go through the qualifier's info + // to obtain the right symbol. + val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE + Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject) } else qual @@ -229,10 +245,6 @@ abstract class TreeGen extends macros.TreeBuilder { Literal(Constant(tp)) setType ConstantType(Constant(tp)) /** Builds a list with given head and tail. */ - def mkNewCons(head: Tree, tail: Tree): Tree = - New(Apply(mkAttributedRef(ConsClass), List(head, tail))) - - /** Builds a list with given head and tail. */ def mkNil: Tree = mkAttributedRef(NilModule) /** Builds a tree representing an undefined local, as in diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 8ad15f37e4..4f60d9cabc 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -104,11 +104,32 @@ abstract class TreeInfo { false } - @deprecated("Use isExprSafeToInline instead", "2.10.0") - def isPureExpr(tree: Tree) = isExprSafeToInline(tree) + /** As if the name of the method didn't give it away, + * this logic is designed around issuing helpful + * warnings and minimizing spurious ones. That means + * don't reuse it for important matters like inlining + * decisions. + */ + def isPureExprForWarningPurposes(tree: Tree) = tree match { + case EmptyTree | Literal(Constant(())) => false + case _ => + def isWarnableRefTree = tree match { + case t: RefTree => isExprSafeToInline(t.qualifier) && t.symbol != null && t.symbol.isAccessor + case _ => false + } + def isWarnableSymbol = { + val sym = tree.symbol + (sym == null) || !(sym.isModule || sym.isLazy) || { + debuglog("'Pure' but side-effecting expression in statement position: " + tree) + false + } + } - def zipMethodParamsAndArgs(params: List[Symbol], args: List[Tree]): List[(Symbol, Tree)] = - mapMethodParamsAndArgs(params, args)((param, arg) => ((param, arg))) + ( !tree.isErrorTyped + && (isExprSafeToInline(tree) || isWarnableRefTree) + && isWarnableSymbol + ) + } def mapMethodParamsAndArgs[R](params: List[Symbol], args: List[Tree])(f: (Symbol, Tree) => R): List[R] = { val b = List.newBuilder[R] @@ -119,11 +140,10 @@ abstract class TreeInfo { val plen = params.length val alen = args.length def fail() = { - global.debugwarn( - "Mismatch trying to zip method parameters and argument list:\n" + - " params = " + params + "\n" + - " args = " + args + "\n" - ) + global.devWarning( + s"""|Mismatch trying to zip method parameters and argument list: + | params = $params + | args = $args""".stripMargin) false } @@ -147,37 +167,6 @@ abstract class TreeInfo { true } - /** - * Selects the correct parameter list when there are nested applications. - * Given Apply(fn, args), args might correspond to any of fn.symbol's parameter - * lists. To choose the correct one before uncurry, we have to unwrap any - * applies: for instance Apply(fn @ Apply(Apply(_, _), _), args) implies args - * correspond to the third parameter list. - * - * The argument fn is the function part of the apply node being considered. - * - * Also accounts for varargs. - */ - private def applyMethodParameters(fn: Tree): List[Symbol] = { - val depth = applyDepth(fn) - // There could be applies which go beyond the parameter list(s), - // being applied to the result of the method call. - // !!! Note that this still doesn't seem correct, although it should - // be closer than what it replaced. - if (depth < fn.symbol.paramss.size) fn.symbol.paramss(depth) - else if (fn.symbol.paramss.isEmpty) Nil - else fn.symbol.paramss.last - } - - def zipMethodParamsAndArgs(t: Tree): List[(Symbol, Tree)] = t match { - case Apply(fn, args) => zipMethodParamsAndArgs(applyMethodParameters(fn), args) - case _ => Nil - } - def foreachMethodParamAndArg(t: Tree)(f: (Symbol, Tree) => Unit): Unit = t match { - case Apply(fn, args) => foreachMethodParamAndArg(applyMethodParameters(fn), args)(f) - case _ => - } - /** Is symbol potentially a getter of a variable? */ def mayBeVarGetter(sym: Symbol): Boolean = sym.info match { @@ -237,6 +226,20 @@ abstract class TreeInfo { tree } + /** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */ + def stripCast(tree: Tree): Tree = tree match { + case TypeApply(sel @ Select(inner, _), _) if isCastSymbol(sel.symbol) => + stripCast(inner) + case Apply(TypeApply(sel @ Select(inner, _), _), Nil) if isCastSymbol(sel.symbol) => + stripCast(inner) + case t => + t + } + + object StripCast { + def unapply(tree: Tree): Some[Tree] = Some(stripCast(tree)) + } + /** Is tree a self or super constructor call? */ def isSelfOrSuperConstrCall(tree: Tree) = { // stripNamedApply for SI-3584: adaptToImplicitMethod in Typers creates a special context @@ -312,10 +315,6 @@ abstract class TreeInfo { case x: Ident => !x.isBackquoted && nme.isVariableName(x.name) case _ => false } - def isDeprecatedIdentifier(tree: Tree): Boolean = tree match { - case x: Ident => !x.isBackquoted && nme.isDeprecatedIdentifierName(x.name) - case _ => false - } /** The first constructor definitions in `stats` */ def firstConstructor(stats: List[Tree]): Tree = stats find { @@ -374,12 +373,6 @@ abstract class TreeInfo { /** Is name a left-associative operator? */ def isLeftAssoc(operator: Name) = operator.nonEmpty && (operator.endChar != ':') - /** Is tree a `this` node which belongs to `enclClass`? */ - def isSelf(tree: Tree, enclClass: Symbol): Boolean = tree match { - case This(_) => tree.symbol == enclClass - case _ => false - } - /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe) */ def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation definitions.SwitchClass @@ -441,15 +434,31 @@ abstract class TreeInfo { case _ => false } - /** Does this CaseDef catch Throwable? */ - def catchesThrowable(cdef: CaseDef) = catchesAllOf(cdef, ThrowableClass.tpe) + private def hasNoSymbol(t: Tree) = t.symbol == null || t.symbol == NoSymbol - /** Does this CaseDef catch everything of a certain Type? */ - def catchesAllOf(cdef: CaseDef, threshold: Type) = - isDefaultCase(cdef) || (cdef.guard.isEmpty && (unbind(cdef.pat) match { - case Typed(Ident(nme.WILDCARD), tpt) => (tpt.tpe != null) && (threshold <:< tpt.tpe) - case _ => false - })) + /** If this CaseDef assigns a name to its top-level pattern, + * in the form 'expr @ pattern' or 'expr: pattern', returns + * the name. Otherwise, nme.NO_NAME. + * + * Note: in the case of Constant patterns such as 'case x @ "" =>', + * the pattern matcher eliminates the binding and inlines the constant, + * so as far as this method is likely to be able to determine, + * the name is NO_NAME. + */ + def assignedNameOfPattern(cdef: CaseDef): Name = cdef.pat match { + case Bind(name, _) => name + case Ident(name) => name + case _ => nme.NO_NAME + } + + /** Does this CaseDef catch Throwable? */ + def catchesThrowable(cdef: CaseDef) = ( + cdef.guard.isEmpty && (unbind(cdef.pat) match { + case Ident(nme.WILDCARD) => true + case i@Ident(name) => hasNoSymbol(i) + case _ => false + }) + ) /** Is this pattern node a catch-all or type-test pattern? */ def isCatchCase(cdef: CaseDef) = cdef match { diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index b2158de9ec..f944e1d5d1 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -31,7 +31,8 @@ trait Trees extends api.Trees { self: SymbolTable => def symbol: Symbol = null //!!!OPT!!! symbol is about 3% of hot compile times -- megamorphic dispatch? def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) } def setSymbol(sym: Symbol): this.type = { symbol = sym; this } - def hasSymbol = false + def hasSymbolField = false + @deprecated("Use hasSymbolField", "2.11.0") def hasSymbol = hasSymbolField def isDef = false @@ -62,7 +63,7 @@ trait Trees extends api.Trees { self: SymbolTable => private[scala] def copyAttrs(tree: Tree): this.type = { rawatt = tree.rawatt tpe = tree.tpe - if (hasSymbol) symbol = tree.symbol + if (hasSymbolField) symbol = tree.symbol this } @@ -210,7 +211,7 @@ trait Trees extends api.Trees { self: SymbolTable => trait TypTree extends Tree with TypTreeApi abstract class SymTree extends Tree with SymTreeContextApi { - override def hasSymbol = true + override def hasSymbolField = true override var symbol: Symbol = NoSymbol } @@ -413,6 +414,16 @@ trait Trees extends api.Trees { self: SymbolTable => def ApplyConstructor(tpt: Tree, args: List[Tree]) = Apply(Select(New(tpt), nme.CONSTRUCTOR), args) + // Creates a constructor call from the constructor symbol. This is + // to avoid winding up with an OverloadedType for the constructor call. + def NewFromConstructor(constructor: Symbol, args: Tree*) = { + assert(constructor.isConstructor, constructor) + val instance = New(TypeTree(constructor.owner.tpe)) + val init = Select(instance, nme.CONSTRUCTOR) setSymbol constructor + + Apply(init, args.toList) + } + case class ApplyDynamic(qual: Tree, args: List[Tree]) extends SymTree with TermTree case class Super(qual: Tree, mix: TypeName) extends TermTree with SuperApi { @@ -849,7 +860,6 @@ trait Trees extends api.Trees { self: SymbolTable => /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? */ def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) - def isReferenceToAnyVal(t: Tree) = isReferenceToScalaMember(t, tpnme.AnyVal) // --- modifiers implementation --------------------------------------- @@ -1314,7 +1324,7 @@ trait Trees extends api.Trees { self: SymbolTable => class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser { final def change(sym: Symbol) = { - if (sym != NoSymbol && sym.owner == oldowner) + if (sym != NoSymbol && sym.owner == oldowner) sym.owner = newowner } override def traverse(tree: Tree) { @@ -1416,7 +1426,7 @@ trait Trees extends api.Trees { self: SymbolTable => } if (tree.tpe ne null) tree.tpe = symSubst(tree.tpe) - if (tree.hasSymbol) { + if (tree.hasSymbolField) { subst(from, to) tree match { case Ident(name0) if tree.symbol != NoSymbol => diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala index 68b4fa69a1..d437b1b058 100644 --- a/src/reflect/scala/reflect/internal/TypeDebugging.scala +++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala @@ -9,8 +9,6 @@ package internal trait TypeDebugging { self: SymbolTable => - import definitions._ - // @M toString that is safe during debugging (does not normalize, ...) object typeDebug { private def to_s(x: Any): String = x match { @@ -20,7 +18,6 @@ trait TypeDebugging { case x: Product => x.productIterator mkString ("(", ", ", ")") case _ => "" + x } - def ptIndent(x: Any) = ("" + x).replaceAll("\\n", " ") def ptBlock(label: String, pairs: (String, Any)*): String = { if (pairs.isEmpty) label + "{ }" else { diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 0c4cda8313..09fc534d8a 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -22,6 +22,8 @@ import util.ThreeValues._ // internal: error case WildcardType => // internal: unknown + case BoundedWildcardType(bounds) => + // internal: unknown case NoType => case NoPrefix => case ThisType(sym) => @@ -66,9 +68,7 @@ import util.ThreeValues._ // a type variable // Replace occurrences of type parameters with type vars, where // inst is the instantiation and constr is a list of bounds. - case DeBruijnIndex(level, index, args) - // for dependent method types: a type referring to a method parameter. - case ErasedValueType(tref) + case ErasedValueType(clazz, underlying) // only used during erasure of derived value classes. */ @@ -91,6 +91,7 @@ trait Types extends api.Types { self: SymbolTable => private final val printLubs = sys.props contains "scalac.debug.lub" private final val traceTypeVars = sys.props contains "scalac.debug.tvar" + private final val breakCycles = settings.breakCycles.value /** In case anyone wants to turn off lub verification without reverting anything. */ private final val verifyLubs = true /** In case anyone wants to turn off type parameter bounds being used @@ -100,10 +101,6 @@ trait Types extends api.Types { self: SymbolTable => protected val enableTypeVarExperimentals = settings.Xexperimental.value - /** Empty immutable maps to avoid allocations. */ - private val emptySymMap = immutable.Map[Symbol, Symbol]() - private val emptySymCount = immutable.Map[Symbol, Int]() - /** The current skolemization level, needed for the algorithms * in isSameType, isSubType that do constraint solving under a prefix. */ @@ -170,10 +167,6 @@ trait Types extends api.Types { self: SymbolTable => log = Nil } finally unlock() } - def size = { - lock() - try log.size finally unlock() - } // `block` should not affect constraints on typevars def undo[T](block: => T): T = { @@ -185,20 +178,6 @@ trait Types extends api.Types { self: SymbolTable => finally undoTo(before) } finally unlock() } - - // if `block` evaluates to false, it should not affect constraints on typevars - def undoUnless(block: => Boolean): Boolean = { - lock() - try { - val before = log - var result = false - - try result = block - finally if (!result) undoTo(before) - - result - } finally unlock() - } } /** A map from lists to compound types that have the given list as parents. @@ -295,7 +274,6 @@ trait Types extends api.Types { self: SymbolTable => abstract class TypeApiImpl extends TypeApi { this: Type => def declaration(name: Name): Symbol = decl(name) - def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name) def declarations = decls def typeArguments = typeArgs def erasure = this match { @@ -382,9 +360,6 @@ trait Types extends api.Types { self: SymbolTable => /** Is this type produced as a repair for an error? */ def isErroneous: Boolean = ErroneousCollector.collect(this) - /** Does this type denote a reference type which can be null? */ - // def isNullable: Boolean = false - /** Can this type only be subtyped by bottom types? * This is assessed to be the case if the class is final, * and all type parameters (if any) are invariant. @@ -522,11 +497,6 @@ trait Types extends api.Types { self: SymbolTable => /** Only used for dependent method types. */ def resultApprox: Type = ApproximateDependentMap(resultType) - /** If this is a TypeRef `clazz`[`T`], return the argument `T` - * otherwise return this type - */ - def remove(clazz: Symbol): Type = this - /** For a curried/nullary method or poly type its non-method result type, * the type itself for all other types */ def finalResultType: Type = this @@ -664,16 +634,6 @@ trait Types extends api.Types { self: SymbolTable => def nonPrivateMember(name: Name): Symbol = memberBasedOnName(name, BridgeAndPrivateFlags) - /** All members with the given flags, excluding bridges. - */ - def membersWithFlags(requiredFlags: Long): Scope = - membersBasedOnFlags(BridgeFlags, requiredFlags) - - /** All non-private members with the given flags, excluding bridges. - */ - def nonPrivateMembersWithFlags(requiredFlags: Long): Scope = - membersBasedOnFlags(BridgeAndPrivateFlags, requiredFlags) - /** The non-private member with given name, admitting members with given flags `admit`. * "Admitting" refers to the fact that members with a PRIVATE, BRIDGE, or VBRIDGE * flag are usually excluded from findMember results, but supplying any of those flags @@ -694,7 +654,6 @@ trait Types extends api.Types { self: SymbolTable => */ def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): Scope = findMembers(excludedFlags, requiredFlags) -// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives def memberBasedOnName(name: Name, excludedFlags: Long): Symbol = findMember(name, excludedFlags, 0, false) @@ -748,6 +707,7 @@ trait Types extends api.Types { self: SymbolTable => * }}} */ def memberInfo(sym: Symbol): Type = { + require(sym ne NoSymbol, this) sym.info.asSeenFrom(this, sym.owner) } @@ -808,7 +768,6 @@ trait Types extends api.Types { self: SymbolTable => else substThis(from, to).substSym(symsFrom, symsTo) /** Returns all parts of this type which satisfy predicate `p` */ - def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p) collect this def withFilter(p: Type => Boolean) = new FilterMapForeach(p) class FilterMapForeach(p: Type => Boolean) extends FilterTypeCollector(p){ @@ -838,9 +797,6 @@ trait Types extends api.Types { self: SymbolTable => /** Does this type contain a reference to this symbol? */ def contains(sym: Symbol): Boolean = new ContainsCollector(sym).collect(this) - /** Does this type contain a reference to this type */ - def containsTp(tp: Type): Boolean = new ContainsTypeCollector(tp).collect(this) - /** Is this type a subtype of that type? */ def <:<(that: Type): Boolean = { if (Statistics.canEnable) stat_<:<(that) @@ -901,11 +857,6 @@ trait Types extends api.Types { self: SymbolTable => else isSameType(this, that)) ); - /** Does this type implement symbol `sym` with same or stronger type? */ - def specializes(sym: Symbol): Boolean = - if (explainSwitch) explain("specializes", specializesSym, this, sym) - else specializesSym(this, sym) - /** Is this type close enough to that type so that members * with the two type would override each other? * This means: @@ -1050,69 +1001,66 @@ trait Types extends api.Types { self: SymbolTable => } def findMembers(excludedFlags: Long, requiredFlags: Long): Scope = { - // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by - // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements - // without this, the matchesType call would lead to type variables on both sides - // of a subtyping/equality judgement, which can lead to recursive types being constructed. - // See (t0851) for a situation where this happens. - val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this) - - if (Statistics.canEnable) Statistics.incCounter(findMembersCount) - val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMembersNanos) else null - - //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG - var members: Scope = null - var required = requiredFlags - var excluded = excludedFlags | DEFERRED - var continue = true - var self: Type = null - while (continue) { - continue = false - val bcs0 = baseClasses - var bcs = bcs0 - while (!bcs.isEmpty) { - val decls = bcs.head.info.decls - var entry = decls.elems - while (entry ne null) { - val sym = entry.sym - val flags = sym.flags - if ((flags & required) == required) { - val excl = flags & excluded - if (excl == 0L && - (// omit PRIVATE LOCALS unless selector class is contained in class owning the def. - (bcs eq bcs0) || - (flags & PrivateLocal) != PrivateLocal || - (bcs0.head.hasTransOwner(bcs.head)))) { - if (members eq null) members = newFindMemberScope - var others: ScopeEntry = members.lookupEntry(sym.name) - var symtpe: Type = null - while ((others ne null) && { - val other = others.sym - (other ne sym) && - ((other.owner eq sym.owner) || - (flags & PRIVATE) != 0 || { - if (self eq null) self = narrowForFindMember(this) - if (symtpe eq null) symtpe = self.memberType(sym) - !(self.memberType(other) matches symtpe) - })}) { - others = members lookupNextEntry others + def findMembersInternal: Scope = { + var members: Scope = null + if (Statistics.canEnable) Statistics.incCounter(findMembersCount) + val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMembersNanos) else null + + //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG + var required = requiredFlags + var excluded = excludedFlags | DEFERRED + var continue = true + var self: Type = null + while (continue) { + continue = false + val bcs0 = baseClasses + var bcs = bcs0 + while (!bcs.isEmpty) { + val decls = bcs.head.info.decls + var entry = decls.elems + while (entry ne null) { + val sym = entry.sym + val flags = sym.flags + if ((flags & required) == required) { + val excl = flags & excluded + if (excl == 0L && + (// omit PRIVATE LOCALS unless selector class is contained in class owning the def. + (bcs eq bcs0) || + (flags & PrivateLocal) != PrivateLocal || + (bcs0.head.hasTransOwner(bcs.head)))) { + if (members eq null) members = newFindMemberScope + var others: ScopeEntry = members.lookupEntry(sym.name) + var symtpe: Type = null + while ((others ne null) && { + val other = others.sym + (other ne sym) && + ((other.owner eq sym.owner) || + (flags & PRIVATE) != 0 || { + if (self eq null) self = narrowForFindMember(this) + if (symtpe eq null) symtpe = self.memberType(sym) + !(self.memberType(other) matches symtpe) + })}) { + others = members lookupNextEntry others + } + if (others eq null) members enter sym + } else if (excl == DEFERRED) { + continue = true } - if (others eq null) members enter sym - } else if (excl == DEFERRED) { - continue = true } - } - entry = entry.next - } // while (entry ne null) - // excluded = excluded | LOCAL - bcs = bcs.tail - } // while (!bcs.isEmpty) - required |= DEFERRED - excluded &= ~(DEFERRED.toLong) - } // while (continue) - if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) - if (suspension ne null) suspension foreach (_.suspended = false) - if (members eq null) EmptyScope else members + entry = entry.next + } // while (entry ne null) + // excluded = excluded | LOCAL + bcs = bcs.tail + } // while (!bcs.isEmpty) + required |= DEFERRED + excluded &= ~(DEFERRED.toLong) + } // while (continue) + if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) + if (members eq null) EmptyScope else members + } + + if (this.isGround) findMembersInternal + else suspendingTypeVars(typeVarsInType(this))(findMembersInternal) } /** @@ -1126,102 +1074,98 @@ trait Types extends api.Types { self: SymbolTable => */ //TODO: use narrow only for modules? (correct? efficiency gain?) def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean): Symbol = { - // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by - // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements - // without this, the matchesType call would lead to type variables on both sides - // of a subtyping/equality judgement, which can lead to recursive types being constructed. - // See (t0851) for a situation where this happens. - val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this) - - if (Statistics.canEnable) Statistics.incCounter(findMemberCount) - val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMemberNanos) else null - - //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG - var member: Symbol = NoSymbol - var members: List[Symbol] = null - var lastM: ::[Symbol] = null - var membertpe: Type = null - var required = requiredFlags - var excluded = excludedFlags | DEFERRED - var continue = true - var self: Type = null - - while (continue) { - continue = false - val bcs0 = baseClasses - var bcs = bcs0 - while (!bcs.isEmpty) { - val decls = bcs.head.info.decls - var entry = decls.lookupEntry(name) - while (entry ne null) { - val sym = entry.sym - val flags = sym.flags - if ((flags & required) == required) { - val excl = flags & excluded - if (excl == 0L && - (// omit PRIVATE LOCALS unless selector class is contained in class owning the def. - (bcs eq bcs0) || - (flags & PrivateLocal) != PrivateLocal || - (bcs0.head.hasTransOwner(bcs.head)))) { - if (name.isTypeName || stableOnly && sym.isStable) { - if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) - if (suspension ne null) suspension foreach (_.suspended = false) - return sym - } else if (member eq NoSymbol) { - member = sym - } else if (members eq null) { - if ((member ne sym) && - ((member.owner eq sym.owner) || - (flags & PRIVATE) != 0 || { - if (self eq null) self = narrowForFindMember(this) - if (membertpe eq null) membertpe = self.memberType(member) - !(membertpe matches self.memberType(sym)) - })) { - lastM = new ::(sym, null) - members = member :: lastM - } - } else { - var others: List[Symbol] = members - var symtpe: Type = null - while ((others ne null) && { - val other = others.head - (other ne sym) && - ((other.owner eq sym.owner) || + def findMemberInternal: Symbol = { + var member: Symbol = NoSymbol + var members: List[Symbol] = null + var lastM: ::[Symbol] = null + if (Statistics.canEnable) Statistics.incCounter(findMemberCount) + val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, findMemberNanos) else null + + //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG + var membertpe: Type = null + var required = requiredFlags + var excluded = excludedFlags | DEFERRED + var continue = true + var self: Type = null + + while (continue) { + continue = false + val bcs0 = baseClasses + var bcs = bcs0 + while (!bcs.isEmpty) { + val decls = bcs.head.info.decls + var entry = decls.lookupEntry(name) + while (entry ne null) { + val sym = entry.sym + val flags = sym.flags + if ((flags & required) == required) { + val excl = flags & excluded + if (excl == 0L && + (// omit PRIVATE LOCALS unless selector class is contained in class owning the def. + (bcs eq bcs0) || + (flags & PrivateLocal) != PrivateLocal || + (bcs0.head.hasTransOwner(bcs.head)))) { + if (name.isTypeName || stableOnly && sym.isStable) { + if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) + return sym + } else if (member eq NoSymbol) { + member = sym + } else if (members eq null) { + if ((member ne sym) && + ((member.owner eq sym.owner) || (flags & PRIVATE) != 0 || { if (self eq null) self = narrowForFindMember(this) - if (symtpe eq null) symtpe = self.memberType(sym) - !(self.memberType(other) matches symtpe) - })}) { - others = others.tail - } - if (others eq null) { - val lastM1 = new ::(sym, null) - lastM.tl = lastM1 - lastM = lastM1 + if (membertpe eq null) membertpe = self.memberType(member) + !(membertpe matches self.memberType(sym)) + })) { + lastM = new ::(sym, null) + members = member :: lastM + } + } else { + var others: List[Symbol] = members + var symtpe: Type = null + while ((others ne null) && { + val other = others.head + (other ne sym) && + ((other.owner eq sym.owner) || + (flags & PRIVATE) != 0 || { + if (self eq null) self = narrowForFindMember(this) + if (symtpe eq null) symtpe = self.memberType(sym) + !(self.memberType(other) matches symtpe) + })}) { + others = others.tail + } + if (others eq null) { + val lastM1 = new ::(sym, null) + lastM.tl = lastM1 + lastM = lastM1 + } } + } else if (excl == DEFERRED) { + continue = true } - } else if (excl == DEFERRED) { - continue = true } - } - entry = decls lookupNextEntry entry - } // while (entry ne null) - // excluded = excluded | LOCAL - bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail - } // while (!bcs.isEmpty) - required |= DEFERRED - excluded &= ~(DEFERRED.toLong) - } // while (continue) - if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) - if (suspension ne null) suspension foreach (_.suspended = false) - if (members eq null) { - if (member == NoSymbol) if (Statistics.canEnable) Statistics.incCounter(noMemberCount) - member - } else { - if (Statistics.canEnable) Statistics.incCounter(multMemberCount) - lastM.tl = Nil - baseClasses.head.newOverloaded(this, members) + entry = decls lookupNextEntry entry + } // while (entry ne null) + // excluded = excluded | LOCAL + bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail + } // while (!bcs.isEmpty) + required |= DEFERRED + excluded &= ~(DEFERRED.toLong) + } // while (continue) + if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) + if (members eq null) { + if (member == NoSymbol) if (Statistics.canEnable) Statistics.incCounter(noMemberCount) + member + } else { + if (Statistics.canEnable) Statistics.incCounter(multMemberCount) + lastM.tl = Nil + baseClasses.head.newOverloaded(this, members) + } } + + if (this.isGround) findMemberInternal + else suspendingTypeVars(typeVarsInType(this))(findMemberInternal) } /** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */ @@ -1250,10 +1194,6 @@ trait Types extends api.Types { self: SymbolTable => def setAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this) def withAnnotations(annots: List[AnnotationInfo]): Type = annotatedType(annots, this) - /** Remove any annotations from this type and from any - * types embedded in this type. */ - def stripAnnotations = StripAnnotationsMap(this) - /** Set the self symbol of an annotated type, or do nothing * otherwise. */ def withSelfsym(sym: Symbol) = this @@ -1346,7 +1286,6 @@ trait Types extends api.Types { self: SymbolTable => override def baseType(clazz: Symbol): Type = this override def safeToString: String = "<error>" override def narrow: Type = this - // override def isNullable: Boolean = true override def kind = "ErrorType" } @@ -1356,7 +1295,6 @@ trait Types extends api.Types { self: SymbolTable => case object WildcardType extends Type { override def isWildcard = true override def safeToString: String = "?" - // override def isNullable: Boolean = true override def kind = "WildcardType" } /** BoundedWildcardTypes, used only during type inference, are created in @@ -1381,7 +1319,6 @@ trait Types extends api.Types { self: SymbolTable => case object NoType extends Type { override def isTrivial: Boolean = true override def safeToString: String = "<notype>" - // override def isNullable: Boolean = true override def kind = "NoType" } @@ -1391,7 +1328,6 @@ trait Types extends api.Types { self: SymbolTable => override def isStable: Boolean = true override def prefixString = "" override def safeToString: String = "<noprefix>" - // override def isNullable: Boolean = true override def kind = "NoPrefixType" } @@ -1404,7 +1340,6 @@ trait Types extends api.Types { self: SymbolTable => assert(false, sym) } - //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym) override def isTrivial: Boolean = sym.isPackageClass override def isNotNull = true override def typeSymbol = sym @@ -1430,7 +1365,7 @@ trait Types extends api.Types { self: SymbolTable => def apply(sym: Symbol): Type = ( if (!phase.erasedTypes) unique(new UniqueThisType(sym)) else if (sym.isImplClass) sym.typeOfThis - else sym.tpe + else sym.tpe_* ) } @@ -1445,7 +1380,6 @@ trait Types extends api.Types { self: SymbolTable => } override def isGround = sym.isPackageClass || pre.isGround - // override def isNullable = underlying.isNullable override def isNotNull = underlying.isNotNull private[reflect] var underlyingCache: Type = NoType private[reflect] var underlyingPeriod = NoPeriod @@ -1543,11 +1477,10 @@ trait Types extends api.Types { self: SymbolTable => } private def lowerString = if (emptyLowerBound) "" else " >: " + lo private def upperString = if (emptyUpperBound) "" else " <: " + hi - private def emptyLowerBound = typeIsNothing(lo) - private def emptyUpperBound = typeIsAny(hi) + private def emptyLowerBound = typeIsNothing(lo) || lo.isWildcard + private def emptyUpperBound = typeIsAny(hi) || hi.isWildcard def isEmptyBounds = emptyLowerBound && emptyUpperBound - // override def isNullable: Boolean = NullClass.tpe <:< lo; override def safeToString = lowerString + upperString override def kind = "TypeBoundsType" } @@ -1632,15 +1565,44 @@ trait Types extends api.Types { self: SymbolTable => override def isStructuralRefinement: Boolean = typeSymbol.isAnonOrRefinementClass && (decls exists symbolIsPossibleInRefinement) - // override def isNullable: Boolean = - // parents forall (p => p.isNullable && !p.typeSymbol.isAbstractType); - override def safeToString: String = parentsString(parents) + ( (if (settings.debug.value || parents.isEmpty || (decls.elems ne null)) fullyInitializeScope(decls).mkString("{", "; ", "}") else "") ) } + protected def computeBaseClasses(tpe: Type): List[Symbol] = { + val parents = tpe.parents // adriaan says tpe.parents does work sometimes, so call it only once + val baseTail = ( + if (parents.isEmpty || parents.head.isInstanceOf[PackageTypeRef]) Nil + else { + //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG + // optimized, since this seems to be performance critical + val superclazz = parents.head // parents.isEmpty was already excluded + var mixins = parents.tail + val sbcs = superclazz.baseClasses + var bcs = sbcs + def isNew(clazz: Symbol): Boolean = ( + superclazz.baseTypeIndex(clazz) < 0 && + { var p = bcs; + while ((p ne sbcs) && (p.head != clazz)) p = p.tail; + p eq sbcs + } + ) + while (!mixins.isEmpty) { + def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] = + if (mbcs.isEmpty) bcs + else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail) + else addMixinBaseClasses(mbcs.tail) + bcs = addMixinBaseClasses(mixins.head.baseClasses) + mixins = mixins.tail + } + bcs + } + ) + tpe.typeSymbol :: baseTail + } + protected def defineBaseTypeSeqOfCompoundType(tpe: CompoundType) = { val period = tpe.baseTypeSeqPeriod if (period != currentPeriod) { @@ -1660,7 +1622,7 @@ trait Types extends api.Types { self: SymbolTable => val paramToVarMap = varToParamMap map (_.swap) val varToParam = new TypeMap { def apply(tp: Type) = varToParamMap get tp match { - case Some(sym) => sym.tpe + case Some(sym) => sym.tpe_* case _ => mapOver(tp) } } @@ -1679,7 +1641,7 @@ trait Types extends api.Types { self: SymbolTable => tpe.baseTypeSeqCache = undetBaseTypeSeq tpe.baseTypeSeqCache = if (tpe.typeSymbol.isRefinementClass) - tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe) + tpe.memo(compoundBaseTypeSeq(tpe))(_.baseTypeSeq updateHead tpe.typeSymbol.tpe_*) else compoundBaseTypeSeq(tpe) } finally { @@ -1701,41 +1663,61 @@ trait Types extends api.Types { self: SymbolTable => throw new TypeError("illegal cyclic inheritance involving " + tpe.typeSymbol) } - protected def defineBaseClassesOfCompoundType(tpe: CompoundType) = { - def computeBaseClasses: List[Symbol] = - if (tpe.parents.isEmpty) List(tpe.typeSymbol) - else { - //Console.println("computing base classes of " + typeSymbol + " at phase " + phase);//DEBUG - // optimized, since this seems to be performance critical - val superclazz = tpe.firstParent - var mixins = tpe.parents.tail - val sbcs = superclazz.baseClasses - var bcs = sbcs - def isNew(clazz: Symbol): Boolean = - superclazz.baseTypeIndex(clazz) < 0 && - { var p = bcs; - while ((p ne sbcs) && (p.head != clazz)) p = p.tail; - p eq sbcs - } - while (!mixins.isEmpty) { - def addMixinBaseClasses(mbcs: List[Symbol]): List[Symbol] = - if (mbcs.isEmpty) bcs - else if (isNew(mbcs.head)) mbcs.head :: addMixinBaseClasses(mbcs.tail) - else addMixinBaseClasses(mbcs.tail) - bcs = addMixinBaseClasses(mixins.head.baseClasses) - mixins = mixins.tail + object baseClassesCycleMonitor { + private var open: List[Symbol] = Nil + @inline private def cycleLog(msg: => String) { + if (settings.debug.value) + Console.err.println(msg) + } + def size = open.size + def push(clazz: Symbol) { + cycleLog("+ " + (" " * size) + clazz.fullNameString) + open ::= clazz + } + def pop(clazz: Symbol) { + assert(open.head eq clazz, (clazz, open)) + open = open.tail + } + def isOpen(clazz: Symbol) = open contains clazz + } + + protected def defineBaseClassesOfCompoundType(tpe: CompoundType) { + def define() = defineBaseClassesOfCompoundType(tpe, force = false) + if (!breakCycles || isPastTyper) define() + else tpe match { + // non-empty parents helpfully excludes all package classes + case tpe @ ClassInfoType(_ :: _, _, clazz) if !clazz.isAnonOrRefinementClass => + // Cycle: force update + if (baseClassesCycleMonitor isOpen clazz) + defineBaseClassesOfCompoundType(tpe, force = true) + else { + baseClassesCycleMonitor push clazz + try define() + finally baseClassesCycleMonitor pop clazz } - tpe.typeSymbol :: bcs - } + case _ => + define() + } + } + private def defineBaseClassesOfCompoundType(tpe: CompoundType, force: Boolean) { val period = tpe.baseClassesPeriod - if (period != currentPeriod) { + if (period == currentPeriod) { + if (force && breakCycles) { + def what = tpe.typeSymbol + " in " + tpe.typeSymbol.owner.fullNameString + val bcs = computeBaseClasses(tpe) + tpe.baseClassesCache = bcs + warning(s"Breaking cycle in base class computation of $what ($bcs)") + } + } + else { tpe.baseClassesPeriod = currentPeriod if (!isValidForBaseClasses(period)) { val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, baseClassesNanos) else null try { tpe.baseClassesCache = null - tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail) - } finally { + tpe.baseClassesCache = tpe.memo(computeBaseClasses(tpe))(tpe.typeSymbol :: _.baseClasses.tail) + } + finally { if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) } } @@ -1931,7 +1913,7 @@ trait Types extends api.Types { self: SymbolTable => case tr @ TypeRef(_, sym, args) if args.nonEmpty => val tparams = tr.initializedTypeParams if (settings.debug.value && !sameLength(tparams, args)) - debugwarn("Mismatched zip in computeRefs(): " + sym.info.typeParams + ", " + args) + devWarning(s"Mismatched zip in computeRefs(): ${sym.info.typeParams}, $args") foreach2(tparams, args) { (tparam1, arg) => if (arg contains tparam) { @@ -1974,7 +1956,7 @@ trait Types extends api.Types { self: SymbolTable => var change = false for ((from, targets) <- refs(NonExpansive).iterator) for (target <- targets) { - var thatInfo = classInfo(target) + val thatInfo = classInfo(target) if (thatInfo.state != Initialized) change = change | thatInfo.propagate() addRefs(NonExpansive, from, thatInfo.getRefs(NonExpansive, target)) @@ -1982,7 +1964,7 @@ trait Types extends api.Types { self: SymbolTable => } for ((from, targets) <- refs(Expansive).iterator) for (target <- targets) { - var thatInfo = classInfo(target) + val thatInfo = classInfo(target) if (thatInfo.state != Initialized) change = change | thatInfo.propagate() addRefs(Expansive, from, thatInfo.getRefs(NonExpansive, target)) @@ -1993,11 +1975,6 @@ trait Types extends api.Types { self: SymbolTable => change } - // override def isNullable: Boolean = - // symbol == AnyClass || - // symbol != NothingClass && (symbol isSubClass ObjectClass) && !(symbol isSubClass NonNullClass); - - // override def isNonNull: Boolean = symbol == NonNullClass || super.isNonNull; override def kind = "ClassInfoType" override def safeToString = @@ -2022,8 +1999,6 @@ trait Types extends api.Types { self: SymbolTable => extends ClassInfoType(List(), decls, clazz) /** A class representing a constant type. - * - * @param value ... */ abstract case class ConstantType(value: Constant) extends SingletonType with ConstantTypeApi { override def underlying: Type = value.tpe @@ -2033,8 +2008,6 @@ trait Types extends api.Types { self: SymbolTable => override def deconst: Type = underlying override def safeToString: String = underlying.toString + "(" + value.escapedStringValue + ")" - // override def isNullable: Boolean = value.value eq null - // override def isNonNull: Boolean = value.value ne null override def kind = "ConstantType" } @@ -2064,7 +2037,7 @@ trait Types extends api.Types { self: SymbolTable => // it later turns out not to have kind *. See SI-4070. Only // logging it for now. if (sym.typeParams.size != args.size) - log("!!! %s.transform(%s), but tparams.isEmpty and args=".format(this, tp, args)) + devWarning(s"$this.transform($tp), but tparams.isEmpty and args=$args") asSeenFromOwner(tp).instantiateTypeParams(sym.typeParams, args) } @@ -2296,7 +2269,6 @@ trait Types extends api.Types { self: SymbolTable => } override def isStable = bounds.hi.typeSymbol isSubClass SingletonClass override def bounds = thisInfo.bounds - // def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies) override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this override def kind = "AbstractTypeRef" } @@ -2833,9 +2805,13 @@ trait Types extends api.Types { self: SymbolTable => override def kind = "OverloadedType" } - def overloadedType(pre: Type, alternatives: List[Symbol]): Type = - if (alternatives.tail.isEmpty) pre memberType alternatives.head - else OverloadedType(pre, alternatives) + /** The canonical creator for OverloadedTypes. + */ + def overloadedType(pre: Type, alternatives: List[Symbol]): Type = alternatives match { + case Nil => NoType + case alt :: Nil => pre memberType alt + case _ => OverloadedType(pre, alternatives) + } /** A class remembering a type instantiation for some a set of overloaded * polymorphic symbols. @@ -2845,21 +2821,9 @@ trait Types extends api.Types { self: SymbolTable => override def safeToString = pre.toString + targs.mkString("(with type arguments ", ", ", ")"); override def memberType(sym: Symbol) = appliedType(pre.memberType(sym), targs) -// override def memberType(sym: Symbol) = pre.memberType(sym) match { -// case PolyType(tparams, restp) => -// restp.subst(tparams, targs) -// /* I don't think this is needed, as existential types close only over value types -// case ExistentialType(tparams, qtpe) => -// existentialAbstraction(tparams, qtpe.memberType(sym)) -// */ -// case ErrorType => -// ErrorType -// } override def kind = "AntiPolyType" } - //private var tidCount = 0 //DEBUG - object HasTypeMember { def apply(name: TypeName, tp: Type): Type = { val bound = refinedType(List(WildcardType), NoSymbol) @@ -2874,16 +2838,6 @@ trait Types extends api.Types { self: SymbolTable => } } - // Not used yet. - object HasTypeParams { - def unapply(tp: Type): Option[(List[Symbol], Type)] = tp match { - case AnnotatedType(_, tp, _) => unapply(tp) - case ExistentialType(tparams, qtpe) => Some((tparams, qtpe)) - case PolyType(tparams, restpe) => Some((tparams, restpe)) - case _ => None - } - } - //@M // a TypeVar used to be a case class with only an origin and a constr // then, constr became mutable (to support UndoLog, I guess), @@ -2977,7 +2931,6 @@ trait Types extends api.Types { self: SymbolTable => require(params.nonEmpty, this) override def isHigherKinded = true - override protected def typeVarString = params.map(_.name).mkString("[", ", ", "]=>" + originName) } /** Precondition: zipped params/args nonEmpty. (Size equivalence enforced structurally.) @@ -2992,10 +2945,6 @@ trait Types extends api.Types { self: SymbolTable => override def params: List[Symbol] = zippedArgs map (_._1) override def typeArgs: List[Type] = zippedArgs map (_._2) - - override protected def typeVarString = ( - zippedArgs map { case (p, a) => p.name + "=" + a } mkString (origin + "[", ", ", "]") - ) } trait UntouchableTypeVar extends TypeVar { @@ -3039,7 +2988,6 @@ trait Types extends api.Types { self: SymbolTable => * in operations that are exposed from types. Hence, no syncing of `constr` * or `encounteredHigherLevel` or `suspended` accesses should be necessary. */ -// var constr = constr0 def instValid = constr.instValid override def isGround = instValid && constr.inst.isGround @@ -3092,7 +3040,10 @@ trait Types extends api.Types { self: SymbolTable => // invariant: before mutating constr, save old state in undoLog // (undoLog is used to reset constraints to avoid piling up unrelated ones) def setInst(tp: Type) { -// assert(!(tp containsTp this), this) + if (tp eq this) { + log(s"TypeVar cycle: called setInst passing $this to itself.") + return + } undoLog record this // if we were compared against later typeskolems, repack the existential, // because skolems are only compatible if they were created at the same level @@ -3237,16 +3188,19 @@ trait Types extends api.Types { self: SymbolTable => def registerTypeEquality(tp: Type, typeVarLHS: Boolean): Boolean = { // println("regTypeEq: "+(safeToString, debugString(tp), tp.getClass, if (typeVarLHS) "in LHS" else "in RHS", if (suspended) "ZZ" else if (constr.instValid) "IV" else "")) //@MDEBUG -// println("constr: "+ constr) - def checkIsSameType(tp: Type) = - if(typeVarLHS) constr.inst =:= tp - else tp =:= constr.inst + def checkIsSameType(tp: Type) = ( + if (typeVarLHS) constr.inst =:= tp + else tp =:= constr.inst + ) if (suspended) tp =:= origin else if (constr.instValid) checkIsSameType(tp) else isRelatable(tp) && { val newInst = wildcardToTypeVarMap(tp) - (constr isWithinBounds newInst) && { setInst(tp); true } + (constr isWithinBounds newInst) && { + setInst(newInst) + true + } } } @@ -3309,7 +3263,6 @@ trait Types extends api.Types { self: SymbolTable => ).flatten map (s => s.decodedName + tparamsOfSym(s)) mkString "#" } private def levelString = if (settings.explaintypes.value) level else "" - protected def typeVarString = originName override def safeToString = ( if ((constr eq null) || (constr.inst eq null)) "TVar<" + originName + "=null>" else if (constr.inst ne NoType) "=?" + constr.inst @@ -3420,22 +3373,12 @@ trait Types extends api.Types { self: SymbolTable => case class NamedType(name: Name, tp: Type) extends Type { override def safeToString: String = name.toString +": "+ tp } - - /** A De Bruijn index referring to a previous type argument. Only used - * as a serialization format. - */ - case class DeBruijnIndex(level: Int, idx: Int, args: List[Type]) extends Type { - override def safeToString: String = "De Bruijn index("+level+","+idx+")" - } - - /** A binder defining data associated with De Bruijn indices. Only used - * as a serialization format. + /** As with NamedType, used only when calling isApplicable. + * Records that the application has a wildcard star (aka _*) + * at the end of it. */ - case class DeBruijnBinder(pnames: List[Name], ptypes: List[Type], restpe: Type) extends Type { - override def safeToString = { - val kind = if (pnames.head.isTypeName) "poly" else "method" - "De Bruijn "+kind+"("+(pnames mkString ",")+";"+(ptypes mkString ",")+";"+restpe+")" - } + case class RepeatedType(tp: Type) extends Type { + override def safeToString: String = tp + ": _*" } /** A temporary type representing the erasure of a user-defined value type. @@ -3480,11 +3423,6 @@ trait Types extends api.Types { self: SymbolTable => (if (typeParams.isEmpty) "" else typeParamsString(this)) + super.safeToString } - // def mkLazyType(tparams: Symbol*)(f: Symbol => Unit): LazyType = ( - // if (tparams.isEmpty) new LazyType { override def complete(sym: Symbol) = f(sym) } - // else new LazyPolyType(tparams.toList) { override def complete(sym: Symbol) = f(sym) } - // ) - // Creators --------------------------------------------------------------- /** Rebind symbol `sym` to an overriding member in type `pre`. */ @@ -3529,10 +3467,6 @@ trait Types extends api.Types { self: SymbolTable => } /** The canonical creator for a refined type with an initially empty scope. - * - * @param parents ... - * @param owner ... - * @return ... */ def refinedType(parents: List[Type], owner: Symbol): Type = refinedType(parents, owner, newScope, owner.pos) @@ -3571,12 +3505,6 @@ trait Types extends api.Types { self: SymbolTable => val pre1 = pre match { case x: SuperType if sym1.isEffectivelyFinal || sym1.isDeferred => x.thistpe - case _: CompoundType if sym1.isClass => - // sharpen prefix so that it is maximal and still contains the class. - pre.parents.reverse dropWhile (_.member(sym1.name) != sym1) match { - case Nil => pre - case parent :: _ => parent - } case _ => pre } if (pre eq pre1) TypeRef(pre, sym1, args) @@ -3658,16 +3586,16 @@ trait Types extends api.Types { self: SymbolTable => tycon match { case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing - case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args) + case TypeRef(pre, sym, Nil) => copyTypeRef(tycon, pre, sym, args) + case TypeRef(pre, sym, bogons) => devWarning(s"Dropping $bogons from $tycon in appliedType.") ; copyTypeRef(tycon, pre, sym, args) case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args) case ExistentialType(tparams, restpe) => newExistentialType(tparams, appliedType(restpe, args)) case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1 - case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check - case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) + case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // @PP: Can this be right? + case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) // @PP: Can this be right? case tv@TypeVar(_, _) => tv.applyArgs(args) case AnnotatedType(annots, underlying, self) => AnnotatedType(annots, appliedType(underlying, args), self) - case ErrorType => tycon - case WildcardType => tycon // needed for neg/t0226 + case ErrorType | WildcardType => tycon case _ => abort(debugString(tycon)) } } @@ -3676,25 +3604,6 @@ trait Types extends api.Types { self: SymbolTable => def appliedType(tyconSym: Symbol, args: Type*): Type = appliedType(tyconSym.typeConstructor, args.toList) - /** A creator for existential types where the type arguments, - * rather than being applied directly, are interpreted as the - * upper bounds of unknown types. For instance if the type argument - * list given is List(AnyRefClass), the resulting type would be - * e.g. Set[_ <: AnyRef] rather than Set[AnyRef] . - */ - def appliedTypeAsUpperBounds(tycon: Type, args: List[Type]): Type = { - tycon match { - case TypeRef(pre, sym, _) if sameLength(sym.typeParams, args) => - val eparams = typeParamsToExistentials(sym) - val bounds = args map (TypeBounds upper _) - foreach2(eparams, bounds)(_ setInfo _) - - newExistentialType(eparams, typeRef(pre, sym, eparams map (_.tpe))) - case _ => - appliedType(tycon, args) - } - } - /** A creator and extractor for type parameterizations that strips empty type parameter lists. * Use this factory method to indicate the type has kind * (it's a polymorphic value) * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty). @@ -3796,18 +3705,6 @@ trait Types extends api.Types { self: SymbolTable => } } - /** Substitutes the empty scope for any non-empty decls in the type. */ - object dropAllRefinements extends TypeMap { - def apply(tp: Type): Type = tp match { - case rt @ RefinedType(parents, decls) if !decls.isEmpty => - mapOver(copyRefinedType(rt, parents, EmptyScope)) - case ClassInfoType(parents, decls, clazz) if !decls.isEmpty => - mapOver(ClassInfoType(parents, EmptyScope, clazz)) - case _ => - mapOver(tp) - } - } - /** Type with all top-level occurrences of abstract types replaced by their bounds */ def abstractTypesToBounds(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala ) case TypeRef(_, sym, _) if sym.isAbstractType => @@ -3830,12 +3727,16 @@ trait Types extends api.Types { self: SymbolTable => // This is the specified behavior. protected def etaExpandKeepsStar = false - object dropRepeatedParamType extends TypeMap { + /** Turn any T* types into Seq[T] except when + * in method parameter position. + */ + object dropIllegalStarTypes extends TypeMap { def apply(tp: Type): Type = tp match { case MethodType(params, restpe) => - MethodType(params, apply(restpe)) - case PolyType(tparams, restpe) => - PolyType(tparams, apply(restpe)) + // Not mapping over params + val restpe1 = apply(restpe) + if (restpe eq restpe1) tp + else MethodType(params, restpe1) case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg) case _ => @@ -3843,50 +3744,6 @@ trait Types extends api.Types { self: SymbolTable => } } - object toDeBruijn extends TypeMap { - private var paramStack: List[List[Symbol]] = Nil - def mkDebruijnBinder(params: List[Symbol], restpe: Type) = { - paramStack = params :: paramStack - try { - DeBruijnBinder(params map (_.name), params map (p => this(p.info)), this(restpe)) - } finally paramStack = paramStack.tail - } - def apply(tp: Type): Type = tp match { - case PolyType(tparams, restpe) => - mkDebruijnBinder(tparams, restpe) - case MethodType(params, restpe) => - mkDebruijnBinder(params, restpe) - case TypeRef(NoPrefix, sym, args) => - val level = paramStack indexWhere (_ contains sym) - if (level < 0) mapOver(tp) - else DeBruijnIndex(level, paramStack(level) indexOf sym, args mapConserve this) - case _ => - mapOver(tp) - } - } - - def fromDeBruijn(owner: Symbol) = new TypeMap { - private var paramStack: List[List[Symbol]] = Nil - def apply(tp: Type): Type = tp match { - case DeBruijnBinder(pnames, ptypes, restpe) => - val isType = pnames.head.isTypeName - val newParams = for (name <- pnames) yield - if (isType) owner.newTypeParameter(name.toTypeName) - else owner.newValueParameter(name.toTermName) - paramStack = newParams :: paramStack - try { - foreach2(newParams, ptypes)((p, t) => p setInfo this(t)) - val restpe1 = this(restpe) - if (isType) PolyType(newParams, restpe1) - else MethodType(newParams, restpe1) - } finally paramStack = paramStack.tail - case DeBruijnIndex(level, idx, args) => - TypeRef(NoPrefix, paramStack(level)(idx), args map this) - case _ => - mapOver(tp) - } - } - // Hash consing -------------------------------------------------------------- private val initialUniquesCapacity = 4096 @@ -4092,7 +3949,7 @@ trait Types extends api.Types { self: SymbolTable => variance = -variance val tparams1 = mapOver(tparams) variance = -variance - var result1 = this(result) + val result1 = this(result) if ((tparams1 eq tparams) && (result1 eq result)) tp else PolyType(tparams1, result1.substSym(tparams, tparams1)) case TypeBounds(lo, hi) => @@ -4154,7 +4011,7 @@ trait Types extends api.Types { self: SymbolTable => else copyMethodType(tp, params1, result1.substSym(params, params1)) case PolyType(tparams, result) => val tparams1 = mapOver(tparams) - var result1 = this(result) + val result1 = this(result) if ((tparams1 eq tparams) && (result1 eq result)) tp else PolyType(tparams1, result1.substSym(tparams, tparams1)) case NullaryMethodType(result) => @@ -4179,12 +4036,10 @@ trait Types extends api.Types { self: SymbolTable => case rtp @ RefinedType(parents, decls) => val parents1 = parents mapConserve this val decls1 = mapOver(decls) - //if ((parents1 eq parents) && (decls1 eq decls)) tp - //else refinementOfClass(tp.typeSymbol, parents1, decls1) copyRefinedType(rtp, parents1, decls1) case ExistentialType(tparams, result) => val tparams1 = mapOver(tparams) - var result1 = this(result) + val result1 = this(result) if ((tparams1 eq tparams) && (result1 eq result)) tp else newExistentialType(tparams1, result1.substSym(tparams, tparams1)) case OverloadedType(pre, alts) => @@ -4209,10 +4064,6 @@ trait Types extends api.Types { self: SymbolTable => if ((annots1 eq annots) && (atp1 eq atp)) tp else if (annots1.isEmpty) atp1 else AnnotatedType(annots1, atp1, selfsym) - case DeBruijnIndex(shift, idx, args) => - val args1 = args mapConserve this - if (args1 eq args) tp - else DeBruijnIndex(shift, idx, args1) /* case ErrorType => tp case WildcardType => tp @@ -4319,21 +4170,6 @@ trait Types extends api.Types { self: SymbolTable => } } - /** A collector that tests for existential types appearing at given variance in a type - * @PP: Commenting out due to not being used anywhere. - */ - // class ContainsVariantExistentialCollector(v: Int) extends TypeCollector(false) with VariantTypeMap { - // variance = v - // - // def traverse(tp: Type) = tp match { - // case ExistentialType(_, _) if (variance == v) => result = true - // case _ => mapOver(tp) - // } - // } - // - // val containsCovariantExistentialCollector = new ContainsVariantExistentialCollector(1) - // val containsContravariantExistentialCollector = new ContainsVariantExistentialCollector(-1) - def typeParamsToExistentials(clazz: Symbol, tparams: List[Symbol]): List[Symbol] = { val eparams = mapWithIndex(tparams)((tparam, i) => clazz.newExistential(newTypeName("?"+i), clazz.pos) setInfo tparam.info.bounds) @@ -4381,6 +4217,20 @@ trait Types extends api.Types { self: SymbolTable => mapOver(tp) } } + /*** + *@M: I think this is more desirable, but Martin prefers to leave raw-types as-is as much as possible + object rawToExistentialInJava extends TypeMap { + def apply(tp: Type): Type = tp match { + // any symbol that occurs in a java sig, not just java symbols + // see http://lampsvn.epfl.ch/trac/scala/ticket/2454#comment:14 + case TypeRef(pre, sym, List()) if !sym.typeParams.isEmpty => + val eparams = typeParamsToExistentials(sym, sym.typeParams) + existentialAbstraction(eparams, TypeRef(pre, sym, eparams map (_.tpe))) + case _ => + mapOver(tp) + } + } + */ /** Used by existentialAbstraction. */ @@ -4615,16 +4465,18 @@ trait Types extends api.Types { self: SymbolTable => tp } - def apply(tp0: Type): Type = if (from.isEmpty) tp0 else { - @tailrec def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type = - if (from.isEmpty) tp - // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from)) - else if (matches(from.head, sym)) toType(tp, to.head) - else subst(tp, sym, from.tail, to.tail) + @tailrec private def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type = ( + if (from.isEmpty) tp + // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(tp, from)) + else if (matches(from.head, sym)) toType(tp, to.head) + else subst(tp, sym, from.tail, to.tail) + ) - val boundSyms = tp0.boundSyms - val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0 - val tp = mapOver(tp1) + def apply(tp0: Type): Type = if (from.isEmpty) tp0 else { + val boundSyms = tp0.boundSyms + val tp1 = if (boundSyms.nonEmpty && (boundSyms exists from.contains)) renameBoundSyms(tp0) else tp0 + val tp = mapOver(tp1) + def substFor(sym: Symbol) = subst(tp, sym, from, to) tp match { // @M @@ -4639,9 +4491,11 @@ trait Types extends api.Types { self: SymbolTable => // (must not recurse --> loops) // 3) replacing m by List in m[Int] should yield List[Int], not just List case TypeRef(NoPrefix, sym, args) => - appliedType(subst(tp, sym, from, to), args) // if args.isEmpty, appliedType is the identity + val tcon = substFor(sym) + if ((tp eq tcon) || args.isEmpty) tcon + else appliedType(tcon.typeConstructor, args) case SingleType(NoPrefix, sym) => - subst(tp, sym, from, to) + substFor(sym) case _ => tp } @@ -4650,29 +4504,35 @@ trait Types extends api.Types { self: SymbolTable => /** A map to implement the `substSym` method. */ class SubstSymMap(from: List[Symbol], to: List[Symbol]) extends SubstMap(from, to) { + def this(pairs: (Symbol, Symbol)*) = this(pairs.toList.map(_._1), pairs.toList.map(_._2)) + protected def toType(fromtp: Type, sym: Symbol) = fromtp match { case TypeRef(pre, _, args) => copyTypeRef(fromtp, pre, sym, args) case SingleType(pre, _) => singleType(pre, sym) } - override def apply(tp: Type): Type = if (from.isEmpty) tp else { - @tailrec def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = - if (from.isEmpty) sym - // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from)) - else if (matches(from.head, sym)) to.head - else subst(sym, from.tail, to.tail) - tp match { + @tailrec private def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = ( + if (from.isEmpty) sym + // else if (to.isEmpty) error("Unexpected substitution on '%s': from = %s but to == Nil".format(sym, from)) + else if (matches(from.head, sym)) to.head + else subst(sym, from.tail, to.tail) + ) + private def substFor(sym: Symbol) = subst(sym, from, to) + + override def apply(tp: Type): Type = ( + if (from.isEmpty) tp + else tp match { case TypeRef(pre, sym, args) if pre ne NoPrefix => - val newSym = subst(sym, from, to) + val newSym = substFor(sym) // mapOver takes care of subst'ing in args mapOver ( if (sym eq newSym) tp else copyTypeRef(tp, pre, newSym, args) ) // assert(newSym.typeParams.length == sym.typeParams.length, "typars mismatch in SubstSymMap: "+(sym, sym.typeParams, newSym, newSym.typeParams)) case SingleType(pre, sym) if pre ne NoPrefix => - val newSym = subst(sym, from, to) + val newSym = substFor(sym) mapOver( if (sym eq newSym) tp else singleType(pre, newSym) ) case _ => super.apply(tp) } - } + ) override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = { object trans extends TypeMapTransformer { @@ -4843,15 +4703,6 @@ trait Types extends api.Types { self: SymbolTable => } } - object StripAnnotationsMap extends TypeMap { - def apply(tp: Type): Type = tp match { - case AnnotatedType(_, atp, _) => - mapOver(atp) - case tp => - mapOver(tp) - } - } - /** A map to convert every occurrence of a wildcard type to a fresh * type variable */ object wildcardToTypeVarMap extends TypeMap { @@ -4913,8 +4764,6 @@ trait Types extends api.Types { self: SymbolTable => /** A map to implement the `filter` method. */ class FilterTypeCollector(p: Type => Boolean) extends TypeCollector[List[Type]](Nil) { - def withFilter(q: Type => Boolean) = new FilterTypeCollector(tp => p(tp) && q(tp)) - override def collect(tp: Type) = super.collect(tp).reverse def traverse(tp: Type) { @@ -5024,7 +4873,7 @@ trait Types extends api.Types { self: SymbolTable => else { var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true) orElse { if (sym.isAliasType) throw missingAliasException - debugwarn(pre+"."+sym+" does no longer exist, phase = "+phase) + devWarning(s"$pre.$sym no longer exist at phase $phase") throw new MissingTypeControl // For build manager and presentation compiler purposes } /** The two symbols have the same fully qualified name */ @@ -5082,7 +4931,7 @@ trait Types extends api.Types { self: SymbolTable => if ((pre1 eq pre) && (sym1 eq sym) && (args1 eq args)/* && sym.isExternal*/) { tp } else if (sym1 == NoSymbol) { - debugwarn("adapt fail: "+pre+" "+pre1+" "+sym) + devWarning(s"adapt to new run failed: pre=$pre pre1=$pre1 sym=$sym") tp } else { copyTypeRef(tp, pre1, sym1, args1) @@ -5133,28 +4982,18 @@ trait Types extends api.Types { self: SymbolTable => class SubTypePair(val tp1: Type, val tp2: Type) { override def hashCode = tp1.hashCode * 41 + tp2.hashCode - override def equals(other: Any) = other match { + override def equals(other: Any) = (this eq other.asInstanceOf[AnyRef]) || (other match { + // suspend TypeVars in types compared by =:=, + // since we don't want to mutate them simply to check whether a subtype test is pending + // in addition to making subtyping "more correct" for type vars, + // it should avoid the stackoverflow that's been plaguing us (https://groups.google.com/d/topic/scala-internals/2gHzNjtB4xA/discussion) + // this method is only called when subtyping hits a recursion threshold (subsametypeRecursions >= LogPendingSubTypesThreshold) case stp: SubTypePair => - // suspend TypeVars in types compared by =:=, - // since we don't want to mutate them simply to check whether a subtype test is pending - // in addition to making subtyping "more correct" for type vars, - // it should avoid the stackoverflow that's been plaguing us (https://groups.google.com/d/topic/scala-internals/2gHzNjtB4xA/discussion) - // this method is only called when subtyping hits a recursion threshold (subsametypeRecursions >= LogPendingSubTypesThreshold) - def suspend(tp: Type) = - if (tp.isGround) null else suspendTypeVarsInType(tp) - def revive(suspension: List[TypeVar]) = - if (suspension ne null) suspension foreach (_.suspended = false) - - val suspensions = Array(tp1, stp.tp1, tp2, stp.tp2) map suspend - - val sameTypes = (tp1 =:= stp.tp1) && (tp2 =:= stp.tp2) - - suspensions foreach revive - - sameTypes + val tvars = List(tp1, stp.tp1, tp2, stp.tp2) flatMap (t => if (t.isGround) Nil else typeVarsInType(t)) + suspendingTypeVars(tvars)(tp1 =:= stp.tp1 && tp2 =:= stp.tp2) case _ => false - } + }) override def toString = tp1+" <:<? "+tp2 } @@ -5226,32 +5065,33 @@ trait Types extends api.Types { self: SymbolTable => def isPopulated(tp1: Type, tp2: Type): Boolean = { def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match { case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => - assert(sym1 == sym2) + assert(sym1 == sym2, (sym1, sym2)) pre1 =:= pre2 && - forall3(args1, args2, sym1.typeParams) { (arg1, arg2, tparam) => - //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG + forall3(args1, args2, sym1.typeParams)((arg1, arg2, tparam) => if (tparam.variance == 0) arg1 =:= arg2 - else if (arg1.isInstanceOf[TypeVar]) - // if left-hand argument is a typevar, make it compatible with variance - // this is for more precise pattern matching - // todo: work this in the spec of this method - // also: think what happens if there are embedded typevars? - if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1 - else true - } + // if left-hand argument is a typevar, make it compatible with variance + // this is for more precise pattern matching + // todo: work this in the spec of this method + // also: think what happens if there are embedded typevars? + else arg1 match { + case _: TypeVar => if (tparam.variance < 0) arg1 <:< arg2 else arg2 <:< arg1 + case _ => true + } + ) case (et: ExistentialType, _) => et.withTypeVars(isConsistent(_, tp2)) case (_, et: ExistentialType) => et.withTypeVars(isConsistent(tp1, _)) } - def check(tp1: Type, tp2: Type) = + def check(tp1: Type, tp2: Type) = ( if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL)) tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol) else tp1.baseClasses forall (bc => tp2.baseTypeIndex(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc))) + ) - check(tp1, tp2)/* && check(tp2, tp1)*/ // need to investgate why this can't be made symmetric -- neg/gadts1 fails, and run/existials also. + check(tp1, tp2) && check(tp2, tp1) } /** Does a pattern of type `patType` need an outer test when executed against @@ -5334,13 +5174,15 @@ trait Types extends api.Types { self: SymbolTable => try { val before = undoLog.log var result = false - - try result = { - isSameType1(tp1, tp2) - } finally if (!result) undoLog.undoTo(before) + try { + result = isSameType1(tp1, tp2) + } + finally if (!result) undoLog.undoTo(before) result - } finally undoLog.unlock() - } finally { + } + finally undoLog.unlock() + } + finally { subsametypeRecursions -= 1 // XXX AM TODO: figure out when it is safe and needed to clear the log -- the commented approach below is too eager (it breaks #3281, #3866) // it doesn't help to keep separate recursion counts for the three methods that now share it @@ -5382,108 +5224,7 @@ trait Types extends api.Types { self: SymbolTable => case _ => tp.normalize } */ -/* - private def isSameType0(tp1: Type, tp2: Type): Boolean = { - if (tp1 eq tp2) return true - ((tp1, tp2) match { - case (ErrorType, _) => true - case (WildcardType, _) => true - case (_, ErrorType) => true - case (_, WildcardType) => true - - case (NoType, _) => false - case (NoPrefix, _) => tp2.typeSymbol.isPackageClass - case (_, NoType) => false - case (_, NoPrefix) => tp1.typeSymbol.isPackageClass - - case (ThisType(sym1), ThisType(sym2)) - if (sym1 == sym2) => - true - case (SingleType(pre1, sym1), SingleType(pre2, sym2)) - if (equalSymsAndPrefixes(sym1, pre1, sym2, pre2)) => - true -/* - case (SingleType(pre1, sym1), ThisType(sym2)) - if (sym1.isModule && - sym1.moduleClass == sym2 && - pre1 =:= sym2.owner.thisType) => - true - case (ThisType(sym1), SingleType(pre2, sym2)) - if (sym2.isModule && - sym2.moduleClass == sym1 && - pre2 =:= sym1.owner.thisType) => - true -*/ - case (ConstantType(value1), ConstantType(value2)) => - value1 == value2 - case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => - equalSymsAndPrefixes(sym1, pre1, sym2, pre2) && - ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) || - isSameTypes(args1, args2)) - // @M! normalize reduces higher-kinded case to PolyType's - case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) => - def isSubScope(s1: Scope, s2: Scope): Boolean = s2.toList.forall { - sym2 => - var e1 = s1.lookupEntry(sym2.name) - (e1 ne null) && { - val substSym = sym2.info.substThis(sym2.owner, e1.sym.owner.thisType) - var isEqual = false - while (!isEqual && (e1 ne null)) { - isEqual = e1.sym.info =:= substSym - e1 = s1.lookupNextEntry(e1) - } - isEqual - } - } - //Console.println("is same? " + tp1 + " " + tp2 + " " + tp1.typeSymbol.owner + " " + tp2.typeSymbol.owner)//DEBUG - isSameTypes(parents1, parents2) && isSubScope(ref1, ref2) && isSubScope(ref2, ref1) - case (MethodType(params1, res1), MethodType(params2, res2)) => - // new dependent types: probably fix this, use substSym as done for PolyType - (isSameTypes(tp1.paramTypes, tp2.paramTypes) && - res1 =:= res2 && - tp1.isImplicit == tp2.isImplicit) - case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => - // assert((tparams1 map (_.typeParams.length)) == (tparams2 map (_.typeParams.length))) - (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210 - res1 =:= res2.substSym(tparams2, tparams1) - case (ExistentialType(tparams1, res1), ExistentialType(tparams2, res2)) => - (tparams1.length == tparams2.length) && (tparams1 corresponds tparams2)(_.info =:= _.info.substSym(tparams2, tparams1)) && // @M looks like it might suffer from same problem as #2210 - res1 =:= res2.substSym(tparams2, tparams1) - case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => - lo1 =:= lo2 && hi1 =:= hi2 - case (BoundedWildcardType(bounds), _) => - bounds containsType tp2 - case (_, BoundedWildcardType(bounds)) => - bounds containsType tp1 - case (tv @ TypeVar(_,_), tp) => - tv.registerTypeEquality(tp, true) - case (tp, tv @ TypeVar(_,_)) => - tv.registerTypeEquality(tp, false) - case (AnnotatedType(_,_,_), _) => - annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations - case (_, AnnotatedType(_,_,_)) => - annotationsConform(tp1, tp2) && annotationsConform(tp2, tp1) && tp1.withoutAnnotations =:= tp2.withoutAnnotations - case (_: SingletonType, _: SingletonType) => - var origin1 = tp1 - while (origin1.underlying.isInstanceOf[SingletonType]) { - assert(origin1 ne origin1.underlying, origin1) - origin1 = origin1.underlying - } - var origin2 = tp2 - while (origin2.underlying.isInstanceOf[SingletonType]) { - assert(origin2 ne origin2.underlying, origin2) - origin2 = origin2.underlying - } - ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2) - case _ => - false - }) || { - val tp1n = normalizePlus(tp1) - val tp2n = normalizePlus(tp2) - ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n) - } - } -*/ + private def isSameType1(tp1: Type, tp2: Type): Boolean = { if ((tp1 eq tp2) || (tp1 eq ErrorType) || (tp1 eq WildcardType) || @@ -5622,12 +5363,12 @@ trait Types extends api.Types { self: SymbolTable => } tp1 match { case tv @ TypeVar(_,_) => - return tv.registerTypeEquality(tp2, true) + return tv.registerTypeEquality(tp2, typeVarLHS = true) case _ => } tp2 match { case tv @ TypeVar(_,_) => - return tv.registerTypeEquality(tp1, false) + return tv.registerTypeEquality(tp1, typeVarLHS = false) case _ => } tp1 match { @@ -5756,18 +5497,6 @@ trait Types extends api.Types { self: SymbolTable => false } - @deprecated("The compiler doesn't use this so you shouldn't either - it will be removed", "2.10.0") - def instTypeVar(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) => - copyTypeRef(tp, instTypeVar(pre), sym, args) - case SingleType(pre, sym) => - singleType(instTypeVar(pre), sym) - case TypeVar(_, constr) => - instTypeVar(constr.inst) - case _ => - tp - } - def isErrorOrWildcard(tp: Type) = (tp eq ErrorType) || (tp eq WildcardType) def isSingleType(tp: Type) = tp match { @@ -5805,10 +5534,11 @@ trait Types extends api.Types { self: SymbolTable => * types which are used internally in type applications and * types which are not. */ + /**** Not used right now, but kept around to document which Types + * land in which bucket. private def isInternalTypeNotUsedAsTypeArg(tp: Type): Boolean = tp match { case AntiPolyType(pre, targs) => true case ClassInfoType(parents, defs, clazz) => true - case DeBruijnIndex(level, index, args) => true case ErasedValueType(tref) => true case NoPrefix => true case NoType => true @@ -5816,6 +5546,7 @@ trait Types extends api.Types { self: SymbolTable => case TypeBounds(lo, hi) => true case _ => false } + ****/ private def isInternalTypeUsedAsTypeArg(tp: Type): Boolean = tp match { case WildcardType => true case BoundedWildcardType(_) => true @@ -5861,7 +5592,7 @@ trait Types extends api.Types { self: SymbolTable => * useful as documentation; it is likely that !isNonValueType(tp) * will serve better than isValueType(tp). */ - def isValueType(tp: Type) = isValueElseNonValue(tp) + /** def isValueType(tp: Type) = isValueElseNonValue(tp) */ /** SLS 3.3, Non-Value Types * Is the given type definitely a non-value type, as defined in SLS 3.3? @@ -5872,7 +5603,7 @@ trait Types extends api.Types { self: SymbolTable => * not designated non-value types because there is code which depends on using * them as type arguments, but their precise status is unclear. */ - def isNonValueType(tp: Type) = !isValueElseNonValue(tp) + /** def isNonValueType(tp: Type) = !isValueElseNonValue(tp) */ def isNonRefinementClassType(tpe: Type) = tpe match { case SingleType(_, sym) => sym.isModuleClass @@ -5921,8 +5652,6 @@ trait Types extends api.Types { self: SymbolTable => corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg) } - def differentOrNone(tp1: Type, tp2: Type) = if (tp1 eq tp2) NoType else tp1 - /** Does type `tp1` conform to `tp2`? */ private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = { if ((tp1 eq tp2) || isErrorOrWildcard(tp1) || isErrorOrWildcard(tp2)) return true @@ -6126,18 +5855,6 @@ trait Types extends api.Types { self: SymbolTable => !(sym isNonBottomSubClass AnyValClass) && !(sym isNonBottomSubClass NotNullClass) - /** Are `tps1` and `tps2` lists of equal length such that all elements - * of `tps1` conform to corresponding elements of `tps2`? - */ - def isSubTypes(tps1: List[Type], tps2: List[Type]): Boolean = (tps1 corresponds tps2)(_ <:< _) - - /** Does type `tp` implement symbol `sym` with same or - * stronger type? Exact only if `sym` is a member of some - * refinement type, otherwise we might return false negatives. - */ - def specializesSym(tp: Type, sym: Symbol): Boolean = - specializesSym(tp, sym, AnyDepth) - def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean = tp.typeSymbol == NothingClass || tp.typeSymbol == NullClass && containsNull(sym.owner) || { @@ -6156,6 +5873,7 @@ trait Types extends api.Types { self: SymbolTable => * than member `sym2` of `tp2`? */ private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Int): Boolean = { + require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth))) val info1 = tp1.memberInfo(sym1) val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1) //System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG @@ -6470,25 +6188,27 @@ trait Types extends api.Types { self: SymbolTable => * @See baseTypeSeq for a definition of sorted and upwards closed. */ private def lubList(ts: List[Type], depth: Int): List[Type] = { - // Matching the type params of one of the initial types means dummies. - val initialTypeParams = ts map (_.typeParams) - def isHotForTs(xs: List[Type]) = initialTypeParams contains (xs map (_.typeSymbol)) + var lubListDepth = 0 + // This catches some recursive situations which would otherwise + // befuddle us, e.g. pos/hklub0.scala + def isHotForTs(xs: List[Type]) = ts exists (_.typeParams == xs.map(_.typeSymbol)) def elimHigherOrderTypeParam(tp: Type) = tp match { - case TypeRef(pre, sym, args) if args.nonEmpty && isHotForTs(args) => tp.typeConstructor - case _ => tp + case TypeRef(_, _, args) if args.nonEmpty && isHotForTs(args) => + logResult("Retracting dummies from " + tp + " in lublist")(tp.typeConstructor) + case _ => tp } - var lubListDepth = 0 - def loop(tsBts: List[List[Type]]): List[Type] = { + // pretypes is a tail-recursion-preserving accumulator. + @annotation.tailrec def loop(pretypes: List[Type], tsBts: List[List[Type]]): List[Type] = { lubListDepth += 1 - if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) Nil - else if (tsBts.tail.isEmpty) tsBts.head + if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) pretypes.reverse + else if (tsBts.tail.isEmpty) pretypes.reverse ++ tsBts.head else { // ts0 is the 1-dimensional frontier of symbols cutting through 2-dimensional tsBts. // Invariant: all symbols "under" (closer to the first row) the frontier // are smaller (according to _.isLess) than the ones "on and beyond" the frontier - val ts0 = tsBts map (_.head) + val ts0 = tsBts map (_.head) // Is the frontier made up of types with the same symbol? val isUniformFrontier = (ts0: @unchecked) match { @@ -6501,23 +6221,23 @@ trait Types extends api.Types { self: SymbolTable => // merging, strip targs that refer to bound tparams (when we're computing the lub of type // constructors.) Also filter out all types that are a subtype of some other type. if (isUniformFrontier) { - if (settings.debug.value || printLubs) { - val fbounds = findRecursiveBounds(ts0) - if (fbounds.nonEmpty) { - println("Encountered " + fbounds.size + " recursive bounds while lubbing " + ts0.size + " types.") - for ((p0, p1) <- fbounds) { - val desc = if (p0 == p1) "its own bounds" else "the bounds of " + p1 - - println(" " + p0.fullLocationString + " appears in " + desc) - println(" " + p1 + " " + p1.info.bounds) + val fbounds = findRecursiveBounds(ts0) map (_._2) + val tcLubList = typeConstructorLubList(ts0) + def isRecursive(tp: Type) = tp.typeSymbol.typeParams exists fbounds.contains + + val ts1 = ts0 map { t => + if (isRecursive(t)) { + tcLubList map (t baseType _.typeSymbol) find (t => !isRecursive(t)) match { + case Some(tp) => logResult(s"Breaking recursion in lublist, substituting weaker type.\n Was: $t\n Now")(tp) + case _ => t } - println("") } + else t } val tails = tsBts map (_.tail) - mergePrefixAndArgs(elimSub(ts0 map elimHigherOrderTypeParam, depth), 1, depth) match { - case Some(tp) => tp :: loop(tails) - case _ => loop(tails) + mergePrefixAndArgs(elimSub(ts1, depth) map elimHigherOrderTypeParam, 1, depth) match { + case Some(tp) => loop(tp :: pretypes, tails) + case _ => loop(pretypes, tails) } } else { @@ -6534,7 +6254,7 @@ trait Types extends api.Types { self: SymbolTable => printLubMatrix((ts zip tsBts).toMap, lubListDepth) } - loop(newtps) + loop(pretypes, newtps) } } } @@ -6543,7 +6263,7 @@ trait Types extends api.Types { self: SymbolTable => if (printLubs) printLubMatrix((ts zip initialBTSes).toMap, depth) - loop(initialBTSes) + loop(Nil, initialBTSes) } /** The minimal symbol of a list of types (as determined by `Symbol.isLess`). */ @@ -6576,10 +6296,6 @@ trait Types extends api.Types { self: SymbolTable => case _ => t } - def elimRefinement(t: Type) = t match { - case RefinedType(parents, decls) if !decls.isEmpty => intersectionType(parents) - case _ => t - } /** Eliminate from list of types all elements which are a subtype * of some other element of the list. */ @@ -6624,28 +6340,12 @@ trait Types extends api.Types { self: SymbolTable => (annotationsLub(lub(ts map (_.withoutAnnotations)), ts), true) else (lub(ts), false) - def weakGlb(ts: List[Type]) = { - if (ts.nonEmpty && (ts forall isNumericValueType)) { - val nglb = numericGlb(ts) - if (nglb != NoType) (nglb, true) - else (glb(ts), false) - } else if (ts exists typeHasAnnotations) { - (annotationsGlb(glb(ts map (_.withoutAnnotations)), ts), true) - } else (glb(ts), false) - } - def numericLub(ts: List[Type]) = ts reduceLeft ((t1, t2) => if (isNumericSubType(t1, t2)) t2 else if (isNumericSubType(t2, t1)) t1 else IntClass.tpe) - def numericGlb(ts: List[Type]) = - ts reduceLeft ((t1, t2) => - if (isNumericSubType(t1, t2)) t1 - else if (isNumericSubType(t2, t1)) t2 - else NoType) - def isWeakSubType(tp1: Type, tp2: Type) = tp1.deconst.normalize match { case TypeRef(_, sym1, _) if isNumericValueClass(sym1) => @@ -6681,6 +6381,23 @@ trait Types extends api.Types { self: SymbolTable => private val lubResults = new mutable.HashMap[(Int, List[Type]), Type] private val glbResults = new mutable.HashMap[(Int, List[Type]), Type] + /** Given a list of types, finds all the base classes they have in + * common, then returns a list of type constructors derived directly + * from the symbols (so any more specific type information is ignored.) + * The list is filtered such that every type constructor in the list + * expects the same number of type arguments, which is chosen based + * on the deepest class among the common baseclasses. + */ + def typeConstructorLubList(ts: List[Type]): List[Type] = { + val bcs = ts.flatMap(_.baseClasses).distinct sortWith (_ isLess _) + val tcons = bcs filter (clazz => ts forall (_.typeSymbol isSubClass clazz)) + + tcons map (_.typeConstructor) match { + case Nil => Nil + case t :: ts => t :: ts.filter(_.typeParams.size == t.typeParams.size) + } + } + def lub(ts: List[Type]): Type = ts match { case List() => NothingClass.tpe case List(t) => t @@ -6688,8 +6405,20 @@ trait Types extends api.Types { self: SymbolTable => if (Statistics.canEnable) Statistics.incCounter(lubCount) val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, lubNanos) else null try { - lub(ts, lubDepth(ts)) - } finally { + val res = lub(ts, lubDepth(ts)) + // If the number of unapplied type parameters in all incoming + // types is consistent, and the lub does not match that, return + // the type constructor of the calculated lub instead. This + // is because lubbing type constructors tends to result in types + // which have been applied to dummies or Nothing. + ts.map(_.typeParams.size).distinct match { + case x :: Nil if res.typeParams.size != x => + logResult(s"Stripping type args from lub because $res is not consistent with $ts")(res.typeConstructor) + case _ => + res + } + } + finally { lubResults.clear() glbResults.clear() if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start) @@ -6723,13 +6452,13 @@ trait Types extends api.Types { self: SymbolTable => } } def lub1(ts0: List[Type]): Type = { - val (ts, tparams) = stripExistentialsAndTypeVars(ts0) + val (ts, tparams) = stripExistentialsAndTypeVars(ts0) val lubBaseTypes: List[Type] = lubList(ts, depth) - val lubParents = spanningTypes(lubBaseTypes) - val lubOwner = commonOwner(ts) - val lubBase = intersectionType(lubParents, lubOwner) + val lubParents = spanningTypes(lubBaseTypes) + val lubOwner = commonOwner(ts) + val lubBase = intersectionType(lubParents, lubOwner) val lubType = - if (phase.erasedTypes || depth == 0) lubBase + if (phase.erasedTypes || depth == 0 ) lubBase else { val lubRefined = refinedType(lubParents, lubOwner) val lubThisType = lubRefined.typeSymbol.thisType @@ -6746,6 +6475,7 @@ trait Types extends api.Types { self: SymbolTable => val syms = narrowts map (t => t.nonPrivateMember(proto.name).suchThat(sym => sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t))) + if (syms contains NoSymbol) NoSymbol else { val symtypes = @@ -6772,10 +6502,8 @@ trait Types extends api.Types { self: SymbolTable => // add a refinement symbol for all non-class members of lubBase // which are refined by every type in ts. for (sym <- lubBase.nonPrivateMembers ; if !excludeFromLub(sym)) { - try { - val lsym = lubsym(sym) - if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lsym, depth) - } catch { + try lubsym(sym) andAlso (addMember(lubThisType, lubRefined, _, depth)) + catch { case ex: NoCommonType => } } @@ -6972,15 +6700,19 @@ trait Types extends api.Types { self: SymbolTable => } tvs.reverse } - /** Make each type var in this type use its original type for comparisons instead - * of collecting constraints. - */ - def suspendTypeVarsInType(tp: Type): List[TypeVar] = { - val tvs = typeVarsInType(tp) - // !!! Is it somehow guaranteed that this will not break under nesting? - // In general one has to save and restore the contents of the field... + + // If this type contains type variables, put them to sleep for a while. + // Don't just wipe them out by replacing them by the corresponding type + // parameter, as that messes up (e.g.) type variables in type refinements. + // Without this, the matchesType call would lead to type variables on both + // sides of a subtyping/equality judgement, which can lead to recursive types + // being constructed. See pos/t0851 for a situation where this happens. + @inline final def suspendingTypeVars[T](tvs: List[TypeVar])(op: => T): T = { + val saved = tvs map (_.suspended) tvs foreach (_.suspended = true) - tvs + + try op + finally foreach2(tvs, saved)(_.suspended = _) } /** Compute lub (if `variance == 1`) or glb (if `variance == -1`) of given list @@ -7019,18 +6751,16 @@ trait Types extends api.Types { self: SymbolTable => debuglog("transposed irregular matrix!?" +(tps, argss)) None case Some(argsst) => - val args = map2(sym.typeParams, argsst) { (tparam, as) => - if (depth == 0) { - if (tparam.variance == variance) { - // Take the intersection of the upper bounds of the type parameters - // rather than falling all the way back to "Any", otherwise we end up not - // conforming to bounds. - val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass) - if (bounds0.isEmpty) AnyClass.tpe - else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym))) - } - else if (tparam.variance == -variance) NothingClass.tpe - else NoType + val args = map2(sym.typeParams, argsst) { (tparam, as0) => + val as = as0.distinct + if (as.size == 1) as.head + else if (depth == 0) { + log("Giving up merging args: can't unify %s under %s".format(as.mkString(", "), tparam.fullLocationString)) + // Don't return "Any" (or "Nothing") when we have to give up due to + // recursion depth. Return NoType, which prevents us from poisoning + // lublist's results. It can recognize the recursion and deal with it, but + // only if we aren't returning invalid types. + NoType } else { if (tparam.variance == variance) lub(as, decr(depth)) @@ -7039,7 +6769,7 @@ trait Types extends api.Types { self: SymbolTable => val l = lub(as, decr(depth)) val g = glb(as, decr(depth)) if (l <:< g) l - else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we + else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we // just err on the conservative side, i.e. with a bound that is too high. // if(!(tparam.info.bounds contains tparam)) //@M can't deal with f-bounds, see #2251 @@ -7087,6 +6817,14 @@ trait Types extends api.Types { self: SymbolTable => } } + def isJavaVarargsAncestor(clazz: Symbol) = ( + clazz.isClass + && clazz.isJavaDefined + && (clazz.info.nonPrivateDecls exists isJavaVarArgsMethod) + ) + def inheritsJavaVarArgsMethod(clazz: Symbol) = + clazz.thisType.baseClasses exists isJavaVarargsAncestor + /** All types in list must be polytypes with type parameter lists of * same length as tparams. * Returns list of list of bounds infos, where corresponding type @@ -7199,6 +6937,15 @@ trait Types extends api.Types { self: SymbolTable => else (ps :+ SerializableClass.tpe).toList ) + /** Members of the given class, other than those inherited + * from Any or AnyRef. + */ + def nonTrivialMembers(clazz: Symbol): Scope = clazz.info.members filterNot isUniversalMember + + /** Members which can be imported into other scopes. + */ + def importableMembers(pre: Type): Scope = pre.members filter isImportable + def objToAny(tp: Type): Type = if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe else tp @@ -7222,7 +6969,7 @@ trait Types extends api.Types { self: SymbolTable => protected def typeToString(tpe: Type): String = if (tostringRecursions >= maxTostringRecursions) { - debugwarn("Exceeded recursion depth attempting to print type.") + devWarning("Exceeded recursion depth attempting to print " + util.shortClassOfInstance(tpe)) if (settings.debug.value) (new Throwable).printStackTrace @@ -7292,7 +7039,6 @@ trait Types extends api.Types { self: SymbolTable => object TypesStats { import BaseTypeSeqsStats._ val rawTypeCount = Statistics.newCounter ("#raw type creations") - val asSeenFromCount = Statistics.newCounter ("#asSeenFrom ops") val subtypeCount = Statistics.newCounter ("#subtype ops") val sametypeCount = Statistics.newCounter ("#sametype ops") val lubCount = Statistics.newCounter ("#toplevel lubs/glbs") diff --git a/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala b/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala index 6170fcbb90..34c6fe234c 100644 --- a/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala +++ b/src/reflect/scala/reflect/internal/pickling/PickleBuffer.scala @@ -62,11 +62,8 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { writeByte((x & 0x7f).toInt) } - /** Write a natural number <code>x</code> at position <code>pos</code>. + /** Write a natural number `x` at position `pos`. * If number is more than one byte, shift rest of array to make space. - * - * @param pos ... - * @param x ... */ def patchNat(pos: Int, x: Int) { def patchNatPrefix(x: Int) { @@ -81,7 +78,7 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { if (y != 0) patchNatPrefix(y) } - /** Write a long number <code>x</code> in signed big endian format, base 256. + /** Write a long number `x` in signed big endian format, base 256. * * @param x The long number to be written. */ @@ -94,9 +91,6 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { // -- Basic input routines -------------------------------------------- - /** Peek at the current byte without moving the read index */ - def peekByte(): Int = bytes(readIndex) - /** Read a byte */ def readByte(): Int = { val x = bytes(readIndex); readIndex += 1; x @@ -151,18 +145,14 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) { result.toIndexedSeq } - /** Perform operation <code>op</code> until the condition - * <code>readIndex == end</code> is satisfied. + /** Perform operation `op` until the condition + * `readIndex == end` is satisfied. * Concatenate results into a list. - * - * @param end ... - * @param op ... - * @return ... */ def until[T](end: Int, op: () => T): List[T] = if (readIndex == end) List() else op() :: until(end, op); - /** Perform operation <code>op</code> the number of + /** Perform operation `op` the number of * times specified. Concatenate the results into a list. */ def times[T](n: Int, op: ()=>T): List[T] = diff --git a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala index 16747af08a..3722c77aa2 100644 --- a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala +++ b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala @@ -56,7 +56,7 @@ object PickleFormat { * | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref} * | 43 ANNOTINFO len_Nat AnnotInfoBody * | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref} - * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat + * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat /* no longer needed */ * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref} * | 49 TREE len_Nat 1 EMPTYtree * | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref} @@ -115,7 +115,6 @@ object PickleFormat { */ val MajorVersion = 5 val MinorVersion = 0 - def VersionString = "V" + MajorVersion + "." + MinorVersion final val TERMname = 1 final val TYPEname = 2 @@ -161,7 +160,7 @@ object PickleFormat { final val ANNOTARGARRAY = 44 final val SUPERtpe = 46 - final val DEBRUIJNINDEXtpe = 47 + final val DEBRUIJNINDEXtpe = 47 // no longer generated final val EXISTENTIALtpe = 48 final val TREE = 49 // prefix code that means a tree is coming diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index f3a5053a91..5a0454a569 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -159,9 +159,9 @@ abstract class UnPickler { result } - /** If entry at <code>i</code> is undefined, define it by performing - * operation <code>op</code> with <code>readIndex at start of i'th - * entry. Restore <code>readIndex</code> afterwards. + /** If entry at `i` is undefined, define it by performing + * operation `op` with `readIndex at start of i'th + * entry. Restore `readIndex` afterwards. */ protected def at[T <: AnyRef](i: Int, op: () => T): T = { var r = entries(i) @@ -186,13 +186,12 @@ abstract class UnPickler { case _ => errorBadSignature("bad name tag: " + tag) } } - protected def readTermName(): TermName = readName().toTermName - protected def readTypeName(): TypeName = readName().toTypeName + private def readEnd() = readNat() + readIndex /** Read a symbol */ protected def readSymbol(): Symbol = { val tag = readByte() - val end = readNat() + readIndex + val end = readEnd() def atEnd = readIndex == end def readExtSymbol(): Symbol = { @@ -325,7 +324,7 @@ abstract class UnPickler { */ protected def readType(forceProperType: Boolean = false): Type = { val tag = readByte() - val end = readNat() + readIndex + val end = readEnd() (tag: @switch) match { case NOtpe => NoType @@ -344,7 +343,7 @@ abstract class UnPickler { case TYPEREFtpe => val pre = readTypeRef() val sym = readSymbolRef() - var args = until(end, readTypeRef) + val args = until(end, readTypeRef) TypeRef(pre, sym, args) case TYPEBOUNDStpe => TypeBounds(readTypeRef(), readTypeRef()) @@ -431,7 +430,7 @@ abstract class UnPickler { protected def readChildren() { val tag = readByte() assert(tag == CHILDREN) - val end = readNat() + readIndex + val end = readEnd() val target = readSymbolRef() while (readIndex != end) target addChild readSymbolRef() } @@ -450,7 +449,7 @@ abstract class UnPickler { */ private def readArrayAnnot() = { readByte() // skip the `annotargarray` tag - val end = readNat() + readIndex + val end = readEnd() until(end, () => readClassfileAnnotArg(readNat())).toArray(JavaArgumentTag) } protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match { @@ -486,7 +485,7 @@ abstract class UnPickler { val tag = readByte() if (tag != SYMANNOT) errorBadSignature("symbol annotation expected ("+ tag +")") - val end = readNat() + readIndex + val end = readEnd() val target = readSymbolRef() target.addAnnotation(readAnnotationInfo(end)) } @@ -497,7 +496,7 @@ abstract class UnPickler { val tag = readByte() if (tag != ANNOTINFO) errorBadSignature("annotation expected (" + tag + ")") - val end = readNat() + readIndex + val end = readEnd() readAnnotationInfo(end) } @@ -506,7 +505,7 @@ abstract class UnPickler { val outerTag = readByte() if (outerTag != TREE) errorBadSignature("tree expected (" + outerTag + ")") - val end = readNat() + readIndex + val end = readEnd() val tag = readByte() val tpe = if (tag == EMPTYtree) NoType else readTypeRef() @@ -764,7 +763,8 @@ abstract class UnPickler { val tag = readNat() if (tag != MODIFIERS) errorBadSignature("expected a modifiers tag (" + tag + ")") - val end = readNat() + readIndex + + readEnd() val pflagsHi = readNat() val pflagsLo = readNat() val pflags = (pflagsHi.toLong << 32) + pflagsLo @@ -796,7 +796,6 @@ abstract class UnPickler { protected def readTreeRef(): Tree = at(readNat(), readTree) protected def readTypeNameRef(): TypeName = readNameRef().toTypeName - protected def readTermNameRef(): TermName = readNameRef().toTermName protected def readTemplateRef(): Template = readTreeRef() match { @@ -843,7 +842,6 @@ abstract class UnPickler { * error reporting, so we rely on the typechecker to report the error). */ def toTypeError(e: MissingRequirementError) = { - // e.printStackTrace() new TypeError(e.msg) } @@ -853,7 +851,7 @@ abstract class UnPickler { private val p = phase override def complete(sym: Symbol) : Unit = try { val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType` - atPhase(p) (sym setInfo tp) + enteringPhase(p) (sym setInfo tp) if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp)) } @@ -871,7 +869,7 @@ abstract class UnPickler { super.complete(sym) var alias = at(j, readSymbol) if (alias.isOverloaded) - alias = atPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) + alias = enteringPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) sym.asInstanceOf[TermSymbol].setAlias(alias) } diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index 81368df7a6..81ed63bfc6 100644 --- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -47,4 +47,5 @@ abstract class MutableSettings extends AbsSettings { def XoldPatmat: BooleanSetting def XnoPatmatAnalysis: BooleanSetting def XfullLubs: BooleanSetting + def breakCycles: BooleanSetting } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 52d1657dc3..59bf51d638 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -69,7 +69,7 @@ trait Erasure { // // This requires that cls.isClass. protected def rebindInnerClass(pre: Type, cls: Symbol): Type = { - if (cls.owner.isClass) cls.owner.tpe else pre // why not cls.isNestedClass? + if (cls.owner.isClass) cls.owner.tpe_* else pre // why not cls.isNestedClass? } def unboxDerivedValueClassMethod(clazz: Symbol): Symbol = @@ -233,7 +233,7 @@ trait Erasure { // It seems there is a deeper problem here, which needs // following up to. But we will not risk regressions // in 2.10 because of it. - log(s"!!! unexpected constructor erasure $tp for $clazz") + devWarning(s"unexpected constructor erasure $tp for $clazz") specialScalaErasure(tp) } } diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index 2ba15e0776..0d644aa73e 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -40,8 +40,6 @@ trait Collections { mforeach(xss)(x => if ((res eq null) && p(x)) res = Some(x)) if (res eq null) None else res } - final def mfilter[A](xss: List[List[A]])(p: A => Boolean) = - for (xs <- xss; x <- xs; if p(x)) yield x final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = { val lb = new ListBuffer[C] @@ -78,19 +76,6 @@ trait Collections { lb.toList } - final def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = { - val buf = new ListBuffer[A] - val seen = mutable.Set[B]() - xs foreach { x => - val y = f(x) - if (!seen(y)) { - buf += x - seen += y - } - } - buf.toList - } - @tailrec final def flattensToEmpty(xss: Seq[Seq[_]]): Boolean = { xss.isEmpty || xss.head.isEmpty && flattensToEmpty(xss.tail) } @@ -189,18 +174,6 @@ trait Collections { } false } - final def forall2[A, B](xs1: List[A], xs2: List[B])(f: (A, B) => Boolean): Boolean = { - var ys1 = xs1 - var ys2 = xs2 - while (!ys1.isEmpty && !ys2.isEmpty) { - if (!f(ys1.head, ys2.head)) - return false - - ys1 = ys1.tail - ys2 = ys2.tail - } - true - } final def forall3[A, B, C](xs1: List[A], xs2: List[B], xs3: List[C])(f: (A, B, C) => Boolean): Boolean = { var ys1 = xs1 var ys2 = xs2 @@ -222,6 +195,3 @@ trait Collections { case _: IllegalArgumentException => None } } - -object Collections extends Collections { } - diff --git a/src/reflect/scala/reflect/internal/util/HashSet.scala b/src/reflect/scala/reflect/internal/util/HashSet.scala index 4135f3c469..74b6a54c6e 100644 --- a/src/reflect/scala/reflect/internal/util/HashSet.scala +++ b/src/reflect/scala/reflect/internal/util/HashSet.scala @@ -6,8 +6,6 @@ package scala.reflect.internal.util object HashSet { - def apply[T >: Null <: AnyRef](): HashSet[T] = this(16) - def apply[T >: Null <: AnyRef](label: String): HashSet[T] = this(label, 16) def apply[T >: Null <: AnyRef](initialCapacity: Int): HashSet[T] = this("No Label", initialCapacity) def apply[T >: Null <: AnyRef](label: String, initialCapacity: Int): HashSet[T] = new HashSet[T](label, initialCapacity) diff --git a/src/reflect/scala/reflect/internal/util/Origins.scala b/src/reflect/scala/reflect/internal/util/Origins.scala index 3259a12163..a2b9e24ebc 100644 --- a/src/reflect/scala/reflect/internal/util/Origins.scala +++ b/src/reflect/scala/reflect/internal/util/Origins.scala @@ -6,9 +6,7 @@ package scala.reflect package internal.util -import NameTransformer._ import scala.collection.{ mutable, immutable } -import Origins._ /** A debugging class for logging from whence a method is being called. * Say you wanted to discover who was calling phase_= in SymbolTable. diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala index 0725e9775b..bbc95feaab 100644 --- a/src/reflect/scala/reflect/internal/util/Position.scala +++ b/src/reflect/scala/reflect/internal/util/Position.scala @@ -128,7 +128,7 @@ abstract class Position extends scala.reflect.api.Position { self => def endOrPoint: Int = point @deprecated("use point instead", "2.9.0") - def offset: Option[Int] = if (isDefined) Some(point) else None + def offset: Option[Int] = if (isDefined) Some(point) else None // used by sbt /** The same position with a different start value (if a range) */ def withStart(off: Int): Position = this diff --git a/src/reflect/scala/reflect/internal/util/Set.scala b/src/reflect/scala/reflect/internal/util/Set.scala index 36bdb8174a..57e5e0c0b9 100644 --- a/src/reflect/scala/reflect/internal/util/Set.scala +++ b/src/reflect/scala/reflect/internal/util/Set.scala @@ -18,8 +18,6 @@ abstract class Set[T <: AnyRef] { def apply(x: T): Boolean = contains(x) - @deprecated("use `iterator` instead", "2.9.0") def elements = iterator - def contains(x: T): Boolean = findEntry(x) ne null diff --git a/src/reflect/scala/reflect/internal/util/SourceFile.scala b/src/reflect/scala/reflect/internal/util/SourceFile.scala index bc2d0ee4db..dd2a6e21f1 100644 --- a/src/reflect/scala/reflect/internal/util/SourceFile.scala +++ b/src/reflect/scala/reflect/internal/util/SourceFile.scala @@ -24,7 +24,6 @@ abstract class SourceFile { assert(offset < length, file + ": " + offset + " >= " + length) new OffsetPosition(this, offset) } - def position(line: Int, column: Int) : Position = new OffsetPosition(this, lineToOffset(line) + column) def offsetToLine(offset: Int): Int def lineToOffset(index : Int): Int @@ -37,9 +36,6 @@ abstract class SourceFile { def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString def path = file.path - def beginsWith(offset: Int, text: String): Boolean = - (content drop offset) startsWith text - def lineToString(index: Int): String = content drop lineToOffset(index) takeWhile (c => !isLineBreakChar(c.toChar)) mkString "" @@ -81,7 +77,6 @@ object ScriptSourceFile { } else 0 } - def stripHeader(cs: Array[Char]): Array[Char] = cs drop headerLength(cs) def apply(file: AbstractFile, content: Array[Char]) = { val underlying = new BatchSourceFile(file, content) @@ -91,7 +86,6 @@ object ScriptSourceFile { stripped } } -import ScriptSourceFile._ class ScriptSourceFile(underlying: BatchSourceFile, content: Array[Char], override val start: Int) extends BatchSourceFile(underlying.file, content) { override def isSelfContained = false diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala index 2c90d2d525..b078b7d4f9 100644 --- a/src/reflect/scala/reflect/internal/util/Statistics.scala +++ b/src/reflect/scala/reflect/internal/util/Statistics.scala @@ -257,7 +257,6 @@ quant) def enabled = _enabled def enabled_=(cond: Boolean) = { if (cond && !_enabled) { - val test = new Timer("", Nil) val start = System.nanoTime() var total = 0L for (i <- 1 to 10000) { diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index 8f6c409e0b..93bbfdd273 100644 --- a/src/reflect/scala/reflect/internal/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -6,7 +6,6 @@ ** |/ ** \* */ - package scala.reflect.internal.util /** This object provides utility methods to extract elements @@ -16,22 +15,14 @@ package scala.reflect.internal.util * @version 1.0 */ trait StringOps { - def onull(s: String) = if (s == null) "" else s - def oempty(xs: String*) = xs filterNot (x => x == null || x == "") - def ojoin(xs: String*): String = oempty(xs: _*) mkString " " - def ojoin(xs: Seq[String], sep: String): String = oempty(xs: _*) mkString sep - def ojoinOr(xs: Seq[String], sep: String, orElse: String) = { - val ys = oempty(xs: _*) - if (ys.isEmpty) orElse else ys mkString sep - } - def trimTrailingSpace(s: String) = { - if (s.length == 0 || !s.charAt(s.length - 1).isWhitespace) s - else { - var idx = s.length - 1 - while (idx >= 0 && s.charAt(idx).isWhitespace) - idx -= 1 - - s.substring(0, idx + 1) + def oempty(xs: String*) = xs filterNot (x => x == null || x == "") + def ojoin(xs: String*): String = oempty(xs: _*) mkString " " + def longestCommonPrefix(xs: List[String]): String = { + if (xs.isEmpty || xs.contains("")) "" + else xs.head.head match { + case ch => + if (xs.tail forall (_.head == ch)) "" + ch + longestCommonPrefix(xs map (_.tail)) + else "" } } @@ -49,14 +40,6 @@ trait StringOps { def words(str: String): List[String] = decompose(str, ' ') - def stripPrefixOpt(str: String, prefix: String): Option[String] = - if (str startsWith prefix) Some(str drop prefix.length) - else None - - def stripSuffixOpt(str: String, suffix: String): Option[String] = - if (str endsWith suffix) Some(str dropRight suffix.length) - else None - def splitWhere(str: String, f: Char => Boolean, doDropIndex: Boolean = false): Option[(String, String)] = splitAt(str, str indexWhere f, doDropIndex) @@ -65,10 +48,6 @@ trait StringOps { else Some((str take idx, str drop (if (doDropIndex) idx + 1 else idx))) /** Returns a string meaning "n elements". - * - * @param n ... - * @param elements ... - * @return ... */ def countElementsAsString(n: Int, elements: String): String = n match { @@ -81,9 +60,6 @@ trait StringOps { } /** Turns a count into a friendly English description if n<=4. - * - * @param n ... - * @return ... */ def countAsString(n: Int): String = n match { diff --git a/src/reflect/scala/reflect/internal/util/TableDef.scala b/src/reflect/scala/reflect/internal/util/TableDef.scala index 8e2bcc2ff7..04ecfe8d76 100644 --- a/src/reflect/scala/reflect/internal/util/TableDef.scala +++ b/src/reflect/scala/reflect/internal/util/TableDef.scala @@ -67,12 +67,6 @@ class TableDef[T](_cols: Column[T]*) { override def toString = allToSeq mkString "\n" } - def formatterFor(rows: Seq[T]): T => String = { - val formatStr = new Table(rows).rowFormat - - x => formatStr.format(colApply(x) : _*) - } - def table(rows: Seq[T]) = new Table(rows) override def toString = cols.mkString("TableDef(", ", ", ")") diff --git a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala index fa83f70f3a..632890d600 100644 --- a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -12,13 +12,9 @@ trait TraceSymbolActivity { if (enabled && global.isCompilerUniverse) scala.sys addShutdownHook showAllSymbols() - private type Set[T] = scala.collection.immutable.Set[T] - private val Set = scala.collection.immutable.Set - val allSymbols = mutable.Map[Int, Symbol]() val allChildren = mutable.Map[Int, List[Int]]() withDefaultValue Nil val prevOwners = mutable.Map[Int, List[(Int, Phase)]]() withDefaultValue Nil - val symsCaused = mutable.Map[Int, Int]() withDefaultValue 0 val allTrees = mutable.Set[Tree]() def recordSymbolsInTree(tree: Tree) { @@ -44,38 +40,6 @@ trait TraceSymbolActivity { } } - /** TODO. - */ - private def reachableDirectlyFromSymbol(sym: Symbol): List[Symbol] = ( - List(sym.owner, sym.alias, sym.thisSym) - ++ sym.children - ++ sym.info.parents.map(_.typeSymbol) - ++ sym.typeParams - ++ sym.paramss.flatten - ) - private def reachable[T](inputs: Traversable[T], mkSymbol: T => Symbol): Set[Symbol] = { - def loop(seen: Set[Symbol], remaining: List[Symbol]): Set[Symbol] = { - remaining match { - case Nil => seen - case head :: rest => - if ((head eq null) || (head eq NoSymbol) || seen(head)) loop(seen, rest) - else loop(seen + head, rest ++ reachableDirectlyFromSymbol(head).filterNot(seen)) - } - } - loop(immutable.Set(), inputs.toList map mkSymbol filterNot (_ eq null) distinct) - } - private def treeList(t: Tree) = { - val buf = mutable.ListBuffer[Tree]() - t foreach (buf += _) - buf.toList - } - - private def reachableFromSymbol(root: Symbol): Set[Symbol] = - reachable[Symbol](List(root, root.info.typeSymbol), x => x) - - private def reachableFromTree(tree: Tree): Set[Symbol] = - reachable[Tree](treeList(tree), _.symbol) - private def signature(id: Int) = runBeforeErasure(allSymbols(id).defString) private def dashes(s: Any): String = ("" + s) map (_ => '-') @@ -119,7 +83,7 @@ trait TraceSymbolActivity { } println("\n") } - private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String = (x: U) => "" + x) = { + private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String) = { showMapFreq(xs.toList groupBy groupFn)(showFn) } private lazy val findErasurePhase: Phase = { @@ -129,7 +93,7 @@ trait TraceSymbolActivity { } ph } - private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body) + private def runBeforeErasure[T](body: => T): T = enteringPhase(findErasurePhase)(body) def showAllSymbols() { if (!enabled) return diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index 9882aad5e5..41e74f80e9 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -1,9 +1,6 @@ package scala.reflect.internal.util import scala.collection.mutable -import scala.collection.mutable.ArrayBuffer -import scala.collection.mutable.Builder -import scala.collection.mutable.SetBuilder import scala.collection.generic.Clearable import scala.runtime.AbstractFunction1 diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala new file mode 100644 index 0000000000..83c8bf67ba --- /dev/null +++ b/src/reflect/scala/reflect/internal/util/package.scala @@ -0,0 +1,34 @@ +package scala +package reflect +package internal + +package object util { + import StringOps.longestCommonPrefix + + // Shorten a name like Symbols$FooSymbol to FooSymbol. + private def shortenName(name: String): String = { + if (name == "") return "" + val segments = (name split '$').toList + val last = segments.last + + if (last.length == 0) + segments takeRight 2 mkString "$" + else + last + } + + def shortClassOfInstance(x: AnyRef): String = shortClass(x.getClass) + def shortClass(clazz: Class[_]): String = { + val name: String = (clazz.getName split '.').last + def isModule = name endsWith "$" // object + def isAnon = (name split '$').last forall (_.isDigit) // anonymous class + + if (isModule) + (name split '$' filterNot (_ == "")).last + "$" + else if (isAnon) { + val parents = clazz.getSuperclass :: clazz.getInterfaces.toList + parents map (c => shortClass(c)) mkString " with " + } + else shortenName(name) + } +} diff --git a/src/reflect/scala/reflect/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala index 15befb67f1..1a8d1c4f5e 100644 --- a/src/reflect/scala/reflect/io/AbstractFile.scala +++ b/src/reflect/scala/reflect/io/AbstractFile.scala @@ -14,9 +14,9 @@ import scala.collection.mutable.ArrayBuffer /** * An abstraction over files for use in the reflection/compiler libraries. - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' - * + * * @author Philippe Altherr * @version 1.0, 23/03/2004 */ @@ -27,7 +27,7 @@ object AbstractFile { /** * If the specified File exists and is a regular file, returns an - * abstract regular file backed by it. Otherwise, returns <code>null</code>. + * abstract regular file backed by it. Otherwise, returns `null`. */ def getFile(file: File): AbstractFile = if (file.isFile) new PlainFile(file) else null @@ -38,10 +38,7 @@ object AbstractFile { /** * If the specified File exists and is either a directory or a * readable zip or jar archive, returns an abstract directory - * backed by it. Otherwise, returns <code>null</code>. - * - * @param file ... - * @return ... + * backed by it. Otherwise, returns `null`. */ def getDirectory(file: File): AbstractFile = if (file.isDirectory) new PlainFile(file) @@ -51,10 +48,7 @@ object AbstractFile { /** * If the specified URL exists and is a readable zip or jar archive, * returns an abstract directory backed by it. Otherwise, returns - * <code>null</code>. - * - * @param file ... - * @return ... + * `null`. */ def getURL(url: URL): AbstractFile = { if (url == null || !Path.isExtensionJarOrZip(url.getPath)) null @@ -80,12 +74,12 @@ object AbstractFile { * </p> * <p> * The interface does <b>not</b> allow to access the content. - * The class <code>symtab.classfile.AbstractFileReader</code> accesses + * The class `symtab.classfile.AbstractFileReader` accesses * bytes, knowing that the character set of classfiles is UTF-8. For - * all other cases, the class <code>SourceFile</code> is used, which honors - * <code>global.settings.encoding.value</code>. + * all other cases, the class `SourceFile` is used, which honors + * `global.settings.encoding.value`. * </p> - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ abstract class AbstractFile extends Iterable[AbstractFile] { @@ -148,7 +142,7 @@ abstract class AbstractFile extends Iterable[AbstractFile] { def toURL: URL = if (file == null) null else file.toURI.toURL /** Returns contents of file (if applicable) in a Char array. - * warning: use <code>Global.getSourceFile()</code> to use the proper + * warning: use `Global.getSourceFile()` to use the proper * encoding when converting to the char array. */ @throws(classOf[IOException]) @@ -175,8 +169,8 @@ abstract class AbstractFile extends Iterable[AbstractFile] { def iterator: Iterator[AbstractFile] /** Returns the abstract file in this abstract directory with the specified - * name. If there is no such file, returns <code>null</code>. The argument - * <code>directory</code> tells whether to look for a directory or + * name. If there is no such file, returns `null`. The argument + * `directory` tells whether to look for a directory or * a regular file. */ def lookupName(name: String, directory: Boolean): AbstractFile @@ -186,19 +180,6 @@ abstract class AbstractFile extends Iterable[AbstractFile] { */ def lookupNameUnchecked(name: String, directory: Boolean): AbstractFile - /** Returns the abstract file in this abstract directory with the specified - * path relative to it, If there is no such file, returns null. The argument - * <code>directory</code> tells whether to look for a directory or a regular - * file. - * - * @param path ... - * @param directory ... - * @return ... - */ - def lookupPath(path: String, directory: Boolean): AbstractFile = { - lookup((f, p, dir) => f.lookupName(p, dir), path, directory) - } - /** Return an abstract file that does not check that `path` denotes * an existing file. */ diff --git a/src/reflect/scala/reflect/io/Directory.scala b/src/reflect/scala/reflect/io/Directory.scala index c040d1eac5..4bf9ed8a36 100644 --- a/src/reflect/scala/reflect/io/Directory.scala +++ b/src/reflect/scala/reflect/io/Directory.scala @@ -14,12 +14,10 @@ import java.io.{ File => JFile } * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object Directory { - import scala.util.Properties.{ tmpDir, userHome, userDir } + import scala.util.Properties.{ userHome, userDir } private def normalizePath(s: String) = Some(apply(Path(s).normalize)) def Current: Option[Directory] = if (userDir == "") None else normalizePath(userDir) - def Home: Option[Directory] = if (userHome == "") None else normalizePath(userHome) - def TmpDir: Option[Directory] = if (tmpDir == "") None else normalizePath(tmpDir) def apply(path: Path): Directory = path.toDirectory @@ -30,20 +28,18 @@ object Directory { path.createDirectory() } } -import Path._ /** An abstraction for directories. * * @author Paul Phillips * @since 2.8 - * + * * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class Directory(jfile: JFile) extends Path(jfile) { override def toAbsolute: Directory = if (isAbsolute) this else super.toAbsolute.toDirectory override def toDirectory: Directory = this override def toFile: File = new File(jfile) - override def isValid = jfile.isDirectory() || !jfile.exists() override def normalize: Directory = super.normalize.toDirectory /** An iterator over the contents of this directory. @@ -60,7 +56,6 @@ class Directory(jfile: JFile) extends Path(jfile) { override def walkFilter(cond: Path => Boolean): Iterator[Path] = list filter cond flatMap (_ walkFilter cond) - def deepDirs: Iterator[Directory] = Path.onlyDirs(deepList()) def deepFiles: Iterator[File] = Path.onlyFiles(deepList()) /** If optional depth argument is not given, will recurse @@ -70,10 +65,4 @@ class Directory(jfile: JFile) extends Path(jfile) { if (depth < 0) list ++ (dirs flatMap (_ deepList (depth))) else if (depth == 0) Iterator.empty else list ++ (dirs flatMap (_ deepList (depth - 1))) - - /** An iterator over the directories underneath this directory, - * to the (optionally) given depth. - */ - def subdirs(depth: Int = 1): Iterator[Directory] = - deepList(depth) collect { case x: Directory => x } } diff --git a/src/reflect/scala/reflect/io/File.scala b/src/reflect/scala/reflect/io/File.scala index 736ba5d51e..c74dc06501 100644 --- a/src/reflect/scala/reflect/io/File.scala +++ b/src/reflect/scala/reflect/io/File.scala @@ -22,8 +22,7 @@ import scala.language.{reflectiveCalls, implicitConversions} */ object File { def pathSeparator = java.io.File.pathSeparator - def separator = java.io.File.separator - + def separator = java.io.File.separator def apply(path: Path)(implicit codec: Codec) = new File(path.jfile)(codec) // Create a temporary file, which will be deleted upon jvm exit. @@ -32,41 +31,7 @@ object File { jfile.deleteOnExit() apply(jfile) } - - type HasClose = { def close(): Unit } - - def closeQuietly(target: HasClose) { - try target.close() catch { case e: IOException => } - } - def closeQuietly(target: JCloseable) { - try target.close() catch { case e: IOException => } - } - - // this is a workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6503430 - // we are using a static initializer to statically initialize a java class so we don't - // trigger java.lang.InternalErrors later when using it concurrently. We ignore all - // the exceptions so as not to cause spurious failures when no write access is available, - // e.g. google app engine. - // - // XXX need to put this behind a setting. - // - // try { - // import Streamable.closing - // val tmp = java.io.File.createTempFile("bug6503430", null, null) - // try closing(new FileInputStream(tmp)) { in => - // val inc = in.getChannel() - // closing(new FileOutputStream(tmp, true)) { out => - // out.getChannel().transferFrom(inc, 0, 0) - // } - // } - // finally tmp.delete() - // } - // catch { - // case _: IllegalArgumentException | _: IllegalStateException | _: IOException | _: SecurityException => () - // } } -import File._ -import Path._ /** An abstraction for files. For character data, a Codec * can be supplied at either creation time or when a method @@ -76,19 +41,17 @@ import Path._ * * @author Paul Phillips * @since 2.8 - * + * * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.'' */ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) with Streamable.Chars { override val creationCodec = constructorCodec - def withCodec(codec: Codec): File = new File(jfile)(codec) override def addExtension(ext: String): File = super.addExtension(ext).toFile override def toAbsolute: File = if (isAbsolute) this else super.toAbsolute.toFile override def toDirectory: Directory = new Directory(jfile) override def toFile: File = this override def normalize: File = super.normalize.toFile - override def isValid = jfile.isFile() || !jfile.exists() override def length = super[Path].length override def walkFilter(cond: Path => Boolean): Iterator[Path] = if (cond(this)) Iterator.single(this) else Iterator.empty @@ -99,14 +62,11 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w /** Obtains a OutputStream. */ def outputStream(append: Boolean = false) = new FileOutputStream(jfile, append) def bufferedOutput(append: Boolean = false) = new BufferedOutputStream(outputStream(append)) - def printStream(append: Boolean = false) = new PrintStream(outputStream(append), true) /** Obtains an OutputStreamWriter wrapped around a FileOutputStream. * This should behave like a less broken version of java.io.FileWriter, * in that unlike the java version you can specify the encoding. */ - def writer(): OutputStreamWriter = writer(false) - def writer(append: Boolean): OutputStreamWriter = writer(append, creationCodec) def writer(append: Boolean, codec: Codec): OutputStreamWriter = new OutputStreamWriter(outputStream(append), codec.charSet) @@ -118,7 +78,6 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w new BufferedWriter(writer(append, codec)) def printWriter(): PrintWriter = new PrintWriter(bufferedWriter(), true) - def printWriter(append: Boolean): PrintWriter = new PrintWriter(bufferedWriter(append), true) /** Creates a new file and writes all the Strings to it. */ def writeAll(strings: String*): Unit = { @@ -127,12 +86,6 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w finally out.close() } - def writeBytes(bytes: Array[Byte]): Unit = { - val out = bufferedOutput() - try out write bytes - finally out.close() - } - def appendAll(strings: String*): Unit = { val out = bufferedWriter(append = true) try strings foreach (out write _) @@ -150,39 +103,6 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w try Some(slurp()) catch { case _: IOException => None } - def copyTo(destPath: Path, preserveFileDate: Boolean = false): Boolean = { - val CHUNK = 1024 * 1024 * 16 // 16 MB - val dest = destPath.toFile - if (!isValid) fail("Source %s is not a valid file." format name) - if (this.normalize == dest.normalize) fail("Source and destination are the same.") - if (!dest.parent.exists) fail("Destination cannot be created.") - if (dest.exists && !dest.canWrite) fail("Destination exists but is not writable.") - if (dest.isDirectory) fail("Destination exists but is a directory.") - - lazy val in_s = inputStream() - lazy val out_s = dest.outputStream() - lazy val in = in_s.getChannel() - lazy val out = out_s.getChannel() - - try { - val size = in.size() - var pos, count = 0L - while (pos < size) { - count = (size - pos) min CHUNK - pos += out.transferFrom(in, pos, count) - } - } - finally List[HasClose](out, out_s, in, in_s) foreach closeQuietly - - if (this.length != dest.length) - fail("Failed to completely copy %s to %s".format(name, dest.name)) - - if (preserveFileDate) - dest.lastModified = this.lastModified - - true - } - /** Reflection since we're into the java 6+ API. */ def setExecutable(executable: Boolean, ownerOnly: Boolean = true): Boolean = { diff --git a/src/reflect/scala/reflect/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 36fdc04db4..3b5d3079cd 100644 --- a/src/reflect/scala/reflect/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -27,7 +27,7 @@ import scala.language.implicitConversions * * @author Paul Phillips * @since 2.8 - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object Path { @@ -49,27 +49,12 @@ object Path { implicit def string2path(s: String): Path = apply(s) implicit def jfile2path(jfile: JFile): Path = apply(jfile) - // java 7 style, we don't use it yet - // object AccessMode extends Enumeration { - // val EXECUTE, READ, WRITE = Value - // } - // def checkAccess(modes: AccessMode*): Boolean = { - // modes foreach { - // case EXECUTE => throw new Exception("Unsupported") // can't check in java 5 - // case READ => if (!jfile.canRead()) return false - // case WRITE => if (!jfile.canWrite()) return false - // } - // true - // } - def onlyDirs(xs: Iterator[Path]): Iterator[Directory] = xs filter (_.isDirectory) map (_.toDirectory) def onlyDirs(xs: List[Path]): List[Directory] = xs filter (_.isDirectory) map (_.toDirectory) def onlyFiles(xs: Iterator[Path]): Iterator[File] = xs filter (_.isFile) map (_.toFile) - def onlyFiles(xs: List[Path]): List[File] = xs filter (_.isFile) map (_.toFile) def roots: List[Path] = java.io.File.listRoots().toList map Path.apply - def apply(segments: Seq[String]): Path = apply(segments mkString java.io.File.separator) def apply(path: String): Path = apply(new JFile(path)) def apply(jfile: JFile): Path = if (jfile.isFile) new File(jfile) @@ -84,19 +69,13 @@ import Path._ /** The Path constructor is private so we can enforce some * semantics regarding how a Path might relate to the world. - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class Path private[io] (val jfile: JFile) { val separator = java.io.File.separatorChar val separatorStr = java.io.File.separator - // Validation: this verifies that the type of this object and the - // contents of the filesystem are in agreement. All objects are - // valid except File objects whose path points to a directory and - // Directory objects whose path points to a file. - def isValid: Boolean = true - // conversions def toFile: File = new File(jfile) def toDirectory: Directory = new Directory(jfile) @@ -104,6 +83,7 @@ class Path private[io] (val jfile: JFile) { def toCanonical: Path = Path(jfile.getCanonicalPath()) def toURI: URI = jfile.toURI() def toURL: URL = toURI.toURL() + /** If this path is absolute, returns it: otherwise, returns an absolute * path made up of root / this. */ @@ -136,7 +116,6 @@ class Path private[io] (val jfile: JFile) { def name: String = jfile.getName() def path: String = jfile.getPath() def normalize: Path = Path(jfile.getAbsolutePath()) - def isRootPath: Boolean = roots exists (_ isSame this) def resolve(other: Path) = if (other.isAbsolute || isEmpty) other else /(other) def relativize(other: Path) = { @@ -152,9 +131,8 @@ class Path private[io] (val jfile: JFile) { Path(createRelativePath(segments, other.segments)) } - // derived from identity - def root: Option[Path] = roots find (this startsWith _) def segments: List[String] = (path split separator).toList filterNot (_.length == 0) + /** * @return The path of the parent directory, or root if path is already root */ @@ -185,10 +163,6 @@ class Path private[io] (val jfile: JFile) { if (i < 0) "" else name.substring(i + 1) } - // def extension: String = (name lastIndexOf '.') match { - // case -1 => "" - // case idx => name drop (idx + 1) - // } // compares against extensions in a CASE INSENSITIVE way. def hasExtension(ext: String, exts: String*) = { val lower = extension.toLowerCase @@ -213,22 +187,18 @@ class Path private[io] (val jfile: JFile) { def canRead = jfile.canRead() def canWrite = jfile.canWrite() def exists = jfile.exists() - def notExists = try !jfile.exists() catch { case ex: SecurityException => false } def isFile = jfile.isFile() def isDirectory = jfile.isDirectory() def isAbsolute = jfile.isAbsolute() - def isHidden = jfile.isHidden() def isEmpty = path.length == 0 // Information def lastModified = jfile.lastModified() - def lastModified_=(time: Long) = jfile setLastModified time // should use setXXX function? def length = jfile.length() // Boolean path comparisons def endsWith(other: Path) = segments endsWith other.segments - def startsWith(other: Path) = segments startsWith other.segments def isSame(other: Path) = toCanonical == other.toCanonical def isFresher(other: Path) = lastModified > other.lastModified @@ -248,7 +218,6 @@ class Path private[io] (val jfile: JFile) { // deletions def delete() = jfile.delete() - def deleteIfExists() = if (jfile.exists()) delete() else false /** Deletes the path recursively. Returns false on failure. * Use with caution! @@ -270,16 +239,6 @@ class Path private[io] (val jfile: JFile) { length == 0 } - def touch(modTime: Long = System.currentTimeMillis) = { - createFile() - if (isFile) - lastModified = modTime - } - - // todo - // def copyTo(target: Path, options ...): Boolean - // def moveTo(target: Path, options ...): Boolean - override def toString() = path override def equals(other: Any) = other match { case x: Path => path == x.path diff --git a/src/reflect/scala/reflect/io/PlainFile.scala b/src/reflect/scala/reflect/io/PlainFile.scala index 82b0568657..0d4d55bdec 100644 --- a/src/reflect/scala/reflect/io/PlainFile.scala +++ b/src/reflect/scala/reflect/io/PlainFile.scala @@ -3,23 +3,11 @@ * @author Martin Odersky */ - package scala.reflect package io import java.io.{ FileInputStream, FileOutputStream, IOException } -import PartialFunction._ -/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ -object PlainFile { - /** - * If the specified File exists, returns an abstract file backed - * by it. Otherwise, returns null. - */ - def fromPath(file: Path): PlainFile = - if (file.isDirectory) new PlainDirectory(file.toDirectory) - else if (file.isFile) new PlainFile(file) - else null -} + /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { override def isDirectory = true @@ -28,7 +16,7 @@ class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) { } /** This class implements an abstract file backed by a File. - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class PlainFile(val givenPath: Path) extends AbstractFile { @@ -77,10 +65,6 @@ class PlainFile(val givenPath: Path) extends AbstractFile { * specified name. If there is no such file, returns null. The * argument "directory" tells whether to look for a directory or * or a regular file. - * - * @param name ... - * @param directory ... - * @return ... */ def lookupName(name: String, directory: Boolean): AbstractFile = { val child = givenPath / name diff --git a/src/reflect/scala/reflect/io/Streamable.scala b/src/reflect/scala/reflect/io/Streamable.scala index 61ec8a4c23..b45cffb150 100644 --- a/src/reflect/scala/reflect/io/Streamable.scala +++ b/src/reflect/scala/reflect/io/Streamable.scala @@ -17,14 +17,14 @@ import Path.fail * * @author Paul Phillips * @since 2.8 - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object Streamable { /** Traits which can be viewed as a sequence of bytes. Source types * which know their length should override def length: Long for more * efficient method implementations. - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Bytes { @@ -69,7 +69,7 @@ object Streamable { } /** For objects which can be viewed as Chars. - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ trait Chars extends Bytes { @@ -81,7 +81,6 @@ object Streamable { */ def creationCodec: Codec = implicitly[Codec] - def chars(): BufferedSource = chars(creationCodec) def chars(codec: Codec): BufferedSource = Source.fromInputStream(inputStream())(codec) def lines(): Iterator[String] = lines(creationCodec) @@ -89,7 +88,6 @@ object Streamable { /** Obtains an InputStreamReader wrapped around a FileInputStream. */ - def reader(): InputStreamReader = reader(creationCodec) def reader(codec: Codec): InputStreamReader = new InputStreamReader(inputStream, codec.charSet) /** Wraps a BufferedReader around the result of reader(). diff --git a/src/reflect/scala/reflect/io/VirtualDirectory.scala b/src/reflect/scala/reflect/io/VirtualDirectory.scala index 78713c2ae0..94cb52e9b5 100644 --- a/src/reflect/scala/reflect/io/VirtualDirectory.scala +++ b/src/reflect/scala/reflect/io/VirtualDirectory.scala @@ -11,7 +11,7 @@ import scala.collection.mutable * An in-memory directory. * * @author Lex Spoon - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory]) @@ -26,7 +26,7 @@ extends AbstractFile { def container = maybeContainer.get def isDirectory = true - var lastModified: Long = System.currentTimeMillis + val lastModified: Long = System.currentTimeMillis override def file = null override def input = sys.error("directories cannot be read") diff --git a/src/reflect/scala/reflect/io/VirtualFile.scala b/src/reflect/scala/reflect/io/VirtualFile.scala index 95f4429fad..09b977bd45 100644 --- a/src/reflect/scala/reflect/io/VirtualFile.scala +++ b/src/reflect/scala/reflect/io/VirtualFile.scala @@ -3,7 +3,6 @@ * @author Martin Odersky */ - package scala.reflect package io @@ -14,7 +13,7 @@ import java.io.{ File => JFile } * * @author Philippe Altherr * @version 1.0, 23/03/2004 - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ class VirtualFile(val name: String, override val path: String) extends AbstractFile { @@ -33,12 +32,8 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF case _ => false } - //######################################################################## - // Private data private var content = Array.emptyByteArray - //######################################################################## - // Public Methods def absolute = this /** Returns null. */ @@ -65,7 +60,6 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF /** Returns the time that this abstract file was last modified. */ private var _lastModified: Long = 0 def lastModified: Long = _lastModified - def lastModified_=(x: Long) = _lastModified = x /** Returns all abstract subfiles of this abstract directory. */ def iterator: Iterator[AbstractFile] = { @@ -84,10 +78,6 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF * specified name. If there is no such file, returns null. The * argument "directory" tells whether to look for a directory or * or a regular file. - * - * @param name ... - * @param directory ... - * @return ... */ def lookupName(name: String, directory: Boolean): AbstractFile = { assert(isDirectory, "not a directory '" + this + "'") @@ -98,6 +88,4 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF * check that it exists. */ def lookupNameUnchecked(name: String, directory: Boolean) = unsupported - - //######################################################################## } diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala index 3b57721e89..097d3cb71c 100644 --- a/src/reflect/scala/reflect/io/ZipArchive.scala +++ b/src/reflect/scala/reflect/io/ZipArchive.scala @@ -20,13 +20,10 @@ import scala.annotation.tailrec * @author Philippe Altherr (original version) * @author Paul Phillips (this one) * @version 2.0, - * + * * ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ object ZipArchive { - def fromPath(path: String): FileZipArchive = fromFile(new JFile(path)) - def fromPath(path: Path): FileZipArchive = fromFile(path.toFile) - /** * @param file a File * @return A ZipArchive if `file` is a readable zip file, otherwise null. @@ -41,7 +38,6 @@ object ZipArchive { * @return A ZipArchive backed by the given url. */ def fromURL(url: URL): URLZipArchive = new URLZipArchive(url) - def fromURL(url: String): URLZipArchive = fromURL(new URL(url)) private def dirName(path: String) = splitPath(path, true) private def baseName(path: String) = splitPath(path, false) @@ -79,7 +75,6 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq else Iterator(f) } } - def deepIterator = walkIterator(iterator) /** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */ sealed abstract class Entry(path: String) extends VirtualFile(baseName(path), path) { // have to keep this name for compat with sbt's compiler-interface diff --git a/src/reflect/scala/reflect/macros/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala index 204dc40858..fbbbe13201 100644 --- a/src/reflect/scala/reflect/macros/TreeBuilder.scala +++ b/src/reflect/scala/reflect/macros/TreeBuilder.scala @@ -11,7 +11,6 @@ abstract class TreeBuilder { val global: Universe import global._ - import definitions._ /** Builds a reference to value whose type is given stable prefix. * The type must be suitable for this. For example, it diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 2d08cd887b..d264cc06b4 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -17,12 +17,9 @@ import internal.ClassfileConstants._ import internal.pickling.UnPickler import scala.collection.mutable.{ HashMap, ListBuffer } import internal.Flags._ -//import scala.tools.nsc.util.ScalaClassLoader -//import scala.tools.nsc.util.ScalaClassLoader._ import ReflectionUtils.{staticSingletonInstance, innerSingletonInstance} import scala.language.existentials import scala.runtime.{ScalaRunTime, BoxesRunTime} -import scala.reflect.internal.util.Collections._ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable => @@ -379,7 +376,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val varargMatch = args.length >= params.length - 1 && isVarArgsList(params) if (!perfectMatch && !varargMatch) { val n_arguments = if (isVarArgsList(params)) s"${params.length - 1} or more" else s"${params.length}" - var s_arguments = if (params.length == 1 && !isVarArgsList(params)) "argument" else "arguments" + val s_arguments = if (params.length == 1 && !isVarArgsList(params)) "argument" else "arguments" throw new ScalaReflectionException(s"${showMethodSig(symbol)} takes $n_arguments $s_arguments") } @@ -496,13 +493,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni Class.forName(path, true, classLoader) /** Does `path` correspond to a Java class with that fully qualified name in the current class loader? */ - def tryJavaClass(path: String): Option[jClass[_]] = - try { - Some(javaClass(path)) - } catch { - case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => - None - } + def tryJavaClass(path: String): Option[jClass[_]] = ( + try Some(javaClass(path)) + catch { case ex @ (_: LinkageError | _: ClassNotFoundException) => None } // TODO - log + ) /** The mirror that corresponds to the classloader that original defined the given Java class */ def mirrorDefining(jclazz: jClass[_]): JavaMirror = { @@ -839,20 +833,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni } /** - * The Scala field corresponding to given Java field. - * @param jfield The Java field - * @return A Scala field object that corresponds to `jfield`. - * // ??? should we return the getter instead? - */ - def fieldToScala(jfield: jField): TermSymbol = - toScala(fieldCache, jfield)(_ fieldToScala1 _) - - private def fieldToScala1(jfield: jField): TermSymbol = { - val owner = followStatic(classToScala(jfield.getDeclaringClass), jfield.getModifiers) - (lookup(owner, jfield.getName) suchThat (!_.isMethod) orElse jfieldAsScala(jfield)).asTerm - } - - /** * The Scala package corresponding to given Java package */ def packageToScala(jpkg: jPackage): ModuleSymbol = packageCache.toScala(jpkg) { @@ -1042,7 +1022,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = { val name = scalaSimpleName(jclazz) val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) - val (clazz, module) = createClassModule(owner, name, completer) + val (clazz, _) = createClassModule(owner, name, completer) classCache enter (jclazz, clazz) clazz } @@ -1107,7 +1087,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni constructorCache enter (jconstr, constr) val tparams = jconstr.getTypeParameters.toList map createTypeParameter val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala - setMethType(constr, tparams, paramtpes, clazz.tpe) + setMethType(constr, tparams, paramtpes, clazz.tpe_*) constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) copyAnnotations(constr, jconstr) constr @@ -1115,13 +1095,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni // -------------------- Scala to Java ----------------------------------- - /** Optionally, the Java package corresponding to a given Scala package, or None if no such Java package exists. - * @param pkg The Scala package - */ - def packageToJavaOption(pkg: ModuleSymbol): Option[jPackage] = packageCache.toJavaOption(pkg) { - Option(jPackage.getPackage(pkg.fullName.toString)) - } - /** The Java class corresponding to given Scala class. * Note: This only works for * - top-level classes diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index e18435d5b0..a12e7d43d4 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -1,8 +1,6 @@ package scala.reflect package runtime -import internal.{SomePhase, NoPhase, Phase, TreeGen} - /** An implementation of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders. * * Should not be instantiated directly, use [[scala.reflect.runtime.universe]] instead. @@ -11,13 +9,14 @@ import internal.{SomePhase, NoPhase, Phase, TreeGen} */ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.SymbolTable { self => - def picklerPhase = SomePhase + def picklerPhase = internal.SomePhase - lazy val settings = new Settings def forInteractive = false def forScaladoc = false + lazy val settings = new Settings + private val isLogging = sys.props contains "scala.debug.reflect" - def log(msg: => AnyRef): Unit = println(" [] "+msg) + def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg) type TreeCopier = InternalTreeCopierOps def newStrictTreeCopier: TreeCopier = new StrictTreeCopier @@ -25,4 +24,3 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S init() } - diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index 0e0cf3fc40..7d04202455 100644 --- a/src/reflect/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -43,6 +43,7 @@ private[reflect] class Settings extends MutableSettings { val printtypes = new BooleanSetting(false) val uniqid = new BooleanSetting(false) val verbose = new BooleanSetting(false) + val breakCycles = new BooleanSetting(false) val Yrecursion = new IntSetting(0) val maxClassfileName = new IntSetting(255) diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 61663f6181..60b22afd18 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -28,7 +28,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => debugInfo("completing "+sym+"/"+clazz.fullName) assert(sym == clazz || sym == module || sym == module.moduleClass) // try { - atPhaseNotLaterThan(picklerPhase) { + enteringPhaseNotLaterThan(picklerPhase) { val loadingMirror = mirrorThatLoaded(sym) val javaClass = loadingMirror.javaClass(clazz.javaClassName) loadingMirror.unpickleClass(clazz, module, javaClass) @@ -116,7 +116,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => currentMirror.tryJavaClass(path) match { case Some(cls) => val loadingMirror = currentMirror.mirrorDefining(cls) - val (clazz, module) = + val (_, module) = if (loadingMirror eq currentMirror) { createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) } else { diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index 00f6952dc1..1154927279 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -83,9 +83,6 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb override protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol = new PackageObjectClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags - override protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol = - new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags - override protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol = new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags @@ -118,7 +115,8 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb override def name_=(x: Name) = synchronized { super.name_=(x) } override def rawname = synchronized { super.rawname } override def typeConstructor: Type = synchronized { super.typeConstructor } - override def tpe: Type = synchronized { super.tpe } + override def tpe_* : Type = synchronized { super.tpe_* } + override def tpeHK : Type = synchronized { super.tpeHK } } trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol { diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index b97913daf0..eadbc0c52e 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -6,7 +6,7 @@ package scala.reflect package object runtime { /** The entry point into Scala runtime reflection. - * + * * To use Scala runtime reflection, simply use or import `scala.reflect.runtime.universe._` * * See [[scala.reflect.api.Universe]] or the diff --git a/src/scalacheck/org/scalacheck/Commands.scala b/src/scalacheck/org/scalacheck/Commands.scala index 88ef8ae2a1..2acc460b5e 100644 --- a/src/scalacheck/org/scalacheck/Commands.scala +++ b/src/scalacheck/org/scalacheck/Commands.scala @@ -87,11 +87,6 @@ trait Commands extends Prop { private val bindings = new scala.collection.mutable.ListBuffer[(State,Any)] - private def initState() = { - bindings.clear() - initialState() - } - private def genCmds: Gen[Cmds] = { def sizedCmds(s: State)(sz: Int): Gen[Cmds] = if(sz <= 0) value(Cmds(Nil, Nil)) else for { diff --git a/src/scalap/scala/tools/scalap/Arguments.scala b/src/scalap/scala/tools/scalap/Arguments.scala index a151e3067e..9f139cb5ea 100644 --- a/src/scalap/scala/tools/scalap/Arguments.scala +++ b/src/scalap/scala/tools/scalap/Arguments.scala @@ -87,7 +87,7 @@ object Arguments { i += 2 } } else { - var iter = prefixes.iterator + val iter = prefixes.iterator val j = i while ((i == j) && iter.hasNext) { val prefix = iter.next diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala b/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala index 1500b81050..489a05ecd0 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/Rule.scala @@ -50,7 +50,7 @@ trait Rule[-In, +Out, +A, +X] extends (In => Result[Out, A, X]) { lazy val choices = Rule.this :: other :: Nil } - def orError[In2 <: In] = this orElse(error[In2]) + def orError[In2 <: In] = this orElse error[Any] def |[In2 <: In, Out2 >: Out, A2 >: A, X2 >: X](other : => Rule[In2, Out2, A2, X2]) = orElse(other) diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala index aa5acbb06d..fd70e0de35 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala @@ -167,57 +167,10 @@ object ScalaSigEntryParsers extends RulesWithState with MemoisableRules { val symbolInfo = nameRef ~ symbolRef ~ nat ~ (symbolRef?) ~ ref ~ get ^~~~~~^ SymbolInfo - def symHeader(key: Int) = (key -~ none | (key + 64) -~ nat) + def symHeader(key: Int): EntryParser[Any] = (key -~ none | (key + 64) -~ nat) def symbolEntry(key : Int) = symHeader(key) -~ symbolInfo - /*************************************************** - * Symbol table attribute format: - * Symtab = nentries_Nat {Entry} - * Entry = 1 TERMNAME len_Nat NameInfo - * | 2 TYPENAME len_Nat NameInfo - * | 3 NONEsym len_Nat - * | 4 TYPEsym len_Nat SymbolInfo - * | 5 ALIASsym len_Nat SymbolInfo - * | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref] - * | 7 MODULEsym len_Nat SymbolInfo - * | 8 VALsym len_Nat [defaultGetter_Ref /* no longer needed*/] SymbolInfo [alias_Ref] - * | 9 EXTref len_Nat name_Ref [owner_Ref] - * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref] - * | 11 NOtpe len_Nat - * | 12 NOPREFIXtpe len_Nat - * | 13 THIStpe len_Nat sym_Ref - * | 14 SINGLEtpe len_Nat type_Ref sym_Ref - * | 15 CONSTANTtpe len_Nat constant_Ref - * | 16 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} - * | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref - * | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref} - * | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref} - * | 20 METHODtpe len_Nat tpe_Ref {sym_Ref} - * | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref} - * | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {sym_Ref} /* no longer needed */ - * | 52 SUPERtpe len_Nat tpe_Ref tpe_Ref - * | 24 LITERALunit len_Nat - * | 25 LITERALboolean len_Nat value_Long - * | 26 LITERALbyte len_Nat value_Long - * | 27 LITERALshort len_Nat value_Long - * | 28 LITERALchar len_Nat value_Long - * | 29 LITERALint len_Nat value_Long - * | 30 LITERALlong len_Nat value_Long - * | 31 LITERALfloat len_Nat value_Long - * | 32 LITERALdouble len_Nat value_Long - * | 33 LITERALstring len_Nat name_Ref - * | 34 LITERALnull len_Nat - * | 35 LITERALclass len_Nat tpe_Ref - * | 36 LITERALenum len_Nat sym_Ref - * | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody - * | 41 CHILDREN len_Nat sym_Ref {sym_Ref} - * | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref} - * | 43 ANNOTINFO len_Nat AnnotInfoBody - * | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref} - * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat - * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref} - */ val noSymbol = 3 -^ NoSymbol val typeSymbol = symbolEntry(4) ^^ TypeSymbol as "typeSymbol" val aliasSymbol = symbolEntry(5) ^^ AliasSymbol as "alias" @@ -260,10 +213,9 @@ object ScalaSigEntryParsers extends RulesWithState with MemoisableRules { 22 -~ typeRef ~ (symbolRef*) ^~^ MethodType, 42 -~ typeRef ~ (attribTreeRef*) ^~^ AnnotatedType, 51 -~ typeRef ~ symbolRef ~ (attribTreeRef*) ^~~^ AnnotatedWithSelfType, - 47 -~ typeLevel ~ typeIndex ^~^ DeBruijnIndexType, 48 -~ typeRef ~ (symbolRef*) ^~^ ExistentialType) as "type" - lazy val literal = oneOf( + lazy val literal: EntryParser[Any] = oneOf( 24 -^ (()), 25 -~ longValue ^^ (_ != 0L), 26 -~ longValue ^^ (_.toByte), diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala index cfe615a6d5..e5a4ff649e 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSigPrinter.scala @@ -70,7 +70,7 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { } def isCaseClassObject(o: ObjectSymbol): Boolean = { - val TypeRefType(prefix, classSymbol: ClassSymbol, typeArgs) = o.infoType + val TypeRefType(_, classSymbol: ClassSymbol, _) = o.infoType o.isFinal && (classSymbol.children.find(x => x.isCase && x.isInstanceOf[MethodSymbol]) match { case Some(_) => true case None => false @@ -167,7 +167,7 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { print("object ") val poName = o.symbolInfo.owner.name print(processName(poName)) - val TypeRefType(prefix, classSymbol: ClassSymbol, typeArgs) = o.infoType + val TypeRefType(_, classSymbol: ClassSymbol, _) = o.infoType printType(classSymbol) print(" {\n") printChildren(level, classSymbol) @@ -179,7 +179,7 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { printModifiers(o) print("object ") print(processName(o.name)) - val TypeRefType(prefix, classSymbol: ClassSymbol, typeArgs) = o.infoType + val TypeRefType(_, classSymbol: ClassSymbol, _) = o.infoType printType(classSymbol) print(" {\n") printChildren(level, classSymbol) @@ -191,7 +191,7 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { val j = str.indexOf("[") if (j > 0) str = str.substring(0, j) str = StringUtil.trimStart(str, "=> ") - var i = str.lastIndexOf(".") + val i = str.lastIndexOf(".") val res = if (i > 0) str.substring(i + 1) else str if (res.length > 1) StringUtil.decapitalize(res.substring(0, 1)) else res.toLowerCase }) @@ -381,7 +381,6 @@ class ScalaSigPrinter(stream: PrintStream, printPrivates: Boolean) { toString(typeRef, sep) } case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => toString(typeRef, sep) - //case DeBruijnIndexType(typeLevel, typeIndex) => case ExistentialType(typeRef, symbols) => { val refs = symbols.map(toString _).filter(!_.startsWith("_")).map("type " + _) toString(typeRef, sep) + (if (refs.size > 0) refs.mkString(" forSome {", "; ", "}") else "") diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala index 543ddbe186..0444e701f2 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/Type.scala @@ -22,5 +22,4 @@ case class PolyType(typeRef : Type, symbols : Seq[TypeSymbol]) extends Type case class PolyTypeWithCons(typeRef : Type, symbols : Seq[TypeSymbol], cons: String) extends Type case class AnnotatedType(typeRef : Type, attribTreeRefs : List[Int]) extends Type case class AnnotatedWithSelfType(typeRef : Type, symbol : Symbol, attribTreeRefs : List[Int]) extends Type -case class DeBruijnIndexType(typeLevel : Int, typeIndex : Int) extends Type case class ExistentialType(typeRef : Type, symbols : Seq[Symbol]) extends Type diff --git a/src/swing/scala/swing/Button.scala b/src/swing/scala/swing/Button.scala index f10d49d804..0170727e3b 100644 --- a/src/swing/scala/swing/Button.scala +++ b/src/swing/scala/swing/Button.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import event._ import javax.swing._ object Button { diff --git a/src/swing/scala/swing/ButtonGroup.scala b/src/swing/scala/swing/ButtonGroup.scala index 2075df7c92..0b04d20837 100644 --- a/src/swing/scala/swing/ButtonGroup.scala +++ b/src/swing/scala/swing/ButtonGroup.scala @@ -8,9 +8,7 @@ package scala.swing -import event._ -import javax.swing.{AbstractButton => JAbstractButton,Icon} -import scala.collection.{ mutable, immutable } +import scala.collection.mutable /** * A button mutex. At most one of its associated buttons is selected diff --git a/src/swing/scala/swing/ComboBox.scala b/src/swing/scala/swing/ComboBox.scala index 5b70f6fda9..ce2b3ba6fb 100644 --- a/src/swing/scala/swing/ComboBox.scala +++ b/src/swing/scala/swing/ComboBox.scala @@ -182,7 +182,7 @@ class ComboBox[A](items: Seq[A]) extends Component with Publisher { * of the component to its own defaults _after_ the renderer has been * configured. That's Swing's principle of most suprise. */ - def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getRenderer) + def renderer: ListView.Renderer[A] = ListView.Renderer.wrap[A](peer.getRenderer) def renderer_=(r: ListView.Renderer[A]) { peer.setRenderer(r.peer) } /* XXX: currently not safe to expose: diff --git a/src/swing/scala/swing/EditorPane.scala b/src/swing/scala/swing/EditorPane.scala index b8c506daf0..9b1aab7874 100644 --- a/src/swing/scala/swing/EditorPane.scala +++ b/src/swing/scala/swing/EditorPane.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - package scala.swing -import event._ import javax.swing._ import javax.swing.text._ -import java.awt.event._ /** * A text component that allows multiline text input and display. diff --git a/src/swing/scala/swing/Font.scala.disabled b/src/swing/scala/swing/Font.scala.disabled deleted file mode 100644 index 9e21eb859c..0000000000 --- a/src/swing/scala/swing/Font.scala.disabled +++ /dev/null @@ -1,70 +0,0 @@ -package scala.swing - -/*object Font { - def apply(fontFormat: Int, fontFile: java.io.File) = java.awt.Font.createFont(fontFormat, fontFile) - def apply(fontFormat: Int, fontStream: java.io.InputStream) = java.awt.Font.createFont(fontFormat, fontStream) - def decode(str: String) = java.awt.Font.decode(str) - - /* TODO: finish implementation - /** - * See [java.awt.Font.getFont]. - */ - def get(attributes: Map[_ <: java.text.AttributedCharacterIterator.Attribute, _]) = - java.awt.Font.getFont(ImmutableMapWrapper(attributes)) - - import java.{util => ju} - private case class ImmutableMapWrapper[A, B](underlying : Map[A, B])(t : ClassTag[A]) extends ju.AbstractMap[A, B] { - self => - override def size = underlying.size - - override def put(k : A, v : B) = - throw new UnsupportedOperationException("This is a wrapper that does not support mutation") - override def remove(k : AnyRef) = - throw new UnsupportedOperationException("This is a wrapper that does not support mutation") - - override def entrySet : ju.Set[ju.Map.Entry[A, B]] = new ju.AbstractSet[ju.Map.Entry[A, B]] { - def size = self.size - - def iterator = new ju.Iterator[ju.Map.Entry[A, B]] { - val ui = underlying.iterator - var prev : Option[A] = None - - def hasNext = ui.hasNext - - def next = { - val (k, v) = ui.next - prev = Some(k) - new ju.Map.Entry[A, B] { - def getKey = k - def getValue = v - def setValue(v1 : B) = self.put(k, v1) - override def equals(other : Any) = other match { - case e : ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue - case _ => false - } - } - } - - def remove = prev match { - case Some(k) => val v = self.remove(k.asInstanceOf[AnyRef]) ; prev = None ; v - case _ => throw new IllegalStateException("next must be called at least once before remove") - } - } - } - } - */ - - /** - * See [java.awt.Font.getFont]. - */ - def get(nm: String) = java.awt.Font.getFont(nm) - /** - * See [java.awt.Font.getFont]. - */ - def get(nm: String, font: Font) = java.awt.Font.getFont(nm, font) - - def Insets(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height) - def Rectangle(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height) - def Point(x: Int, y: Int) = new Point(x, y) - def Dimension(x: Int, y: Int) = new Dimension(x, y) -}*/
\ No newline at end of file diff --git a/src/swing/scala/swing/FormattedTextField.scala b/src/swing/scala/swing/FormattedTextField.scala index 311ff42d0a..b08075850c 100644 --- a/src/swing/scala/swing/FormattedTextField.scala +++ b/src/swing/scala/swing/FormattedTextField.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - - package scala.swing -import event._ import javax.swing._ -import java.awt.event._ object FormattedTextField { /** diff --git a/src/swing/scala/swing/ListView.scala b/src/swing/scala/swing/ListView.scala index 40639aa9e2..d0c4e45190 100644 --- a/src/swing/scala/swing/ListView.scala +++ b/src/swing/scala/swing/ListView.scala @@ -216,7 +216,7 @@ class ListView[A] extends Component { def adjusting = peer.getSelectionModel.getValueIsAdjusting } - def renderer: ListView.Renderer[A] = ListView.Renderer.wrap(peer.getCellRenderer) + def renderer: ListView.Renderer[A] = ListView.Renderer.wrap[A](peer.getCellRenderer) def renderer_=(r: ListView.Renderer[A]) { peer.setCellRenderer(r.peer) } def fixedCellWidth = peer.getFixedCellWidth diff --git a/src/swing/scala/swing/MainFrame.scala b/src/swing/scala/swing/MainFrame.scala index 85ce0755ac..1dfc155f9c 100644 --- a/src/swing/scala/swing/MainFrame.scala +++ b/src/swing/scala/swing/MainFrame.scala @@ -6,12 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import event._ - /** * A frame that can be used for main application windows. Shuts down the * framework and quits the application when closed. diff --git a/src/swing/scala/swing/PasswordField.scala b/src/swing/scala/swing/PasswordField.scala index d2fdd0d38a..fd0b586a0f 100644 --- a/src/swing/scala/swing/PasswordField.scala +++ b/src/swing/scala/swing/PasswordField.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - - package scala.swing -import event._ import javax.swing._ -import java.awt.event._ /** * A password field, that displays a replacement character for each character in the password. diff --git a/src/swing/scala/swing/ProgressBar.scala b/src/swing/scala/swing/ProgressBar.scala index 33dd716524..81e2989c3e 100644 --- a/src/swing/scala/swing/ProgressBar.scala +++ b/src/swing/scala/swing/ProgressBar.scala @@ -6,12 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import event._ - /** * A bar indicating progress of some action. Can be in indeterminate mode, * in which it indicates that the action is in progress (usually by some diff --git a/src/swing/scala/swing/Reactions.scala b/src/swing/scala/swing/Reactions.scala index d8a62aa99d..c32212cf3a 100644 --- a/src/swing/scala/swing/Reactions.scala +++ b/src/swing/scala/swing/Reactions.scala @@ -14,8 +14,6 @@ import event.Event import scala.collection.mutable.{Buffer, ListBuffer} object Reactions { - import scala.ref._ - class Impl extends Reactions { private val parts: Buffer[Reaction] = new ListBuffer[Reaction] def isDefinedAt(e: Event) = parts.exists(_ isDefinedAt e) diff --git a/src/swing/scala/swing/SplitPane.scala b/src/swing/scala/swing/SplitPane.scala index dd4f2908d5..f61dfedbf4 100644 --- a/src/swing/scala/swing/SplitPane.scala +++ b/src/swing/scala/swing/SplitPane.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import event._ import Swing._ /** diff --git a/src/swing/scala/swing/SwingActor.scala b/src/swing/scala/swing/SwingActor.scala index 6692180aac..c665fa4c00 100644 --- a/src/swing/scala/swing/SwingActor.scala +++ b/src/swing/scala/swing/SwingActor.scala @@ -6,12 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import scala.actors._ - // Dummy to keep ant from recompiling on every run. trait SwingActor { } diff --git a/src/swing/scala/swing/TabbedPane.scala b/src/swing/scala/swing/TabbedPane.scala index 338050515a..6e46256f86 100644 --- a/src/swing/scala/swing/TabbedPane.scala +++ b/src/swing/scala/swing/TabbedPane.scala @@ -112,9 +112,6 @@ class TabbedPane extends Component with Publisher { */ def tabPlacement_=(b: Alignment.Value) { peer.setTabPlacement(b.id) } - @deprecated("Use tabPlacement_=() instead.", "2.9.1") - def tabPlacement(b: Alignment.Value) { peer.setTabPlacement(b.id) } - /** * The current page selection */ diff --git a/src/swing/scala/swing/TextArea.scala b/src/swing/scala/swing/TextArea.scala index 01bf115d28..2f6bdca119 100644 --- a/src/swing/scala/swing/TextArea.scala +++ b/src/swing/scala/swing/TextArea.scala @@ -6,13 +6,9 @@ ** |/ ** \* */ - - package scala.swing -import event._ import javax.swing._ -import java.awt.event._ /** * A text component that allows multiline text input and display. diff --git a/src/swing/scala/swing/TextComponent.scala b/src/swing/scala/swing/TextComponent.scala index 48c03a5f54..4d23399737 100644 --- a/src/swing/scala/swing/TextComponent.scala +++ b/src/swing/scala/swing/TextComponent.scala @@ -6,12 +6,9 @@ ** |/ ** \* */ - - package scala.swing import event._ -import javax.swing._ import javax.swing.text._ import javax.swing.event._ diff --git a/src/swing/scala/swing/ToggleButton.scala b/src/swing/scala/swing/ToggleButton.scala index 3d3d0b957f..8f210d00d8 100644 --- a/src/swing/scala/swing/ToggleButton.scala +++ b/src/swing/scala/swing/ToggleButton.scala @@ -6,11 +6,8 @@ ** |/ ** \* */ - - package scala.swing -import event._ import javax.swing._ /** diff --git a/src/swing/scala/swing/Window.scala b/src/swing/scala/swing/Window.scala index 5bdb50e959..a9f4ae7538 100644 --- a/src/swing/scala/swing/Window.scala +++ b/src/swing/scala/swing/Window.scala @@ -6,13 +6,10 @@ ** |/ ** \* */ - - package scala.swing import java.awt.{Window => AWTWindow} import event._ -import javax.swing._ /** * A window with decoration such as a title, border, and action buttons. diff --git a/test/files/disabled/A.scala b/test/disabled/buildmanager/overloaded_1/A.scala index c070faf978..c070faf978 100644 --- a/test/files/disabled/A.scala +++ b/test/disabled/buildmanager/overloaded_1/A.scala diff --git a/test/files/disabled/overloaded_1.check b/test/disabled/buildmanager/overloaded_1/overloaded_1.check index 4d643ce6b4..4d643ce6b4 100644 --- a/test/files/disabled/overloaded_1.check +++ b/test/disabled/buildmanager/overloaded_1/overloaded_1.check diff --git a/test/files/disabled/overloaded_1.test b/test/disabled/buildmanager/overloaded_1/overloaded_1.test index 392e0d365f..392e0d365f 100644 --- a/test/files/disabled/overloaded_1.test +++ b/test/disabled/buildmanager/overloaded_1/overloaded_1.test diff --git a/test/files/disabled/t4245/A.scala b/test/disabled/buildmanager/t4245/A.scala index 7c4efe1b4b..7c4efe1b4b 100644 --- a/test/files/disabled/t4245/A.scala +++ b/test/disabled/buildmanager/t4245/A.scala diff --git a/test/files/disabled/t4245/t4245.check b/test/disabled/buildmanager/t4245/t4245.check index 3d3898c671..3d3898c671 100644 --- a/test/files/disabled/t4245/t4245.check +++ b/test/disabled/buildmanager/t4245/t4245.check diff --git a/test/files/disabled/t4245/t4245.test b/test/disabled/buildmanager/t4245/t4245.test index 392e0d365f..392e0d365f 100644 --- a/test/files/disabled/t4245/t4245.test +++ b/test/disabled/buildmanager/t4245/t4245.test diff --git a/test/files/run/t4146.scala b/test/disabled/run/t4146.scala index 93ce22b519..a17de50ee1 100644 --- a/test/files/run/t4146.scala +++ b/test/disabled/run/t4146.scala @@ -1,4 +1,4 @@ -object bob extends Application { +object bob extends App { var name = "Bob" } diff --git a/test/files/bench/equality/eqeq.eqlog b/test/files/bench/equality/eqeq.eqlog index d1e27aceed..55a5eb430a 100644 --- a/test/files/bench/equality/eqeq.eqlog +++ b/test/files/bench/equality/eqeq.eqlog @@ -1,42 +1,42 @@ -Banchmark results for testing equality operations:
-eq.scala: Base case, use eq equality only
-eqeq.scala: Test case, use == instead of eq.
-All tests run on Thinkpad T400, 1.6.0_12 client VM.
-Test command: java eq 5 5
- java eqeq 5 5
-eq.scala, no -optimise
-eq$ 109 78 79 63 63
-eq$ 94 63 63 78 78
-eq$ 94 62 62 62 78
-eq$ 94 78 78 78 78
-eq$ 94 78 78 78 78
-eq.scala, with -optimise
-eq$ 421 63 62 47 63
-eq$ 406 62 62 63 62
-eq$ 407 62 62 78 63
-eq$ 406 63 63 62 62
-eq$ 407 62 62 63 47
-eqeq.scala with version of BoxesRuntime as of Nov 13th, no -optimise
-eqeq$ 562 516 516 516 515
-eqeq$ 547 515 515 531 532
-eqeq$ 532 516 516 515 516
-eqeq$ 547 531 531 516 531
-eqeq$ 547 515 515 516 516
-eqeq.scala with version of BoxesRuntime as of Nov 13th, with -optimise
-eqeq$ 1031 390 391 391 391
-eqeq$ 1031 391 391 391 390
-eqeq$ 1031 390 390 391 391
-eqeq$ 1031 406 407 391 390
-eqeq$ 1031 390 390 391 391
-eqeq.scala with 1st optimized of Nov 14th, no -optimise
-eqeq$ 484 421 438 438 437
-eqeq$ 484 438 437 437 438
-eqeq$ 469 437 453 454 438
-eqeq$ 468 437 438 468 438
-eqeq$ 485 437 437 422 438
-eqeq.scala with 1st optimized of Nov 14th, with -optimise
-eqeq$ 1016 375 391 375 375
-eqeq$ 1016 375 391 390 375
-eqeq$ 1016 390 391 375 375
-eqeq$ 1015 375 391 390 375
-eqeq$ 1016 390 375 375 375
+Banchmark results for testing equality operations: +eq.scala: Base case, use eq equality only +eqeq.scala: Test case, use == instead of eq. +All tests run on Thinkpad T400, 1.6.0_12 client VM. +Test command: java eq 5 5 + java eqeq 5 5 +eq.scala, no -optimise +eq$ 109 78 79 63 63 +eq$ 94 63 63 78 78 +eq$ 94 62 62 62 78 +eq$ 94 78 78 78 78 +eq$ 94 78 78 78 78 +eq.scala, with -optimise +eq$ 421 63 62 47 63 +eq$ 406 62 62 63 62 +eq$ 407 62 62 78 63 +eq$ 406 63 63 62 62 +eq$ 407 62 62 63 47 +eqeq.scala with version of BoxesRuntime as of Nov 13th, no -optimise +eqeq$ 562 516 516 516 515 +eqeq$ 547 515 515 531 532 +eqeq$ 532 516 516 515 516 +eqeq$ 547 531 531 516 531 +eqeq$ 547 515 515 516 516 +eqeq.scala with version of BoxesRuntime as of Nov 13th, with -optimise +eqeq$ 1031 390 391 391 391 +eqeq$ 1031 391 391 391 390 +eqeq$ 1031 390 390 391 391 +eqeq$ 1031 406 407 391 390 +eqeq$ 1031 390 390 391 391 +eqeq.scala with 1st optimized of Nov 14th, no -optimise +eqeq$ 484 421 438 438 437 +eqeq$ 484 438 437 437 438 +eqeq$ 469 437 453 454 438 +eqeq$ 468 437 438 468 438 +eqeq$ 485 437 437 422 438 +eqeq.scala with 1st optimized of Nov 14th, with -optimise +eqeq$ 1016 375 391 375 375 +eqeq$ 1016 375 391 390 375 +eqeq$ 1016 390 391 375 375 +eqeq$ 1015 375 391 390 375 +eqeq$ 1016 390 375 375 375 diff --git a/test/files/continuations-run/implicit-infer-annotations.check b/test/files/continuations-run/implicit-infer-annotations.check new file mode 100644 index 0000000000..e8206c4319 --- /dev/null +++ b/test/files/continuations-run/implicit-infer-annotations.check @@ -0,0 +1,5 @@ +Range(5, 6, 7, 8, 9, 10) +Range(5, 6, 7, 8, 9, 10) +15 +List(10, 1, 2, 3) +Range(5, 6, 7, 8, 9, 10) diff --git a/test/files/continuations-run/implicit-infer-annotations.scala b/test/files/continuations-run/implicit-infer-annotations.scala new file mode 100644 index 0000000000..3f0e959f60 --- /dev/null +++ b/test/files/continuations-run/implicit-infer-annotations.scala @@ -0,0 +1,59 @@ +import annotation._ + +object A { + class foo[-B,+C] extends StaticAnnotation with TypeConstraint + + def shift[A, B, C](fun: (A => B) => C): A @foo[B, C] = ??? + def reset[A, C](ctx: => (A @foo[A, C])): C = ??? + + def m1 = reset { shift { f: (Int => Range) => f(5) }.to(10) } +} + +object B { + import scala.util.continuations._ + + def m1 = reset { shift { f: (Int => Range) => f(5) }.to(10) } + def m2 = reset { val a = shift { f: (Int => Range) => f(5) } ; a.to(10) } + + val x1 = reset{ + shift{ cont: (Int => Range) => + cont(5) + }.to(10) + } + + val x2 = reset{ + val a = shift{ cont: (Int => Range) => + cont(5) + } + a.to(10) + } // x is now Range(5, 6, 7, 8, 9, 10) + + val x3 = reset{ + shift{ cont: (Int => Int) => + cont(5) + } + 10 + } // x is now 15 + + val x4 = reset{ + 10 :: shift{ cont: (List[Int] => List[Int]) => + cont(List(1, 2, 3)) + } + } // x is List(10, 1, 2, 3) + + val x5 = reset{ + new scala.runtime.RichInt(shift{ cont: (Int => Range) => + cont(5) + }) to 10 + } +} + +object Test { + def main(args: Array[String]): Unit = { + import B._ + println(x1) + println(x2) + println(x3) + println(x4) + println(x5) + } +} diff --git a/test/files/detach-run/actor/java.policy b/test/files/detach-run/actor/java.policy index 4beb2ca26b..b305f10b4c 100644 --- a/test/files/detach-run/actor/java.policy +++ b/test/files/detach-run/actor/java.policy @@ -19,7 +19,7 @@ grant codeBase "@PROJECT_LIB_BASE@" { permission java.util.PropertyPermission "java.rmi.server.hostname", "read"; permission java.util.PropertyPermission "sun.rmi.dgc.server.gcInterval", "read,write"; }; -
+ //grant { // permission java.security.AllPermission; //}; diff --git a/test/files/instrumented/t6611.check b/test/files/instrumented/t6611.check new file mode 100644 index 0000000000..5cd691e93a --- /dev/null +++ b/test/files/instrumented/t6611.check @@ -0,0 +1 @@ +Method call statistics: diff --git a/test/files/instrumented/t6611.scala b/test/files/instrumented/t6611.scala new file mode 100644 index 0000000000..4c52f8a5ef --- /dev/null +++ b/test/files/instrumented/t6611.scala @@ -0,0 +1,35 @@ +import scala.tools.partest.instrumented.Instrumentation._ + +object Test { + def main(args: Array[String]) { + startProfiling() + + // tests optimization in Cleanup for varargs reference arrays + Array("") + + + Array(true) + Array(true, false) + Array(1: Byte) + Array(1: Byte, 2: Byte) + Array(1: Short) + Array(1: Short, 2: Short) + Array(1) + Array(1, 2) + Array(1L) + Array(1L, 2L) + Array(1d) + Array(1d, 2d) + Array(1f) + Array(1f, 2f) + + /* Not currently optimized: + Array[Int](1, 2) etc + Array(()) + Array((), ()) + */ + + stopProfiling() + printStatistics() + } +} diff --git a/test/files/jvm/t1143-2/t1143-2.scala b/test/files/jvm/t1143-2/t1143-2.scala index 44b1febd8b..13ab13b48c 100644 --- a/test/files/jvm/t1143-2/t1143-2.scala +++ b/test/files/jvm/t1143-2/t1143-2.scala @@ -16,43 +16,39 @@ object Serialize { } } -@serializable @SerialVersionUID(1L) -class VarModel[T]( getter: => T, setter: T => Unit ) -{ +class VarModel[T](getter: => T, setter: T => Unit) extends Serializable { Serialize.write(getter) Serialize.write(setter) - def this( getter: => T ) = this( getter, null ) + def this(getter: => T) = this(getter, null) def getObject: AnyRef = getter.asInstanceOf[AnyRef] - def setObject( v: AnyRef ) = { - if( setter==null ) - throw new RuntimeException( "Tried to set readonly model!") - setter( v.asInstanceOf[T] ) + def setObject(v: AnyRef) = { + if(setter==null) + throw new RuntimeException("Tried to set readonly model!") + setter(v.asInstanceOf[T]) } def detach = () } -@serializable @SerialVersionUID(1L) -class Printer( p: VarModel[String] ) { - def print = println( p.getObject ); +class Printer(p: VarModel[String]) extends Serializable { + def print = println(p.getObject) } class Component extends Marker { } class Form extends Component { } -@serializable @SerialVersionUID(1L) -class Main { +class Main extends Serializable { var pass = "pass" - def main(args : Array[String]) : Unit = { + def main(args: Array[String]): Unit = { val f = new Form { - val p = new Printer( new VarModel( pass, s => pass = s ) ); + val p = new Printer(new VarModel(pass, s => pass = s)) p.print } () diff --git a/test/files/jvm/t1143.scala b/test/files/jvm/t1143.scala index 7dd374f432..eb03c7224e 100644 --- a/test/files/jvm/t1143.scala +++ b/test/files/jvm/t1143.scala @@ -16,9 +16,8 @@ object Serialize { } } -@serializable @SerialVersionUID(1L) -class VarModel[T](getter: => T, setter: T => Unit) { +class VarModel[T](getter: => T, setter: T => Unit) extends Serializable { Serialize.write(getter) Serialize.write(setter) @@ -35,23 +34,20 @@ class VarModel[T](getter: => T, setter: T => Unit) { def detach = () } -@serializable @SerialVersionUID(1L) -class Printer(p: VarModel[String]) { +class Printer(p: VarModel[String]) extends Serializable { def print = println(p.getObject) } -@serializable @SerialVersionUID(1L) -class Component { +class Component extends Serializable { } class Form extends Component { } -@serializable @SerialVersionUID(1L) -class Main { +class Main extends Serializable { var pass = "pass" def main(args: Array[String]) { val f = new Form { diff --git a/test/files/jvm/t1342/SI.scala b/test/files/jvm/t1342/SI.scala index 8e3b753210..7c37d4bcd7 100644 --- a/test/files/jvm/t1342/SI.scala +++ b/test/files/jvm/t1342/SI.scala @@ -4,7 +4,7 @@ class SI extends JI { } } -object Test extends Application { +object Test extends App { val x: JI = new SI x.varArgsMethod("one", "two") } diff --git a/test/files/jvm/t1600.scala b/test/files/jvm/t1600.scala index 7e23687425..69179c1ba4 100644 --- a/test/files/jvm/t1600.scala +++ b/test/files/jvm/t1600.scala @@ -69,8 +69,7 @@ object Test { var hashCodeModifier = 0 } - @serializable - class Foo { + class Foo extends Serializable { override def hashCode = System.identityHashCode(this) + Foo.hashCodeModifier } } diff --git a/test/files/jvm/ticket2163/ticket2163.java b/test/files/jvm/t2163/t2163.java index b6511d241c..83bd37d212 100644 --- a/test/files/jvm/ticket2163/ticket2163.java +++ b/test/files/jvm/t2163/t2163.java @@ -1,9 +1,9 @@ import java.util.*; -public class ticket2163 { +public class t2163 { public void test() { List<Integer> array = new ArrayList<Integer>(); - Ticket2163Scala<List> foo = new Ticket2163Scala<List>(array); + T2163Scala<List> foo = new T2163Scala<List>(array); foo.bar(array); } } diff --git a/test/files/jvm/t2163/t2163.scala b/test/files/jvm/t2163/t2163.scala new file mode 100644 index 0000000000..f73b520cbe --- /dev/null +++ b/test/files/jvm/t2163/t2163.scala @@ -0,0 +1,5 @@ +class T2163Scala[CC[X]](x: CC[Int]) { + def bar[DD[X]](meh: DD[Int]): CC[Int] = x +} + +object Test extends App {} diff --git a/test/files/jvm/t2470.cmds b/test/files/jvm/t2470.cmds deleted file mode 100644 index b4ef0f4aeb..0000000000 --- a/test/files/jvm/t2470.cmds +++ /dev/null @@ -1,3 +0,0 @@ -javac Action.java Task.java -scalac Test_1.scala -scalac Read_Classfile_2.scala diff --git a/test/files/jvm/t2570/Test.scala b/test/files/jvm/t2570/Test.scala index 7944aedae6..f1cba53546 100644 --- a/test/files/jvm/t2570/Test.scala +++ b/test/files/jvm/t2570/Test.scala @@ -1,3 +1,3 @@ class Test2 extends Test1[Test3[Test4]] class Test4 -object Test extends Application {}
\ No newline at end of file +object Test extends App {}
\ No newline at end of file diff --git a/test/files/jvm/t3003.cmds b/test/files/jvm/t3003.cmds deleted file mode 100644 index c00396627c..0000000000 --- a/test/files/jvm/t3003.cmds +++ /dev/null @@ -1,2 +0,0 @@ -javac Annot.java -scalac Test_1.scala diff --git a/test/files/jvm/t3415/HelloWorld.scala b/test/files/jvm/t3415/HelloWorld.scala index 53bf55e444..5ef012390e 100644 --- a/test/files/jvm/t3415/HelloWorld.scala +++ b/test/files/jvm/t3415/HelloWorld.scala @@ -1,4 +1,4 @@ -object Test extends Application { +object Test extends App { @Hello def foo() { } } diff --git a/test/files/jvm/ticket4283/AbstractFoo.java b/test/files/jvm/t4283/AbstractFoo.java index 74f3827fe3..74f3827fe3 100644 --- a/test/files/jvm/ticket4283/AbstractFoo.java +++ b/test/files/jvm/t4283/AbstractFoo.java diff --git a/test/files/jvm/ticket4283/ScalaBipp.scala b/test/files/jvm/t4283/ScalaBipp.scala index 36dea9f4de..36dea9f4de 100644 --- a/test/files/jvm/ticket4283/ScalaBipp.scala +++ b/test/files/jvm/t4283/ScalaBipp.scala diff --git a/test/files/jvm/ticket4283/Test.scala b/test/files/jvm/t4283/Test.scala index 9bbfaab928..9bbfaab928 100644 --- a/test/files/jvm/ticket4283/Test.scala +++ b/test/files/jvm/t4283/Test.scala diff --git a/test/files/jvm/ticket2163/ticket2163.scala b/test/files/jvm/ticket2163/ticket2163.scala deleted file mode 100644 index d30bfe251b..0000000000 --- a/test/files/jvm/ticket2163/ticket2163.scala +++ /dev/null @@ -1,5 +0,0 @@ -class Ticket2163Scala[CC[X]](x: CC[Int]) { - def bar[DD[X]](meh: DD[Int]): CC[Int] = x -} - -object Test extends Application {} diff --git a/test/files/jvm/typerep.scala b/test/files/jvm/typerep.scala index 3befc7ff3f..47bd16a467 100644 --- a/test/files/jvm/typerep.scala +++ b/test/files/jvm/typerep.scala @@ -280,100 +280,74 @@ object TypeRep { override def toString = "Nothing" } - @serializable case class ClassRep[A](elemRep: TypeRep[A]) extends TypeRep[Class[A]] { override def toString = "Class[" + elemRep + "]" } - @serializable case class SomeRep[A](elemRep: TypeRep[A]) extends TypeRep[Some[A]] { override def toString = "Some[" + elemRep + "]" } - @serializable case class NoneRep[A](elemRep: TypeRep[A]) extends TypeRep[Option[A]] { override def toString = "None[" + elemRep + "]" } - - @serializable case class ListRep[A](elemRep: TypeRep[A]) extends TypeRep[List[A]] { override def toString = "List[" + elemRep + "]" } - - @serializable case class ArrayRep[A](elemRep: TypeRep[A]) extends TypeRep[Array[A]] { override def toString = "Array[" + elemRep + "]" } - - @serializable case class Tuple2Rep[A1, A2](_1: TypeRep[A1], _2: TypeRep[A2]) extends TypeRep[(A1, A2)] { override def toString = "Tuple2[" + _1 + ", " + _2 + "]" } - @serializable case class Tuple3Rep[A1, A2, A3](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3]) extends TypeRep[Tuple3[A1, A2, A3]] { override def toString = "Tuple3[" + _1 + ", " + _2 + ", " + _3 + "]" } - @serializable case class Tuple4Rep[A1, A2, A3, A4](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4]) extends TypeRep[Tuple4[A1, A2, A3, A4]] { override def toString = "Tuple4[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + "]" } - @serializable case class Tuple5Rep[A1, A2, A3, A4, A5](_1: TypeRep[A1], _2: TypeRep[A2], _3: TypeRep[A3], _4: TypeRep[A4], _5: TypeRep[A5]) extends TypeRep[Tuple5[A1, A2, A3, A4, A5]] { override def toString = "Tuple5[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + "]" } - @serializable case class Tuple6Rep[A1, A2, A3, A4, A5, A6](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6]) extends TypeRep[Tuple6[A1, A2, A3, A4, A5, A6]] { override def toString = "Tuple6[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + "]" } - @serializable case class Tuple7Rep[A1, A2, A3, A4, A5, A6, A7](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7]) extends TypeRep[Tuple7[A1, A2, A3, A4, A5, A6, A7]] { override def toString = "Tuple7[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + "]" } - @serializable case class Tuple8Rep[A1, A2, A3, A4, A5, A6, A7, A8](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7], val _8: TypeRep[A8]) extends TypeRep[Tuple8[A1, A2, A3, A4, A5, A6, A7, A8]] { override def toString = "Tuple8[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ", " + _8 + "]" } - @serializable case class Tuple9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9](val _1: TypeRep[A1], val _2: TypeRep[A2], val _3: TypeRep[A3], val _4: TypeRep[A4], val _5: TypeRep[A5], val _6: TypeRep[A6], val _7: TypeRep[A7], val _8: TypeRep[A8], val _9: TypeRep[A9]) extends TypeRep[Tuple9[A1, A2, A3, A4, A5, A6, A7, A8, A9]] { override def toString = "Tuple9[" + _1 + ", " + _2 + ", " + _3 + ", " + _4 + ", " + _5 + ", " + _6 + ", " + _7 + ", " + _8 + ", " + _9 + "]" } - @serializable case class Function1Rep[A1, B](a1: TypeRep[A1], b: TypeRep[B]) extends TypeRep[Function1[A1, B]] { override def toString = "Function1[" + a1 + ", " + b + "]" } - @serializable case class Function2Rep[A1, A2, B](a1: TypeRep[A1], a2: TypeRep[A2], b: TypeRep[B]) extends TypeRep[Function2[A1, A2, B]] { override def toString = "Function2[" + a1 + ", " + a2 + ", " + b + "]" } - @serializable case class Function3Rep[A1, A2, A3, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], b: TypeRep[B]) extends TypeRep[Function3[A1, A2, A3, B]] { override def toString = "Function3[" + a1 + ", " + a2 + ", " + a3 + ", " + b + "]" } - @serializable case class Function4Rep[A1, A2, A3, A4, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], b: TypeRep[B]) extends TypeRep[Function4[A1, A2, A3, A4, B]] { override def toString = "Function4[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + b + "]" } - @serializable case class Function5Rep[A1, A2, A3, A4, A5, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], b: TypeRep[B]) extends TypeRep[Function5[A1, A2, A3, A4, A5, B]] { override def toString = "Function5[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + b + "]" } - @serializable case class Function6Rep[A1, A2, A3, A4, A5, A6, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], b: TypeRep[B]) extends TypeRep[Function6[A1, A2, A3, A4, A5, A6, B]] { override def toString = "Function6[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + b + "]" } - @serializable case class Function7Rep[A1, A2, A3, A4, A5, A6, A7, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], b: TypeRep[B]) extends TypeRep[Function7[A1, A2, A3, A4, A5, A6, A7, B]] { override def toString = "Function7[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + b + "]" } - @serializable case class Function8Rep[A1, A2, A3, A4, A5, A6, A7, A8, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], b: TypeRep[B]) extends TypeRep[Function8[A1, A2, A3, A4, A5, A6, A7, A8, B]] { override def toString = "Function8[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + a8 + b + "]" } - @serializable case class Function9Rep[A1, A2, A3, A4, A5, A6, A7, A8, A9, B](a1: TypeRep[A1], a2: TypeRep[A2], a3: TypeRep[A3], a4: TypeRep[A4], a5: TypeRep[A5], a6: TypeRep[A6], a7: TypeRep[A7], a8: TypeRep[A8], a9: TypeRep[A9], b: TypeRep[B]) extends TypeRep[Function9[A1, A2, A3, A4, A5, A6, A7, A8, A9, B]] { override def toString = "Function9[" + a1 + ", " + a2 + ", " + a3 + ", " + a4 + ", " + a5 + ", " + a6 + ", " + a7 + ", " + a8 + ", " + b + "]" } /* - @serializable case class ObjectRep[A](c: Class) extends TypeRep[A] { override def toString = c.getName } diff --git a/test/files/lib/jsoup-1.3.1.jar.desired.sha1 b/test/files/lib/jsoup-1.3.1.jar.desired.sha1 new file mode 100644 index 0000000000..46fa3dae9d --- /dev/null +++ b/test/files/lib/jsoup-1.3.1.jar.desired.sha1 @@ -0,0 +1 @@ +346d3dff4088839d6b4d163efa2892124039d216 ?jsoup-1.3.1.jar diff --git a/test/files/neg/abstract-inaccessible.check b/test/files/neg/abstract-inaccessible.check index 42b98ac026..d56f5691be 100644 --- a/test/files/neg/abstract-inaccessible.check +++ b/test/files/neg/abstract-inaccessible.check @@ -1,13 +1,15 @@ -abstract-inaccessible.scala:5: error: method implementMe in trait YourTrait references private[foo] trait Bippy. +abstract-inaccessible.scala:5: warning: method implementMe in trait YourTrait references private[foo] trait Bippy. Classes which cannot access Bippy may be unable to provide a concrete implementation of implementMe. def implementMe(f: Int => (String, Bippy)): Unit ^ -abstract-inaccessible.scala:6: error: method overrideMe in trait YourTrait references private[foo] trait Bippy. +abstract-inaccessible.scala:6: warning: method overrideMe in trait YourTrait references private[foo] trait Bippy. Classes which cannot access Bippy may be unable to override overrideMe. def overrideMe[T <: Bippy](x: T): T = x ^ -abstract-inaccessible.scala:7: error: method overrideMeAlso in trait YourTrait references private[foo] trait Bippy. +abstract-inaccessible.scala:7: warning: method overrideMeAlso in trait YourTrait references private[foo] trait Bippy. Classes which cannot access Bippy may be unable to override overrideMeAlso. def overrideMeAlso(x: Map[Int, Set[Bippy]]) = 5 ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/ambiguous-float-dots.check b/test/files/neg/ambiguous-float-dots.check index 6c21056d7a..cdd2d6fa2a 100644 --- a/test/files/neg/ambiguous-float-dots.check +++ b/test/files/neg/ambiguous-float-dots.check @@ -1,16 +1,27 @@ -ambiguous-float-dots.scala:2: error: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. +ambiguous-float-dots.scala:2: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. val x0 = 5. ^ -ambiguous-float-dots.scala:6: error: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. +ambiguous-float-dots.scala:6: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. val x1 = 5.f ^ -ambiguous-float-dots.scala:7: error: Treating numbers with a leading zero as octal is deprecated. +ambiguous-float-dots.scala:7: warning: Treating numbers with a leading zero as octal is deprecated. val y0 = 055 ^ -ambiguous-float-dots.scala:11: error: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. +ambiguous-float-dots.scala:11: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. 1.+(2) ^ -ambiguous-float-dots.scala:12: error: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. +ambiguous-float-dots.scala:12: warning: This lexical syntax is deprecated. From scala 2.11, a dot will only be considered part of a number if it is immediately followed by a digit. 1. + 2 ^ -5 errors found +ambiguous-float-dots.scala:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 1.+(2) + ^ +ambiguous-float-dots.scala:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 1. + 2 + ^ +ambiguous-float-dots.scala:13: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 1 + 2 + ^ +error: No warnings can be incurred under -Xfatal-warnings. +8 warnings found +one error found diff --git a/test/files/neg/array-not-seq.check b/test/files/neg/array-not-seq.check deleted file mode 100644 index a3a639e772..0000000000 --- a/test/files/neg/array-not-seq.check +++ /dev/null @@ -1,13 +0,0 @@ -array-not-seq.scala:2: error: An Array will no longer match as Seq[_]. - def f1(x: Any) = x.isInstanceOf[Seq[_]] - ^ -array-not-seq.scala:4: error: An Array will no longer match as Seq[_]. - case _: Seq[_] => true - ^ -array-not-seq.scala:16: error: An Array will no longer match as Seq[_]. - case (Some(_: Seq[_]), Nil, _) => 1 - ^ -array-not-seq.scala:17: error: An Array will no longer match as Seq[_]. - case (None, List(_: List[_], _), _) => 2 - ^ -four errors found diff --git a/test/files/neg/array-not-seq.flags b/test/files/neg/array-not-seq.flags deleted file mode 100644 index 4e9f7e4a56..0000000000 --- a/test/files/neg/array-not-seq.flags +++ /dev/null @@ -1 +0,0 @@ --Xmigration -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/array-not-seq.scala b/test/files/neg/array-not-seq.scala deleted file mode 100644 index 5f367bdd85..0000000000 --- a/test/files/neg/array-not-seq.scala +++ /dev/null @@ -1,26 +0,0 @@ -object Test { - def f1(x: Any) = x.isInstanceOf[Seq[_]] - def f2(x: Any) = x match { - case _: Seq[_] => true - case _ => false - } - - def f3(x: Any) = x match { - case _: Array[_] => true - case _ => false - } - - def f4(x: Any) = x.isInstanceOf[Traversable[_]] - - def f5(x1: Any, x2: Any, x3: AnyRef) = (x1, x2, x3) match { - case (Some(_: Seq[_]), Nil, _) => 1 - case (None, List(_: List[_], _), _) => 2 - case _ => 3 - } - - def main(args: Array[String]): Unit = { - // println(f1(Array(1))) - // println(f2(Array(1))) - // println(f3(Array(1)) - } -} diff --git a/test/files/neg/catch-all.check b/test/files/neg/catch-all.check index 62f895cc7e..2d58dd99a8 100644 --- a/test/files/neg/catch-all.check +++ b/test/files/neg/catch-all.check @@ -1,10 +1,15 @@ -catch-all.scala:2: error: This catches all Throwables. If this is really intended, use `case _ : Throwable` to clear this warning. +catch-all.scala:2: warning: This catches all Throwables, which often has undesirable consequences. +If intentional, use `case _ : Throwable` to clear this warning. try { "warn" } catch { case _ => } ^ -catch-all.scala:4: error: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning. +catch-all.scala:4: warning: This catches all Throwables, which often has undesirable consequences. +If intentional, use `case x : Throwable` to clear this warning. try { "warn" } catch { case x => } ^ -catch-all.scala:6: error: This catches all Throwables. If this is really intended, use `case x : Throwable` to clear this warning. +catch-all.scala:6: warning: This catches all Throwables, which often has undesirable consequences. +If intentional, use `case x : Throwable` to clear this warning. try { "warn" } catch { case _: RuntimeException => ; case x => } ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/check-dead.check b/test/files/neg/check-dead.check index 29601c1d4a..2150a942bf 100644 --- a/test/files/neg/check-dead.check +++ b/test/files/neg/check-dead.check @@ -1,13 +1,15 @@ -check-dead.scala:7: error: dead code following this construct +check-dead.scala:7: warning: dead code following this construct def z1 = y1(throw new Exception) // should warn ^ -check-dead.scala:10: error: dead code following this construct +check-dead.scala:10: warning: dead code following this construct def z2 = y2(throw new Exception) // should warn ^ -check-dead.scala:29: error: dead code following this construct +check-dead.scala:29: warning: dead code following this construct throw new Exception // should warn ^ -check-dead.scala:33: error: dead code following this construct +check-dead.scala:33: warning: dead code following this construct throw new Exception // should warn ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check index d785179a56..e5f1a38d96 100644 --- a/test/files/neg/checksensible.check +++ b/test/files/neg/checksensible.check @@ -1,100 +1,102 @@ -checksensible.scala:13: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:13: warning: comparing a fresh object using `eq' will always yield false (new AnyRef) eq (new AnyRef) ^ -checksensible.scala:14: error: comparing a fresh object using `ne' will always yield true +checksensible.scala:14: warning: comparing a fresh object using `ne' will always yield true (new AnyRef) ne (new AnyRef) ^ -checksensible.scala:15: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:15: warning: comparing a fresh object using `eq' will always yield false Shmoopie eq (new AnyRef) ^ -checksensible.scala:16: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:16: warning: comparing a fresh object using `eq' will always yield false (Shmoopie: AnyRef) eq (new AnyRef) ^ -checksensible.scala:17: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:17: warning: comparing a fresh object using `eq' will always yield false (new AnyRef) eq Shmoopie ^ -checksensible.scala:18: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:18: warning: comparing a fresh object using `eq' will always yield false (new AnyRef) eq null ^ -checksensible.scala:19: error: comparing a fresh object using `eq' will always yield false +checksensible.scala:19: warning: comparing a fresh object using `eq' will always yield false null eq new AnyRef ^ -checksensible.scala:26: error: comparing values of types Unit and Int using `==' will always yield false +checksensible.scala:26: warning: comparing values of types Unit and Int using `==' will always yield false (c = 1) == 0 ^ -checksensible.scala:27: error: comparing values of types Int and Unit using `==' will always yield false +checksensible.scala:27: warning: comparing values of types Int and Unit using `==' will always yield false 0 == (c = 1) ^ -checksensible.scala:29: error: comparing values of types Int and String using `==' will always yield false +checksensible.scala:29: warning: comparing values of types Int and String using `==' will always yield false 1 == "abc" ^ -checksensible.scala:33: error: comparing values of types Some[Int] and Int using `==' will always yield false +checksensible.scala:33: warning: comparing values of types Some[Int] and Int using `==' will always yield false Some(1) == 1 // as above ^ -checksensible.scala:38: error: comparing a fresh object using `==' will always yield false +checksensible.scala:38: warning: comparing a fresh object using `==' will always yield false new AnyRef == 1 ^ -checksensible.scala:41: error: comparing values of types Int and Boolean using `==' will always yield false +checksensible.scala:41: warning: comparing values of types Int and Boolean using `==' will always yield false 1 == (new java.lang.Boolean(true)) ^ -checksensible.scala:43: error: comparing values of types Int and Boolean using `!=' will always yield true +checksensible.scala:43: warning: comparing values of types Int and Boolean using `!=' will always yield true 1 != true ^ -checksensible.scala:44: error: comparing values of types Unit and Boolean using `==' will always yield false +checksensible.scala:44: warning: comparing values of types Unit and Boolean using `==' will always yield false () == true ^ -checksensible.scala:45: error: comparing values of types Unit and Unit using `==' will always yield true +checksensible.scala:45: warning: comparing values of types Unit and Unit using `==' will always yield true () == () ^ -checksensible.scala:46: error: comparing values of types Unit and Unit using `==' will always yield true +checksensible.scala:46: warning: comparing values of types Unit and Unit using `==' will always yield true () == println ^ -checksensible.scala:47: error: comparing values of types Unit and scala.runtime.BoxedUnit using `==' will always yield true +checksensible.scala:47: warning: comparing values of types Unit and scala.runtime.BoxedUnit using `==' will always yield true () == scala.runtime.BoxedUnit.UNIT // these should warn for always being true/false ^ -checksensible.scala:48: error: comparing values of types scala.runtime.BoxedUnit and Unit using `!=' will always yield false +checksensible.scala:48: warning: comparing values of types scala.runtime.BoxedUnit and Unit using `!=' will always yield false scala.runtime.BoxedUnit.UNIT != () ^ -checksensible.scala:51: error: comparing values of types Int and Unit using `!=' will always yield true +checksensible.scala:51: warning: comparing values of types Int and Unit using `!=' will always yield true (1 != println) ^ -checksensible.scala:52: error: comparing values of types Int and Symbol using `!=' will always yield true +checksensible.scala:52: warning: comparing values of types Int and Symbol using `!=' will always yield true (1 != 'sym) ^ -checksensible.scala:58: error: comparing a fresh object using `==' will always yield false +checksensible.scala:58: warning: comparing a fresh object using `==' will always yield false ((x: Int) => x + 1) == null ^ -checksensible.scala:59: error: comparing a fresh object using `==' will always yield false +checksensible.scala:59: warning: comparing a fresh object using `==' will always yield false Bep == ((_: Int) + 1) ^ -checksensible.scala:61: error: comparing a fresh object using `==' will always yield false +checksensible.scala:61: warning: comparing a fresh object using `==' will always yield false new Object == new Object ^ -checksensible.scala:62: error: comparing a fresh object using `==' will always yield false +checksensible.scala:62: warning: comparing a fresh object using `==' will always yield false new Object == "abc" ^ -checksensible.scala:63: error: comparing a fresh object using `!=' will always yield true +checksensible.scala:63: warning: comparing a fresh object using `!=' will always yield true new Exception() != new Exception() ^ -checksensible.scala:66: error: comparing values of types Int and Null using `==' will always yield false +checksensible.scala:66: warning: comparing values of types Int and Null using `==' will always yield false if (foo.length == null) "plante" else "plante pas" ^ -checksensible.scala:71: error: comparing values of types Bip and Bop using `==' will always yield false +checksensible.scala:71: warning: comparing values of types Bip and Bop using `==' will always yield false (x1 == x2) ^ -checksensible.scala:81: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false +checksensible.scala:81: warning: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false c3 == z1 ^ -checksensible.scala:82: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false +checksensible.scala:82: warning: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false z1 == c3 ^ -checksensible.scala:83: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true +checksensible.scala:83: warning: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true z1 != c3 ^ -checksensible.scala:84: error: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true +checksensible.scala:84: warning: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true c3 != "abc" ^ -checksensible.scala:95: error: comparing values of types Unit and Int using `!=' will always yield true +checksensible.scala:95: warning: comparing values of types Unit and Int using `!=' will always yield true while ((c = in.read) != -1) ^ -33 errors found +error: No warnings can be incurred under -Xfatal-warnings. +33 warnings found +one error found diff --git a/test/files/neg/classmanifests_new_deprecations.check b/test/files/neg/classmanifests_new_deprecations.check index 12428c7626..fddd6bf5b4 100644 --- a/test/files/neg/classmanifests_new_deprecations.check +++ b/test/files/neg/classmanifests_new_deprecations.check @@ -1,31 +1,33 @@ -classmanifests_new_deprecations.scala:2: error: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:2: warning: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead def cm1[T: ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:3: error: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:3: warning: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead def cm2[T](implicit evidence$1: ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:4: error: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead val cm3: ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:4: error: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:4: warning: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead val cm3: ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:6: error: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:6: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead def rcm1[T: scala.reflect.ClassManifest] = ??? ^ -classmanifests_new_deprecations.scala:7: error: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:7: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead def rcm2[T](implicit evidence$1: scala.reflect.ClassManifest[T]) = ??? ^ -classmanifests_new_deprecations.scala:8: error: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead val rcm3: scala.reflect.ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:8: error: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:8: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead val rcm3: scala.reflect.ClassManifest[Int] = null ^ -classmanifests_new_deprecations.scala:10: error: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:10: warning: type ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead type CM[T] = ClassManifest[T] ^ -classmanifests_new_deprecations.scala:15: error: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead +classmanifests_new_deprecations.scala:15: warning: type ClassManifest in package reflect is deprecated: Use scala.reflect.ClassTag instead type RCM[T] = scala.reflect.ClassManifest[T] ^ -10 errors found +error: No warnings can be incurred under -Xfatal-warnings. +10 warnings found +one error found diff --git a/test/files/neg/cycle-bounds.check b/test/files/neg/cycle-bounds.check new file mode 100644 index 0000000000..d924838aec --- /dev/null +++ b/test/files/neg/cycle-bounds.check @@ -0,0 +1,4 @@ +cycle-bounds.scala:5: error: illegal cyclic reference involving type T +class NotOk[T <: Comparable[_ <: T]] + ^ +one error found diff --git a/test/files/neg/cycle-bounds.flags b/test/files/neg/cycle-bounds.flags new file mode 100644 index 0000000000..ca20f55172 --- /dev/null +++ b/test/files/neg/cycle-bounds.flags @@ -0,0 +1 @@ +-Ybreak-cycles diff --git a/test/files/neg/cycle-bounds.scala b/test/files/neg/cycle-bounds.scala new file mode 100644 index 0000000000..0b43bc703e --- /dev/null +++ b/test/files/neg/cycle-bounds.scala @@ -0,0 +1,5 @@ +// This should be allowed +class Ok[T <: Comparable[_ >: T]] + +// This is (il)legitimately a cyclic reference +class NotOk[T <: Comparable[_ <: T]] diff --git a/test/files/neg/dbldef.check b/test/files/neg/dbldef.check index 3ee63475e4..b896c4cdcf 100644 --- a/test/files/neg/dbldef.check +++ b/test/files/neg/dbldef.check @@ -6,9 +6,7 @@ dbldef.scala:1: error: type mismatch; required: Int case class test0(x: Int, x: Float) ^ -dbldef.scala:1: error: type mismatch; - found : Float - required: Int +dbldef.scala:1: error: in class test0, multiple overloaded alternatives of x define default arguments case class test0(x: Int, x: Float) ^ three errors found diff --git a/test/files/neg/exhausting.check b/test/files/neg/exhausting.check index 0f0d13cb33..c573eb3e15 100644 --- a/test/files/neg/exhausting.check +++ b/test/files/neg/exhausting.check @@ -1,25 +1,27 @@ -exhausting.scala:21: error: match may not be exhaustive. +exhausting.scala:21: warning: match may not be exhaustive. It would fail on the following input: List(_, _, _) def fail1[T](xs: List[T]) = xs match { ^ -exhausting.scala:27: error: match may not be exhaustive. +exhausting.scala:27: warning: match may not be exhaustive. It would fail on the following input: Nil def fail2[T](xs: List[T]) = xs match { ^ -exhausting.scala:32: error: match may not be exhaustive. +exhausting.scala:32: warning: match may not be exhaustive. It would fail on the following input: List((x: Int forSome x not in (1, 2))) def fail3a(xs: List[Int]) = xs match { ^ -exhausting.scala:39: error: match may not be exhaustive. +exhausting.scala:39: warning: match may not be exhaustive. It would fail on the following input: Bar3 def fail3[T](x: Foo[T]) = x match { ^ -exhausting.scala:47: error: match may not be exhaustive. +exhausting.scala:47: warning: match may not be exhaustive. It would fail on the following inputs: (Bar1, Bar2), (Bar1, Bar3), (Bar2, Bar1), (Bar2, Bar2) def fail4[T <: AnyRef](xx: (Foo[T], Foo[T])) = xx match { ^ -exhausting.scala:56: error: match may not be exhaustive. +exhausting.scala:56: warning: match may not be exhaustive. It would fail on the following inputs: (Bar1, Bar2), (Bar1, Bar3), (Bar2, Bar1), (Bar2, Bar2) def fail5[T](xx: (Foo[T], Foo[T])) = xx match { ^ -6 errors found +error: No warnings can be incurred under -Xfatal-warnings. +6 warnings found +one error found diff --git a/test/files/neg/gadts1.check b/test/files/neg/gadts1.check index 44d2b114d6..a61231a27a 100644 --- a/test/files/neg/gadts1.check +++ b/test/files/neg/gadts1.check @@ -1,8 +1,3 @@ -gadts1.scala:15: error: type mismatch; - found : Test.Double - required: a - case NumTerm(n) => c.x = Double(1.0) - ^ gadts1.scala:20: error: class Cell of type Test.Cell does not take type parameters. case Cell[a](x: Int) => c.x = 5 ^ @@ -11,4 +6,4 @@ gadts1.scala:20: error: type mismatch; required: a case Cell[a](x: Int) => c.x = 5 ^ -three errors found +two errors found diff --git a/test/files/neg/import-precedence.check b/test/files/neg/import-precedence.check new file mode 100644 index 0000000000..5f99611052 --- /dev/null +++ b/test/files/neg/import-precedence.check @@ -0,0 +1,19 @@ +import-precedence.scala:18: error: reference to X is ambiguous; +it is imported twice in the same scope by +import uniq1.uniq2._ +and import uniq1.X + object Y { def f = X } + ^ +import-precedence.scala:61: error: reference to X is ambiguous; +it is imported twice in the same scope by +import uniq1.uniq2._ +and import uniq1._ + object Y { def f = X } + ^ +import-precedence.scala:67: error: reference to X is ambiguous; +it is imported twice in the same scope by +import uniq1.uniq2.X +and import uniq1.X + object Y { def f = X } + ^ +three errors found diff --git a/test/files/neg/import-precedence.scala b/test/files/neg/import-precedence.scala new file mode 100644 index 0000000000..0401635e32 --- /dev/null +++ b/test/files/neg/import-precedence.scala @@ -0,0 +1,68 @@ +package uniq1 { + object X + package uniq2 { + object X + package uniq3 { + object X + package uniq4 { + object X + } + } + } +} + +package p1 { + import uniq1.X + package p2 { + import uniq1.uniq2._ + object Y { def f = X } + } +} + +package p2 { + import uniq1.uniq2._ + package p2 { + import uniq1.X + object Y { def f = X } + } +} + +package p3 { + import uniq1.X + import uniq1.uniq2._ + object Y { def f = X } +} + +package p4 { + import uniq1.uniq2._ + import uniq1.X + object Y { def f = X } +} + +package p5 { + import uniq1.X + package p6 { + import uniq1.uniq2.X + object Y { def f = X } + } +} + +package p6 { + import uniq1._ + package p5 { + import uniq1.uniq2._ + object Y { def f = X } + } +} + +package p7 { + import uniq1._ + import uniq1.uniq2._ + object Y { def f = X } +} + +package p8 { + import uniq1.X + import uniq1.uniq2.X + object Y { def f = X } +} diff --git a/test/files/neg/lubs.check b/test/files/neg/lubs.check index 77ab20102c..affbd4983c 100644 --- a/test/files/neg/lubs.check +++ b/test/files/neg/lubs.check @@ -1,5 +1,10 @@ +lubs.scala:10: error: type mismatch; + found : test1.A[test1.A[Object]] + required: test1.A[test1.A[test1.A[Any]]] + val x3: A[A[A[Any]]] = f + ^ lubs.scala:11: error: type mismatch; - found : test1.A[test1.A[test1.A[Any]]] + found : test1.A[test1.A[Object]] required: test1.A[test1.A[test1.A[test1.A[Any]]]] val x4: A[A[A[A[Any]]]] = f ^ @@ -13,4 +18,4 @@ lubs.scala:25: error: type mismatch; required: test2.A{type T >: Null <: test2.A{type T >: Null <: test2.A{type T >: Null <: test2.A}}} val x4: A { type T >: Null <: A { type T >: Null <: A { type T >: Null <: A } } } = f ^ -three errors found +four errors found diff --git a/test/files/neg/macro-deprecate-idents.check b/test/files/neg/macro-deprecate-idents.check index 22b667c390..c653eabaef 100644 --- a/test/files/neg/macro-deprecate-idents.check +++ b/test/files/neg/macro-deprecate-idents.check @@ -1,52 +1,54 @@ -macro-deprecate-idents.scala:2: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:2: warning: macro is now a reserved word; usage as an identifier is deprecated val macro = ??? ^ -macro-deprecate-idents.scala:6: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:6: warning: macro is now a reserved word; usage as an identifier is deprecated var macro = ??? ^ -macro-deprecate-idents.scala:10: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:10: warning: macro is now a reserved word; usage as an identifier is deprecated type macro = Int ^ -macro-deprecate-idents.scala:14: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:14: warning: macro is now a reserved word; usage as an identifier is deprecated class macro ^ -macro-deprecate-idents.scala:18: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:18: warning: macro is now a reserved word; usage as an identifier is deprecated class macro ^ -macro-deprecate-idents.scala:22: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:22: warning: macro is now a reserved word; usage as an identifier is deprecated object macro ^ -macro-deprecate-idents.scala:26: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:26: warning: macro is now a reserved word; usage as an identifier is deprecated object macro ^ -macro-deprecate-idents.scala:30: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:30: warning: macro is now a reserved word; usage as an identifier is deprecated trait macro ^ -macro-deprecate-idents.scala:34: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:34: warning: macro is now a reserved word; usage as an identifier is deprecated trait macro ^ -macro-deprecate-idents.scala:37: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:37: warning: macro is now a reserved word; usage as an identifier is deprecated package macro { ^ -macro-deprecate-idents.scala:38: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:38: warning: macro is now a reserved word; usage as an identifier is deprecated package macro.bar { ^ -macro-deprecate-idents.scala:43: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:43: warning: macro is now a reserved word; usage as an identifier is deprecated package macro.foo { ^ -macro-deprecate-idents.scala:48: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:48: warning: macro is now a reserved word; usage as an identifier is deprecated val Some(macro) = Some(42) ^ -macro-deprecate-idents.scala:49: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:49: warning: macro is now a reserved word; usage as an identifier is deprecated macro match { ^ -macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:50: warning: macro is now a reserved word; usage as an identifier is deprecated case macro => println(macro) ^ -macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:50: warning: macro is now a reserved word; usage as an identifier is deprecated case macro => println(macro) ^ -macro-deprecate-idents.scala:55: error: macro is now a reserved word; usage as an identifier is deprecated +macro-deprecate-idents.scala:55: warning: macro is now a reserved word; usage as an identifier is deprecated def macro = 2 ^ -17 errors found +error: No warnings can be incurred under -Xfatal-warnings. +17 warnings found +one error found diff --git a/test/files/neg/main1.check b/test/files/neg/main1.check index 1a7a13e1e9..b745105818 100644 --- a/test/files/neg/main1.check +++ b/test/files/neg/main1.check @@ -1,26 +1,28 @@ -main1.scala:3: error: Foo has a main method with parameter type Array[String], but foo1.Foo will not be a runnable program. +main1.scala:3: warning: Foo has a main method with parameter type Array[String], but foo1.Foo will not be a runnable program. Reason: companion is a trait, which means no static forwarder can be generated. object Foo { // companion is trait ^ -main1.scala:10: error: Foo has a main method with parameter type Array[String], but foo2.Foo will not be a runnable program. +main1.scala:10: warning: Foo has a main method with parameter type Array[String], but foo2.Foo will not be a runnable program. Reason: companion contains its own main method, which means no static forwarder can be generated. object Foo { // companion has its own main ^ -main1.scala:22: error: Foo has a main method with parameter type Array[String], but foo3.Foo will not be a runnable program. +main1.scala:22: warning: Foo has a main method with parameter type Array[String], but foo3.Foo will not be a runnable program. Reason: companion contains its own main method (implementation restriction: no main is allowed, regardless of signature), which means no static forwarder can be generated. object Foo { // Companion contains main, but not an interfering main. ^ -main1.scala:31: error: Foo has a main method with parameter type Array[String], but foo4.Foo will not be a runnable program. +main1.scala:31: warning: Foo has a main method with parameter type Array[String], but foo4.Foo will not be a runnable program. Reason: companion contains its own main method, which means no static forwarder can be generated. object Foo extends Foo { // Inherits main from the class ^ -main1.scala:39: error: Foo has a main method with parameter type Array[String], but foo5.Foo will not be a runnable program. +main1.scala:39: warning: Foo has a main method with parameter type Array[String], but foo5.Foo will not be a runnable program. Reason: companion contains its own main method, which means no static forwarder can be generated. object Foo extends Foo { // Overrides main from the class ^ -5 errors found +error: No warnings can be incurred under -Xfatal-warnings. +5 warnings found +one error found diff --git a/test/files/neg/migration28.check b/test/files/neg/migration28.check index d7dfacf3db..afb4db62e2 100644 --- a/test/files/neg/migration28.check +++ b/test/files/neg/migration28.check @@ -1,5 +1,7 @@ -migration28.scala:4: error: method scanRight in trait TraversableLike has changed semantics in version 2.9.0: +migration28.scala:4: warning: method scanRight in trait TraversableLike has changed semantics in version 2.9.0: The behavior of `scanRight` has changed. The previous behavior can be reproduced with scanRight.reverse. List(1,2,3,4,5).scanRight(0)(_+_) ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/names-defaults-neg-warn.check b/test/files/neg/names-defaults-neg-warn.check index e1085acf76..0f4edef84e 100644 --- a/test/files/neg/names-defaults-neg-warn.check +++ b/test/files/neg/names-defaults-neg-warn.check @@ -1,7 +1,9 @@ -names-defaults-neg-warn.scala:11: error: the parameter name s has been deprecated. Use x instead. +names-defaults-neg-warn.scala:11: warning: the parameter name s has been deprecated. Use x instead. deprNam2.f(s = "dlfkj") ^ -names-defaults-neg-warn.scala:12: error: the parameter name x has been deprecated. Use s instead. +names-defaults-neg-warn.scala:12: warning: the parameter name x has been deprecated. Use s instead. deprNam2.g(x = "dlkjf") ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/newpat_unreachable.check b/test/files/neg/newpat_unreachable.check index 08453cac19..a928e3853a 100644 --- a/test/files/neg/newpat_unreachable.check +++ b/test/files/neg/newpat_unreachable.check @@ -1,27 +1,29 @@ -newpat_unreachable.scala:6: error: patterns after a variable pattern cannot match (SLS 8.1.1) +newpat_unreachable.scala:6: warning: patterns after a variable pattern cannot match (SLS 8.1.1) If you intended to match against parameter b of method contrivedExample, you must use backticks, like: case `b` => case b => println("matched b") ^ -newpat_unreachable.scala:7: error: unreachable code due to variable pattern 'b' on line 6 +newpat_unreachable.scala:7: warning: unreachable code due to variable pattern 'b' on line 6 If you intended to match against parameter c of method contrivedExample, you must use backticks, like: case `c` => case c => println("matched c") ^ -newpat_unreachable.scala:8: error: unreachable code due to variable pattern 'b' on line 6 +newpat_unreachable.scala:8: warning: unreachable code due to variable pattern 'b' on line 6 If you intended to match against value d in class A, you must use backticks, like: case `d` => case d => println("matched d") ^ -newpat_unreachable.scala:9: error: unreachable code due to variable pattern 'b' on line 6 +newpat_unreachable.scala:9: warning: unreachable code due to variable pattern 'b' on line 6 case _ => println("matched neither") ^ -newpat_unreachable.scala:22: error: patterns after a variable pattern cannot match (SLS 8.1.1) +newpat_unreachable.scala:22: warning: patterns after a variable pattern cannot match (SLS 8.1.1) If you intended to match against parameter b of method g, you must use backticks, like: case `b` => case b => 1 ^ -newpat_unreachable.scala:23: error: unreachable code due to variable pattern 'b' on line 22 +newpat_unreachable.scala:23: warning: unreachable code due to variable pattern 'b' on line 22 If you intended to match against parameter c of method h, you must use backticks, like: case `c` => case c => 2 ^ -newpat_unreachable.scala:24: error: unreachable code due to variable pattern 'b' on line 22 +newpat_unreachable.scala:24: warning: unreachable code due to variable pattern 'b' on line 22 case _ => 3 ^ -7 errors found +error: No warnings can be incurred under -Xfatal-warnings. +7 warnings found +one error found diff --git a/test/files/neg/nonlocal-warning.check b/test/files/neg/nonlocal-warning.check new file mode 100644 index 0000000000..67b3b10095 --- /dev/null +++ b/test/files/neg/nonlocal-warning.check @@ -0,0 +1,10 @@ +nonlocal-warning.scala:4: warning: This catches all Throwables, which often has undesirable consequences. +If intentional, use `case x : Throwable` to clear this warning. + catch { case x => 11 } + ^ +nonlocal-warning.scala:2: warning: catch block may intercept non-local return from method foo + def foo(l: List[Int]): Int = { + ^ +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/pending/pos/t4649.flags b/test/files/neg/nonlocal-warning.flags index e8fb65d50c..e8fb65d50c 100644 --- a/test/pending/pos/t4649.flags +++ b/test/files/neg/nonlocal-warning.flags diff --git a/test/files/neg/nonlocal-warning.scala b/test/files/neg/nonlocal-warning.scala new file mode 100644 index 0000000000..f908a86302 --- /dev/null +++ b/test/files/neg/nonlocal-warning.scala @@ -0,0 +1,18 @@ +class Foo { + def foo(l: List[Int]): Int = { + try l foreach { _ => return 5 } + catch { case x => 11 } + 22 + } + + val pf: PartialFunction[Throwable, Unit] = { + case x if false => () + } + + def bar(l: List[Int]): Int = { + try l foreach { _ => return 5 } + catch pf + finally println() + 22 + } +} diff --git a/test/files/neg/nullary-override.check b/test/files/neg/nullary-override.check index 6b2ded2d4a..f032f4a6c2 100644 --- a/test/files/neg/nullary-override.check +++ b/test/files/neg/nullary-override.check @@ -1,4 +1,6 @@ -nullary-override.scala:2: error: non-nullary method overrides nullary method +nullary-override.scala:2: warning: non-nullary method overrides nullary method class B extends A { override def x(): Int = 4 } ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/overloaded-implicit.check b/test/files/neg/overloaded-implicit.check index bdbe6a89d5..ca0870705d 100644 --- a/test/files/neg/overloaded-implicit.check +++ b/test/files/neg/overloaded-implicit.check @@ -1,7 +1,9 @@ -overloaded-implicit.scala:2: error: parameterized overloaded implicit methods are not visible as view bounds +overloaded-implicit.scala:2: warning: parameterized overloaded implicit methods are not visible as view bounds implicit def imp1[T](x: List[T]): Map[T, T] = Map() ^ -overloaded-implicit.scala:3: error: parameterized overloaded implicit methods are not visible as view bounds +overloaded-implicit.scala:3: warning: parameterized overloaded implicit methods are not visible as view bounds implicit def imp1[T](x: Set[T]): Map[T, T] = Map() ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/overloaded-implicit.flags b/test/files/neg/overloaded-implicit.flags index 7949c2afa2..9c1e74e4ef 100644 --- a/test/files/neg/overloaded-implicit.flags +++ b/test/files/neg/overloaded-implicit.flags @@ -1 +1 @@ --Xlint -Xfatal-warnings +-Xlint -Xfatal-warnings -Xdev diff --git a/test/files/neg/package-ob-case.check b/test/files/neg/package-ob-case.check index e6b2f858ef..063a120db1 100644 --- a/test/files/neg/package-ob-case.check +++ b/test/files/neg/package-ob-case.check @@ -1,5 +1,7 @@ -package-ob-case.scala:3: error: it is not recommended to define classes/objects inside of package objects. +package-ob-case.scala:3: warning: it is not recommended to define classes/objects inside of package objects. If possible, define class X in package foo instead. case class X(z: Int) { } ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/patmat-type-check.check b/test/files/neg/patmat-type-check.check index 721217c314..fedac3b746 100644 --- a/test/files/neg/patmat-type-check.check +++ b/test/files/neg/patmat-type-check.check @@ -1,12 +1,27 @@ patmat-type-check.scala:11: warning: fruitless type test: a value of type Test.Bop4[T] cannot also be a Seq[A] def s3[T](x: Bop4[T]) = x match { case Seq('b', 'o', 'b') => true } ^ +patmat-type-check.scala:11: error: pattern type is incompatible with expected type; + found : Seq[A] + required: Test.Bop4[T] + def s3[T](x: Bop4[T]) = x match { case Seq('b', 'o', 'b') => true } + ^ patmat-type-check.scala:15: warning: fruitless type test: a value of type Test.Bop5[_$1,T1,T2] cannot also be a Seq[A] def s4[T1, T2](x: Bop5[_, T1, T2]) = x match { case Seq('b', 'o', 'b') => true } ^ +patmat-type-check.scala:15: error: pattern type is incompatible with expected type; + found : Seq[A] + required: Test.Bop5[_$1,T1,T2] where type _$1 + def s4[T1, T2](x: Bop5[_, T1, T2]) = x match { case Seq('b', 'o', 'b') => true } + ^ patmat-type-check.scala:19: warning: fruitless type test: a value of type Test.Bop3[T] cannot also be a Seq[A] def f4[T](x: Bop3[T]) = x match { case Seq('b', 'o', 'b') => true } ^ +patmat-type-check.scala:19: error: pattern type is incompatible with expected type; + found : Seq[A] + required: Test.Bop3[T] + def f4[T](x: Bop3[T]) = x match { case Seq('b', 'o', 'b') => true } + ^ patmat-type-check.scala:22: error: scrutinee is incompatible with pattern type; found : Seq[A] required: String @@ -28,4 +43,4 @@ patmat-type-check.scala:30: error: scrutinee is incompatible with pattern type; def f4[T](x: Bop3[Char]) = x match { case Seq('b', 'o', 'b') => true } // fail ^ three warnings found -four errors found +7 errors found diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check index 4556e6622f..6069dfdaab 100644 --- a/test/files/neg/patmatexhaust.check +++ b/test/files/neg/patmatexhaust.check @@ -1,40 +1,42 @@ -patmatexhaust.scala:7: error: match may not be exhaustive. +patmatexhaust.scala:7: warning: match may not be exhaustive. It would fail on the following input: Baz def ma1(x:Foo) = x match { ^ -patmatexhaust.scala:11: error: match may not be exhaustive. +patmatexhaust.scala:11: warning: match may not be exhaustive. It would fail on the following input: Bar(_) def ma2(x:Foo) = x match { ^ -patmatexhaust.scala:23: error: match may not be exhaustive. +patmatexhaust.scala:23: warning: match may not be exhaustive. It would fail on the following inputs: (Kult(_), Kult(_)), (Qult(), Qult()) def ma3(x:Mult) = (x,x) match { // not exhaustive ^ -patmatexhaust.scala:49: error: match may not be exhaustive. +patmatexhaust.scala:49: warning: match may not be exhaustive. It would fail on the following inputs: Gp(), Gu def ma4(x:Deep) = x match { // missing cases: Gu, Gp ^ -patmatexhaust.scala:55: error: unreachable code +patmatexhaust.scala:55: warning: unreachable code case _ if 1 == 0 => ^ -patmatexhaust.scala:53: error: match may not be exhaustive. +patmatexhaust.scala:53: warning: match may not be exhaustive. It would fail on the following input: Gp() def ma5(x:Deep) = x match { ^ -patmatexhaust.scala:75: error: match may not be exhaustive. +patmatexhaust.scala:75: warning: match may not be exhaustive. It would fail on the following input: B() def ma9(x: B) = x match { ^ -patmatexhaust.scala:100: error: match may not be exhaustive. +patmatexhaust.scala:100: warning: match may not be exhaustive. It would fail on the following input: C1() def ma10(x: C) = x match { // not exhaustive: C1 is not sealed. ^ -patmatexhaust.scala:114: error: match may not be exhaustive. +patmatexhaust.scala:114: warning: match may not be exhaustive. It would fail on the following inputs: D1, D2() def ma10(x: C) = x match { // not exhaustive: C1 has subclasses. ^ -patmatexhaust.scala:126: error: match may not be exhaustive. +patmatexhaust.scala:126: warning: match may not be exhaustive. It would fail on the following input: C1() def ma10(x: C) = x match { // not exhaustive: C1 is not abstract. ^ -10 errors found +error: No warnings can be incurred under -Xfatal-warnings. +10 warnings found +one error found diff --git a/test/files/neg/permanent-blindness.check b/test/files/neg/permanent-blindness.check index 18b4543707..cdde201ef6 100644 --- a/test/files/neg/permanent-blindness.check +++ b/test/files/neg/permanent-blindness.check @@ -1,10 +1,12 @@ -permanent-blindness.scala:10: error: imported `Bippy' is permanently hidden by definition of class Bippy in package bar +permanent-blindness.scala:10: warning: imported `Bippy' is permanently hidden by definition of class Bippy in package bar import foo.{ Bippy, Bop, Dingus } ^ -permanent-blindness.scala:10: error: imported `Bop' is permanently hidden by definition of object Bop in package bar +permanent-blindness.scala:10: warning: imported `Bop' is permanently hidden by definition of object Bop in package bar import foo.{ Bippy, Bop, Dingus } ^ -permanent-blindness.scala:10: error: imported `Dingus' is permanently hidden by definition of object Dingus in package bar +permanent-blindness.scala:10: warning: imported `Dingus' is permanently hidden by definition of object Dingus in package bar import foo.{ Bippy, Bop, Dingus } ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/sealed-final-neg.check b/test/files/neg/sealed-final-neg.check new file mode 100644 index 0000000000..500d23f49a --- /dev/null +++ b/test/files/neg/sealed-final-neg.check @@ -0,0 +1,4 @@ +sealed-final-neg.scala:41: error: expected class or object definition +"Due to SI-6142 this emits no warnings, so we'll just break it until that's fixed." +^ +one error found diff --git a/test/files/neg/sealed-final-neg.flags b/test/files/neg/sealed-final-neg.flags new file mode 100644 index 0000000000..cfabf7a5b4 --- /dev/null +++ b/test/files/neg/sealed-final-neg.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Yinline-warnings -optimise
\ No newline at end of file diff --git a/test/files/neg/sealed-final-neg.scala b/test/files/neg/sealed-final-neg.scala new file mode 100644 index 0000000000..bc25330e13 --- /dev/null +++ b/test/files/neg/sealed-final-neg.scala @@ -0,0 +1,41 @@ +package neg1 { + sealed abstract class Foo { + @inline def bar(x: Int) = x + 1 + } + object Foo { + def mkFoo(): Foo = new Baz2 + } + + object Baz1 extends Foo + final class Baz2 extends Foo + final class Baz3 extends Foo { + override def bar(x: Int) = x - 1 + } + + object Test { + // bar can't be inlined - it is overridden in Baz3 + def f = Foo.mkFoo() bar 10 + } +} + +package neg2 { + sealed abstract class Foo { + @inline def bar(x: Int) = x + 1 + } + object Foo { + def mkFoo(): Foo = new Baz2 + } + + object Baz1 extends Foo + final class Baz2 extends Foo + class Baz3 extends Foo { + override def bar(x: Int) = x - 1 + } + + object Test { + // bar can't be inlined - Baz3 is not final + def f = Foo.mkFoo() bar 10 + } +} + +"Due to SI-6142 this emits no warnings, so we'll just break it until that's fixed." diff --git a/test/files/neg/sealed-java-enums.check b/test/files/neg/sealed-java-enums.check index 20d00c8e91..a3c39ec5cd 100644 --- a/test/files/neg/sealed-java-enums.check +++ b/test/files/neg/sealed-java-enums.check @@ -1,5 +1,7 @@ -sealed-java-enums.scala:5: error: match may not be exhaustive. +sealed-java-enums.scala:5: warning: match may not be exhaustive. It would fail on the following inputs: BLOCKED, TERMINATED, TIMED_WAITING def f(state: State) = state match { ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/stmt-expr-discard.check b/test/files/neg/stmt-expr-discard.check index 2d6420a61d..1207e6da50 100644 --- a/test/files/neg/stmt-expr-discard.check +++ b/test/files/neg/stmt-expr-discard.check @@ -1,7 +1,9 @@ -stmt-expr-discard.scala:3: error: a pure expression does nothing in statement position; you may be omitting necessary parentheses +stmt-expr-discard.scala:3: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 2 ^ -stmt-expr-discard.scala:4: error: a pure expression does nothing in statement position; you may be omitting necessary parentheses +stmt-expr-discard.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 4 ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/switch.check b/test/files/neg/switch.check index e4730b6459..f968d3a448 100644 --- a/test/files/neg/switch.check +++ b/test/files/neg/switch.check @@ -1,7 +1,9 @@ -switch.scala:38: error: could not emit switch for @switch annotated match +switch.scala:38: warning: could not emit switch for @switch annotated match def fail2(c: Char) = (c: @switch @unchecked) match { ^ -switch.scala:45: error: could not emit switch for @switch annotated match +switch.scala:45: warning: could not emit switch for @switch annotated match def fail3(c: Char) = (c: @unchecked @switch) match { ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t1224.check b/test/files/neg/t1224.check index fb61275911..ab8a6f1130 100644 --- a/test/files/neg/t1224.check +++ b/test/files/neg/t1224.check @@ -1,4 +1,4 @@ -t1224.scala:4: error: illegal cyclic reference involving type T +t1224.scala:4: error: lower bound C[A.this.T] does not conform to upper bound C[C[A.this.T]] type T >: C[T] <: C[C[T]] ^ one error found diff --git a/test/files/neg/t1224.flags b/test/files/neg/t1224.flags new file mode 100644 index 0000000000..ca20f55172 --- /dev/null +++ b/test/files/neg/t1224.flags @@ -0,0 +1 @@ +-Ybreak-cycles diff --git a/test/files/neg/t2442.check b/test/files/neg/t2442.check index 714816fd62..9ff0b44661 100644 --- a/test/files/neg/t2442.check +++ b/test/files/neg/t2442.check @@ -1,9 +1,11 @@ -t2442.scala:4: error: match may not be exhaustive. +t2442.scala:4: warning: match may not be exhaustive. It would fail on the following input: THREE def f(e: MyEnum) = e match { ^ -t2442.scala:11: error: match may not be exhaustive. +t2442.scala:11: warning: match may not be exhaustive. It would fail on the following input: BLUE def g(e: MySecondEnum) = e match { ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t2796.check b/test/files/neg/t2796.check index aeb18497ed..4456a7fc19 100644 --- a/test/files/neg/t2796.check +++ b/test/files/neg/t2796.check @@ -1,4 +1,6 @@ -t2796.scala:7: error: Implementation restriction: early definitions in traits are not initialized before the super class is initialized. +t2796.scala:7: warning: Implementation restriction: early definitions in traits are not initialized before the super class is initialized. val abstractVal = "T1.abstractVal" // warn ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t2968.check b/test/files/neg/t2968.check new file mode 100644 index 0000000000..5d2387f98c --- /dev/null +++ b/test/files/neg/t2968.check @@ -0,0 +1,10 @@ +t2968.scala:8: error: Missing closing brace `}' assumed here +} // missing brace +^ +t2968.scala:17: error: Missing closing brace `}' assumed here +} // missing brace +^ +t2968.scala:26: error: Missing closing brace `}' assumed here +} // missing brace +^ +three errors found diff --git a/test/files/neg/t2968.scala b/test/files/neg/t2968.scala new file mode 100644 index 0000000000..41c3a798a5 --- /dev/null +++ b/test/files/neg/t2968.scala @@ -0,0 +1,26 @@ +object t1 { + case object Const { + } + + class Var + { + +} // missing brace + +object t2 { + case class Const() { + } + + class Var + { + +} // missing brace + +object t3 { + final case class Const() { + } + + class Var + { + +} // missing brace diff --git a/test/files/neg/t2968b.check b/test/files/neg/t2968b.check new file mode 100644 index 0000000000..36d25a2d12 --- /dev/null +++ b/test/files/neg/t2968b.check @@ -0,0 +1,4 @@ +t2968b.scala:7: error: '}' expected but eof found. +// missing brace + ^ +one error found diff --git a/test/files/neg/t2968b.scala b/test/files/neg/t2968b.scala new file mode 100644 index 0000000000..422b618aba --- /dev/null +++ b/test/files/neg/t2968b.scala @@ -0,0 +1,7 @@ +case class Const() +{ +} + +class Var +{ +// missing brace diff --git a/test/files/neg/t3098.check b/test/files/neg/t3098.check index 85829747b9..5343b128f0 100644 --- a/test/files/neg/t3098.check +++ b/test/files/neg/t3098.check @@ -1,5 +1,7 @@ -b.scala:3: error: match may not be exhaustive. +b.scala:3: warning: match may not be exhaustive. It would fail on the following input: (_ : C) def f = (null: T) match { ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t3160ambiguous.check b/test/files/neg/t3160ambiguous.check new file mode 100644 index 0000000000..e80d9a5461 --- /dev/null +++ b/test/files/neg/t3160ambiguous.check @@ -0,0 +1,7 @@ +t3160ambiguous.scala:8: error: reference to Node is ambiguous; +it is imported twice in the same scope by +import scala.xml._ +and import Bippy._ + def f(x: Node): String = ??? // ambiguous, because Bippy.Node is accessible + ^ +one error found diff --git a/test/files/neg/t3160ambiguous.scala b/test/files/neg/t3160ambiguous.scala new file mode 100644 index 0000000000..cb9759b79c --- /dev/null +++ b/test/files/neg/t3160ambiguous.scala @@ -0,0 +1,15 @@ +object Bippy { + private class Node +} +class Bippy { + import Bippy._ + import scala.xml._ + + def f(x: Node): String = ??? // ambiguous, because Bippy.Node is accessible +} +class Other { + import Bippy._ + import scala.xml._ + + def f(x: Node): String = ??? // unambiguous, because Bippy.Node is inaccessible +} diff --git a/test/files/neg/t3224.check b/test/files/neg/t3224.check index 29304c567a..69b02c8862 100644 --- a/test/files/neg/t3224.check +++ b/test/files/neg/t3224.check @@ -1,6 +1,26 @@ -t3224.scala:29: error: polymorphic expression cannot be instantiated to expected type; +t3224.scala:30: error: polymorphic expression cannot be instantiated to expected type; found : [T]Array[T] required: List[?] - println(Texts textL Array()); println(Texts textL Array(1)); println(Texts textL Array(1, 1)) - ^ -one error found + println(Texts textL Array()) + ^ +t3224.scala:34: error: type mismatch; + found : List[Nothing] + required: Array[?] + println(Texts textA List()) + ^ +t3224.scala:35: error: type mismatch; + found : List[Int] + required: Array[?] + println(Texts textA List(1)) + ^ +t3224.scala:36: error: type mismatch; + found : List[Int] + required: Array[?] + println(Texts textA List(1, 1)); + ^ +t3224.scala:48: error: polymorphic expression cannot be instantiated to expected type; + found : [T]Array[T] + required: List[?] + assert(size(Array()) == 0) + ^ +5 errors found diff --git a/test/files/neg/t3224.scala b/test/files/neg/t3224.scala index 774de3335a..b7af8a67b5 100755 --- a/test/files/neg/t3224.scala +++ b/test/files/neg/t3224.scala @@ -1,30 +1,50 @@ object Texts{ - def textL[T](list: List[T]) = { - list match{ - case List() => "Empty" - case List(_) => "One" + def textL[T](list: List[T]) = { + list match{ + case List() => "Empty" + case List(_) => "One" case List(_*) => "Many" } } - def textA[T](array: Array[T]) = { - array match{ - case Array() => "Empty" - case Array(_) => "One" + def textA[T](array: Array[T]) = { + array match{ + case Array() => "Empty" + case Array(_) => "One" case Array(_*) => "Many" } } } object Test extends App { + { + implicit def array2list[T](array: Array[T]) = { + println(array.toList.size) + array.toList + } + + println(Texts textL List()) + println(Texts textL List(1)) + println(Texts textL List(1, 1)); + + println(Texts textL Array()) + println(Texts textL Array(1)) + println(Texts textL Array(1, 1)) - implicit def array2list[T](array: Array[T]) = { - println(array.toList.size) - array.toList + println(Texts textA List()) + println(Texts textA List(1)) + println(Texts textA List(1, 1)); + + println(Texts textA Array()) + println(Texts textA Array(1)) + println(Texts textA Array(1, 1)) } - - println(Texts textL List()); println(Texts textL List(1)); println(Texts textL List(1, 1)); + { + implicit def array2list[T](array: Array[T]) = array.toList + def size[T](list: List[T]) = list.size - println(Texts textL Array()); println(Texts textL Array(1)); println(Texts textL Array(1, 1)) + assert(size(array2list(Array())) == 0) + assert(size(Array()) == 0) + } } diff --git a/test/files/neg/t3234.check b/test/files/neg/t3234.check index 477b021e5e..8f0d624ed9 100644 --- a/test/files/neg/t3234.check +++ b/test/files/neg/t3234.check @@ -1,2 +1,6 @@ -error: there were 1 inliner warnings; re-run with -Yinline-warnings for details +t3234.scala:17: warning: At the end of the day, could not inline @inline-marked method foo3 + println(foo(42) + foo2(11) + foo3(2)) + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t3234.flags b/test/files/neg/t3234.flags index c9cefdc4b9..cc3d9fb6f0 100644 --- a/test/files/neg/t3234.flags +++ b/test/files/neg/t3234.flags @@ -1 +1 @@ --Yinline -Xfatal-warnings
\ No newline at end of file +-Yinline -Yinline-warnings -Xfatal-warnings diff --git a/test/files/neg/t3683a.check b/test/files/neg/t3683a.check index 3de3ad784e..6386265ebc 100644 --- a/test/files/neg/t3683a.check +++ b/test/files/neg/t3683a.check @@ -1,5 +1,7 @@ -t3683a.scala:14: error: match may not be exhaustive. +t3683a.scala:14: warning: match may not be exhaustive. It would fail on the following input: XX() w match { ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t4302.check b/test/files/neg/t4302.check index 450d28bbc5..ea48729276 100644 --- a/test/files/neg/t4302.check +++ b/test/files/neg/t4302.check @@ -1,4 +1,6 @@ -t4302.scala:2: error: abstract type T is unchecked since it is eliminated by erasure +t4302.scala:2: warning: abstract type T is unchecked since it is eliminated by erasure def hasMatch[T](x: AnyRef) = x.isInstanceOf[T] ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t4440.check b/test/files/neg/t4440.check index 2861dc3040..10e7188e32 100644 --- a/test/files/neg/t4440.check +++ b/test/files/neg/t4440.check @@ -1,13 +1,15 @@ -t4440.scala:12: error: The outer reference in this type test cannot be checked at run time. +t4440.scala:12: warning: The outer reference in this type test cannot be checked at run time. case _: b.Inner => println("b") ^ -t4440.scala:13: error: The outer reference in this type test cannot be checked at run time. +t4440.scala:13: warning: The outer reference in this type test cannot be checked at run time. case _: a.Inner => println("a") // this is the case we want ^ -t4440.scala:16: error: The outer reference in this type test cannot be checked at run time. +t4440.scala:16: warning: The outer reference in this type test cannot be checked at run time. case _: a.Inner => println("a") ^ -t4440.scala:17: error: The outer reference in this type test cannot be checked at run time. +t4440.scala:17: warning: The outer reference in this type test cannot be checked at run time. case _: b.Inner => println("b") // this is the case we want ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/t4537.check b/test/files/neg/t4537.check deleted file mode 100644 index 931bcd0405..0000000000 --- a/test/files/neg/t4537.check +++ /dev/null @@ -1,4 +0,0 @@ -c.scala:7: error: object Settings in package a cannot be accessed in package a - println(Settings.Y) - ^ -one error found diff --git a/test/files/neg/t4537/c.scala b/test/files/neg/t4537/c.scala deleted file mode 100644 index 379599112d..0000000000 --- a/test/files/neg/t4537/c.scala +++ /dev/null @@ -1,8 +0,0 @@ -package b -package c - -import a._ - -object Test { - println(Settings.Y) -}
\ No newline at end of file diff --git a/test/files/neg/t4691_exhaust_extractor.check b/test/files/neg/t4691_exhaust_extractor.check index cd12e56f86..6396944145 100644 --- a/test/files/neg/t4691_exhaust_extractor.check +++ b/test/files/neg/t4691_exhaust_extractor.check @@ -1,13 +1,15 @@ -t4691_exhaust_extractor.scala:17: error: match may not be exhaustive. +t4691_exhaust_extractor.scala:17: warning: match may not be exhaustive. It would fail on the following input: Bar3() def f1(x: Foo) = x match { ^ -t4691_exhaust_extractor.scala:23: error: match may not be exhaustive. +t4691_exhaust_extractor.scala:23: warning: match may not be exhaustive. It would fail on the following input: Bar3() def f2(x: Foo) = x match { ^ -t4691_exhaust_extractor.scala:29: error: match may not be exhaustive. +t4691_exhaust_extractor.scala:29: warning: match may not be exhaustive. It would fail on the following input: Bar3() def f3(x: Foo) = x match { ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/t4749.check b/test/files/neg/t4749.check index 93ad3935fa..34eed6e433 100644 --- a/test/files/neg/t4749.check +++ b/test/files/neg/t4749.check @@ -1,28 +1,30 @@ -t4749.scala:2: error: Fail1 has a main method with parameter type Array[String], but bippy.Fail1 will not be a runnable program. +t4749.scala:2: warning: Fail1 has a main method with parameter type Array[String], but bippy.Fail1 will not be a runnable program. Reason: main method must have exact signature (Array[String])Unit object Fail1 { ^ -t4749.scala:6: error: Fail2 has a main method with parameter type Array[String], but bippy.Fail2 will not be a runnable program. +t4749.scala:6: warning: Fail2 has a main method with parameter type Array[String], but bippy.Fail2 will not be a runnable program. Reason: main methods cannot be generic. object Fail2 { ^ -t4749.scala:13: error: Fail3 has a main method with parameter type Array[String], but bippy.Fail3 will not be a runnable program. +t4749.scala:13: warning: Fail3 has a main method with parameter type Array[String], but bippy.Fail3 will not be a runnable program. Reason: main methods cannot refer to type parameters or abstract types. object Fail3 extends Bippy[Unit] { } ^ -t4749.scala:16: error: Fail4 has a main method with parameter type Array[String], but bippy.Fail4 will not be a runnable program. +t4749.scala:16: warning: Fail4 has a main method with parameter type Array[String], but bippy.Fail4 will not be a runnable program. Reason: companion is a trait, which means no static forwarder can be generated. object Fail4 { ^ -t4749.scala:21: error: Fail5 has a main method with parameter type Array[String], but bippy.Fail5 will not be a runnable program. +t4749.scala:21: warning: Fail5 has a main method with parameter type Array[String], but bippy.Fail5 will not be a runnable program. Reason: companion contains its own main method, which means no static forwarder can be generated. object Fail5 extends Fail5 { } ^ -t4749.scala:26: error: Fail6 has a main method with parameter type Array[String], but bippy.Fail6 will not be a runnable program. +t4749.scala:26: warning: Fail6 has a main method with parameter type Array[String], but bippy.Fail6 will not be a runnable program. Reason: companion contains its own main method (implementation restriction: no main is allowed, regardless of signature), which means no static forwarder can be generated. object Fail6 { ^ -6 errors found +error: No warnings can be incurred under -Xfatal-warnings. +6 warnings found +one error found diff --git a/test/files/neg/t4762.check b/test/files/neg/t4762.check index 5e67f2022a..a0525f6226 100644 --- a/test/files/neg/t4762.check +++ b/test/files/neg/t4762.check @@ -1,7 +1,9 @@ -t4762.scala:15: error: private[this] value x in class B shadows mutable x inherited from class A. Changes to x will not be visible within class B - you may want to give them distinct names. +t4762.scala:15: warning: private[this] value x in class B shadows mutable x inherited from class A. Changes to x will not be visible within class B - you may want to give them distinct names. /* (99,99) */ (this.x, this.y), ^ -t4762.scala:48: error: private[this] value x in class Derived shadows mutable x inherited from class Base. Changes to x will not be visible within class Derived - you may want to give them distinct names. +t4762.scala:48: warning: private[this] value x in class Derived shadows mutable x inherited from class Base. Changes to x will not be visible within class Derived - you may want to give them distinct names. class Derived( x : Int ) extends Base( x ) { override def toString = x.toString } ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t4851.check b/test/files/neg/t4851.check index 8011350f23..0fd66b9efe 100644 --- a/test/files/neg/t4851.check +++ b/test/files/neg/t4851.check @@ -1,43 +1,45 @@ -S.scala:2: error: Adapting argument list by inserting (): leaky (Object-receiving) target makes this especially dangerous. +S.scala:2: warning: Adapting argument list by inserting (): leaky (Object-receiving) target makes this especially dangerous. signature: J(x: Any): J given arguments: <none> after adaptation: new J((): Unit) val x1 = new J ^ -S.scala:3: error: Adapting argument list by inserting (): leaky (Object-receiving) target makes this especially dangerous. +S.scala:3: warning: Adapting argument list by inserting (): leaky (Object-receiving) target makes this especially dangerous. signature: J(x: Any): J given arguments: <none> after adaptation: new J((): Unit) val x2 = new J() ^ -S.scala:4: error: Adapting argument list by creating a 5-tuple: this may not be what you want. +S.scala:4: warning: Adapting argument list by creating a 5-tuple: this may not be what you want. signature: J(x: Any): J given arguments: 1, 2, 3, 4, 5 after adaptation: new J((1, 2, 3, 4, 5): (Int, Int, Int, Int, Int)) val x3 = new J(1, 2, 3, 4, 5) ^ -S.scala:6: error: Adapting argument list by creating a 3-tuple: this may not be what you want. +S.scala:6: warning: Adapting argument list by creating a 3-tuple: this may not be what you want. signature: Some.apply[A](x: A): Some[A] given arguments: 1, 2, 3 after adaptation: Some((1, 2, 3): (Int, Int, Int)) val y1 = Some(1, 2, 3) ^ -S.scala:7: error: Adapting argument list by creating a 3-tuple: this may not be what you want. +S.scala:7: warning: Adapting argument list by creating a 3-tuple: this may not be what you want. signature: Some(x: A): Some[A] given arguments: 1, 2, 3 after adaptation: new Some((1, 2, 3): (Int, Int, Int)) val y2 = new Some(1, 2, 3) ^ -S.scala:9: error: Adapting argument list by inserting (): this is unlikely to be what you want. +S.scala:9: warning: Adapting argument list by inserting (): this is unlikely to be what you want. signature: J2[T](x: T): J2[T] given arguments: <none> after adaptation: new J2((): Unit) val z1 = new J2 ^ -S.scala:10: error: Adapting argument list by inserting (): this is unlikely to be what you want. +S.scala:10: warning: Adapting argument list by inserting (): this is unlikely to be what you want. signature: J2[T](x: T): J2[T] given arguments: <none> after adaptation: new J2((): Unit) val z2 = new J2() ^ -7 errors found +error: No warnings can be incurred under -Xfatal-warnings. +7 warnings found +one error found diff --git a/test/files/neg/t5353.check b/test/files/neg/t5353.check new file mode 100644 index 0000000000..75e2435600 --- /dev/null +++ b/test/files/neg/t5353.check @@ -0,0 +1,4 @@ +t5353.scala:2: error: this type parameter must be specified + def f(x: Boolean) = if (x) Array("abc") else Array() + ^ +one error found diff --git a/test/files/neg/t5353.scala b/test/files/neg/t5353.scala new file mode 100644 index 0000000000..1ee869aac1 --- /dev/null +++ b/test/files/neg/t5353.scala @@ -0,0 +1,3 @@ +class A { + def f(x: Boolean) = if (x) Array("abc") else Array() +} diff --git a/test/files/neg/t5426.check b/test/files/neg/t5426.check index d9e192d3f0..98f3ddaaae 100644 --- a/test/files/neg/t5426.check +++ b/test/files/neg/t5426.check @@ -1,13 +1,15 @@ -t5426.scala:2: error: comparing values of types Some[Int] and Int using `==' will always yield false +t5426.scala:2: warning: comparing values of types Some[Int] and Int using `==' will always yield false def f1 = Some(5) == 5 ^ -t5426.scala:3: error: comparing values of types Int and Some[Int] using `==' will always yield false +t5426.scala:3: warning: comparing values of types Int and Some[Int] using `==' will always yield false def f2 = 5 == Some(5) ^ -t5426.scala:8: error: comparing values of types Int and Some[Int] using `==' will always yield false +t5426.scala:8: warning: comparing values of types Int and Some[Int] using `==' will always yield false (x1 == x2) ^ -t5426.scala:9: error: comparing values of types Some[Int] and Int using `==' will always yield false +t5426.scala:9: warning: comparing values of types Some[Int] and Int using `==' will always yield false (x2 == x1) ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/t5663-badwarneq.check b/test/files/neg/t5663-badwarneq.check index 00c2234e9d..12e93ff373 100644 --- a/test/files/neg/t5663-badwarneq.check +++ b/test/files/neg/t5663-badwarneq.check @@ -1,22 +1,24 @@ -t5663-badwarneq.scala:42: error: comparing case class values of types Some[Int] and None.type using `==' will always yield false +t5663-badwarneq.scala:42: warning: comparing case class values of types Some[Int] and None.type using `==' will always yield false println(new Some(1) == None) // Should complain on type, was: spuriously complains on fresh object ^ -t5663-badwarneq.scala:43: error: comparing case class values of types Some[Int] and Thing using `==' will always yield false +t5663-badwarneq.scala:43: warning: comparing case class values of types Some[Int] and Thing using `==' will always yield false println(Some(1) == new Thing(1)) // Should complain on type, was: spuriously complains on fresh object ^ -t5663-badwarneq.scala:51: error: ThingOne and Thingy are unrelated: they will most likely never compare equal +t5663-badwarneq.scala:51: warning: ThingOne and Thingy are unrelated: they will most likely never compare equal println(t1 == t2) // true, but apparently unrelated, a compromise warning ^ -t5663-badwarneq.scala:52: error: ThingThree and Thingy are unrelated: they will most likely never compare equal +t5663-badwarneq.scala:52: warning: ThingThree and Thingy are unrelated: they will most likely never compare equal println(t4 == t2) // true, complains because ThingThree is final and Thingy not a subclass, stronger claim than unrelated ^ -t5663-badwarneq.scala:55: error: comparing case class values of types ThingTwo and Some[Int] using `==' will always yield false +t5663-badwarneq.scala:55: warning: comparing case class values of types ThingTwo and Some[Int] using `==' will always yield false println(t3 == Some(1)) // false, warn on different cases ^ -t5663-badwarneq.scala:56: error: comparing values of types ThingOne and Cousin using `==' will always yield false +t5663-badwarneq.scala:56: warning: comparing values of types ThingOne and Cousin using `==' will always yield false println(t1 == c) // should warn ^ -t5663-badwarneq.scala:64: error: comparing case class values of types Simple and SimpleSibling.type using `==' will always yield false +t5663-badwarneq.scala:64: warning: comparing case class values of types Simple and SimpleSibling.type using `==' will always yield false println(new Simple() == SimpleSibling) // like Some(1) == None, but needn't be final case ^ -7 errors found +error: No warnings can be incurred under -Xfatal-warnings. +7 warnings found +one error found diff --git a/test/files/neg/t5692a.check b/test/files/neg/t5692a.check index ded95a8820..7fbfb5dba7 100644 --- a/test/files/neg/t5692a.check +++ b/test/files/neg/t5692a.check @@ -1,4 +1,4 @@ -Test_2.scala:2: error: type parameter not specified +Test_2.scala:2: error: this type parameter must be specified def x = Macros.foo ^ one error found diff --git a/test/files/neg/t5692b.check b/test/files/neg/t5692b.check index e453870ec8..16796826b4 100644 --- a/test/files/neg/t5692b.check +++ b/test/files/neg/t5692b.check @@ -1,4 +1,4 @@ -Test_2.scala:2: error: type parameters not specified +Test_2.scala:2: error: these type parameters must be specified def x = Macros.foo ^ one error found diff --git a/test/files/neg/t5762.check b/test/files/neg/t5762.check index 10064032aa..2a2f12144a 100644 --- a/test/files/neg/t5762.check +++ b/test/files/neg/t5762.check @@ -1,13 +1,15 @@ -t5762.scala:6: error: non-variable type argument Int in type pattern D[Int] is unchecked since it is eliminated by erasure +t5762.scala:6: warning: non-variable type argument Int in type pattern D[Int] is unchecked since it is eliminated by erasure case _: D[Int] if bippy => 1 ^ -t5762.scala:7: error: non-variable type argument String in type pattern D[String] is unchecked since it is eliminated by erasure +t5762.scala:7: warning: non-variable type argument String in type pattern D[String] is unchecked since it is eliminated by erasure case _: D[String] => 2 ^ -t5762.scala:20: error: non-variable type argument D[Int] in type pattern D[D[Int]] is unchecked since it is eliminated by erasure +t5762.scala:20: warning: non-variable type argument D[Int] in type pattern D[D[Int]] is unchecked since it is eliminated by erasure case _: D[D[Int]] if bippy => 1 ^ -t5762.scala:21: error: non-variable type argument D[String] in type pattern D[D[String]] is unchecked since it is eliminated by erasure +t5762.scala:21: warning: non-variable type argument D[String] in type pattern D[D[String]] is unchecked since it is eliminated by erasure case _: D[D[String]] => 2 ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/t5830.check b/test/files/neg/t5830.check index 726fac2a1e..58c3a1be38 100644 --- a/test/files/neg/t5830.check +++ b/test/files/neg/t5830.check @@ -1,7 +1,9 @@ -t5830.scala:6: error: unreachable code +t5830.scala:6: warning: unreachable code case 'a' => println("b") // unreachable ^ -t5830.scala:4: error: could not emit switch for @switch annotated match +t5830.scala:4: warning: could not emit switch for @switch annotated match def unreachable(ch: Char) = (ch: @switch) match { ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t6011.check b/test/files/neg/t6011.check index 5b5a861e5b..cb7f189031 100644 --- a/test/files/neg/t6011.check +++ b/test/files/neg/t6011.check @@ -1,10 +1,12 @@ -t6011.scala:4: error: unreachable code +t6011.scala:4: warning: unreachable code case 'a' | 'c' => 1 // unreachable ^ -t6011.scala:10: error: unreachable code +t6011.scala:10: warning: unreachable code case 'b' | 'a' => 1 // unreachable ^ -t6011.scala:8: error: could not emit switch for @switch annotated match +t6011.scala:8: warning: could not emit switch for @switch annotated match def f2(ch: Char): Any = (ch: @annotation.switch) match { ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/t6048.check b/test/files/neg/t6048.check index 5bdf2eca88..5e11d24fde 100644 --- a/test/files/neg/t6048.check +++ b/test/files/neg/t6048.check @@ -1,13 +1,15 @@ -t6048.scala:3: error: unreachable code +t6048.scala:3: warning: unreachable code case _ if false => x // unreachable ^ -t6048.scala:8: error: unreachable code +t6048.scala:8: warning: unreachable code case _ if false => x // unreachable ^ -t6048.scala:13: error: patterns after a variable pattern cannot match (SLS 8.1.1) +t6048.scala:13: warning: patterns after a variable pattern cannot match (SLS 8.1.1) case _ => x ^ -t6048.scala:14: error: unreachable code due to variable pattern on line 13 +t6048.scala:14: warning: unreachable code due to variable pattern on line 13 case 5 if true => x // unreachable ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/t6162-inheritance.check b/test/files/neg/t6162-inheritance.check index a7d3cc3238..e98fa79eb7 100644 --- a/test/files/neg/t6162-inheritance.check +++ b/test/files/neg/t6162-inheritance.check @@ -1,10 +1,18 @@ -t6162-inheritance.scala:6: error: inheritance from class Foo in package t6126 is deprecated: `Foo` will be made final in a future version. +t6162-inheritance.scala:6: warning: inheritance from class Foo in package t6126 is deprecated: `Foo` will be made final in a future version. class SubFoo extends Foo ^ -t6162-inheritance.scala:11: error: inheritance from trait T in package t6126 is deprecated +t6162-inheritance.scala:11: warning: inheritance from trait T in package t6126 is deprecated object SubT extends T ^ -t6162-inheritance.scala:17: error: inheritance from trait S in package t6126 is deprecated +t6162-inheritance.scala:17: warning: inheritance from trait S in package t6126 is deprecated new S { ^ -three errors found +t6162-inheritance.scala:6: warning: inheritance from class Foo in package t6126 is deprecated: `Foo` will be made final in a future version. +class SubFoo extends Foo + ^ +t6162-inheritance.scala:11: warning: inheritance from trait T in package t6126 is deprecated +object SubT extends T + ^ +error: No warnings can be incurred under -Xfatal-warnings. +5 warnings found +one error found diff --git a/test/files/neg/t6162-overriding.check b/test/files/neg/t6162-overriding.check index e774888d36..6bff75d88d 100644 --- a/test/files/neg/t6162-overriding.check +++ b/test/files/neg/t6162-overriding.check @@ -1,7 +1,9 @@ -t6162-overriding.scala:14: error: overriding method bar in class Bar is deprecated: `bar` will be made private in a future version. +t6162-overriding.scala:14: warning: overriding method bar in class Bar is deprecated: `bar` will be made private in a future version. override def bar = 43 ^ -t6162-overriding.scala:15: error: overriding method baz in class Bar is deprecated +t6162-overriding.scala:15: warning: overriding method baz in class Bar is deprecated override def baz = 43 ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t6264.check b/test/files/neg/t6264.check index 438be4c39f..c0975a80b2 100644 --- a/test/files/neg/t6264.check +++ b/test/files/neg/t6264.check @@ -1,4 +1,6 @@ -t6264.scala:3: error: non-variable type argument Tuple1[_] in type Tuple2[_, Tuple1[_]] is unchecked since it is eliminated by erasure +t6264.scala:3: warning: non-variable type argument Tuple1[_] in type Tuple2[_, Tuple1[_]] is unchecked since it is eliminated by erasure x.isInstanceOf[Tuple2[_, Tuple1[_]]] ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t6276.check b/test/files/neg/t6276.check index 0b3dfa5531..f275de9d0a 100644 --- a/test/files/neg/t6276.check +++ b/test/files/neg/t6276.check @@ -1,19 +1,21 @@ -t6276.scala:4: error: method a in class C does nothing other than call itself recursively +t6276.scala:4: warning: method a in class C does nothing other than call itself recursively def a: Any = a // warn ^ -t6276.scala:5: error: value b in class C does nothing other than call itself recursively +t6276.scala:5: warning: value b in class C does nothing other than call itself recursively val b: Any = b // warn ^ -t6276.scala:7: error: method c in class C does nothing other than call itself recursively +t6276.scala:7: warning: method c in class C does nothing other than call itself recursively def c: Any = this.c // warn ^ -t6276.scala:8: error: method d in class C does nothing other than call itself recursively +t6276.scala:8: warning: method d in class C does nothing other than call itself recursively def d: Any = C.this.d // warn ^ -t6276.scala:13: error: method a does nothing other than call itself recursively +t6276.scala:13: warning: method a does nothing other than call itself recursively def a: Any = a // warn ^ -t6276.scala:22: error: method a does nothing other than call itself recursively +t6276.scala:22: warning: method a does nothing other than call itself recursively def a = a // warn ^ -6 errors found +error: No warnings can be incurred under -Xfatal-warnings. +6 warnings found +one error found diff --git a/test/files/neg/t6355.check b/test/files/neg/t6355.check new file mode 100644 index 0000000000..c1fa147f52 --- /dev/null +++ b/test/files/neg/t6355.check @@ -0,0 +1,4 @@ +t6355.scala:12: error: implementation restriction: applyDynamic cannot be overloaded + def applyDynamic(name: String)(x: Int): Int = 2 + ^ +one error found diff --git a/test/files/neg/t6355.scala b/test/files/neg/t6355.scala new file mode 100644 index 0000000000..3007dc49f6 --- /dev/null +++ b/test/files/neg/t6355.scala @@ -0,0 +1,13 @@ +package foo + +import scala.language.dynamics + +class DoesntExtendDynamic { + def applyDynamic(name: String)(s: String): Int = 1 + def applyDynamic(name: String)(x: Int): Int = 2 +} + +class A extends Dynamic { + def applyDynamic(name: String)(s: String): Int = 1 + def applyDynamic(name: String)(x: Int): Int = 2 +} diff --git a/test/files/neg/t6357.check b/test/files/neg/t6357.check new file mode 100644 index 0000000000..a534d1439a --- /dev/null +++ b/test/files/neg/t6357.check @@ -0,0 +1,4 @@ +t6357.scala:3: error: value class may not be a local class + final class Y(val j: Int) extends AnyVal + ^ +one error found diff --git a/test/files/neg/t6357.scala b/test/files/neg/t6357.scala new file mode 100644 index 0000000000..47f5629638 --- /dev/null +++ b/test/files/neg/t6357.scala @@ -0,0 +1,6 @@ +object K { + def q = { + final class Y(val j: Int) extends AnyVal + 3 + } +} diff --git a/test/files/neg/t6406-regextract.check b/test/files/neg/t6406-regextract.check new file mode 100644 index 0000000000..19425a68b0 --- /dev/null +++ b/test/files/neg/t6406-regextract.check @@ -0,0 +1,6 @@ +t6406-regextract.scala:4: warning: method unapplySeq in class Regex is deprecated: Extracting a match result from anything but a CharSequence or Match is deprecated + List(1) collect { case r(i) => i } + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/t6406-regextract.flags b/test/files/neg/t6406-regextract.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/t6406-regextract.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/t6406-regextract.scala b/test/files/neg/t6406-regextract.scala new file mode 100644 index 0000000000..0f5dad908d --- /dev/null +++ b/test/files/neg/t6406-regextract.scala @@ -0,0 +1,5 @@ + +object Test extends App { + val r = "(\\d+)".r + List(1) collect { case r(i) => i } +} diff --git a/test/files/neg/t6426.check b/test/files/neg/t6426.check new file mode 100644 index 0000000000..149f74c4de --- /dev/null +++ b/test/files/neg/t6426.check @@ -0,0 +1,7 @@ +t6426.scala:4: error: wildcard invalid as backquoted identifier + println(`_`.Buffer(0)) + ^ +t6426.scala:5: error: ')' expected but '}' found. +} +^ +two errors found diff --git a/test/files/neg/t6426.scala b/test/files/neg/t6426.scala new file mode 100644 index 0000000000..a27d18eb58 --- /dev/null +++ b/test/files/neg/t6426.scala @@ -0,0 +1,5 @@ +class A { + import collection.{mutable => _, _} + + println(`_`.Buffer(0)) +} diff --git a/test/files/neg/t6567.check b/test/files/neg/t6567.check new file mode 100644 index 0000000000..a733d75354 --- /dev/null +++ b/test/files/neg/t6567.check @@ -0,0 +1,9 @@ +t6567.scala:8: warning: Suspicious application of an implicit view (Test.this.a2b) in the argument to Option.apply. + Option[B](a) + ^ +t6567.scala:10: warning: Suspicious application of an implicit view (Test.this.a2b) in the argument to Option.apply. + val b: Option[B] = Option(a) + ^ +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/t6567.flags b/test/files/neg/t6567.flags new file mode 100644 index 0000000000..e93641e931 --- /dev/null +++ b/test/files/neg/t6567.flags @@ -0,0 +1 @@ +-Xlint -Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/t6567.scala b/test/files/neg/t6567.scala new file mode 100644 index 0000000000..650e5e39ae --- /dev/null +++ b/test/files/neg/t6567.scala @@ -0,0 +1,11 @@ +class A +class B + +object Test { + val a: A = null + implicit def a2b(a: A) = new B + + Option[B](a) + + val b: Option[B] = Option(a) +} diff --git a/test/files/neg/unchecked-abstract.check b/test/files/neg/unchecked-abstract.check index 6e811dc156..72019082ac 100644 --- a/test/files/neg/unchecked-abstract.check +++ b/test/files/neg/unchecked-abstract.check @@ -1,25 +1,27 @@ -unchecked-abstract.scala:16: error: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:16: warning: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Contravariant[H]]) ^ -unchecked-abstract.scala:21: error: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:21: warning: abstract type H in type Contravariant[M.this.H] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Contravariant[H]]) ^ -unchecked-abstract.scala:27: error: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:27: warning: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[T]]) ^ -unchecked-abstract.scala:28: error: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:28: warning: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[L]]) ^ -unchecked-abstract.scala:31: error: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:31: warning: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[H]]) ^ -unchecked-abstract.scala:33: error: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:33: warning: abstract type L in type Invariant[M.this.L] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[L]]) ^ -unchecked-abstract.scala:36: error: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:36: warning: abstract type H in type Invariant[M.this.H] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[H]]) ^ -unchecked-abstract.scala:37: error: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure +unchecked-abstract.scala:37: warning: abstract type T in type Invariant[M.this.T] is unchecked since it is eliminated by erasure /* warn */ println(x.isInstanceOf[Invariant[T]]) ^ -8 errors found +error: No warnings can be incurred under -Xfatal-warnings. +8 warnings found +one error found diff --git a/test/files/neg/unchecked-impossible.check b/test/files/neg/unchecked-impossible.check index 0ab371dbaa..d150a5a853 100644 --- a/test/files/neg/unchecked-impossible.check +++ b/test/files/neg/unchecked-impossible.check @@ -1,4 +1,10 @@ -unchecked-impossible.scala:5: error: fruitless type test: a value of type T2[Int,Int] cannot also be a Seq[A] +unchecked-impossible.scala:5: warning: fruitless type test: a value of type T2[Int,Int] cannot also be a Seq[A] case Seq(x) => ^ +unchecked-impossible.scala:5: error: pattern type is incompatible with expected type; + found : Seq[A] + required: T2[Int,Int] + case Seq(x) => + ^ +one warning found one error found diff --git a/test/files/neg/unchecked-knowable.check b/test/files/neg/unchecked-knowable.check index d279427327..327a5f202d 100644 --- a/test/files/neg/unchecked-knowable.check +++ b/test/files/neg/unchecked-knowable.check @@ -1,7 +1,9 @@ -unchecked-knowable.scala:18: error: fruitless type test: a value of type Bippy cannot also be a A1 +unchecked-knowable.scala:18: warning: fruitless type test: a value of type Bippy cannot also be a A1 /* warn */ (new Bippy).isInstanceOf[A1] ^ -unchecked-knowable.scala:19: error: fruitless type test: a value of type Bippy cannot also be a B1 +unchecked-knowable.scala:19: warning: fruitless type test: a value of type Bippy cannot also be a B1 /* warn */ (new Bippy).isInstanceOf[B1] ^ -two errors found +error: No warnings can be incurred under -Xfatal-warnings. +two warnings found +one error found diff --git a/test/files/neg/unchecked-refinement.check b/test/files/neg/unchecked-refinement.check index d81517464f..e85a51f44d 100644 --- a/test/files/neg/unchecked-refinement.check +++ b/test/files/neg/unchecked-refinement.check @@ -1,13 +1,15 @@ -unchecked-refinement.scala:17: error: abstract type U in type pattern Foo[U,U,V] is unchecked since it is eliminated by erasure +unchecked-refinement.scala:17: warning: abstract type U in type pattern Foo[U,U,V] is unchecked since it is eliminated by erasure /* warn */ case _: Foo[U, U, V] if b => () ^ -unchecked-refinement.scala:19: error: non-variable type argument Any in type pattern Foo[Any,U,V] is unchecked since it is eliminated by erasure +unchecked-refinement.scala:19: warning: non-variable type argument Any in type pattern Foo[Any,U,V] is unchecked since it is eliminated by erasure /* warn */ case _: Foo[Any, U, V] if b => () ^ -unchecked-refinement.scala:23: error: a pattern match on a refinement type is unchecked +unchecked-refinement.scala:23: warning: a pattern match on a refinement type is unchecked /* nowarn - todo */ case x: AnyRef { def bippy: Int } if b => x.bippy // this could/should do an instance check and not warn ^ -unchecked-refinement.scala:24: error: a pattern match on a refinement type is unchecked +unchecked-refinement.scala:24: warning: a pattern match on a refinement type is unchecked /* nowarn - todo */ case x: AnyRef { def size: Int } if b => x.size // this could/should do a static conformance test and not warn ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/unchecked-suppress.check b/test/files/neg/unchecked-suppress.check index 2e23d21386..038105918e 100644 --- a/test/files/neg/unchecked-suppress.check +++ b/test/files/neg/unchecked-suppress.check @@ -1,10 +1,12 @@ -unchecked-suppress.scala:4: error: non-variable type argument Int in type pattern Set[Int] is unchecked since it is eliminated by erasure +unchecked-suppress.scala:4: warning: non-variable type argument Int in type pattern Set[Int] is unchecked since it is eliminated by erasure case xs: Set[Int] => xs.head // unchecked ^ -unchecked-suppress.scala:5: error: non-variable type argument String in type pattern Map[String @unchecked,String] is unchecked since it is eliminated by erasure +unchecked-suppress.scala:5: warning: non-variable type argument String in type pattern Map[String @unchecked,String] is unchecked since it is eliminated by erasure case xs: Map[String @unchecked, String] => xs.head // one unchecked, one okay ^ -unchecked-suppress.scala:7: error: non-variable type argument Int in type pattern (Int, Int) => Int is unchecked since it is eliminated by erasure +unchecked-suppress.scala:7: warning: non-variable type argument Int in type pattern (Int, Int) => Int is unchecked since it is eliminated by erasure case f: ((Int, Int) => Int) => // unchecked ^ -three errors found +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/unchecked.check b/test/files/neg/unchecked.check index 2883b716c9..570f02f219 100644 --- a/test/files/neg/unchecked.check +++ b/test/files/neg/unchecked.check @@ -1,19 +1,21 @@ -unchecked.scala:18: error: non-variable type argument String in type pattern Iterable[String] is unchecked since it is eliminated by erasure +unchecked.scala:18: warning: non-variable type argument String in type pattern Iterable[String] is unchecked since it is eliminated by erasure case xs: Iterable[String] => xs.head // unchecked ^ -unchecked.scala:22: error: non-variable type argument Any in type pattern Set[Any] is unchecked since it is eliminated by erasure +unchecked.scala:22: warning: non-variable type argument Any in type pattern Set[Any] is unchecked since it is eliminated by erasure case xs: Set[Any] => xs.head // unchecked ^ -unchecked.scala:26: error: non-variable type argument Any in type pattern Map[Any,Any] is unchecked since it is eliminated by erasure +unchecked.scala:26: warning: non-variable type argument Any in type pattern Map[Any,Any] is unchecked since it is eliminated by erasure case xs: Map[Any, Any] => xs.head // unchecked ^ -unchecked.scala:35: error: non-variable type argument List[Nothing] in type pattern Test.Contra[List[Nothing]] is unchecked since it is eliminated by erasure +unchecked.scala:35: warning: non-variable type argument List[Nothing] in type pattern Test.Contra[List[Nothing]] is unchecked since it is eliminated by erasure case xs: Contra[List[Nothing]] => xs.head // unchecked ^ -unchecked.scala:50: error: non-variable type argument String in type pattern Test.Exp[String] is unchecked since it is eliminated by erasure +unchecked.scala:50: warning: non-variable type argument String in type pattern Test.Exp[String] is unchecked since it is eliminated by erasure case ArrayApply(x: Exp[Array[T]], _, j: Exp[String]) => x // unchecked ^ -unchecked.scala:55: error: non-variable type argument Array[T] in type pattern Test.Exp[Array[T]] is unchecked since it is eliminated by erasure +unchecked.scala:55: warning: non-variable type argument Array[T] in type pattern Test.Exp[Array[T]] is unchecked since it is eliminated by erasure case ArrayApply(x: Exp[Array[T]], _, _) => x // unchecked ^ -6 errors found +error: No warnings can be incurred under -Xfatal-warnings. +6 warnings found +one error found diff --git a/test/files/neg/unchecked2.check b/test/files/neg/unchecked2.check index 68fdfa82ac..a7b8391856 100644 --- a/test/files/neg/unchecked2.check +++ b/test/files/neg/unchecked2.check @@ -1,43 +1,45 @@ -unchecked2.scala:4: error: fruitless type test: a value of type Some[List[Int]] cannot also be a Option[List[String]] (but still might match its erasure) +unchecked2.scala:4: warning: fruitless type test: a value of type Some[List[Int]] cannot also be a Option[List[String]] (but still might match its erasure) /* warn */ Some(List(1)).isInstanceOf[Option[List[String]]] ^ -unchecked2.scala:5: error: non-variable type argument Option[_] in type Option[Option[_]] is unchecked since it is eliminated by erasure +unchecked2.scala:5: warning: non-variable type argument Option[_] in type Option[Option[_]] is unchecked since it is eliminated by erasure /* warn */ Some(123).isInstanceOf[Option[Option[_]]] ^ -unchecked2.scala:6: error: fruitless type test: a value of type Some[Int] cannot also be a Option[String] (but still might match its erasure) +unchecked2.scala:6: warning: fruitless type test: a value of type Some[Int] cannot also be a Option[String] (but still might match its erasure) /* warn */ Some(123).isInstanceOf[Option[String]] ^ -unchecked2.scala:7: error: fruitless type test: a value of type Some[Int] cannot also be a Option[List[String]] (but still might match its erasure) +unchecked2.scala:7: warning: fruitless type test: a value of type Some[Int] cannot also be a Option[List[String]] (but still might match its erasure) /* warn */ Some(123).isInstanceOf[Option[List[String]]] ^ -unchecked2.scala:8: error: fruitless type test: a value of type Some[Int] cannot also be a Option[List[Int => String]] (but still might match its erasure) +unchecked2.scala:8: warning: fruitless type test: a value of type Some[Int] cannot also be a Option[List[Int => String]] (but still might match its erasure) /* warn */ Some(123).isInstanceOf[Option[List[Int => String]]] ^ -unchecked2.scala:9: error: fruitless type test: a value of type Some[Int] cannot also be a Option[(String, Double)] (but still might match its erasure) +unchecked2.scala:9: warning: fruitless type test: a value of type Some[Int] cannot also be a Option[(String, Double)] (but still might match its erasure) /* warn */ Some(123).isInstanceOf[Option[(String, Double)]] ^ -unchecked2.scala:10: error: fruitless type test: a value of type Some[Int] cannot also be a Option[String => Double] (but still might match its erasure) +unchecked2.scala:10: warning: fruitless type test: a value of type Some[Int] cannot also be a Option[String => Double] (but still might match its erasure) /* warn */ Some(123).isInstanceOf[Option[String => Double]] ^ -unchecked2.scala:14: error: non-variable type argument List[String] in type Option[List[String]] is unchecked since it is eliminated by erasure +unchecked2.scala:14: warning: non-variable type argument List[String] in type Option[List[String]] is unchecked since it is eliminated by erasure /* warn */ (Some(List(1)): Any).isInstanceOf[Option[List[String]]] ^ -unchecked2.scala:15: error: non-variable type argument Int in type Option[Int] is unchecked since it is eliminated by erasure +unchecked2.scala:15: warning: non-variable type argument Int in type Option[Int] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[Int]] ^ -unchecked2.scala:16: error: non-variable type argument String in type Option[String] is unchecked since it is eliminated by erasure +unchecked2.scala:16: warning: non-variable type argument String in type Option[String] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[String]] ^ -unchecked2.scala:17: error: non-variable type argument List[String] in type Option[List[String]] is unchecked since it is eliminated by erasure +unchecked2.scala:17: warning: non-variable type argument List[String] in type Option[List[String]] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[List[String]]] ^ -unchecked2.scala:18: error: non-variable type argument List[Int => String] in type Option[List[Int => String]] is unchecked since it is eliminated by erasure +unchecked2.scala:18: warning: non-variable type argument List[Int => String] in type Option[List[Int => String]] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[List[Int => String]]] ^ -unchecked2.scala:19: error: non-variable type argument (String, Double) in type Option[(String, Double)] is unchecked since it is eliminated by erasure +unchecked2.scala:19: warning: non-variable type argument (String, Double) in type Option[(String, Double)] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[(String, Double)]] ^ -unchecked2.scala:20: error: non-variable type argument String => Double in type Option[String => Double] is unchecked since it is eliminated by erasure +unchecked2.scala:20: warning: non-variable type argument String => Double in type Option[String => Double] is unchecked since it is eliminated by erasure /* warn */ (Some(123): Any).isInstanceOf[Option[String => Double]] ^ -14 errors found +error: No warnings can be incurred under -Xfatal-warnings. +14 warnings found +one error found diff --git a/test/files/neg/unchecked3.check b/test/files/neg/unchecked3.check index f4f0c74257..a7582a8930 100644 --- a/test/files/neg/unchecked3.check +++ b/test/files/neg/unchecked3.check @@ -1,37 +1,42 @@ -unchecked3.scala:24: error: non-variable type argument Double in type pattern E1[Double] is unchecked since it is eliminated by erasure +unchecked3.scala:24: warning: non-variable type argument Double in type pattern E1[Double] is unchecked since it is eliminated by erasure /* warn */ def peerTypes2(x: B1[Int]) = x match { case _: E1[Double] => true } ^ -unchecked3.scala:25: error: non-variable type argument Double in type pattern F1[Double] is unchecked since it is eliminated by erasure +unchecked3.scala:25: warning: non-variable type argument Double in type pattern F1[Double] is unchecked since it is eliminated by erasure /* warn */ def peerTypes3(x: B1[_]) = x match { case _: F1[Double] => true } ^ -unchecked3.scala:28: error: non-variable type argument Int in type pattern A2[Int] is unchecked since it is eliminated by erasure +unchecked3.scala:28: warning: non-variable type argument Int in type pattern A2[Int] is unchecked since it is eliminated by erasure /* warn */ def twotypes1[T](x: B2[T, Int]) = x match { case _: A2[Int] => true } ^ -unchecked3.scala:32: error: non-variable type argument Int in type pattern B2[_,Int] is unchecked since it is eliminated by erasure +unchecked3.scala:32: warning: non-variable type argument Int in type pattern B2[_,Int] is unchecked since it is eliminated by erasure /* warn */ def twotypes5[T](x: A2[T]) = x match { case _: B2[_, Int] => true } ^ -unchecked3.scala:40: error: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure +unchecked3.scala:40: warning: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[List[String]] => () ^ -unchecked3.scala:43: error: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure +unchecked3.scala:43: warning: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[Array[List[String]]] => () ^ -unchecked3.scala:50: error: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure +unchecked3.scala:50: warning: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[List[String]] => () ^ -unchecked3.scala:53: error: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure +unchecked3.scala:53: warning: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[Array[List[String]]] => () ^ -unchecked3.scala:60: error: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure +unchecked3.scala:60: warning: non-variable type argument String in type pattern Array[List[String]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[List[String]] => () ^ -unchecked3.scala:62: error: non-variable type argument Array[String] in type pattern Array[List[Array[String]]] is unchecked since it is eliminated by erasure +unchecked3.scala:62: warning: non-variable type argument Array[String] in type pattern Array[List[Array[String]]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[List[Array[String]]] => () ^ -unchecked3.scala:63: error: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure +unchecked3.scala:63: warning: non-variable type argument String in type pattern Array[Array[List[String]]] is unchecked since it is eliminated by erasure /* warn */ case _: Array[Array[List[String]]] => () ^ -unchecked3.scala:75: error: abstract type A in type pattern Set[Q.this.A] is unchecked since it is eliminated by erasure +unchecked3.scala:75: warning: abstract type A in type pattern Set[Q.this.A] is unchecked since it is eliminated by erasure /* warn */ case xs: Set[A] => xs.head ^ -12 errors found +unchecked3.scala:62: warning: unreachable code + /* warn */ case _: Array[List[Array[String]]] => () + ^ +error: No warnings can be incurred under -Xfatal-warnings. +13 warnings found +one error found diff --git a/test/files/neg/unit-returns-value.check b/test/files/neg/unit-returns-value.check index ab458a350b..f30a506ebe 100644 --- a/test/files/neg/unit-returns-value.check +++ b/test/files/neg/unit-returns-value.check @@ -1,7 +1,15 @@ -unit-returns-value.scala:4: error: a pure expression does nothing in statement position; you may be omitting necessary parentheses +unit-returns-value.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses if (b) return 5 ^ -unit-returns-value.scala:4: error: enclosing method f has result type Unit: return value discarded +unit-returns-value.scala:4: warning: enclosing method f has result type Unit: return value discarded if (b) return 5 ^ -two errors found +unit-returns-value.scala:22: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + i1 // warn + ^ +unit-returns-value.scala:23: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + i2 // warn + ^ +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/unit-returns-value.scala b/test/files/neg/unit-returns-value.scala index ecc981f217..fc5a37069f 100644 --- a/test/files/neg/unit-returns-value.scala +++ b/test/files/neg/unit-returns-value.scala @@ -3,9 +3,30 @@ object Test { var b = false if (b) return 5 } - + // no warning def g { return println("hello") } } + +class UnusedValues { + var i1 = 2 + val i2 = 2 + lazy val i3 = 2 + object i4 { } + def i5 = 2 + final def i6 = 2 + + def x = { + i1 // warn + i2 // warn + i3 // no warn + i4 // no warn + i5 // no warn + i6 // could warn someday, if i6 returned 2.type instead of Int + + 5 + } +} + diff --git a/test/files/neg/virtpatmat_reach_null.check b/test/files/neg/virtpatmat_reach_null.check index 595c8ec889..e0c36c8c5b 100644 --- a/test/files/neg/virtpatmat_reach_null.check +++ b/test/files/neg/virtpatmat_reach_null.check @@ -1,4 +1,6 @@ -virtpatmat_reach_null.scala:13: error: unreachable code +virtpatmat_reach_null.scala:13: warning: unreachable code case _ => // unreachable ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/virtpatmat_reach_sealed_unsealed.check b/test/files/neg/virtpatmat_reach_sealed_unsealed.check index 10638eff52..064a12bcaa 100644 --- a/test/files/neg/virtpatmat_reach_sealed_unsealed.check +++ b/test/files/neg/virtpatmat_reach_sealed_unsealed.check @@ -1,14 +1,16 @@ -virtpatmat_reach_sealed_unsealed.scala:16: error: match may not be exhaustive. +virtpatmat_reach_sealed_unsealed.scala:16: warning: match may not be exhaustive. It would fail on the following input: false (true: Boolean) match { case true => } // not exhaustive, but reachable ^ -virtpatmat_reach_sealed_unsealed.scala:18: error: unreachable code +virtpatmat_reach_sealed_unsealed.scala:18: warning: unreachable code (true: Boolean) match { case true => case false => case _ => } // exhaustive, last case is unreachable ^ -virtpatmat_reach_sealed_unsealed.scala:19: error: unreachable code +virtpatmat_reach_sealed_unsealed.scala:19: warning: unreachable code (true: Boolean) match { case true => case false => case _: Boolean => } // exhaustive, last case is unreachable ^ -virtpatmat_reach_sealed_unsealed.scala:20: error: unreachable code +virtpatmat_reach_sealed_unsealed.scala:20: warning: unreachable code (true: Boolean) match { case true => case false => case _: Any => } // exhaustive, last case is unreachable ^ -four errors found +error: No warnings can be incurred under -Xfatal-warnings. +four warnings found +one error found diff --git a/test/files/neg/virtpatmat_unreach_select.check b/test/files/neg/virtpatmat_unreach_select.check index 3771971020..4fc78cd412 100644 --- a/test/files/neg/virtpatmat_unreach_select.check +++ b/test/files/neg/virtpatmat_unreach_select.check @@ -1,4 +1,6 @@ -virtpatmat_unreach_select.scala:10: error: unreachable code +virtpatmat_unreach_select.scala:10: warning: unreachable code case WARNING.id => // unreachable ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/warn-inferred-any.check b/test/files/neg/warn-inferred-any.check new file mode 100644 index 0000000000..4628033e55 --- /dev/null +++ b/test/files/neg/warn-inferred-any.check @@ -0,0 +1,12 @@ +warn-inferred-any.scala:8: warning: a type was inferred to be `Any`; this may indicate a programming error. + { List(1, 2, 3) contains "a" } // only this warns + ^ +warn-inferred-any.scala:16: warning: a type was inferred to be `AnyVal`; this may indicate a programming error. + { 1l to 5l contains 5 } + ^ +warn-inferred-any.scala:17: warning: a type was inferred to be `AnyVal`; this may indicate a programming error. + { 1l to 5l contains 5d } + ^ +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/warn-inferred-any.flags b/test/files/neg/warn-inferred-any.flags new file mode 100644 index 0000000000..a3127d392a --- /dev/null +++ b/test/files/neg/warn-inferred-any.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Ywarn-infer-any diff --git a/test/files/neg/warn-inferred-any.scala b/test/files/neg/warn-inferred-any.scala new file mode 100644 index 0000000000..b853e6e5a8 --- /dev/null +++ b/test/files/neg/warn-inferred-any.scala @@ -0,0 +1,19 @@ +trait Foo[-A <: AnyRef, +B <: AnyRef] { + def run[U](x: A)(action: B => U): Boolean = ??? + + { run(_: A)(_: B => String) } +} + +trait Xs[+A] { + { List(1, 2, 3) contains "a" } // only this warns + { List(1, 2, 3) contains 1 } + { identity(List(1, 2, 3) contains 1) } + { List("a") foreach println } +} + +trait Ys[+A] { + { 1 to 5 contains 5l } + { 1l to 5l contains 5 } + { 1l to 5l contains 5d } + { 1l to 5l contains 5l } +} diff --git a/test/files/neg/warn-unused-imports.check b/test/files/neg/warn-unused-imports.check new file mode 100644 index 0000000000..e61ec267d3 --- /dev/null +++ b/test/files/neg/warn-unused-imports.check @@ -0,0 +1,44 @@ +warn-unused-imports.scala:7: warning: it is not recommended to define classes/objects inside of package objects. +If possible, define class A in package p1 instead. + class A + ^ +warn-unused-imports.scala:13: warning: it is not recommended to define classes/objects inside of package objects. +If possible, define class A in package p2 instead. + class A + ^ +warn-unused-imports.scala:99: warning: local trait Warn is never used + trait Warn { // warn about unused local trait for good measure + ^ +warn-unused-imports.scala:57: warning: Unused import + import p1.A // warn + ^ +warn-unused-imports.scala:62: warning: Unused import + import p1.{ A, B } // warn on A + ^ +warn-unused-imports.scala:67: warning: Unused import + import p1.{ A, B } // warn on both + ^ +warn-unused-imports.scala:67: warning: Unused import + import p1.{ A, B } // warn on both + ^ +warn-unused-imports.scala:73: warning: Unused import + import c._ // warn + ^ +warn-unused-imports.scala:78: warning: Unused import + import p1._ // warn + ^ +warn-unused-imports.scala:85: warning: Unused import + import c._ // warn + ^ +warn-unused-imports.scala:91: warning: Unused import + import p1.c._ // warn + ^ +warn-unused-imports.scala:98: warning: Unused import + import p1._ // warn + ^ +warn-unused-imports.scala:118: warning: Unused import + import p1.A // warn + ^ +error: No warnings can be incurred under -Xfatal-warnings. +13 warnings found +one error found diff --git a/test/files/neg/warn-unused-imports.flags b/test/files/neg/warn-unused-imports.flags new file mode 100644 index 0000000000..954eaba352 --- /dev/null +++ b/test/files/neg/warn-unused-imports.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Xlint diff --git a/test/files/neg/warn-unused-imports.scala b/test/files/neg/warn-unused-imports.scala new file mode 100644 index 0000000000..b7a2f1c414 --- /dev/null +++ b/test/files/neg/warn-unused-imports.scala @@ -0,0 +1,125 @@ +class Bippo { + def length: Int = 123 + class Tree +} + +package object p1 { + class A + implicit class B(val s: String) { def bippy = s } + val c: Bippo = new Bippo + type D = String +} +package object p2 { + class A + implicit class B(val s: String) { def bippy = s } + val c: Bippo = new Bippo + type D = Int +} + +trait NoWarn { + { + import p1._ // no warn + println("abc".bippy) + } + + { + import p1._ // no warn + println(new A) + } + + { + import p1.B // no warn + println("abc".bippy) + } + + { + import p1._ // no warn + import c._ // no warn + println(length) + } + + { + import p1._ // no warn + import c._ // no warn + val x: Tree = null + println(x) + } + + { + import p1.D // no warn + val x: D = null + println(x) + } +} + +trait Warn { + { + import p1.A // warn + println(123) + } + + { + import p1.{ A, B } // warn on A + println("abc".bippy) + } + + { + import p1.{ A, B } // warn on both + println(123) + } + + { + import p1._ // no warn (technically this could warn, but not worth the effort to unroll unusedness transitively) + import c._ // warn + println(123) + } + + { + import p1._ // warn + println(123) + } + + { + class Tree + import p1._ // no warn + import c._ // warn + val x: Tree = null + println(x) + } + + { + import p1.c._ // warn + println(123) + } +} + +trait Nested { + { + import p1._ // warn + trait Warn { // warn about unused local trait for good measure + import p2._ + println(new A) + println("abc".bippy) + } + println("") + } + + { + import p1._ // no warn + trait NoWarn { + import p2.B // no warn + println("abc".bippy) + println(new A) + } + println(new NoWarn { }) + } + + { + import p1.A // warn + trait Warn { + import p2.A + println(new A) + } + println(new Warn { }) + } +} diff --git a/test/files/neg/warn-unused-privates.check b/test/files/neg/warn-unused-privates.check new file mode 100644 index 0000000000..9c41a33e8f --- /dev/null +++ b/test/files/neg/warn-unused-privates.check @@ -0,0 +1,63 @@ +warn-unused-privates.scala:2: warning: private constructor in class Bippy is never used + private def this(c: Int) = this(c, c) // warn + ^ +warn-unused-privates.scala:4: warning: private method in class Bippy is never used + private def boop(x: Int) = x+a+b // warn + ^ +warn-unused-privates.scala:6: warning: private val in class Bippy is never used + final private val MILLIS2: Int = 1000 // warn + ^ +warn-unused-privates.scala:13: warning: private val in object Bippy is never used + private val HEY_INSTANCE: Int = 1000 // warn + ^ +warn-unused-privates.scala:35: warning: private val in class Boppy is never used + private val hummer = "def" // warn + ^ +warn-unused-privates.scala:42: warning: private var in trait Accessors is never used + private var v1: Int = 0 // warn + ^ +warn-unused-privates.scala:43: warning: private setter in trait Accessors is never used + private var v2: Int = 0 // warn, never set + ^ +warn-unused-privates.scala:44: warning: private var in trait Accessors is never used + private var v3: Int = 0 // warn, never got + ^ +warn-unused-privates.scala:56: warning: private default argument in trait DefaultArgs is never used + private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 + ^ +warn-unused-privates.scala:56: warning: private default argument in trait DefaultArgs is never used + private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 + ^ +warn-unused-privates.scala:67: warning: local var in method f0 is never used + var x = 1 // warn + ^ +warn-unused-privates.scala:74: warning: local val in method f1 is never used + val b = new Outer // warn + ^ +warn-unused-privates.scala:84: warning: private object in object Types is never used + private object Dongo { def f = this } // warn + ^ +warn-unused-privates.scala:94: warning: local object in method l1 is never used + object HiObject { def f = this } // warn + ^ +warn-unused-privates.scala:78: warning: local var x in method f2 is never set - it could be a val + var x = 100 // warn about it being a var + ^ +warn-unused-privates.scala:85: warning: private class Bar1 in object Types is never used + private class Bar1 // warn + ^ +warn-unused-privates.scala:87: warning: private type Alias1 in object Types is never used + private type Alias1 = String // warn + ^ +warn-unused-privates.scala:95: warning: local class Hi is never used + class Hi { // warn + ^ +warn-unused-privates.scala:99: warning: local class DingDongDoobie is never used + class DingDongDoobie // warn + ^ +warn-unused-privates.scala:102: warning: local type OtherThing is never used + type OtherThing = String // warn + ^ +error: No warnings can be incurred under -Xfatal-warnings. +20 warnings found +one error found diff --git a/test/files/neg/warn-unused-privates.flags b/test/files/neg/warn-unused-privates.flags new file mode 100644 index 0000000000..7949c2afa2 --- /dev/null +++ b/test/files/neg/warn-unused-privates.flags @@ -0,0 +1 @@ +-Xlint -Xfatal-warnings diff --git a/test/files/neg/warn-unused-privates.scala b/test/files/neg/warn-unused-privates.scala new file mode 100644 index 0000000000..cb6e946a34 --- /dev/null +++ b/test/files/neg/warn-unused-privates.scala @@ -0,0 +1,105 @@ +class Bippy(a: Int, b: Int) { + private def this(c: Int) = this(c, c) // warn + private def bippy(x: Int): Int = bippy(x) // TODO: could warn + private def boop(x: Int) = x+a+b // warn + final private val MILLIS1 = 2000 // no warn, might have been inlined + final private val MILLIS2: Int = 1000 // warn + final private val HI_COMPANION: Int = 500 // no warn, accessed from companion + def hi() = Bippy.HI_INSTANCE +} +object Bippy { + def hi(x: Bippy) = x.HI_COMPANION + private val HI_INSTANCE: Int = 500 // no warn, accessed from instance + private val HEY_INSTANCE: Int = 1000 // warn +} + +class A(val msg: String) +class B1(msg: String) extends A(msg) +class B2(msg0: String) extends A(msg0) +class B3(msg0: String) extends A("msg") + +/*** Early defs warnings disabled primarily due to SI-6595. + * The test case is here to assure we aren't issuing false positives; + * the ones labeled "warn" don't warn. + ***/ +class Boppy extends { + private val hmm: String = "abc" // no warn, used in early defs + private val hom: String = "def" // no warn, used in body + private final val him = "ghi" // no warn, might have been (was) inlined + final val him2 = "ghi" // no warn, same + final val himinline = him + private val hum: String = "jkl" // warn + final val ding = hmm.length +} with Mutable { + val dinger = hom + private val hummer = "def" // warn + + private final val bum = "ghi" // no warn, might have been (was) inlined + final val bum2 = "ghi" // no warn, same +} + +trait Accessors { + private var v1: Int = 0 // warn + private var v2: Int = 0 // warn, never set + private var v3: Int = 0 // warn, never got + private var v4: Int = 0 // no warn + + def bippy(): Int = { + v3 = 5 + v4 = 6 + v2 + v4 + } +} + +trait DefaultArgs { + // warn about default getters for x2 and x3 + private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 + + def boppy() = bippy(5, 100, 200) +} + +class Outer { + class Inner +} + +trait Locals { + def f0 = { + var x = 1 // warn + var y = 2 + y = 3 + y + y + } + def f1 = { + val a = new Outer // no warn + val b = new Outer // warn + new a.Inner + } + def f2 = { + var x = 100 // warn about it being a var + x + } +} + +object Types { + private object Dongo { def f = this } // warn + private class Bar1 // warn + private class Bar2 // no warn + private type Alias1 = String // warn + private type Alias2 = String // no warn + def bippo = (new Bar2).toString + + def f(x: Alias2) = x.length + + def l1() = { + object HiObject { def f = this } // warn + class Hi { // warn + def f1: Hi = new Hi + def f2(x: Hi) = x + } + class DingDongDoobie // warn + class Bippy // no warn + type Something = Bippy // no warn + type OtherThing = String // warn + (new Bippy): Something + } +} diff --git a/test/files/pos/annotations.scala b/test/files/pos/annotations.scala index 706a715bad..501e2a6bd3 100644 --- a/test/files/pos/annotations.scala +++ b/test/files/pos/annotations.scala @@ -2,7 +2,7 @@ class ann(i: Int) extends scala.annotation.Annotation class cfann(x: String) extends annotation.ClassfileAnnotation // annotations on abstract types -abstract class C1[@serializable @cloneable +T, U, V[_]] +abstract class C1[@cloneable +T, U, V[_]] abstract class C2[@deprecated @ann(1) T <: Number, V] diff --git a/test/files/pos/attributes.scala b/test/files/pos/attributes.scala index ec735d0aae..60e00bff7d 100644 --- a/test/files/pos/attributes.scala +++ b/test/files/pos/attributes.scala @@ -1,3 +1,5 @@ +class serializable extends annotation.StaticAnnotation + @serializable class C1; @serializable @volatile class C2; @serializable @volatile class C3; diff --git a/test/files/pos/chang/Test.scala b/test/files/pos/chang/Test.scala index 9bb745e377..f74c6355b5 100644 --- a/test/files/pos/chang/Test.scala +++ b/test/files/pos/chang/Test.scala @@ -1,3 +1,3 @@ -object Test extends Application { +object Test extends App { new com.netgents.hello.Outer[String] } diff --git a/test/files/pos/classtag-pos.flags b/test/files/pos/classtag-pos.flags new file mode 100644 index 0000000000..281f0a10cd --- /dev/null +++ b/test/files/pos/classtag-pos.flags @@ -0,0 +1 @@ +-Yrangepos diff --git a/test/files/pos/classtag-pos.scala b/test/files/pos/classtag-pos.scala new file mode 100644 index 0000000000..768d2e27f4 --- /dev/null +++ b/test/files/pos/classtag-pos.scala @@ -0,0 +1,5 @@ +import scala.reflect.runtime.universe._ + +class A { + def f[T: TypeTag] = typeOf[T] match { case TypeRef(_, _, args) => args } +} diff --git a/test/files/pos/cycle-jsoup.flags b/test/files/pos/cycle-jsoup.flags new file mode 100644 index 0000000000..ca20f55172 --- /dev/null +++ b/test/files/pos/cycle-jsoup.flags @@ -0,0 +1 @@ +-Ybreak-cycles diff --git a/test/files/pos/cycle-jsoup.scala b/test/files/pos/cycle-jsoup.scala new file mode 100644 index 0000000000..879e693537 --- /dev/null +++ b/test/files/pos/cycle-jsoup.scala @@ -0,0 +1,5 @@ +object Test { + def main(args : Array[String]) { + org.jsoup.Jsoup.parse(null: java.net.URL, 3000) + } +} diff --git a/test/files/pos/cycle.flags b/test/files/pos/cycle.flags new file mode 100644 index 0000000000..ca20f55172 --- /dev/null +++ b/test/files/pos/cycle.flags @@ -0,0 +1 @@ +-Ybreak-cycles diff --git a/test/files/pos/cycle/J_1.java b/test/files/pos/cycle/J_1.java new file mode 100644 index 0000000000..0cc218eebe --- /dev/null +++ b/test/files/pos/cycle/J_1.java @@ -0,0 +1,16 @@ +package bar; + +public class J_1 { + public void f(C.D arg) { + } +} + +class B extends J_1 { + public void g(C.D arg) { + } +} + +class C extends B { + public class D { + } +} diff --git a/test/files/pos/cycle/X_2.scala b/test/files/pos/cycle/X_2.scala new file mode 100644 index 0000000000..c1840f3b99 --- /dev/null +++ b/test/files/pos/cycle/X_2.scala @@ -0,0 +1,3 @@ +import bar.J_1._ //<--- illegal cyclic reference involving + +class X diff --git a/test/pending/pos/exhaust_2.scala b/test/files/pos/exhaust_2.scala index 4f4e47c43b..4f4e47c43b 100644 --- a/test/pending/pos/exhaust_2.scala +++ b/test/files/pos/exhaust_2.scala diff --git a/test/files/pos/liftcode_polymorphic.scala b/test/files/pos/liftcode_polymorphic.scala index 8f537d278a..249f5a0569 100644 --- a/test/files/pos/liftcode_polymorphic.scala +++ b/test/files/pos/liftcode_polymorphic.scala @@ -1,6 +1,6 @@ import scala.reflect.runtime.universe._ -object Append extends Application { +object Append extends App { def append[A](l1: List[A], l2: List[A]):List[A] = l1 match { diff --git a/test/pending/pos/no-widen-locals.scala b/test/files/pos/no-widen-locals.scala index 013e63f0a2..013e63f0a2 100644 --- a/test/pending/pos/no-widen-locals.scala +++ b/test/files/pos/no-widen-locals.scala diff --git a/test/files/pos/sealed-final.flags b/test/files/pos/sealed-final.flags new file mode 100644 index 0000000000..cfabf7a5b4 --- /dev/null +++ b/test/files/pos/sealed-final.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Yinline-warnings -optimise
\ No newline at end of file diff --git a/test/files/pos/sealed-final.scala b/test/files/pos/sealed-final.scala new file mode 100644 index 0000000000..bdedb5c1f6 --- /dev/null +++ b/test/files/pos/sealed-final.scala @@ -0,0 +1,14 @@ +sealed abstract class Foo { + @inline def bar(x: Int) = x + 1 +} +object Foo { + def mkFoo(): Foo = new Baz2 +} + +object Baz1 extends Foo +final class Baz2 extends Foo + +object Test { + // bar should be inlined now + def f = Foo.mkFoo() bar 10 +} diff --git a/test/files/pos/spec-annotations.scala b/test/files/pos/spec-annotations.scala index 48281e5df5..6c1f737470 100644 --- a/test/files/pos/spec-annotations.scala +++ b/test/files/pos/spec-annotations.scala @@ -1,7 +1,7 @@ class ann(i: Int) extends scala.annotation.Annotation // annotations on abstract types -abstract class C1[@serializable @cloneable +T, U, V[_]] +abstract class C1[@cloneable +T, U, V[_]] abstract class C2[@deprecated @ann(1) T <: Number, V] diff --git a/test/files/pos/super.cmds b/test/files/pos/super.cmds deleted file mode 100644 index 8f3f8a4172..0000000000 --- a/test/files/pos/super.cmds +++ /dev/null @@ -1,2 +0,0 @@ -javac Super_1.java -scalac Super_2.scala diff --git a/test/files/pos/t0851.scala b/test/files/pos/t0851.scala new file mode 100644 index 0000000000..fc7109dcd4 --- /dev/null +++ b/test/files/pos/t0851.scala @@ -0,0 +1,14 @@ +package test + +object test1 { + case class Foo[T,T2](f : (T,T2) => String) extends (((T,T2)) => String){ + def apply(t : T) = (s:T2) => f(t,s) + def apply(p : (T,T2)) = f(p._1,p._2) + } + implicit def g[T](f : (T,String) => String) = Foo(f) + def main(args : Array[String]) : Unit = { + val f = (x:Int,s:String) => s + x + println(f(1)) + () + } +} diff --git a/test/files/pos/t0872.scala b/test/files/pos/t0872.scala new file mode 100644 index 0000000000..8f4c1c4436 --- /dev/null +++ b/test/files/pos/t0872.scala @@ -0,0 +1,8 @@ +object Main { + def main(args : Array[String]) { + val fn = (a : Int, str : String) => "a: " + a + ", str: " + str + implicit def fx[T](f : (T,String) => String) = (x:T) => f(x,null) + println(fn(1)) + () + } +} diff --git a/test/files/pos/t1029.cmds b/test/files/pos/t1029.cmds deleted file mode 100644 index 06b863dc03..0000000000 --- a/test/files/pos/t1029.cmds +++ /dev/null @@ -1,2 +0,0 @@ -scalac Test_1.scala -scalac Test_2.scala diff --git a/test/files/pos/t1107.scala b/test/files/pos/t1107a.scala index 0bf40bb4cc..0bf40bb4cc 100644 --- a/test/files/pos/t1107.scala +++ b/test/files/pos/t1107a.scala diff --git a/test/files/pos/t1203.scala b/test/files/pos/t1203a.scala index 062ef93fc6..062ef93fc6 100644 --- a/test/files/pos/t1203.scala +++ b/test/files/pos/t1203a.scala diff --git a/test/files/pos/t1230/S.scala b/test/files/pos/t1230/S.scala index f8a691b6de..530dd4b853 100644 --- a/test/files/pos/t1230/S.scala +++ b/test/files/pos/t1230/S.scala @@ -1 +1 @@ -object S extends Application { (new J).foo = 5 } +object S extends App { (new J).foo = 5 } diff --git a/test/files/pos/t1231/S.scala b/test/files/pos/t1231/S.scala index ee08866e04..f14aa2561b 100644 --- a/test/files/pos/t1231/S.scala +++ b/test/files/pos/t1231/S.scala @@ -1 +1 @@ -object S extends Application { println(J.j1) } +object S extends App { println(J.j1) } diff --git a/test/files/pos/t1385.scala b/test/files/pos/t1385.scala index 59953bcc39..6fe7308281 100644 --- a/test/files/pos/t1385.scala +++ b/test/files/pos/t1385.scala @@ -1,3 +1,3 @@ -@serializable object Test { - private def readResolve:AnyRef = this +object Test extends Serializable { + private def readResolve: AnyRef = this } diff --git a/test/pending/pos/t1751/A1_2.scala b/test/files/pos/t1751/A1_2.scala index 354d5eecd0..354d5eecd0 100644 --- a/test/pending/pos/t1751/A1_2.scala +++ b/test/files/pos/t1751/A1_2.scala diff --git a/test/pending/pos/t1751/A2_1.scala b/test/files/pos/t1751/A2_1.scala index c768062e43..c768062e43 100644 --- a/test/pending/pos/t1751/A2_1.scala +++ b/test/files/pos/t1751/A2_1.scala diff --git a/test/pending/pos/t1751/SuiteClasses.java b/test/files/pos/t1751/SuiteClasses.java index a415e4f572..a415e4f572 100644 --- a/test/pending/pos/t1751/SuiteClasses.java +++ b/test/files/pos/t1751/SuiteClasses.java diff --git a/test/pending/pos/t1782/Ann.java b/test/files/pos/t1782/Ann.java index 0dcfbd2ed7..0dcfbd2ed7 100644 --- a/test/pending/pos/t1782/Ann.java +++ b/test/files/pos/t1782/Ann.java diff --git a/test/pending/pos/t1782/Days.java b/test/files/pos/t1782/Days.java index 203a87b1c2..203a87b1c2 100644 --- a/test/pending/pos/t1782/Days.java +++ b/test/files/pos/t1782/Days.java diff --git a/test/pending/pos/t1782/ImplementedBy.java b/test/files/pos/t1782/ImplementedBy.java index 6aa8b4fa9e..6aa8b4fa9e 100644 --- a/test/pending/pos/t1782/ImplementedBy.java +++ b/test/files/pos/t1782/ImplementedBy.java diff --git a/test/pending/pos/t1782/Test_1.scala b/test/files/pos/t1782/Test_1.scala index 6467a74c29..6467a74c29 100644 --- a/test/pending/pos/t1782/Test_1.scala +++ b/test/files/pos/t1782/Test_1.scala diff --git a/test/files/pos/t1942.cmds b/test/files/pos/t1942.cmds deleted file mode 100644 index c14311042a..0000000000 --- a/test/files/pos/t1942.cmds +++ /dev/null @@ -1,2 +0,0 @@ -scalac A_1.scala -scalac Test_2.scala diff --git a/test/files/pos/t2464.cmds b/test/files/pos/t2464.cmds deleted file mode 100644 index ca733ef23d..0000000000 --- a/test/files/pos/t2464.cmds +++ /dev/null @@ -1,3 +0,0 @@ -javac JavaOne.java -scalac ScalaOne_1.scala -scalac t2464_2.scala diff --git a/test/files/pos/t2726.cmds b/test/files/pos/t2726.cmds deleted file mode 100644 index 5fcb18bfbb..0000000000 --- a/test/files/pos/t2726.cmds +++ /dev/null @@ -1,2 +0,0 @@ -scalac SQLBuilder_1.scala -scalac test_2.scala diff --git a/test/pending/pos/t294/Ann.java b/test/files/pos/t294/Ann.java index 934ca46297..934ca46297 100644 --- a/test/pending/pos/t294/Ann.java +++ b/test/files/pos/t294/Ann.java diff --git a/test/pending/pos/t294/Ann2.java b/test/files/pos/t294/Ann2.java index 025b79e794..025b79e794 100644 --- a/test/pending/pos/t294/Ann2.java +++ b/test/files/pos/t294/Ann2.java diff --git a/test/pending/pos/t294/Test_1.scala b/test/files/pos/t294/Test_1.scala index ff1f34b10e..ff1f34b10e 100644 --- a/test/pending/pos/t294/Test_1.scala +++ b/test/files/pos/t294/Test_1.scala diff --git a/test/pending/pos/t294/Test_2.scala b/test/files/pos/t294/Test_2.scala index 9fb1c6e175..9fb1c6e175 100644 --- a/test/pending/pos/t294/Test_2.scala +++ b/test/files/pos/t294/Test_2.scala diff --git a/test/files/pos/t3160.scala b/test/files/pos/t3160.scala new file mode 100644 index 0000000000..3309ece160 --- /dev/null +++ b/test/files/pos/t3160.scala @@ -0,0 +1,6 @@ +import scala.collection.mutable._ +import scala.xml._ + +class A { + def f(x: Node): Node = ??? +} diff --git a/test/files/pos/t3577.scala b/test/files/pos/t3577.scala new file mode 100644 index 0000000000..80a280f67a --- /dev/null +++ b/test/files/pos/t3577.scala @@ -0,0 +1,29 @@ +case class Check[A](val value: A) + +case class C2(checks: Check[_]*); + +object C { + def m(x : C2): Any = (null: Any) match { + case C2(_, rest @ _*) => { + rest.map(_.value) + } + } +} + +/////////////////// + +object Container { + trait Exp[+T] + abstract class FuncExp[-S, +T] + + sealed abstract class FoundNode[T, Repr] { + def optimize[TupleT, U, That](parentNode: FlatMap[T, Repr, U, That]): Any + def optimize2[TupleT, U, That](parentNode: Any): Any + } + + class FlatMap[T, Repr, U, That] + + val Seq(fn: FoundNode[t, repr]) = Seq[FoundNode[_, _]]() + fn.optimize(null) // was: scala.MatchError: ? (of class BoundedWildcardType) @ Variances#varianceInType + fn.optimize2(null) // was: fatal error: bad type: ?(class scala.reflect.internal.Types$BoundedWildcardType) @ Pickle.putType +} diff --git a/test/files/pos/t4649.flags b/test/files/pos/t4649.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t4649.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/pending/pos/t4649.scala b/test/files/pos/t4649.scala index 0d6caa8d7a..0d6caa8d7a 100644 --- a/test/pending/pos/t4649.scala +++ b/test/files/pos/t4649.scala diff --git a/test/files/pos/t4744.flags b/test/files/pos/t4744.flags new file mode 100644 index 0000000000..ca20f55172 --- /dev/null +++ b/test/files/pos/t4744.flags @@ -0,0 +1 @@ +-Ybreak-cycles diff --git a/test/files/pos/t4744/Bar.scala b/test/files/pos/t4744/Bar.scala new file mode 100644 index 0000000000..1fb6d78973 --- /dev/null +++ b/test/files/pos/t4744/Bar.scala @@ -0,0 +1 @@ +class Bar { val quux = new Foo[java.lang.Integer]() } diff --git a/test/files/pos/t4744/Foo.java b/test/files/pos/t4744/Foo.java new file mode 100644 index 0000000000..6c764d0470 --- /dev/null +++ b/test/files/pos/t4744/Foo.java @@ -0,0 +1 @@ +public class Foo<T extends Comparable<? super T>> {} diff --git a/test/pending/pos/t4786.scala b/test/files/pos/t4786.scala index f0579142b8..f0579142b8 100644 --- a/test/pending/pos/t4786.scala +++ b/test/files/pos/t4786.scala diff --git a/test/files/pos/t5130.scala b/test/files/pos/t5130.scala new file mode 100644 index 0000000000..676d3c7050 --- /dev/null +++ b/test/files/pos/t5130.scala @@ -0,0 +1,46 @@ +import scala.language.reflectiveCalls + +class A { + this_a => + + def b = new B + class B { def a: this_a.type = this_a } +} +trait A2 { def c = () } + +object Test { + val v1 = new A { def c = () } + val v2 = new A with A2 { } + val v3: A { def c: Unit } = null + def d1 = new A { def c = () } + def d2 = new A with A2 { } + def d3: A { def c: Unit } = null + var x1 = new A { def c = () } + var x2 = new A with A2 { } + var x3: A { def c: Unit } = null + + def main(args: Array[String]): Unit = { + val mv1 = new A { def c = () } + val mv2 = new A with A2 { } + val mv3: A { def c: Unit } = null + def md1 = new A { def c = () } + def md2 = new A with A2 { } + def md3: A { def c: Unit } = null + + v1.b.a.c + v2.b.a.c + v3.b.a.c + d1.b.a.c + d2.b.a.c + d3.b.a.c + x1.b.a.c + x2.b.a.c + x3.b.a.c + mv1.b.a.c + mv2.b.a.c + mv3.b.a.c + md1.b.a.c + md2.b.a.c + md3.b.a.c + } +} diff --git a/test/pending/pos/t5399a.scala b/test/files/pos/t5399a.scala index 4ebd85ad03..4ebd85ad03 100644 --- a/test/pending/pos/t5399a.scala +++ b/test/files/pos/t5399a.scala diff --git a/test/files/pos/t5604b/T_1.scala b/test/files/pos/t5604b/T_1.scala new file mode 100644 index 0000000000..179dcb10c6 --- /dev/null +++ b/test/files/pos/t5604b/T_1.scala @@ -0,0 +1,6 @@ +// sandbox/t5604/T.scala +package t6504 + +trait T { + def foo: Boolean = false +} diff --git a/test/files/pos/t5604b/T_2.scala b/test/files/pos/t5604b/T_2.scala new file mode 100644 index 0000000000..179dcb10c6 --- /dev/null +++ b/test/files/pos/t5604b/T_2.scala @@ -0,0 +1,6 @@ +// sandbox/t5604/T.scala +package t6504 + +trait T { + def foo: Boolean = false +} diff --git a/test/files/pos/t5604b/Test_1.scala b/test/files/pos/t5604b/Test_1.scala new file mode 100644 index 0000000000..f7c58ebe83 --- /dev/null +++ b/test/files/pos/t5604b/Test_1.scala @@ -0,0 +1,7 @@ +// sandbox/t5604/Test.scala +package t6504 + +object Test { + def blerg1(a: Any): Any = if (foo) blerg1(0) + def blerg2(a: Any): Any = if (t6504.foo) blerg2(0) +} diff --git a/test/files/pos/t5604b/Test_2.scala b/test/files/pos/t5604b/Test_2.scala new file mode 100644 index 0000000000..f7c58ebe83 --- /dev/null +++ b/test/files/pos/t5604b/Test_2.scala @@ -0,0 +1,7 @@ +// sandbox/t5604/Test.scala +package t6504 + +object Test { + def blerg1(a: Any): Any = if (foo) blerg1(0) + def blerg2(a: Any): Any = if (t6504.foo) blerg2(0) +} diff --git a/test/files/pos/t5604b/pack_1.scala b/test/files/pos/t5604b/pack_1.scala new file mode 100644 index 0000000000..f50d568bfa --- /dev/null +++ b/test/files/pos/t5604b/pack_1.scala @@ -0,0 +1,5 @@ +// sandbox/t5604/pack.scala +package t6504 + +object `package` extends T { +} diff --git a/test/pending/pos/t5606.scala b/test/files/pos/t5606.scala index 2545271e32..2545271e32 100644 --- a/test/pending/pos/t5606.scala +++ b/test/files/pos/t5606.scala diff --git a/test/pending/pos/t5639/Bar.scala b/test/files/pos/t5639/Bar.scala index f577500acd..f577500acd 100644 --- a/test/pending/pos/t5639/Bar.scala +++ b/test/files/pos/t5639/Bar.scala diff --git a/test/pending/pos/t5639/Foo.scala b/test/files/pos/t5639/Foo.scala index 6602150661..6602150661 100644 --- a/test/pending/pos/t5639/Foo.scala +++ b/test/files/pos/t5639/Foo.scala diff --git a/test/files/pos/t5809.scala b/test/files/pos/t5809.scala index 133e13c4ed..4bcd743faa 100644 --- a/test/files/pos/t5809.scala +++ b/test/files/pos/t5809.scala @@ -1,5 +1,6 @@ package object foo { implicit class PimpedInt(foo: Int) { def bar = ??? + def bippy = foo } -}
\ No newline at end of file +} diff --git a/test/files/pos/t5859.scala b/test/files/pos/t5859.scala new file mode 100644 index 0000000000..2a31e68ee5 --- /dev/null +++ b/test/files/pos/t5859.scala @@ -0,0 +1,15 @@ + +class A { + def f(xs: List[Int], ys: AnyRef*) = () + def f(xs: AnyRef*) = () + + f() + f(List[AnyRef](): _*) + f(List(): _*) + f(Nil: _*) + f(Array(): _*) + f(Array[AnyRef](): _*) + f(List(1)) + f(List(1), Nil: _*) + f(List(1), Array(): _*) +} diff --git a/test/files/pos/t6072.scala b/test/files/pos/t6072.scala new file mode 100644 index 0000000000..e25ebbffc5 --- /dev/null +++ b/test/files/pos/t6072.scala @@ -0,0 +1,3 @@ +class A { + object B { def eq(lvl: Int) = ??? } +} diff --git a/test/files/pos/t6301.scala b/test/files/pos/t6301.scala new file mode 100644 index 0000000000..fa81bbfa77 --- /dev/null +++ b/test/files/pos/t6301.scala @@ -0,0 +1,9 @@ +trait LoadedOver[@specialized(Int) A] { + def foo(x: Any): A + def foo(xs: String): A +} + +object Test { + def loaded: AnyRef with LoadedOver[Int] = sys.error("") + loaded.foo("") +} diff --git a/test/files/pos/t640.scala b/test/files/pos/t640.scala index 55f61df8af..45608bc3d4 100644 --- a/test/files/pos/t640.scala +++ b/test/files/pos/t640.scala @@ -1,2 +1,2 @@ -@serializable class A -@serializable class B extends A +class A extends Serializable +class B extends A with Serializable diff --git a/test/files/pos/t6447.scala b/test/files/pos/t6447.scala new file mode 100644 index 0000000000..1c0c0f2a31 --- /dev/null +++ b/test/files/pos/t6447.scala @@ -0,0 +1,18 @@ +import scala.language.experimental.macros +import scala.reflect.macros.Context + +class X { type T } + +object X { + // this works + def foo(x: X): x.T = macro fooImpl + def fooImpl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ??? + + // this doesn't + def bar(x: X, y: X): (x.T, y.T) = macro barImpl + def barImpl(c: Context)(x: c.Expr[X], y: c.Expr[X]): c.Expr[(x.value.T, y.value.T)] = ??? + + // neither does this + def baz(x: X)(xs: List[x.T]): Unit = macro bazImpl + def bazImpl(c: Context)(x: c.Expr[X])(xs: c.Expr[List[x.value.T]]): c.Expr[Unit] = ??? +} diff --git a/test/files/pos/t6482.scala b/test/files/pos/t6482.scala new file mode 100644 index 0000000000..24ea38e519 --- /dev/null +++ b/test/files/pos/t6482.scala @@ -0,0 +1,11 @@ +final class TraversableOnceOps[+A](val collection: TraversableOnce[A]) extends AnyVal { + def reduceLeftOption[B >: A](op: (B, A) => B): Option[B] = + if (collection.isEmpty) None else Some(collection.reduceLeft[B](op)) +} +// error: type arguments [B] do not conform to method reduceLeft's type parameter bounds [B >: A] +// if (collection.isEmpty) None else Some(collection.reduceLeft[B](op)) +// ^ + +class Foo[+A <: AnyRef](val xs: List[A]) extends AnyVal { + def baz[B >: A](x: B): List[B] = x :: xs +} diff --git a/test/files/pos/t6664.scala b/test/files/pos/t6664.scala new file mode 100644 index 0000000000..7eb85f619d --- /dev/null +++ b/test/files/pos/t6664.scala @@ -0,0 +1,4 @@ +final case class A(i: Int, s: String) { + protected def copy(s2: String): A = A(i, s2) + protected def copy(i2: Int): A = A(i2, s) +} diff --git a/test/files/pos/t6664b.scala b/test/files/pos/t6664b.scala new file mode 100644 index 0000000000..a622866838 --- /dev/null +++ b/test/files/pos/t6664b.scala @@ -0,0 +1,5 @@ +object T { + def A(s: String): A = new A(3, s) + def A(i: Int): A = A(i, "abc") + case class A(i: Int, s: String) +} diff --git a/test/files/pos/t715.cmds b/test/files/pos/t715.cmds deleted file mode 100644 index 2836967fca..0000000000 --- a/test/files/pos/t715.cmds +++ /dev/null @@ -1,2 +0,0 @@ -scalac meredith_1.scala -scalac runner_2.scala diff --git a/test/files/pos/t715/meredith_1.scala b/test/files/pos/t715/meredith_1.scala index 8261b9881a..c28afb4a9b 100644 --- a/test/files/pos/t715/meredith_1.scala +++ b/test/files/pos/t715/meredith_1.scala @@ -3,7 +3,7 @@ package com.sap.dspace.model.othello; import scala.xml._ trait XMLRenderer { - type T <: Any {def getClass() : java.lang.Class[_]} + type T <: Any {def getClass(): java.lang.Class[_]} val valueTypes = List( classOf[java.lang.Boolean], @@ -14,21 +14,21 @@ trait XMLRenderer { ) def value2XML( - value : Object, - field : java.lang.reflect.Field, - pojo : T - ) : Node = { + value: Object, + field: java.lang.reflect.Field, + pojo: T + ): Node = { value match { - case null => Text( "null" ) + case null => Text("null") case vUnmatched => if (value.isInstanceOf[java.lang.Boolean]) - Text( value.asInstanceOf[java.lang.Boolean].toString ) + Text(value.asInstanceOf[java.lang.Boolean].toString) else if (value.isInstanceOf[java.lang.Integer]) - Text( value.asInstanceOf[java.lang.Integer].toString ) + Text(value.asInstanceOf[java.lang.Integer].toString) else if (value.isInstanceOf[java.lang.Float]) - Text( value.asInstanceOf[java.lang.Float].toString ) + Text(value.asInstanceOf[java.lang.Float].toString) // else if (value.isInstanceOf[T]) - // pojo2XML( value.asInstanceOf[T] ) + // pojo2XML(value.asInstanceOf[T]) else <unmatchedType> <theType> @@ -42,16 +42,16 @@ trait XMLRenderer { } def field2XML( - field : java.lang.reflect.Field, - pojo : T - ) : Elem = { + field: java.lang.reflect.Field, + pojo: T + ): Elem = { - val accessible = field.isAccessible; - field.setAccessible( true ); + val accessible = field.isAccessible + field.setAccessible(true) // BUGBUG lgm need to disambiguate on type and possibly make // recursive call to pojo2XML - val fldValXML = value2XML( field.get( pojo ), field, pojo ); - field.setAccessible( accessible ); + val fldValXML = value2XML(field.get( pojo ), field, pojo) + field.setAccessible( accessible ) Elem( null, @@ -62,37 +62,37 @@ trait XMLRenderer { ) } - def pojo2XML( pojo : T ) : Elem = { + def pojo2XML(pojo: T): Elem = { val progeny = for (field <- pojo.getClass.getDeclaredFields) - yield field2XML( field, pojo ); + yield field2XML(field, pojo) Elem( null, pojo.getClass.getName, null, TopScope, - progeny.asInstanceOf[Array[scala.xml.Node]] : _* + progeny.asInstanceOf[Array[scala.xml.Node]]: _* ) } } -case class POJO2XMLRenderer( recurse : Boolean ) +case class POJO2XMLRenderer(recurse: Boolean) extends XMLRenderer { type T = java.io.Serializable override def value2XML( - value : Object, - field : java.lang.reflect.Field, - pojo : java.io.Serializable - ) : Node = { - if (recurse) super.value2XML( value, field, pojo ) - else Text( value + "" ) + value: Object, + field: java.lang.reflect.Field, + pojo: java.io.Serializable + ): Node = { + if (recurse) super.value2XML(value, field, pojo) + else Text(value + "") } } -object thePOJO2XMLRenderer extends POJO2XMLRenderer( true ) { +object thePOJO2XMLRenderer extends POJO2XMLRenderer(true) { } -object Test extends Application { +object Test extends App { println(com.sap.dspace.model.othello.thePOJO2XMLRenderer) } diff --git a/test/files/pos/t715/runner_2.scala b/test/files/pos/t715/runner_2.scala index 1e4f40d654..d54805629a 100644 --- a/test/files/pos/t715/runner_2.scala +++ b/test/files/pos/t715/runner_2.scala @@ -1,3 +1,3 @@ -object Test extends Application { +object Test extends App { println(com.sap.dspace.model.othello.thePOJO2XMLRenderer) } diff --git a/test/files/pos/ticket2251.scala b/test/files/pos/ticket2251.scala index b3afee4ea9..c220e85350 100644 --- a/test/files/pos/ticket2251.scala +++ b/test/files/pos/ticket2251.scala @@ -22,4 +22,18 @@ lub of List(D, C) is B[_2] forSome { type _2 >: D with C{} <: B[_1] forSome { ty // should be: B[X] forSome {type X <: B[X]} -- can this be done automatically? for now, just detect f-bounded polymorphism and fall back to more coarse approximation val data: List[A] = List(new C, new D) + + val data2 = List(new C, new D) + + val data3: List[B[X] forSome { type X <: B[_ <: A] }] = List(new C, new D) + + // Not yet -- + // val data4: List[B[X] forSome { type X <: B[X] }] = List(new C, new D) + // <console>:7: error: type mismatch; + // found : List[B[_ >: D with C <: B[_ >: D with C <: A]]] + // required: List[B[X] forSome { type X <: B[X] }] + // val data4: List[B[X] forSome { type X <: B[X] }] = List(new C, new D) + + // works + val data5 = List[B[X] forSome { type X <: B[X] }](new C, new D) } diff --git a/test/files/presentation/ide-bug-1000531.check b/test/files/presentation/ide-bug-1000531.check index 4be98a6b21..6c3892d272 100644 --- a/test/files/presentation/ide-bug-1000531.check +++ b/test/files/presentation/ide-bug-1000531.check @@ -19,7 +19,7 @@ retrieved 126 members [accessible: true] `method addString(b: StringBuilder)StringBuilder` [accessible: true] `method addString(b: StringBuilder, sep: String)StringBuilder` [accessible: true] `method addString(b: StringBuilder, start: String, sep: String, end: String)StringBuilder` -[accessible: true] `method aggregate[B](z: B)(seqop: (B, B) => B, combop: (B, B) => B)B` +[accessible: true] `method aggregate[B](z: => B)(seqop: (B, B) => B, combop: (B, B) => B)B` [accessible: true] `method asInstanceOf[T0]=> T0` [accessible: true] `method buffered=> scala.collection.BufferedIterator[B]` [accessible: true] `method collectFirst[B](pf: PartialFunction[B,B])Option[B]` diff --git a/test/files/run/collection-stacks.check b/test/files/run/collection-stacks.check new file mode 100644 index 0000000000..aa25cd1fa6 --- /dev/null +++ b/test/files/run/collection-stacks.check @@ -0,0 +1,14 @@ +3-2-1: true +3-2-1: true +apply +3: true +3: true +1: true +1: true +top +3: true +3: true +pop +2-1: true +3: true +2-1: true diff --git a/test/files/run/collection-stacks.scala b/test/files/run/collection-stacks.scala new file mode 100644 index 0000000000..be9fbbf1ae --- /dev/null +++ b/test/files/run/collection-stacks.scala @@ -0,0 +1,38 @@ +import scala.collection.{ immutable, mutable } + +object Test extends App { + def mutableStack[T](xs: T*): mutable.Stack[T] = { + val s = new mutable.Stack[T] + s.pushAll(xs) + s + } + + def immutableStack[T](xs: T*): immutable.Stack[T] = { + immutable.Stack.empty[T] pushAll xs + } + + def check[T](expected: T, got: T) { + println(got + ": " + (expected == got)) + } + + // check #957 + check("3-2-1", immutableStack(1, 2, 3).iterator.mkString("-")) + check("3-2-1", mutableStack(1, 2, 3).iterator.mkString("-")) + + println("apply") + check(3, immutableStack(1, 2, 3).apply(0)) + check(3, mutableStack(1, 2, 3).apply(0)) + check(1, immutableStack(1, 2, 3).apply(2)) + check(1, mutableStack(1, 2, 3).apply(2)) + + println("top") + check(3, immutableStack(1, 2, 3).top) + check(3, mutableStack(1, 2, 3).top) + + println("pop") + check("2-1", immutableStack(1, 2, 3).pop.mkString("-")) + check(3, mutableStack(1, 2, 3).pop()) + check("2-1", { val s = mutableStack(1, 2, 3); s.pop(); s.toList.mkString("-") }) +} + +// vim: set ts=2 sw=2 et: diff --git a/test/files/run/compiler-asSeenFrom.scala b/test/files/run/compiler-asSeenFrom.scala index 19feb45101..0d4b504d3c 100644 --- a/test/files/run/compiler-asSeenFrom.scala +++ b/test/files/run/compiler-asSeenFrom.scala @@ -47,10 +47,10 @@ package ll { for (p <- typeRefPrefixes ; c <- classes filter (isPossibleEnclosure(p.typeSymbol, _)) ; a <- targs) yield typeRef(p, c, List(a)) ) - + val wfmt = "%-" + 25 + "s" def to_s(x: Any): String = wfmt.format(x.toString.replaceAll("""\bll\.""", "")) - + def fmt(args: Any*): String = { (args map to_s mkString " ").replaceAll("""\s+$""", "") } @@ -61,7 +61,7 @@ package ll { } def permuteAsSeenFrom(targs: List[Type]) = ( - for { + for { tp <- typeRefs(targs filterNot (_ eq NoType)) prefix <- asSeenPrefixes if tp.prefix != prefix @@ -72,11 +72,11 @@ package ll { } yield ((site, tp, prefix, seen)) ) - + def block(label: Any)(lines: List[String]): List[String] = { val first = "" + label + " {" val last = "}" - + first +: lines.map(" " + _) :+ last } @@ -84,7 +84,7 @@ package ll { permuteAsSeenFrom(targs).groupBy(_._1).toList.sortBy(_._1.toString) flatMap { case (site, xs) => block(fmt(site)) { - fmt("type", "seen from prefix", "is") :: + fmt("type", "seen from prefix", "is") :: fmt("----", "----------------", "--") :: { xs.groupBy(_._2).toList.sortBy(_._1.toString) flatMap { case (tp, ys) => @@ -95,7 +95,7 @@ package ll { } } } - + def pretty(xs: List[_]) = if (xs.isEmpty) "" else xs.mkString("\n ", "\n ", "\n") def signaturesIn(info: Type): List[String] = ( @@ -103,11 +103,11 @@ package ll { filterNot (s => s.isType || s.owner == ObjectClass || s.owner == AnyClass || s.isConstructor) map (_.defString) ) - + def check(source: String, unit: global.CompilationUnit) = { import syms._ - afterTyper { + exitingTyper { val typeArgs = List[Type](IntClass.tpe, ListClass[Int]) ++ tparams.map(_.tpe) permute(typeArgs) foreach println } diff --git a/test/files/run/constant-type.check b/test/files/run/constant-type.check index dfd8be5297..4eededb8ba 100644 --- a/test/files/run/constant-type.check +++ b/test/files/run/constant-type.check @@ -13,16 +13,16 @@ scala> :power scala> val s = transformedType(StringClass.toType).asInstanceOf[Type] s: $r.intp.global.Type = String -scala> { println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } +scala> { println(exitingPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } Class[String](classOf[java.lang.String]) -scala> { afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } +scala> { exitingPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } Class(classOf[java.lang.String]) -scala> { ConstantType(Constant(s)); println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } +scala> { ConstantType(Constant(s)); println(exitingPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } Class[String](classOf[java.lang.String]) -scala> { ConstantType(Constant(s)); afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } +scala> { ConstantType(Constant(s)); exitingPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } Class(classOf[java.lang.String]) scala> diff --git a/test/files/run/constant-type.scala b/test/files/run/constant-type.scala index 84539e2895..373746af4a 100644 --- a/test/files/run/constant-type.scala +++ b/test/files/run/constant-type.scala @@ -9,9 +9,9 @@ object Test extends ReplTest { def code = """ :power val s = transformedType(StringClass.toType).asInstanceOf[Type] -{ println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } -{ afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } -{ ConstantType(Constant(s)); println(afterPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } -{ ConstantType(Constant(s)); afterPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } +{ println(exitingPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))) } +{ exitingPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))) } +{ ConstantType(Constant(s)); println(exitingPhase(currentRun.erasurePhase)(ConstantType(Constant(s)))); } +{ ConstantType(Constant(s)); exitingPhase(currentRun.erasurePhase)(println(ConstantType(Constant(s)))); } """ } diff --git a/test/files/run/deeps.check b/test/files/run/deeps.check new file mode 100644 index 0000000000..a68e474f62 --- /dev/null +++ b/test/files/run/deeps.check @@ -0,0 +1,87 @@ +testEquals1 +false +false +true + +testEquals2 +false +false +true + +testEquals3 +x=Array(1) +y=Array(1) +false +false +true + +x=Array(Array(1), Array(1)) +y=Array(Array(1), Array(1)) +false +false +true + +x=Array(Array(Array(1), Array(1)), Array(Array(1), Array(1))) +y=Array(Array(Array(1), Array(1)), Array(Array(1), Array(1))) +false +false +true + +testEquals4 +false +false +true +false +false +true +Array(true, false) +Array(true, false) +[true;false] +true;false + +Array(Array(true, false), Array(true, false)) +Array(Array(true, false), Array(true, false)) +[Array(true, false);Array(true, false)] +Array(true, false);Array(true, false) + +Array(Array(Array(true, false), Array(true, false)), Array(Array(true, false), Array(true, false))) +Array(Array(Array(true, false), Array(true, false)), Array(Array(true, false), Array(true, false))) +[Array(Array(true, false), Array(true, false));Array(Array(true, false), Array(true, false))] +Array(Array(true, false), Array(true, false));Array(Array(true, false), Array(true, false)) + +Array(1.0, 0.0) +Array(1.0, 0.0) +[1.0;0.0] +1.0;0.0 + +Array(Array(1.0, 0.0), Array(1.0, 0.0)) +Array(Array(1.0, 0.0), Array(1.0, 0.0)) +[Array(1.0, 0.0);Array(1.0, 0.0)] +Array(1.0, 0.0);Array(1.0, 0.0) + +Array(Array(Array(1.0, 0.0), Array(1.0, 0.0)), Array(Array(1.0, 0.0), Array(1.0, 0.0))) +Array(Array(Array(1.0, 0.0), Array(1.0, 0.0)), Array(Array(1.0, 0.0), Array(1.0, 0.0))) +[Array(Array(1.0, 0.0), Array(1.0, 0.0));Array(Array(1.0, 0.0), Array(1.0, 0.0))] +Array(Array(1.0, 0.0), Array(1.0, 0.0));Array(Array(1.0, 0.0), Array(1.0, 0.0)) + +Array(a, b) +Array(a, b) +[a;b] +a;b + +Array(Array(a, b), Array(a, b)) +Array(Array(a, b), Array(a, b)) +[Array(a, b);Array(a, b)] +Array(a, b);Array(a, b) + +Array(Array(Array(a, b), Array(a, b)), Array(Array(a, b), Array(a, b))) +Array(Array(Array(a, b), Array(a, b)), Array(Array(a, b), Array(a, b))) +[Array(Array(a, b), Array(a, b));Array(Array(a, b), Array(a, b))] +Array(Array(a, b), Array(a, b));Array(Array(a, b), Array(a, b)) + +[Array(true, false); Array(false)] +[Array(1, 2); Array(3)] +[Array(1, 2); Array(3)] + +Array(boo, and, foo) +Array(a) diff --git a/test/files/run/deeps.scala b/test/files/run/deeps.scala new file mode 100644 index 0000000000..6049cc6024 --- /dev/null +++ b/test/files/run/deeps.scala @@ -0,0 +1,114 @@ +//############################################################################ +// deepEquals / deep.toString +//############################################################################ + +//############################################################################ +// need to revisit array equqality +object Test { + + def testEquals1 { + println(Array(1) == Array(1)) + println(Array(1) equals Array(1)) + println(Array(1).deep == Array(1).deep) + println + } + + def testEquals2 { + println(Array(Array(1), Array(2)) == Array(Array(1), Array(2))) + println(Array(Array(1), Array(2)) equals Array(Array(1), Array(2))) + println(Array(Array(1), Array(2)).deep equals Array(Array(1), Array(2)).deep) + println + } + + def testEquals3 { + val a1 = Array(1) + val b1 = Array(1) + val a2 = Array(a1, b1) + val b2 = Array(a1, b1) + val a3 = Array(a2, b2) + val b3 = Array(a2, b2) + def test[T](x: Array[T], y: Array[T]) { + println("x=" + x.deep.toString) + println("y=" + y.deep.toString) + println(x == y) + println(x equals y) + println(x.deep == y.deep) + println + } + test(a1, b1) + test(a2, b2) + test(a3, b3) + } + + def testEquals4 { + println("boo:and:foo".split(':') == "boo:and:foo".split(':')) + println("boo:and:foo".split(':') equals "boo:and:foo".split(':')) + println("boo:and:foo".split(':').deep == "boo:and:foo".split(':').deep) + + val xs = new java.util.ArrayList[String](); xs.add("a") + val ys = new java.util.ArrayList[String](); ys.add("a") + println(xs.toArray == ys.toArray) + println(xs.toArray equals ys.toArray) + println(xs.toArray.deep == ys.toArray.deep) + } + + def testToString1 { + def sweep(s: String) = ( + s.replaceAll("D@[0-9a-fA-F]+", "D@0000000") + .replaceAll("Z@[0-9a-fA-F]+", "Z@0000000") + .replaceAll(";@[0-9a-fA-F]+", ";@0000000") + ) + def test[T](a: Array[T]) { + println(sweep(a.deep.toString)) + println(a.deep.toString) + println(a.deep.mkString("[", ";", "]")) + println(a.deep.mkString(";")) + println + } + + val ba1 = Array(true, false) + val ba2 = Array(ba1, ba1) + val ba3 = Array(ba2, ba2) + test(ba1) + test(ba2) + test(ba3) + + val da1 = Array(1.0d, 0.0d) + val da2 = Array(da1, da1) + val da3 = Array(da2, da2) + test(da1) + test(da2) + test(da3) + + val sa1 = Array("a", "b") + val sa2 = Array(sa1, sa1) + val sa3 = Array(sa2, sa2) + test(sa1) + test(sa2) + test(sa3) + } + + def testToString2 { + println(Array(Array(true, false), Array(false)).deep.mkString("[", "; ", "]")) + println(Array(Array('1', '2'), Array('3')).deep.mkString("[", "; ", "]")) + println(Array(Array(1, 2), Array(3)).deep.mkString("[", "; ", "]")) + println + } + + def testToString3 { + println("boo:and:foo".split(':').deep.toString) + + val xs = new java.util.ArrayList[String](); xs.add("a") + println(xs.toArray.deep.toString) + } + + def main(args: Array[String]): Unit = { + println("testEquals1") ; testEquals1 + println("testEquals2") ; testEquals2 + println("testEquals3") ; testEquals3 + println("testEquals4") ; testEquals4 + testToString1 + testToString2 + testToString3 + } +} diff --git a/test/files/run/existentials-in-compiler.scala b/test/files/run/existentials-in-compiler.scala index c69d1217fd..14c25849cb 100644 --- a/test/files/run/existentials-in-compiler.scala +++ b/test/files/run/existentials-in-compiler.scala @@ -73,7 +73,7 @@ package extest { def check(source: String, unit: global.CompilationUnit) = { getRequiredPackage("extest").moduleClass.info.decls.toList.filter(_.isType).map(_.initialize).sortBy(_.name.toString) foreach { clazz => - afterTyper { + exitingTyper { clazz.info println(clazz.defString) println(" " + classExistentialType(clazz) + "\n") diff --git a/test/files/run/lub-visibility.check b/test/files/run/lub-visibility.check index 3461d1bf6b..f3a6bef215 100644 --- a/test/files/run/lub-visibility.check +++ b/test/files/run/lub-visibility.check @@ -8,7 +8,7 @@ scala> // should infer List[scala.collection.immutable.Seq[Nothing]] scala> // but reverted that for SI-5534. scala> val x = List(List(), Vector()) -x: List[scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq{def dropRight(n: Int): scala.collection.immutable.Seq[Any] with scala.collection.AbstractSeq[Any]; def takeRight(n: Int): scala.collection.immutable.Seq[Any] with scala.collection.AbstractSeq[Any]; def drop(n: Int): scala.collection.immutable.Seq[Any] with scala.collection.AbstractSeq[Any]; def take(n: Int): scala.collection.immutable.Seq[Any] with scala.collection.AbstractSeq[Any]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[Any] with scala.collection.AbstractSeq[Any]}]; def dropRight(n: Int): scala.collection.immutable.Seq[Nothing] with scala.collection.Ab... +x: List[scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]{def dropRight(n: Int): scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]; def takeRight(n: Int): scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing]; def drop(n: Int): scala.collecti... scala> scala> diff --git a/test/files/run/parserJavaIdent.check b/test/files/run/parserJavaIdent.check new file mode 100644 index 0000000000..597ddbee47 --- /dev/null +++ b/test/files/run/parserJavaIdent.check @@ -0,0 +1,26 @@ +[1.7] parsed: simple +[1.8] parsed: with123 +[1.6] parsed: with$ +[1.10] parsed: withøßöèæ +[1.6] parsed: with_ +[1.6] parsed: _with +[1.1] failure: java identifier expected + +3start +^ +[1.1] failure: java identifier expected + +-start +^ +[1.5] failure: java identifier expected + +with-s + ^ +[1.3] failure: java identifier expected + +we♥scala + ^ +[1.6] failure: java identifier expected + +with space + ^ diff --git a/test/files/run/parserJavaIdent.scala b/test/files/run/parserJavaIdent.scala new file mode 100644 index 0000000000..c068075e4e --- /dev/null +++ b/test/files/run/parserJavaIdent.scala @@ -0,0 +1,26 @@ +object Test extends scala.util.parsing.combinator.JavaTokenParsers { + + def test[A](s: String) { + val res = parseAll(ident, s) match { + case Failure(_, in) => Failure("java identifier expected", in) + case o => o + } + println(res) + } + + def main(args: Array[String]) { + // Happy tests + test("simple") + test("with123") + test("with$") + test("withøßöèæ") + test("with_") + test("_with") + // Sad tests + test("3start") + test("-start") + test("with-s") + test("we♥scala") + test("with space") + } +} diff --git a/test/pending/run/reify_implicits-new.check b/test/files/run/reify_implicits-new.check index e3aeb20f6b..e3aeb20f6b 100644 --- a/test/pending/run/reify_implicits-new.check +++ b/test/files/run/reify_implicits-new.check diff --git a/test/pending/run/reify_implicits-new.scala b/test/files/run/reify_implicits-new.scala index 42a1deef26..42a1deef26 100644 --- a/test/pending/run/reify_implicits-new.scala +++ b/test/files/run/reify_implicits-new.scala diff --git a/test/pending/run/reify_implicits-old.check b/test/files/run/reify_implicits-old.check index e3aeb20f6b..e3aeb20f6b 100644 --- a/test/pending/run/reify_implicits-old.check +++ b/test/files/run/reify_implicits-old.check diff --git a/test/pending/run/reify_implicits-old.scala b/test/files/run/reify_implicits-old.scala index 8ff256d2d4..8ff256d2d4 100644 --- a/test/pending/run/reify_implicits-old.scala +++ b/test/files/run/reify_implicits-old.scala diff --git a/test/files/run/reify_newimpl_11.check b/test/files/run/reify_newimpl_11.check index 2f5cb581e6..c019c6db2d 100644 --- a/test/files/run/reify_newimpl_11.check +++ b/test/files/run/reify_newimpl_11.check @@ -1,2 +1,4 @@ -scala.tools.reflect.ToolBoxError: reflective toolbox has failed: -unresolved free type variables (namely: T defined by C in reify_newimpl_11.scala:6:11). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types +scala.tools.reflect.ToolBoxError: reflective toolbox failed due to unresolved free type variables: + T defined by C in reify_newimpl_11.scala:6:11 +have you forgotten to use TypeTag annotations for type parameters external to a reifee? +if you have troubles tracking free type variables, consider using -Xlog-free-types diff --git a/test/files/run/reify_newimpl_13.check b/test/files/run/reify_newimpl_13.check index d518cd7b84..13e3c9af1e 100644 --- a/test/files/run/reify_newimpl_13.check +++ b/test/files/run/reify_newimpl_13.check @@ -1,2 +1,4 @@ -scala.tools.reflect.ToolBoxError: reflective toolbox has failed: -unresolved free type variables (namely: T defined by C in reify_newimpl_13.scala:7:13). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types +scala.tools.reflect.ToolBoxError: reflective toolbox failed due to unresolved free type variables: + T defined by C in reify_newimpl_13.scala:7:13 +have you forgotten to use TypeTag annotations for type parameters external to a reifee? +if you have troubles tracking free type variables, consider using -Xlog-free-types diff --git a/test/files/run/reify_newimpl_19.check b/test/files/run/reify_newimpl_19.check index 8b8652f92c..c749d4f106 100644 --- a/test/files/run/reify_newimpl_19.check +++ b/test/files/run/reify_newimpl_19.check @@ -1,2 +1,4 @@ -scala.tools.reflect.ToolBoxError: reflective toolbox has failed: -unresolved free type variables (namely: T defined by C in reify_newimpl_19.scala:7:10). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types +scala.tools.reflect.ToolBoxError: reflective toolbox failed due to unresolved free type variables: + T defined by C in reify_newimpl_19.scala:7:10 +have you forgotten to use TypeTag annotations for type parameters external to a reifee? +if you have troubles tracking free type variables, consider using -Xlog-free-types diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index 35cd04ba87..7716221f54 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -14,7 +14,6 @@ scala> :type List[1, 2, 3] List[1, 2, 3] ^ - scala> :type List(1, 2, 3) List[Int] @@ -52,10 +51,9 @@ scala> :type protected lazy val f = 5 Access to protected value f not permitted because enclosing object $eval in package $line19 is not a subclass of object $iw where target is defined - lazy val $result = `f` + lazy val $result = f ^ - scala> :type def f = 5 => Int diff --git a/test/files/run/repl-out-dir.check b/test/files/run/repl-out-dir.check new file mode 100644 index 0000000000..a96f9ba9d9 --- /dev/null +++ b/test/files/run/repl-out-dir.check @@ -0,0 +1,53 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> case class Bippy(x: Int) +defined class Bippy + +scala> val x = Bippy(1) +x: Bippy = Bippy(1) + +scala> $intp.showDirectory +repl-out-dir-run.obj + $line1 + $eval$.class + $eval.class + $line2 + $eval$.class + $eval.class + $read$$iw$$iw$.class + $read$$iw$.class + $read$.class + $read.class + $line3 + $eval$.class + $eval.class + $read$$iw$$iw$.class + $read$$iw$$iw$Bippy$.class + $read$$iw$$iw$Bippy.class + $read$$iw$.class + $read$.class + $read.class + $line4 + $eval$.class + $eval.class + $read$$iw$$iw$.class + $read$$iw$.class + $read$.class + $read.class + $line5 + $eval$.class + $eval.class + $read$$iw$$iw$.class + $read$$iw$.class + $read$.class + $read.class + $repl_$init.class + Test$.class + Test.class + +scala> + +scala> diff --git a/test/files/run/repl-out-dir.scala b/test/files/run/repl-out-dir.scala new file mode 100644 index 0000000000..33c823aa2d --- /dev/null +++ b/test/files/run/repl-out-dir.scala @@ -0,0 +1,13 @@ +import scala.tools.partest.ReplTest +import scala.tools.nsc.Settings + +object Test extends ReplTest { + override def extraSettings = s"-Yrepl-outdir ${testOutput.path}" + + def code = s""" +case class Bippy(x: Int) +val x = Bippy(1) +$$intp.showDirectory + """ + +} diff --git a/test/files/run/search.check b/test/files/run/search.check new file mode 100644 index 0000000000..a885696509 --- /dev/null +++ b/test/files/run/search.check @@ -0,0 +1,6 @@ +Found(2) +Found(4) +InsertionPoint(9) +Found(2) +Found(4) +InsertionPoint(9) diff --git a/test/files/run/search.scala b/test/files/run/search.scala new file mode 100644 index 0000000000..ed7fed54a7 --- /dev/null +++ b/test/files/run/search.scala @@ -0,0 +1,14 @@ +object Test extends App { + import scala.collection.{LinearSeq, IndexedSeq} + import scala.collection.Searching.search + + val ls = LinearSeq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13) + println(ls.search(3)) + println(ls.search(5, 3, 8)) + println(ls.search(12)) + + val is = IndexedSeq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 13) + println(is.search(3)) + println(is.search(5, 3, 8)) + println(is.search(12)) +} diff --git a/test/files/run/settings-parse.check b/test/files/run/settings-parse.check new file mode 100644 index 0000000000..18145c9100 --- /dev/null +++ b/test/files/run/settings-parse.check @@ -0,0 +1,566 @@ +0) List(-cp, ) ==> Settings { + -d = . + -classpath = "" +} + +1) List(-cp, , ) ==> Settings { + -d = . + -classpath = "" +} + +2) List(, -cp, ) ==> Settings { + -d = . + -classpath = "" +} + +3) List(-cp, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +4) List(-cp, , , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +5) List(-cp, , -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +6) List(, -cp, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +7) List(-cp, , -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +8) List(-cp, , , -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +9) List(-cp, , -deprecation, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +10) List(-cp, , -deprecation, foo.scala, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +11) List(, -cp, , -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +12) List(-cp, , foo.scala) ==> Settings { + -d = . + -classpath = "" +} + +13) List(-cp, , , foo.scala) ==> Settings { + -d = . + -classpath = "" +} + +14) List(-cp, , foo.scala, ) ==> Settings { + -d = . + -classpath = "" +} + +15) List(, -cp, , foo.scala) ==> Settings { + -d = . + -classpath = "" +} + +16) List(-cp, , foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +17) List(-cp, , , foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +18) List(-cp, , foo.scala, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +19) List(-cp, , foo.scala, -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +20) List(, -cp, , foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +21) List(-deprecation, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +22) List(, -deprecation, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +23) List(-deprecation, -cp, , ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +24) List(-deprecation, , -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +25) List(-deprecation, -cp, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +26) List(, -deprecation, -cp, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +27) List(-deprecation, -cp, , , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +28) List(-deprecation, -cp, , foo.scala, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +29) List(-deprecation, , -cp, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +30) List(-deprecation, foo.scala, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +31) List(, -deprecation, foo.scala, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +32) List(-deprecation, , foo.scala, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +33) List(-deprecation, foo.scala, -cp, , ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +34) List(-deprecation, foo.scala, , -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +35) List(foo.scala, -cp, ) ==> Settings { + -d = . + -classpath = "" +} + +36) List(, foo.scala, -cp, ) ==> Settings { + -d = . + -classpath = "" +} + +37) List(foo.scala, -cp, , ) ==> Settings { + -d = . + -classpath = "" +} + +38) List(foo.scala, , -cp, ) ==> Settings { + -d = . + -classpath = "" +} + +39) List(foo.scala, -cp, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +40) List(, foo.scala, -cp, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +41) List(foo.scala, -cp, , , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +42) List(foo.scala, -cp, , -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +43) List(foo.scala, , -cp, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +44) List(foo.scala, -deprecation, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +45) List(, foo.scala, -deprecation, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +46) List(foo.scala, , -deprecation, -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +47) List(foo.scala, -deprecation, -cp, , ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +48) List(foo.scala, -deprecation, , -cp, ) ==> Settings { + -d = . + -deprecation = true + -classpath = "" +} + +0) List(-cp, /tmp:/bippy) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +1) List(-cp, /tmp:/bippy, ) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +2) List(, -cp, /tmp:/bippy) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +3) List(-cp, /tmp:/bippy, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +4) List(-cp, /tmp:/bippy, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +5) List(-cp, /tmp:/bippy, -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +6) List(, -cp, /tmp:/bippy, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +7) List(-cp, /tmp:/bippy, -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +8) List(-cp, /tmp:/bippy, , -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +9) List(-cp, /tmp:/bippy, -deprecation, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +10) List(-cp, /tmp:/bippy, -deprecation, foo.scala, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +11) List(, -cp, /tmp:/bippy, -deprecation, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +12) List(-cp, /tmp:/bippy, foo.scala) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +13) List(-cp, /tmp:/bippy, , foo.scala) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +14) List(-cp, /tmp:/bippy, foo.scala, ) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +15) List(, -cp, /tmp:/bippy, foo.scala) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +16) List(-cp, /tmp:/bippy, foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +17) List(-cp, /tmp:/bippy, , foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +18) List(-cp, /tmp:/bippy, foo.scala, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +19) List(-cp, /tmp:/bippy, foo.scala, -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +20) List(, -cp, /tmp:/bippy, foo.scala, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +21) List(-deprecation, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +22) List(, -deprecation, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +23) List(-deprecation, -cp, /tmp:/bippy, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +24) List(-deprecation, , -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +25) List(-deprecation, -cp, /tmp:/bippy, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +26) List(, -deprecation, -cp, /tmp:/bippy, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +27) List(-deprecation, -cp, /tmp:/bippy, , foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +28) List(-deprecation, -cp, /tmp:/bippy, foo.scala, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +29) List(-deprecation, , -cp, /tmp:/bippy, foo.scala) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +30) List(-deprecation, foo.scala, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +31) List(, -deprecation, foo.scala, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +32) List(-deprecation, , foo.scala, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +33) List(-deprecation, foo.scala, -cp, /tmp:/bippy, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +34) List(-deprecation, foo.scala, , -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +35) List(foo.scala, -cp, /tmp:/bippy) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +36) List(, foo.scala, -cp, /tmp:/bippy) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +37) List(foo.scala, -cp, /tmp:/bippy, ) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +38) List(foo.scala, , -cp, /tmp:/bippy) ==> Settings { + -d = . + -classpath = /tmp:/bippy +} + +39) List(foo.scala, -cp, /tmp:/bippy, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +40) List(, foo.scala, -cp, /tmp:/bippy, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +41) List(foo.scala, -cp, /tmp:/bippy, , -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +42) List(foo.scala, -cp, /tmp:/bippy, -deprecation, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +43) List(foo.scala, , -cp, /tmp:/bippy, -deprecation) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +44) List(foo.scala, -deprecation, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +45) List(, foo.scala, -deprecation, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +46) List(foo.scala, , -deprecation, -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +47) List(foo.scala, -deprecation, -cp, /tmp:/bippy, ) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + +48) List(foo.scala, -deprecation, , -cp, /tmp:/bippy) ==> Settings { + -d = . + -deprecation = true + -classpath = /tmp:/bippy +} + diff --git a/test/files/run/settings-parse.scala b/test/files/run/settings-parse.scala new file mode 100644 index 0000000000..2b04f55b24 --- /dev/null +++ b/test/files/run/settings-parse.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc._ + +object Test { + val tokens = List("", "-deprecation", "foo.scala") + val subsets = tokens.toSet.subsets.toList + val permutations0 = subsets.flatMap(_.toList.permutations).distinct + + def runWithCp(cp: String) = { + val permutations = permutations0 flatMap ("-cp CPTOKEN" :: _ permutations) + + for ((p, i) <- permutations.distinct.sortBy(_ mkString "").zipWithIndex) { + val args = p flatMap (_ split "\\s+") map (x => if (x == "CPTOKEN") cp else x) + val s = new settings.MutableSettings(println) + val (ok, residual) = s.processArguments(args, processAll = true) + + val expected = args filter (_ == "foo.scala") + assert(residual == expected, residual) + assert(ok, args) + println(s"$i) $args ==> $s") + } + } + + def main(args0: Array[String]): Unit = { + runWithCp("") + runWithCp("/tmp:/bippy") + } +} diff --git a/test/files/run/shortClass.check b/test/files/run/shortClass.check new file mode 100644 index 0000000000..fbdb725cca --- /dev/null +++ b/test/files/run/shortClass.check @@ -0,0 +1,10 @@ +bippity.bop.Foo +bippity.bop.Foo$Bar +bippity.bop.Foo$Bar$ +Test$$anon$1 +Test$$anon$2 +Foo +Bar +Bar$ +Foo with DingDongBippy +Bar with DingDongBippy diff --git a/test/files/run/shortClass.scala b/test/files/run/shortClass.scala new file mode 100644 index 0000000000..b7bb016896 --- /dev/null +++ b/test/files/run/shortClass.scala @@ -0,0 +1,24 @@ +import scala.reflect.internal.util._ + +package bippity { + trait DingDongBippy + + package bop { + class Foo { + class Bar + object Bar + } + } +} + +object Test { + import bippity._ + import bop._ + + def main(args: Array[String]): Unit = { + val f = new Foo + val instances = List(f, new f.Bar, f.Bar, new Foo with DingDongBippy, new f.Bar with DingDongBippy) + instances map (_.getClass.getName) foreach println + instances map shortClassOfInstance foreach println + } +} diff --git a/test/files/run/streams.check b/test/files/run/streams.check index 7f894052d9..032057d4a1 100644 --- a/test/files/run/streams.check +++ b/test/files/run/streams.check @@ -23,3 +23,4 @@ Stream(100001, ?) true true 705082704 +6 diff --git a/test/files/run/streams.scala b/test/files/run/streams.scala index 51b4e5d76c..dc5d0204ac 100644 --- a/test/files/run/streams.scala +++ b/test/files/run/streams.scala @@ -29,7 +29,7 @@ object Test extends App { def powers(x: Int) = if ((x&(x-1)) == 0) Some(x) else None println(s3.flatMap(powers).reverse.head) - // large enough to generate StackOverflows (on most systems) + // large enough to generate StackOverflows (on most systems) // unless the following methods are tail call optimized. val size = 100000 @@ -43,4 +43,7 @@ object Test extends App { println(Stream.from(1).take(size).foldLeft(0)(_ + _)) val arr = new Array[Int](size) Stream.from(1).take(size).copyToArray(arr, 0) + + // dropRight terminates + println(Stream from 1 dropRight 1000 take 3 sum) } diff --git a/test/files/run/t1500.scala b/test/files/run/t1500.scala index ab132b724f..6d2e7ee05f 100644 --- a/test/files/run/t1500.scala +++ b/test/files/run/t1500.scala @@ -21,7 +21,7 @@ object Test { val settings = new Settings() settings.classpath.value = System.getProperty("java.class.path") val tool = new interpreter.IMain(settings) - val global = tool.compiler + val global = tool.global import global._ import definitions._ diff --git a/test/files/run/t1501.scala b/test/files/run/t1501.scala index aba206bc7a..a2f7bb3a65 100644 --- a/test/files/run/t1501.scala +++ b/test/files/run/t1501.scala @@ -31,7 +31,7 @@ object Test { val settings = new Settings() settings.classpath.value = System.getProperty("java.class.path") val tool = new interpreter.IMain(settings) - val global = tool.compiler + val global = tool.global import global._ import definitions._ diff --git a/test/files/run/t2251.check b/test/files/run/t2251.check new file mode 100644 index 0000000000..55ad2a5857 --- /dev/null +++ b/test/files/run/t2251.check @@ -0,0 +1 @@ +Set(List(List(C), Stream(D, ?))) diff --git a/test/files/run/t2251.scala b/test/files/run/t2251.scala new file mode 100644 index 0000000000..00c5619b49 --- /dev/null +++ b/test/files/run/t2251.scala @@ -0,0 +1,19 @@ +class A +trait B[T <: B[T]] extends A +class C extends B[C] { override def toString = "C" } +class D extends B[D] { override def toString = "D" } + +class E { + val ys = List(List(new C), Stream(new D)) +} + +object Test { + def trav = List(List(), Stream()) + + def main(args: Array[String]): Unit = { + val f = (new E).ys _ + var xs: Set[List[_ <: Seq[B[_]]]] = Set() + xs += f() + println(xs) + } +} diff --git a/test/files/run/t2251b.check b/test/files/run/t2251b.check new file mode 100644 index 0000000000..42b0be457a --- /dev/null +++ b/test/files/run/t2251b.check @@ -0,0 +1,11 @@ +TypeTag[List[scala.collection.immutable.LinearSeq[B[_ >: D with C <: B[_ >: D with C <: A]]] with scala.collection.AbstractSeq[B[_ >: D with C <: B[_ >: D with C <: A]]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def dropRight(n: Int): scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def takeRight(n: Int): scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def drop(n: Int): scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def take(n: Int): scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.LinearSeq with scala.collection.AbstractSeq]; def reverse: scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def dropRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A]}; def splitAt(n: Int): (scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A], scala.collection.immutable.LinearSeq[A] with scala.collection.AbstractSeq[A])}]] +TypeTag[List[scala.collection.immutable.Iterable[B[_ >: F with E with D with C <: B[_ >: F with E with D with C <: A]]] with F with Int => Any]] +TypeTag[List[scala.collection.immutable.Seq[B[_ >: D with C <: B[_ >: D with C <: A]]] with scala.collection.AbstractSeq[B[_ >: D with C <: B[_ >: D with C <: A]]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}; def takeRight(n: Int): scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}; def drop(n: Int): scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}; def take(n: Int): scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}; def slice(from: Int,until: Int): scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}; def splitAt(n: Int): (scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A], scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]); def init: scala.collection.immutable.Seq[B[_ >: D with C <: A]] with scala.collection.AbstractSeq[B[_ >: D with C <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.immutable.Seq with scala.collection.AbstractSeq]; def dropRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def takeRight(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def drop(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def take(n: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def slice(from: Int,until: Int): scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]; def init: scala.collection.immutable.Seq[A] with scala.collection.AbstractSeq[A]}}]] +TypeTag[List[scala.collection.Set[_ >: G with F <: B[_ >: G with F <: B[_ >: G with F <: A]]]]] +TypeTag[List[scala.collection.Set[_ >: G with F <: B[_ >: G with F <: B[_ >: G with F <: A]]]]] +TypeTag[List[scala.collection.Set[_ >: G with F <: B[_ >: G with F <: B[_ >: G with F <: A]]]]] +TypeTag[List[Seq[B[_ >: G with F <: B[_ >: G with F <: A]]]]] +TypeTag[List[scala.collection.Map[_ >: F with C <: B[_ >: F with C <: B[_ >: F with C <: A]], B[_ >: G with D <: B[_ >: G with D <: A]]]]] +TypeTag[List[scala.collection.AbstractSeq[B[_ >: G with F <: B[_ >: G with F <: A]]] with scala.collection.LinearSeq[B[_ >: G with F <: B[_ >: G with F <: A]]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.AbstractSeq with scala.collection.LinearSeq]; def dropRight(n: Int): scala.collection.AbstractSeq[B[_ >: G with F <: A]] with scala.collection.LinearSeq[B[_ >: G with F <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.AbstractSeq with scala.collection.LinearSeq]; def dropRight(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def drop(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def take(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def slice(from: Int,until: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]}; def drop(n: Int): scala.collection.AbstractSeq[B[_ >: G with F <: A]] with scala.collection.LinearSeq[B[_ >: G with F <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.AbstractSeq with scala.collection.LinearSeq]; def dropRight(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def drop(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def take(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def slice(from: Int,until: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]}; def take(n: Int): scala.collection.AbstractSeq[B[_ >: G with F <: A]] with scala.collection.LinearSeq[B[_ >: G with F <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.AbstractSeq with scala.collection.LinearSeq]; def dropRight(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def drop(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def take(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def slice(from: Int,until: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]}; def slice(from: Int,until: Int): scala.collection.AbstractSeq[B[_ >: G with F <: A]] with scala.collection.LinearSeq[B[_ >: G with F <: A]]{def companion: scala.collection.generic.GenericCompanion[scala.collection.AbstractSeq with scala.collection.LinearSeq]; def dropRight(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def drop(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def take(n: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]; def slice(from: Int,until: Int): scala.collection.AbstractSeq[A] with scala.collection.LinearSeq[A]}}]] +TypeTag[List[Seq[B[_ >: G with F <: B[_ >: G with F <: A]]]]] +TypeTag[List[Seq[B[_ >: G with F <: B[_ >: G with F <: A]]]]] diff --git a/test/files/run/t2251b.scala b/test/files/run/t2251b.scala new file mode 100644 index 0000000000..b67b3aec1e --- /dev/null +++ b/test/files/run/t2251b.scala @@ -0,0 +1,48 @@ +class A +trait B[T <: B[T]] extends A +class B1[T <: B1[T]] extends B[T] +class C extends B[C] { override def toString = "C" } +class D extends B[D] { override def toString = "D" } +class E extends B[E] { override def toString = "E" } +class F extends B[F] { override def toString = "F" } +class G extends B1[G] { override def toString = "G" } + +object Test { + import scala.collection.{ mutable, immutable } + import scala.collection.immutable.{ Vector } + import scala.reflect.runtime.universe._ + def what[T: TypeTag](x: T) = println(typeTag[T]) + + def main(args: Array[String]): Unit = { + what(List(List(new C), Stream(new D))) + what(List(List(new C), Stream(new D), Vector(new E), Set(new F))) + what(List(immutable.Vector(new C), Stream(new D))) + what(List(collection.Set(new F), mutable.Set(new G))) + what(List(collection.Set(new F), immutable.Set(new G))) + what(List(mutable.Set(new F), immutable.Set(new G))) + what(List(mutable.Seq(new F), immutable.Seq(new G))) + what(List(mutable.Map(new C -> new D), immutable.Map(new F -> new G))) + what(List(mutable.MutableList(new F), immutable.List(new G))) + what(List(mutable.Seq(new F), collection.Seq(new G))) + what(List(mutable.LinearSeq(new F), collection.IndexedSeq(new G))) + } +} + + +// class D extends B[D] { override def toString = "D" } + + +// class E { +// val ys = List(List(new C), Stream(new D)) +// } + +// object Test { +// def trav = List(List(), Stream()) + +// def main(args: Array[String]): Unit = { +// val f = (new E).ys _ +// var xs: Set[List[_ <: Seq[B[_]]]] = Set() +// xs += f() +// println(xs) +// } +// } diff --git a/test/pending/run/t2318.check b/test/files/run/t2318.check index a486f1ac47..a486f1ac47 100644 --- a/test/pending/run/t2318.check +++ b/test/files/run/t2318.check diff --git a/test/pending/run/t2318.scala b/test/files/run/t2318.scala index e42cbb9680..47d083eb9d 100644 --- a/test/pending/run/t2318.scala +++ b/test/files/run/t2318.scala @@ -7,7 +7,8 @@ object Test { override def checkPermission(perm: Permission) = perm match { case _: java.lang.RuntimePermission => () case _: java.io.FilePermission => () - case x: java.security.AccessControlException if x.getName contains ".networkaddress." => () // generality ftw + case x: java.security.SecurityPermission if x.getName contains ".networkaddress." => () // generality ftw + case x: java.util.PropertyPermission if x.getName == "sun.net.inetaddr.ttl" => () case _ => super.checkPermission(perm) } } diff --git a/test/files/run/t2418.check b/test/files/run/t2418.check new file mode 100644 index 0000000000..f599e28b8a --- /dev/null +++ b/test/files/run/t2418.check @@ -0,0 +1 @@ +10 diff --git a/test/files/run/t2418.scala b/test/files/run/t2418.scala new file mode 100644 index 0000000000..f330bef60a --- /dev/null +++ b/test/files/run/t2418.scala @@ -0,0 +1,10 @@ +class Foo { + @volatile final var x=10 + override def toString = "" + x +} + +object Test { + def main(args: Array[String]): Unit = { + println((new Foo)) + } +} diff --git a/test/files/run/t2886.check b/test/files/run/t2886.check index ce31bc7408..cb0db8a6dc 100644 --- a/test/files/run/t2886.check +++ b/test/files/run/t2886.check @@ -1,5 +1,5 @@ ((x: String) => { - val x$1 = x; - val x$2 = x; + <artifact> val x$1 = x; + <artifact> val x$2 = x; Test.this.test(x$2, x$1) }) diff --git a/test/files/run/t3038d.scala b/test/files/run/t3038d.scala index 6cd2d83776..9550165235 100644 --- a/test/files/run/t3038d.scala +++ b/test/files/run/t3038d.scala @@ -16,9 +16,7 @@ trait Foo { } } - -@serializable -class Bar extends Foo { +class Bar extends Foo with Serializable { @transient protected var first: Any = null def size = a @transient var second: Any = null diff --git a/test/files/run/t3667.check b/test/files/run/t3667.check index bbe5d1bc48..6375c88997 100644 --- a/test/files/run/t3667.check +++ b/test/files/run/t3667.check @@ -1,6 +1,3 @@ -1 -2 -3 4 2 3 diff --git a/test/files/run/t3667.scala b/test/files/run/t3667.scala index f30d57ce3a..ada09d5886 100644 --- a/test/files/run/t3667.scala +++ b/test/files/run/t3667.scala @@ -1,27 +1,9 @@ object Test { def main(args: Array[String]) { - val o1 = new Outer1 - val o2 = new Outer2 - val o3 = new Outer3 val o4 = new Outer4 val o5 = new Outer5 val o6 = new Outer6 - println(1) - ser(new o1.Inner(1)) - o1.Inner // make sure the Inner$module field of the Outer1 instance is initialized! - ser(new o1.Inner(1)) - - println(2) - ser(new o2.Inner(1)) - o2.Inner - ser(new o2.Inner(1)) - - println(3) - ser(new o3.Inner(1)) - o3.Inner - ser(new o3.Inner(1)) - println(4) ser(new o4.Inner(1)) o4.Inner @@ -54,23 +36,6 @@ object Test { } -@serializable -class Outer1 { - @serializable - class Inner(x: Int = 1) -} - -@serializable -class Outer2 { - case class Inner(x: Int = 1) -} - -@serializable -class Outer3 { - case class Inner(x: Int) -} - - class Outer4 extends Serializable { class Inner(x: Int = 1) extends Serializable } diff --git a/test/pending/run/t3897.check b/test/files/run/t3897.check index 244b83716f..244b83716f 100644 --- a/test/pending/run/t3897.check +++ b/test/files/run/t3897.check diff --git a/test/pending/run/t3897/J_2.java b/test/files/run/t3897/J_2.java index 178412dc92..178412dc92 100644 --- a/test/pending/run/t3897/J_2.java +++ b/test/files/run/t3897/J_2.java diff --git a/test/pending/run/t3897/a_1.scala b/test/files/run/t3897/a_1.scala index 4da959e2ac..4da959e2ac 100644 --- a/test/pending/run/t3897/a_1.scala +++ b/test/files/run/t3897/a_1.scala diff --git a/test/pending/run/t3897/a_2.scala b/test/files/run/t3897/a_2.scala index 4d9e59ef05..4d9e59ef05 100644 --- a/test/pending/run/t3897/a_2.scala +++ b/test/files/run/t3897/a_2.scala diff --git a/test/files/run/t4023.check b/test/files/run/t4023.check new file mode 100644 index 0000000000..05f867c397 --- /dev/null +++ b/test/files/run/t4023.check @@ -0,0 +1,21 @@ +Try 1: (6 classes) +class Test$C$B1 +class Test$C$B2 +class Test$C$B3$ +class Test$C$B4$ +class Test$C$B5$ +class Test$C$B6$ +Try 2: (6 classes) +class Test$C$B1 +class Test$C$B2 +class Test$C$B3$ +class Test$C$B4$ +class Test$C$B5$ +class Test$C$B6$ +Try 3: (6 classes) +class Test$C$B1 +class Test$C$B2 +class Test$C$B3$ +class Test$C$B4$ +class Test$C$B5$ +class Test$C$B6$ diff --git a/test/files/run/t4023.scala b/test/files/run/t4023.scala new file mode 100644 index 0000000000..4846fa31b4 --- /dev/null +++ b/test/files/run/t4023.scala @@ -0,0 +1,23 @@ +object Test { + object C { + class B1 + private class B2 + object B3 + private object B4 + object B5 extends B1 + private object B6 extends B2 + + val valuesTry1 = this.getClass.getDeclaredClasses + val valuesTry2 = C.getClass.getDeclaredClasses + val valuesTry3 = getClass.getDeclaredClasses + } + + def main(args: Array[String]) { + println("Try 1: (" + C.valuesTry1.length + " classes)") + C.valuesTry1.foreach(println) + println("Try 2: (" + C.valuesTry2.length + " classes)") + C.valuesTry2.foreach(println) + println("Try 3: (" + C.valuesTry3.length + " classes)") + C.valuesTry3.foreach(println) + } +}
\ No newline at end of file diff --git a/test/files/run/t4047.scala b/test/files/run/t4047.scala index cd42a8b4df..08989bd278 100644 --- a/test/files/run/t4047.scala +++ b/test/files/run/t4047.scala @@ -18,7 +18,7 @@ class D extends Bar[Unit]{ def foo = println("Unit: called D.foo") } -object Test extends Application { +object Test extends App { val a: Foo[Unit] = new A a.foo a.foo diff --git a/test/files/run/t4537.check b/test/files/run/t4537.check new file mode 100644 index 0000000000..63739ca64a --- /dev/null +++ b/test/files/run/t4537.check @@ -0,0 +1 @@ +b.Settings diff --git a/test/files/neg/t4537/a.scala b/test/files/run/t4537/a.scala index 65e183c5f8..125e223e13 100644 --- a/test/files/neg/t4537/a.scala +++ b/test/files/run/t4537/a.scala @@ -1,5 +1,5 @@ package a private[a] object Settings { - val X = 0 -}
\ No newline at end of file + val X = "a.Settings" +} diff --git a/test/files/neg/t4537/b.scala b/test/files/run/t4537/b.scala index bb9dd4e15a..c709d49b04 100644 --- a/test/files/neg/t4537/b.scala +++ b/test/files/run/t4537/b.scala @@ -1,5 +1,5 @@ package b object Settings { - val Y = 0 -}
\ No newline at end of file + val Y = "b.Settings" +} diff --git a/test/files/run/t4537/c.scala b/test/files/run/t4537/c.scala new file mode 100644 index 0000000000..ee05d4bbfb --- /dev/null +++ b/test/files/run/t4537/c.scala @@ -0,0 +1,8 @@ +package b +package c + +import a._ + +object Unambiguous { + println(Settings.Y) +} diff --git a/test/files/run/t4537/d.scala b/test/files/run/t4537/d.scala new file mode 100644 index 0000000000..dd1d2045ed --- /dev/null +++ b/test/files/run/t4537/d.scala @@ -0,0 +1,6 @@ +import a._ +import b._ + +object Test extends App { + println(Settings.Y) +} diff --git a/test/files/run/t4729.check b/test/files/run/t4729.check new file mode 100644 index 0000000000..9a2aa56d99 --- /dev/null +++ b/test/files/run/t4729.check @@ -0,0 +1,4 @@ +WrappedArray(1, 2) +WrappedArray(1, 2) +WrappedArray(1, 2) +WrappedArray(1, 2) diff --git a/test/files/run/t4729/J_1.java b/test/files/run/t4729/J_1.java new file mode 100644 index 0000000000..2ffb5a88d1 --- /dev/null +++ b/test/files/run/t4729/J_1.java @@ -0,0 +1,4 @@ +// Java Interface: +public interface J_1 { + public void method(String... s); +} diff --git a/test/files/run/t4729/S_2.scala b/test/files/run/t4729/S_2.scala new file mode 100644 index 0000000000..e34e3d34d4 --- /dev/null +++ b/test/files/run/t4729/S_2.scala @@ -0,0 +1,29 @@ + // Scala class: +class ScalaVarArgs extends J_1 { + // -- no problem on overriding it using ordinary class + def method(s: String*) { println(s) } +} + +object Test { + def main(args: Array[String]) { + //[1] Ok - no problem using inferred type + val varArgs = new J_1 { + def method(s: String*) { println(s) } + } + varArgs.method("1", "2") + + //[2] Ok -- no problem when explicit set its type after construction + val b: J_1 = varArgs + b.method("1", "2") + + //[3] Ok -- no problem on calling its method + (new ScalaVarArgs).method("1", "2") + (new ScalaVarArgs: J_1).method("1", "2") + + //[4] Not Ok -- error when assigning anonymous class to a explictly typed val + // Compiler error: object creation impossible, since method method in trait VarArgs of type (s: <repeated...>[java.lang.String])Unit is not defined + val tagged: J_1 = new J_1 { + def method(s: String*) { println(s) } + } + } +} diff --git a/test/files/run/t4935.flags b/test/files/run/t4935.flags index ac14fe5dbd..49d036a887 100644 --- a/test/files/run/t4935.flags +++ b/test/files/run/t4935.flags @@ -1 +1 @@ --optimize
+-optimize diff --git a/test/files/run/t4996.check b/test/files/run/t4996.check new file mode 100644 index 0000000000..8d45b413c9 --- /dev/null +++ b/test/files/run/t4996.check @@ -0,0 +1,4 @@ +B.foo +M.foo +B.foo +M.foo
\ No newline at end of file diff --git a/test/files/run/t4996.scala b/test/files/run/t4996.scala new file mode 100644 index 0000000000..8e7636aaac --- /dev/null +++ b/test/files/run/t4996.scala @@ -0,0 +1,47 @@ + + + + + + +trait A[@specialized(Int) T] { + def foo(t: T) +} + + +trait B extends A[Int] { + def foo(t: Int) { + println("B.foo") + } +} + + +trait M extends B { + abstract override def foo(t: Int) { + super.foo(t) + println("M.foo") + } +} + + +object C extends B with M + + +object D extends B { + override def foo(t: Int) { + super.foo(t) + println("M.foo") + } +} + + +object Test { + + def main(args: Array[String]) { + D.foo(42) // OK, prints B.foo M.foo + C.foo(42) // was StackOverflowError + } + +} + + diff --git a/test/pending/run/t5293-map.scala b/test/files/run/t5293-map.scala index 2707aed07e..2707aed07e 100644 --- a/test/pending/run/t5293-map.scala +++ b/test/files/run/t5293-map.scala diff --git a/test/pending/run/t5293.scala b/test/files/run/t5293.scala index 01ead45d2a..01ead45d2a 100644 --- a/test/pending/run/t5293.scala +++ b/test/files/run/t5293.scala diff --git a/test/pending/run/t5418.check b/test/files/run/t5418.check index e69de29bb2..e69de29bb2 100644 --- a/test/pending/run/t5418.check +++ b/test/files/run/t5418.check diff --git a/test/pending/run/t5418.scala b/test/files/run/t5418.scala index e3cb20cf82..e3cb20cf82 100644 --- a/test/pending/run/t5418.scala +++ b/test/files/run/t5418.scala diff --git a/test/files/run/t5604.check b/test/files/run/t5604.check new file mode 100644 index 0000000000..53a2fc8894 --- /dev/null +++ b/test/files/run/t5604.check @@ -0,0 +1,8 @@ +long +double +long +double +long +double +long +double diff --git a/test/files/run/t5604.scala b/test/files/run/t5604.scala new file mode 100644 index 0000000000..a06c8aab3e --- /dev/null +++ b/test/files/run/t5604.scala @@ -0,0 +1,50 @@ +// a.scala +// Fri Jan 13 11:31:47 PST 2012 + +package foo { + object regular extends Duh { + def buh(n: Long) = println("long") + def buh(n: Double) = println("double") + } + class regular { + import regular._ + + duh(33L) + duh(3.0d) + foo.regular.duh(33L) + foo.regular.duh(3.0d) + buh(66L) + buh(6.0d) + foo.regular.buh(66L) + foo.regular.buh(6.0d) + } + + trait Duh { + def duh(n: Long) = println("long") + def duh(n: Double) = println("double") + } + package object bar extends Duh { + def buh(n: Long) = println("long") + def buh(n: Double) = println("double") + } + package bar { + object Main { + def main(args:Array[String]) { + duh(33L) + duh(3.0d) + foo.bar.duh(33L) + foo.bar.duh(3.0d) + buh(66L) + buh(6.0d) + foo.bar.buh(66L) + foo.bar.buh(6.0d) + } + } + } +} + +object Test { + def main(args: Array[String]): Unit = { + foo.bar.Main.main(null) + } +} diff --git a/test/pending/run/t5610a.check b/test/files/run/t5610a.check index 2aa46b3b91..2aa46b3b91 100644 --- a/test/pending/run/t5610a.check +++ b/test/files/run/t5610a.check diff --git a/test/pending/run/t5610a.scala b/test/files/run/t5610a.scala index f20b295762..f20b295762 100644 --- a/test/pending/run/t5610a.scala +++ b/test/files/run/t5610a.scala diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check index 34f4b22134..42921ae2f5 100644 --- a/test/files/run/t6028.check +++ b/test/files/run/t6028.check @@ -31,14 +31,14 @@ package <empty> { }; final def apply(): Int = $anonfun$foo$1.this.apply$mcI$sp(); <specialized> def apply$mcI$sp(): Int = $anonfun$foo$1.this.$outer.T$$classParam.+($anonfun$foo$1.this.$outer.field()).+($anonfun$foo$1.this.methodParam$1).+($anonfun$foo$1.this.methodLocal$1); - <synthetic> <paramaccessor> private[this] val $outer: T = _; - <synthetic> <stable> def T$$anonfun$$$outer(): T = $anonfun$foo$1.this.$outer; - final <bridge> def apply(): Object = scala.Int.box($anonfun$foo$1.this.apply()); + <synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _; + <synthetic> <stable> <artifact> def T$$anonfun$$$outer(): T = $anonfun$foo$1.this.$outer; + final <bridge> <artifact> def apply(): Object = scala.Int.box($anonfun$foo$1.this.apply()); <synthetic> <paramaccessor> private[this] val methodParam$1: Int = _; <synthetic> <paramaccessor> private[this] val methodLocal$1: Int = _ }; abstract trait MethodLocalTrait$1 extends Object { - <synthetic> <stable> def T$MethodLocalTrait$$$outer(): T + <synthetic> <stable> <artifact> def T$MethodLocalTrait$$$outer(): T }; object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 { def <init>($outer: T, barParam$1: Int): T#MethodLocalObject$2.type = { @@ -46,9 +46,9 @@ package <empty> { MethodLocalObject$2.this.$asInstanceOf[T#MethodLocalTrait$1$class]()./*MethodLocalTrait$1$class*/$init$(barParam$1); () }; - <synthetic> <paramaccessor> private[this] val $outer: T = _; - <synthetic> <stable> def T$MethodLocalObject$$$outer(): T = MethodLocalObject$2.this.$outer; - <synthetic> <stable> def T$MethodLocalTrait$$$outer(): T = MethodLocalObject$2.this.$outer + <synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _; + <synthetic> <stable> <artifact> def T$MethodLocalObject$$$outer(): T = MethodLocalObject$2.this.$outer; + <synthetic> <stable> <artifact> def T$MethodLocalTrait$$$outer(): T = MethodLocalObject$2.this.$outer }; final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = { MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1); @@ -69,9 +69,9 @@ package <empty> { <specialized> def apply$mcV$sp(): Unit = try { $anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1 } finally (); - <synthetic> <paramaccessor> private[this] val $outer: T = _; - <synthetic> <stable> def T$$anonfun$$$outer(): T = $anonfun$tryy$1.this.$outer; - final <bridge> def apply(): Object = { + <synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _; + <synthetic> <stable> <artifact> def T$$anonfun$$$outer(): T = $anonfun$tryy$1.this.$outer; + final <bridge> <artifact> def apply(): Object = { $anonfun$tryy$1.this.apply(); scala.runtime.BoxedUnit.UNIT }; diff --git a/test/files/run/t6064.scala b/test/files/run/t6064.scala new file mode 100644 index 0000000000..fc184dd92d --- /dev/null +++ b/test/files/run/t6064.scala @@ -0,0 +1,9 @@ +object Test extends App { + assert(Option(42) contains 42) + assert(Some(42) contains 42) + assert(Option(BigInt(42)) contains 42) + assert(Option(42) contains BigInt(42)) + assert(!(None contains 42)) + assert(Some(null) contains null) + assert(!(Option(null) contains null)) +}
\ No newline at end of file diff --git a/test/files/run/t6150.scala b/test/files/run/t6150.scala index bd8af5d460..f3e83e1549 100644 --- a/test/files/run/t6150.scala +++ b/test/files/run/t6150.scala @@ -1,7 +1,3 @@ - - - - object Test { import collection.{ immutable, mutable, generic } def TheOneTrueCBF = collection.IndexedSeq.ReusableCBF @@ -38,7 +34,3 @@ object Test { check(iv.:+(4)(cbf3)) } } - - - - diff --git a/test/files/run/t6154.check b/test/files/run/t6154.check new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/test/files/run/t6154.check @@ -0,0 +1 @@ +ok diff --git a/test/files/run/t6154.scala b/test/files/run/t6154.scala new file mode 100644 index 0000000000..02ef62905f --- /dev/null +++ b/test/files/run/t6154.scala @@ -0,0 +1,10 @@ +object Test { + def foo(a: Int) { + var bar: Int = 0 + bar = try { 0 } catch { case ex: Throwable => 0 } + new { foo(bar) } + } + + def main(args: Array[String]): Unit = + try foo(0) catch { case _: java.lang.StackOverflowError => println("ok") } +} diff --git a/test/files/run/t6206.check b/test/files/run/t6206.check new file mode 100644 index 0000000000..8064573667 --- /dev/null +++ b/test/files/run/t6206.check @@ -0,0 +1,4 @@ +outer +outer +inner +inner diff --git a/test/files/run/t6206.scala b/test/files/run/t6206.scala new file mode 100644 index 0000000000..07ff246d02 --- /dev/null +++ b/test/files/run/t6206.scala @@ -0,0 +1,37 @@ +class Outer { + def apply( position : Inner ) {} + class Inner + + this.apply(new Inner) + this (new Inner) // error, +} + + +class Outer1 { + + self => + + def apply( position : Inner ) : String = "outer" + + class Inner( ) { + + def apply(arg: Inner): String = "inner" + + def testMe = { + List( + self.apply( this ), // a) this works + self( this ), // b) this does not work! + this apply this, + this(this) + ) foreach println + } + } +} + +object Test { + def main(args: Array[String]): Unit = { + val o = new Outer1 + val i = new o.Inner + i.testMe + } +} diff --git a/test/files/run/t6223.check b/test/files/run/t6223.check index 90ec019407..4a09d1930f 100644 --- a/test/files/run/t6223.check +++ b/test/files/run/t6223.check @@ -1,4 +1,4 @@ bar -bar$mcI$sp bar$mIc$sp bar$mIcI$sp +bar$mcI$sp diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala index 4ab7c832e6..fb176e32e6 100644 --- a/test/files/run/t6223.scala +++ b/test/files/run/t6223.scala @@ -5,7 +5,7 @@ class Foo[@specialized(Int) A](a:A) { object Test { def main(args:Array[String]) { val f = new Foo(333) - val ms = f.getClass().getDeclaredMethods() + val ms = f.getClass().getDeclaredMethods().sortBy(_.getName) ms.foreach(m => println(m.getName)) } } diff --git a/test/files/run/t6381.check b/test/files/run/t6381.check new file mode 100644 index 0000000000..b51cfd0398 --- /dev/null +++ b/test/files/run/t6381.check @@ -0,0 +1,17 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> import language.experimental.macros +import language.experimental.macros + +scala> def pos_impl(c: reflect.macros.Context): c.Expr[String] = + c.literal(c.enclosingPosition.getClass.toString) +pos_impl: (c: scala.reflect.macros.Context)c.Expr[String] + +scala> def pos = macro pos_impl +pos: String + +scala> pos +res0: String = class scala.reflect.internal.util.RangePosition + +scala> diff --git a/test/files/run/t6381.scala b/test/files/run/t6381.scala new file mode 100644 index 0000000000..859ec3cb30 --- /dev/null +++ b/test/files/run/t6381.scala @@ -0,0 +1,13 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ + |import language.experimental.macros + |def pos_impl(c: reflect.macros.Context): c.Expr[String] = + | c.literal(c.enclosingPosition.getClass.toString) + |def pos = macro pos_impl + |pos + |""".stripMargin.trim + + override def extraSettings: String = "-Yrangepos" +} diff --git a/test/files/run/t6406-regextract.check b/test/files/run/t6406-regextract.check new file mode 100644 index 0000000000..88c5a52eb3 --- /dev/null +++ b/test/files/run/t6406-regextract.check @@ -0,0 +1,4 @@ +List(1, 3) +List(1, 3) +List(1, 3) +Some(2011) Some(2011) diff --git a/test/files/run/t6406-regextract.scala b/test/files/run/t6406-regextract.scala new file mode 100644 index 0000000000..83679a5167 --- /dev/null +++ b/test/files/run/t6406-regextract.scala @@ -0,0 +1,30 @@ + +object Test extends App { + import util.matching._ + import Regex._ + + val r = "(\\d+)".r + val q = """(\d)""".r + val ns = List("1,2","x","3,4") + val u = r.unanchored + + val is = ns collect { case u(x) => x } map { case r(x) => x } + println(is) + // Match from same pattern + val js = (ns map { u findFirstMatchIn _ }).flatten map { case r(x) => x } + println(js) + // Match not from same pattern + val ks = (ns map { q findFirstMatchIn _ }).flatten map { case r(x) => x } + println(ks) + + val t = "Last modified 2011-07-15" + val p1 = """(\d\d\d\d)-(\d\d)-(\d\d)""".r + val y1: Option[String] = for { + p1(year, month, day) <- p1 findFirstIn t + } yield year + val y2: Option[String] = for { + p1(year, month, day) <- p1 findFirstMatchIn t + } yield year + println(s"$y1 $y2") + +} diff --git a/test/files/run/t6448.check b/test/files/run/t6448.check new file mode 100644 index 0000000000..9401568319 --- /dev/null +++ b/test/files/run/t6448.check @@ -0,0 +1,32 @@ + +=List.collect= +f(1) +f(2) +List(1) + +=List.collectFirst= +f(1) +Some(1) + +=Option.collect= +f(1) +Some(1) + +=Option.collect= +f(2) +None + +=Stream.collect= +f(1) +f(2) +List(1) + +=Stream.collectFirst= +f(1) +Some(1) + +=ParVector.collect= +(ParVector(1),2) + +=ParArray.collect= +(ParArray(1),2) diff --git a/test/files/run/t6448.scala b/test/files/run/t6448.scala new file mode 100644 index 0000000000..4d1528e500 --- /dev/null +++ b/test/files/run/t6448.scala @@ -0,0 +1,61 @@ +// Tests to show that various `collect` functions avoid calling +// both `PartialFunction#isDefinedAt` and `PartialFunction#apply`. +// +object Test { + def f(i: Int) = { println("f(" + i + ")"); true } + class Counter { + var count = 0 + def apply(i: Int) = synchronized {count += 1; true} + } + + def testing(label: String)(body: => Any) { + println(s"\n=$label=") + println(body) + } + + def main(args: Array[String]) { + testing("List.collect")(List(1, 2) collect { case x if f(x) && x < 2 => x}) + testing("List.collectFirst")(List(1, 2) collectFirst { case x if f(x) && x < 2 => x}) + testing("Option.collect")(Some(1) collect { case x if f(x) && x < 2 => x}) + testing("Option.collect")(Some(2) collect { case x if f(x) && x < 2 => x}) + testing("Stream.collect")((Stream(1, 2).collect { case x if f(x) && x < 2 => x}).toList) + testing("Stream.collectFirst")(Stream.continually(1) collectFirst { case x if f(x) && x < 2 => x}) + + import collection.parallel.ParIterable + import collection.parallel.immutable.ParVector + import collection.parallel.mutable.ParArray + testing("ParVector.collect") { + val counter = new Counter() + (ParVector(1, 2) collect { case x if counter(x) && x < 2 => x}, counter.synchronized(counter.count)) + } + + testing("ParArray.collect") { + val counter = new Counter() + (ParArray(1, 2) collect { case x if counter(x) && x < 2 => x}, counter.synchronized(counter.count)) + } + + object PendingTests { + testing("Iterator.collect")((Iterator(1, 2) collect { case x if f(x) && x < 2 => x}).toList) + + testing("List.view.collect")((List(1, 2).view collect { case x if f(x) && x < 2 => x}).force) + + // This would do the trick in Future.collect, but I haven't added this yet as there is a tradeoff + // with extra allocations to consider. + // + // pf.lift(v) match { + // case Some(x) => p success x + // case None => fail(v) + // } + testing("Future.collect") { + import concurrent.ExecutionContext.Implicits.global + import concurrent.Await + import concurrent.duration.Duration + val result = concurrent.future(1) collect { case x if f(x) => x} + Await.result(result, Duration.Inf) + } + + // TODO Future.{onSuccess, onFailure, recoverWith, andThen} + } + + } +} diff --git a/test/files/run/t6467.scala b/test/files/run/t6467.scala new file mode 100644 index 0000000000..dc93b69fdc --- /dev/null +++ b/test/files/run/t6467.scala @@ -0,0 +1,20 @@ + + + + +import collection._ + + + +object Test extends App { + + def compare(s1: String, s2: String) { + assert(s1 == s2, s1 + "\nvs.\n" + s2) + } + + compare(List(1, 2, 3, 4).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234") + compare(List(1, 2, 3, 4).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, "1234") + compare(Seq(0 until 100: _*).aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString) + compare(Seq(0 until 100: _*).par.aggregate(new java.lang.StringBuffer)(_ append _, _ append _).toString, (0 until 100).mkString) + +}
\ No newline at end of file diff --git a/test/files/run/t6584.check b/test/files/run/t6584.check new file mode 100644 index 0000000000..35c8688751 --- /dev/null +++ b/test/files/run/t6584.check @@ -0,0 +1,8 @@ +Array: 102400 +Vector: 102400 +List: 102400 +Stream: 102400 +Array: 102400 +Vector: 102400 +List: 102400 +Stream: 102400 diff --git a/test/files/run/t6584.scala b/test/files/run/t6584.scala new file mode 100644 index 0000000000..24c236ef35 --- /dev/null +++ b/test/files/run/t6584.scala @@ -0,0 +1,16 @@ +object Test { + def main(args: Array[String]): Unit = { + val size = 100 * 1024 + val doubled = (1 to size) ++ (1 to size) + + println("Array: " + Array.tabulate(size)(x => x).distinct.size) + println("Vector: " + Vector.tabulate(size)(x => x).distinct.size) + println("List: " + List.tabulate(size)(x => x).distinct.size) + println("Stream: " + Stream.tabulate(size)(x => x).distinct.size) + + println("Array: " + doubled.toArray.distinct.size) + println("Vector: " + doubled.toVector.distinct.size) + println("List: " + doubled.toList.distinct.size) + println("Stream: " + doubled.toStream.distinct.size) + } +} diff --git a/test/files/run/t6611.scala b/test/files/run/t6611.scala new file mode 100644 index 0000000000..c295368aea --- /dev/null +++ b/test/files/run/t6611.scala @@ -0,0 +1,61 @@ +object Test extends App { + locally { + val a = Array("1") + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array("1": Object) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(true) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1: Short) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1: Byte) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1L) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1f) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(1d) + val a2 = Array(a: _*) + assert(a ne a2) + } + + locally { + val a = Array(()) + val a2 = Array(a: _*) + assert(a ne a2) + } +} diff --git a/test/files/run/t6637.check b/test/files/run/t6637.check new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/test/files/run/t6637.check @@ -0,0 +1 @@ +ok diff --git a/test/files/run/t6637.scala b/test/files/run/t6637.scala new file mode 100644 index 0000000000..d3c380370b --- /dev/null +++ b/test/files/run/t6637.scala @@ -0,0 +1,8 @@ + +object Test extends App { + try { + class A ; class B ; List().head.isInstanceOf[A with B] + } catch { + case _ :java.util.NoSuchElementException => println("ok") + } +} diff --git a/test/flaky/pos/t2868.cmds b/test/flaky/pos/t2868.cmds deleted file mode 100644 index ed8124a9e0..0000000000 --- a/test/flaky/pos/t2868.cmds +++ /dev/null @@ -1,3 +0,0 @@ -javac Jann.java Nest.java -scalac pick_1.scala -scalac test_2.scala diff --git a/test/partest b/test/partest index 8352f8a946..ae60c49929 100755 --- a/test/partest +++ b/test/partest @@ -70,6 +70,12 @@ if $cygwin; then else format=windows fi + if [ -n "${JAVA_HOME}" ] ; then + JAVA_HOME=`cygpath --$format "$JAVA_HOME"` + fi + if [ -n "${JAVACMD}" ] ; then + JAVACMD=`cygpath --$format "$JAVACMD"` + fi SCALA_HOME=`cygpath --$format "$SCALA_HOME"` EXT_CLASSPATH=`cygpath --path --$format "$EXT_CLASSPATH"` fi @@ -84,7 +90,7 @@ if [ ! -z "${PARTEST_DEBUG}" ] ; then partestDebugStr="-Dpartest.debug=${PARTEST_DEBUG}" fi -${JAVACMD:=java} \ +"${JAVACMD:=java}" \ $JAVA_OPTS -cp "$EXT_CLASSPATH" \ ${partestDebugStr} \ -Dscala.home="${SCALA_HOME}" \ diff --git a/test/pending/pos/overloading-boundaries.scala b/test/pending/pos/overloading-boundaries.scala new file mode 100644 index 0000000000..d2e9fdbb12 --- /dev/null +++ b/test/pending/pos/overloading-boundaries.scala @@ -0,0 +1,37 @@ +package bar { + object bippy extends (Double => String) { + def apply(x: Double): String = "Double" + } +} + +package object bar { + def bippy(x: Int, y: Int, z: Int) = "(Int, Int, Int)" +} + +object Test { + def main(args: Array[String]): Unit = { + println(bar.bippy(5.5d)) + println(bar.bippy(1, 2, 3)) + } +} + +/**** + +% scalac3 a.scala +a.scala:13: error: not enough arguments for method bippy: (x: Int, y: Int, z: Int)String. +Unspecified value parameters y, z. + println(bar.bippy(5.5d)) + ^ +one error found + +# Comment out the call to bar.bippy(5.5d) - compiles +% scalac3 a.scala + +# Compiles only from pure source though - if classes are present, fails. +% scalac3 a.scala +a.scala:2: error: bippy is already defined as method bippy in package object bar + object bippy extends (Double => String) { + ^ +one error found + +****/ diff --git a/test/pending/pos/t1751.cmds b/test/pending/pos/t1751.cmds deleted file mode 100644 index d4a4898ffd..0000000000 --- a/test/pending/pos/t1751.cmds +++ /dev/null @@ -1,3 +0,0 @@ -javac SuiteClasses.java -scalac A2_1.scala -scalac A1_2.scala diff --git a/test/pending/pos/t1782.cmds b/test/pending/pos/t1782.cmds deleted file mode 100644 index 61f3d3788e..0000000000 --- a/test/pending/pos/t1782.cmds +++ /dev/null @@ -1,2 +0,0 @@ -javac Ann.java Days.java ImplementedBy.java -scalac Test_1.scala diff --git a/test/pending/pos/t1832.scala b/test/pending/pos/t1832.scala deleted file mode 100644 index bca863f4bd..0000000000 --- a/test/pending/pos/t1832.scala +++ /dev/null @@ -1,10 +0,0 @@ -// Edit by paulp: reduced. -trait Cloning { - trait Foo - def fn(g: Int => Unit): Foo - - implicit def mkStar(i: Int) = new { def *(a: Foo): Foo = null } - - val pool1 = 4 * fn { case i => i * 2 } - val pool2 = 4 * fn { case i: Int => i * 2 } -} diff --git a/test/pending/pos/t294.cmds b/test/pending/pos/t294.cmds deleted file mode 100644 index 62c9a5a068..0000000000 --- a/test/pending/pos/t294.cmds +++ /dev/null @@ -1,3 +0,0 @@ -javac Ann.java Ann2.java -scalac Test_1.scala -scalac Test_2.scala diff --git a/test/pending/pos/t4612.scala b/test/pending/pos/t4612.scala new file mode 100644 index 0000000000..a93c12ef01 --- /dev/null +++ b/test/pending/pos/t4612.scala @@ -0,0 +1,15 @@ +class CyclicReferenceCompilerBug { + trait Trait[A] { + def foo: A + } + + class Class extends Trait[Class] { + def foo = new Class + + trait OtherTrait extends Trait[OtherTrait] { + self: Class => + + def foo = new Class + } + } +} diff --git a/test/pending/pos/t4695/T_1.scala b/test/pending/pos/t4695/T_1.scala new file mode 100644 index 0000000000..70fb1a7f21 --- /dev/null +++ b/test/pending/pos/t4695/T_1.scala @@ -0,0 +1,4 @@ +package foo + +class Bar { } +package object Bar { } diff --git a/test/pending/pos/t4695/T_2.scala b/test/pending/pos/t4695/T_2.scala new file mode 100644 index 0000000000..70fb1a7f21 --- /dev/null +++ b/test/pending/pos/t4695/T_2.scala @@ -0,0 +1,4 @@ +package foo + +class Bar { } +package object Bar { } diff --git a/test/pending/pos/t4717.scala b/test/pending/pos/t4717.scala deleted file mode 100644 index 7eaa3dd487..0000000000 --- a/test/pending/pos/t4717.scala +++ /dev/null @@ -1,7 +0,0 @@ -trait Bounds[@specialized A] { - // okay without `>: A` - def x[B >: A]: Unit = new Bounds[B] { - lazy val it = ??? // def or val okay - it - } -}
\ No newline at end of file diff --git a/test/pending/pos/t5082.scala b/test/pending/pos/t5082.scala new file mode 100644 index 0000000000..20a6cfc55f --- /dev/null +++ b/test/pending/pos/t5082.scala @@ -0,0 +1,8 @@ +object Test { + sealed trait A + case object A1 extends A +} + +trait Something[T] + +case class Test() extends Something[Test.A] diff --git a/test/pending/pos/t5259.scala b/test/pending/pos/t5259.scala deleted file mode 100644 index 317e28a9dc..0000000000 --- a/test/pending/pos/t5259.scala +++ /dev/null @@ -1,14 +0,0 @@ -object DefaultArgBogusTypeMismatch { - - class A[T] - class B { - type T = this.type - def m(implicit a : A[T] = new A[T]) = a - } - - def newB = new B - val a1 = newB.m // Bogus type mismatch - - val stableB = new B - val a2 = stableB.m // OK -} diff --git a/test/pending/pos/t5399.scala b/test/pending/pos/t5399.scala deleted file mode 100644 index 89caba39c1..0000000000 --- a/test/pending/pos/t5399.scala +++ /dev/null @@ -1,8 +0,0 @@ -class Test { - class A[T] - class B[T](val a: A[T]) - - case class CaseClass[T](x: T) - - def break(existB: B[_]) = CaseClass(existB.a) match { case CaseClass(_) => } -} diff --git a/test/pending/pos/t5626.scala b/test/pending/pos/t5626.scala deleted file mode 100644 index 7ab3881827..0000000000 --- a/test/pending/pos/t5626.scala +++ /dev/null @@ -1,12 +0,0 @@ -object Test { - val blob0 = new { - case class Foo(i : Int) - } - val foo0 = blob0.Foo(22) - - val blob1 = new { - class Foo(i: Int) - object Foo { def apply(i: Int): Foo = new Foo(i) } - } - val foo1 = blob1.Foo(22) -} diff --git a/test/pending/pos/t5654.scala b/test/pending/pos/t5654.scala deleted file mode 100644 index eb711a5f37..0000000000 --- a/test/pending/pos/t5654.scala +++ /dev/null @@ -1,4 +0,0 @@ -case class Bomb(a: Array[_]) -case class Bomb2(a: Array[T] forSome { type T }) -class Okay1(a: Array[_]) -case class Okay2(s: Seq[_])
\ No newline at end of file diff --git a/test/pending/pos/t5877.scala b/test/pending/pos/t5877.scala new file mode 100644 index 0000000000..b77605f7f2 --- /dev/null +++ b/test/pending/pos/t5877.scala @@ -0,0 +1,5 @@ +package foo { } + +package object foo { + implicit class Foo(val s: String) { } +} diff --git a/test/pending/pos/t5954/T_1.scala b/test/pending/pos/t5954/T_1.scala new file mode 100644 index 0000000000..0064c596b6 --- /dev/null +++ b/test/pending/pos/t5954/T_1.scala @@ -0,0 +1,8 @@ +package p { + package base { + class X + } + package object base { + case class B() + } +} diff --git a/test/pending/pos/t5954/T_2.scala b/test/pending/pos/t5954/T_2.scala new file mode 100644 index 0000000000..0064c596b6 --- /dev/null +++ b/test/pending/pos/t5954/T_2.scala @@ -0,0 +1,8 @@ +package p { + package base { + class X + } + package object base { + case class B() + } +} diff --git a/test/pending/pos/t5954/T_3.scala b/test/pending/pos/t5954/T_3.scala new file mode 100644 index 0000000000..0064c596b6 --- /dev/null +++ b/test/pending/pos/t5954/T_3.scala @@ -0,0 +1,8 @@ +package p { + package base { + class X + } + package object base { + case class B() + } +} diff --git a/test/pending/pos/t6225.scala b/test/pending/pos/t6225.scala new file mode 100644 index 0000000000..d7dff3c419 --- /dev/null +++ b/test/pending/pos/t6225.scala @@ -0,0 +1,11 @@ +package library.x { + class X { + class Foo + implicit val foo = new Foo + } +} +package library { package object x extends X } +package app { + import library.x._ + object App { implicitly[Foo] } +} diff --git a/test/pending/pos/z1720.scala b/test/pending/pos/z1720.scala deleted file mode 100644 index 6050f3ff88..0000000000 --- a/test/pending/pos/z1720.scala +++ /dev/null @@ -1,16 +0,0 @@ -package test - -class Thing { - def info: Info[this.type] = InfoRepository.getInfo(this) - def info2: Info[this.type] = { - def self: this.type = this - InfoRepository.getInfo(self) - } -} - -trait Info[T] -case class InfoImpl[T](thing: T) extends Info[T] - -object InfoRepository { - def getInfo(t: Thing): Info[t.type] = InfoImpl(t) -}
\ No newline at end of file diff --git a/test/scaladoc/resources/links.scala b/test/scaladoc/resources/links.scala index bd69665357..ecac9c63cf 100644 --- a/test/scaladoc/resources/links.scala +++ b/test/scaladoc/resources/links.scala @@ -25,6 +25,7 @@ package scala.test.scaladoc.links { object Target { type T = Int => Int type S = Int + type ::[X] = scala.collection.immutable.::[X] class C def foo(i: Int) = 2 def foo(z: String) = 3 @@ -46,6 +47,7 @@ package scala.test.scaladoc.links { * - [[[[Target!.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) * - [[Target$.T object Target -> type T]] * - [[Target$.S object Target -> type S]] + * - [[Target$.:: object Target -> type ::]] * - [[Target$.foo(z:Str* object Target -> def foo]] * - [[Target$.bar object Target -> def bar]] * - [[[[Target$.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) diff --git a/test/scaladoc/run/links.scala b/test/scaladoc/run/links.scala index 0c67857e1c..9fbf618558 100644 --- a/test/scaladoc/run/links.scala +++ b/test/scaladoc/run/links.scala @@ -25,7 +25,7 @@ object Test extends ScaladocModelTest { val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember]) val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl]) - assert(memberLinks == 17, memberLinks + " == 17 (the member links in object TEST)") + assert(memberLinks == 18, memberLinks + " == 18 (the member links in object TEST)") assert(templateLinks == 6, templateLinks + " == 6 (the template links in object TEST)") } -}
\ No newline at end of file +} diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala index 13eacf79a5..d7b5e48288 100644 --- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala +++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala @@ -680,7 +680,7 @@ object Test extends Properties("HtmlFactory") { property("package object") = files("com/example/p1/package.html") match { case node: scala.xml.Node => - node.toString contains "com.example.p1.package#packageObjectMethod" + node.toString contains "com.example.p1#packageObjectMethod" case _ => false } diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh index 4fe6dd67a0..704bf4944d 100755 --- a/tools/binary-repo-lib.sh +++ b/tools/binary-repo-lib.sh @@ -208,7 +208,7 @@ pullJarFile() { local sha1=$(cat ${jar}${desired_ext}) local jar_dir=$(dirname $jar) local jar_name=${jar#$jar_dir/} - local version=${sha1% ?$jar_name} + local version=${sha1%% *} local remote_uri=${version}/${jar#$basedir/} echo "Resolving [${remote_uri}]" pullJarFileToCache $remote_uri $version diff --git a/tools/make-release-notes b/tools/make-release-notes deleted file mode 100755 index dcd206f7fc..0000000000 --- a/tools/make-release-notes +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -# This tool is used to build a *scaffold* of a release note that you can fill in details with before posting to the list. -# It aims to provide *all* the information you need, and probably need to prune it before releasing. -# Author: jsuereth - -fixMessages() { - local tag1="$1" - local tag2="$2" - git log $tag1..$tag2 "--format=format: * %h - %s" --no-merges --grep "SI-" -} - -allcommitMessages() { - local tag1="$1" - local tag2="$2" - git log $tag1..$tag2 "--format=format: * %h - %s" --no-merges -} - -authors() { - local tag1="$1" - local tag2="$2" - git log $tag1..$tag2 --format=format:%an --no-merges | sort | uniq -c | sort -rh -} - - -message() { - local tag1="$1" - local tag2="$2" - - echo "A new release of Scala is available! Please point your build tools at ${tag2#v}" - echo - echo "Here's a list of the issues that have been fixed since ${tag1#v}: " - fixMessages "$tag1" "$tag2" - echo - echo - echo "Special thanks to all the contributions!" - echo "------- --------------------------------" - authors "$tag1" "$tag2" - echo "------- --------------------------------" - echo - echo - echo "Here's a complete list of changes:" - allcommitMessages "$tag1" "$tag2" -} - - -message "$1" "$2" - - diff --git a/tools/make-release-notes.scala b/tools/make-release-notes.scala new file mode 100644 index 0000000000..3e5b60d223 --- /dev/null +++ b/tools/make-release-notes.scala @@ -0,0 +1,129 @@ +#!/bin/sh +exec scala -feature $0 $@ +!# + +import sys.process._ + +val tag1 = "v2.10.0-M4" +val tag2 = "v2.10.0-M5" + +// Git commit parsing magikz + +case class Commit(sha: String, author: String, header: String, body: String) { + override def toString = " * " + sha + " (" + author + ") " + header + " - " + body.take(5) + " ..." +} + +val gitFormat = "--format=format:*-*%h``%aN``%s``%b" + +def processGitCommits(input: String): IndexedSeq[Commit] = + ((input split "[\\r\\n]*\\*\\-\\*").view map (_ split "``") collect { + case Array(sha, author, hdr, msg) => Commit(sha, author, hdr, msg) + }).toVector + +val commits = + processGitCommits(Process(Seq("git", "log", tag1+".."+tag2,"--format=format:*-*%h``%aN``%s``%b","--no-merges")).!!) + +val authors: Seq[(String, Int)] = { + val grouped: Vector[(String,Int)] = (commits groupBy (_.author)).map { case (a,c) => a -> c.length }{collection.breakOut} + (grouped sortBy (_._2)).reverse +} + +def hasFixins(msg: String): Boolean = ( + (msg contains "SI-") /*&& ((msg.toLowerCase contains "fix") || (msg.toLowerCase contains "close"))*/ +) + +val fixCommits = + for { + commit <- commits + searchString = commit.body + commit.header + if hasFixins(searchString) + } yield commit + + +val siPattern = java.util.regex.Pattern.compile("(SI-[0-9]+)") + +def fixLinks(commit: Commit): String = { + val searchString = commit.body + commit.header + val m = siPattern matcher searchString + val issues = new collection.mutable.ArrayBuffer[String] + while(m.find()) { + issues += (m group 1) + } + issues map (si => """<a href="https://issues.scala-lang.org/browse/%s">%s</a>""" format (si, si)) mkString ", " +} + + +// HTML Generation for Toni + +def commitShaLink(sha: String) = + """<a href="https://github.com/scala/scala/commit/%s">%s</a>""" format (sha,sha) + +def printBlankLine(): Unit = println("<p> </p>") +def printHeader4(msg: String): Unit = println("<h4>%s</h4>" format (msg)) + +def printCommiterList(): Unit = { + printBlankLine() + printHeader4("Special thanks to all the contribtuors!") + println("""<table border="0" cellspacing="0" cellpadding="1"> + <thead><tr><th>#</th><th align="left">Author</th></tr></thead> + <tbody>""") + for((author, count) <- authors) + println("""<tr><td align="right">%d </td><td>%s</td></tr>""" format (count, author)) + println("""</tbody> +</table>""") +} + +def printCommitList(): Unit = { + printBlankLine() + printHeader4("Complete commit list!") + println("""<table border="0" cellspacing="0" cellpadding="1"> + <thead><tr><th>sha</th><th align="left">Title</th></tr></thead> + <tbody>""") + for(commit <- commits) { + println("<tr>") + println("""<td align="right">%s </td><td>%s</td>""" format (commitShaLink(commit.sha), commit.header)) + /*print("<td>") + (commit.body split "[\\r\\n]") foreach { line => + print(line) + print("<br/>") + } + print("</td>")*/ + println("""</tr>""") + } + println("""</tbody> +</table>""") +} + +def issueFixPrinter(): Unit = { + printBlankLine() + printHeader4("Here's a list of isssues that have been fixed since %s" format (tag1)) + println("""<table border="0" cellspacing="0" cellpading="1"> + <thead><tr><th>Issue(s)</th><th>Commit</th><th>Message</th></tr></thead> + <tbody>""") + for(commit <- fixCommits) { + println("""<tr><td>%s </td><td>%s </td><td>%s</td></tr>""" format(fixLinks(commit), commitShaLink(commit.sha), commit.header)) + } + println("""</tbody> +</table>""") + printBlankLine() +} + +def printHTML(): Unit = { + println("""<html> + <head> + <title>%s - Release notes</title> + </head> + <body> + <h3>A new release of Scala is available! Please point your build tools at %s</h3> + <p>:: INSERT HAND GENERATED NOTES HERE ::</p> +""" format(tag2, tag2 drop 1)) + issueFixPrinter() + printCommiterList() + printCommitList() + println("""</body></html>""") +} + +printHTML() + + + diff --git a/tools/partest-ack b/tools/partest-ack new file mode 100755 index 0000000000..0c8244257b --- /dev/null +++ b/tools/partest-ack @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# +# wrapper around partest for fine-grained test selection via ack + +args="$@" + +pathMatches () { + ack --noenv --text --files-with-matches "$@" test/files + + for p in $(find test/files/* -print); do + [[ $p =~ $1 ]] && echo "$p" + done +} + +testIds () { + pathMatches "$@" | \ + perl -pe 's#^(test/files/[^/]+/[^/.]+).*$#$1#' | \ + sort -u +} +testPaths () { + for id in "$@"; do + if [[ -d $id ]]; then + echo $id + elif [[ -f ${id}.scala ]]; then + echo "${id}.scala" + else + echo >&2 "No test corresponds to $id" + fi + done +} + +[[ $# -gt 0 ]] || { + cat <<EOM +Usage: $0 <regex> [ack options] + +Given a regular expression (and optionally, any arguments accepted by ack) +runs all the tests for which any associated file matches the regex. Associated +files include .check and .flags files. Tests in directories will match if any +file matches. A file can match the regex by its contents or by its name. + +You must have ack installed: http://betterthangrep.com/ack-standalone + +Examples: + + % tools/partest-ack monad + Found 4 tests matching 'ack monad' + + Testing individual files + testing: [...]/files/pos/tcpoly_boundedmonad.scala [ OK ] + testing: [...]/files/pos/tcpoly_ticket2096.scala [ OK ] + testing: [...]/files/run/tcpoly_monads.scala [ OK ] + testing: [...]/files/presentation/callcc-interpreter [ OK ] + + % tools/partest-ack monad -i # -i == ignore case + Found 12 tests matching 'ack monad -i' + + Testing individual files + [etc] +EOM + + exit 0 +} + +paths=$(testPaths $(testIds "$@")) +if [[ -z $paths ]]; then + echo >&2 "No matching tests." +else + count=$(echo $(echo "$paths" | wc -w)) + echo "Found $count tests matching 'ack $@'" + test/partest $paths +fi |