diff options
author | Paul Phillips <paulp@improving.org> | 2012-08-17 09:14:09 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-08-17 09:14:09 -0700 |
commit | b794f4a87f5217fd381f129cd75946a2ced6eb44 (patch) | |
tree | 872c1c5b20effcc499a3b1141ab4d9c1900bf2a9 | |
parent | 62d319e46ff672f523e266009025fe3723651229 (diff) | |
parent | 7fc860963a4f76cb18e44c20f2bdfb49641033f3 (diff) | |
download | scala-b794f4a87f5217fd381f129cd75946a2ced6eb44.tar.gz scala-b794f4a87f5217fd381f129cd75946a2ced6eb44.tar.bz2 scala-b794f4a87f5217fd381f129cd75946a2ced6eb44.zip |
Merge remote-tracking branch 'origin/2.10.x' into merge-210
# By Eugene Burmako (12) and others
# Via Paul Phillips (4) and others
* origin/2.10.x:
Fixes SI-6236.
Fixes SI-6189.
Hunting down eliminable :: allocations.
Absolutize tools.nsc => scala.tools.nsc.
more cleanup for typedMacroBody
shaves more than 150 lines off typedMacroBody
Optimization in SubstMap.
removes dead code
pull request feedback
more macro cleanup
further cleanup of transformTypeTagEvidenceParams
macroImplSigs => macroImplSig
Dominik's comments on api.Mirrors
phaseId(currentPeriod) >= erasurePhase.id
materializeImplicit and implicitsOfExpectedType
cleanup of reflection- and macro-related stuff
adds the `skipPackage` attribute to Scaladoc
Fixes backend crash due to incorrect consumedTypes
Fix SI-6208. mutable.Queue now returns mutable.Queue for collection methods rather than MutableList.
131 files changed, 1005 insertions, 1116 deletions
@@ -2178,6 +2178,7 @@ DOCUMENTATION docfooter="epfl" docsourceurl="${scaladoc.url}€{FILE_PATH}.scala#L1" docUncompilable="${src.dir}/library-aux" + skipPackages="scala.reflect.macros" sourcepath="${src.dir}" classpathref="pack.classpath" addparams="${scalac.args.all}" diff --git a/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala index 69fa416f8f..c5c1c84cde 100644 --- a/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/macros/runtime/FrontEnds.scala @@ -41,7 +41,7 @@ trait FrontEnds extends scala.tools.reflect.FrontEnds { } def interactive(): Unit = universe.reporter match { - case reporter: tools.nsc.reporters.AbstractReporter => reporter.displayPrompt() + case reporter: scala.tools.nsc.reporters.AbstractReporter => reporter.displayPrompt() case _ => () } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala b/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala index 19fb03364e..0a8a8d015d 100644 --- a/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala +++ b/src/compiler/scala/reflect/macros/runtime/Infrastructure.scala @@ -18,19 +18,7 @@ trait Infrastructure { val libraryClassPath: List[java.net.URL] = universe.classPath.asURLs - lazy val libraryClassLoader: ClassLoader = { - val classpath = libraryClassPath - var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - - // [Eugene] a heuristic to detect REPL - if (universe.settings.exposeEmptyPackage.value) { - import scala.tools.nsc.interpreter._ - val virtualDirectory = universe.settings.outputDirs.getSingleOutput.get - loader = new AbstractFileClassLoader(virtualDirectory, loader) {} - } - - loader - } + lazy val libraryClassLoader: ClassLoader = universe.analyzer.macroClassloader type Run = universe.Run diff --git a/src/compiler/scala/reflect/macros/runtime/Settings.scala b/src/compiler/scala/reflect/macros/runtime/Settings.scala index 9c24273cd7..e9d9a17b81 100644 --- a/src/compiler/scala/reflect/macros/runtime/Settings.scala +++ b/src/compiler/scala/reflect/macros/runtime/Settings.scala @@ -13,18 +13,17 @@ trait Settings { def compilerSettings: List[String] = universe.settings.recreateArgs def setCompilerSettings(options: String): this.type = - // todo. is not going to work with quoted arguments with embedded whitespaces + // SI-5925: doesn't work with arguments that contains whitespaces setCompilerSettings(options.split(" ").toList) def setCompilerSettings(options: List[String]): this.type = { - val settings = new tools.nsc.Settings(_ => ()) - // [Eugene] what settings should we exclude? + val settings = new scala.tools.nsc.Settings(_ => ()) settings.copyInto(universe.settings) this } def withCompilerSettings[T](options: String)(op: => T): T = - // todo. is not going to work with quoted arguments with embedded whitespaces + // SI-5925: doesn't work with arguments that contains whitespaces withCompilerSettings(options.split(" ").toList)(op) def withCompilerSettings[T](options: List[String])(op: => T): T = { diff --git a/src/compiler/scala/reflect/macros/util/Traces.scala b/src/compiler/scala/reflect/macros/util/Traces.scala index 6c2f115994..d16916b753 100644 --- a/src/compiler/scala/reflect/macros/util/Traces.scala +++ b/src/compiler/scala/reflect/macros/util/Traces.scala @@ -2,17 +2,12 @@ package scala.reflect.macros package util trait Traces { - def globalSettings: tools.nsc.Settings + def globalSettings: scala.tools.nsc.Settings - // [Eugene] lots of ways to log: - // 1) trace(...) - // 2) log(...) - // 3) if (foo) { doStuff(); includingSomeLogs(); } - // what is the conventional way of unifying this? val macroDebugLite = globalSettings.YmacrodebugLite.value val macroDebugVerbose = globalSettings.YmacrodebugVerbose.value val macroTraceLite = scala.tools.nsc.util.trace when (macroDebugLite || macroDebugVerbose) val macroTraceVerbose = scala.tools.nsc.util.trace when macroDebugVerbose @inline final def macroLogLite(msg: => Any) { if (macroDebugLite || macroDebugVerbose) println(msg) } @inline final def macroLogVerbose(msg: => Any) { if (macroDebugVerbose) println(msg) } -}
\ 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 30b232c779..2b6ce23d57 100644 --- a/src/compiler/scala/reflect/reify/Reifier.scala +++ b/src/compiler/scala/reflect/reify/Reifier.scala @@ -52,7 +52,6 @@ abstract class Reifier extends States */ lazy val reification: Tree = { try { - // [Eugene] conventional way of doing this? if (universe exists (_.isErroneous)) CannotReifyErroneousPrefix(universe) if (universe.tpe == null) CannotReifyUntypedPrefix(universe) @@ -62,7 +61,6 @@ abstract class Reifier extends States reifyTrace("reifee is located at: ")(tree.pos) reifyTrace("universe = ")(universe) reifyTrace("mirror = ")(mirror) - // [Eugene] conventional way of doing this? if (tree exists (_.isErroneous)) CannotReifyErroneousReifee(tree) if (tree.tpe == null) CannotReifyUntypedReifee(tree) val pipeline = mkReificationPipeline @@ -108,11 +106,7 @@ abstract class Reifier extends States // // todo. this is a common problem with non-trivial macros in our current macro system // needs to be solved some day - // - // list of non-hygienic transformations: - // todo. to be updated - // [Eugene++] yeah, ugly and extremely brittle, but we do need to do resetAttrs. will be fixed later - // todo. maybe try `resetLocalAttrs` once the dust settles + // maybe try `resetLocalAttrs` once the dust settles var importantSymbols = Set[Symbol]( NothingClass, AnyClass, SingletonClass, PredefModule, ScalaRunTimeModule, TypeCreatorClass, TreeCreatorClass, MirrorOfClass, BaseUniverseClass, JavaUniverseClass, ReflectRuntimePackage, ReflectRuntimeCurrentMirror) diff --git a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala index 7f066a2cc3..ca6e14cfd3 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenSymbols.scala @@ -72,6 +72,7 @@ trait GenSymbols { */ val hasPackagelessParent = sym.ownerChain.tail.tail exists (_.isEmptyPackageClass) if (sym.isStatic && (sym.isClass || sym.isModule) && !hasPackagelessParent) { + // SI-6238: if applicable, emit references to StandardDefinitions instead of staticClass/staticModule calls val resolver = if (sym.isType) nme.staticClass else nme.staticModule mirrorMirrorCall(resolver, reify(sym.fullName)) } else { diff --git a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala index c762a28f99..1d2e177688 100644 --- a/src/compiler/scala/reflect/reify/codegen/GenTypes.scala +++ b/src/compiler/scala/reflect/reify/codegen/GenTypes.scala @@ -23,7 +23,7 @@ trait GenTypes { if (isSemiConcreteTypeMember(tpe)) return reifySemiConcreteTypeMember(tpe) - // [Eugene] how do I check that the substitution is legal w.r.t tpe.info? + // SI-6242: splicing might violate type bounds val spliced = spliceType(tpe) if (spliced != EmptyTree) return spliced @@ -69,7 +69,6 @@ trait GenTypes { def reificationIsConcrete: Boolean = state.reificationIsConcrete def spliceType(tpe: Type): Tree = { - // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird! val quantified = currentQuantified if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) { if (reifyDebug) println("splicing " + tpe) diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala index 41cf6c066a..4d1e22abe7 100644 --- a/src/compiler/scala/reflect/reify/phases/Calculate.scala +++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala @@ -9,7 +9,7 @@ trait Calculate { implicit class RichCalculateSymbol(sym: Symbol) { def metalevel: Int = { assert(sym != null && sym != NoSymbol); localSymbols.getOrElse(sym, 0) } - def isLocalToReifee = (localSymbols contains sym) // [Eugene] how do I account for local skolems? + def isLocalToReifee = (localSymbols contains sym) // todo. how do I account for local skolems? } implicit class RichCalculateType(tpe: Type) { diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala index e26dd7e227..fcf3c0e65c 100644 --- a/src/compiler/scala/reflect/reify/phases/Reshape.scala +++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala @@ -248,7 +248,6 @@ trait Reshape { New(TypeTree(ann.atp) setOriginal extractOriginal(ann.original), List(args)) } - // [Eugene] is this implemented correctly? private def trimAccessors(deff: Tree, stats: List[Tree]): List[Tree] = { val symdefs = (stats collect { case vodef: ValOrDefDef => vodef } map (vodeff => vodeff.symbol -> vodeff)).toMap val accessors = collection.mutable.Map[ValDef, List[DefDef]]() @@ -287,7 +286,7 @@ trait Reshape { val name1 = nme.dropLocalSuffix(name) val vdef1 = ValDef(mods2, name1, tpt, rhs) if (reifyDebug) println("resetting visibility of field: %s => %s".format(vdef, vdef1)) - Some(vdef1) // no copyAttrs here, because new ValDef and old symbols are not out of sync + Some(vdef1) // no copyAttrs here, because new ValDef and old symbols are now out of sync case ddef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) => if (accessors.values.exists(_.contains(ddef))) { if (reifyDebug) println("discarding accessor method: " + ddef) diff --git a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala index 420f55c0e0..ec1f132c1b 100644 --- a/src/compiler/scala/reflect/reify/utils/NodePrinters.scala +++ b/src/compiler/scala/reflect/reify/utils/NodePrinters.scala @@ -23,6 +23,7 @@ trait NodePrinters { // depended upon. Of more fragile code I cannot conceive. // @Eugene: This stuff is only needed to debug-print out reifications in human-readable format // 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 { diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala index b96ac6f29b..b2c6441222 100644 --- a/src/compiler/scala/tools/ant/Scaladoc.scala +++ b/src/compiler/scala/tools/ant/Scaladoc.scala @@ -44,7 +44,8 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} * - `docgenerator`, * - `docrootcontent`, * - `unchecked`, - * - `nofail`. + * - `nofail`, + * - `skipPackages`. * * It also takes the following parameters as nested elements: * - `src` (for srcdir), @@ -159,6 +160,9 @@ class Scaladoc extends ScalaMatchingTask { /** Instruct the scaladoc tool to group similar functions together */ private var docGroups: Boolean = false + /** Instruct the scaladoc tool to skip certain packages */ + private var docSkipPackages: String = "" + /*============================================================================*\ ** Properties setters ** \*============================================================================*/ @@ -442,6 +446,12 @@ class Scaladoc extends ScalaMatchingTask { def setGroups(input: String) = docGroups = Flag.getBooleanValue(input, "groups") + /** Instruct the scaladoc tool to skip certain packages. + * @param input A colon-delimited list of fully qualified package names that will be skipped from scaladoc. + */ + def setSkipPackages(input: String) = + docSkipPackages = input + /*============================================================================*\ ** Properties getters ** \*============================================================================*/ @@ -642,6 +652,7 @@ class Scaladoc extends ScalaMatchingTask { docSettings.docRawOutput.value = docRawOutput docSettings.docNoPrefixes.value = docNoPrefixes docSettings.docGroups.value = docGroups + docSettings.docSkipPackages.value = docSkipPackages if(!docDiagramsDotPath.isEmpty) docSettings.docDiagramsDotPath.value = docDiagramsDotPath.get if (!docgenerator.isEmpty) docSettings.docgenerator.value = docgenerator.get diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 6ecdbf1f3f..ce9153e70a 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -42,8 +42,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) with DocComments with Positions { self => - // [Eugene++] would love to find better homes for the new things dumped into Global - // the mirror -------------------------------------------------- override def isCompilerUniverse = true @@ -61,16 +59,14 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } def RootClass: ClassSymbol = rootMirror.RootClass def EmptyPackageClass: ClassSymbol = rootMirror.EmptyPackageClass - // [Eugene++] this little inconvenience gives us precise types for Expr.mirror and TypeTag.mirror - // by the way, is it possible to define variant type members? - - override def settings = currentSettings import definitions.findNamedMember def findMemberFromRoot(fullName: Name): Symbol = rootMirror.findMemberFromRoot(fullName) // alternate constructors ------------------------------------------ + override def settings = currentSettings + def this(reporter: Reporter) = this(new Settings(err => reporter.error(null, err)), reporter) @@ -827,8 +823,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Is given package class a system package class that cannot be invalidated? */ private def isSystemPackageClass(pkg: Symbol) = - // [Eugene++ to Martin] please, verify -// was: pkg == definitions.RootClass || pkg == RootClass || pkg == definitions.ScalaPackageClass || { val pkgname = pkg.fullName @@ -891,8 +885,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) else new MergedClassPath(elems, classPath.context) val oldEntries = mkClassPath(subst.keys) val newEntries = mkClassPath(subst.values) - // [Eugene++ to Martin] please, verify -// was: reSync(definitions.RootClass, Some(classPath), Some(oldEntries), Some(newEntries), invalidated, failed) reSync(RootClass, Some(classPath), Some(oldEntries), Some(newEntries), invalidated, failed) } } @@ -952,8 +944,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) invalidateOrRemove(root) } else { if (classesFound) { - // [Eugene++ to Martin] please, verify -// was: if (root.isRoot) invalidateOrRemove(definitions.EmptyPackageClass) if (root.isRoot) invalidateOrRemove(EmptyPackageClass) else failed += root } diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala index 1fdf4c631e..0b54eda66d 100644 --- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala @@ -145,8 +145,7 @@ abstract class NodePrinters { str.toString } def printModifiers(tree: MemberDef) { - // [Eugene++] there's most likely a bug here (?) - // see `Printers.printAnnotations` for more information + // SI-5885: by default this won't print annotations of not yet initialized symbols val annots0 = tree.symbol.annotations match { case Nil => tree.mods.annotations case xs => xs map annotationInfoToString diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala index 74d1f8ab4b..d8fb632f73 100644 --- a/src/compiler/scala/tools/nsc/ast/Positions.scala +++ b/src/compiler/scala/tools/nsc/ast/Positions.scala @@ -11,13 +11,6 @@ trait Positions extends scala.reflect.internal.Positions { def validatePositions(tree: Tree) {} - // [Eugene] disabling this for now. imo it doesn't justify pollution of the public API - // override def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = { - // if (tree.pos != NoPosition && tree.pos != annot.pos) debugwarn("Overwriting annotation "+ tree.annotation +" of tree "+ tree +" with annotation "+ annot) - // // if ((tree.annotation.isInstanceOf[scala.reflect.internal.util.Position] || !annot.isInstanceOf[scala.reflect.internal.util.Position]) && tree.isInstanceOf[Block]) - // // println("Updating block from "+ tree.annotation +" to "+ annot) - // } - class ValidatingPosAssigner extends PosAssigner { var pos: Position = _ override def traverse(t: Tree) { diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 2ee38d4b91..e90d779885 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -95,7 +95,7 @@ trait TreeDSL { 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) def GEN_& (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.AND), other) @@ -234,7 +234,7 @@ trait TreeDSL { } class DefTreeStart(val name: Name) extends TreeVODDStart with DefCreator { def tparams: List[TypeDef] = Nil - def vparamss: List[List[ValDef]] = List(Nil) + def vparamss: List[List[ValDef]] = ListOfNil } class IfStart(cond: Tree, thenp: Tree) { diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index d7352045f5..3ccd8ec4ae 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -44,7 +44,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { setInfo analyzer.ImportType(qual) ) val importTree = ( - Import(qual, List(ImportSelector(nme.WILDCARD, -1, null, -1))) + Import(qual, ImportSelector.wildList) setSymbol importSym setType NoType ) @@ -58,7 +58,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { def mkUnchecked(expr: Tree): Tree = atPos(expr.pos) { // This can't be "Annotated(New(UncheckedClass), expr)" because annotations // are very picky about things and it crashes the compiler with "unexpected new". - Annotated(New(scalaDot(UncheckedClass.name), List(Nil)), expr) + Annotated(New(scalaDot(UncheckedClass.name), ListOfNil), expr) } // if it's a Match, mark the selector unchecked; otherwise nothing. def mkUncheckedMatch(tree: Tree) = tree match { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 381b834a0c..b703a90ebf 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -111,16 +111,13 @@ trait Trees extends reflect.internal.Trees { self: Global => if (body forall treeInfo.isInterfaceMember) List() else List( atPos(wrappingPos(superPos, lvdefs)) ( - DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(Constant()))))) + DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), ListOfNil, TypeTree(), Block(lvdefs, Literal(Constant()))))) } else { // 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) - def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) - val superCall = (superRef /: argss) (mkApply) - // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal - // val superCall = (superRef /: argss) (Apply) + val superCall = (superRef /: argss) (Apply.apply) List( atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant()))))) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 391874c488..cbe9d96e4d 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -192,7 +192,7 @@ self => override def blockExpr(): Tree = skipBraces(EmptyTree) - override def templateBody(isPre: Boolean) = skipBraces((emptyValDef, List(EmptyTree))) + override def templateBody(isPre: Boolean) = skipBraces((emptyValDef, EmptyTree.asList)) } class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends SourceFileParser(unit.source) { @@ -395,7 +395,7 @@ self => NoMods, nme.CONSTRUCTOR, Nil, - List(Nil), + ListOfNil, TypeTree(), Block(List(Apply(gen.mkSuperSelect, Nil)), Literal(Constant(()))) ) @@ -404,7 +404,7 @@ self => def mainParamType = AppliedTypeTree(Ident(tpnme.Array), List(Ident(tpnme.String))) def mainParameter = List(ValDef(Modifiers(Flags.PARAM), nme.argv, mainParamType, EmptyTree)) def mainSetArgv = List(ValDef(NoMods, nme.args, TypeTree(), Ident(nme.argv))) - def mainNew = makeNew(Nil, emptyValDef, stmts, List(Nil), NoPosition, NoPosition) + def mainNew = makeNew(Nil, emptyValDef, stmts, ListOfNil, NoPosition, NoPosition) def mainDef = DefDef(NoMods, nme.main, Nil, List(mainParameter), scalaDot(tpnme.Unit), Block(mainSetArgv, mainNew)) // object Main @@ -2093,7 +2093,7 @@ self => def annotationExpr(): Tree = atPos(in.offset) { val t = exprSimpleType() if (in.token == LPAREN) New(t, multipleArgumentExprs()) - else New(t, List(Nil)) + else New(t, ListOfNil) } /* -------- PARAMETERS ------------------------------------------- */ @@ -2732,10 +2732,10 @@ self => def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = { val parents = new ListBuffer[Tree] += startAnnotType() val argss = ( - // TODO: the insertion of List(Nil) here is where "new Foo" becomes + // TODO: the insertion of ListOfNil here is where "new Foo" becomes // indistinguishable from "new Foo()". if (in.token == LPAREN && !isTrait) multipleArgumentExprs() - else List(Nil) + else ListOfNil ) while (in.token == WITH) { @@ -2773,7 +2773,7 @@ self => val (self1, body1) = templateBodyOpt(traitParentSeen = isTrait) (parents, argss, self1, earlyDefs ::: body1) } else { - (List(), List(List()), self, body) + (List(), ListOfNil, self, body) } } else { val (parents, argss) = templateParents(isTrait = isTrait) @@ -2800,7 +2800,7 @@ self => else { newLineOptWhenFollowedBy(LBRACE) val (self, body) = templateBodyOpt(traitParentSeen = false) - (List(), List(List()), self, body) + (List(), ListOfNil, self, body) } ) def anyrefParents() = { @@ -2813,7 +2813,7 @@ self => def anyvalConstructor() = ( // Not a well-formed constructor, has to be finished later - see note // regarding AnyVal constructor in AddInterfaces. - DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(), Block(Nil, Literal(Constant()))) + DefDef(NoMods, nme.CONSTRUCTOR, Nil, ListOfNil, TypeTree(), Block(Nil, Literal(Constant()))) ) val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart @@ -2834,7 +2834,7 @@ self => * @param isPre specifies whether in early initializer (true) or not (false) */ def templateBody(isPre: Boolean) = inBraces(templateStatSeq(isPre = isPre)) match { - case (self, Nil) => (self, List(EmptyTree)) + case (self, Nil) => (self, EmptyTree.asList) case result => result } def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = { @@ -2938,7 +2938,7 @@ self => /** Informal - for the repl and other direct parser accessors. */ def templateStats(): List[Tree] = templateStatSeq(isPre = false)._2 match { - case Nil => List(EmptyTree) + case Nil => EmptyTree.asList case stats => stats } diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index 5afec611e9..146329183c 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -162,7 +162,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) { /** could optimize if args.length == 0, args.length == 1 AND args(0) is <: Node. */ def makeXMLseq(pos: Position, args: Seq[Tree]) = { - val buffer = ValDef(NoMods, _buf, TypeTree(), New(_scala_xml_NodeBuffer, List(Nil))) + val buffer = ValDef(NoMods, _buf, TypeTree(), New(_scala_xml_NodeBuffer, ListOfNil)) val applies = args filterNot isEmptyText map (t => Apply(Select(Ident(_buf), _plus), List(t))) atPos(pos)( Block(buffer :: applies.toList, Ident(_buf)) ) diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 73f5ec7b3c..1cd1b63691 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -217,12 +217,12 @@ abstract class TreeBuilder { atPos(cpos) { ClassDef( Modifiers(FINAL), x, Nil, - Template(parents, self, NoMods, List(Nil), argss, stats, cpos.focus)) + Template(parents, self, NoMods, ListOfNil, argss, stats, cpos.focus)) }), atPos(npos) { New( Ident(x) setPos npos.focus, - List(Nil)) + ListOfNil) } ) } @@ -546,10 +546,7 @@ abstract class TreeBuilder { rhs1, List( atPos(pat1.pos) { - def mkIdent(name: Name) = Ident(name) - CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map mkIdent, true)) - // [Eugene++] no longer compiles after I moved the `Ident` case class into scala.reflect.internal - // CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) + CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident.apply, true)) } )) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index a480429026..a40d8c1a06 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -880,14 +880,29 @@ abstract class GenICode extends SubComponent { case app @ Apply(fun @ Select(qual, _), args) if !ctx.method.symbol.isStaticConstructor - && fun.symbol.isAccessor && fun.symbol.accessed.hasStaticAnnotation => + && fun.symbol.isAccessor && fun.symbol.accessed.hasStaticAnnotation + && qual.tpe.typeSymbol.orElse(fun.symbol.owner).companionClass != NoSymbol => // bypass the accessor to the companion object and load the static field directly - // the only place were this bypass is not done, is the static intializer for the static field itself + // this bypass is not done: + // - if the static intializer for the static field itself + // - if there is no companion class of the object owner - this happens in the REPL val sym = fun.symbol generatedType = toTypeKind(sym.accessed.info) - val hostClass = qual.tpe.typeSymbol.orElse(sym.owner).companionClass - val staticfield = hostClass.info.findMember(sym.accessed.name, NoFlags, NoFlags, false) - + val hostOwner = qual.tpe.typeSymbol.orElse(sym.owner) + val hostClass = hostOwner.companionClass + val staticfield = hostClass.info.findMember(sym.accessed.name, NoFlags, NoFlags, false) orElse { + if (!currentRun.compiles(hostOwner)) { + // hostOwner was separately compiled -- the static field symbol needs to be recreated in hostClass + import Flags._ + debuglog("recreating sym.accessed.name: " + sym.accessed.name) + val objectfield = hostOwner.info.findMember(sym.accessed.name, NoFlags, NoFlags, false) + val staticfield = hostClass.newVariable(newTermName(sym.accessed.name.toString), tree.pos, STATIC | SYNTHETIC | FINAL) setInfo objectfield.tpe + staticfield.addAnnotation(definitions.StaticClass) + hostClass.info.decls enter staticfield + staticfield + } else NoSymbol + } + if (sym.isGetter) { ctx.bb.emit(LOAD_FIELD(staticfield, true) setHostClass hostClass, tree.pos) ctx diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index a8d517aa74..ffe8c8afe3 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -2,11 +2,6 @@ * Copyright 2005-2012 LAMP/EPFL * @author Martin Odersky */ -/* NSC -- new scala compiler - * Copyright 2005-2012 LAMP/EPFL - * @author Martin Odersky - */ - package scala.tools.nsc package backend diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala index 4311fe9df5..1fcb406e96 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala @@ -82,10 +82,17 @@ trait Opcodes { self: ICodes => final val jumpsCat = 10 final val retCat = 11 + private lazy val ObjectReferenceList = ObjectReference :: Nil + /** This class represents an instruction of the intermediate code. * Each case subclass will represent a specific operation. */ abstract class Instruction extends Cloneable { + // Vlad: I used these for checking the quality of the implementation, and we should regularely run a build with them + // enabled. But for production these should definitely be disabled, unless we enjoy getting angry emails from Greg :) + //if (!this.isInstanceOf[opcodes.LOAD_EXCEPTION]) + // assert(consumed == consumedTypes.length) + //assert(produced == producedTypes.length) def category: Int = 0 // undefined @@ -101,6 +108,7 @@ trait Opcodes { self: ICodes => def consumedTypes: List[TypeKind] = Nil /** This instruction produces these types on top of the stack. */ + // 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 */ @@ -143,7 +151,12 @@ trait Opcodes { self: ICodes => override def consumed = 0 override def produced = 1 - override def producedTypes = List(REFERENCE(clasz)) + override def producedTypes = + // we're not allowed to have REFERENCE(Array), but what about compiling the Array class? Well, we use object for it. + if (clasz != global.definitions.ArrayClass) + REFERENCE(clasz) :: Nil + else + ObjectReference :: Nil override def category = localsCat } @@ -157,7 +170,7 @@ trait Opcodes { self: ICodes => override def consumed = 0 override def produced = 1 - override def producedTypes = List(toTypeKind(constant.tpe)) + override def producedTypes = toTypeKind(constant.tpe) :: Nil override def category = constCat } @@ -171,8 +184,8 @@ trait Opcodes { self: ICodes => override def consumed = 2 override def produced = 1 - override def consumedTypes = List(ARRAY(kind), INT) - override def producedTypes = List(kind) + override def consumedTypes = ARRAY(kind) :: INT :: Nil + override def producedTypes = kind :: Nil override def category = arraysCat } @@ -185,7 +198,7 @@ trait Opcodes { self: ICodes => override def consumed = 0 override def produced = 1 - override def producedTypes = List(local.kind) + override def producedTypes = local.kind :: Nil override def category = localsCat } @@ -203,8 +216,8 @@ trait Opcodes { self: ICodes => override def consumed = if (isStatic) 0 else 1 override def produced = 1 - override def consumedTypes = if (isStatic) Nil else List(REFERENCE(field.owner)); - override def producedTypes = List(toTypeKind(field.tpe)); + override def consumedTypes = if (isStatic) Nil else REFERENCE(field.owner) :: Nil + override def producedTypes = toTypeKind(field.tpe) :: Nil // more precise information about how to load this field // see #4283 @@ -222,7 +235,7 @@ trait Opcodes { self: ICodes => override def consumed = 0 override def produced = 1 - override def producedTypes = List(REFERENCE(module)) + override def producedTypes = REFERENCE(module) :: Nil override def category = stackCat } @@ -235,7 +248,7 @@ trait Opcodes { self: ICodes => override def consumed = 3 override def produced = 0 - override def consumedTypes = List(ARRAY(kind), INT, kind) + override def consumedTypes = ARRAY(kind) :: INT :: kind :: Nil override def category = arraysCat } @@ -248,7 +261,7 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 - override def consumedTypes = List(local.kind) + override def consumedTypes = local.kind :: Nil override def category = localsCat } @@ -267,9 +280,9 @@ trait Opcodes { self: ICodes => override def consumedTypes = if (isStatic) - List(toTypeKind(field.tpe)) + toTypeKind(field.tpe) :: Nil else - List(REFERENCE(field.owner), toTypeKind(field.tpe)); + REFERENCE(field.owner) :: toTypeKind(field.tpe) :: Nil; override def category = fldsCat } @@ -281,7 +294,7 @@ trait Opcodes { self: ICodes => case class STORE_THIS(kind: TypeKind) extends Instruction { override def consumed = 1 override def produced = 0 - override def consumedTypes = List(kind) + override def consumedTypes = kind :: Nil override def category = localsCat } @@ -308,34 +321,34 @@ trait Opcodes { self: ICodes => override def produced = 1 override def consumedTypes = primitive match { - case Negation(kind) => List(kind) - case Test(_, kind, true) => List(kind) - case Test(_, kind, false) => List(kind, kind) - case Comparison(_, kind) => List(kind, kind) - case Arithmetic(NOT, kind) => List(kind) - case Arithmetic(_, kind) => List(kind, kind) - case Logical(_, kind) => List(kind, kind) - case Shift(_, kind) => List(kind, INT) - case Conversion(from, _) => List(from) - case ArrayLength(kind) => List(ARRAY(kind)) - case StringConcat(kind) => List(ConcatClass, kind) + case Negation(kind) => kind :: Nil + case Test(_, kind, true) => kind :: Nil + case Test(_, kind, false) => kind :: kind :: Nil + case Comparison(_, kind) => kind :: kind :: Nil + case Arithmetic(NOT, kind) => kind :: Nil + case Arithmetic(_, kind) => kind :: kind :: Nil + case Logical(_, kind) => kind :: kind :: Nil + case Shift(_, kind) => kind :: INT :: Nil + case Conversion(from, _) => from :: Nil + case ArrayLength(kind) => ARRAY(kind) :: Nil + case StringConcat(kind) => ConcatClass :: kind :: Nil case StartConcat => Nil - case EndConcat => List(ConcatClass) + case EndConcat => ConcatClass :: Nil } override def producedTypes = primitive match { - case Negation(kind) => List(kind) - case Test(_, _, true) => List(BOOL) - case Test(_, _, false) => List(BOOL) - case Comparison(_, _) => List(INT) - case Arithmetic(_, kind) => List(kind) - case Logical(_, kind) => List(kind) - case Shift(_, kind) => List(kind) - case Conversion(_, to) => List(to) - case ArrayLength(_) => List(INT) - case StringConcat(_) => List(ConcatClass) - case StartConcat => List(ConcatClass) - case EndConcat => List(REFERENCE(global.definitions.StringClass)) + case Negation(kind) => kind :: Nil + case Test(_, _, true) => BOOL :: Nil + case Test(_, _, false) => BOOL :: Nil + case Comparison(_, _) => INT :: Nil + case Arithmetic(_, kind) => kind :: Nil + case Logical(_, kind) => kind :: Nil + case Shift(_, kind) => kind :: Nil + case Conversion(_, to) => to :: Nil + case ArrayLength(_) => INT :: Nil + case StringConcat(_) => ConcatClass :: Nil + case StartConcat => ConcatClass :: Nil + case EndConcat => REFERENCE(global.definitions.StringClass) :: Nil } override def category = arilogCat @@ -381,14 +394,13 @@ trait Opcodes { self: ICodes => else args } - override def produced = - if (producedType == UNIT || method.isConstructor) 0 - else 1 - - private def producedType: TypeKind = toTypeKind(method.info.resultType) - override def producedTypes = - if (produced == 0) Nil - else List(producedType) + private val producedList = toTypeKind(method.info.resultType) match { + case UNIT => Nil + case _ if method.isConstructor => Nil + case kind => kind :: Nil + } + override def produced = producedList.size + override def producedTypes = producedList /** object identity is equality for CALL_METHODs. Needed for * being able to store such instructions into maps, when more @@ -404,15 +416,17 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def consumedTypes = boxType :: Nil override def produced = 1 + override def producedTypes = BOXED(boxType) :: Nil override def category = objsCat } case class UNBOX(boxType: TypeKind) extends Instruction { - assert(boxType.isValueType && (boxType ne UNIT)) // documentation + assert(boxType.isValueType && !boxType.isInstanceOf[BOXED] && (boxType ne UNIT)) // documentation override def toString(): String = "UNBOX " + boxType override def consumed = 1 - override def consumedTypes = ObjectReference :: Nil + override def consumedTypes = ObjectReferenceList override def produced = 1 + override def producedTypes = boxType :: Nil override def category = objsCat } @@ -426,6 +440,7 @@ trait Opcodes { self: ICodes => override def consumed = 0; override def produced = 1; + override def producedTypes = kind :: Nil /** The corresponding constructor call. */ var init: CALL_METHOD = _ @@ -445,6 +460,7 @@ trait Opcodes { self: ICodes => override def consumed = dims; override def consumedTypes = List.fill(dims)(INT) override def produced = 1; + override def producedTypes = ARRAY(elem) :: Nil override def category = arraysCat } @@ -458,8 +474,9 @@ trait Opcodes { self: ICodes => override def toString(): String ="IS_INSTANCE "+typ override def consumed = 1 - override def consumedTypes = ObjectReference :: Nil override def produced = 1 + override def consumedTypes = ObjectReferenceList + override def producedTypes = BOOL :: Nil override def category = castsCat } @@ -474,8 +491,8 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 1 - override val consumedTypes = List(ObjectReference) - override def producedTypes = List(typ) + override def consumedTypes = ObjectReferenceList + override def producedTypes = typ :: Nil override def category = castsCat } @@ -495,7 +512,7 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 - override val consumedTypes = List(INT) + override def consumedTypes = INT :: Nil def flatTagsCount: Int = { var acc = 0; var rest = tags; while(rest.nonEmpty) { acc += rest.head.length; rest = rest.tail }; acc } // a one-liner @@ -536,7 +553,7 @@ trait Opcodes { self: ICodes => override def consumed = 2 override def produced = 0 - override val consumedTypes = List(kind, kind) + override def consumedTypes = kind :: kind :: Nil override def category = jumpsCat } @@ -559,8 +576,7 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 - override val consumedTypes = List(kind) - + override def consumedTypes = kind :: Nil override def category = jumpsCat } @@ -573,7 +589,7 @@ trait Opcodes { self: ICodes => override def consumed = if (kind == UNIT) 0 else 1 override def produced = 0 - // TODO override val consumedTypes = List(kind) + override def consumedTypes = if (kind == UNIT) Nil else kind :: Nil override def category = retCat } @@ -592,6 +608,8 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 + override def consumedTypes = toTypeKind(clasz.tpe) :: Nil + override def category = retCat } @@ -606,6 +624,8 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 + override def consumedTypes = typ :: Nil + override def category = stackCat } @@ -616,6 +636,8 @@ trait Opcodes { self: ICodes => case class DUP (typ: TypeKind) extends Instruction { override def consumed = 1 override def produced = 2 + override def consumedTypes = typ :: Nil + override def producedTypes = typ :: typ :: Nil override def category = stackCat } @@ -630,6 +652,8 @@ trait Opcodes { self: ICodes => override def consumed = 1 override def produced = 0 + override def consumedTypes = ObjectReference :: Nil + override def category = objsCat } @@ -644,6 +668,8 @@ trait Opcodes { self: ICodes => override def consumed = 1; override def produced = 0; + override def consumedTypes = ObjectReference :: Nil + override def category = objsCat } @@ -738,10 +764,10 @@ trait Opcodes { self: ICodes => override def consumed = 0 override def produced = 1 - override def producedTypes = List(msil_mgdptr(local.kind)) + override def producedTypes = msil_mgdptr(local.kind) :: Nil override def category = localsCat - } + } case class CIL_LOAD_FIELD_ADDRESS(field: Symbol, isStatic: Boolean) extends Instruction { /** Returns a string representation of this instruction */ @@ -751,11 +777,11 @@ trait Opcodes { self: ICodes => override def consumed = if (isStatic) 0 else 1 override def produced = 1 - override def consumedTypes = if (isStatic) Nil else List(REFERENCE(field.owner)); - override def producedTypes = List(msil_mgdptr(REFERENCE(field.owner))); + override def consumedTypes = if (isStatic) Nil else REFERENCE(field.owner) :: Nil; + override def producedTypes = msil_mgdptr(REFERENCE(field.owner)) :: Nil; override def category = fldsCat -} + } case class CIL_LOAD_ARRAY_ITEM_ADDRESS(kind: TypeKind) extends Instruction { /** Returns a string representation of this instruction */ @@ -764,8 +790,8 @@ trait Opcodes { self: ICodes => override def consumed = 2 override def produced = 1 - override def consumedTypes = List(ARRAY(kind), INT) - override def producedTypes = List(msil_mgdptr(kind)) + override def consumedTypes = ARRAY(kind) :: INT :: Nil + override def producedTypes = msil_mgdptr(kind) :: Nil override def category = arraysCat } @@ -773,16 +799,16 @@ trait Opcodes { self: ICodes => case class CIL_UNBOX(valueType: TypeKind) extends Instruction { override def toString(): String = "CIL_UNBOX " + valueType override def consumed = 1 - override def consumedTypes = ObjectReference :: Nil // actually consumes a 'boxed valueType' + override def consumedTypes = ObjectReferenceList // actually consumes a 'boxed valueType' override def produced = 1 - override def producedTypes = List(msil_mgdptr(valueType)) + override def producedTypes = msil_mgdptr(valueType) :: Nil override def category = objsCat } case class CIL_INITOBJ(valueType: TypeKind) extends Instruction { override def toString(): String = "CIL_INITOBJ " + valueType override def consumed = 1 - override def consumedTypes = ObjectReference :: Nil // actually consumes a managed pointer + override def consumedTypes = ObjectReferenceList // actually consumes a managed pointer override def produced = 0 override def category = objsCat } @@ -793,9 +819,8 @@ trait Opcodes { self: ICodes => override def consumed = method.tpe.paramTypes.length override def consumedTypes = method.tpe.paramTypes map toTypeKind override def produced = 1 - override def producedTypes = List(toTypeKind(method.tpe.resultType)) + override def producedTypes = toTypeKind(method.tpe.resultType) :: Nil override def category = objsCat } - } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 1a9201fd67..96a88b1b0e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -2217,15 +2217,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters { def getMerged(): 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 merged = mutable.Map.empty[Local, List[Interval]] - - def addToMerged(lv: Local, start: Label, end: Label) { - val ranges = merged.getOrElseUpdate(lv, Nil) - val coalesced = fuse(ranges, Interval(start, end)) - merged.update(lv, coalesced) - } - + val merged = mutable.Map[Local, List[Interval]]() + def addToMerged(lv: Local, start: Label, end: Label) { + val intv = Interval(start, end) + merged(lv) = if (merged contains lv) fuse(merged(lv), intv) else intv :: Nil + } for(LocVarEntry(lv, start, end) <- seen) { addToMerged(lv, start, end) } /* for each var with unbalanced start(s) of scope(s): diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index 327436ed20..89195020c4 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -176,7 +176,7 @@ trait ModelFactoryImplicitSupport { val appliedTree = new ApplyImplicitView(viewTree, List(Ident("<argument>") setType viewTree.tpe.paramTypes.head)) val appliedTreeTyped: Tree = { val newContext = context.makeImplicit(context.ambiguousErrors) - newContext.macrosEnabled = false // [Eugene] I assume you want macro signature, not macro expansion + newContext.macrosEnabled = false val newTyper = global.analyzer.newTyper(newContext) newTyper.silent(_.typed(appliedTree, global.analyzer.EXPRmode, WildcardType), false) match { diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 1626985823..c340b72ec3 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -145,7 +145,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private def _initSources = List(new BatchSourceFile("<init>", "class $repl_$init { }")) private def _initialize() = { try { - // [Eugene] todo. if this crashes, REPL will hang + // todo. if this crashes, REPL will hang new _compiler.Run() compileSources _initSources _initializeComplete = true true diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala index 6a14e1ea12..91b70726c2 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala @@ -23,7 +23,7 @@ trait Imports { val hd :: tl = sym.fullName.split('.').toList map newTermName val tree = Import( tl.foldLeft(Ident(hd): Tree)((x, y) => Select(x, y)), - List(ImportSelector(nme.WILDCARD, -1, null, -1)) + ImportSelector.wildList ) tree setSymbol sym new ImportHandler(tree) diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala index a7ceda176e..04ccb87389 100644 --- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -213,7 +213,7 @@ trait TypeStrings { private def tparamString[T: ru.TypeTag] : String = { def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil } - // [Eugene++] todo. need to use not the `rootMirror`, but a mirror with the REPL's classloader + // [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))): _*) diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index d1c404b3e3..c5da8822d5 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -551,7 +551,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { if (parentToken == AT && in.token == DEFAULT) { val annot = atPos(pos) { - New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), List(List())) + New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), ListOfNil) } mods1 = mods1 withAnnotations List(annot) skipTo(SEMI) @@ -640,7 +640,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def importCompanionObject(cdef: ClassDef): Tree = atPos(cdef.pos) { - Import(Ident(cdef.name.toTermName), List(ImportSelector(nme.WILDCARD, -1, null, -1))) + Import(Ident(cdef.name.toTermName), ImportSelector.wildList) } // Importing the companion object members cannot be done uncritically: see @@ -841,7 +841,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val predefs = List( DefDef( Modifiers(Flags.JAVA | Flags.STATIC), nme.values, List(), - List(List()), + ListOfNil, arrayOf(enumType), blankExpr), DefDef( diff --git a/src/compiler/scala/tools/nsc/package.scala b/src/compiler/scala/tools/nsc/package.scala index 9ad0d9ba1f..9d593e5acc 100644 --- a/src/compiler/scala/tools/nsc/package.scala +++ b/src/compiler/scala/tools/nsc/package.scala @@ -14,4 +14,6 @@ package object nsc { type MissingRequirementError = scala.reflect.internal.MissingRequirementError val MissingRequirementError = scala.reflect.internal.MissingRequirementError + + val ListOfNil = List(Nil) } diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 436867257a..300bf833a8 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -50,14 +50,14 @@ abstract class CleanUp extends Transform with ast.TreeDSL { private def transformTemplate(tree: Tree) = { val t @ Template(parents, self, body) = tree clearStatics() - + val newBody = transformTrees(body) val templ = deriveTemplate(tree)(_ => transformTrees(newStaticMembers.toList) ::: newBody) try addStaticInits(templ) // postprocess to include static ctors finally clearStatics() } private def mkTerm(prefix: String): TermName = unit.freshTermName(prefix) - + //private val classConstantMeth = new HashMap[String, Symbol] //private val symbolStaticFields = new HashMap[String, (Symbol, Tree, Tree)] @@ -542,12 +542,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { else tree } - + case ValDef(mods, name, tpt, rhs) if tree.symbol.hasStaticAnnotation => log("moving @static valdef field: " + name + ", in: " + tree.symbol.owner) val sym = tree.symbol val owner = sym.owner - + val staticBeforeLifting = atPhase(currentRun.erasurePhase) { owner.isStatic } val isPrivate = atPhase(currentRun.typerPhase) { sym.getter(owner).hasFlag(PRIVATE) } val isProtected = atPhase(currentRun.typerPhase) { sym.getter(owner).hasFlag(PROTECTED) } @@ -574,19 +574,19 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val compclass = enclosing.newClass(newTypeName(owner.name.toString)) compclass setInfo ClassInfoType(List(ObjectClass.tpe), newScope, compclass) enclosing.info.decls enter compclass - - val compclstree = ClassDef(compclass, NoMods, List(List()), List(List()), List(), tree.pos) - + + val compclstree = ClassDef(compclass, NoMods, ListOfNil, ListOfNil, List(), tree.pos) + syntheticClasses.getOrElseUpdate(enclosing, mutable.Set()) += compclstree - + compclass case comp => comp } - + // create a static field in the companion class for this @static field val stfieldSym = linkedClass.newVariable(newTermName(name), tree.pos, STATIC | SYNTHETIC | FINAL) setInfo sym.tpe stfieldSym.addAnnotation(StaticClass) - + val names = classNames.getOrElseUpdate(linkedClass, linkedClass.info.decls.collect { case sym if sym.name.isTermName => sym.name } toSet) @@ -597,9 +597,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { ) } else { linkedClass.info.decls enter stfieldSym - + val initializerBody = rhs - + // static field was previously initialized in the companion object itself, like this: // staticBodies((linkedClass, stfieldSym)) = Select(This(owner), sym.getter(owner)) // instead, we move the initializer to the static ctor of the companion class @@ -608,7 +608,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } } super.transform(tree) - + /* MSIL requires that the stack is empty at the end of a try-block. * Hence, we here rewrite all try blocks with a result != {Unit, All} such that they * store their result in a local variable. The catch blocks are adjusted as well. @@ -722,7 +722,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { case Block(stats, expr) => stats :+ expr case t => List(t) } - + val newCtor = findStaticCtor(template) match { // in case there already were static ctors - augment existing ones // currently, however, static ctors aren't being generated anywhere else @@ -746,7 +746,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { deriveTemplate(template)(newCtor :: _) } } - + private def addStaticDeclarations(tree: Template, clazz: Symbol) { // add static field initializer statements for each static field in clazz if (!clazz.isModuleClass) for { @@ -757,22 +757,23 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val valdef = staticBodies((clazz, stfieldSym)) val ValDef(_, _, _, rhs) = valdef val fixedrhs = rhs.changeOwner((valdef.symbol, clazz.info.decl(nme.CONSTRUCTOR))) - + val stfieldDef = localTyper.typedPos(tree.pos)(VAL(stfieldSym) === EmptyTree) val flattenedInit = fixedrhs match { case Block(stats, expr) => Block(stats, REF(stfieldSym) === expr) case rhs => REF(stfieldSym) === rhs } val stfieldInit = localTyper.typedPos(tree.pos)(flattenedInit) - + // add field definition to new defs newStaticMembers append stfieldDef newStaticInits append stfieldInit + case _ => // ignore @static on other members } } - - - + + + override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { super.transformStats(stats, exprOwner) ++ { // flush pending synthetic classes created in this owner @@ -785,22 +786,22 @@ abstract class CleanUp extends Transform with ast.TreeDSL { case clsdef @ ClassDef(mods, name, tparams, t @ Template(parent, self, body)) => // process all classes in the package again to add static initializers clearStatics() - + addStaticDeclarations(t, clsdef.symbol) - + val templ = deriveTemplate(t)(_ => transformTrees(newStaticMembers.toList) ::: body) val ntempl = try addStaticInits(templ) finally clearStatics() - + val derived = deriveClassDef(clsdef)(_ => ntempl) classNames.remove(clsdef.symbol) derived - + case stat => stat } } - + } // CleanUpTransformer } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index f2f4a44b02..afc109c47a 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -506,14 +506,14 @@ abstract class Constructors extends Transform with ast.TreeDSL { val applyMethodDef = DefDef( sym = applyMethod, - vparamss = List(List()), + vparamss = ListOfNil, rhs = Block(applyMethodStats, gen.mkAttributedRef(BoxedUnit_UNIT))) ClassDef( sym = closureClass, constrMods = Modifiers(0), vparamss = List(List(outerFieldDef)), - argss = List(List()), + argss = ListOfNil, body = List(applyMethodDef), superPos = impl.pos) } diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index c884a9a0c5..717d9209ae 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -966,7 +966,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { stats flatMap { case stat @ Assign(lhs @ Select(This(_), _), rhs) => stat :: checkedGetter(lhs) // remove initialization for default values - case Apply(lhs @ Select(Ident(self), _), List(EmptyTree)) if lhs.symbol.isSetter => Nil + case Apply(lhs @ Select(Ident(self), _), EmptyTree.asList) if lhs.symbol.isSetter => Nil case stat => List(stat) }, exprOwner diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 58914b61d8..3366244bc6 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -111,7 +111,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case TypeRef(_, GroupOfSpecializable, arg :: Nil) => arg.typeArgs map (_.typeSymbol) case _ => - List(tp.typeSymbol) + tp.typeSymbol :: Nil } } } @@ -362,7 +362,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // creating each permutation of concrete types def loop(ctypes: List[List[Type]]): List[List[Type]] = ctypes match { case Nil => Nil - case set :: Nil => set map (x => List(x)) + case set :: Nil => set map (_ :: Nil) case set :: sets => for (x <- set ; xs <- loop(sets)) yield x :: xs } // zip the keys with each permutation to create a TypeEnv. @@ -424,7 +424,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: argSyms.map(_.tpe)) case ExistentialType(_, res) => specializedTypeVars(res) case AnnotatedType(_, tp, _) => specializedTypeVars(tp) - case TypeBounds(lo, hi) => specializedTypeVars(List(lo, hi)) + case TypeBounds(lo, hi) => specializedTypeVars(lo :: hi :: Nil) case RefinedType(parents, _) => parents flatMap specializedTypeVars toSet case _ => Set() } @@ -436,7 +436,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val sClassMap = anyrefSpecCache.getOrElseUpdate(sClass, mutable.Map[Symbol, Symbol]()) sClassMap.getOrElseUpdate(tparam, - tparam.cloneSymbol(sClass, tparam.flags, (tparam.name append tpnme.SPECIALIZED_SUFFIX).asInstanceOf[Name]) // [Eugene++] why do we need this cast? + tparam.cloneSymbol(sClass, tparam.flags, (tparam.name append tpnme.SPECIALIZED_SUFFIX).asInstanceOf[Name]) // [Eugene] why do we need this cast? modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe)) ).tpe } @@ -1772,10 +1772,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def forwardCall(pos: scala.reflect.internal.util.Position, receiver: Tree, paramss: List[List[ValDef]]): Tree = { val argss = mmap(paramss)(x => Ident(x.symbol)) - def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) - atPos(pos) { (receiver /: argss) (mkApply) } - // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal - // atPos(pos) { (receiver /: argss) (Apply) } + atPos(pos) { (receiver /: argss) (Apply.apply) } } /** Forward to the generic class constructor. If the current class initializes @@ -1817,10 +1814,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else Ident(x.symbol) ) - def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) - atPos(pos) { (receiver /: argss) (mkApply) } - // [Eugene++] no longer compiles after I moved the `Apply` case class into scala.reflect.internal - // atPos(pos) { (receiver /: argss) (Apply) } + atPos(pos) { (receiver /: argss) (Apply.apply) } } /** Add method m to the set of symbols for which we need an implementation tree diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index fc61997cd5..81b8427f18 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -277,7 +277,7 @@ abstract class UnCurry extends InfoTransform localTyper.typedPos(fun.pos) { Block( - List(ClassDef(anonClass, NoMods, List(List()), List(List()), List(applyMethodDef), fun.pos)), + List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyMethodDef), fun.pos)), Typed(New(anonClass.tpe), TypeTree(fun.tpe))) } @@ -402,7 +402,7 @@ abstract class UnCurry extends InfoTransform localTyper.typedPos(fun.pos) { Block( - List(ClassDef(anonClass, NoMods, List(List()), List(List()), List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)), + List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)), Typed(New(anonClass.tpe), TypeTree(fun.tpe))) } } @@ -564,7 +564,7 @@ abstract class UnCurry extends InfoTransform sym.setInfo(MethodType(List(), tree.tpe)) tree.changeOwner(currentOwner -> sym) localTyper.typedPos(tree.pos)(Block( - List(DefDef(sym, List(Nil), tree)), + List(DefDef(sym, ListOfNil, tree)), Apply(Ident(sym), Nil) )) } @@ -717,8 +717,12 @@ abstract class UnCurry extends InfoTransform } case dd @ DefDef(_, _, _, vparamss0, _, rhs0) => + val vparamss1 = vparamss0 match { + case _ :: Nil => vparamss0 + case _ => vparamss0.flatten :: Nil + } val flatdd = copyDefDef(dd)( - vparamss = List(vparamss0.flatten), + vparamss = vparamss1, rhs = nonLocalReturnKeys get dd.symbol match { case Some(k) => atPos(rhs0.pos)(nonLocalReturnTry(rhs0, k, dd.symbol)) case None => rhs0 diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 632f30b3a6..d0716e1a35 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -8,12 +8,15 @@ package typechecker import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.StringOps.{ countElementsAsString, countAsString } -import symtab.Flags.{ PRIVATE, PROTECTED } +import symtab.Flags.{ PRIVATE, PROTECTED, IS_ERROR } +import scala.compat.Platform.EOL trait ContextErrors { self: Analyzer => import global._ + import definitions._ + import treeInfo._ object ErrorKinds extends Enumeration { type ErrorKind = Value @@ -424,8 +427,11 @@ trait ContextErrors { def AbstractionFromVolatileTypeError(vd: ValDef) = issueNormalTypeError(vd, "illegal abstraction from value with volatile type "+vd.symbol.tpe) + private[ContextErrors] def TypedApplyWrongNumberOfTpeParametersErrorMessage(fun: Tree) = + "wrong number of type parameters for "+treeSymTypeMsg(fun) + def TypedApplyWrongNumberOfTpeParametersError(tree: Tree, fun: Tree) = { - issueNormalTypeError(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun)) + issueNormalTypeError(tree, TypedApplyWrongNumberOfTpeParametersErrorMessage(fun)) setError(tree) } @@ -622,11 +628,11 @@ trait ContextErrors { } // cyclic errors - def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) = - issueTypeError(PosAndMsgTypeError(errPos, "cyclic aliasing or subtyping involving "+sym0)) + 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, lockedSym: Symbol) = + issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym)) } } @@ -750,21 +756,24 @@ trait ContextErrors { kindErrors.toList.mkString("\n", ", ", "")) } - def NotWithinBounds(tree: Tree, prefix: String, targs: List[Type], - tparams: List[Symbol], kindErrors: List[String]) = { - if (settings.explaintypes.value) { + private[ContextErrors] def NotWithinBoundsErrorMessage(prefix: String, targs: List[Type], tparams: List[Symbol], explaintypes: Boolean) = { + if (explaintypes) { val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds) (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ)) (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi)) () } - issueNormalTypeError(tree, - prefix + "type arguments " + targs.mkString("[", ",", "]") + - " do not conform to " + tparams.head.owner + "'s type parameter bounds " + - (tparams map (_.defString)).mkString("[", ",", "]")) + prefix + "type arguments " + targs.mkString("[", ",", "]") + + " do not conform to " + tparams.head.owner + "'s type parameter bounds " + + (tparams map (_.defString)).mkString("[", ",", "]") } + def NotWithinBounds(tree: Tree, prefix: String, targs: List[Type], + tparams: List[Symbol], kindErrors: List[String]) = + issueNormalTypeError(tree, + NotWithinBoundsErrorMessage(prefix, targs, tparams, settings.explaintypes.value)) + //substExpr def PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) = issueNormalTypeError(tree, @@ -1084,4 +1093,133 @@ trait ContextErrors { setError(arg) } } + + // using an exception here is actually a good idea + // because the lifespan of this exception is extremely small and controlled + // moreover exceptions let us avoid an avalanche of "if (!hasError) do stuff" checks + case object MacroBodyTypecheckException extends Exception with scala.util.control.ControlThrowable + + trait MacroErrors { + self: MacroTyper => + + private implicit val context0 = typer.context + val context = typer.context + + // helpers + + private def lengthMsg(flavor: String, violation: String, extra: Symbol) = { + val noun = if (flavor == "value") "parameter" else "type parameter" + val message = noun + " lists have different length, " + violation + " extra " + noun + val suffix = if (extra ne NoSymbol) " " + extra.defString else "" + message + suffix + } + + private def abbreviateCoreAliases(s: String): String = List("AbsTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x)) + + private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = { + var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString + if (abbreviate) argsPart = abbreviateCoreAliases(argsPart) + var retPart = restpe.toString + if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart) + argsPart + ": " + retPart + } + + // not exactly an error generator, but very related + // and I dearly wanted to push it away from Macros.scala + private def checkSubType(slot: String, rtpe: Type, atpe: Type) = { + val ok = if (macroDebugVerbose || settings.explaintypes.value) { + if (rtpe eq atpe) println(rtpe + " <: " + atpe + "?" + EOL + "true") + withTypesExplained(rtpe <:< atpe) + } else rtpe <:< atpe + if (!ok) { + compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, abbreviateCoreAliases(rtpe.toString), abbreviateCoreAliases(atpe.toString))) + } + } + + // errors + + private def fail() = { + // need to set the IS_ERROR flag to prohibit spurious expansions + if (macroDef != null) macroDef setFlag IS_ERROR + // not setting ErrorSymbol as in `infer.setError`, because we still need to know that it's a macro + // otherwise assignTypeToTree in Namers might fail if macroDdef.tpt == EmptyTree + macroDdef setType ErrorType + throw MacroBodyTypecheckException + } + + private def genericError(tree: Tree, message: String) = { + issueNormalTypeError(tree, message) + fail() + } + + private def implRefError(message: String) = genericError(methPart(macroDdef.rhs), message) + + private def compatibilityError(message: String) = + implRefError( + "macro implementation has wrong shape:"+ + "\n required: " + showMeth(rparamss, rret, abbreviate = true) + + "\n found : " + showMeth(aparamss, aret, abbreviate = false) + + "\n" + message) + + // Phase I: sanity checks + + def MacroDefIsFastTrack() = { + macroLogVerbose("typecheck terminated unexpectedly: macro is fast track") + assert(!macroDdef.tpt.isEmpty, "fast track macros must provide result type") + throw MacroBodyTypecheckException // don't call fail, because we don't need IS_ERROR + } + + def MacroFeatureNotEnabled() = { + macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled") + fail() + } + + // Phase II: typecheck the right-hand side of the macro def + + // do nothing, just fail. relevant typecheck errors have already been reported + def MacroDefUntypeableBodyError() = fail() + + def MacroDefInvalidBodyError() = genericError(macroDdef, "macro body has wrong shape:\n required: macro [<implementation object>].<method name>[[<type args>]]") + + def MacroImplNotPublicError() = implRefError("macro implementation must be public") + + def MacroImplOverloadedError() = implRefError("macro implementation cannot be overloaded") + + def MacroImplWrongNumberOfTypeArgumentsError(macroImplRef: Tree) = implRefError(typer.TyperErrorGen.TypedApplyWrongNumberOfTpeParametersErrorMessage(macroImplRef)) + + def MacroImplNotStaticError() = implRefError("macro implementation must be in statically accessible object") + + // Phase III: check compatibility between the macro def and its macro impl + // aXXX (e.g. aparams) => characteristics of the macro impl ("a" stands for "actual") + // rXXX (e.g. rparams) => characteristics of a reference macro impl signature synthesized from the macro def ("r" stands for "reference") + + def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than AbsTypeTag evidences") + + def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ") + + def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length))) + + def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length)))) + + def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkSubType("parameter " + rparam.name, rparam.tpe, atpe) + + def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkSubType("return type", atpe, rret) + + def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name) + + def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = { + if (isRepeated(rparam) && !isRepeated(aparam)) + compatibilityError("types incompatible for parameter " + rparam.name + ": corresponding is not a vararg parameter") + if (!isRepeated(rparam) && isRepeated(aparam)) + compatibilityError("types incompatible for parameter " + aparam.name + ": corresponding is not a vararg parameter") + } + + def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) = + compatibilityError(typer.infer.InferErrorGen.NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value)) + + def MacroImplTparamInstantiationError(atparams: List[Symbol], ex: NoInstance) = + compatibilityError( + "type parameters "+(atparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+ + ex.getMessage) + } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index dd5588e9a6..6a908c6c65 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -27,6 +27,13 @@ trait Contexts { self: Analyzer => override def implicitss: List[List[ImplicitInfo]] = Nil 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 + } private val startContext = { NoContext.make( @@ -46,13 +53,12 @@ trait Contexts { self: Analyzer => * among its leading imports, or if the tree is [[scala.Predef]], `Predef` is not imported. */ protected def rootImports(unit: CompilationUnit): List[Symbol] = { - import definitions._ - assert(isDefinitionsInitialized, "definitions uninitialized") + assert(definitions.isDefinitionsInitialized, "definitions uninitialized") if (settings.noimports.value) Nil - else if (unit.isJava) List(JavaLangPackage) - else if (settings.nopredef.value || treeInfo.noPredefImportForUnit(unit.body)) List(JavaLangPackage, ScalaPackage) - else List(JavaLangPackage, ScalaPackage, PredefModule) + else if (unit.isJava) RootImports.javaList + else if (settings.nopredef.value || treeInfo.noPredefImportForUnit(unit.body)) RootImports.javaAndScalaList + else RootImports.completeList } def rootContext(unit: CompilationUnit): Context = rootContext(unit, EmptyTree, false) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index f9035f26b9..a34fc71b8f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1185,10 +1185,6 @@ trait Implicits { // ClassTags are not path-dependent, so their materializer doesn't care about prefixes if (tagClass eq ClassTagClass) gen.mkBasisUniverseRef else pre match { - // [Eugene to Martin] this is the crux of the interaction between - // implicits and reifiers here we need to turn a (supposedly - // path-dependent) type into a tree that will be used as a prefix I'm - // not sure if I've done this right - please, review case SingleType(prePre, preSym) => gen.mkAttributedRef(prePre, preSym) setType pre // necessary only to compile typetags used inside the Universe cake @@ -1341,13 +1337,7 @@ trait Implicits { /** Materializes implicits of magic types (currently, manifests and tags). * Will be replaced by implicit macros once we fix them. */ - private def materializeImplicit(pt: Type): SearchResult = { - def fallback = { - searchImplicit(implicitsOfExpectedType, false) - // shouldn't we pass `pt` to `implicitsOfExpectedType`, or is the recursive case - // for an abstract type really only meant for tags? - } - + private def materializeImplicit(pt: Type): SearchResult = pt match { case TypeRef(_, sym, _) if sym.isAbstractType => materializeImplicit(pt.dealias.bounds.lo) // #3977: use pt.dealias, not pt (if pt is a type alias, pt.bounds.lo == pt) @@ -1363,17 +1353,17 @@ trait Implicits { // unlike `dealias`, `betaReduce` performs at most one step of dealiasing // while dealias pops all aliases in a single invocation case sym if sym.isAliasType => materializeImplicit(pt.betaReduce) - case _ => fallback + case _ => SearchFailure } case _ => - fallback + SearchFailure } - } /** The result of the implicit search: * First search implicits visible in current context. * If that fails, search implicits in expected type `pt`. - * // [Eugene] the following lines should be deleted after we migrate delegate tag materialization to implicit macros + * + * todo. the following lines should be deleted after we migrate delegate tag materialization to implicit macros * If that fails, and `pt` is an instance of a ClassTag, try to construct a class tag. * If that fails, and `pt` is an instance of a TypeTag, try to construct a type tag. * If that fails, and `pt` is an instance of a ClassManifest, try to construct a class manifest. @@ -1400,6 +1390,10 @@ trait Implicits { result = materializeImplicit(pt) + // `materializeImplicit` does some preprocessing for `pt` + // is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`? + if (result == SearchFailure) result = searchImplicit(implicitsOfExpectedType, false) + if (result == SearchFailure) { context.updateBuffer(previousErrs) Statistics.stopTimer(oftypeFailNanos, failstart) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 032212e3c0..5673a724d1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1661,7 +1661,7 @@ trait Infer { // for functional values, the `apply` method might be overloaded val mtypes = followApply(alt.tpe) match { case OverloadedType(_, alts) => alts map (_.tpe) - case t => List(t) + case t => t :: Nil } // Drop those that use a default; keep those that use vararg/tupling conversion. mtypes exists (t => diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index c8bf70e9e0..4601f63809 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -24,7 +24,7 @@ import scala.reflect.internal.util.Collections._ * * Then fooBar needs to point to a static method of the following form: * - * def fooBar[T: c.AbsTypeTag] + * def fooBar[T: c.AbsTypeTag] // type tag annotation is optional * (c: scala.reflect.macros.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = { @@ -32,7 +32,7 @@ import scala.reflect.internal.util.Collections._ * } * * Then, if foo is called in qual.foo[Int](elems), where qual: D, - * the macro application is expanded to a reflective invocation of fooBar with parameters + * the macro application is expanded to a reflective invocation of fooBar with parameters: * * (simpleMacroContext{ type PrefixType = D; val prefix = qual }) * (Expr(elems)) @@ -43,6 +43,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { import global._ import definitions._ + import treeInfo.{isRepeatedParamType => _, _} import MacrosStats._ def globalSettings = global.settings @@ -132,9 +133,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // there are some more clever cases when seemingly non-static method ends up being statically accessible // however, the code below doesn't account for these guys, because it'd take a look of time to get it right // for now I leave it as a todo and move along to more the important stuff - // [Eugene] relies on the fact that macro implementations can only be defined in static classes - // [Martin to Eugene++] There's similar logic buried in Symbol#flatname. Maybe we can refactor? - // [Eugene] we will refactor once I get my hands on https://issues.scala-lang.org/browse/SI-5498 + // todo. refactor when fixing SI-5498 def className: String = { def loop(sym: Symbol): String = sym match { case sym if sym.owner.isPackageClass => @@ -214,46 +213,110 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { MacroImplBinding.unpickle(pickle) } - /** A list of compatible macro implementation signatures. + /** Transforms parameters lists of a macro impl. + * The `transform` function is invoked only for AbsTypeTag evidence parameters. * - * In the example above: + * The transformer takes two arguments: a value parameter from the parameter list + * and a type parameter that is witnesses by the value parameter. + * + * If the transformer returns a NoSymbol, the value parameter is not included from the result. + * If the transformer returns something else, this something else is included in the result instead of the value parameter. + * + * Despite of being highly esoteric, this function significantly simplifies signature analysis. + * For example, it can be used to strip macroImpl.paramss from the evidences (necessary when checking def <-> impl correspondence) + * or to streamline creation of the list of macro arguments. + */ + private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = { + if (paramss.isEmpty || paramss.last.isEmpty) return paramss // no implicit parameters in the signature => nothing to do + if (paramss.head.isEmpty || !(paramss.head.head.tpe <:< MacroContextClass.tpe)) return paramss // no context parameter in the signature => nothing to do + def transformTag(param: Symbol): Symbol = param.tpe.dealias match { + case TypeRef(SingleType(SingleType(NoPrefix, c), universe), AbsTypeTagClass, targ :: Nil) + if c == paramss.head.head && universe == MacroContextUniverse => + transform(param, targ.typeSymbol) + case _ => + param + } + val transformed = paramss.last map transformTag filter (_ ne NoSymbol) + if (transformed.isEmpty) paramss.init else paramss.init :+ transformed + } + + def computeMacroDefTypeFromMacroImpl(macroDdef: DefDef, macroImpl: Symbol): Type = { + // Step I. Transform c.Expr[T] to T + var runtimeType = macroImpl.tpe.finalResultType.dealias match { + case TypeRef(_, ExprClass, runtimeType :: Nil) => runtimeType + case _ => AnyTpe // so that macro impls with rhs = ??? don't screw up our inference + } + + // Step II. Transform type parameters of a macro implementation into type arguments in a macro definition's body + runtimeType = runtimeType.substituteTypes(macroImpl.typeParams, loadMacroImplBinding(macroDdef.symbol).targs.map(_.tpe)) + + // Step III. Transform c.prefix.value.XXX to this.XXX and implParam.value.YYY to defParam.YYY + def unsigma(tpe: Type): Type = + transformTypeTagEvidenceParams(macroImpl.paramss, (param, tparam) => NoSymbol) match { + case (implCtxParam :: Nil) :: implParamss => + val implToDef = flatMap2(implParamss, macroDdef.vparamss)(map2(_, _)((_, _))).toMap + object UnsigmaTypeMap extends TypeMap { + def apply(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) => + val pre1 = pre match { + case SingleType(SingleType(SingleType(NoPrefix, c), prefix), value) if c == implCtxParam && prefix == MacroContextPrefix && value == ExprValue => + ThisType(macroDdef.symbol.owner) + case SingleType(SingleType(NoPrefix, implParam), value) if value == ExprValue => + implToDef get implParam map (defParam => SingleType(NoPrefix, defParam.symbol)) getOrElse pre + case _ => + pre + } + val args1 = args map mapOver + TypeRef(pre1, sym, args1) + case _ => + mapOver(tp) + } + } + + UnsigmaTypeMap(tpe) + case _ => + tpe + } + + unsigma(runtimeType) + } + + /** A reference macro implementation signature compatible with a given macro definition. + * + * In the example above for the following macro def: + * def foo[T](xs: List[T]): T = macro fooBar + * + * This function will return: * (c: scala.reflect.macros.Context)(xs: c.Expr[List[T]]): c.Expr[T] * + * Note that type tag evidence parameters are not included into the result. + * Type tag context bounds for macro impl tparams are optional. + * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here. + * * @param macroDef The macro definition symbol * @param tparams The type parameters of the macro definition * @param vparamss The value parameters of the macro definition * @param retTpe The return type of the macro definition */ - private def macroImplSigs(macroDef: Symbol, tparams: List[TypeDef], vparamss: List[List[ValDef]], retTpe: Type): (List[List[List[Symbol]]], Type) = { + 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 { - val hasThis = macroDef.owner.isClass - val ownerTpe = macroDef.owner match { - case owner if owner.isModuleClass => new UniqueThisType(macroDef.owner) - case owner if owner.isClass => macroDef.owner.tpe - case _ => NoType - } - val hasTparams = !tparams.isEmpty - 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, paramsCtx(0)), MacroContextPrefix), ExprValue) + 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 Some(macroDefParam) => SingleType(SingleType(NoPrefix, param(macroDefParam)), ExprValue) + case _ => pre } case _ => pre } - val args1 = args map mapOver - TypeRef(pre1, sym, args1) + TypeRef(pre1, sym, args map mapOver) case _ => mapOver(tp) } @@ -277,29 +340,14 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { val paramCache = collection.mutable.Map[Symbol, Symbol]() def param(tree: Tree): Symbol = paramCache.getOrElseUpdate(tree.symbol, { - // [Eugene] deskolemization became necessary once I implemented inference of macro def return type - // please, verify this solution, but for now I'll leave it here - cargo cult for the win - val sym = tree.symbol.deSkolemize + val sym = tree.symbol val sigParam = makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe)) if (sym.isSynthetic) sigParam.flags |= SYNTHETIC sigParam }) - val paramsCtx = List(ctxParam) - val paramsThis = List(makeParam(nme.macroThis, macroDef.pos, implType(false, ownerTpe), SYNTHETIC)) - val paramsTparams = tparams map param - val paramssParams = mmap(vparamss)(param) - - var paramsss = List[List[List[Symbol]]]() - // tparams are no longer part of a signature, they get into macro implementations via context bounds -// if (hasTparams && hasThis) paramsss :+= paramsCtx :: paramsThis :: paramsTparams :: paramssParams -// if (hasTparams) paramsss :+= paramsCtx :: paramsTparams :: paramssParams - // _this params are no longer part of a signature, its gets into macro implementations via Context.prefix -// if (hasThis) paramsss :+= paramsCtx :: paramsThis :: paramssParams - paramsss :+= paramsCtx :: paramssParams - - val tsym = getMember(MacroContextClass, tpnme.Expr) - val implRetTpe = typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(retTpe))) + val paramss = List(ctxParam) :: mmap(vparamss)(param) + val implRetTpe = typeRef(singleType(NoPrefix, ctxParam), getMember(MacroContextClass, tpnme.Expr), List(sigma(retTpe))) } import SigGenerator._ @@ -307,137 +355,26 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { macroTraceVerbose("tparams are: ")(tparams) macroTraceVerbose("vparamss are: ")(vparamss) macroTraceVerbose("retTpe is: ")(retTpe) - macroTraceVerbose("macroImplSigs are: ")(paramsss, implRetTpe) + macroTraceVerbose("macroImplSig is: ")(paramss, implRetTpe) } - private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = { - import definitions.{ AbsTypeTagClass, MacroContextClass } - if (paramss.isEmpty || paramss.last.isEmpty) - return paramss - - val ContextParam = paramss.head match { - case p :: Nil => p filter (_.tpe <:< definitions.MacroContextClass.tpe) - case _ => NoSymbol - } - def isTag(sym: Symbol): Boolean = (sym == AbsTypeTagClass) || (sym.isAliasType && isTag(sym.info.typeSymbol)) - def transformTag(param: Symbol): Symbol = param.tpe match { - case TypeRef(SingleType(NoPrefix, ContextParam), sym, tp :: Nil) if isTag(sym) => transform(param, tp.typeSymbol) - case _ => param - } - val last = paramss.last map transformTag filterNot (_ eq NoSymbol) - if (last.isEmpty) paramss.init else paramss.init :+ last - } - - /** As specified above, body of a macro definition must reference its implementation. - * This function verifies that the body indeed refers to a method, and that - * the referenced macro implementation is compatible with the given macro definition. + /** Verifies that the body of a macro def typechecks to a reference to a static public non-overloaded method, + * and that that method is signature-wise compatible with the given macro definition. * - * This means that macro implementation (fooBar in example above) must: - * 1) Refer to a statically accessible, non-overloaded method. - * 2) Have the right parameter lists as outlined in the SIP / in the doc comment of this class. - * - * @return typechecked rhs of the given macro definition + * @return Typechecked rhs of the given macro definition if everything is okay. + * EmptyTree if an error occurs. */ - def typedMacroBody(typer: Typer, ddef: DefDef): Tree = { - import typer.context - macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos)) - - val macroDef = ddef.symbol - val defpos = macroDef.pos - val implpos = ddef.rhs.pos - assert(macroDef.isTermMacro, ddef) - - if (fastTrack contains ddef.symbol) { - macroLogVerbose("typecheck terminated unexpectedly: macro is hardwired") - assert(!ddef.tpt.isEmpty, "hardwired macros must provide result type") - return EmptyTree - } - - if (!typer.checkFeature(ddef.pos, MacrosFeature, immediate = true)) { - macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled") - ddef.symbol setFlag IS_ERROR - return EmptyTree - } - - implicit class AugmentedString(s: String) { - def abbreviateCoreAliases: String = { // hack! - var result = s - result = result.replace("c.universe.AbsTypeTag", "c.AbsTypeTag") - result = result.replace("c.universe.Expr", "c.Expr") - result - } - } - - var _hasError = false - def hasError = _hasError - def setError(): Unit = { - _hasError = true - macroDef setFlag IS_ERROR - } - def reportError(pos: Position, msg: String) = { - setError() - context.error(pos, msg) - macroDef setFlag IS_ERROR - } - - def invalidBodyError() = - reportError(defpos, - "macro body has wrong shape:" + - "\n required: macro <reference to implementation object>.<implementation method name>" + - "\n or : macro <implementation method name>") - def validatePreTyper(rhs: Tree): Unit = rhs match { - // we do allow macro invocations inside macro bodies - // personally I don't mind if pre-typer tree is a macro invocation - // that later resolves to a valid reference to a macro implementation - // however, I don't think that invalidBodyError() should hint at that - // let this be an Easter Egg :) - case Apply(_, _) => ; - case TypeApply(_, _) => ; - case Super(_, _) => ; - case This(_) => ; - case Ident(_) => ; - case Select(_, _) => ; - case _ => invalidBodyError() - } - def validatePostTyper(rhs1: Tree): Unit = { - def loop(tree: Tree): Unit = { - def errorNotStatic() = - reportError(implpos, "macro implementation must be in statically accessible object") - - def ensureRoot(sym: Symbol) = - if (!sym.isModule && !sym.isModuleClass) errorNotStatic() - - def ensureModule(sym: Symbol) = - if (!sym.isModule) errorNotStatic() - - tree match { - case TypeApply(fun, _) => - loop(fun) - case Super(qual, _) => - ensureRoot(macroDef.owner) - loop(qual) - case This(_) => - ensureRoot(tree.symbol) - case Select(qual, name) if name.isTypeName => - loop(qual) - case Select(qual, name) if name.isTermName => - if (tree.symbol != rhs1.symbol) ensureModule(tree.symbol) - loop(qual) - case Ident(name) if name.isTypeName => - ; - case Ident(name) if name.isTermName => - if (tree.symbol != rhs1.symbol) ensureModule(tree.symbol) - case _ => - invalidBodyError() - } - } - - loop(rhs1) - } - - val rhs = ddef.rhs - validatePreTyper(rhs) - if (hasError) macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef) + def typedMacroBody(typer: Typer, macroDdef: DefDef): Tree = + try new MacroTyper(typer, macroDdef).typed + catch { case MacroBodyTypecheckException => EmptyTree } + + class MacroTyper(val typer: Typer, val macroDdef: DefDef) extends MacroErrors { + // Phase I: sanity checks + val macroDef = macroDdef.symbol + macroLogVerbose("typechecking macro def %s at %s".format(macroDef, macroDdef.pos)) + assert(macroDef.isTermMacro, macroDdef) + if (fastTrack contains macroDef) MacroDefIsFastTrack() + if (!typer.checkFeature(macroDdef.pos, MacrosFeature, immediate = true)) MacroFeatureNotEnabled() // we use typed1 instead of typed, because otherwise adapt is going to mess us up // if adapt sees <qualifier>.<method>, it will want to perform eta-expansion and will fail @@ -445,11 +382,13 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // because it's adapt which is responsible for automatic expansion during typechecking def typecheckRhs(rhs: Tree): Tree = { try { - val prevNumErrors = reporter.ERROR.count // [Eugene] funnily enough, the isErroneous check is not enough - var rhs1 = if (hasError) EmptyTree else typer.typed1(rhs, EXPRmode, WildcardType) - def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors + // interestingly enough, just checking isErroneous doesn't cut it + // e.g. a "type arguments [U] do not conform to method foo's type parameter bounds" error + // doesn't manifest itself as an error in the resulting tree + val prevNumErrors = reporter.ERROR.count + var rhs1 = typer.typed1(rhs, EXPRmode, WildcardType) def rhsNeedsMacroExpansion = rhs1.symbol != null && rhs1.symbol.isTermMacro && !rhs1.symbol.isErroneous - while (!typecheckedWithErrors && rhsNeedsMacroExpansion) { + while (rhsNeedsMacroExpansion) { rhs1 = macroExpand1(typer, rhs1) match { case Success(expanded) => try { @@ -465,287 +404,83 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { result } } + val typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors + if (typecheckedWithErrors) MacroDefUntypeableBodyError() rhs1 } catch { case ex: TypeError => typer.reportTypeError(context, rhs.pos, ex) - typer.infer.setError(rhs) - } - } - - val prevNumErrors = reporter.ERROR.count // funnily enough, the isErroneous check is not enough - var rhs1 = typecheckRhs(rhs) - val macroImpl = rhs1.symbol - def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors - if (typecheckedWithErrors) { - setError() - macroTraceVerbose("body of a macro def failed to typecheck: ")(ddef) - } else { - if (!hasError) { - if (macroImpl == null) { - invalidBodyError() - } else { - if (!macroImpl.isMethod) - invalidBodyError() - if (!macroImpl.isPublic) - reportError(implpos, "macro implementation must be public") - if (macroImpl.isOverloaded) - reportError(implpos, "macro implementation cannot be overloaded") - if (!macroImpl.typeParams.isEmpty && (!rhs1.isInstanceOf[TypeApply])) - reportError(implpos, "macro implementation reference needs type arguments") - if (!hasError) - validatePostTyper(rhs1) - } - if (hasError) - macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef) - } - if (!hasError) { - bindMacroImpl(macroDef, rhs1) // we must bind right over here, because return type inference needs this info + MacroDefUntypeableBodyError() } } - if (!hasError) { - def checkCompatibility(reqparamss: List[List[Symbol]], actparamss: List[List[Symbol]], reqres: Type, actres: Type): List[String] = { - var hasError = false - var errors = List[String]() - def compatibilityError(msg: String) { - hasError = true - errors :+= msg - } - - val flatreqparams = reqparamss.flatten - val flatactparams = actparamss.flatten - val tparams = macroImpl.typeParams - val tvars = tparams map freshVar - def lengthMsg(which: String, extra: Symbol) = - "parameter lists have different length, "+which+" extra parameter "+extra.defString - if (actparamss.length != reqparamss.length) - compatibilityError("number of parameter sections differ") - - def checkSubType(slot: String, reqtpe: Type, acttpe: Type): Unit = { - val ok = if (macroDebugVerbose) { - if (reqtpe eq acttpe) println(reqtpe + " <: " + acttpe + "?" + EOL + "true") - withTypesExplained(reqtpe <:< acttpe) - } else reqtpe <:< acttpe - if (!ok) { - compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, reqtpe.toString.abbreviateCoreAliases, acttpe.toString.abbreviateCoreAliases)) - } - } - - if (!hasError) { - try { - for ((rparams, aparams) <- reqparamss zip actparamss) { - if (rparams.length < aparams.length) - compatibilityError(lengthMsg("found", aparams(rparams.length))) - if (aparams.length < rparams.length) - compatibilityError(lengthMsg("required", rparams(aparams.length)).abbreviateCoreAliases) - } - // if the implementation signature is already deemed to be incompatible, we bail out - // otherwise, high-order type magic employed below might crash in weird ways - if (!hasError) { - for ((rparams, aparams) <- reqparamss zip actparamss) { - for ((rparam, aparam) <- rparams zip aparams) { - def isRepeated(param: Symbol) = param.tpe.typeSymbol == RepeatedParamClass - if (rparam.name != aparam.name && !rparam.isSynthetic) { - val rparam1 = rparam - val aparam1 = aparam - compatibilityError("parameter names differ: "+rparam.name+" != "+aparam.name) - } - if (isRepeated(rparam) && !isRepeated(aparam)) - compatibilityError("types incompatible for parameter "+rparam.name+": corresponding is not a vararg parameter") - if (!isRepeated(rparam) && isRepeated(aparam)) - compatibilityError("types incompatible for parameter "+aparam.name+": corresponding is not a vararg parameter") - if (!hasError) { - var atpe = aparam.tpe.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars) - atpe = atpe.dealias // SI-5706 - // strip the { type PrefixType = ... } refinement off the Context or otherwise we get compatibility errors - atpe = atpe match { - case RefinedType(List(tpe), Scope(sym)) if tpe == MacroContextClass.tpe && sym.allOverriddenSymbols.contains(MacroContextPrefixType) => tpe - case _ => atpe - } - checkSubType("parameter " + rparam.name, rparam.tpe, atpe) - } - } - } - } - if (!hasError) { - val atpe = actres.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars) - checkSubType("return type", atpe, reqres) - } - if (!hasError) { - val targs = solvedTypes(tvars, tparams, tparams map varianceInType(actres), false, - lubDepth(flatactparams map (_.tpe)) max lubDepth(flatreqparams map (_.tpe))) - val boundsOk = typer.silent(_.infer.checkBounds(ddef, NoPrefix, NoSymbol, tparams, targs, "")) - boundsOk match { - case SilentResultValue(true) => ; - case SilentResultValue(false) | SilentTypeError(_) => - val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds) - compatibilityError("type arguments " + targs.mkString("[", ",", "]") + - " do not conform to " + tparams.head.owner + "'s type parameter bounds " + - (tparams map (_.defString)).mkString("[", ",", "]")) - } - } - } catch { - case ex: NoInstance => - compatibilityError( - "type parameters "+(tparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+ - ex.getMessage) - } - } - - errors.toList - } - - var actparamss = macroImpl.paramss - actparamss = transformTypeTagEvidenceParams(actparamss, (param, tparam) => NoSymbol) - - val rettpe = if (!ddef.tpt.isEmpty) typer.typedType(ddef.tpt).tpe else computeMacroDefTypeFromMacroImpl(ddef, macroDef, macroImpl) - val (reqparamsss0, reqres0) = macroImplSigs(macroDef, ddef.tparams, ddef.vparamss, rettpe) - var reqparamsss = reqparamsss0 - - // prohibit implicit params on macro implementations - // we don't have to do this, but it appears to be more clear than allowing them - val implicitParams = actparamss.flatten filter (_.isImplicit) - if (implicitParams.length > 0) { - reportError(implicitParams.head.pos, "macro implementations cannot have implicit parameters other than AbsTypeTag evidences") - macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef) - } - - if (!hasError) { - val reqres = reqres0 - val actres = macroImpl.tpe.finalResultType - def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = { - var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString - if (abbreviate) argsPart = argsPart.abbreviateCoreAliases - var retPart = restpe.toString - if (abbreviate || ddef.tpt.tpe == null) retPart = retPart.abbreviateCoreAliases - argsPart + ": " + retPart - } - def compatibilityError(addendum: String) = - reportError(implpos, - "macro implementation has wrong shape:"+ - "\n required: "+showMeth(reqparamsss.head, reqres, true) + - (reqparamsss.tail map (paramss => "\n or : "+showMeth(paramss, reqres, true)) mkString "")+ - "\n found : "+showMeth(actparamss, actres, false)+ - "\n"+addendum) - - macroTraceVerbose("considering " + reqparamsss.length + " possibilities of compatible macro impl signatures for macro def: ")(ddef.name) - val results = reqparamsss map (checkCompatibility(_, actparamss, reqres, actres)) - if (macroDebugVerbose) (reqparamsss zip results) foreach { case (reqparamss, result) => - println("%s %s".format(if (result.isEmpty) "[ OK ]" else "[FAILED]", reqparamss)) - result foreach (errorMsg => println(" " + errorMsg)) - } - - if (results forall (!_.isEmpty)) { - var index = reqparamsss indexWhere (_.length == actparamss.length) - if (index == -1) index = 0 - val mostRelevantMessage = results(index).head - compatibilityError(mostRelevantMessage) - } else { - assert((results filter (_.isEmpty)).length == 1, results) - if (macroDebugVerbose) (reqparamsss zip results) filter (_._2.isEmpty) foreach { case (reqparamss, result) => - println("typechecked macro impl as: " + reqparamss) - } - } - } + // Phase II: typecheck the right-hand side of the macro def + val typed = typecheckRhs(macroDdef.rhs) + typed match { + case MacroImplReference(owner, meth, targs) => + if (!meth.isMethod) MacroDefInvalidBodyError() + if (!meth.isPublic) MacroImplNotPublicError() + if (meth.isOverloaded) MacroImplOverloadedError() + if (!owner.isStaticOwner && !owner.moduleClass.isStaticOwner) MacroImplNotStaticError() + if (meth.typeParams.length != targs.length) MacroImplWrongNumberOfTypeArgumentsError(typed) + bindMacroImpl(macroDef, typed) + case _ => + MacroDefInvalidBodyError() } - rhs1 - } - - def computeMacroDefTypeFromMacroImpl(macroDdef: DefDef, macroDef: Symbol, macroImpl: Symbol): Type = { - // get return type from method type - def unwrapRet(tpe: Type): Type = { - def loop(tpe: Type) = tpe match { - case NullaryMethodType(ret) => ret - case mtpe @ MethodType(_, ret) => unwrapRet(ret) - case _ => tpe - } + // Phase III: check compatibility between the macro def and its macro impl + // this check ignores type tag evidence parameters, because type tag context bounds are optional + // aXXX (e.g. aparamss) => characteristics of the macro impl ("a" stands for "actual") + // rXXX (e.g. rparamss) => characteristics of a reference macro impl signature synthesized from the macro def ("r" stands for "reference") + val macroImpl = typed.symbol + val aparamss = transformTypeTagEvidenceParams(macroImpl.paramss, (param, tparam) => NoSymbol) + val aret = macroImpl.tpe.finalResultType + val macroDefRet = + if (!macroDdef.tpt.isEmpty) typer.typedType(macroDdef.tpt).tpe + else computeMacroDefTypeFromMacroImpl(macroDdef, macroImpl) + val (rparamss, rret) = macroImplSig(macroDef, macroDdef.tparams, macroDdef.vparamss, macroDefRet) + + val implicitParams = aparamss.flatten filter (_.isImplicit) + if (implicitParams.nonEmpty) MacroImplNonTagImplicitParameters(implicitParams) + if (aparamss.length != rparamss.length) MacroImplParamssMismatchError() + + val atparams = macroImpl.typeParams + val atvars = atparams map freshVar + def atpeToRtpe(atpe: Type) = atpe.substSym(aparamss.flatten, rparamss.flatten).instantiateTypeParams(atparams, atvars) - tpe match { - case PolyType(_, tpe) => loop(tpe) - case _ => loop(tpe) - } - } - var metaType = unwrapRet(macroImpl.tpe) + try { + map2(aparamss, rparamss)((aparams, rparams) => { + if (aparams.length < rparams.length) MacroImplMissingParamsError(aparams, rparams) + if (rparams.length < aparams.length) MacroImplExtraParamsError(aparams, rparams) + }) - // downgrade from metalevel-0 to metalevel-1 - def inferRuntimeType(metaType: Type): Type = metaType match { - case TypeRef(pre, sym, args) if sym.name == tpnme.Expr && args.length == 1 => - args.head - case _ => - AnyClass.tpe - } - var runtimeType = inferRuntimeType(metaType) - - // transform type parameters of a macro implementation into type parameters of a macro definition - runtimeType = runtimeType map { - case TypeRef(pre, sym, args) => - // [Eugene] not sure which of these deSkolemizes are necessary - // sym.paramPos is unreliable (see another case below) - val tparams = macroImpl.typeParams map (_.deSkolemize) - val paramPos = tparams indexOf sym.deSkolemize - val sym1 = - if (paramPos == -1) sym - else loadMacroImplBinding(macroDef).targs(paramPos).tpe.typeSymbol - TypeRef(pre, sym1, args) - case tpe => - tpe - } + // cannot fuse these loops because if aparamss.flatten != rparamss.flatten + // then `atpeToRtpe` is going to fail with an unsound substitution + map2(aparamss.flatten, rparamss.flatten)((aparam, rparam) => { + if (aparam.name != rparam.name && !rparam.isSynthetic) MacroImplParamNameMismatchError(aparam, rparam) + if (isRepeated(aparam) ^ isRepeated(rparam)) MacroImplVarargMismatchError(aparam, rparam) + checkMacroImplParamTypeMismatch(stripOffPrefixTypeRefinement(atpeToRtpe(aparam.tpe)), rparam) + }) - // as stated in the spec, before being matched to macroimpl, type and value parameters of macrodef - // undergo a special transformation, sigma, that adapts them to the different metalevel macroimpl lives in - // as a result, we need to reverse this transformation when inferring macrodef ret from macroimpl ret - def unsigma(tpe: Type): Type = { - // unfortunately, we cannot dereference ``paramss'', because we're in the middle of inferring a type for ``macroDef'' -// val defParamss = macroDef.paramss - val defParamss = mmap(macroDdef.vparamss)(_.symbol) - var implParamss = macroImpl.paramss - implParamss = transformTypeTagEvidenceParams(implParamss, (param, tparam) => NoSymbol) - - val implCtxParam = if (implParamss.length > 0 && implParamss(0).length > 0) implParamss(0)(0) else null - def implParamToDefParam(implParam: Symbol): Symbol = { - val indices = (((implParamss drop 1).zipWithIndex) map { case (implParams, index) => (index, implParams indexOf implParam) } filter (_._2 != -1)).headOption - val defParam = indices flatMap { - case (plistIndex, pIndex) => - if (defParamss.length <= plistIndex) None - else if (defParamss(plistIndex).length <= pIndex) None - else Some(defParamss(plistIndex)(pIndex)) - } - defParam.orNull - } + checkMacroImplResultTypeMismatch(atpeToRtpe(aret), rret) - class UnsigmaTypeMap extends TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) => - val pre1 = pre match { - case SingleType(SingleType(SingleType(NoPrefix, param), prefix), value) if param == implCtxParam && prefix == MacroContextPrefix && value == ExprValue => - ThisType(macroDef.owner) - case SingleType(SingleType(NoPrefix, param), value) if implParamToDefParam(param) != null && value == ExprValue => - val macroDefParam = implParamToDefParam(param) - SingleType(NoPrefix, macroDefParam) - case _ => - pre - } - val args1 = args map mapOver - TypeRef(pre1, sym, args1) - case _ => - mapOver(tp) - } + val maxLubDepth = lubDepth(aparamss.flatten map (_.tpe)) max lubDepth(rparamss.flatten map (_.tpe)) + val atargs = solvedTypes(atvars, atparams, atparams map varianceInType(aret), upper = false, depth = maxLubDepth) + val boundsOk = typer.silent(_.infer.checkBounds(macroDdef, NoPrefix, NoSymbol, atparams, atargs, "")) + boundsOk match { + case SilentResultValue(true) => // do nothing, success + case SilentResultValue(false) | SilentTypeError(_) => MacroImplTargMismatchError(atargs, atparams) } - - new UnsigmaTypeMap() apply tpe + } catch { + case ex: NoInstance => MacroImplTparamInstantiationError(atparams, ex) } - runtimeType = unsigma(runtimeType) - - runtimeType } /** Macro classloader that is used to resolve and run macro implementations. * Loads classes from from -cp (aka the library classpath). * Is also capable of detecting REPL and reusing its classloader. */ - private lazy val macroClassloader: ClassLoader = { + lazy val macroClassloader: ClassLoader = { if (global.forMSIL) throw new UnsupportedOperationException("Scala reflection not available on this platform") @@ -753,7 +488,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath)) val loader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) - // [Eugene] a heuristic to detect the REPL + // a heuristic to detect the REPL if (global.settings.exposeEmptyPackage.value) { macroLogVerbose("macro classloader: initializing from a REPL classloader".format(global.classPath.asURLs)) import scala.tools.nsc.interpreter._ @@ -771,7 +506,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { * 4) Resolves macro implementation within the loaded companion. * * @return Requested runtime if macro implementation can be loaded successfully from either of the mirrors, - * null otherwise. + * `null` otherwise. */ type MacroRuntime = List[Any] => Any private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, MacroRuntime] @@ -787,9 +522,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { val methName = binding.methName macroLogVerbose(s"resolved implementation as $className.$methName") - // [Eugene++] I don't use Scala reflection here, because it seems to interfere with JIT magic + // I don't use Scala reflection here, because it seems to interfere with JIT magic // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20% // I'm not sure what's the reason - for me it's pure voodoo + // upd. my latest experiments show that everything's okay + // it seems that in 2.10.1 we can easily switch to Scala reflection try { macroTraceVerbose("loading implementation class: ")(className) macroTraceVerbose("classloader is: ")(ReflectionUtils.show(macroClassloader)) @@ -824,9 +561,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { /** Calculate the arguments to pass to a macro implementation when expanding the provided tree. * * This includes inferring the exact type and instance of the macro context to pass, and also - * allowing for missing parameter sections in macro implementation (see ``macroImplParamsss'' for more info). + * allowing for missing parameter sections in macro implementation (see `macroImplParamsss` for more info). * - * @return list of runtime objects to pass to the implementation obtained by ``macroRuntime'' + * @return list of runtime objects to pass to the implementation obtained by `macroRuntime` */ private def macroArgs(typer: Typer, expandee: Tree): Option[List[Any]] = { val macroDef = expandee.symbol @@ -847,7 +584,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { collectMacroArgs(expandee) val argcDoesntMatch = macroDef.paramss.length != exprArgs.length - val nullaryArgsEmptyParams = exprArgs.isEmpty && macroDef.paramss == List(List()) + val nullaryArgsEmptyParams = exprArgs.isEmpty && macroDef.paramss == ListOfNil if (argcDoesntMatch && !nullaryArgsEmptyParams) { typer.TyperErrorGen.MacroPartialApplicationError(expandee); return None } var argss: List[List[Any]] = List(context) :: exprArgs.toList @@ -882,14 +619,14 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // val outer2 = new outer1.C[String] // outer2.foo[Boolean] // - // then T and U need to be inferred from the lexical scope of the call using ``asSeenFrom'' - // whereas V won't be resolved by asSeenFrom and need to be loaded directly from ``expandee'' which needs to contain a TypeApply node + // then T and U need to be inferred from the lexical scope of the call using `asSeenFrom` + // whereas V won't be resolved by asSeenFrom and need to be loaded directly from `expandee` which needs to contain a TypeApply node // also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim val tags = binding.signature filter (_ != -1) map (paramPos => { val targ = binding.targs(paramPos).tpe.typeSymbol val tpe = if (targ.isTypeParameterOrSkolem) { if (targ.owner == macroDef) { - // [Eugene] doesn't work when macro def is compiled separately from its usages + // doesn't work when macro def is compiled separately from its usages // then targ is not a skolem and isn't equal to any of macroDef.typeParams // val argPos = targ.deSkolemize.paramPos val argPos = macroDef.typeParams.indexWhere(_.name == targ.name) @@ -927,14 +664,14 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } /** Keeps track of macros in-flight. - * See more informations in comments to ``openMacros'' in ``scala.reflect.macros.Context''. + * See more informations in comments to `openMacros` in `scala.reflect.macros.Context`. */ var openMacros = List[MacroContext]() def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition /** Performs macro expansion: - * 1) Checks whether the expansion needs to be delayed (see ``mustDelayMacroExpansion'') - * 2) Loads macro implementation using ``macroMirror'' + * 1) Checks whether the expansion needs to be delayed (see `mustDelayMacroExpansion`) + * 2) Loads macro implementation using `macroMirror` * 3) Synthesizes invocation arguments for the macro implementation * 4) Checks that the result is a tree bound to this universe * 5) Typechecks the result against the return type of the macro definition @@ -970,7 +707,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { // so I added this dummy local for the ease of debugging var expectedTpe = expandee.tpe - // [Eugene] weird situation. what's the conventional way to deal with it? val isNullaryInvocation = expandee match { case TypeApply(Select(_, _), _) => true case TypeApply(Ident(_), _) => true @@ -1029,7 +765,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { Failure(expandee) } - /** Does the same as ``macroExpand'', but without typechecking the expansion + /** 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 = @@ -1117,8 +853,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { macroLogLite("typechecking macro expansion %s at %s".format(expandee, expandee.pos)) macroArgs(typer, expandee).fold(failExpansion(): MacroExpansionResult) { args => (args: @unchecked) match { - // [Eugene++] crashes virtpatmat: + // crashes virtpatmat: // case args @ ((context: MacroContext) :: _) => + // todo. extract a minimized test case case args @ (context0 :: _) => val context = context0.asInstanceOf[MacroContext] if (nowDelayed) { @@ -1197,7 +934,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { } private def handleMacroExpansionException(typer: Typer, expandee: Tree, ex: Throwable): MacroExpansionResult = { - // [Eugene] any ideas about how to improve this one? val realex = ReflectionUtils.unwrapThrowable(ex) realex match { case realex: reflect.macros.runtime.AbortMacroException => @@ -1211,7 +947,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { try { // [Eugene] is there a better way? // [Paul] See Exceptional.scala and Origins.scala. - val relevancyThreshold = realex.getStackTrace().indexWhere(este => este.getMethodName == "macroExpand1") + val relevancyThreshold = realex.getStackTrace().indexWhere(_.getMethodName endsWith "macroExpand1") if (relevancyThreshold == -1) None else { var relevantElements = realex.getStackTrace().take(relevancyThreshold + 1) @@ -1287,7 +1023,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { /** Performs macro expansion on all subtrees of a given tree. * Innermost macros are expanded first, outermost macros are expanded last. - * See the documentation for ``macroExpand'' for more information. + * See the documentation for `macroExpand` for more information. */ def macroExpandAll(typer: Typer, expandee: Tree): Tree = new Transformer { diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index dd180e6b76..4f597f97c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -31,7 +31,6 @@ trait MethodSynthesis { else DefDef(sym, body) def applyTypeInternal(tags: List[TT[_]]): Type = { - // [Eugene++ to Paul] needs review!! val symbols = tags map compilerSymbolFromTag val container :: args = symbols val tparams = container.typeConstructor.typeParams @@ -53,21 +52,14 @@ trait MethodSynthesis { applyTypeInternal(List(t1)) def applyType[CC[X1], X1](implicit t1: TT[CC[_]], t2: TT[X1]): Type = - applyTypeInternal(List[TT[_]](t1, t2)) + applyTypeInternal(List(t1, t2)) def applyType[CC[X1, X2], X1, X2](implicit t1: TT[CC[_,_]], t2: TT[X1], t3: TT[X2]): Type = - // [Eugene++] without an explicit type annotation for List, we get this: - // [scalacfork] C:\Projects\KeplerUnderRefactoring\src\compiler\scala\tools\nsc\typechecker\MethodSynthesis.scala:59: error: no type parameters for method apply: (xs: A*)List[A] in object List exist so that it can be applied to arguments (scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[CC[_, _]], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[X1], scala.tools.nsc.typechecker.MethodSynthesis.synthesisUtil.TT[X2]) - // [scalacfork] --- because --- - // [scalacfork] undetermined type - // [scalacfork] applyTypeInternal(List(t1, t2, t3)) - applyTypeInternal(List[TT[_]](t1, t2, t3)) + 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[TT[_]](t1, t2, t3, t4)) + applyTypeInternal(List(t1, t2, t3, t4)) - // [Martin->Eugene] !!! reinstantiate when typeables are in. - // [Eugene++->Martin] now this compiles, will soon check it out def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = { val fnSymbol = compilerSymbolFromTag(t) val formals = compilerTypeFromTag(t).typeArguments @@ -250,7 +242,7 @@ trait MethodSynthesis { abort("No synthetics for " + meth + ": synthetics contains " + context.unit.synthetics.keys.mkString(", ")) } case _ => - List(stat) + stat :: Nil } def standardAccessors(vd: ValDef): List[DerivedFromValDef] = ( @@ -499,7 +491,7 @@ trait MethodSynthesis { // Derives a tree without attempting to use the original tree's symbol. override def derivedTree = { atPos(tree.pos.focus) { - DefDef(derivedMods, name, Nil, List(Nil), tree.tpt.duplicate, + DefDef(derivedMods, name, Nil, ListOfNil, tree.tpt.duplicate, if (isDeferred) EmptyTree else Select(This(owner), tree.name) ) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index fc9cb02d37..fd27c3c070 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -973,7 +973,7 @@ trait Namers extends MethodSynthesis { // Add a () parameter section if this overrides some method with () parameters. if (clazz.isClass && vparamss.isEmpty && overriddenSymbol.alternatives.exists( _.info.isInstanceOf[MethodType])) { - vparamSymss = List(List()) + vparamSymss = ListOfNil } mforeach(vparamss) { vparam => if (vparam.tpt.isEmpty) { @@ -1032,7 +1032,7 @@ trait Namers extends MethodSynthesis { var baseParamss = (vparamss, overridden.tpe.paramss) match { // match empty and missing parameter list case (Nil, List(Nil)) => Nil - case (List(Nil), Nil) => List(Nil) + case (List(Nil), Nil) => ListOfNil case (_, paramss) => paramss } assert( diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 3507bc4e09..d2ec2f793f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1298,13 +1298,12 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def transformStat(tree: Tree, index: Int): List[Tree] = tree match { case t if treeInfo.isSelfConstrCall(t) => assert(index == 0, index) - val t = transform(tree) - if (currentLevel.maxindex > 0) { + try transform(tree) :: Nil + finally if (currentLevel.maxindex > 0) { // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 debuglog("refsym = " + currentLevel.refsym) unit.error(currentLevel.refpos, "forward reference not allowed from self constructor invocation") } - List(t) case ModuleDef(_, _, _) => eliminateModuleDefs(tree) case ValDef(_, _, _, _) => val tree1 @ ValDef(_, _, _, rhs) = transform(tree) // important to do before forward reference check @@ -1316,11 +1315,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R debuglog("refsym = " + currentLevel.refsym) unit.error(currentLevel.refpos, "forward reference extends over definition of " + lazySym) } - List(tree1) + tree1 :: Nil } case Import(_, _) => Nil case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) || (tree.symbol hasFlag MACRO) => Nil - case _ => List(transform(tree)) + case _ => transform(tree) :: Nil } /* Check whether argument types conform to bounds of type parameters */ diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 2a71295690..032465351e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -290,7 +290,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT log("Ensuring accessor for call to protected " + sym.fullLocationString + " from " + currentClass) ensureAccessor(sel) } else - mayNeedProtectedAccessor(sel, List(EmptyTree), false) + mayNeedProtectedAccessor(sel, EmptyTree.asList, false) } case Super(_, mix) => @@ -303,7 +303,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT transformSuperSelect(sel) case _ => - mayNeedProtectedAccessor(sel, List(EmptyTree), true) + mayNeedProtectedAccessor(sel, EmptyTree.asList, true) } case DefDef(mods, name, tparams, vparamss, tpt, rhs) if tree.symbol.isMethodWithExtension => diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 26ab3fcfba..0c9ed29182 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -63,7 +63,7 @@ trait SyntheticMethods extends ast.TreeDSL { // in the original order. def accessors = clazz.caseFieldAccessors sortBy { acc => originalAccessors indexWhere { orig => - (acc.name == orig.name) || (acc.name startsWith (orig.name append "$").asInstanceOf[Name]) // [Eugene++] why do we need this cast? + (acc.name == orig.name) || (acc.name startsWith (orig.name append "$").asInstanceOf[Name]) // [Eugene] why do we need this cast? } } val arity = accessors.size @@ -87,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL { ) def forwardToRuntime(method: Symbol): Tree = - forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_").asInstanceOf[Name]))(mkThis :: _) // [Eugene++] why do we need this cast? + forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_").asInstanceOf[Name]))(mkThis :: _) // [Eugene] why do we need this cast? def callStaticsMethod(name: String)(args: Tree*): Tree = { val method = termMember(RuntimeStaticsModule, name) diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 4a0977eb90..f0dca64a00 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -462,7 +462,6 @@ trait TypeDiagnostics { case CyclicReference(sym, info: TypeCompleter) => if (context0.owner.isTermMacro) { // see comments to TypeSigError for an explanation of this special case - // [Eugene] is there a better way? throw ex } else { val pos = info.tree match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6ef45dd56e..b83019775d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -51,7 +51,6 @@ trait Typers extends Modes with Adaptations with Tags { transformed.clear() } - // [Eugene] shouldn't this be converted to resetAllAttrs? object UnTyper extends Traverser { override def traverse(tree: Tree) = { if (tree != EmptyTree) tree.tpe = null @@ -195,16 +194,14 @@ trait Typers extends Modes with Adaptations with Tags { case PolyType(_, _) => EmptyTree case _ => def wrapImplicit(from: Type): Tree = { - val result = inferImplicit(tree, functionType(List(from), to), reportAmbiguous, true, context, saveErrors) + val result = inferImplicit(tree, functionType(from :: Nil, to), reportAmbiguous, true, context, saveErrors) if (result.subst != EmptyTreeTypeSubstituter) { result.subst traverse tree notifyUndetparamsInferred(result.subst.from, result.subst.to) } result.tree } - val result = wrapImplicit(from) - if (result != EmptyTree) result - else wrapImplicit(byNameType(from)) + wrapImplicit(from) orElse wrapImplicit(byNameType(from)) } } @@ -909,7 +906,7 @@ trait Typers extends Modes with Adaptations with Tags { def adaptType(): Tree = { if (inFunMode(mode)) { - // [Eugene++] the commented line below makes sense for typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) + // todo. the commented line below makes sense for typechecking, say, TypeApply(Ident(`some abstract type symbol`), List(...)) // because otherwise Ident will have its tpe set to a TypeRef, not to a PolyType, and `typedTypeApply` will fail // but this needs additional investigation, because it crashes t5228, gadts1 and maybe something else // tree setType tree.tpe.normalize @@ -2502,7 +2499,7 @@ trait Typers extends Modes with Adaptations with Tags { def translated = if (members.head eq EmptyTree) setError(tree) - else typed(atPos(tree.pos)(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos.focus)), atPos(tree.pos.focus)(New(anonClass.tpe)))), mode, pt) + else typed(atPos(tree.pos)(Block(List(ClassDef(anonClass, NoMods, ListOfNil, ListOfNil, members, tree.pos.focus)), atPos(tree.pos.focus)(New(anonClass.tpe)))), mode, pt) } // Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` } @@ -2606,7 +2603,7 @@ trait Typers extends Modes with Adaptations with Tags { val stats1 = typedStats(stats, NoSymbol) // this code kicks in only after typer, so `stats` will never be filled in time // as a result, most of compound type trees with non-empty stats will fail to reify - // [Eugene++] todo. investigate whether something can be done about this + // todo. investigate whether something can be done about this val att = templ.attachments.get[CompoundTypeTreeOriginalAttachment].getOrElse(CompoundTypeTreeOriginalAttachment(Nil, Nil)) templ.removeAttachment[CompoundTypeTreeOriginalAttachment] templ addAttachment att.copy(stats = stats1) @@ -3412,7 +3409,7 @@ trait Typers extends Modes with Adaptations with Tags { } if (hasError) annotationError - else AnnotationInfo(annType, List(), nvPairs map {p => (p._1.asInstanceOf[Name], p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos)) // [Eugene+] why do we need this cast? + else AnnotationInfo(annType, List(), nvPairs map {p => (p._1.asInstanceOf[Name], p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos)) // [Eugene] why do we need this cast? } } else if (requireJava) { reportAnnotationError(NestedAnnotationError(ann, annType)) @@ -4029,9 +4026,9 @@ trait Typers extends Modes with Adaptations with Tags { } else { var thenp1 = typed(thenp, pt) var elsep1 = typed(elsep, pt) + def thenTp = packedType(thenp1, context.owner) + def elseTp = packedType(elsep1, context.owner) - lazy val thenTp = packedType(thenp1, context.owner) - lazy val elseTp = packedType(elsep1, context.owner) // println("typedIf: "+(thenp1.tpe, elsep1.tpe, ptOrLub(List(thenp1.tpe, elsep1.tpe)),"\n", thenTp, elseTp, thenTp =:= elseTp)) val (owntype, needAdapt) = // in principle we should pack the types of each branch before lubbing, but lub doesn't really work for existentials anyway @@ -4043,7 +4040,7 @@ trait Typers extends Modes with Adaptations with Tags { && thenTp =:= elseTp ) (thenp1.tpe, false) // use unpacked type // TODO: skolemize (lub of packed types) when that no longer crashes on files/pos/t4070b.scala - else ptOrLub(List(thenp1.tpe, elsep1.tpe), pt) + else ptOrLub(thenp1.tpe :: elsep1.tpe :: Nil, pt) if (needAdapt) { //isNumericValueType(owntype)) { thenp1 = adapt(thenp1, mode, owntype) @@ -5101,7 +5098,7 @@ trait Typers extends Modes with Adaptations with Tags { 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) + // 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) { @@ -5177,9 +5174,7 @@ trait Typers extends Modes with Adaptations with Tags { case ReferenceToBoxed(idt @ Ident(_)) => val id1 = typed1(idt, mode, pt) match { case id: Ident => id } - // [Eugene] am I doing it right? - val erasedTypes = phaseId(currentPeriod) >= currentRun.erasurePhase.id - val tpe = capturedVariableType(idt.symbol, erasedTypes = erasedTypes) + val tpe = capturedVariableType(idt.symbol, erasedTypes = phase.erasedTypes) treeCopy.ReferenceToBoxed(tree, id1) setType tpe case Literal(value) => @@ -5453,7 +5448,7 @@ trait Typers extends Modes with Adaptations with Tags { val isMacroBodyOkay = !tree.symbol.isErroneous && !(tree1 exists (_.isErroneous)) val shouldInheritMacroImplReturnType = ddef.tpt.isEmpty - if (isMacroBodyOkay && shouldInheritMacroImplReturnType) computeMacroDefTypeFromMacroImpl(ddef, tree.symbol, tree1.symbol) else AnyClass.tpe + if (isMacroBodyOkay && shouldInheritMacroImplReturnType) computeMacroDefTypeFromMacroImpl(ddef, tree1.symbol) else AnyClass.tpe } def transformedOr(tree: Tree, op: => Tree): Tree = transformed.get(tree) match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 4871ef199c..5db1863f67 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -115,7 +115,7 @@ trait Unapplies extends ast.TreeDSL Modifiers(OVERRIDE | FINAL), nme.toString_, Nil, - List(Nil), + ListOfNil, TypeTree(), Literal(Constant(cdef.name.decode))) @@ -126,7 +126,7 @@ trait Unapplies extends ast.TreeDSL ModuleDef( Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin), cdef.name.toTermName, - Template(parents, emptyValDef, NoMods, Nil, List(Nil), body, cdef.impl.pos.focus)) + Template(parents, emptyValDef, NoMods, Nil, ListOfNil, body, cdef.impl.pos.focus)) } private val caseMods = Modifiers(SYNTHETIC | CASE) diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala index 40ceefcc70..48a4811744 100644 --- a/src/compiler/scala/tools/reflect/MacroImplementations.scala +++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala @@ -6,11 +6,12 @@ import scala.collection.mutable.ListBuffer import scala.collection.mutable.Stack abstract class MacroImplementations { - val c: Context + val c: Context - import c.universe.{Position => SPosition, _} + import c.universe._ + import definitions._ - def macro_StringInterpolation_f(parts: List[Tree], args: List[Tree], origApplyPos: SPosition): Tree = { + def macro_StringInterpolation_f(parts: List[Tree], args: List[Tree], origApplyPos: c.universe.Position): Tree = { // the parts all have the same position information (as the expression is generated by the compiler) // the args have correct position information diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index eeec973299..8cc5a4e531 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -16,9 +16,6 @@ import scala.reflect.NameTransformer import scala.reflect.api.JavaUniverse import scala.reflect.base.MirrorOf -// [Eugene++ to Martin] by the way, toolboxes are unable to compile anything that involves packages -// is this intentional? - abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val mirror: u.Mirror @@ -187,10 +184,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName)) def makeParam(schema: (FreeTermSymbol, TermName)) = { val (fv, name) = schema - // [Eugene] conventional way of doing this? - val underlying = fv.tpe.resultType - val tpe = appliedType(definitions.FunctionClass(0).tpe, List(underlying)) - meth.newValueParameter(name) setInfo tpe + meth.newValueParameter(name) setInfo appliedType(definitions.FunctionClass(0).tpe, List(fv.tpe.resultType)) } meth setInfo MethodType(freeTerms.map(makeParam).toList, AnyClass.tpe) minfo.decls enter meth diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 2afe2acc13..5e347b051f 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -275,7 +275,7 @@ sealed abstract class Option[+A] extends Product with Serializable { * if it is nonempty, or the empty list if the $option is empty. */ def toList: List[A] = - if (isEmpty) List() else List(this.get) + if (isEmpty) List() else new ::(this.get, Nil) /** Returns a [[scala.util.Left]] containing the given * argument `left` if this $option is empty, or diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index 903de4a247..9b04256c8d 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -65,14 +65,14 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * @throws `NoSuchElementException` if the $coll is empty. */ def head: A - + /** Optionally selects the first element. * $orderDependent * @return the first element of this $coll if it is nonempty, * `None` if it is empty. */ def headOption: Option[A] - + /** Tests whether this $coll can be repeatedly traversed. * @return `true` */ @@ -92,14 +92,14 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * @throws NoSuchElementException If the $coll is empty. */ def last: A - + /** Optionally selects the last element. * $orderDependent * @return the last element of this $coll$ if it is nonempty, * `None` if it is empty. */ def lastOption: Option[A] - + /** Selects all elements except the last. * $orderDependent * @return a $coll consisting of all elements of this $coll @@ -107,7 +107,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with * @throws `UnsupportedOperationException` if the $coll is empty. */ def init: Repr - + /** Computes a prefix scan of the elements of the collection. * * Note: The neutral element `z` may be applied more than once. @@ -210,7 +210,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That /** Builds a new collection by applying a function to all elements of this $coll - * and using the elements of the resulting collections. + * and using the elements of the resulting collections. * * @param f the function to apply to each element. * @tparam B the element type of the returned collection. diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index 2aa19d6cb0..21c3a84699 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -32,6 +32,7 @@ import generic._ */ class Queue[A] extends MutableList[A] + with LinearSeqOptimized[A, Queue[A]] with GenericTraversableTemplate[A, Queue] with Cloneable[Queue[A]] with Serializable @@ -165,6 +166,17 @@ extends MutableList[A] * @return the first element. */ def front: A = head + + + // TODO - Don't override this just for new to create appropriate type.... + override def tail: Queue[A] = { + require(nonEmpty, "tail of empty list") + val tl = new Queue[A] + tl.first0 = first0.tail + tl.last0 = last0 + tl.len = len - 1 + tl + } } diff --git a/src/library/scala/reflect/ScalaLongSignature.java b/src/library/scala/reflect/ScalaLongSignature.java index fce58207f1..5b6d78f446 100644 --- a/src/library/scala/reflect/ScalaLongSignature.java +++ b/src/library/scala/reflect/ScalaLongSignature.java @@ -5,9 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** - * [Martin to Eugene++] Todo: Move to somewhere else? -*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ScalaLongSignature { diff --git a/src/library/scala/reflect/ScalaSignature.java b/src/library/scala/reflect/ScalaSignature.java index f0df99fe79..a8af554d2b 100644 --- a/src/library/scala/reflect/ScalaSignature.java +++ b/src/library/scala/reflect/ScalaSignature.java @@ -5,8 +5,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/** * [Martin to Eugene++] Todo: Move to somewhere else? - */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ScalaSignature { diff --git a/src/library/scala/reflect/base/Base.scala b/src/library/scala/reflect/base/Base.scala index 714fd365ef..28ebdf4377 100644 --- a/src/library/scala/reflect/base/Base.scala +++ b/src/library/scala/reflect/base/Base.scala @@ -279,8 +279,6 @@ class Base extends Universe { self => val NoPosition = new Position - def atPos[T <: Tree](pos: Position)(tree: T): T = tree - private val generated = new mutable.HashMap[String, WeakReference[Symbol]] private def cached(name: String)(symExpr: => Symbol): Symbol = @@ -411,6 +409,22 @@ class Base extends Universe { self => lazy val ListClass = staticClass("scala.List") lazy val PredefModule = staticModule("scala.Predef") + + lazy val ByteTpe = TypeRef(ScalaPrefix, ByteClass, Nil) + lazy val ShortTpe = TypeRef(ScalaPrefix, ShortClass, Nil) + lazy val CharTpe = TypeRef(ScalaPrefix, CharClass, Nil) + lazy val IntTpe = TypeRef(ScalaPrefix, IntClass, Nil) + lazy val LongTpe = TypeRef(ScalaPrefix, LongClass, Nil) + lazy val FloatTpe = TypeRef(ScalaPrefix, FloatClass, Nil) + lazy val DoubleTpe = TypeRef(ScalaPrefix, DoubleClass, Nil) + lazy val BooleanTpe = TypeRef(ScalaPrefix, BooleanClass, Nil) + lazy val UnitTpe = TypeRef(ScalaPrefix, UnitClass, Nil) + lazy val AnyTpe = TypeRef(ScalaPrefix, AnyClass, Nil) + lazy val AnyValTpe = TypeRef(ScalaPrefix, AnyValClass, Nil) + lazy val NothingTpe = TypeRef(ScalaPrefix, NothingClass, Nil) + lazy val NullTpe = TypeRef(ScalaPrefix, NullClass, Nil) + lazy val ObjectTpe = TypeRef(JavaLangPrefix, ObjectClass, Nil) + lazy val AnyRefTpe = ObjectTpe } import definitions._ @@ -419,22 +433,6 @@ class Base extends Universe { self => private lazy val ScalaPrefix = thisModuleType("scala") private lazy val JavaLangPrefix = thisModuleType("java.lang") - lazy val ByteTpe = TypeRef(ScalaPrefix, ByteClass, Nil) - lazy val ShortTpe = TypeRef(ScalaPrefix, ShortClass, Nil) - lazy val CharTpe = TypeRef(ScalaPrefix, CharClass, Nil) - lazy val IntTpe = TypeRef(ScalaPrefix, IntClass, Nil) - lazy val LongTpe = TypeRef(ScalaPrefix, LongClass, Nil) - lazy val FloatTpe = TypeRef(ScalaPrefix, FloatClass, Nil) - lazy val DoubleTpe = TypeRef(ScalaPrefix, DoubleClass, Nil) - lazy val BooleanTpe = TypeRef(ScalaPrefix, BooleanClass, Nil) - lazy val UnitTpe = TypeRef(ScalaPrefix, UnitClass, Nil) - lazy val AnyTpe = TypeRef(ScalaPrefix, AnyClass, Nil) - lazy val AnyValTpe = TypeRef(ScalaPrefix, AnyValClass, Nil) - lazy val NothingTpe = TypeRef(ScalaPrefix, NothingClass, Nil) - lazy val NullTpe = TypeRef(ScalaPrefix, NullClass, Nil) - lazy val ObjectTpe = TypeRef(JavaLangPrefix, ObjectClass, Nil) - lazy val AnyRefTpe = ObjectTpe - private var nodeCount = 0 // not synchronized abstract class Tree extends TreeBase with Product { @@ -489,6 +487,7 @@ class Base extends Universe { self => } case object EmptyTree extends TermTree { + val asList = List(this) override def isEmpty = true } @@ -745,7 +744,6 @@ class Base extends Universe { self => implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree]) implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree]) - // [Eugene++] to be removed after SI-5863 is fixed def ClassDef(sym: Symbol, impl: Template): ClassDef = ??? def ModuleDef(sym: Symbol, impl: Template): ModuleDef = ??? def ValDef(sym: Symbol, rhs: Tree): ValDef = ??? diff --git a/src/library/scala/reflect/base/BuildUtils.scala b/src/library/scala/reflect/base/BuildUtils.scala index eaba0ec2b7..98f32231ad 100644 --- a/src/library/scala/reflect/base/BuildUtils.scala +++ b/src/library/scala/reflect/base/BuildUtils.scala @@ -5,6 +5,10 @@ trait BuildUtils { self: Universe => val build: BuildBase + // this API abstracts away the functionality necessary for reification + // it's too gimmicky and unstructured to be exposed directly in the universe + // but we need it in a publicly available place for reification to work + abstract class BuildBase { /** Selects type symbol with given simple name `name` from the defined members of `owner`. */ @@ -53,7 +57,6 @@ trait BuildUtils { self: Universe => * the only usage for it is preserving the captured symbol for compile-time analysis * @param flags (optional) flags of the free variable * @param origin (optional) debug information that tells where this symbol comes from - * [Martin to Eugene: why needed?] */ def newFreeExistential(name: String, info: Type, value: => Any, flags: FlagSet = NoFlags, origin: String = null): FreeTypeSymbol @@ -68,9 +71,6 @@ trait BuildUtils { self: Universe => def flagsFromBits(bits: Long): FlagSet - // [Eugene++ to Martin] these are necessary for reification - // on a second thought, I added them to BuildUtils instead of base - def emptyValDef: ValDef def This(sym: Symbol): Tree diff --git a/src/library/scala/reflect/base/Exprs.scala b/src/library/scala/reflect/base/Exprs.scala index 47af4f3a9d..10c222722a 100644 --- a/src/library/scala/reflect/base/Exprs.scala +++ b/src/library/scala/reflect/base/Exprs.scala @@ -39,10 +39,7 @@ trait Exprs { self: Universe => otherMirror.universe.Expr[T](otherMirror1, treec)(tag1) } - lazy val tree: Tree = treec[Exprs.this.type](mirror) - // [Eugene++] this is important - // !!! remove when we have improved type inference for singletons - // search for .type] to find other instances + lazy val tree: Tree = treec(mirror) lazy val staticType: Type = implicitly[AbsTypeTag[T]].tpe def actualType: Type = treeType(tree) diff --git a/src/library/scala/reflect/base/MirrorOf.scala b/src/library/scala/reflect/base/MirrorOf.scala index 6dc8090eee..1e9619d062 100644 --- a/src/library/scala/reflect/base/MirrorOf.scala +++ b/src/library/scala/reflect/base/MirrorOf.scala @@ -1,8 +1,6 @@ package scala.reflect package base -// [Eugene++ to Martin] why was this a member of `scala.reflect`, but not `scala.reflect.base`? - abstract class MirrorOf[U <: base.Universe with Singleton] { /** .. */ val universe: U diff --git a/src/library/scala/reflect/base/Positions.scala b/src/library/scala/reflect/base/Positions.scala index cefeb51c9a..76a7382e9e 100644 --- a/src/library/scala/reflect/base/Positions.scala +++ b/src/library/scala/reflect/base/Positions.scala @@ -14,9 +14,4 @@ trait Positions { /** .. */ val NoPosition: Position - - /** Assigns a given position to all position-less nodes of a given AST. - */ - def atPos[T <: Tree](pos: Position)(tree: T): T - // [Eugene++] why do we have this in base? } diff --git a/src/library/scala/reflect/base/StandardDefinitions.scala b/src/library/scala/reflect/base/StandardDefinitions.scala index fe32fdb4c2..8f1c96ea3f 100644 --- a/src/library/scala/reflect/base/StandardDefinitions.scala +++ b/src/library/scala/reflect/base/StandardDefinitions.scala @@ -6,37 +6,12 @@ package scala.reflect package base -// [Eugene++] not sure whether we need this in the top level of the universe -trait StandardTypes { - self: Universe => - - val ByteTpe: Type - val ShortTpe: Type - val CharTpe: Type - val IntTpe: Type - val LongTpe: Type - val FloatTpe: Type - val DoubleTpe: Type - val BooleanTpe: Type - val UnitTpe: Type - - val AnyTpe: Type - val AnyValTpe: Type - val AnyRefTpe: Type - val ObjectTpe: Type - - val NothingTpe: Type - val NullTpe: Type -} - -trait StandardDefinitions extends StandardTypes { +trait StandardDefinitions { self: Universe => val definitions: DefinitionsBase - // [Eugene] todo. shortcut to these fields if possible when generating tags - // todo. also shortcut to StandardTypes, of course - trait DefinitionsBase { + trait DefinitionsBase extends StandardTypes { // packages def ScalaPackageClass: ClassSymbol def ScalaPackage: ModuleSymbol @@ -66,9 +41,32 @@ trait StandardDefinitions extends StandardTypes { def StringClass : ClassSymbol def ClassClass : ClassSymbol def ArrayClass : ClassSymbol - def ListClass : ClassSymbol // [Eugene] I'd say List has earned its right to be here + def ListClass : ClassSymbol // the Predef object def PredefModule: ModuleSymbol } + + trait StandardTypes { + // the scala value classes + val UnitTpe: Type + val ByteTpe: Type + val ShortTpe: Type + val CharTpe: Type + val IntTpe: Type + val LongTpe: Type + val FloatTpe: Type + val DoubleTpe: Type + val BooleanTpe: Type + + // top types + val AnyTpe: Type + val AnyValTpe: Type + val AnyRefTpe: Type + val ObjectTpe: Type + + // bottom types + val NothingTpe: Type + val NullTpe: Type + } } diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala index fe857c540f..294fa19d62 100644 --- a/src/library/scala/reflect/base/Symbols.scala +++ b/src/library/scala/reflect/base/Symbols.scala @@ -3,9 +3,6 @@ package base trait Symbols { self: Universe => - // [Eugene++ to Martin] why is Symbol >: Null, whereas all other symbol types are not nullable? - // same question goes for Types - /** The abstract type of symbols representing declarations */ type Symbol >: Null <: SymbolBase @@ -266,7 +263,7 @@ trait Symbols { self: Universe => * by inspecting its `selfType.termSymbol`. */ def moduleClass: Symbol // needed for tree traversals - // [Eugene++] when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life + // when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life final override def isModule = true final override def asModule = this diff --git a/src/library/scala/reflect/base/TagInterop.scala b/src/library/scala/reflect/base/TagInterop.scala index a9f0b60fd2..ec054106eb 100644 --- a/src/library/scala/reflect/base/TagInterop.scala +++ b/src/library/scala/reflect/base/TagInterop.scala @@ -4,12 +4,9 @@ package base import scala.runtime.ScalaRunTime._ trait TagInterop { self: Universe => - // [Eugene++] `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work + // todo. `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work // if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala - // [Eugene++] would be great if we could approximate the interop without any mirrors - // todo. think how to implement that - def typeTagToManifest[T: ClassTag](mirror: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use scala.reflect.runtime.universe from scala-reflect.jar.") diff --git a/src/library/scala/reflect/base/Trees.scala b/src/library/scala/reflect/base/Trees.scala index 70993fd77f..224965a2b7 100644 --- a/src/library/scala/reflect/base/Trees.scala +++ b/src/library/scala/reflect/base/Trees.scala @@ -5,10 +5,6 @@ package scala.reflect package base -// [Eugene++] of all reflection APIs, this one is in the biggest need of review and documentation - -// Syncnote: Trees are currently not thread-safe. -// [Eugene++] now when trees are finally abstract types, can we do something for this? trait Trees { self: Universe => /** The base API that all trees support */ @@ -81,7 +77,6 @@ trait Trees { self: Universe => * example is Parens, which is eliminated during parsing. */ type Tree >: Null <: TreeBase - // [Eugene++] todo. discuss nullability of abstract types /** A tag that preserves the identity of the `Tree` abstract type from erasure. * Can be used for pattern matching, instance tests, serialization and likes. @@ -1381,7 +1376,6 @@ trait Trees { self: Universe => /** ... */ lazy val NoMods = Modifiers() - // [Eugene++] temporarily moved here until SI-5863 is fixed // ---------------------- factories ---------------------------------------------- /** @param sym the class symbol diff --git a/src/library/scala/reflect/base/TypeTags.scala b/src/library/scala/reflect/base/TypeTags.scala index b673122d00..c9d1ccf5bc 100644 --- a/src/library/scala/reflect/base/TypeTags.scala +++ b/src/library/scala/reflect/base/TypeTags.scala @@ -99,9 +99,10 @@ import language.implicitConversions * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API. * Consider using reflection API provided by Java (for classes) and Scala (for types) instead. */ -// [Eugene++] implement serialization for typetags trait TypeTags { self: Universe => + import definitions._ + /** * If an implicit value of type u.AbsTypeTag[T] is required, the compiler will make one up on demand. * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T. @@ -164,7 +165,7 @@ trait TypeTags { self: Universe => } private class AbsTypeTagImpl[T](val mirror: Mirror, val tpec: TypeCreator) extends AbsTypeTag[T] { - lazy val tpe: Type = tpec[self.type](mirror) + lazy val tpe: Type = tpec(mirror) def in[U <: Universe with Singleton](otherMirror: MirrorOf[U]): U # AbsTypeTag[T] = { val otherMirror1 = otherMirror.asInstanceOf[MirrorOf[otherMirror.universe.type]] otherMirror.universe.AbsTypeTag[T](otherMirror1, tpec) diff --git a/src/library/scala/reflect/base/Types.scala b/src/library/scala/reflect/base/Types.scala index 28aaf2d04d..b016b77f36 100644 --- a/src/library/scala/reflect/base/Types.scala +++ b/src/library/scala/reflect/base/Types.scala @@ -14,7 +14,7 @@ trait Types { self: Universe => /** A tag that preserves the identity of the `Type` abstract type from erasure. * Can be used for pattern matching, instance tests, serialization and likes. */ - implicit val TypeTagg: ClassTag[Type] // [Eugene++] rename! + implicit val TypeTagg: ClassTag[Type] /** This constant is used as a special value that indicates that no meaningful type exists. */ diff --git a/src/library/scala/reflect/macros/internal/package.scala b/src/library/scala/reflect/macros/internal/package.scala index 912db53ed4..0a0e6c5b51 100644 --- a/src/library/scala/reflect/macros/internal/package.scala +++ b/src/library/scala/reflect/macros/internal/package.scala @@ -5,9 +5,7 @@ import scala.reflect.ClassTag // anchors for materialization macros emitted during tag materialization in Implicits.scala // implementation is magically hardwired into `scala.reflect.reify.Taggers` -// // todo. once we have implicit macros for tag generation, we can remove these anchors -// [Eugene++] how do I hide this from scaladoc? package object internal { private[scala] def materializeClassTag[T](u: BaseUniverse): ClassTag[T] = ??? // macro private[scala] def materializeAbsTypeTag[T](u: BaseUniverse): u.AbsTypeTag[T] = ??? // macro diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala index 2d3f54a95e..79476bdc16 100644 --- a/src/library/scala/util/Marshal.scala +++ b/src/library/scala/util/Marshal.scala @@ -37,8 +37,6 @@ object Marshal { val in = new ObjectInputStream(new ByteArrayInputStream(buffer)) val found = in.readObject.asInstanceOf[ClassTag[_]] try { - // [Eugene] needs review - // previously was: found <:< expected found.runtimeClass.asSubclass(expected.runtimeClass) in.readObject.asInstanceOf[A] } catch { diff --git a/src/reflect/scala/reflect/api/FrontEnds.scala b/src/reflect/scala/reflect/api/FrontEnds.scala index a201b83444..a27450d49d 100644 --- a/src/reflect/scala/reflect/api/FrontEnds.scala +++ b/src/reflect/scala/reflect/api/FrontEnds.scala @@ -1,8 +1,6 @@ package scala.reflect package api -// [Martin to Eugene] Todo: Needs to be evicted from API -// [Eugene++ to Martin] but how? we need them for macros trait FrontEnds { type Position >: Null diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index de540a9605..fbc29a514e 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -1,8 +1,6 @@ package scala.reflect package api -// [Martin] Importers need to be made mirror aware. -// [Eugene++] this is important trait Importers { self: Universe => def mkImporter(from0: Universe): Importer { val from: from0.type } diff --git a/src/reflect/scala/reflect/api/JavaUniverse.scala b/src/reflect/scala/reflect/api/JavaUniverse.scala index 8bf62a357c..f2388433c4 100644 --- a/src/reflect/scala/reflect/api/JavaUniverse.scala +++ b/src/reflect/scala/reflect/api/JavaUniverse.scala @@ -1,8 +1,6 @@ package scala.reflect package api -// [Martin] Moved to compiler because it needs to see runtime.Universe -// The two will be united in scala-reflect anyway. trait JavaUniverse extends Universe with Mirrors with TagInterop { self => type RuntimeClass = java.lang.Class[_] diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index f2f96645e3..7d185d9879 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -5,19 +5,7 @@ trait Mirrors { self: Universe => type RuntimeClass >: Null - // [Eugene] also, it might make sense to provide shortcuts for the API - // - // for example, right now to invoke the same method for several different instances, you need: - // 1) get the method symbol - // 2) get the instance mirror for every instance - // 3) call reflectMethod on the instance mirrors for every instance - // 4) call apply for every instance (okay, this can be united with step #3, but still) - // - // I have several suggestions that we can discuss later: - // 1) For every `reflectXXX(sym: Symbol): XXXMirror`, add `reflectXXX(name: String, types: Type*): XXXMirror` and `reflectXXXs(): List[XXXMirror]` - // 2) Provide a way to skip obtaining InstanceMirror (step #2 in the outline provided above) - - // [Eugene] another improvement would be have mirrors reproduce the structure of the reflection domain + // todo. an improvement might be having mirrors reproduce the structure of the reflection domain // e.g. a ClassMirror could also have a list of fields, methods, constructors and so on // read up more on the proposed design in "Reflecting Scala" by Y. Coppel @@ -162,7 +150,7 @@ trait Mirrors { self: Universe => def runtimeClass: RuntimeClass /** True if the mirror represents the static part - * if a runtime class or the companion object of a Scala class. + * of a runtime class or the companion object of a Scala class. * One has: * * this.isStatic == this.isInstanceOf[ModuleMirror] @@ -204,7 +192,7 @@ trait Mirrors { self: Universe => * Otherwise, if the mirror represents the static part of a runtime class, the * mirror representing the instance part of the same class. */ - def companion: Option[ClassMirror] + override def companion: Option[ClassMirror] } /** A mirror that reflects the instance parts of a runtime class */ @@ -231,7 +219,7 @@ trait Mirrors { self: Universe => * Otherwise, if the mirror represents a runtime instance class, a mirror representing the static * part of the same class. */ - def companion: Option[ModuleMirror] + override def companion: Option[ModuleMirror] } /** A mirror that reflects instances and static classes */ diff --git a/src/reflect/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala index 9d3d90d9f8..5e8d958f02 100644 --- a/src/reflect/scala/reflect/api/Positions.scala +++ b/src/reflect/scala/reflect/api/Positions.scala @@ -7,6 +7,10 @@ trait Positions extends base.Positions { /** .. */ type Position >: Null <: PositionApi { type Pos = Position } + /** Assigns a given position to all position-less nodes of a given AST. + */ + def atPos[T <: Tree](pos: Position)(tree: T): T + /** A position that wraps a set of trees. * The point of the wrapping position is the point of the default position. * If some of the trees are ranges, returns a range position enclosing all ranges @@ -20,14 +24,6 @@ trait Positions extends base.Positions { * Otherwise returns a synthetic offset position to point. */ def wrappingPos(trees: List[Tree]): Position - - /** Ensure that given tree has no positions that overlap with - * any of the positions of `others`. This is done by - * shortening the range or assigning TransparentPositions - * to some of the nodes in `tree`. - */ - //def ensureNonOverlapping(tree: Tree, others: List[Tree]) - // [Eugene++] can this method be of use for macros? } /** The Position class and its subclasses represent positions of ASTs and symbols. diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala index 3415b0fa10..9e7b3c9712 100644 --- a/src/reflect/scala/reflect/api/Symbols.scala +++ b/src/reflect/scala/reflect/api/Symbols.scala @@ -21,7 +21,7 @@ trait Symbols extends base.Symbols { self: Universe => /** A list of annotations attached to this Symbol. */ - // [Eugene++] we cannot expose the `annotations` method because it doesn't auto-initialize a symbol (see SI-5423) + // we cannot expose the `annotations` method because it doesn't auto-initialize a symbol (see SI-5423) // there was an idea to use the `isCompilerUniverse` flag and auto-initialize symbols in `annotations` whenever this flag is false // but it doesn't work, because the unpickler (that is shared between reflective universes and global universes) is very picky about initialization // scala.reflect.internal.Types$TypeError: bad reference while unpickling scala.collection.immutable.Nil: type Nothing not found in scala.type not found. @@ -205,7 +205,6 @@ trait Symbols extends base.Symbols { self: Universe => /** The API of term symbols */ trait TermSymbolApi extends SymbolApi with TermSymbolBase { this: TermSymbol => /** Does this symbol represent a value, i.e. not a module and not a method? - * [Eugene++] I need a review of the implementation */ def isValue: Boolean diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala index 4d2254cb9f..5ab085741e 100644 --- a/src/reflect/scala/reflect/api/TagInterop.scala +++ b/src/reflect/scala/reflect/api/TagInterop.scala @@ -4,16 +4,10 @@ package api import scala.reflect.base.TypeCreator import scala.reflect.base.{Universe => BaseUniverse} -// [Martin] Moved to compiler because it needs to see runtime.Universe -// The two will be united in scala-reflect anyway. trait TagInterop { self: JavaUniverse => - // [Eugene++] would be great if we could approximate the interop without any mirrors - // todo. think how to implement that - override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: base.Universe # TypeTag[T]): Manifest[T] = { - // [Eugene++] implement more sophisticated logic - // Martin said it'd be okay to simply copypaste `Implicits.manifestOfType` + // SI-6239: make this conversion more precise val mirror = mirror0.asInstanceOf[Mirror] val runtimeClass = mirror.runtimeClass(tag.in(mirror).tpe) Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]] diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala index 199cf9b9e5..ebaedd7ac3 100644 --- a/src/reflect/scala/reflect/api/Types.scala +++ b/src/reflect/scala/reflect/api/Types.scala @@ -293,7 +293,6 @@ trait Types extends base.Types { self: Universe => // Creators --------------------------------------------------------------- // too useful and too non-trivial to be left out of public API - // [Eugene to Paul] needs review! /** The canonical creator for single-types */ def singleType(pre: Type, sym: Symbol): Type diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index f01247d918..2daf3d1c85 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -19,23 +19,6 @@ trait Definitions extends api.StandardDefinitions { object definitions extends DefinitionsClass - // [Eugene] find a way to make these non-lazy - lazy val ByteTpe = definitions.ByteClass.toTypeConstructor - lazy val ShortTpe = definitions.ShortClass.toTypeConstructor - lazy val CharTpe = definitions.CharClass.toTypeConstructor - lazy val IntTpe = definitions.IntClass.toTypeConstructor - lazy val LongTpe = definitions.LongClass.toTypeConstructor - lazy val FloatTpe = definitions.FloatClass.toTypeConstructor - lazy val DoubleTpe = definitions.DoubleClass.toTypeConstructor - lazy val BooleanTpe = definitions.BooleanClass.toTypeConstructor - lazy val UnitTpe = definitions.UnitClass.toTypeConstructor - lazy val AnyTpe = definitions.AnyClass.toTypeConstructor - lazy val ObjectTpe = definitions.ObjectClass.toTypeConstructor - lazy val AnyValTpe = definitions.AnyValClass.toTypeConstructor - lazy val AnyRefTpe = definitions.AnyRefClass.toTypeConstructor - lazy val NothingTpe = definitions.NothingClass.toTypeConstructor - lazy val NullTpe = definitions.NullClass.toTypeConstructor - /** Since both the value parameter types and the result type may * require access to the type parameter symbols, we model polymorphic * creation as a function from those symbols to (formal types, result type). @@ -143,10 +126,19 @@ trait Definitions extends api.StandardDefinitions { lazy val Boolean_or = getMemberMethod(BooleanClass, nme.ZOR) lazy val Boolean_not = getMemberMethod(BooleanClass, nme.UNARY_!) - lazy val ScalaNumericValueClasses = ScalaValueClasses filterNot Set[Symbol](UnitClass, BooleanClass) + lazy val UnitTpe = UnitClass.toTypeConstructor + lazy val ByteTpe = ByteClass.toTypeConstructor + lazy val ShortTpe = ShortClass.toTypeConstructor + lazy val CharTpe = CharClass.toTypeConstructor + lazy val IntTpe = IntClass.toTypeConstructor + lazy val LongTpe = LongClass.toTypeConstructor + lazy val FloatTpe = FloatClass.toTypeConstructor + lazy val DoubleTpe = DoubleClass.toTypeConstructor + lazy val BooleanTpe = BooleanClass.toTypeConstructor - def ScalaValueClassesNoUnit = ScalaValueClasses filterNot (_ eq UnitClass) - def ScalaValueClasses: List[ClassSymbol] = List( + lazy val ScalaNumericValueClasses = ScalaValueClasses filterNot Set[Symbol](UnitClass, BooleanClass) + lazy val ScalaValueClassesNoUnit = ScalaValueClasses filterNot (_ eq UnitClass) + lazy val ScalaValueClasses: List[ClassSymbol] = List( UnitClass, BooleanClass, ByteClass, @@ -242,6 +234,9 @@ trait Definitions extends api.StandardDefinitions { lazy val AnyClass = enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT) lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.tpe) lazy val ObjectClass = getRequiredClass(sn.Object.toString) + lazy val AnyTpe = definitions.AnyClass.toTypeConstructor + lazy val AnyRefTpe = definitions.AnyRefClass.toTypeConstructor + lazy val ObjectTpe = definitions.ObjectClass.toTypeConstructor // Note: this is not the type alias AnyRef, it's a companion-like // object used by the @specialize annotation. @@ -255,6 +250,7 @@ trait Definitions extends api.StandardDefinitions { anyval.info.decls enter av_constr anyval }).asInstanceOf[ClassSymbol] + lazy val AnyValTpe = definitions.AnyValClass.toTypeConstructor // bottom types lazy val RuntimeNothingClass = getClassByName(fulltpnme.RuntimeNothing) @@ -276,6 +272,8 @@ trait Definitions extends api.StandardDefinitions { || (that ne NothingClass) && (that isSubClass ObjectClass) ) } + lazy val NothingTpe = definitions.NothingClass.toTypeConstructor + lazy val NullTpe = definitions.NullClass.toTypeConstructor // exceptions and other throwables lazy val ClassCastExceptionClass = requiredClass[ClassCastException] @@ -302,7 +300,7 @@ trait Definitions extends api.StandardDefinitions { def Sys_error = getMemberMethod(SysPackage, nme.error) // Modules whose members are in the default namespace - // [Eugene++] ScalaPackage and JavaLangPackage are never ever shared between mirrors + // SI-5941: ScalaPackage and JavaLangPackage are never ever shared between mirrors // as a result, `Int` becomes `scala.Int` and `String` becomes `java.lang.String` // I could just change `isOmittablePrefix`, but there's more to it, so I'm leaving this as a todo for now lazy val UnqualifiedModules = List(PredefModule, ScalaPackage, JavaLangPackage) @@ -338,7 +336,6 @@ trait Definitions extends api.StandardDefinitions { lazy val SymbolModule = requiredModule[scala.Symbol.type] lazy val Symbol_apply = getMemberMethod(SymbolModule, nme.apply) - def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) // [Eugene++] obsolete? def arrayApplyMethod = getMemberMethod(ScalaRunTimeModule, nme.array_apply) def arrayUpdateMethod = getMemberMethod(ScalaRunTimeModule, nme.array_update) def arrayLengthMethod = getMemberMethod(ScalaRunTimeModule, nme.array_length) @@ -383,6 +380,7 @@ 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 isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params) @@ -978,12 +976,7 @@ trait Definitions extends api.StandardDefinitions { throw new FatalError(owner + " does not have a " + what + " " + name) } - def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule): Symbol = - // [Eugene++] `getMemberClass` leads to crashes in mixin: - // "object languageFeature does not have a member class implicitConversions" - // that's because by that time `implicitConversions` becomes a module - // getMemberClass(owner, newTypeName(name)) - getMember(owner, newTypeName(name)) + 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)) @@ -1008,28 +1001,24 @@ trait Definitions extends api.StandardDefinitions { } } def getMemberValue(owner: Symbol, name: Name): TermSymbol = { - // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTermName) match { case x: TermSymbol => x case _ => fatalMissingSymbol(owner, name, "member value") } } def getMemberModule(owner: Symbol, name: Name): ModuleSymbol = { - // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTermName) match { case x: ModuleSymbol => x case _ => fatalMissingSymbol(owner, name, "member object") } } def getMemberType(owner: Symbol, name: Name): TypeSymbol = { - // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTypeName) match { case x: TypeSymbol => x case _ => fatalMissingSymbol(owner, name, "member type") } } def getMemberClass(owner: Symbol, name: Name): ClassSymbol = { - // [Eugene++] should be a ClassCastException instead? val y = getMember(owner, name.toTypeName) getMember(owner, name.toTypeName) match { case x: ClassSymbol => x @@ -1037,48 +1026,8 @@ trait Definitions extends api.StandardDefinitions { } } def getMemberMethod(owner: Symbol, name: Name): TermSymbol = { - // [Eugene++] is this a bug? - // - // System.err.println(result.getClass) - // System.err.println(result.flags) - // System.err.println("isMethod = " + result.isMethod) - // System.err.println("isTerm = " + result.isTerm) - // System.err.println("isValue = " + result.isValue) - // result.asMethod - // - // prints this: - // - // quick.lib: - // [javac] Compiling 1 source file to C:\Projects\KeplerUnderRefactoring\build\quick\classes\library - // [scalacfork] Compiling 769 files to C:\Projects\KeplerUnderRefactoring\build\quick\classes\library - // [scalacfork] class scala.reflect.internal.Symbols$TermSymbol - // [scalacfork] 8589934592 - // [scalacfork] isMethod = false - // [scalacfork] isTerm = true - // [scalacfork] isValue = true - // [scalacfork] - // [scalacfork] while compiling: C:\Projects\KeplerUnderRefactoring\src\library\scala\LowPriorityImplicits.scala - // [scalacfork] current phase: cleanup - // [scalacfork] library version: version 2.10.0-20120507-185519-665d1d9127 - // [scalacfork] compiler version: version 2.10.0-20120507-185519-665d1d9127 - // [scalacfork] reconstructed args: -Xmacros -classpath C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library;C:\\Projects\\KeplerUnderRefactoring\\lib\\forkjoin.jar -d C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library -sourcepath C:\\Projects\\KeplerUnderRefactoring\\src\\library - // [scalacfork] - // [scalacfork] unhandled exception while transforming LowPriorityImplicits.scala - // [scalacfork] error: - // [scalacfork] while compiling: C:\Projects\KeplerUnderRefactoring\src\library\scala\LowPriorityImplicits.scala - // [scalacfork] current phase: cleanup - // [scalacfork] library version: version 2.10.0-20120507-185519-665d1d9127 - // [scalacfork] compiler version: version 2.10.0-20120507-185519-665d1d9127 - // [scalacfork] reconstructed args: -Xmacros -classpath C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library;C:\\Projects\\KeplerUnderRefactoring\\lib\\forkjoin.jar -d C:\\Projects\\KeplerUnderRefactoring\\build\\quick\\classes\\library -sourcepath C:\\Projects\\KeplerUnderRefactoring\\src\\library - // [scalacfork] - // [scalacfork] uncaught exception during compilation: java.lang.ClassCastException - // [scalacfork] error: java.lang.ClassCastException: value apply - // [scalacfork] at scala.reflect.base.Symbols$SymbolBase$class.asMethod(Symbols.scala:118) - // [scalacfork] at scala.reflect.internal.Symbols$SymbolContextApiImpl.asMethod(Symbols.scala:63) - // [scalacfork] at scala.reflect.internal.Definitions$DefinitionsClass.Symbol_apply(Definitions.scala:381) - - // [Eugene++] should be a ClassCastException instead? getMember(owner, name.toTermName) match { + // todo. member symbol becomes a term symbol in cleanup. is this a bug? // case x: MethodSymbol => x case x: TermSymbol => x case _ => fatalMissingSymbol(owner, name, "method") diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 00017e087a..25441f9812 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -2,10 +2,9 @@ package scala.reflect package internal import scala.collection.mutable.WeakHashMap -// todo: move importers to a mirror +// SI-6241: move importers to a mirror trait Importers { self: SymbolTable => - // [Eugene] possible to make this less cast-heavy? def mkImporter(from0: api.Universe): Importer { val from: from0.type } = ( if (self eq from0) { new Importer { diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 0c86e4fba0..9580ed1f72 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -3,7 +3,7 @@ * @author Martin Odersky */ -// [Eugene++ to Martin] we need to unify this prettyprinter with NodePrinters +// todo. we need to unify this prettyprinter with NodePrinters package scala.reflect package internal @@ -174,12 +174,7 @@ trait Printers extends api.Printers { self: SymbolTable => } def printAnnotations(tree: Tree) { - if (!isCompilerUniverse && tree.symbol != null && tree.symbol != NoSymbol) - // [Eugene++] todo. this is not 100% correct, but is necessary for sane printing - // the problem is that getting annotations doesn't automatically initialize the symbol - // so we might easily print something as if it doesn't have annotations, whereas it does - tree.symbol.initialize - + // SI-5885: by default this won't print annotations of not yet initialized symbols val annots = tree.symbol.annotations match { case Nil => tree.asInstanceOf[MemberDef].mods.annotations case anns => anns diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index c1e5f78d50..f63e2602b1 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -1008,8 +1008,6 @@ trait StdNames { val javanme = nme.javaKeywords - // [Eugene++ to Martin] had to move a lot of stuff from here to TermNames to satisfy the contract - // why do we even have stuff in object nme? cf. object tpnme object nme extends TermNames { def isModuleVarName(name: Name): Boolean = diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 5e83f638a2..0953849f05 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -294,14 +294,31 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = newAbstractType(name, pos, EXISTENTIAL | newFlags) - /** Synthetic value parameters when parameter symbols are not available - */ - final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[TermSymbol]] = { + private def freshNamer: () => TermName = { var cnt = 0 - def freshName() = { cnt += 1; nme.syntheticParamName(cnt) } - mmap(argtypess)(tp => newValueParameter(freshName(), owner.pos.focus, SYNTHETIC) setInfo tp) + () => { 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. + */ + final def newSyntheticValueParams(argtypes: List[Type]): List[TermSymbol] = + newSyntheticValueParams(argtypes, freshNamer) + + final def newSyntheticValueParams(argtypes: List[Type], freshName: () => TermName): List[TermSymbol] = + argtypes map (tp => newSyntheticValueParam(tp, freshName())) + + /** Synthetic value parameter when parameter symbol is not available. + * Calling this method multiple times will re-use the same parameter name. + */ + 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)) @@ -328,18 +345,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def freshExistential(suffix: String): TypeSymbol = newExistential(freshExistentialName(suffix), pos) - /** Synthetic value parameters when parameter symbols are not available. - * Calling this method multiple times will re-use the same parameter names. - */ - final def newSyntheticValueParams(argtypes: List[Type]): List[TermSymbol] = - newSyntheticValueParamss(List(argtypes)).head - - /** Synthetic value parameter when parameter symbol is not available. - * Calling this method multiple times will re-use the same parameter name. - */ - final def newSyntheticValueParam(argtype: Type): Symbol = - newSyntheticValueParams(List(argtype)).head - /** Type skolems are type parameters ''seen from the inside'' * Assuming a polymorphic method m[T], its type is a PolyType which has a TypeParameter * with name `T` in its typeParams list. While type checking the parameters, result type and @@ -848,7 +853,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isInitialized: Boolean = validTo != NoPeriod - // [Eugene] todo. needs to be reviewed and [only then] rewritten without explicit returns /** Determines whether this symbol can be loaded by subsequent reflective compilation */ final def isLocatable: Boolean = { if (this == NoSymbol) return false @@ -1536,7 +1540,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => def alternatives: List[Symbol] = if (isOverloaded) info.asInstanceOf[OverloadedType].alternatives - else List(this) + else this :: Nil def filter(cond: Symbol => Boolean): Symbol = if (isOverloaded) { @@ -1640,7 +1644,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => (info.decls filter (_.isCaseAccessorMethod)).toList final def constrParamAccessors: List[Symbol] = - info.decls.toList filter (sym => !sym.isMethod && sym.isParamAccessor) + info.decls.filter(sym => !sym.isMethod && sym.isParamAccessor).toList /** The symbol accessed by this accessor (getter or setter) function. */ final def accessed: Symbol = accessed(owner.info) diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index d160695e67..f953e9b757 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -194,7 +194,7 @@ abstract class TreeGen extends macros.TreeBuilder { mkTypeApply(mkAttributedSelect(target, method), targs map TypeTree) private def mkSingleTypeApply(value: Tree, tpe: Type, what: Symbol, wrapInApply: Boolean) = { - val tapp = mkAttributedTypeApply(value, what, List(tpe.normalize)) + val tapp = mkAttributedTypeApply(value, what, tpe.normalize :: Nil) if (wrapInApply) Apply(tapp, Nil) else tapp } private def typeTestSymbol(any: Boolean) = if (any) Any_isInstanceOf else Object_isInstanceOf diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index fa4a35cfe9..d67ec0931c 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -17,7 +17,7 @@ abstract class TreeInfo { val global: SymbolTable import global._ - import definitions.{ isVarArgsList, isCastSymbol, ThrowableClass, TupleClass } + import definitions.{ isVarArgsList, isCastSymbol, ThrowableClass, TupleClass, MacroContextClass, MacroContextPrefixType } /* Does not seem to be used. Not sure what it does anyway. def isOwnerDefinition(tree: Tree): Boolean = tree match { @@ -525,20 +525,18 @@ abstract class TreeInfo { */ def noPredefImportForUnit(body: Tree) = { // Top-level definition whose leading imports include Predef. - def containsLeadingPredefImport(defs: List[Tree]): Boolean = defs match { - case PackageDef(_, defs1) :: _ => containsLeadingPredefImport(defs1) - case Import(expr, _) :: rest => isReferenceToPredef(expr) || containsLeadingPredefImport(rest) - case _ => false + def isLeadingPredefImport(defn: Tree): Boolean = defn match { + case PackageDef(_, defs1) => defs1 exists isLeadingPredefImport + case Import(expr, _) => isReferenceToPredef(expr) + case _ => false } - // Compilation unit is class or object 'name' in package 'scala' def isUnitInScala(tree: Tree, name: Name) = tree match { case PackageDef(Ident(nme.scala_), defs) => firstDefinesClassOrObject(defs, name) case _ => false } - ( isUnitInScala(body, nme.Predef) - || containsLeadingPredefImport(List(body))) + isUnitInScala(body, nme.Predef) || isLeadingPredefImport(body) } def isAbsTypeDef(tree: Tree) = tree match { @@ -595,4 +593,23 @@ abstract class TreeInfo { object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic) object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName) object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed) + + object MacroImplReference { + private def refPart(tree: Tree): Tree = tree match { + case TypeApply(fun, _) => refPart(fun) + case ref: RefTree => ref + case _ => EmptyTree + } + + def unapply(tree: Tree) = refPart(tree) match { + case ref: RefTree => Some((ref.qualifier.symbol, ref.symbol, typeArguments(tree))) + case _ => None + } + } + + def stripOffPrefixTypeRefinement(tpe: Type): Type = + tpe.dealias match { + case RefinedType(List(tpe), Scope(sym)) if tpe == MacroContextClass.tpe && sym.allOverriddenSymbols.contains(MacroContextPrefixType) => tpe + case _ => tpe + } } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 94d51b7455..b21a28eea8 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -230,6 +230,7 @@ trait Trees extends api.Trees { self: SymbolTable => } case object EmptyTree extends TermTree { + val asList = List(this) super.tpe_=(NoType) override def tpe_=(t: Type) = if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") @@ -290,7 +291,10 @@ trait Trees extends api.Trees { self: SymbolTable => object LabelDef extends LabelDefExtractor case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) extends ImportSelectorApi - object ImportSelector extends ImportSelectorExtractor + object ImportSelector extends ImportSelectorExtractor { + val wild = ImportSelector(nme.WILDCARD, -1, null, -1) + val wildList = List(wild) + } case class Import(expr: Tree, selectors: List[ImportSelector]) extends SymTree with ImportApi @@ -979,12 +983,7 @@ trait Trees extends api.Trees { self: SymbolTable => */ def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match { case Nil => ApplyConstructor(tpt, Nil) - case xs :: rest => { - def mkApply(fun: Tree, args: List[Tree]) = Apply(fun, args) - rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(mkApply) - // [Eugene++] no longer compiles after I moved the `Apply` case class here - // rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(Apply) - } + case xs :: rest => rest.foldLeft(ApplyConstructor(tpt, xs): Tree)(Apply.apply) } /** 0-1 argument list new, based on a type. diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 969cbf2456..6e7c06d0da 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -265,14 +265,14 @@ trait Types extends api.Types { self: SymbolTable => def declarations = decls def typeArguments = typeArgs def erasure = this match { - case ConstantType(value) => widen.erasure // [Eugene to Martin] constant types are unaffected by erasure. weird. + case ConstantType(value) => widen.erasure case _ => var result: Type = transformedType(this) result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result case _ => result } - // [Eugene] erasure screws up all ThisTypes for modules into PackageTypeRefs + // erasure screws up all ThisTypes for modules into PackageTypeRefs // we need to unscrew them, or certain typechecks will fail mysteriously // http://groups.google.com/group/scala-internals/browse_thread/thread/6d3277ae21b6d581 result = result.map(tpe => tpe match { @@ -284,7 +284,6 @@ trait Types extends api.Types { self: SymbolTable => def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type = substSym(from, to) def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to) - // [Eugene] to be discussed and refactored def isConcrete = { def notConcreteSym(sym: Symbol) = sym.isAbstractType && !sym.isExistential @@ -304,11 +303,8 @@ trait Types extends api.Types { self: SymbolTable => !notConcreteTpe(this) } - // [Eugene] is this comprehensive? - // the only thingies that we want to splice are: 1) type parameters, 2) type members + // the only thingies that we want to splice are: 1) type parameters, 2) abstract type members // the thingies that we don't want to splice are: 1) concrete types (obviously), 2) existential skolems - // this check seems to cover them all, right? - // todo. after we discuss this, move the check to subclasses def isSpliceable = { this.isInstanceOf[TypeRef] && typeSymbol.isAbstractType && !typeSymbol.isExistential } @@ -446,7 +442,7 @@ trait Types extends api.Types { self: SymbolTable => if (phase.erasedTypes) this else { val cowner = commonOwner(this) - refinedType(List(this), cowner, EmptyScope, cowner.pos).narrow + refinedType(this :: Nil, cowner, EmptyScope, cowner.pos).narrow } /** For a TypeBounds type, itself; @@ -1011,7 +1007,7 @@ trait Types extends api.Types { self: SymbolTable => if (!e.sym.hasFlag(excludedFlags)) { if (sym == NoSymbol) sym = e.sym else { - if (alts.isEmpty) alts = List(sym) + if (alts.isEmpty) alts = sym :: Nil alts = e.sym :: alts } } @@ -3719,10 +3715,11 @@ trait Types extends api.Types { self: SymbolTable => case TypeRef(_, SingletonClass, _) => AnyClass.tpe case tp1 @ RefinedType(parents, decls) => - var parents1 = parents filter (_.typeSymbol != SingletonClass) - if (parents1.isEmpty) parents1 = List(AnyClass.tpe) - if (parents1.tail.isEmpty && decls.isEmpty) mapOver(parents1.head) - else mapOver(copyRefinedType(tp1, parents1, decls)) + parents filter (_.typeSymbol != SingletonClass) match { + case Nil => AnyClass.tpe + case p :: Nil if decls.isEmpty => mapOver(p) + case ps => mapOver(copyRefinedType(tp1, ps, decls)) + } case tp1 => mapOver(tp1) } @@ -4587,10 +4584,12 @@ trait Types extends api.Types { self: SymbolTable => tp match { case TypeRef(pre, sym, args) if pre ne NoPrefix => val newSym = subst(sym, from, to) + // 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)) - mapOver(copyTypeRef(tp, pre, newSym, args)) // mapOver takes care of subst'ing in args case SingleType(pre, sym) if pre ne NoPrefix => - mapOver(singleType(pre, subst(sym, from, to))) + val newSym = subst(sym, from, to) + mapOver( if (sym eq newSym) tp else singleType(pre, newSym) ) case _ => super.apply(tp) } @@ -5629,6 +5628,7 @@ 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) diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index 2ac0e64edd..14b5d3003d 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -69,7 +69,7 @@ trait Collections { } lb.toList } - + final def flatCollect[A, B](elems: List[A])(pf: PartialFunction[A, Traversable[B]]): List[B] = { val lb = new ListBuffer[B] for (x <- elems ; if pf isDefinedAt x) @@ -104,7 +104,7 @@ trait Collections { index += 1 } } - + // @inline final def findOrElse[A](xs: TraversableOnce[A])(p: A => Boolean)(orElse: => A): A = { xs find p getOrElse orElse diff --git a/src/reflect/scala/reflect/macros/Infrastructure.scala b/src/reflect/scala/reflect/macros/Infrastructure.scala index 5ae2c08265..a8a8b814b1 100644 --- a/src/reflect/scala/reflect/macros/Infrastructure.scala +++ b/src/reflect/scala/reflect/macros/Infrastructure.scala @@ -46,10 +46,6 @@ trait Infrastructure { * val valueOfX = toolBox.runExpr(imported).asInstanceOf[T] * ... * } - * - * // [Eugene++] using this guy will tremendously slow down the compilation - * // https://twitter.com/xeno_by/status/201248317831774208 - * // todo. we need to address this somehow */ def libraryClassLoader: ClassLoader diff --git a/src/reflect/scala/reflect/macros/Settings.scala b/src/reflect/scala/reflect/macros/Settings.scala index 8d166056c3..a2cdb4c8e1 100644 --- a/src/reflect/scala/reflect/macros/Settings.scala +++ b/src/reflect/scala/reflect/macros/Settings.scala @@ -12,14 +12,10 @@ trait Settings { /** Exposes current compiler settings as a list of options. * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options. */ - // [Eugene] ugly? yes, but I don't really fancy copy/pasting all our settings here and keep it synchronized at all times - // why all settings? because macros need to be in full control of the stuff going on - // maybe later we can implement a gettable/settable list of important settings, but for now let's leave it like that def compilerSettings: List[String] /** Updates current compiler settings with an option string. * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options. - * todo. http://groups.google.com/group/scala-internals/browse_thread/thread/07c18cff41f59203 */ def setCompilerSettings(options: String): this.type @@ -28,12 +24,12 @@ trait Settings { */ def setCompilerSettings(options: List[String]): this.type - /** Temporary sets compiler settings to a given option string and executes a given closure. + /** Temporarily sets compiler settings to a given option string and executes a given closure. * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options. */ def withCompilerSettings[T](options: String)(op: => T): T - /** Temporary sets compiler settings to a given list of options and executes a given closure. + /** Temporarily sets compiler settings to a given list of options and executes a given closure. * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options. */ def withCompilerSettings[T](options: List[String])(op: => T): T diff --git a/src/reflect/scala/reflect/macros/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala index 06f5caf68b..ca29194859 100644 --- a/src/reflect/scala/reflect/macros/TreeBuilder.scala +++ b/src/reflect/scala/reflect/macros/TreeBuilder.scala @@ -1,10 +1,6 @@ package scala.reflect package macros -// [Eugene] I added some stuff that was necessary for typetag materialization macros -// but we should think it over and pick other generally useful stuff -// same goes for tree traversers/transformers, type maps, etc -// and once we expose all that, there's another question: how do we stay in sync? abstract class TreeBuilder { val global: Universe diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 4ce2cda04a..967ac69148 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -88,7 +88,6 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym // ----------- Caching ------------------------------------------------------------------ - // [Eugene++ to Martin] not weak? why? private val classCache = new TwoWayCache[jClass[_], ClassSymbol] private val packageCache = new TwoWayCache[Package, ModuleSymbol] private val methodCache = new TwoWayCache[jMethod, MethodSymbol] @@ -659,43 +658,33 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym private def followStatic(clazz: Symbol, mods: Int) = if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz - implicit class RichClass(jclazz: jClass[_]) { - // [Eugene++] `jclazz.isLocalClass` doesn't work because of problems with `getSimpleName` - // java.lang.Error: sOwner(class Test$A$1) has failed - // Caused by: java.lang.InternalError: Malformed class name - // at java.lang.Class.getSimpleName(Class.java:1133) - // at java.lang.Class.isAnonymousClass(Class.java:1188) - // at java.lang.Class.isLocalClass(Class.java:1199) - // (see t5256c.scala for more details) + /** Methods which need to be treated with care + * because they either are getSimpleName or call getSimpleName: + * + * public String getSimpleName() + * public boolean isAnonymousClass() + * public boolean isLocalClass() + * public String getCanonicalName() + * + * A typical manifestation: + * + * // java.lang.Error: sOwner(class Test$A$1) has failed + * // Caused by: java.lang.InternalError: Malformed class name + * // at java.lang.Class.getSimpleName(Class.java:1133) + * // at java.lang.Class.isAnonymousClass(Class.java:1188) + * // at java.lang.Class.isLocalClass(Class.java:1199) + * // (see t5256c.scala for more details) + * + * TODO - find all such calls and wrap them. + * TODO - create mechanism to avoid the recurrence of unwrapped calls. + */ + implicit class RichClass(jclazz: jClass[_]) { + // `jclazz.isLocalClass` doesn't work because of problems with `getSimpleName` // hence we have to approximate by removing the `isAnonymousClass` check // def isLocalClass0: Boolean = jclazz.isLocalClass def isLocalClass0: Boolean = jclazz.getEnclosingMethod != null || jclazz.getEnclosingConstructor != null } - // [Eugene++] overflow from Paul's changes made concurrently with reflection refactoring - // https://github.com/scala/scala/commit/90d2bee45b25844f809f8c5300aefcb1bfe9e336 - // - // /** Methods which need to be wrapped because they either are getSimpleName - // * or call getSimpleName: - // * - // * public String getSimpleName() - // * public boolean isAnonymousClass() - // * public boolean isLocalClass() - // * public boolean isMemberClass() - // * public String getCanonicalName() - // * - // * TODO - find all such calls and wrap them. - // * TODO - create mechanism to avoid the recurrence of unwrapped calls. - // */ - // private def wrapClassCheck[T](alt: T)(body: => T): T = - // try body catch { case x: InternalError if x.getMessage == "Malformed class name" => alt } - - // private def wrapIsLocalClass(clazz: jClass[_]): Boolean = - // wrapClassCheck(false)(clazz.isLocalClass) - - // private def wrapGetSimpleName(clazz: jClass[_]): String = - // wrapClassCheck("")(clazz.getSimpleName) - /** * The Scala owner of the Scala class corresponding to the Java class `jclazz` */ @@ -1208,7 +1197,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym override def missingHook(owner: Symbol, name: Name): Symbol = { if (owner.hasPackageFlag) { val mirror = mirrorThatLoaded(owner) - // [Eugene++] this makes toolbox tests pass, but it's a mere workaround for SI-5865 + // todo. this makes toolbox tests pass, but it's a mere workaround for SI-5865 // assert((owner.info decl name) == NoSymbol, s"already exists: $owner . $name") if (owner.isRootSymbol && mirror.tryJavaClass(name.toString).isDefined) return mirror.EmptyPackageClass.info decl name diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 95c1bc861b..6bfafe6af1 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -61,10 +61,8 @@ trait SymbolLoaders { self: SymbolTable => assert(!(name.toString endsWith "[]"), name) val clazz = owner.newClass(name) val module = owner.newModule(name.toTermName) - // [Eugene++] am I doing this right? - // todo: drop condition, see what goes wrong - // [Eugene++ to Martin] test/files/run/t5256g and test/files/run/t5256h will crash - // reflection meeting verdict: need to enter the symbols into the first symbol in the owner chain that has a non-empty scope + // without this check test/files/run/t5256g and test/files/run/t5256h will crash + // todo. reflection meeting verdict: need to enter the symbols into the first symbol in the owner chain that has a non-empty scope if (owner.info.decls != EmptyScope) { owner.info.decls enter clazz owner.info.decls enter module diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala index 907c0dd369..1a17dd12d2 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala @@ -1,6 +1,7 @@ package scala.reflect package runtime +// SI-6240: test thread-safety, make trees synchronized as well trait SynchronizedOps extends internal.SymbolTable with SynchronizedSymbols with SynchronizedTypes { self: SymbolTable => diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala index c65357b652..12db7a7bf9 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala @@ -134,8 +134,6 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable => trait SynchronizedModuleClassSymbol extends ModuleClassSymbol with SynchronizedClassSymbol { override def sourceModule = synchronized { super.sourceModule } - // [Eugene++ to Martin] doesn't override anything. no longer necessary? - // def sourceModule_=(module: ModuleSymbol) = synchronized { super.sourceModule_=(module) } override def implicitMembers: Scope = synchronized { super.implicitMembers } } } diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala index d00094c0c1..ccdea3e82d 100644 --- a/src/reflect/scala/reflect/runtime/package.scala +++ b/src/reflect/scala/reflect/runtime/package.scala @@ -5,8 +5,6 @@ package object runtime { // type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection lazy val universe: api.JavaUniverse = new runtime.JavaUniverse - // [Eugene++ to Martin] removed `mirrorOfLoader`, because one can use `universe.runtimeMirror` instead - // implementation magically hardwired to the `currentMirror` method below def currentMirror: universe.Mirror = ??? // macro } diff --git a/src/reflect/scala/tools/nsc/io/Path.scala b/src/reflect/scala/tools/nsc/io/Path.scala index bfad4b93c5..e965c70111 100644 --- a/src/reflect/scala/tools/nsc/io/Path.scala +++ b/src/reflect/scala/tools/nsc/io/Path.scala @@ -43,8 +43,6 @@ object Path { if (i < 0) "" else name.substring(i + 1).toLowerCase } - // [Eugene++] I hope that noone relied on this method -// def isJarOrZip(f: Path, examineFile: Boolean = true) = Jar.isJarOrZip(f, examineFile) // not certain these won't be problematic, but looks good so far implicit def string2path(s: String): Path = apply(s) diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index a8a9c65f63..49c272cc28 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -10,10 +10,10 @@ package scala.tools.scalap import java.io.{ PrintStream, OutputStreamWriter, ByteArrayOutputStream } import scala.reflect.NameTransformer import scalax.rules.scalasig._ -import tools.nsc.util.{ ClassPath, JavaClassPath } -import tools.util.PathResolver +import scala.tools.nsc.util.{ ClassPath, JavaClassPath } +import scala.tools.util.PathResolver import ClassPath.DefaultJavaContext -import tools.nsc.io.{ PlainFile, AbstractFile } +import scala.tools.nsc.io.{ PlainFile, AbstractFile } /**The main object used to execute scalap on the command-line. * diff --git a/test/files/neg/macro-invalidshape-a.check b/test/files/neg/macro-invalidshape-a.check index 246b5c3226..098ec35a00 100644 --- a/test/files/neg/macro-invalidshape-a.check +++ b/test/files/neg/macro-invalidshape-a.check @@ -1,6 +1,5 @@ Macros_Test_2.scala:2: error: macro body has wrong shape:
- required: macro <reference to implementation object>.<implementation method name>
- or : macro <implementation method name>
+ required: macro [<implementation object>].<method name>[[<type args>]]
def foo(x: Any) = macro 2
^
one error found
diff --git a/test/files/neg/macro-invalidshape-b.check b/test/files/neg/macro-invalidshape-b.check index 59701d023b..297ff69199 100644 --- a/test/files/neg/macro-invalidshape-b.check +++ b/test/files/neg/macro-invalidshape-b.check @@ -1,6 +1,5 @@ Macros_Test_2.scala:2: error: macro body has wrong shape:
- required: macro <reference to implementation object>.<implementation method name>
- or : macro <implementation method name>
+ required: macro [<implementation object>].<method name>[[<type args>]]
def foo(x: Any) = macro Impls.foo(null)(null)
^
one error found
diff --git a/test/files/neg/macro-invalidshape-c.check b/test/files/neg/macro-invalidshape-c.check index 84d8c35222..6513df166e 100644 --- a/test/files/neg/macro-invalidshape-c.check +++ b/test/files/neg/macro-invalidshape-c.check @@ -1,6 +1,9 @@ -Macros_Test_2.scala:2: error: macro body has wrong shape:
- required: macro <reference to implementation object>.<implementation method name>
- or : macro <implementation method name>
+Macros_Test_2.scala:2: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
def foo(x: Any) = macro {2; Impls.foo}
- ^
+ ^
+Macros_Test_2.scala:2: error: missing arguments for method foo in object Impls;
+follow this method with `_' if you want to treat it as a partially applied function
+ def foo(x: Any) = macro {2; Impls.foo}
+ ^
+one warning found
one error found
diff --git a/test/files/neg/macro-invalidsig-context-bounds.check b/test/files/neg/macro-invalidsig-context-bounds.check index 6c9482e537..5d42ebc515 100644 --- a/test/files/neg/macro-invalidsig-context-bounds.check +++ b/test/files/neg/macro-invalidsig-context-bounds.check @@ -1,4 +1,7 @@ -Impls_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences - def foo[U: c.AbsTypeTag: Numeric](c: Ctx) = { - ^ -one error found +Macros_Test_1.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.macros.Context): c.Expr[Any]
+ found : (c: scala.reflect.macros.Context)(implicit evidence$2: Numeric[U]): c.universe.Literal
+macro implementations cannot have implicit parameters other than AbsTypeTag evidences
+ def foo[U] = macro Impls.foo[U]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-implicit-params.check b/test/files/neg/macro-invalidsig-implicit-params.check index 98b3167b7a..62156770e4 100644 --- a/test/files/neg/macro-invalidsig-implicit-params.check +++ b/test/files/neg/macro-invalidsig-implicit-params.check @@ -1,4 +1,7 @@ -Impls_Macros_1.scala:5: error: macro implementations cannot have implicit parameters other than AbsTypeTag evidences - def foo_targs[T, U: c.AbsTypeTag](c: Ctx)(implicit x: c.Expr[Int]) = { - ^ -one error found +Impls_Macros_1.scala:18: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Unit]
+ found : (c: scala.reflect.macros.Context)(implicit x: c.Expr[Int]): c.Expr[Unit]
+macro implementations cannot have implicit parameters other than AbsTypeTag evidences
+ def foo_targs[U](x: Int) = macro Impls.foo_targs[T, U]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-badtype.check b/test/files/neg/macro-invalidsig-tparams-badtype.check index e5e8366ba4..20c58ff2bb 100644 --- a/test/files/neg/macro-invalidsig-tparams-badtype.check +++ b/test/files/neg/macro-invalidsig-tparams-badtype.check @@ -3,5 +3,5 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: found : (c: scala.reflect.macros.Context)(U: c.universe.Type): Nothing
number of parameter sections differ
def foo[U] = macro Impls.foo[U]
- ^
+ ^
one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-a.check b/test/files/neg/macro-invalidsig-tparams-notparams-a.check index 5b4ef42ea5..5aee62b9e5 100644 --- a/test/files/neg/macro-invalidsig-tparams-notparams-a.check +++ b/test/files/neg/macro-invalidsig-tparams-notparams-a.check @@ -1,4 +1,4 @@ -Macros_Test_2.scala:2: error: macro implementation reference needs type arguments
+Macros_Test_2.scala:2: error: wrong number of type parameters for method foo: [U](c: scala.reflect.macros.Context)(implicit evidence$1: c.AbsTypeTag[U])Nothing
def foo = macro Impls.foo
^
one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-b.check b/test/files/neg/macro-invalidsig-tparams-notparams-b.check index 261e3b8293..e8de8a4c6b 100644 --- a/test/files/neg/macro-invalidsig-tparams-notparams-b.check +++ b/test/files/neg/macro-invalidsig-tparams-notparams-b.check @@ -1,4 +1,4 @@ -Macros_Test_2.scala:3: error: macro implementation reference needs type arguments
+Macros_Test_2.scala:3: error: wrong number of type parameters for method foo: [T, U, V](c: scala.reflect.macros.Context)(implicit evidence$1: c.AbsTypeTag[T], implicit evidence$2: c.AbsTypeTag[U], implicit V: c.AbsTypeTag[V])c.Expr[Unit]
def foo[V] = macro Impls.foo
^
one error found
diff --git a/test/files/neg/static-annot.scala b/test/files/neg/static-annot.scala index c6c626d42b..c0b5ed30d8 100644 --- a/test/files/neg/static-annot.scala +++ b/test/files/neg/static-annot.scala @@ -45,3 +45,9 @@ class PrivateProtectedLazy { println(PrivateProtectedLazy.baz) println(PrivateProtectedLazy.bam) } + + +class StaticDef { + // this should not crash the compiler + @static def x = 42 +} diff --git a/test/files/pos/t6208.scala b/test/files/pos/t6208.scala new file mode 100644 index 0000000000..dac571346d --- /dev/null +++ b/test/files/pos/t6208.scala @@ -0,0 +1,4 @@ +object Test { + val col = collection.mutable.Queue(1,2,3) + val WORK: collection.mutable.Queue[Int] = col filterNot (_ % 2 == 0) +} diff --git a/test/files/run/dead-code-elimination.check b/test/files/run/dead-code-elimination.check new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/files/run/dead-code-elimination.check diff --git a/test/files/run/dead-code-elimination.flags b/test/files/run/dead-code-elimination.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/run/dead-code-elimination.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/run/dead-code-elimination.scala b/test/files/run/dead-code-elimination.scala new file mode 100644 index 0000000000..1af17c936b --- /dev/null +++ b/test/files/run/dead-code-elimination.scala @@ -0,0 +1,33 @@ + +// This testcase is a snippet that did not compile correctly under +// pre-release 2.10.x. The relevant discussion around it can be +// found at: +// https://groups.google.com/forum/?fromgroups#!topic/scala-internals/qcyTjk8euUI[1-25] +// +// The reason it did not compile is related to the fact that ICode +// ops did not correctly define the stack entries they consumed and +// the dead code elimination phase was unable to correctly reconstruct +// the stack after code elimination. +// +// Originally, this did not compile, but I included it in the run +// tests because this was ASM-dependand and did not happen for GenJVM. +// +// Thus, we run the code and force the loading of class B -- if the +// bytecode is incorrect, it will fail the test. + +final class A { + def f1 = true + def f2 = true + @inline def f3 = f1 || f2 + class B { + def f() = 1 to 10 foreach (_ => f3) + } + def f = (new B).f() +} + +object Test { + def main(args: Array[String]): Unit = { + // force the loading of B + (new A).f + } +} diff --git a/test/files/run/macro-def-path-dependent-d.check b/test/files/run/macro-def-path-dependent-d1.check index 1ea14b4e20..1ea14b4e20 100644 --- a/test/files/run/macro-def-path-dependent-d.check +++ b/test/files/run/macro-def-path-dependent-d1.check diff --git a/test/files/run/macro-def-path-dependent-d.flags b/test/files/run/macro-def-path-dependent-d1.flags index cd66464f2f..cd66464f2f 100644 --- a/test/files/run/macro-def-path-dependent-d.flags +++ b/test/files/run/macro-def-path-dependent-d1.flags diff --git a/test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala b/test/files/run/macro-def-path-dependent-d1/Impls_Macros_1.scala index 2daf6fc3fb..2daf6fc3fb 100644 --- a/test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala +++ b/test/files/run/macro-def-path-dependent-d1/Impls_Macros_1.scala diff --git a/test/files/run/macro-def-path-dependent-d/Test_2.scala b/test/files/run/macro-def-path-dependent-d1/Test_2.scala index 7dffc5107d..7dffc5107d 100644 --- a/test/files/run/macro-def-path-dependent-d/Test_2.scala +++ b/test/files/run/macro-def-path-dependent-d1/Test_2.scala diff --git a/test/files/run/macro-def-path-dependent-d2.check b/test/files/run/macro-def-path-dependent-d2.check new file mode 100644 index 0000000000..1ea14b4e20 --- /dev/null +++ b/test/files/run/macro-def-path-dependent-d2.check @@ -0,0 +1 @@ +it works
diff --git a/test/files/run/macro-def-path-dependent-d2.flags b/test/files/run/macro-def-path-dependent-d2.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-def-path-dependent-d2.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-def-path-dependent-d2/Impls_1.scala b/test/files/run/macro-def-path-dependent-d2/Impls_1.scala new file mode 100644 index 0000000000..1cda64e43e --- /dev/null +++ b/test/files/run/macro-def-path-dependent-d2/Impls_1.scala @@ -0,0 +1,7 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.macros.Context +import scala.reflect.api.Universe + +object Impls { + def materializeTypeTag_impl[T: c.AbsTypeTag](c: Context)(u: c.Expr[Universe])(e: c.Expr[T]): c.Expr[u.value.TypeTag[T]] = ??? +}
\ No newline at end of file diff --git a/test/files/run/macro-def-path-dependent-d2/Macros_2.scala b/test/files/run/macro-def-path-dependent-d2/Macros_2.scala new file mode 100644 index 0000000000..65ce4d8bd2 --- /dev/null +++ b/test/files/run/macro-def-path-dependent-d2/Macros_2.scala @@ -0,0 +1,7 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.macros.Context +import scala.reflect.api.Universe + +object Macros { + def materializeTypeTag[T](u: Universe)(e: T) = macro Impls.materializeTypeTag_impl[T] +}
\ No newline at end of file diff --git a/test/files/run/macro-def-path-dependent-d2/Test_3.scala b/test/files/run/macro-def-path-dependent-d2/Test_3.scala new file mode 100644 index 0000000000..7dffc5107d --- /dev/null +++ b/test/files/run/macro-def-path-dependent-d2/Test_3.scala @@ -0,0 +1,3 @@ +object Test extends App { + println("it works") +}
\ No newline at end of file diff --git a/test/files/run/reify_ann1a.scala b/test/files/run/reify_ann1a.scala index 9f994fb2eb..754baef6b7 100644 --- a/test/files/run/reify_ann1a.scala +++ b/test/files/run/reify_ann1a.scala @@ -21,6 +21,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala index 3e0d3e0802..eb00b4cb10 100644 --- a/test/files/run/reify_ann1b.scala +++ b/test/files/run/reify_ann1b.scala @@ -21,6 +21,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/reify_ann2a.scala b/test/files/run/reify_ann2a.scala index 63a17ee192..9f901d86bd 100644 --- a/test/files/run/reify_ann2a.scala +++ b/test/files/run/reify_ann2a.scala @@ -21,6 +21,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/reify_ann3.scala b/test/files/run/reify_ann3.scala index dbb6a1b443..cbf1e10063 100644 --- a/test/files/run/reify_ann3.scala +++ b/test/files/run/reify_ann3.scala @@ -15,6 +15,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/reify_ann4.scala b/test/files/run/reify_ann4.scala index b4845d1586..58c8c2c521 100644 --- a/test/files/run/reify_ann4.scala +++ b/test/files/run/reify_ann4.scala @@ -19,6 +19,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/reify_ann5.scala b/test/files/run/reify_ann5.scala index 0ae8d317ce..801db07960 100644 --- a/test/files/run/reify_ann5.scala +++ b/test/files/run/reify_ann5.scala @@ -16,6 +16,7 @@ object Test extends App { // test 2: import and typecheck val toolbox = cm.mkToolBox() val ttree = toolbox.typeCheck(tree) + ttree.foreach(sub => if (sub.hasSymbol) sub.symbol.typeSignature) println(ttree.toString) // test 3: import and compile diff --git a/test/files/run/static-annot-repl.check b/test/files/run/static-annot-repl.check new file mode 100644 index 0000000000..d1029a9809 --- /dev/null +++ b/test/files/run/static-annot-repl.check @@ -0,0 +1,32 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> import annotation.static +import annotation.static + +scala> @static var x1 = 42 +x1: Int = 42 + +scala> @static val x2 = 43 +x2: Int = 43 + +scala> @static def x3 = 44 +x3: Int + +scala> x1 +res0: Int = 42 + +scala> x2 +res1: Int = 43 + +scala> x3 +res2: Int = 44 + +scala> class Test { + @static def x = 42 +} +defined class Test + +scala>
\ No newline at end of file diff --git a/test/files/run/static-annot-repl.scala b/test/files/run/static-annot-repl.scala new file mode 100644 index 0000000000..1d2e9b2d7e --- /dev/null +++ b/test/files/run/static-annot-repl.scala @@ -0,0 +1,22 @@ + + + +import scala.tools.partest.ReplTest + + + +object Test extends ReplTest { + def code = """ +import annotation.static +@static var x1 = 42 +@static val x2 = 43 +@static def x3 = 44 +x1 +x2 +x3 +class Test { + @static def x = 42 +} +""" + +} diff --git a/test/files/run/static-annot/field.scala b/test/files/run/static-annot/field.scala index a7d8158321..8408a51800 100644 --- a/test/files/run/static-annot/field.scala +++ b/test/files/run/static-annot/field.scala @@ -23,8 +23,10 @@ class Foo trait Check { def checkStatic(cls: Class[_]) { cls.getDeclaredFields.find(_.getName == "bar") match { - case Some(f) => assert(Modifier.isStatic(f.getModifiers), "no static modifier") - case None => assert(false, "no static field bar in class") + case Some(f) => + assert(Modifier.isStatic(f.getModifiers), "no static modifier") + case None => + assert(false, "no static field bar in class") } } @@ -170,6 +172,10 @@ object Foo7 { @static val bar = "string" } class AndHisFriend + + object AndHisLonelyFriend { + @static val bar = "another" + } } @@ -177,6 +183,9 @@ object Test7 extends Check { def test() { checkStatic(classOf[Foo7.AndHisFriend]) assert(Foo7.AndHisFriend.bar == "string") + + checkStatic(Class.forName("Foo7$AndHisLonelyFriend")) + assert(Foo7.AndHisLonelyFriend.bar == "another") } } diff --git a/test/files/run/t6236.check b/test/files/run/t6236.check new file mode 100644 index 0000000000..a0a2e88d0a --- /dev/null +++ b/test/files/run/t6236.check @@ -0,0 +1,2 @@ +353 +353
\ No newline at end of file diff --git a/test/files/run/t6236/file_1.scala b/test/files/run/t6236/file_1.scala new file mode 100644 index 0000000000..92d22799fc --- /dev/null +++ b/test/files/run/t6236/file_1.scala @@ -0,0 +1,9 @@ + + +package p { + object y { + object x { + @scala.annotation.static val foo: Int = 353 + } + } +} diff --git a/test/files/run/t6236/file_2.scala b/test/files/run/t6236/file_2.scala new file mode 100644 index 0000000000..51823004ca --- /dev/null +++ b/test/files/run/t6236/file_2.scala @@ -0,0 +1,10 @@ + + + +object Test { + def main(args: Array[String]): Unit = { + println(p.y.x.foo) + println(p.y.x.foo) + } +} + |