From ffc2389840852a120fecd772206d55db9a79f30e Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 5 Feb 2012 16:49:18 +0100 Subject: Replaced LiftCode with a function in MacroContext Major cleanup of reification: * LiftCode phase has been removed * Code has been deprecated and will be removed as we roll a new starr * Logic related to type-directed lifting has been purged scala.reflect.macro.Context#reify now provides the same services as LiftCode provided (except that it returns Tree, not Code). For testing purposes, I've retained the oh-so-convenient automagic lift. test/files/codelib/code.jar now hosts Code.lift reimplemented in a macro, so that the tests can continue working as if nothing has happened. --- test/pending/run/reify_closure2b.scala | 4 ++-- test/pending/run/reify_closure3b.scala | 4 ++-- test/pending/run/reify_closure4b.scala | 4 ++-- test/pending/run/reify_closure5b.scala | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'test/pending/run') diff --git a/test/pending/run/reify_closure2b.scala b/test/pending/run/reify_closure2b.scala index e9fb40bede..a1fead07ae 100644 --- a/test/pending/run/reify_closure2b.scala +++ b/test/pending/run/reify_closure2b.scala @@ -5,9 +5,9 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { def foo(y: Int): Int => Int = { class Foo(y: Int) { - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + y - } + }} } val reporter = new ConsoleReporter(new Settings) diff --git a/test/pending/run/reify_closure3b.scala b/test/pending/run/reify_closure3b.scala index 5c4f3c81b9..acf07c4749 100644 --- a/test/pending/run/reify_closure3b.scala +++ b/test/pending/run/reify_closure3b.scala @@ -7,9 +7,9 @@ object Test extends App { class Foo(y: Int) { def y1 = y - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + y1 - } + }} } val reporter = new ConsoleReporter(new Settings) diff --git a/test/pending/run/reify_closure4b.scala b/test/pending/run/reify_closure4b.scala index 24dfa9fe17..ed102298c5 100644 --- a/test/pending/run/reify_closure4b.scala +++ b/test/pending/run/reify_closure4b.scala @@ -7,9 +7,9 @@ object Test extends App { class Foo(y: Int) { val y1 = y - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + y1 - } + }} } val reporter = new ConsoleReporter(new Settings) diff --git a/test/pending/run/reify_closure5b.scala b/test/pending/run/reify_closure5b.scala index 02eb771f0c..29e911538f 100644 --- a/test/pending/run/reify_closure5b.scala +++ b/test/pending/run/reify_closure5b.scala @@ -5,9 +5,9 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { def foo[T](ys: List[T]): Int => Int = { class Foo[T](ys: List[T]) { - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + ys.length - } + }} } val reporter = new ConsoleReporter(new Settings) -- cgit v1.2.3 From f914350f8f5fecce7350a4c7e1a6c2fe447c7324 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 5 Feb 2012 14:26:42 +0100 Subject: Fixes https://issues.scala-lang.org/browse/SI-5272 --- src/compiler/scala/tools/nsc/ast/Reifiers.scala | 4 ++-- test/files/run/t5272_1.check | 1 + test/files/run/t5272_1.scala | 17 +++++++++++++++++ test/files/run/t5272_2.check | 1 + test/files/run/t5272_2.scala | 16 ++++++++++++++++ test/pending/run/t5272.check | 1 - test/pending/run/t5272.scala | 17 ----------------- 7 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 test/files/run/t5272_1.check create mode 100644 test/files/run/t5272_1.scala create mode 100644 test/files/run/t5272_2.check create mode 100644 test/files/run/t5272_2.scala delete mode 100644 test/pending/run/t5272.check delete mode 100644 test/pending/run/t5272.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index 952110ade2..ef87925959 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -281,9 +281,9 @@ trait Reifiers { self: Global => private def reifyTree(tree: Tree): Tree = tree match { case EmptyTree => reifyMirrorObject(EmptyTree) - case This(_) if !(boundSyms contains tree.symbol) => + case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => reifyFree(tree) - case Ident(_) if !(boundSyms contains tree.symbol) => + case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here. mirrorCall("Select", reifyFree(tree), reifyName(nme.elem)) diff --git a/test/files/run/t5272_1.check b/test/files/run/t5272_1.check new file mode 100644 index 0000000000..9f8d6f24e7 --- /dev/null +++ b/test/files/run/t5272_1.check @@ -0,0 +1 @@ +okay \ No newline at end of file diff --git a/test/files/run/t5272_1.scala b/test/files/run/t5272_1.scala new file mode 100644 index 0000000000..3f44d05fb3 --- /dev/null +++ b/test/files/run/t5272_1.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + 2 match { + case 2 => println("okay") + case _ => println("not okay") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5272_2.check b/test/files/run/t5272_2.check new file mode 100644 index 0000000000..549f3f3af8 --- /dev/null +++ b/test/files/run/t5272_2.check @@ -0,0 +1 @@ +okay2 \ No newline at end of file diff --git a/test/files/run/t5272_2.scala b/test/files/run/t5272_2.scala new file mode 100644 index 0000000000..833ee65285 --- /dev/null +++ b/test/files/run/t5272_2.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + 2 match { + case x => println("okay" + x) + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5272.check b/test/pending/run/t5272.check deleted file mode 100644 index dcf02b2fb6..0000000000 --- a/test/pending/run/t5272.check +++ /dev/null @@ -1 +0,0 @@ -okay diff --git a/test/pending/run/t5272.scala b/test/pending/run/t5272.scala deleted file mode 100644 index 3f44d05fb3..0000000000 --- a/test/pending/run/t5272.scala +++ /dev/null @@ -1,17 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - 2 match { - case 2 => println("okay") - case _ => println("not okay") - } - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} -- cgit v1.2.3 From 75696bc3d310a53594d97853f38bb0dbfef42390 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 5 Feb 2012 16:56:48 +0100 Subject: Fixes https://issues.scala-lang.org/browse/SI-5334 New version of reification isn't susceptible to this bug. The problem was with Code.lift generating not only a tree, but also a manifest with the type of that tree. That led to an issue in the case of the type of the manifest depending on a class declared inside the quasiquote. Now manifests in reification are gone, so is the problem. --- test/files/run/t5334_1.check | 2 ++ test/files/run/t5334_1.scala | 16 ++++++++++++++++ test/files/run/t5334_2.check | 2 ++ test/files/run/t5334_2.scala | 16 ++++++++++++++++ test/pending/run/t5334_1.scala | 15 --------------- test/pending/run/t5334_2.scala | 15 --------------- 6 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 test/files/run/t5334_1.check create mode 100644 test/files/run/t5334_1.scala create mode 100644 test/files/run/t5334_2.check create mode 100644 test/files/run/t5334_2.scala delete mode 100644 test/pending/run/t5334_1.scala delete mode 100644 test/pending/run/t5334_2.scala (limited to 'test/pending/run') diff --git a/test/files/run/t5334_1.check b/test/files/run/t5334_1.check new file mode 100644 index 0000000000..e09aedaede --- /dev/null +++ b/test/files/run/t5334_1.check @@ -0,0 +1,2 @@ +C +C \ No newline at end of file diff --git a/test/files/run/t5334_1.scala b/test/files/run/t5334_1.scala new file mode 100644 index 0000000000..7acf282bb8 --- /dev/null +++ b/test/files/run/t5334_1.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { override def toString = "C" } + new C + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + println(ttree.tpe) + println(toolbox.runExpr(ttree)) +} diff --git a/test/files/run/t5334_2.check b/test/files/run/t5334_2.check new file mode 100644 index 0000000000..2ae76754c0 --- /dev/null +++ b/test/files/run/t5334_2.check @@ -0,0 +1,2 @@ +List[(C, C)] +List((C,C)) \ No newline at end of file diff --git a/test/files/run/t5334_2.scala b/test/files/run/t5334_2.scala new file mode 100644 index 0000000000..26f0778400 --- /dev/null +++ b/test/files/run/t5334_2.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { override def toString() = "C" } + List((new C, new C)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + println(ttree.tpe) + println(toolbox.runExpr(ttree)) +} diff --git a/test/pending/run/t5334_1.scala b/test/pending/run/t5334_1.scala deleted file mode 100644 index c1eba89c2b..0000000000 --- a/test/pending/run/t5334_1.scala +++ /dev/null @@ -1,15 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - class C - new C - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5334_2.scala b/test/pending/run/t5334_2.scala deleted file mode 100644 index 361b8c85f2..0000000000 --- a/test/pending/run/t5334_2.scala +++ /dev/null @@ -1,15 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - class C - List((new C, new C)) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} -- cgit v1.2.3 From 6548dcf12d83e327df2f90048140fb95346b7e95 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 12 Feb 2012 23:07:30 +0100 Subject: reifyAnnotations Annotations are now supported by the reifier: * AnnotationInfos from symbols get transformed back into mods. * AnnotatedTypes are retained and are reified along with AnnotationInfos. Reification is no magic, and reification of annotations especially: * Annotations cannot refer to symbols defined inside the quasiquote. This restriction is due to the fact that we need to erase locally defined symbols before reifying to make subsequent reflective compilations succeed. However, while doing that, we also need to make sure that we don't make resulting ASTs non-compilable by removing essential information. This is tricky, and it more or less works for TypeTrees, but not for annotations that can contain arbitrary ASTs. For more details look into the comments to Reifiers.scala. * Classfile annotations that contain array arguments and are applied to types, i.e. the ones that generate AnnotatedTypes, cannot be reified. This is because of limitations of manifest infrastructure. Typechecking "Array(mirror.LiteralAnnotArg(...))" would require the compiler to produce a manifest for a path-dependent type, which cannot be done now. Review by @odersky. --- .../scala/reflect/internal/AnnotationInfos.scala | 17 +- .../scala/reflect/internal/Importers.scala | 196 +++-- .../scala/reflect/internal/TreePrinters.scala | 3 + src/compiler/scala/tools/nsc/ast/Reifiers.scala | 969 +++++++++++++-------- .../scala/tools/nsc/ast/ReifyPrinters.scala | 22 +- .../scala/tools/nsc/ast/TreePrinters.scala | 3 - src/compiler/scala/tools/nsc/ast/Trees.scala | 19 - .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + .../scala/tools/nsc/typechecker/Macros.scala | 47 +- .../scala/tools/nsc/typechecker/Typers.scala | 25 +- src/library/scala/reflect/api/Trees.scala | 20 + test/files/neg/reify_ann2a.check | 4 + test/files/neg/reify_ann2a.scala | 30 + test/files/neg/reify_ann2b.check | 7 + test/files/neg/reify_ann2b.scala | 30 + test/files/run/reify_ann1a.check | 30 + test/files/run/reify_ann1a.scala | 30 + test/files/run/reify_ann1b.check | 30 + test/files/run/reify_ann1b.scala | 30 + test/files/run/reify_classfileann_a.check | 18 + test/files/run/reify_classfileann_a.scala | 24 + test/files/run/t5224.check | 9 + test/files/run/t5224.scala | 9 + test/files/run/t5225_1.check | 4 + test/files/run/t5225_1.scala | 7 + test/files/run/t5225_2.check | 4 + test/files/run/t5225_2.scala | 7 + test/files/run/t5419.check | 1 + test/files/run/t5419.scala | 9 + test/pending/run/reify_classfileann_b.check | 0 test/pending/run/reify_classfileann_b.scala | 28 + test/pending/run/t5224.check | 9 - test/pending/run/t5224.scala | 8 - test/pending/run/t5225_1.check | 4 - test/pending/run/t5225_1.scala | 8 - test/pending/run/t5225_2.check | 4 - test/pending/run/t5225_2.scala | 8 - 37 files changed, 1136 insertions(+), 538 deletions(-) create mode 100644 test/files/neg/reify_ann2a.check create mode 100644 test/files/neg/reify_ann2a.scala create mode 100644 test/files/neg/reify_ann2b.check create mode 100644 test/files/neg/reify_ann2b.scala create mode 100644 test/files/run/reify_ann1a.check create mode 100644 test/files/run/reify_ann1a.scala create mode 100644 test/files/run/reify_ann1b.check create mode 100644 test/files/run/reify_ann1b.scala create mode 100644 test/files/run/reify_classfileann_a.check create mode 100644 test/files/run/reify_classfileann_a.scala create mode 100644 test/files/run/t5224.check create mode 100644 test/files/run/t5224.scala create mode 100644 test/files/run/t5225_1.check create mode 100644 test/files/run/t5225_1.scala create mode 100644 test/files/run/t5225_2.check create mode 100644 test/files/run/t5225_2.scala create mode 100644 test/files/run/t5419.check create mode 100644 test/files/run/t5419.scala create mode 100644 test/pending/run/reify_classfileann_b.check create mode 100644 test/pending/run/reify_classfileann_b.scala delete mode 100644 test/pending/run/t5224.check delete mode 100644 test/pending/run/t5224.scala delete mode 100644 test/pending/run/t5225_1.check delete mode 100644 test/pending/run/t5225_1.scala delete mode 100644 test/pending/run/t5225_2.check delete mode 100644 test/pending/run/t5225_2.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala index c3dde3e6d1..9a7c79d856 100644 --- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala +++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala @@ -116,6 +116,11 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => // Classfile annot: args empty. Scala annot: assocs empty. assert(args.isEmpty || assocs.isEmpty, atp) + // @xeno.by: necessary for reification, see Reifiers.scala for more info + private var orig: Tree = EmptyTree + def original = orig + def setOriginal(t: Tree): this.type = { orig = t; this } + override def toString = ( atp + (if (!args.isEmpty) args.mkString("(", ", ", ")") else "") + @@ -130,7 +135,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => private var forced = false private lazy val forcedInfo = try { - val result = lazyInfo + val result = lazyInfo if (result.pos == NoPosition) result setPos pos result } finally forced = true @@ -138,10 +143,12 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => def atp: Type = forcedInfo.atp def args: List[Tree] = forcedInfo.args def assocs: List[(Name, ClassfileAnnotArg)] = forcedInfo.assocs + def original: Tree = forcedInfo.original + def setOriginal(t: Tree): this.type = { forcedInfo.setOriginal(t); this } // We should always be able to print things without forcing them. override def toString = if (forced) forcedInfo.toString else "@" - + override def pos: Position = if (forced) forcedInfo.pos else NoPosition } @@ -166,10 +173,16 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable => def args: List[Tree] def assocs: List[(Name, ClassfileAnnotArg)] + // @xeno.by: necessary for reification, see Reifiers.scala for more info + def original: Tree + def setOriginal(t: Tree): this.type + /** Hand rolling Product. */ def _1 = atp def _2 = args def _3 = assocs + // @xeno.by: original hasn't become a product member for backward compatibility purposes + // def _4 = original def canEqual(other: Any) = other.isInstanceOf[AnnotationInfo] override def productPrefix = "AnnotationInfo" diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 6c843e6f15..63efaede07 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -9,10 +9,25 @@ trait Importers { self: SymbolTable => val from: SymbolTable lazy val symMap: WeakHashMap[from.Symbol, Symbol] = new WeakHashMap + lazy val tpeMap: WeakHashMap[from.Type, Type] = new WeakHashMap + + // fixups and maps prevent stackoverflows in importer + var pendingSyms = 0 + var pendingTpes = 0 + lazy val fixups = collection.mutable.MutableList[Function0[Unit]]() + def addFixup(fixup: => Unit): Unit = fixups += (() => fixup) + def tryFixup(): Unit = { + if (pendingSyms == 0 && pendingTpes == 0) { + val fixups = this.fixups.toList + this.fixups.clear() + fixups foreach { _() } + } + } object reverse extends from.Importer { val from: self.type = self for ((fromsym, mysym) <- Importer.this.symMap) symMap += ((mysym, fromsym)) + for ((fromtpe, mytpe) <- Importer.this.tpeMap) tpeMap += ((mytpe, fromtpe)) } def importPosition(pos: from.Position): Position = NoPosition @@ -78,7 +93,7 @@ trait Importers { self: SymbolTable => mysym resetFlag Flags.LOCKED } // end doImport - def importOrRelink: Symbol = + def importOrRelink: Symbol = { if (sym == null) null else if (sym == from.NoSymbol) @@ -129,69 +144,103 @@ trait Importers { self: SymbolTable => } else doImport(sym) } - symMap getOrElseUpdate (sym, importOrRelink) + } // end importOrRelink + + if (symMap contains sym) { + symMap(sym) + } else { + pendingSyms += 1 + + try { + symMap getOrElseUpdate (sym, importOrRelink) + } finally { + pendingSyms -= 1 + tryFixup() + } + } } - def importType(tpe: from.Type): Type = tpe match { - case from.TypeRef(pre, sym, args) => - TypeRef(importType(pre), importSymbol(sym), args map importType) - case from.ThisType(clazz) => - ThisType(importSymbol(clazz)) - case from.SingleType(pre, sym) => - SingleType(importType(pre), importSymbol(sym)) - case from.MethodType(params, restpe) => - MethodType(params map importSymbol, importType(restpe)) - case from.PolyType(tparams, restpe) => - PolyType(tparams map importSymbol, importType(restpe)) - case from.NullaryMethodType(restpe) => - NullaryMethodType(importType(restpe)) - case from.ConstantType(constant @ from.Constant(_)) => - ConstantType(importConstant(constant)) - case from.SuperType(thistpe, supertpe) => - SuperType(importType(thistpe), importType(supertpe)) - case from.TypeBounds(lo, hi) => - TypeBounds(importType(lo), importType(hi)) - case from.BoundedWildcardType(bounds) => - BoundedWildcardType(importTypeBounds(bounds)) - case from.ClassInfoType(parents, decls, clazz) => - val myclazz = importSymbol(clazz) - val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope - val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz) - myclazz setInfo polyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope - decls foreach importSymbol // will enter itself into myclazz - myclazzTpe - case from.RefinedType(parents, decls) => - RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol)) - case from.ExistentialType(tparams, restpe) => - newExistentialType(tparams map importSymbol, importType(restpe)) - case from.OverloadedType(pre, alts) => - OverloadedType(importType(pre), alts map importSymbol) - case from.AntiPolyType(pre, targs) => - AntiPolyType(importType(pre), targs map importType) - case x: from.TypeVar => - TypeVar(importType(x.origin), importTypeConstraint(x.constr0), x.typeArgs map importType, x.params map importSymbol) - case from.NotNullType(tpe) => - NotNullType(importType(tpe)) - case from.AnnotatedType(annots, tpe, selfsym) => - AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym)) - case from.ErrorType => - ErrorType - case from.WildcardType => - WildcardType - case from.NoType => - NoType - case from.NoPrefix => - NoPrefix - case null => - null + def importType(tpe: from.Type): Type = { + def doImport(tpe: from.Type): Type = tpe match { + case from.TypeRef(pre, sym, args) => + TypeRef(importType(pre), importSymbol(sym), args map importType) + case from.ThisType(clazz) => + ThisType(importSymbol(clazz)) + case from.SingleType(pre, sym) => + SingleType(importType(pre), importSymbol(sym)) + case from.MethodType(params, restpe) => + MethodType(params map importSymbol, importType(restpe)) + case from.PolyType(tparams, restpe) => + PolyType(tparams map importSymbol, importType(restpe)) + case from.NullaryMethodType(restpe) => + NullaryMethodType(importType(restpe)) + case from.ConstantType(constant @ from.Constant(_)) => + ConstantType(importConstant(constant)) + case from.SuperType(thistpe, supertpe) => + SuperType(importType(thistpe), importType(supertpe)) + case from.TypeBounds(lo, hi) => + TypeBounds(importType(lo), importType(hi)) + case from.BoundedWildcardType(bounds) => + BoundedWildcardType(importTypeBounds(bounds)) + case from.ClassInfoType(parents, decls, clazz) => + val myclazz = importSymbol(clazz) + val myscope = if (myclazz.isPackageClass) newPackageScope(myclazz) else newScope + val myclazzTpe = ClassInfoType(parents map importType, myscope, myclazz) + myclazz setInfo polyType(myclazz.typeParams, myclazzTpe) // needed so that newly created symbols find their scope + decls foreach importSymbol // will enter itself into myclazz + myclazzTpe + case from.RefinedType(parents, decls) => + RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol)) + case from.ExistentialType(tparams, restpe) => + newExistentialType(tparams map importSymbol, importType(restpe)) + case from.OverloadedType(pre, alts) => + OverloadedType(importType(pre), alts map importSymbol) + case from.AntiPolyType(pre, targs) => + AntiPolyType(importType(pre), targs map importType) + case x: from.TypeVar => + TypeVar(importType(x.origin), importTypeConstraint(x.constr0), x.typeArgs map importType, x.params map importSymbol) + case from.NotNullType(tpe) => + NotNullType(importType(tpe)) + case from.AnnotatedType(annots, tpe, selfsym) => + AnnotatedType(annots map importAnnotationInfo, importType(tpe), importSymbol(selfsym)) + case from.ErrorType => + ErrorType + case from.WildcardType => + WildcardType + case from.NoType => + NoType + case from.NoPrefix => + NoPrefix + case null => + null + } // end doImport + + def importOrRelink: Type = + doImport(tpe) + + if (tpeMap contains tpe) { + tpeMap(tpe) + } else { + pendingTpes += 1 + + try { + tpeMap getOrElseUpdate (tpe, importOrRelink) + } finally { + pendingTpes -= 1 + tryFixup() + } + } } def importTypeBounds(bounds: from.TypeBounds) = importType(bounds).asInstanceOf[TypeBounds] - def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = - AnnotationInfo(importType(ann.atp), ann.args map importTree, ann.assocs map { - case (name, arg) => (importName(name), importAnnotArg(arg)) - }) + def importAnnotationInfo(ann: from.AnnotationInfo): AnnotationInfo = { + val atp1 = importType(ann.atp) + val args1 = ann.args map importTree + val assocs1 = ann.assocs map { case (name, arg) => (importName(name), importAnnotArg(arg)) } + val original1 = importTree(ann.original) + AnnotationInfo(atp1, args1, assocs1) setOriginal original1 + } def importAnnotArg(arg: from.ClassfileAnnotArg): ClassfileAnnotArg = arg match { case from.LiteralAnnotArg(constant @ from.Constant(_)) => @@ -265,6 +314,8 @@ trait Importers { self: SymbolTable => new Function(vparams map importValDef, importTree(body)) case from.Assign(lhs, rhs) => new Assign(importTree(lhs), importTree(rhs)) + case from.AssignOrNamedArg(lhs, rhs) => + new AssignOrNamedArg(importTree(lhs), importTree(rhs)) case from.If(cond, thenp, elsep) => new If(importTree(cond), importTree(thenp), importTree(elsep)) case from.Match(selector, cases) => @@ -326,21 +377,24 @@ trait Importers { self: SymbolTable => case null => null } - if (mytree != null) { - val mysym = if (tree hasSymbol) importSymbol(tree.symbol) else NoSymbol - val mytpe = importType(tree.tpe) + addFixup({ + if (mytree != null) { + val mysym = if (tree hasSymbol) importSymbol(tree.symbol) else NoSymbol + val mytpe = importType(tree.tpe) - mytree match { - case mytt: TypeTree => - val tt = tree.asInstanceOf[from.TypeTree] - if (mytree hasSymbol) mytt.symbol = mysym - if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe) - if (tt.original != null) mytt.setOriginal(importTree(tt.original)) - case _ => - if (mytree hasSymbol) mytree.symbol = importSymbol(tree.symbol) - mytree.tpe = importType(tree.tpe) + mytree match { + case mytt: TypeTree => + val tt = tree.asInstanceOf[from.TypeTree] + if (mytree hasSymbol) mytt.symbol = mysym + if (tt.wasEmpty) mytt.defineType(mytpe) else mytt.setType(mytpe) + if (tt.original != null) mytt.setOriginal(importTree(tt.original)) + case _ => + if (mytree hasSymbol) mytree.symbol = importSymbol(tree.symbol) + mytree.tpe = importType(tree.tpe) + } } - } + }) + tryFixup() mytree } diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index e484faff2e..2b1d833c73 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -299,6 +299,9 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => case Assign(lhs, rhs) => print(lhs, " = ", rhs) + case AssignOrNamedArg(lhs, rhs) => + print(lhs, " = ", rhs) + case If(cond, thenp, elsep) => print("if (", cond, ")"); indent; println() print(thenp); undent diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index 105d2cb62b..b82d78b786 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -22,278 +22,413 @@ import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } trait Reifiers { self: Global => def reify(tree: Tree): Tree = { - if (tree.tpe != null) { - val saved = printTypings - try { - val reifyDebug = settings.Yreifydebug.value - val debugTrace = util.trace when reifyDebug - debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) - debugTrace("transformed = ") { - val reifier = new Reifier() - val untyped = reifier.reifyTopLevel(tree) - - val reifyCopypaste = settings.Yreifycopypaste.value - if (reifyCopypaste) { - if (reifyDebug) println("=======================") - println(reifiedNodeToString(untyped)) - if (reifyDebug) println("=======================") - } - - untyped - } - } finally { - printTypings = saved + class Reifier { + import definitions._ + import Reifier._ + + final val scalaPrefix = "scala." + final val localPrefix = "$local" + final val memoizerName = "$memo" + + val reifyDebug = settings.Yreifydebug.value + + private val reifiableSyms = mutable.ArrayBuffer[Symbol]() // the symbols that are reified with the tree + private val symIndex = mutable.HashMap[Symbol, Int]() // the index of a reifiable symbol in `reifiableSyms` + private var boundSyms = Set[Symbol]() // set of all symbols that are bound in tree to be reified + + private def definedInLiftedCode(tpe: Type) = + tpe exists (tp => boundSyms contains tp.typeSymbol) + + private def definedInLiftedCode(sym: Symbol) = + boundSyms contains sym + + /** + * Generate tree of the form + * + * { val $mr = scala.reflect.runtime.Mirror + * $local1 = new TypeSymbol(owner1, NoPosition, name1) + * ... + * $localN = new TermSymbol(ownerN, NoPositiion, nameN) + * $local1.setInfo(tpe1) + * ... + * $localN.setInfo(tpeN) + * $localN.setAnnotations(annotsN) + * rtree + * } + * + * where + * + * - `$localI` are free type symbols in the environment, as well as local symbols + * of refinement types. + * - `tpeI` are the info's of `symI` + * - `rtree` is code that generates `data` at runtime, maintaining all attributes. + * - `data` is typically a tree or a type. + */ + def reifyTopLevel(data: Any): Tree = { + val rtree = reify(data) + Block(mirrorAlias :: reifySymbolTableSetup, rtree) } - } else { - CannotReifyPreTyperTrees(tree) - } - } - - class Reifier() { - import definitions._ - - final val scalaPrefix = "scala." - final val localPrefix = "$local" - final val memoizerName = "$memo" - - val reifyDebug = settings.Yreifydebug.value - - private val reifiableSyms = mutable.ArrayBuffer[Symbol]() // the symbols that are reified with the tree - private val symIndex = mutable.HashMap[Symbol, Int]() // the index of a reifiable symbol in `reifiableSyms` - private var boundSyms = Set[Symbol]() // set of all symbols that are bound in tree to be reified - - /** - * Generate tree of the form - * - * { val $mr = scala.reflect.runtime.Mirror - * $local1 = new TypeSymbol(owner1, NoPosition, name1) - * ... - * $localN = new TermSymbol(ownerN, NoPositiion, nameN) - * $local1.setInfo(tpe1) - * ... - * $localN.setInfo(tpeN) - * $localN.setAnnotations(annotsN) - * rtree - * } - * - * where - * - * - `$localI` are free type symbols in the environment, as well as local symbols - * of refinement types. - * - `tpeI` are the info's of `symI` - * - `rtree` is code that generates `data` at runtime, maintaining all attributes. - * - `data` is typically a tree or a type. - */ - def reifyTopLevel(data: Any): Tree = { - val rtree = reify(data) - Block(mirrorAlias :: reifySymbolTableSetup, rtree) - } - private def isLocatable(sym: Symbol) = - sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0 + private def isLocatable(sym: Symbol) = + sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0 - private def registerReifiableSymbol(sym: Symbol): Unit = - if (!(symIndex contains sym)) { - sym.owner.ownersIterator find (x => !isLocatable(x)) foreach registerReifiableSymbol - symIndex(sym) = reifiableSyms.length - reifiableSyms += sym - } + private def registerReifiableSymbol(sym: Symbol): Unit = + if (!(symIndex contains sym)) { + sym.owner.ownersIterator find (x => !isLocatable(x)) foreach registerReifiableSymbol + symIndex(sym) = reifiableSyms.length + reifiableSyms += sym + } - // helper methods - - private def localName(sym: Symbol): TermName = - newTermName(localPrefix + symIndex(sym)) - - private def call(fname: String, args: Tree*): Tree = - Apply(termPath(fname), args.toList) - - private def mirrorSelect(name: String): Tree = - termPath(nme.MIRROR_PREFIX + name) - - private def mirrorCall(name: TermName, args: Tree*): Tree = - call("" + (nme.MIRROR_PREFIX append name), args: _*) - - private def mirrorCall(name: String, args: Tree*): Tree = - call(nme.MIRROR_PREFIX + name, args: _*) - - private def mirrorFactoryCall(value: Product, args: Tree*): Tree = - mirrorCall(value.productPrefix, args: _*) - - private def scalaFactoryCall(name: String, args: Tree*): Tree = - call(scalaPrefix + name + ".apply", args: _*) - - private def mkList(args: List[Tree]): Tree = - scalaFactoryCall("collection.immutable.List", args: _*) - - private def reifyModifiers(m: Modifiers) = - mirrorCall("modifiersFromInternalFlags", reify(m.flags), reify(m.privateWithin), reify(m.annotations)) - - private def reifyAggregate(name: String, args: Any*) = - scalaFactoryCall(name, (args map reify).toList: _*) - - /** - * Reify a list - */ - private def reifyList(xs: List[Any]): Tree = - mkList(xs map reify) - - /** Reify a name */ - private def reifyName(name: Name) = - mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString))) - - private def isFree(sym: Symbol) = - !(symIndex contains sym) - - /** - * Reify a reference to a symbol - */ - private def reifySymRef(sym: Symbol): Tree = { - symIndex get sym match { - case Some(idx) => - Ident(localName(sym)) - case None => - if (sym == NoSymbol) - mirrorSelect("NoSymbol") - else if (sym == RootPackage) - mirrorSelect("definitions.RootPackage") - else if (sym == RootClass) - mirrorSelect("definitions.RootClass") - else if (sym == EmptyPackage) - mirrorSelect("definitions.EmptyPackage") - else if (sym.isModuleClass) - Select(reifySymRef(sym.sourceModule), "moduleClass") - else if (sym.isStatic && sym.isClass) - mirrorCall("staticClass", reify(sym.fullName)) - else if (sym.isStatic && sym.isModule) - mirrorCall("staticModule", reify(sym.fullName)) - else if (isLocatable(sym)) - if (sym.isTypeParameter) - mirrorCall("selectParam", reify(sym.owner), reify(sym.paramPos)) + // helper methods + + private def localName(sym: Symbol): TermName = + newTermName(localPrefix + symIndex(sym)) + + private def call(fname: String, args: Tree*): Tree = + Apply(termPath(fname), args.toList) + + private def mirrorSelect(name: String): Tree = + termPath(nme.MIRROR_PREFIX + name) + + private def mirrorCall(name: TermName, args: Tree*): Tree = + call("" + (nme.MIRROR_PREFIX append name), args: _*) + + private def mirrorCall(name: String, args: Tree*): Tree = + call(nme.MIRROR_PREFIX + name, args: _*) + + private def mirrorFactoryCall(value: Product, args: Tree*): Tree = + mirrorFactoryCall(value.productPrefix, args: _*) + + private def mirrorFactoryCall(prefix: String, args: Tree*): Tree = + mirrorCall(prefix, args: _*) + + private def scalaFactoryCall(name: String, args: Tree*): Tree = + call(scalaPrefix + name + ".apply", args: _*) + + private def mkList(args: List[Tree]): Tree = + scalaFactoryCall("collection.immutable.List", args: _*) + + private def reifyModifiers(m: Modifiers) = + mirrorCall("modifiersFromInternalFlags", reify(m.flags), reify(m.privateWithin), reify(m.annotations)) + + private def reifyAggregate(name: String, args: Any*) = + scalaFactoryCall(name, (args map reify).toList: _*) + + /** + * Reify a list + */ + private def reifyList(xs: List[Any]): Tree = + mkList(xs map reify) + + /** + * Reify an array + */ + private def reifyArray(xs: Array[_]): Tree = + // @xeno.by: doesn't work for Array(LiteralAnnotArg(...)) + // because we cannot generate manifests for path-dependent types + scalaFactoryCall(nme.Array, xs map reify: _*) + + /** Reify a name */ + private def reifyName(name: Name) = + mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString))) + + private def isFree(sym: Symbol) = + !(symIndex contains sym) + + /** + * Reify a reference to a symbol + */ + private def reifySymRef(sym: Symbol): Tree = { + symIndex get sym match { + case Some(idx) => + Ident(localName(sym)) + case None => + if (sym == NoSymbol) + mirrorSelect("NoSymbol") + else if (sym == RootPackage) + mirrorSelect("definitions.RootPackage") + else if (sym == RootClass) + mirrorSelect("definitions.RootClass") + else if (sym == EmptyPackage) + mirrorSelect("definitions.EmptyPackage") + else if (sym.isModuleClass) + Select(reifySymRef(sym.sourceModule), "moduleClass") + else if (sym.isStatic && sym.isClass) + mirrorCall("staticClass", reify(sym.fullName)) + else if (sym.isStatic && sym.isModule) + mirrorCall("staticModule", reify(sym.fullName)) + else if (isLocatable(sym)) + if (sym.isTypeParameter) + mirrorCall("selectParam", reify(sym.owner), reify(sym.paramPos)) + else { + if (reifyDebug) println("locatable: " + sym + " " + sym.isPackageClass + " " + sym.owner + " " + sym.isTypeParameter) + val rowner = reify(sym.owner) + val rname = reify(sym.name.toString) + if (sym.isType) + mirrorCall("selectType", rowner, rname) + else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { + val index = sym.owner.info.decl(sym.name).alternatives indexOf sym + assert(index >= 0, sym) + mirrorCall("selectOverloadedMethod", rowner, rname, reify(index)) + } else + mirrorCall("selectTerm", rowner, rname) + } else { - if (reifyDebug) println("locatable: " + sym + " " + sym.isPackageClass + " " + sym.owner + " " + sym.isTypeParameter) - val rowner = reify(sym.owner) - val rname = reify(sym.name.toString) - if (sym.isType) - mirrorCall("selectType", rowner, rname) - else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { - val index = sym.owner.info.decl(sym.name).alternatives indexOf sym - assert(index >= 0, sym) - mirrorCall("selectOverloadedMethod", rowner, rname, reify(index)) - } else - mirrorCall("selectTerm", rowner, rname) - } - else { - if (sym.isTerm) { - if (reifyDebug) println("Free: " + sym) - val symtpe = lambdaLift.boxIfCaptured(sym, sym.tpe, erasedTypes = false) - def markIfCaptured(arg: Ident): Tree = - if (sym.isCapturedVariable) referenceCapturedVariable(arg) else arg - mirrorCall("newFreeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym))) - } else { - if (reifyDebug) println("Late local: " + sym) - registerReifiableSymbol(sym) - reifySymRef(sym) + if (sym.isTerm) { + if (reifyDebug) println("Free: " + sym) + val symtpe = lambdaLift.boxIfCaptured(sym, sym.tpe, erasedTypes = false) + def markIfCaptured(arg: Ident): Tree = + if (sym.isCapturedVariable) referenceCapturedVariable(arg) else arg + mirrorCall("newFreeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym))) + } else { + if (reifyDebug) println("Late local: " + sym) + registerReifiableSymbol(sym) + reifySymRef(sym) + } } - } + } } - } - /** - * reify the creation of a symbol - */ - private def reifySymbolDef(sym: Symbol): Tree = { - if (reifyDebug) println("reify sym def " + sym) - - ValDef(NoMods, localName(sym), TypeTree(), - Apply( - Select(reify(sym.owner), "newNestedSymbol"), - List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags))) + /** + * reify the creation of a symbol + */ + private def reifySymbolDef(sym: Symbol): Tree = { + if (reifyDebug) println("reify sym def " + sym) + + ValDef(NoMods, localName(sym), TypeTree(), + Apply( + Select(reify(sym.owner), "newNestedSymbol"), + List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags))) + ) ) - ) - } + } - /** - * Generate code to add type and annotation info to a reified symbol - */ - private def fillInSymbol(sym: Symbol): Tree = { - val rset = Apply(Select(reifySymRef(sym), nme.setTypeSignature), List(reifyType(sym.info))) - if (sym.annotations.isEmpty) rset - else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations))) - } + /** + * Generate code to add type and annotation info to a reified symbol + */ + private def fillInSymbol(sym: Symbol): Tree = { + val rset = Apply(Select(reifySymRef(sym), nme.setTypeSignature), List(reifyType(sym.info))) + if (sym.annotations.isEmpty) rset + else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations))) + } - /** Reify a scope */ - private def reifyScope(scope: Scope): Tree = { - scope foreach registerReifiableSymbol - mirrorCall(nme.newScopeWith, scope.toList map reifySymRef: _*) - } + /** Reify a scope */ + private def reifyScope(scope: Scope): Tree = { + scope foreach registerReifiableSymbol + mirrorCall(nme.newScopeWith, scope.toList map reifySymRef: _*) + } - /** Reify a list of symbols that need to be created */ - private def reifySymbols(syms: List[Symbol]): Tree = { - syms foreach registerReifiableSymbol - mkList(syms map reifySymRef) - } + /** Reify a list of symbols that need to be created */ + private def reifySymbols(syms: List[Symbol]): Tree = { + syms foreach registerReifiableSymbol + mkList(syms map reifySymRef) + } - /** Reify a type that defines some symbols */ - private def reifyTypeBinder(value: Product, bound: List[Symbol], underlying: Type): Tree = - mirrorFactoryCall(value, reifySymbols(bound), reify(underlying)) - - /** Reify a type */ - private def reifyType(tpe0: Type): Tree = { - val tpe = tpe0.normalize - val tsym = tpe.typeSymbol - if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) - Select(reifySymRef(tpe.typeSymbol), nme.asTypeConstructor) - else tpe match { - case t @ NoType => - reifyMirrorObject(t) - case t @ NoPrefix => - reifyMirrorObject(t) - case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => - mirrorCall(nme.thisModuleType, reify(clazz.fullName)) - case t @ RefinedType(parents, decls) => - registerReifiableSymbol(tpe.typeSymbol) - mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) - case t @ ClassInfoType(parents, decls, clazz) => - registerReifiableSymbol(clazz) - mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) - case t @ ExistentialType(tparams, underlying) => - reifyTypeBinder(t, tparams, underlying) - case t @ PolyType(tparams, underlying) => - reifyTypeBinder(t, tparams, underlying) - case t @ MethodType(params, restpe) => - reifyTypeBinder(t, params, restpe) - case _ => - reifyProductUnsafe(tpe) + /** Reify a type that defines some symbols */ + private def reifyTypeBinder(value: Product, bound: List[Symbol], underlying: Type): Tree = + mirrorFactoryCall(value, reifySymbols(bound), reify(underlying)) + + /** Reify a type */ + private def reifyType(tpe0: Type): Tree = { + val tpe = tpe0.normalize + + if (tpe.isErroneous) + CannotReifyErroneousType(tpe) + if (definedInLiftedCode(tpe)) + CannotReifyTypeInvolvingBoundType(tpe) + + val tsym = tpe.typeSymbol + if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) + Select(reifySymRef(tpe.typeSymbol), nme.asTypeConstructor) + else tpe match { + case t @ NoType => + reifyMirrorObject(t) + case t @ NoPrefix => + reifyMirrorObject(t) + case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic => + mirrorCall(nme.thisModuleType, reify(clazz.fullName)) + case t @ RefinedType(parents, decls) => + registerReifiableSymbol(tpe.typeSymbol) + mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) + case t @ ClassInfoType(parents, decls, clazz) => + registerReifiableSymbol(clazz) + mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) + case t @ ExistentialType(tparams, underlying) => + reifyTypeBinder(t, tparams, underlying) + case t @ PolyType(tparams, underlying) => + reifyTypeBinder(t, tparams, underlying) + case t @ MethodType(params, restpe) => + reifyTypeBinder(t, params, restpe) + case t @ AnnotatedType(anns, underlying, selfsym) => + val saved1 = reifySymbols + val saved2 = reifyTypes + + try { + // one more quirk of reifying annotations + // + // when reifying AnnotatedTypes we need to reify all the types and symbols of inner ASTs + // that's because a lot of logic expects post-typer trees to have non-null tpes + // + // Q: reified trees are pre-typer, so there's shouldn't be a problem. + // reflective typechecker will fill in missing symbols and types, right? + // A: actually, no. annotation ASTs live inside AnnotatedTypes, + // and insides of the types is the place where typechecker doesn't look. + reifySymbols = true + reifyTypes = true + if (reifyDebug) println("reify AnnotatedType: " + tpe) + reifyProductUnsafe(tpe) + } finally { + reifySymbols = saved1 + reifyTypes = saved2 + } + case _ => + reifyProductUnsafe(tpe) + } } - } - private def definedInLiftedCode(tpe: Type) = - tpe exists (tp => boundSyms contains tp.typeSymbol) + var reifySymbols = false + var reifyTypes = false + + /** Reify a tree */ + private def reifyTree(tree: Tree): Tree = { + def reifyDefault(tree: Tree) = + reifyProduct(tree) + + var rtree = tree match { + case tree if tree.isErroneous => + CannotReifyErroneousTree(tree) + case self.EmptyTree => + reifyMirrorObject(EmptyTree) + case self.emptyValDef => + mirrorSelect(nme.emptyValDef) + case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => + reifyFree(tree) + case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => + if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { + if (reifyDebug) println("captured variable: " + tree.symbol) + captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here. + mirrorCall("Select", reifyFree(tree), reifyName(nme.elem)) + } else reifyFree(tree) + case tt: TypeTree if (tt.tpe != null) => + reifyTypeTree(tt) + case ta @ TypeApply(hk, ts) => + def isErased(tt: TypeTree) = tt.tpe != null && definedInLiftedCode(tt.tpe) && tt.original == null + val discard = ts collect { case tt: TypeTree => tt } exists isErased + if (reifyDebug && discard) println("discarding TypeApply: " + tree) + if (discard) reifyTree(hk) else reifyDefault(ta) + case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) => + CannotReifyClassOfBoundType(tree, tpe) + case Literal(constant @ Constant(sym: Symbol)) if boundSyms contains sym => + CannotReifyClassOfBoundEnum(tree, constant.tpe) + case tree if tree.isDef => + if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe)))) + // registerReifiableSymbol(tree.symbol) + boundSyms += tree.symbol + + val prefix = tree.productPrefix + val elements = (tree.productIterator map { + // annotations exist in two flavors: + // 1) pre-typer ones that populate: a) Modifiers, b) Annotated nodes (irrelevant in this context) + // 2) post-typer ones that dwell inside: a) sym.annotations, b) AnnotatedTypes (irrelevant in this context) + // + // here we process Modifiers that are involved in deftrees + // AnnotatedTypes get reified elsewhere (currently, in ``reifyTypeTree'') + case Modifiers(flags, privateWithin, annotations) => + assert(annotations.isEmpty) // should've been eliminated by the typer + val postTyper = tree.symbol.annotations filter (_.original != EmptyTree) + if (reifyDebug && !postTyper.isEmpty) println("reify symbol annotations for %s: %s".format(tree.symbol, tree.symbol.annotations)) + val preTyper = postTyper map toPreTyperAnnotation + Modifiers(flags, privateWithin, preTyper) + case x => + x + }).toList + reifyProduct(prefix, elements) + case _ => + reifyDefault(tree) + } - private def isErased(tree: Tree) = tree match { - case tt: TypeTree => definedInLiftedCode(tt.tpe) && tt.original == null - case _ => false - } + // usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation + // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why. + if (reifySymbols && tree.hasSymbol) { + if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree)) + rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol))) + } + if (reifyTypes && tree.tpe != null) { + if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree)) + rtree = Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe))) + } - /** Reify a tree */ - private def reifyTree(tree: Tree): Tree = tree match { - case EmptyTree => - reifyMirrorObject(EmptyTree) - case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => - reifyFree(tree) - case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) => - if (tree.symbol.isVariable && tree.symbol.owner.isTerm) { - captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here. - mirrorCall("Select", reifyFree(tree), reifyName(nme.elem)) - } else reifyFree(tree) - case tt: TypeTree if (tt.tpe != null) => + rtree + } + + /** Reify pre-typer representation of a type. + * + * NB: This is the trickiest part of reification! + * + * In most cases, we're perfectly fine to reify a Type itself (see ``reifyType''). + * However if the type involves a symbol declared inside the quasiquote (i.e. registered in ``boundSyms''), + * then we cannot reify it, or otherwise subsequent reflective compilation will fail. + * + * Why will it fail? Because reified deftrees (e.g. ClassDef(...)) will generate fresh symbols during that compilation, + * so naively reified symbols will become out of sync, which brings really funny compilation errors and/or crashes, e.g.: + * https://issues.scala-lang.org/browse/SI-5230 + * + * To deal with this unpleasant fact, we need to fall back from types to equivalent trees (after all, parser trees don't contain any types, just trees, so it should be possible). + * Luckily, these original trees get preserved for us in the ``original'' field when Trees get transformed into TypeTrees. + * And if an original of a type tree is empty, we can safely assume that this type is non-essential (e.g. was inferred/generated by the compiler). + * In that case the type can be omitted (e.g. reified as an empty TypeTree), since it will be inferred again later on. + * + * An important property of the original is that it isn't just a pre-typer tree. + * It's actually kind of a post-typer tree with symbols assigned to its Idents (e.g. Ident("List") will contain a symbol that points to immutable.this.List). + * This is very important, since subsequent reflective compilation won't have to resolve these symbols. + * In general case, such resolution cannot be performed, since reification doesn't preserve lexical context, + * which means that reflective compilation won't be aware of, say, imports that were provided when the reifee has been compiled. + * + * This workaround worked surprisingly well and allowed me to fix several important reification bugs, until the abstraction has leaked. + * Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees. + * To the moment I know two such situations: + * 1) Unapplies: https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057 + * 2) Annotations: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless + * 3) + */ + private def reifyTypeTree(tt: TypeTree): Tree = { if (definedInLiftedCode(tt.tpe)) { - // erase non-essential (i.e. inferred) types - // reify symless counterparts of essential types - // @xeno.by: in general case reflective compiler lacks the context to typecheck the originals - // more info here: https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057 - // this is A BIG BAD TODO! - if (tt.original != null) reify(tt.original) else mirrorCall("TypeTree") + if (reifyDebug) println("reifyTypeTree, defined in lifted code: " + tt.tpe) + if (tt.original != null) { + val annotations = tt.tpe filter { _.isInstanceOf[AnnotatedType] } collect { case atp: AnnotatedType => atp.annotations } flatten + val annmap = annotations map { ann => (ann.original, ann) } toMap + + // annotations exist in two flavors: + // 1) pre-typer ones that populate: a) Modifiers (irrelevant in this context), b) Annotated nodes + // 2) post-typer ones that dwell inside: a) sym.annotations (irrelevant in this context), b) AnnotatedTypes + // + // here we process AnnotatedTypes, since only they can be involved in TypeTrees + // Modifiers get reified elsewhere (currently, in the "isDef" case of ``reifyTree'') + // + // the problem with annotations is that their originals don't preserve any symbols at all + // read the comment to this method to find out why it's bad + // that's why we transplant typechecked, i.e. symful, annotations onto original trees + class AnnotationFixup extends self.Transformer { + override def transform(tree: Tree) = tree match { + case Annotated(ann0, args) => + assert(annmap contains ann0) + val ann1 = annmap(ann0) + val ann = toPreTyperAnnotation(ann1) + Annotated(ann, transform(args)) + case _ => + tree + } + } + + if (reifyDebug) println("verdict: essential, reify as original") + val patchedOriginal = new AnnotationFixup().transform(tt.original) + reifyTree(patchedOriginal) + } else { + // type is deemed to be non-essential + // erase it and hope that subsequent reflective compilation will be able to recreate it again + if (reifyDebug) println("verdict: non-essential, discard") + mirrorCall("TypeTree") + } } else { var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe)) // @xeno.by: originals get typechecked during subsequent reflective compilation, which leads to subtle bugs @@ -306,124 +441,219 @@ trait Reifiers { self: Global => // } rtt } - case ta @ TypeApply(hk, ts) => - if (ts exists isErased) reifyTree(hk) else reifyProduct(ta) - case self.emptyValDef => - mirrorSelect(nme.emptyValDef) - case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) => - CannotReifyClassOfBoundType(tree, tpe) - case Literal(constant @ Constant(sym: Symbol)) if boundSyms contains sym => - CannotReifyClassOfBoundEnum(tree, constant.tpe) - case _ => - if (tree.isDef) { - if (reifyDebug) println("boundSym: " + tree.symbol) - boundSyms += tree.symbol + } + + /** Reify post-typer representation of an annotation */ + private def reifyAnnotation(ann: AnnotationInfo): Tree = + // @xeno.by: if you reify originals, you get SO when trying to reify AnnotatedTypes, so screw it - after all, it's not that important + mirrorFactoryCall("AnnotationInfo", reifyType(ann.atp), reifyList(ann.args), reify(ann.assocs)) + + /** Reify pre-typer representation of an annotation. + * The trick here is to retain the symbols that have been populated during typechecking of the annotation. + * If we do not do that, subsequent reflective compilation will fail. + */ + private def toPreTyperAnnotation(ann: AnnotationInfo): Tree = { + if (definedInLiftedCode(ann.atp)) { + // todo. deconstruct reifiable tree from ann.original and ann.args+ann.assocs + // + // keep in mind that we can't simply use ann.original, because its args are symless + // which means that any imported symbol (e.g. List) will crash subsequent reflective compilation + // hint: if I had enough time, I'd try to extract reifiable annotation type from ann.original + // and to apply its constructor to ann.args (that are symful, i.e. suitable for reification) + // + // also, if we pursue the route of reifying annotations defined in lifted code + // we should think about how to provide types for all nodes of the return value + // this will be necessary for reifying AnnotatedTypes, since ASTs inside ATs must all have non-null tpes + // an alternative would be downgrading ATs to Annotated nodes, but this needs careful thinking + // for now I just leave this as an implementation restriction + CannotReifyAnnotationInvolvingBoundType(ann) + } else { + val args = if (ann.assocs.isEmpty) { + ann.args + } else { + def toScalaAnnotation(jann: ClassfileAnnotArg): Tree = jann match { + case LiteralAnnotArg(const) => + Literal(const) + case ArrayAnnotArg(arr) => + Apply(Ident(definitions.ArrayModule), arr.toList map toScalaAnnotation) + case NestedAnnotArg(ann) => + toPreTyperAnnotation(ann) + } + + ann.assocs map { case (nme, arg) => AssignOrNamedArg(Ident(nme), toScalaAnnotation(arg)) } + } + + New(TypeTree(ann.atp), List(args)) + } + } + + /** + * Reify a free reference. The result will be either a mirror reference + * to a global value, or else a mirror Literal. + */ + private def reifyFree(tree: Tree): Tree = tree match { + case This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass => + val sym = tree.symbol + if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) + if (reifyDebug) println("Free: " + sym) + val freeVar = mirrorCall("newFreeVar", reify(sym.name.toString), reify(sym.tpe), This(sym)) + mirrorCall(nme.Ident, freeVar) + case This(_) => + if (reifyDebug) println("This for %s, reified as This".format(tree.symbol)) + mirrorCall(nme.This, reifySymRef(tree.symbol)) + case _ => + mirrorCall(nme.Ident, reifySymRef(tree.symbol)) + } + + // todo: consider whether we should also reify positions + private def reifyPosition(pos: Position): Tree = + reifyMirrorObject(NoPosition) + + // !!! we must eliminate these casts. + private def reifyProductUnsafe(x: Any): Tree = + if (x.isInstanceOf[Product]) reifyProduct(x.asInstanceOf[Product]) + else throw new Exception("%s of type %s cannot be cast to Product".format(x, x.getClass)) + private def reifyProduct(x: Product): Tree = + reifyProduct(x.productPrefix, x.productIterator.toList) + private def reifyProduct(prefix: String, elements: List[Any]): Tree = { + // @xeno.by: reflection would be more robust, but, hey, this is a hot path + if (prefix.startsWith("Tuple")) reifyAggregate(prefix, elements: _*) + else mirrorCall(prefix, (elements map reify): _*) + } + + /** + * Reify a case object defined in Mirror + */ + private def reifyMirrorObject(name: String): Tree = mirrorSelect(name) + private def reifyMirrorObject(x: Product): Tree = reifyMirrorObject(x.productPrefix) + + private def isReifiableConstant(value: Any) = value match { + case null => true // seems pretty reifable to me? + case _: String => true + case _ => isAnyVal(value) + } + + /** Reify an arbitary value */ + private def reify(value: Any): Tree = value match { + case tree: Tree => reifyTree(tree) + case sym: Symbol => reifySymRef(sym) + case tpe: Type => reifyType(tpe) + case xs: List[_] => reifyList(xs) + case xs: Array[_] => reifyArray(xs) + case scope: Scope => reifyScope(scope) + case x: Name => reifyName(x) + case x: Position => reifyPosition(x) + case x: Modifiers => reifyModifiers(x) + case x: AnnotationInfo => reifyAnnotation(x) + case _ => + if (isReifiableConstant(value)) Literal(Constant(value)) + else reifyProductUnsafe(value) + } + + /** + * An (unreified) path that refers to definition with given fully qualified name + * @param mkName Creator for last portion of name (either TermName or TypeName) + */ + private def path(fullname: String, mkName: String => Name): Tree = { + val parts = fullname split "\\." + val prefixParts = parts.init + val lastName = mkName(parts.last) + if (prefixParts.isEmpty) Ident(lastName) + else { + val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _)) + Select(prefixTree, lastName) + } + } + + /** An (unreified) path that refers to term definition with given fully qualified name */ + private def termPath(fullname: String): Tree = path(fullname, newTermName) + + /** An (unreified) path that refers to type definition with given fully qualified name */ + private def typePath(fullname: String): Tree = path(fullname, newTypeName) + + private def mirrorAlias = + ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(termPath(fullnme.MirrorPackage)), termPath(fullnme.MirrorPackage)) + + /** + * Generate code that generates a symbol table of all symbols registered in `reifiableSyms` + */ + private def reifySymbolTableSetup: List[Tree] = { + val symDefs, fillIns = new mutable.ArrayBuffer[Tree] + var i = 0 + while (i < reifiableSyms.length) { + // fillInSymbol might create new reifiableSyms, that's why this is done iteratively + symDefs += reifySymbolDef(reifiableSyms(i)) + fillIns += fillInSymbol(reifiableSyms(i)) + i += 1 } - reifyProduct(tree) - /* - if (tree.isDef || tree.isInstanceOf[Function]) - registerReifiableSymbol(tree.symbol) - if (tree.hasSymbol) - rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol))) - Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe))) -*/ - } + symDefs.toList ++ fillIns.toList + } + } // end of Reifier - /** - * Reify a free reference. The result will be either a mirror reference - * to a global value, or else a mirror Literal. - */ - private def reifyFree(tree: Tree): Tree = tree match { - case This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass => - val sym = tree.symbol - if (reifyDebug) println("This for %s, reified as freeVar".format(sym)) - if (reifyDebug) println("Free: " + sym) - val freeVar = mirrorCall("newFreeVar", reify(sym.name.toString), reify(sym.tpe), This(sym)) - mirrorCall(nme.Ident, freeVar) - case This(_) => - if (reifyDebug) println("This for %s, reified as This".format(tree.symbol)) - mirrorCall(nme.This, reifySymRef(tree.symbol)) - case _ => - mirrorCall(nme.Ident, reifySymRef(tree.symbol)) - } + object Reifier { + def CannotReifyPreTyperTree(tree: Tree) = { + val msg = "pre-typer trees are not supported, consider typechecking the tree before passing it to the reifier" + throw new ReifierError(tree.pos, msg) + } - // todo: consider whether we should also reify positions - private def reifyPosition(pos: Position): Tree = - reifyMirrorObject(NoPosition) - - // !!! we must eliminate these casts. - private def reifyProductUnsafe(x: Any): Tree = - reifyProduct(x.asInstanceOf[Product]) - private def reifyProduct(x: Product): Tree = - mirrorCall(x.productPrefix, (x.productIterator map reify).toList: _*) - - /** - * Reify a case object defined in Mirror - */ - private def reifyMirrorObject(name: String): Tree = mirrorSelect(name) - private def reifyMirrorObject(x: Product): Tree = reifyMirrorObject(x.productPrefix) - - private def isReifiableConstant(value: Any) = value match { - case null => true // seems pretty reifable to me? - case _: String => true - case _ => isAnyVal(value) - } + def CannotReifyErroneousTree(tree: Tree) = { + val msg = "erroneous trees are not supported, make sure that your tree typechecks successfully before passing it to the reifier" + throw new ReifierError(tree.pos, msg) + } - /** Reify an arbitary value */ - private def reify(value: Any): Tree = value match { - case tree: Tree => reifyTree(tree) - case sym: Symbol => reifySymRef(sym) - case tpe: Type => reifyType(tpe) - case xs: List[_] => reifyList(xs) - case xs: Array[_] => scalaFactoryCall(nme.Array, xs map reify: _*) - case scope: Scope => reifyScope(scope) - case x: Name => reifyName(x) - case x: Position => reifyPosition(x) - case x: Modifiers => reifyModifiers(x) - case _ => - if (isReifiableConstant(value)) Literal(Constant(value)) - else reifyProductUnsafe(value) - } + def CannotReifyErroneousType(tpe: Type) = { + val msg = "erroneous types are not supported, make sure that your tree typechecks successfully before passing it to the reifier" + throw new ReifierError(NoPosition, msg) + } - /** - * An (unreified) path that refers to definition with given fully qualified name - * @param mkName Creator for last portion of name (either TermName or TypeName) - */ - private def path(fullname: String, mkName: String => Name): Tree = { - val parts = fullname split "\\." - val prefixParts = parts.init - val lastName = mkName(parts.last) - if (prefixParts.isEmpty) Ident(lastName) - else { - val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _)) - Select(prefixTree, lastName) + def CannotReifyClassOfBoundType(tree: Tree, tpe: Type) = { + val msg = "implementation restriction: cannot reify classOf[%s] which refers to a type declared inside the block being reified".format(tpe) + throw new ReifierError(tree.pos, msg) + } + + def CannotReifyClassOfBoundEnum(tree: Tree, tpe: Type) = { + val msg = "implementation restriction: cannot reify classOf[%s] which refers to an enum declared inside the block being reified".format(tpe) + throw new ReifierError(tree.pos, msg) + } + + def CannotReifyTypeInvolvingBoundType(tpe: Type) = { + val msg = "implementation restriction: cannot reify type %s which involves a symbol declared inside the block being reified".format(tpe) + throw new ReifierError(NoPosition, msg) } - } - /** An (unreified) path that refers to term definition with given fully qualified name */ - private def termPath(fullname: String): Tree = path(fullname, newTermName) - - /** An (unreified) path that refers to type definition with given fully qualified name */ - private def typePath(fullname: String): Tree = path(fullname, newTypeName) - - private def mirrorAlias = - ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(termPath(fullnme.MirrorPackage)), termPath(fullnme.MirrorPackage)) - - /** - * Generate code that generates a symbol table of all symbols registered in `reifiableSyms` - */ - private def reifySymbolTableSetup: List[Tree] = { - val symDefs, fillIns = new mutable.ArrayBuffer[Tree] - var i = 0 - while (i < reifiableSyms.length) { - // fillInSymbol might create new reifiableSyms, that's why this is done iteratively - symDefs += reifySymbolDef(reifiableSyms(i)) - fillIns += fillInSymbol(reifiableSyms(i)) - i += 1 + def CannotReifyAnnotationInvolvingBoundType(ann: AnnotationInfo) = { + val msg = "implementation restriction: cannot reify annotation @%s which involves a symbol declared inside the block being reified".format(ann) + throw new ReifierError(ann.original.pos, msg) } + } // end of Reifier + + // begin reify + import Reifier._ + if (tree.tpe != null) { + val saved = printTypings + try { + val reifyDebug = settings.Yreifydebug.value + val debugTrace = util.trace when reifyDebug + debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) + debugTrace("transformed = ") { + val reifier = new Reifier() + val untyped = reifier.reifyTopLevel(tree) + + val reifyCopypaste = settings.Yreifycopypaste.value + if (reifyCopypaste) { + if (reifyDebug) println("=======================") + println(reifiedNodeToString(untyped)) + if (reifyDebug) println("=======================") + } - symDefs.toList ++ fillIns.toList + untyped + } + } finally { + printTypings = saved + } + } else { + CannotReifyPreTyperTree(tree) } } @@ -431,19 +661,4 @@ trait Reifiers { self: Global => class ReifierError(var pos: Position, val msg: String) extends Throwable(msg) { def this(msg: String) = this(NoPosition, msg) } - - def CannotReifyPreTyperTrees(tree: Tree) = { - val msg = "pre-typer trees are not supported, consider typechecking the tree before passing it to the reifier" - throw new ReifierError(tree.pos, msg) - } - - def CannotReifyClassOfBoundType(tree: Tree, tpe: Type) = { - val msg = "cannot reify classOf[%s] which refers to a type declared inside the block being reified".format(tpe) - throw new ReifierError(tree.pos, msg) - } - - def CannotReifyClassOfBoundEnum(tree: Tree, tpe: Type) = { - val msg = "cannot reify classOf[%s] which refers to an enum declared inside the block being reified".format(tpe) - throw new ReifierError(tree.pos, msg) - } } diff --git a/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala index 98135fadda..fce59bb099 100644 --- a/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala @@ -34,22 +34,22 @@ trait ReifyPrinters { self: NodePrinters => s = s.replace("modifiersFromInternalFlags", "Modifiers") s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()") s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => { - val buf = new StringBuilder + val buf = new collection.mutable.ListBuffer[String] - val flags = m.group(1).toLong - val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", " - if (s_flags != "") - buf.append("Set(" + s_flags + ")") + val annotations = m.group(3) + if (buf.nonEmpty || annotations.nonEmpty) + buf.append("List(" + annotations + ")") val privateWithin = "" + m.group(2) - if (privateWithin != "") - buf.append(", newTypeName(\"" + privateWithin + "\")") + if (buf.nonEmpty || privateWithin != "") + buf.append("newTypeName(\"" + privateWithin + "\")") - val annotations = m.group(3) - if (annotations.nonEmpty) - buf.append(", List(" + annotations + ")") + val flags = m.group(1).toLong + val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", " + if (buf.nonEmpty || s_flags != "") + buf.append("Set(" + s_flags + ")") - "Modifiers(" + buf.toString + ")" + "Modifiers(" + buf.reverse.mkString(", ") + ")" }) s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => { val flags = m.group(1).toLong diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index c060e938bb..3371353f25 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -51,9 +51,6 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => treePrinter.println() treePrinter.print(definition) - case AssignOrNamedArg(lhs, rhs) => - treePrinter.print(lhs, " = ", rhs) - case TypeTreeWithDeferredRefCheck() => treePrinter.print("") diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 83b6252b26..9e304a0eb5 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -30,12 +30,6 @@ trait Trees extends reflect.internal.Trees { self: Global => override def isType = definition.isType } - /** Either an assignment or a named argument. Only appears in argument lists, - * eliminated by typecheck (doTypedApply) - */ - case class AssignOrNamedArg(lhs: Tree, rhs: Tree) - extends TermTree - /** Array selection . only used during erasure */ case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) extends TermTree with RefTree @@ -155,8 +149,6 @@ trait Trees extends reflect.internal.Trees { self: Global => traverser.traverseTrees(ts) case DocDef(comment, definition) => traverser.traverse(definition) - case AssignOrNamedArg(lhs, rhs) => - traverser.traverse(lhs); traverser.traverse(rhs) case SelectFromArray(qualifier, selector, erasure) => traverser.traverse(qualifier) case ReferenceToBoxed(idt) => @@ -168,7 +160,6 @@ trait Trees extends reflect.internal.Trees { self: Global => trait TreeCopier extends super.TreeCopierOps { def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck @@ -180,8 +171,6 @@ trait Trees extends reflect.internal.Trees { self: Global => class StrictTreeCopier extends super.StrictTreeCopier with TreeCopier { def DocDef(tree: Tree, comment: DocComment, definition: Tree) = new DocDef(comment, definition).copyAttrs(tree) - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = - new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree) def ReferenceToBoxed(tree: Tree, idt: Ident) = @@ -197,11 +186,6 @@ trait Trees extends reflect.internal.Trees { self: Global => if (comment0 == comment) && (definition0 == definition) => t case _ => this.treeCopy.DocDef(tree, comment, definition) } - def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { - case t @ AssignOrNamedArg(lhs0, rhs0) - if (lhs0 == lhs) && (rhs0 == rhs) => t - case _ => this.treeCopy.AssignOrNamedArg(tree, lhs, rhs) - } def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = tree match { case t @ SelectFromArray(qualifier0, selector0, _) if (qualifier0 == qualifier) && (selector0 == selector) => t @@ -232,8 +216,6 @@ trait Trees extends reflect.internal.Trees { self: Global => override protected def xtransform(transformer: super.Transformer, tree: Tree): Tree = tree match { case DocDef(comment, definition) => transformer.treeCopy.DocDef(tree, comment, transformer.transform(definition)) - case AssignOrNamedArg(lhs, rhs) => - transformer.treeCopy.AssignOrNamedArg(tree, transformer.transform(lhs), transformer.transform(rhs)) case SelectFromArray(qualifier, selector, erasure) => transformer.treeCopy.SelectFromArray( tree, transformer.transform(qualifier), selector, erasure) @@ -333,7 +315,6 @@ trait Trees extends reflect.internal.Trees { self: Global => case Parens(expr) (only used during parsing) case DocDef(comment, defn) => (eliminated by typer) - case AssignOrNamedArg(lhs, rhs) => (eliminated by typer) case TypeTreeWithDeferredRefCheck() => (created and eliminated by typer) case SelectFromArray(_, _, _) => (created and eliminated by erasure) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 485a1f3a5c..e949cb3eb2 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -167,6 +167,7 @@ trait ScalaSettings extends AbsScalaSettings val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification.") + val Ymacrodebug = BooleanSetting ("-Ymacro-debug", "Trace macro-related activities: generation of synthetics, expansion, exceptions.") val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup") val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") . withPostSetHook(_ => interpreter.replProps.debug setValue true) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 48ec59234e..ed249796a8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -49,7 +49,7 @@ trait Macros { self: Analyzer => * If `foo` is declared in an object, the second parameter list is () instead of (_this: _context.Tree). * If macro has no type arguments, the third parameter list is omitted (it's not empty, but omitted altogether). * - * To find out the desugared representation of your particular macro, compile it with -Ydebug. + * To find out the desugared representation of your particular macro, compile it with -Ymacro-debug. */ def macroMethDef(mdef: DefDef): Tree = { def paramDef(name: Name, tpt: Tree) = ValDef(Modifiers(PARAM), name, tpt, EmptyTree) @@ -86,7 +86,7 @@ trait Macros { self: Analyzer => def addMacroMethods(templ: Template, namer: Namer): Unit = { for (ddef @ DefDef(mods, _, _, _, _, _) <- templ.body if mods hasFlag MACRO) { - val trace = scala.tools.nsc.util.trace when settings.debug.value + val trace = scala.tools.nsc.util.trace when settings.Ymacrodebug.value val sym = namer.enterSyntheticSym(trace("macro def: ")(macroMethDef(ddef))) trace("added to "+namer.context.owner.enclClass+": ")(sym) } @@ -106,16 +106,43 @@ trait Macros { self: Analyzer => * not contain the macro implementation. */ def macroImpl(mac: Symbol): Option[(AnyRef, mirror.Symbol)] = { + val debug = settings.Ymacrodebug.value + val trace = scala.tools.nsc.util.trace when debug + trace("looking for macro implementation: ")(mac.fullNameString) + try { val mmeth = macroMeth(mac) + trace("found implementation at: ")(mmeth.fullNameString) + if (mmeth == NoSymbol) None else { val receiverClass: mirror.Symbol = mirror.symbolForName(mmeth.owner.fullName) + if (debug) { + println("receiverClass is: " + receiverClass.fullNameString) + + val jreceiverClass = mirror.classToJava(receiverClass) + val jreceiverSource = jreceiverClass.getProtectionDomain.getCodeSource + println("jreceiverClass is %s from %s".format(jreceiverClass, jreceiverSource)) + + val jreceiverClasspath = jreceiverClass.getClassLoader match { + case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" + case _ => "" + } + println("jreceiverClassLoader is %s with classpath %s".format(jreceiverClass.getClassLoader, jreceiverClasspath)) + } + val receiverObj = receiverClass.companionModule + trace("receiverObj is: ")(receiverObj.fullNameString) + if (receiverObj == mirror.NoSymbol) None else { val receiver = mirror.companionInstance(receiverClass) val rmeth = receiverObj.info.member(mirror.newTermName(mmeth.name.toString)) + if (debug) { + println("rmeth is: " + rmeth.fullNameString) + println("jrmeth is: " + mirror.methodToJava(rmeth)) + } + if (rmeth == mirror.NoSymbol) None else { Some((receiver, rmeth)) @@ -133,16 +160,21 @@ trait Macros { self: Analyzer => * tree that calls this method instead of the macro. */ def macroExpand(tree: Tree, context: Context): Option[Any] = { + val trace = scala.tools.nsc.util.trace when settings.Ymacrodebug.value + trace("macroExpand: ")(tree) + val macroDef = tree.symbol macroImpl(macroDef) match { case Some((receiver, rmeth)) => val argss = List(global) :: macroArgs(tree) val paramss = macroMeth(macroDef).paramss + trace("paramss: ")(paramss) val rawArgss = for ((as, ps) <- argss zip paramss) yield { if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1) else as } val rawArgs: Seq[Any] = rawArgss.flatten + trace("rawArgs: ")(rawArgs) val savedInfolevel = nodePrinters.infolevel try { // @xeno.by: InfoLevel.Verbose examines and prints out infos of symbols @@ -156,16 +188,19 @@ trait Macros { self: Analyzer => } catch { case ex => val realex = ReflectionUtils.unwrapThrowable(ex) - val stacktrace = new java.io.StringWriter() - realex.printStackTrace(new java.io.PrintWriter(stacktrace)) - val msg = System.getProperty("line.separator") + stacktrace + val msg = if (settings.Ymacrodebug.value) { + val stacktrace = new java.io.StringWriter() + realex.printStackTrace(new java.io.PrintWriter(stacktrace)) + System.getProperty("line.separator") + stacktrace + } else { + realex.getMessage + } context.unit.error(tree.pos, "exception during macro expansion: " + msg) None } finally { nodePrinters.infolevel = savedInfolevel } case None => - val trace = scala.tools.nsc.util.trace when settings.debug.value def notFound() = { context.unit.error(tree.pos, "macro implementation not found: " + macroDef.name) None diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6f6edc62c7..ef69e1525e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1404,7 +1404,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def typedClassDef(cdef: ClassDef): Tree = { // attributes(cdef) val clazz = cdef.symbol - val typedMods = removeAnnotations(cdef.mods) + val typedMods = typedModifiers(cdef.mods) assert(clazz != NoSymbol, cdef) reenterTypeParams(cdef.tparams) val tparams1 = cdef.tparams mapConserve (typedTypeDef) @@ -1441,7 +1441,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { linkedClass.info.decl(nme.CONSTRUCTOR).alternatives foreach (_.initialize) val clazz = mdef.symbol.moduleClass - val typedMods = removeAnnotations(mdef.mods) + val typedMods = typedModifiers(mdef.mods) assert(clazz != NoSymbol, mdef) val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, newScope)) { _.typedTemplate(mdef.impl, { @@ -1541,8 +1541,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { /** Remove definition annotations from modifiers (they have been saved * into the symbol's ``annotations'' in the type completer / namer) + * + * However reification does need annotation definitions to proceed. + * Unfortunately, AnnotationInfo doesn't provide enough info to reify it in general case. + * The biggest problem is with the "atp: Type" field, which cannot be reified in some situations + * that involve locally defined annotations. See more about that in Reifiers.scala. + * + * That's why the original tree gets saved into ``original'' field of AnnotationInfo (happens elsewhere). + * The field doesn't get pickled/unpickled and exists only during a single compilation run. + * This simultaneously allows us to reify annotations and to preserve backward compatibility. */ - def removeAnnotations(mods: Modifiers): Modifiers = + def typedModifiers(mods: Modifiers): Modifiers = mods.copy(annotations = Nil) setPositions mods.positions /** @@ -1553,7 +1562,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // attributes(vdef) val sym = vdef.symbol.initialize val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor) - val typedMods = removeAnnotations(vdef.mods) + val typedMods = typedModifiers(vdef.mods) // complete lazy annotations val annots = sym.annotations @@ -1764,7 +1773,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt)) checkNonCyclic(ddef, tpt1) ddef.tpt.setType(tpt1.tpe) - val typedMods = removeAnnotations(ddef.mods) + val typedMods = typedModifiers(ddef.mods) var rhs1 = if (ddef.name == nme.CONSTRUCTOR && !ddef.symbol.hasStaticFlag) { // need this to make it possible to generate static ctors if (!meth.isPrimaryConstructor && @@ -1813,7 +1822,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { tdef.symbol.initialize reenterTypeParams(tdef.tparams) val tparams1 = tdef.tparams mapConserve typedTypeDef - val typedMods = removeAnnotations(tdef.mods) + val typedMods = typedModifiers(tdef.mods) // complete lazy annotations val annots = tdef.symbol.annotations @@ -2770,7 +2779,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } if (hasError) annotationError - else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setPos(ann.pos) + else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setOriginal(ann).setPos(ann.pos) } } else if (requireJava) { reportAnnotationError(NestedAnnotationError(ann, annType)) @@ -2810,7 +2819,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def annInfo(t: Tree): AnnotationInfo = t match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => - AnnotationInfo(annType, args, List()).setPos(t.pos) + AnnotationInfo(annType, args, List()).setOriginal(ann).setPos(t.pos) case Block(stats, expr) => context.warning(t.pos, "Usage of named or default arguments transformed this annotation\n"+ diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 32940cbcd6..2c960392ec 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -439,6 +439,12 @@ trait Trees { self: Universe => case class Assign(lhs: Tree, rhs: Tree) extends TermTree + /** Either an assignment or a named argument. Only appears in argument lists, + * eliminated by typecheck (doTypedApply) + */ + case class AssignOrNamedArg(lhs: Tree, rhs: Tree) + extends TermTree + /** Conditional expression */ case class If(cond: Tree, thenp: Tree, elsep: Tree) extends TermTree @@ -716,6 +722,8 @@ trait Trees { self: Universe => } case Assign(lhs, rhs) => traverse(lhs); traverse(rhs) + case AssignOrNamedArg(lhs, rhs) => + traverse(lhs); traverse(rhs) case If(cond, thenp, elsep) => traverse(cond); traverse(thenp); traverse(elsep) case Match(selector, cases) => @@ -814,6 +822,7 @@ trait Trees { self: Universe => def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match def Return(tree: Tree, expr: Tree): Return @@ -876,6 +885,8 @@ trait Trees { self: Universe => new Function(vparams, body).copyAttrs(tree) def Assign(tree: Tree, lhs: Tree, rhs: Tree) = new Assign(lhs, rhs).copyAttrs(tree) + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = + new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = new If(cond, thenp, elsep).copyAttrs(tree) def Match(tree: Tree, selector: Tree, cases: List[CaseDef]) = @@ -1021,6 +1032,11 @@ trait Trees { self: Universe => if (lhs0 == lhs) && (rhs0 == rhs) => t case _ => treeCopy.Assign(tree, lhs, rhs) } + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ AssignOrNamedArg(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => treeCopy.AssignOrNamedArg(tree, lhs, rhs) + } def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match { case t @ If(cond0, thenp0, elsep0) if (cond0 == cond) && (thenp0 == thenp) && (elsep0 == elsep) => t @@ -1205,6 +1221,8 @@ trait Trees { self: Universe => } case Assign(lhs, rhs) => treeCopy.Assign(tree, transform(lhs), transform(rhs)) + case AssignOrNamedArg(lhs, rhs) => + treeCopy.AssignOrNamedArg(tree, transform(lhs), transform(rhs)) case If(cond, thenp, elsep) => treeCopy.If(tree, transform(cond), transform(thenp), transform(elsep)) case Match(selector, cases) => @@ -1372,6 +1390,8 @@ trait Trees { self: Universe => // vparams => body where vparams:List[ValDef] case Assign(lhs, rhs) => // lhs = rhs + case AssignOrNamedArg(lhs, rhs) => (eliminated by typer, resurrected by reifier) + // @annotation(lhs = rhs) case If(cond, thenp, elsep) => // if (cond) thenp else elsep case Match(selector, cases) => diff --git a/test/files/neg/reify_ann2a.check b/test/files/neg/reify_ann2a.check new file mode 100644 index 0000000000..2afe37e1d8 --- /dev/null +++ b/test/files/neg/reify_ann2a.check @@ -0,0 +1,4 @@ +reify_ann2a.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(immutable.this.List.apply[String]("1a")) which involves a symbol declared inside the block being reified + val tree = scala.reflect.Code.lift{ + ^ +one error found diff --git a/test/files/neg/reify_ann2a.scala b/test/files/neg/reify_ann2a.scala new file mode 100644 index 0000000000..071919eb76 --- /dev/null +++ b/test/files/neg/reify_ann2a.scala @@ -0,0 +1,30 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + class ann(bar: List[String]) extends StaticAnnotation + + @ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) { + @ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = { + @ann(bar=List("7a")) @ann(bar=List("7b")) val r = (x + 3): @ann(bar=List("8a")) @ann(bar=List("8b")) + val s = 4: Int @ann(bar=List("9a")) @ann(bar=List("9b")) + r + s + } + } + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/files/neg/reify_ann2b.check b/test/files/neg/reify_ann2b.check new file mode 100644 index 0000000000..ceb70689f1 --- /dev/null +++ b/test/files/neg/reify_ann2b.check @@ -0,0 +1,7 @@ +reify_ann2b.scala:10: error: inner classes cannot be classfile annotations + class ann(bar: String) extends ClassfileAnnotation + ^ +reify_ann2b.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(bar = "1a") which involves a symbol declared inside the block being reified + val tree = scala.reflect.Code.lift{ + ^ +two errors found diff --git a/test/files/neg/reify_ann2b.scala b/test/files/neg/reify_ann2b.scala new file mode 100644 index 0000000000..74273ad6ec --- /dev/null +++ b/test/files/neg/reify_ann2b.scala @@ -0,0 +1,30 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + class ann(bar: String) extends ClassfileAnnotation + + @ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) { + @ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = { + @ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b") + val s = 4: Int @ann(bar="9a") @ann(bar="9b") + r + s + } + } + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/files/run/reify_ann1a.check b/test/files/run/reify_ann1a.check new file mode 100644 index 0000000000..2822238706 --- /dev/null +++ b/test/files/run/reify_ann1a.check @@ -0,0 +1,30 @@ +{ + @new ann(immutable.this.List.apply[String]("1a")) @new ann(immutable.this.List.apply[String]("1b")) class C[@new ann(immutable.this.List.apply[String]("2a")) @new ann(immutable.this.List.apply[String]("2b")) T>: Nothing <: Any] extends Object with ScalaObject { + @new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) private[this] val x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b")) = _; + def (@new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b"))) = { + super.(); + () + }; + @new ann(immutable.this.List.apply[String]("5a")) @new ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = { + @new ann(immutable.this.List.apply[String]("7a")) @new ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.$plus(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a"))); + val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a"))); + r.$plus(s) + } + }; + () +} +{ + @ann(immutable.this.List.apply[String]("1a")) @ann(immutable.this.List.apply[String]("1b")) class C[@ann(immutable.this.List.apply[String]("2a")) @ann(immutable.this.List.apply[String]("2b")) T>: Nothing <: Any] extends Object with ScalaObject { + @ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) private[this] val x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a")) = _; + def (@ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a"))): C[T] = { + C.super.(); + () + }; + @ann(immutable.this.List.apply[String]("5a")) @ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = { + @ann(immutable.this.List.apply[String]("7a")) @ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.+(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a"))); + val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a"))); + r.+(s) + } + }; + () +} diff --git a/test/files/run/reify_ann1a.scala b/test/files/run/reify_ann1a.scala new file mode 100644 index 0000000000..933ea21b20 --- /dev/null +++ b/test/files/run/reify_ann1a.scala @@ -0,0 +1,30 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +class ann(bar: List[String]) extends StaticAnnotation + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + @ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) { + @ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = { + @ann(bar=List("7a")) @ann(bar=List("7b")) val r = (x + 3): @ann(bar=List("8a")) @ann(bar=List("8b")) + val s = 4: Int @ann(bar=List("9a")) @ann(bar=List("9b")) + r + s + } + } + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/files/run/reify_ann1b.check b/test/files/run/reify_ann1b.check new file mode 100644 index 0000000000..e240e1e0ce --- /dev/null +++ b/test/files/run/reify_ann1b.check @@ -0,0 +1,30 @@ +{ + @new ann(bar = "1a") @new ann(bar = "1b") class C[@new ann(bar = "2a") @new ann(bar = "2b") T>: Nothing <: Any] extends Object with ScalaObject { + @new ann(bar = "3a") @new ann(bar = "3b") private[this] val x: T @ann(bar = "4a") @ann(bar = "4b") = _; + def (@new ann(bar = "3a") @new ann(bar = "3b") x: T @ann(bar = "4a") @ann(bar = "4b")) = { + super.(); + () + }; + @new ann(bar = "5a") @new ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = { + @new ann(bar = "7a") @new ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.$plus(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a")); + val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a")); + r.$plus(s) + } + }; + () +} +{ + @ann(bar = "1a") @ann(bar = "1b") class C[@ann(bar = "2a") @ann(bar = "2b") T>: Nothing <: Any] extends Object with ScalaObject { + @ann(bar = "3a") @ann(bar = "3b") private[this] val x: T @ann(bar = "4b") @ann(bar = "4a") = _; + def (@ann(bar = "3a") @ann(bar = "3b") x: T @ann(bar = "4b") @ann(bar = "4a")): C[T] = { + C.super.(); + () + }; + @ann(bar = "5a") @ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = { + @ann(bar = "7a") @ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.+(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a")); + val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a")); + r.+(s) + } + }; + () +} diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala new file mode 100644 index 0000000000..53dfe08086 --- /dev/null +++ b/test/files/run/reify_ann1b.scala @@ -0,0 +1,30 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +class ann(bar: String) extends ClassfileAnnotation + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + @ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) { + @ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = { + @ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b") + val s = 4: Int @ann(bar="9a") @ann(bar="9b") + r + s + } + } + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/files/run/reify_classfileann_a.check b/test/files/run/reify_classfileann_a.check new file mode 100644 index 0000000000..1773263a94 --- /dev/null +++ b/test/files/run/reify_classfileann_a.check @@ -0,0 +1,18 @@ +{ + @new ann(bar = "1", quux = Array("2", "3"), baz = new ann(bar = "4")) class C extends Object with ScalaObject { + def () = { + super.(); + () + } + }; + () +} +{ + @ann(bar = "1", quux = ["2", "3"], baz = ann(bar = "4")) class C extends Object with ScalaObject { + def (): C = { + C.super.(); + () + } + }; + () +} diff --git a/test/files/run/reify_classfileann_a.scala b/test/files/run/reify_classfileann_a.scala new file mode 100644 index 0000000000..6bf4750bbc --- /dev/null +++ b/test/files/run/reify_classfileann_a.scala @@ -0,0 +1,24 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends ClassfileAnnotation + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + @ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4")) class C + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/files/run/t5224.check b/test/files/run/t5224.check new file mode 100644 index 0000000000..5bead91b36 --- /dev/null +++ b/test/files/run/t5224.check @@ -0,0 +1,9 @@ +{ + @new Foo(bar = "qwe") class C extends Object with ScalaObject { + def () = { + super.(); + () + } + }; + () +} diff --git a/test/files/run/t5224.scala b/test/files/run/t5224.scala new file mode 100644 index 0000000000..2226a69a05 --- /dev/null +++ b/test/files/run/t5224.scala @@ -0,0 +1,9 @@ +import scala.reflect._ +import scala.reflect.api._ + +class Foo(bar: String) extends ClassfileAnnotation + +object Test extends App { + val tree = scala.reflect.Code.lift{@Foo(bar = "qwe") class C}.tree + println(tree.toString) +} \ No newline at end of file diff --git a/test/files/run/t5225_1.check b/test/files/run/t5225_1.check new file mode 100644 index 0000000000..719da572c7 --- /dev/null +++ b/test/files/run/t5225_1.check @@ -0,0 +1,4 @@ +{ + @new transient() @new volatile() var x: Int = 2; + () +} diff --git a/test/files/run/t5225_1.scala b/test/files/run/t5225_1.scala new file mode 100644 index 0000000000..a655b7dd71 --- /dev/null +++ b/test/files/run/t5225_1.scala @@ -0,0 +1,7 @@ +import scala.reflect._ +import scala.reflect.api._ + +object Test extends App { + val tree = scala.reflect.Code.lift{@transient @volatile var x = 2}.tree + println(tree.toString) +} \ No newline at end of file diff --git a/test/files/run/t5225_2.check b/test/files/run/t5225_2.check new file mode 100644 index 0000000000..c4f6b4761e --- /dev/null +++ b/test/files/run/t5225_2.check @@ -0,0 +1,4 @@ +{ + def foo(@new cloneable() x: Int): String = ""; + () +} diff --git a/test/files/run/t5225_2.scala b/test/files/run/t5225_2.scala new file mode 100644 index 0000000000..65ea9b2f73 --- /dev/null +++ b/test/files/run/t5225_2.scala @@ -0,0 +1,7 @@ +import scala.reflect._ +import scala.reflect.api._ + +object Test extends App { + val tree = scala.reflect.Code.lift{def foo(@cloneable x: Int) = ""}.tree + println(tree.toString) +} \ No newline at end of file diff --git a/test/files/run/t5419.check b/test/files/run/t5419.check new file mode 100644 index 0000000000..7e6d739354 --- /dev/null +++ b/test/files/run/t5419.check @@ -0,0 +1 @@ +(5: Int(5) @Foo) diff --git a/test/files/run/t5419.scala b/test/files/run/t5419.scala new file mode 100644 index 0000000000..695786e5c4 --- /dev/null +++ b/test/files/run/t5419.scala @@ -0,0 +1,9 @@ +import scala.reflect._ +import scala.reflect.api._ + +class Foo extends StaticAnnotation + +object Test extends App { + val tree = scala.reflect.Code.lift{5: @Foo}.tree + println(tree.toString) +} \ No newline at end of file diff --git a/test/pending/run/reify_classfileann_b.check b/test/pending/run/reify_classfileann_b.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/reify_classfileann_b.scala b/test/pending/run/reify_classfileann_b.scala new file mode 100644 index 0000000000..b76dd8fc9f --- /dev/null +++ b/test/pending/run/reify_classfileann_b.scala @@ -0,0 +1,28 @@ +import scala.reflect._ +import scala.reflect.api._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends ClassfileAnnotation + +object Test extends App { + // test 1: reify + val tree = scala.reflect.Code.lift{ + class C { + def x: Int = { + 2: @ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4")) + } + } + }.tree + println(tree.toString) + + // test 2: import and typecheck + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + println(ttree.toString) + + // test 3: import and compile + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/pending/run/t5224.check b/test/pending/run/t5224.check deleted file mode 100644 index 2b920773c0..0000000000 --- a/test/pending/run/t5224.check +++ /dev/null @@ -1,9 +0,0 @@ -{ - @serializable class C extends Object with ScalaObject { - def () = { - super.(); - () - } - }; - () -} \ No newline at end of file diff --git a/test/pending/run/t5224.scala b/test/pending/run/t5224.scala deleted file mode 100644 index 865ce4bfe9..0000000000 --- a/test/pending/run/t5224.scala +++ /dev/null @@ -1,8 +0,0 @@ -import scala.reflect._ -import scala.reflect.api._ - -object Test extends App { - println(scala.reflect.Code.lift{ - @serializable class C - }.tree.toString) -} \ No newline at end of file diff --git a/test/pending/run/t5225_1.check b/test/pending/run/t5225_1.check deleted file mode 100644 index b29cd9c365..0000000000 --- a/test/pending/run/t5225_1.check +++ /dev/null @@ -1,4 +0,0 @@ -{ - @transient @volatile var x: Int = 2; - () -} \ No newline at end of file diff --git a/test/pending/run/t5225_1.scala b/test/pending/run/t5225_1.scala deleted file mode 100644 index 454502e810..0000000000 --- a/test/pending/run/t5225_1.scala +++ /dev/null @@ -1,8 +0,0 @@ -import scala.reflect._ -import scala.reflect.api._ - -object Test extends App { - println(scala.reflect.Code.lift{ - @transient @volatile var x = 2 - }.tree.toString) -} \ No newline at end of file diff --git a/test/pending/run/t5225_2.check b/test/pending/run/t5225_2.check deleted file mode 100644 index 88972fd27f..0000000000 --- a/test/pending/run/t5225_2.check +++ /dev/null @@ -1,4 +0,0 @@ -{ - def foo(@cloneable x: Int): String = ""; - () -} diff --git a/test/pending/run/t5225_2.scala b/test/pending/run/t5225_2.scala deleted file mode 100644 index 82bad0f353..0000000000 --- a/test/pending/run/t5225_2.scala +++ /dev/null @@ -1,8 +0,0 @@ -import scala.reflect._ -import scala.reflect.api._ - -object Test extends App { - println(scala.reflect.Code.lift{ - def foo(@cloneable x: Int) = "" - }.tree.toString) -} \ No newline at end of file -- cgit v1.2.3 From adb218d8d230b4713942f5b220d8cd0602995aae Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Mon, 13 Feb 2012 22:04:54 +0100 Subject: Fixes https://issues.scala-lang.org/browse/SI-5229 --- .../scala/reflect/internal/Importers.scala | 108 ++++++++++++--------- src/compiler/scala/reflect/runtime/ToolBoxes.scala | 11 ++- .../scala/reflect/runtime/TreeBuildUtil.scala | 20 +++- src/compiler/scala/reflect/runtime/Universe.scala | 2 +- src/compiler/scala/tools/nsc/ast/Reifiers.scala | 10 ++ src/compiler/scala/tools/nsc/ast/Trees.scala | 30 ++++-- test/files/run/reify_inner1.check | 1 + test/files/run/reify_inner1.scala | 22 +++++ test/files/run/reify_inner2.check | 1 + test/files/run/reify_inner2.scala | 22 +++++ test/files/run/reify_inner3.check | 1 + test/files/run/reify_inner3.scala | 22 +++++ test/files/run/reify_inner4.check | 1 + test/files/run/reify_inner4.scala | 22 +++++ test/files/run/t5229_1.check | 0 test/files/run/t5229_1.scala | 14 +++ test/files/run/t5229_2.check | 2 + test/files/run/t5229_2.scala | 19 ++++ test/files/run/t5270.check | 1 + test/files/run/t5270.scala | 26 +++++ test/pending/run/t5229_1.check | 0 test/pending/run/t5229_1.scala | 14 --- test/pending/run/t5229_1_nolift.scala | 1 - test/pending/run/t5229_2.check | 2 - test/pending/run/t5229_2.scala | 19 ---- test/pending/run/t5270.check | 1 - test/pending/run/t5270.scala | 26 ----- 27 files changed, 273 insertions(+), 125 deletions(-) create mode 100644 test/files/run/reify_inner1.check create mode 100644 test/files/run/reify_inner1.scala create mode 100644 test/files/run/reify_inner2.check create mode 100644 test/files/run/reify_inner2.scala create mode 100644 test/files/run/reify_inner3.check create mode 100644 test/files/run/reify_inner3.scala create mode 100644 test/files/run/reify_inner4.check create mode 100644 test/files/run/reify_inner4.scala create mode 100644 test/files/run/t5229_1.check create mode 100644 test/files/run/t5229_1.scala create mode 100644 test/files/run/t5229_2.check create mode 100644 test/files/run/t5229_2.scala create mode 100644 test/files/run/t5270.check create mode 100644 test/files/run/t5270.scala delete mode 100644 test/pending/run/t5229_1.check delete mode 100644 test/pending/run/t5229_1.scala delete mode 100644 test/pending/run/t5229_1_nolift.scala delete mode 100644 test/pending/run/t5229_2.check delete mode 100644 test/pending/run/t5229_2.scala delete mode 100644 test/pending/run/t5270.check delete mode 100644 test/pending/run/t5270.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 63efaede07..c232e3b7c1 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -32,8 +32,11 @@ trait Importers { self: SymbolTable => def importPosition(pos: from.Position): Position = NoPosition - def importSymbol(sym: from.Symbol): Symbol = { + def importSymbol(sym0: from.Symbol): Symbol = { def doImport(sym: from.Symbol): Symbol = { + if (symMap.contains(sym)) + return symMap(sym) + val myowner = importSymbol(sym.owner) val mypos = importPosition(sym.pos) val myname = importName(sym.name).toTermName @@ -47,7 +50,7 @@ trait Importers { self: SymbolTable => case x: from.MethodSymbol => linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol) case x: from.ModuleSymbol => - linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, doImport) + linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) case x: from.FreeVar => newFreeVar(importName(x.name).toTermName, importType(x.tpe), x.value, myflags) case x: from.TermSymbol => @@ -59,14 +62,14 @@ trait Importers { self: SymbolTable => case y: from.Symbol => importSymbol(y) } myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) - /* - case x: from.ModuleClassSymbol => - val mysym = new ModuleClassSymbol(myowner, mypos, myname.toTypeName) - mysym.sourceModule = importSymbol(x.sourceModule) - mysym -*/ + case x: from.ModuleClassSymbol => + val mysym = myowner.newModuleClassSymbol(myname.toTypeName, mypos, myflags) + symMap(x) = mysym + mysym.sourceModule = importSymbol(x.sourceModule) + mysym case x: from.ClassSymbol => val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags) + symMap(x) = mysym if (sym.thisSym != sym) { mysym.typeOfThis = importType(sym.typeOfThis) mysym.thisSym.name = importName(sym.thisSym.name) @@ -78,7 +81,7 @@ trait Importers { self: SymbolTable => symMap(sym) = mysym mysym setFlag Flags.LOCKED mysym setInfo { - val mytypeParams = sym.typeParams map doImport + val mytypeParams = sym.typeParams map importSymbol new LazyPolyType(mytypeParams) { override def complete(s: Symbol) { val result = sym.info match { @@ -94,6 +97,7 @@ trait Importers { self: SymbolTable => } // end doImport def importOrRelink: Symbol = { + val sym = sym0 // makes sym visible in the debugger if (sym == null) null else if (sym == from.NoSymbol) @@ -101,51 +105,61 @@ trait Importers { self: SymbolTable => else if (sym.isRoot) definitions.RootClass else { - val myowner = importSymbol(sym.owner) - val myname = importName(sym.name) - if (sym.isModuleClass) { - assert(sym.sourceModule != NoSymbol, sym) - val mymodule = importSymbol(sym.sourceModule) - assert(mymodule != NoSymbol, sym) - assert(mymodule.moduleClass != NoSymbol, mymodule) - mymodule.moduleClass - } else if (myowner.isClass && !myowner.isRefinementClass && !(myowner hasFlag Flags.LOCKED) && sym.owner.info.decl(sym.name).exists) { - // symbol is in class scope, try to find equivalent one in local scope - if (sym.isOverloaded) - myowner.newOverloaded(myowner.thisType, sym.alternatives map importSymbol) - else { - var existing: Symbol = myowner.info.decl(myname) - if (existing.isOverloaded) { - existing = - if (sym.isMethod) { - val localCopy = doImport(sym) - existing filter (_.tpe matches localCopy.tpe) - } else { - existing filter (!_.isMethod) - } - assert(!existing.isOverloaded, - "import failure: cannot determine unique overloaded method alternative from\n "+ - (existing.alternatives map (_.defString) mkString "\n")+"\n that matches "+sym+":"+sym.tpe) + val name = sym.name + val owner = sym.owner + var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType + var existing = scope.decl(name) + if (sym.isPackageClass || sym.isModuleClass) existing = existing.moduleClass + if (!existing.exists) scope = from.NoType + + val myname = importName(name) + val myowner = importSymbol(owner) + val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType + var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods + if (sym.isPackageClass || sym.isModuleClass) myexisting = importSymbol(sym.sourceModule).moduleClass + if (!sym.isOverloaded && myexisting.isOverloaded) { + myexisting = + if (sym.isMethod) { + val localCopy = doImport(sym) + myexisting filter (_.tpe matches localCopy.tpe) + } else { + myexisting filter (!_.isMethod) } - if (existing != NoSymbol) existing - else { + assert(!myexisting.isOverloaded, + "import failure: cannot determine unique overloaded method alternative from\n "+ + (myexisting.alternatives map (_.defString) mkString "\n")+"\n that matches "+sym+":"+sym.tpe) + } + + val mysym = { + if (sym.isOverloaded) { + myowner.newOverloaded(myowner.thisType, sym.alternatives map importSymbol) + } else if (sym.isTypeParameter && sym.paramPos >= 0 && !(myowner hasFlag Flags.LOCKED)) { + assert(myowner.typeParams.length > sym.paramPos, + "import failure: cannot determine parameter "+sym+" (#"+sym.paramPos+") in "+ + myowner+typeParamsString(myowner.rawInfo)+"\n original symbol was: "+ + sym.owner+from.typeParamsString(sym.owner.info)) + myowner.typeParams(sym.paramPos) + } else { + if (myexisting != NoSymbol) { + myexisting + } else { val mysym = doImport(sym) - assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+existing) - myowner.info.decls enter mysym + + if (myscope != NoType) { + assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+myexisting) + myowner.info.decls enter mysym + } + mysym } } - } else if (sym.isTypeParameter && sym.paramPos >= 0 && !(myowner hasFlag Flags.LOCKED)) { - assert(myowner.typeParams.length > sym.paramPos, - "import failure: cannot determine parameter "+sym+" (#"+sym.paramPos+") in "+ - myowner+typeParamsString(myowner.rawInfo)+"\n original symbol was: "+ - sym.owner+from.typeParamsString(sym.owner.info)) - myowner.typeParams(sym.paramPos) - } else - doImport(sym) + } + + mysym } } // end importOrRelink + val sym = sym0 if (symMap contains sym) { symMap(sym) } else { @@ -410,4 +424,4 @@ trait Importers { self: SymbolTable => case _ => constant.value }) } -} +} \ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index c09022e535..880c68eaa0 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -44,11 +44,11 @@ trait ToolBoxes extends { self: Universe => // !!! Why is this is in the empty package? If it's only to make // it inaccessible then please put it somewhere designed for that // rather than polluting the empty package with synthetics. - trace("typing: ")(showAttributed(tree)) + trace("typing: ")(showAttributed(tree, true, true, settings.Yshowsymkinds.value)) val ownerClass = EmptyPackageClass.newClassWithInfo(newTypeName(""), List(ObjectClass.tpe), newScope) val owner = ownerClass.newLocalDummy(tree.pos) val ttree = typer.atOwner(tree, owner).typed(tree, analyzer.EXPRmode, pt) - trace("typed: ")(showAttributed(ttree)) + trace("typed: ")(showAttributed(ttree, true, true, settings.Yshowsymkinds.value)) ttree } @@ -78,9 +78,9 @@ trait ToolBoxes extends { self: Universe => List(List()), List(methdef), NoPosition)) - trace("wrapped: ")(showAttributed(moduledef)) + trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value)) val cleanedUp = resetLocalAttrs(moduledef) - trace("cleaned up: ")(showAttributed(cleanedUp)) + trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value)) cleanedUp } @@ -192,7 +192,8 @@ trait ToolBoxes extends { self: Universe => def typeCheck(tree: rm.Tree, expectedType: rm.Type): rm.Tree = { if (compiler.settings.verbose.value) println("typing "+tree+", pt = "+expectedType) val ttree = importAndTypeCheck(tree, expectedType) - exporter.importTree(ttree).asInstanceOf[rm.Tree] + val ettree = exporter.importTree(ttree).asInstanceOf[rm.Tree] + ettree } def typeCheck(tree: rm.Tree): rm.Tree = diff --git a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala index 275c85f332..0b54843344 100644 --- a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala +++ b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala @@ -2,9 +2,23 @@ package scala.reflect package runtime trait TreeBuildUtil extends Universe with api.TreeBuildUtil { - def staticClass(fullname: String): Symbol = definitions.getRequiredClass(fullname) - def staticModule(fullname: String): Symbol = definitions.getRequiredModule(fullname) - def thisModuleType(fullname: String) = staticModule(fullname).moduleClass.thisType + def staticClass(fullname: String): Symbol = { + val sym = definitions.getRequiredClass(fullname) + sym.initialize + sym + } + + def staticModule(fullname: String): Symbol = { + val sym = definitions.getRequiredModule(fullname) + sym.initialize + sym + } + + def thisModuleType(fullname: String) = { + val sym = staticModule(fullname).moduleClass + sym.initialize + sym.thisType + } /** Selects type symbol with given name from the defined members of prefix type */ diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala index c786bb86c5..700f819226 100644 --- a/src/compiler/scala/reflect/runtime/Universe.scala +++ b/src/compiler/scala/reflect/runtime/Universe.scala @@ -16,7 +16,7 @@ class Universe extends SymbolTable { val gen = new TreeGen { val global: Universe.this.type = Universe.this } - def settings = new Settings + lazy val settings = new Settings def forInteractive = false def forScaladoc = false diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index b82d78b786..91d5d2bf4a 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -325,6 +325,16 @@ trait Reifiers { self: Global => // registerReifiableSymbol(tree.symbol) boundSyms += tree.symbol + if (tree.symbol.sourceModule != NoSymbol) { + if (reifyDebug) println("boundSym (sourceModule): " + tree.symbol.sourceModule) + boundSyms += tree.symbol.sourceModule + } + + if (tree.symbol.moduleClass != NoSymbol) { + if (reifyDebug) println("boundSym (moduleClass): " + tree.symbol.moduleClass) + boundSyms += tree.symbol.moduleClass + } + val prefix = tree.productPrefix val elements = (tree.productIterator map { // annotations exist in two flavors: diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 9e304a0eb5..855b55bb5e 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -251,12 +251,27 @@ trait Trees extends reflect.internal.Trees { self: Global => * (bq:) This transformer has mutable state and should be discarded after use */ private class ResetAttrs(localOnly: Boolean) { + val debug = settings.debug.value + val trace = scala.tools.nsc.util.trace when debug + val locals = util.HashSet[Symbol](8) + val orderedLocals = collection.mutable.ListBuffer[Symbol]() + def registerLocal(sym: Symbol) { + if (sym != null && sym != NoSymbol) { + if (debug && !(locals contains sym)) orderedLocals append sym + locals addEntry sym + } + } class MarkLocals extends self.Traverser { - def markLocal(tree: Tree) = - if (tree.symbol != null && tree.symbol != NoSymbol) - locals addEntry tree.symbol + def markLocal(tree: Tree) { + if (tree.symbol != null && tree.symbol != NoSymbol) { + val sym = tree.symbol + registerLocal(sym) + registerLocal(sym.sourceModule) + registerLocal(sym.moduleClass) + } + } override def traverse(tree: Tree) = { tree match { @@ -301,9 +316,12 @@ trait Trees extends reflect.internal.Trees { self: Global => def transform[T <: Tree](x: T): T = { new MarkLocals().traverse(x) - val trace = scala.tools.nsc.util.trace when settings.debug.value - val eoln = System.getProperty("line.separator") - trace("locals (%d total): %n".format(locals.size))(locals.toList map {" " + _} mkString eoln) + if (debug) { + assert(locals.size == orderedLocals.size) + val eoln = System.getProperty("line.separator") + val msg = orderedLocals.toList filter {_ != NoSymbol} map {" " + _} mkString eoln + trace("locals (%d total): %n".format(orderedLocals.size))(msg) + } val x1 = new Transformer().transform(x) assert(x.getClass isInstance x1) diff --git a/test/files/run/reify_inner1.check b/test/files/run/reify_inner1.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/reify_inner1.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/reify_inner1.scala b/test/files/run/reify_inner1.scala new file mode 100644 index 0000000000..69931198e0 --- /dev/null +++ b/test/files/run/reify_inner1.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { + class D { + val x = 2 + } + } + + val outer = new C() + val inner = new outer.D() + println(inner.x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/reify_inner2.check b/test/files/run/reify_inner2.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/reify_inner2.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/reify_inner2.scala b/test/files/run/reify_inner2.scala new file mode 100644 index 0000000000..0f12fd472a --- /dev/null +++ b/test/files/run/reify_inner2.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { + object D { + val x = 2 + } + } + + val outer = new C() + val inner = outer.D + println(inner.x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/reify_inner3.check b/test/files/run/reify_inner3.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/reify_inner3.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/reify_inner3.scala b/test/files/run/reify_inner3.scala new file mode 100644 index 0000000000..6b97b42b34 --- /dev/null +++ b/test/files/run/reify_inner3.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C { + class D { + val x = 2 + } + } + + val outer = C + val inner = new outer.D + println(inner.x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/reify_inner4.check b/test/files/run/reify_inner4.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/reify_inner4.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/reify_inner4.scala b/test/files/run/reify_inner4.scala new file mode 100644 index 0000000000..de8c973b09 --- /dev/null +++ b/test/files/run/reify_inner4.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C { + object D { + val x = 2 + } + } + + val outer = C + val inner = outer.D + println(inner.x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5229_1.check b/test/files/run/t5229_1.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/t5229_1.scala b/test/files/run/t5229_1.scala new file mode 100644 index 0000000000..1d7bf0590b --- /dev/null +++ b/test/files/run/t5229_1.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5229_2.check b/test/files/run/t5229_2.check new file mode 100644 index 0000000000..5db6ec9b38 --- /dev/null +++ b/test/files/run/t5229_2.check @@ -0,0 +1,2 @@ +2 +evaluated = null diff --git a/test/files/run/t5229_2.scala b/test/files/run/t5229_2.scala new file mode 100644 index 0000000000..67be7328a6 --- /dev/null +++ b/test/files/run/t5229_2.scala @@ -0,0 +1,19 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C { + val x = 2 + } + + println(C.x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + val evaluated = toolbox.runExpr(ttree) + println("evaluated = " + evaluated) +} diff --git a/test/files/run/t5270.check b/test/files/run/t5270.check new file mode 100644 index 0000000000..08839f6bb2 --- /dev/null +++ b/test/files/run/t5270.check @@ -0,0 +1 @@ +200 diff --git a/test/files/run/t5270.scala b/test/files/run/t5270.scala new file mode 100644 index 0000000000..10f79790b0 --- /dev/null +++ b/test/files/run/t5270.scala @@ -0,0 +1,26 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class Y { + def y = 100 + } + + trait Z { this: Y => + val z = 2 * y + } + + class X extends Y with Z { + def println() = Predef.println(z) + } + + new X().println() + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5229_1.check b/test/pending/run/t5229_1.check deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/pending/run/t5229_1.scala b/test/pending/run/t5229_1.scala deleted file mode 100644 index 1d7bf0590b..0000000000 --- a/test/pending/run/t5229_1.scala +++ /dev/null @@ -1,14 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - object C - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5229_1_nolift.scala b/test/pending/run/t5229_1_nolift.scala deleted file mode 100644 index 33855d2e4f..0000000000 --- a/test/pending/run/t5229_1_nolift.scala +++ /dev/null @@ -1 +0,0 @@ -object C diff --git a/test/pending/run/t5229_2.check b/test/pending/run/t5229_2.check deleted file mode 100644 index 5db6ec9b38..0000000000 --- a/test/pending/run/t5229_2.check +++ /dev/null @@ -1,2 +0,0 @@ -2 -evaluated = null diff --git a/test/pending/run/t5229_2.scala b/test/pending/run/t5229_2.scala deleted file mode 100644 index 67be7328a6..0000000000 --- a/test/pending/run/t5229_2.scala +++ /dev/null @@ -1,19 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - object C { - val x = 2 - } - - println(C.x) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) - println("evaluated = " + evaluated) -} diff --git a/test/pending/run/t5270.check b/test/pending/run/t5270.check deleted file mode 100644 index 08839f6bb2..0000000000 --- a/test/pending/run/t5270.check +++ /dev/null @@ -1 +0,0 @@ -200 diff --git a/test/pending/run/t5270.scala b/test/pending/run/t5270.scala deleted file mode 100644 index 10f79790b0..0000000000 --- a/test/pending/run/t5270.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - class Y { - def y = 100 - } - - trait Z { this: Y => - val z = 2 * y - } - - class X extends Y with Z { - def println() = Predef.println(z) - } - - new X().println() - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} -- cgit v1.2.3 From f6174691647bb1fae7e86d53790b1e540b890755 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 14 Feb 2012 00:05:18 +0100 Subject: Preprocessing for reifees --- src/compiler/scala/tools/nsc/ast/Reifiers.scala | 149 +++++++++++++++++++----- test/files/run/t5271_1.check | 0 test/files/run/t5271_1.scala | 14 +++ test/files/run/t5271_2.check | 1 + test/files/run/t5271_2.scala | 16 +++ test/files/run/t5271_3.check | 1 + test/files/run/t5271_3.scala | 17 +++ test/files/run/t5271_4.check | 0 test/files/run/t5271_4.scala | 14 +++ test/files/run/t5273_1.check | 1 + test/files/run/t5273_1.scala | 17 +++ test/files/run/t5273_2a.check | 1 + test/files/run/t5273_2a.scala | 15 +++ test/files/run/t5273_2b.check | 1 + test/files/run/t5273_2b.scala | 16 +++ test/files/run/t5276_1a.check | 1 + test/files/run/t5276_1a.scala | 15 +++ test/files/run/t5276_1b.check | 1 + test/files/run/t5276_1b.scala | 15 +++ test/files/run/t5276_2a.check | 1 + test/files/run/t5276_2a.scala | 18 +++ test/files/run/t5276_2b.check | 1 + test/files/run/t5276_2b.scala | 19 +++ test/pending/run/t5271_1.check | 0 test/pending/run/t5271_1.scala | 14 --- test/pending/run/t5271_2.check | 1 - test/pending/run/t5271_2.scala | 16 --- test/pending/run/t5273_1.check | 1 - test/pending/run/t5273_1.scala | 16 --- test/pending/run/t5273_2.check | 1 - test/pending/run/t5273_2.scala | 17 --- test/pending/run/t5276.check | 1 - test/pending/run/t5276.scala | 15 --- 33 files changed, 303 insertions(+), 113 deletions(-) create mode 100644 test/files/run/t5271_1.check create mode 100644 test/files/run/t5271_1.scala create mode 100644 test/files/run/t5271_2.check create mode 100644 test/files/run/t5271_2.scala create mode 100644 test/files/run/t5271_3.check create mode 100644 test/files/run/t5271_3.scala create mode 100644 test/files/run/t5271_4.check create mode 100644 test/files/run/t5271_4.scala create mode 100644 test/files/run/t5273_1.check create mode 100644 test/files/run/t5273_1.scala create mode 100644 test/files/run/t5273_2a.check create mode 100644 test/files/run/t5273_2a.scala create mode 100644 test/files/run/t5273_2b.check create mode 100644 test/files/run/t5273_2b.scala create mode 100644 test/files/run/t5276_1a.check create mode 100644 test/files/run/t5276_1a.scala create mode 100644 test/files/run/t5276_1b.check create mode 100644 test/files/run/t5276_1b.scala create mode 100644 test/files/run/t5276_2a.check create mode 100644 test/files/run/t5276_2a.scala create mode 100644 test/files/run/t5276_2b.check create mode 100644 test/files/run/t5276_2b.scala delete mode 100644 test/pending/run/t5271_1.check delete mode 100644 test/pending/run/t5271_1.scala delete mode 100644 test/pending/run/t5271_2.check delete mode 100644 test/pending/run/t5271_2.scala delete mode 100644 test/pending/run/t5273_1.check delete mode 100644 test/pending/run/t5273_1.scala delete mode 100644 test/pending/run/t5273_2.check delete mode 100644 test/pending/run/t5273_2.scala delete mode 100644 test/pending/run/t5276.check delete mode 100644 test/pending/run/t5276.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala index 91d5d2bf4a..21e075950f 100644 --- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -8,6 +8,7 @@ package ast import symtab._ import Flags._ +import scala.reflect.api.Modifier._ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer import scala.tools.nsc.util.FreshNameCreator @@ -289,10 +290,102 @@ trait Reifiers { self: Global => var reifySymbols = false var reifyTypes = false + /** Preprocess a tree before reification */ + private def trimTree(tree: Tree): Tree = { + def trimSyntheticCaseClassMembers(deff: Tree, stats: List[Tree]) = { + var stats1 = stats filterNot (stat => stat.isDef && { + if (stat.symbol.isCaseAccessorMethod && reifyDebug) println("discarding case accessor method: " + stat) + stat.symbol.isCaseAccessorMethod + }) + stats1 = stats1 filterNot (memberDef => memberDef.isDef && { + val isSynthetic = memberDef.symbol.isSynthetic + // @xeno.by: this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass) + // that's why I replace the check with an assumption that all synthetic members are, in fact, generated of case classes +// val isCaseMember = deff.symbol.isCaseClass || deff.symbol.companionClass.isCaseClass + val isCaseMember = true + if (isSynthetic && isCaseMember && reifyDebug) println("discarding case class synthetic def: " + memberDef) + isSynthetic && isCaseMember + }) + stats1 = stats1 map { + case valdef @ ValDef(mods, name, tpt, rhs) if valdef.symbol.isCaseAccessor => + if (reifyDebug) println("resetting visibility of case accessor field: " + valdef) + val Modifiers(flags, privateWithin, annotations) = mods + val flags1 = flags & ~Flags.LOCAL & ~Flags.PRIVATE + val mods1 = Modifiers(flags1, privateWithin, annotations) + ValDef(mods1, name, tpt, rhs).copyAttrs(valdef) + case stat => + stat + } + stats1 + } + + def trimSyntheticCaseClassCompanions(stats: List[Tree]) = + stats diff (stats collect { case moddef: ModuleDef => moddef } filter (moddef => { + val isSynthetic = moddef.symbol.isSynthetic + // @xeno.by: this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass) + // that's why I replace the check with an assumption that all synthetic modules are, in fact, companions of case classes +// val isCaseCompanion = moddef.symbol.companionClass.isCaseClass + val isCaseCompanion = true + // @xeno.by: we also have to do this ugly hack for the very same reason described above + // normally this sort of stuff is performed in reifyTree, which binds related symbols, however, local companions will be out of its reach + if (reifyDebug) println("boundSym: "+ moddef.symbol) + boundSyms += moddef.symbol + if (isSynthetic && isCaseCompanion && reifyDebug) println("discarding synthetic case class companion: " + moddef) + isSynthetic && isCaseCompanion + })) + + tree match { + case tree if tree.isErroneous => + tree + case ta @ TypeApply(hk, ts) => + def isErased(tt: TypeTree) = tt.tpe != null && definedInLiftedCode(tt.tpe) && tt.original == null + val discard = ts collect { case tt: TypeTree => tt } exists isErased + if (reifyDebug && discard) println("discarding TypeApply: " + tree) + if (discard) hk else ta + case classDef @ ClassDef(mods, name, params, impl) => + val Template(parents, self, body) = impl + val body1 = trimSyntheticCaseClassMembers(classDef, body) + var impl1 = Template(parents, self, body1).copyAttrs(impl) + ClassDef(mods, name, params, impl1).copyAttrs(classDef) + case moduledef @ ModuleDef(mods, name, impl) => + val Template(parents, self, body) = impl + val body1 = trimSyntheticCaseClassMembers(moduledef, body) + var impl1 = Template(parents, self, body1).copyAttrs(impl) + ModuleDef(mods, name, impl1).copyAttrs(moduledef) + case template @ Template(parents, self, body) => + val body1 = trimSyntheticCaseClassCompanions(body) + Template(parents, self, body1).copyAttrs(template) + case block @ Block(stats, expr) => + val stats1 = trimSyntheticCaseClassCompanions(stats) + Block(stats1, expr).copyAttrs(block) + case valdef @ ValDef(mods, name, tpt, rhs) if valdef.symbol.isLazy => + if (reifyDebug) println("dropping $lzy in lazy val's name: " + tree) + val name1 = if (name endsWith nme.LAZY_LOCAL) name dropRight nme.LAZY_LOCAL.length else name + ValDef(mods, name1, tpt, rhs).copyAttrs(valdef) + case unapply @ UnApply(fun, args) => + def extractExtractor(tree: Tree): Tree = { + val Apply(fun, args) = tree + args match { + case List(Ident(special)) if special == nme.SELECTOR_DUMMY => + val Select(extractor, flavor) = fun + assert(flavor == nme.unapply || flavor == nme.unapplySeq) + extractor + case _ => + extractExtractor(fun) + } + } + + if (reifyDebug) println("unapplying unapply: " + tree) + val fun1 = extractExtractor(fun) + Apply(fun1, args).copyAttrs(unapply) + case _ => + tree + } + } + /** Reify a tree */ - private def reifyTree(tree: Tree): Tree = { - def reifyDefault(tree: Tree) = - reifyProduct(tree) + private def reifyTree(tree0: Tree): Tree = { + val tree = trimTree(tree0) var rtree = tree match { case tree if tree.isErroneous => @@ -311,29 +404,24 @@ trait Reifiers { self: Global => } else reifyFree(tree) case tt: TypeTree if (tt.tpe != null) => reifyTypeTree(tt) - case ta @ TypeApply(hk, ts) => - def isErased(tt: TypeTree) = tt.tpe != null && definedInLiftedCode(tt.tpe) && tt.original == null - val discard = ts collect { case tt: TypeTree => tt } exists isErased - if (reifyDebug && discard) println("discarding TypeApply: " + tree) - if (discard) reifyTree(hk) else reifyDefault(ta) case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) => CannotReifyClassOfBoundType(tree, tpe) case Literal(constant @ Constant(sym: Symbol)) if boundSyms contains sym => CannotReifyClassOfBoundEnum(tree, constant.tpe) case tree if tree.isDef => if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe)))) - // registerReifiableSymbol(tree.symbol) boundSyms += tree.symbol - if (tree.symbol.sourceModule != NoSymbol) { - if (reifyDebug) println("boundSym (sourceModule): " + tree.symbol.sourceModule) - boundSyms += tree.symbol.sourceModule - } - - if (tree.symbol.moduleClass != NoSymbol) { - if (reifyDebug) println("boundSym (moduleClass): " + tree.symbol.moduleClass) - boundSyms += tree.symbol.moduleClass - } + bindRelatedSymbol(tree.symbol.sourceModule, "sourceModule") + bindRelatedSymbol(tree.symbol.moduleClass, "moduleClass") + bindRelatedSymbol(tree.symbol.companionClass, "companionClass") + bindRelatedSymbol(tree.symbol.companionModule, "companionModule") + Some(tree.symbol) collect { case termSymbol: TermSymbol => bindRelatedSymbol(termSymbol.referenced, "referenced") } + def bindRelatedSymbol(related: Symbol, name: String): Unit = + if (related != null && related != NoSymbol) { + if (reifyDebug) println("boundSym (" + name + "): " + related) + boundSyms += related + } val prefix = tree.productPrefix val elements = (tree.productIterator map { @@ -354,7 +442,7 @@ trait Reifiers { self: Global => }).toList reifyProduct(prefix, elements) case _ => - reifyDefault(tree) + reifyProduct(tree) } // usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation @@ -396,10 +484,8 @@ trait Reifiers { self: Global => * * This workaround worked surprisingly well and allowed me to fix several important reification bugs, until the abstraction has leaked. * Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees. - * To the moment I know two such situations: - * 1) Unapplies: https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057 - * 2) Annotations: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless - * 3) + * To the moment I know only one such situation: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless. + * This is laboriously worked around in the code below. I hope this will be the only workaround in this department. */ private def reifyTypeTree(tt: TypeTree): Tree = { if (definedInLiftedCode(tt.tpe)) { @@ -441,14 +527,15 @@ trait Reifiers { self: Global => } } else { var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe)) - // @xeno.by: originals get typechecked during subsequent reflective compilation, which leads to subtle bugs - // https://issues.scala-lang.org/browse/SI-5273?focusedCommentId=56057#comment-56057 - // until this is somehow sorted out, I disable reification of originals - // if (tt.original != null) { - // val setOriginal = Select(rtt, newTermName("setOriginal")) - // val reifiedOriginal = reify(tt.original) - // rtt = Apply(setOriginal, List(reifiedOriginal)) - // } + // @xeno.by: temporarily disabling reification of originals + // subsequent reflective compilation will try to typecheck them + // and this means that the reifier has to do additional efforts to ensure that this will succeed + // additional efforts + no clear benefit = will be implemented later +// if (tt.original != null) { +// val setOriginal = Select(rtt, newTermName("setOriginal")) +// val reifiedOriginal = reify(tt.original) +// rtt = Apply(setOriginal, List(reifiedOriginal)) +// } rtt } } diff --git a/test/files/run/t5271_1.check b/test/files/run/t5271_1.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/t5271_1.scala b/test/files/run/t5271_1.scala new file mode 100644 index 0000000000..5f10e64528 --- /dev/null +++ b/test/files/run/t5271_1.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5271_2.check b/test/files/run/t5271_2.check new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/test/files/run/t5271_2.check @@ -0,0 +1 @@ +4 diff --git a/test/files/run/t5271_2.scala b/test/files/run/t5271_2.scala new file mode 100644 index 0000000000..71967c04ed --- /dev/null +++ b/test/files/run/t5271_2.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + val c = C(2, 2) + println(c.foo * c.bar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5271_3.check b/test/files/run/t5271_3.check new file mode 100644 index 0000000000..f32a5804e2 --- /dev/null +++ b/test/files/run/t5271_3.check @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/test/files/run/t5271_3.scala b/test/files/run/t5271_3.scala new file mode 100644 index 0000000000..bfa116c691 --- /dev/null +++ b/test/files/run/t5271_3.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C { def qwe = 4 } + case class C(foo: Int, bar: Int) + val c = C(2, 2) + println(c.foo * c.bar == C.qwe) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5271_4.check b/test/files/run/t5271_4.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/t5271_4.scala b/test/files/run/t5271_4.scala new file mode 100644 index 0000000000..e5e16033e8 --- /dev/null +++ b/test/files/run/t5271_4.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case object C + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5273_1.check b/test/files/run/t5273_1.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/files/run/t5273_1.check @@ -0,0 +1 @@ +2 diff --git a/test/files/run/t5273_1.scala b/test/files/run/t5273_1.scala new file mode 100644 index 0000000000..1175881c9f --- /dev/null +++ b/test/files/run/t5273_1.scala @@ -0,0 +1,17 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + List(1, 2, 3) match { + case foo :: bar :: _ => println(foo * bar) + case _ => println("this is getting out of hand!") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5273_2a.check b/test/files/run/t5273_2a.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/t5273_2a.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/t5273_2a.scala b/test/files/run/t5273_2a.scala new file mode 100644 index 0000000000..12ddbb280a --- /dev/null +++ b/test/files/run/t5273_2a.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val foo :: bar :: _ = List(1, 2, 3) + println(foo * bar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5273_2b.check b/test/files/run/t5273_2b.check new file mode 100644 index 0000000000..c551774ca5 --- /dev/null +++ b/test/files/run/t5273_2b.check @@ -0,0 +1 @@ +name = American Dollar, shortname = USD, value = 2,8567 diff --git a/test/files/run/t5273_2b.scala b/test/files/run/t5273_2b.scala new file mode 100644 index 0000000000..8b75084463 --- /dev/null +++ b/test/files/run/t5273_2b.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val RegexParser = """(.*) \d+([A-Z]+) \| (.*) \|.*""".r + val RegexParser(name, shortname, value) = "American Dollar 1USD | 2,8567 | sometext" + println("name = %s, shortname = %s, value = %s".format(name, shortname, value)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5276_1a.check b/test/files/run/t5276_1a.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/t5276_1a.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/t5276_1a.scala b/test/files/run/t5276_1a.scala new file mode 100644 index 0000000000..c8afbba19e --- /dev/null +++ b/test/files/run/t5276_1a.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + lazy val x = 2 + println(x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5276_1b.check b/test/files/run/t5276_1b.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/t5276_1b.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/t5276_1b.scala b/test/files/run/t5276_1b.scala new file mode 100644 index 0000000000..31582201fb --- /dev/null +++ b/test/files/run/t5276_1b.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + implicit lazy val x = 2 + implicitly[Int] + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5276_2a.check b/test/files/run/t5276_2a.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/t5276_2a.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/t5276_2a.scala b/test/files/run/t5276_2a.scala new file mode 100644 index 0000000000..179c14b739 --- /dev/null +++ b/test/files/run/t5276_2a.scala @@ -0,0 +1,18 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { + lazy val x = 2 + } + + println(new C().x) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/files/run/t5276_2b.check b/test/files/run/t5276_2b.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/files/run/t5276_2b.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/files/run/t5276_2b.scala b/test/files/run/t5276_2b.scala new file mode 100644 index 0000000000..6fe2873fef --- /dev/null +++ b/test/files/run/t5276_2b.scala @@ -0,0 +1,19 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class C { + implicit lazy val x = 2 + def y = implicitly[Int] + } + + println(new C().y) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} diff --git a/test/pending/run/t5271_1.check b/test/pending/run/t5271_1.check deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/pending/run/t5271_1.scala b/test/pending/run/t5271_1.scala deleted file mode 100644 index 5f10e64528..0000000000 --- a/test/pending/run/t5271_1.scala +++ /dev/null @@ -1,14 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - case class C(foo: Int, bar: Int) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5271_2.check b/test/pending/run/t5271_2.check deleted file mode 100644 index b8626c4cff..0000000000 --- a/test/pending/run/t5271_2.check +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/test/pending/run/t5271_2.scala b/test/pending/run/t5271_2.scala deleted file mode 100644 index 71967c04ed..0000000000 --- a/test/pending/run/t5271_2.scala +++ /dev/null @@ -1,16 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - case class C(foo: Int, bar: Int) - val c = C(2, 2) - println(c.foo * c.bar) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5273_1.check b/test/pending/run/t5273_1.check deleted file mode 100644 index c551774ca5..0000000000 --- a/test/pending/run/t5273_1.check +++ /dev/null @@ -1 +0,0 @@ -name = American Dollar, shortname = USD, value = 2,8567 diff --git a/test/pending/run/t5273_1.scala b/test/pending/run/t5273_1.scala deleted file mode 100644 index 8b75084463..0000000000 --- a/test/pending/run/t5273_1.scala +++ /dev/null @@ -1,16 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - val RegexParser = """(.*) \d+([A-Z]+) \| (.*) \|.*""".r - val RegexParser(name, shortname, value) = "American Dollar 1USD | 2,8567 | sometext" - println("name = %s, shortname = %s, value = %s".format(name, shortname, value)) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5273_2.check b/test/pending/run/t5273_2.check deleted file mode 100644 index 0cfbf08886..0000000000 --- a/test/pending/run/t5273_2.check +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/test/pending/run/t5273_2.scala b/test/pending/run/t5273_2.scala deleted file mode 100644 index 1175881c9f..0000000000 --- a/test/pending/run/t5273_2.scala +++ /dev/null @@ -1,17 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - List(1, 2, 3) match { - case foo :: bar :: _ => println(foo * bar) - case _ => println("this is getting out of hand!") - } - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5276.check b/test/pending/run/t5276.check deleted file mode 100644 index 0cfbf08886..0000000000 --- a/test/pending/run/t5276.check +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/test/pending/run/t5276.scala b/test/pending/run/t5276.scala deleted file mode 100644 index 432fdb91e4..0000000000 --- a/test/pending/run/t5276.scala +++ /dev/null @@ -1,15 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - lazy x = 2 - println(x) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} -- cgit v1.2.3 From 97ec16850b152e6e03aba351cc918c66583362f3 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 14 Feb 2012 21:59:43 +0100 Subject: Disables typechecking that precedes reflective compilation Previously toolboxes used to typecheck their inputs before compiling. Actually, the initial demo by Martin first typechecked the reified tree, then ran it, which typechecked it again, and only then launched the reflective compiler. However, as observed in https://issues.scala-lang.org/browse/SI-5464 current implementation of typechecking is not always idempotent. That's why we cannot allow inputs of toolboxes to be typechecked, at least not until the aforementioned issue is closed. This is not only a convention but also a check inside compileExpr. --- .../scala/reflect/internal/Importers.scala | 2 +- src/compiler/scala/reflect/runtime/ToolBoxes.scala | 40 ++++---- test/files/neg/reify_ann2a.scala | 2 +- test/files/neg/reify_ann2b.scala | 2 +- test/files/run/reify_ann1a.scala | 2 +- test/files/run/reify_ann1b.scala | 2 +- test/files/run/reify_anonymous.scala | 3 +- test/files/run/reify_classfileann_a.scala | 2 +- test/files/run/reify_closure1.scala | 3 +- test/files/run/reify_closure2a.scala | 3 +- test/files/run/reify_closure3a.scala | 3 +- test/files/run/reify_closure4a.scala | 3 +- test/files/run/reify_closure5a.scala | 3 +- test/files/run/reify_closure6.scala | 3 +- test/files/run/reify_closure7.scala | 3 +- test/files/run/reify_closure8a.scala | 3 +- test/files/run/reify_closures10.scala | 3 +- test/files/run/reify_complex.scala | 3 +- test/files/run/reify_extendbuiltins.scala | 3 +- test/files/run/reify_for1.scala | 3 +- test/files/run/reify_fors.check | 5 + test/files/run/reify_fors.scala | 106 ++++++++++++++++++++ test/files/run/reify_generic.scala | 3 +- test/files/run/reify_generic2.scala | 3 +- test/files/run/reify_getter.scala | 3 +- test/files/run/reify_implicits.scala | 3 +- test/files/run/reify_inheritance.scala | 3 +- test/files/run/reify_inner1.scala | 3 +- test/files/run/reify_inner2.scala | 3 +- test/files/run/reify_inner3.scala | 3 +- test/files/run/reify_inner4.scala | 3 +- test/files/run/reify_maps.check | 4 + test/files/run/reify_maps.scala | 25 +++++ test/files/run/reify_printf.scala | 3 +- test/files/run/reify_sort.scala | 3 +- test/files/run/reify_sort1.scala | 3 +- test/files/run/reify_this.scala | 3 +- test/files/run/reify_timeofday.check | 1 + test/files/run/reify_timeofday.scala | 47 +++++++++ test/files/run/reify_varargs.scala | 3 +- test/files/run/t5229_1.scala | 3 +- test/files/run/t5229_2.check | 2 +- test/files/run/t5229_2.scala | 3 +- test/files/run/t5230.check | 2 +- test/files/run/t5230.scala | 3 +- test/files/run/t5258a.scala | 3 +- test/files/run/t5266_1.check | 2 +- test/files/run/t5266_1.scala | 3 +- test/files/run/t5266_2.check | 2 +- test/files/run/t5266_2.scala | 3 +- test/files/run/t5269.scala | 3 +- test/files/run/t5270.scala | 3 +- test/files/run/t5271_1.check | 11 +++ test/files/run/t5271_1.scala | 3 +- test/files/run/t5271_2.check | 13 ++- test/files/run/t5271_2.scala | 3 +- test/files/run/t5271_3.check | 20 +++- test/files/run/t5271_3.scala | 3 +- test/files/run/t5271_4.scala | 3 +- test/files/run/t5272_1.scala | 3 +- test/files/run/t5272_2.scala | 3 +- test/files/run/t5273_1.scala | 3 +- test/files/run/t5273_2a.scala | 3 +- test/files/run/t5273_2b.scala | 3 +- test/files/run/t5274_1.scala | 3 +- test/files/run/t5274_2.scala | 3 +- test/files/run/t5275.scala | 3 +- test/files/run/t5276_1a.scala | 3 +- test/files/run/t5276_1b.scala | 5 +- test/files/run/t5276_2a.scala | 3 +- test/files/run/t5276_2b.scala | 3 +- test/files/run/t5277_1.scala | 3 +- test/files/run/t5277_2.scala | 3 +- test/files/run/t5279.scala | 3 +- test/files/run/t5334_1.check | 1 - test/files/run/t5334_1.scala | 4 +- test/files/run/t5334_2.check | 1 - test/files/run/t5334_2.scala | 4 +- test/files/run/t5335.scala | 3 +- test/pending/run/reify_addressbook.scala | 3 +- test/pending/run/reify_brainf_ck.scala | 3 +- test/pending/run/reify_callccinterpreter.scala | 3 +- test/pending/run/reify_classfileann_b.scala | 8 +- test/pending/run/reify_closure2b.scala | 3 +- test/pending/run/reify_closure3b.scala | 3 +- test/pending/run/reify_closure4b.scala | 3 +- test/pending/run/reify_closure5b.scala | 3 +- test/pending/run/reify_closure8b.scala | 3 +- test/pending/run/reify_closure9a.scala | 3 +- test/pending/run/reify_closure9b.scala | 3 +- test/pending/run/reify_closures11.scala | 3 +- test/pending/run/reify_csv.scala | 3 +- test/pending/run/reify_fors.check | 5 - test/pending/run/reify_fors.scala | 107 --------------------- test/pending/run/reify_gadts.scala | 3 +- test/pending/run/reify_lazyevaluation.scala | 3 +- test/pending/run/reify_maps.check | 4 - test/pending/run/reify_maps.scala | 26 ----- test/pending/run/reify_properties.scala | 3 +- test/pending/run/reify_simpleinterpreter.scala | 3 +- test/pending/run/reify_timeofday.check | 1 - test/pending/run/reify_timeofday.scala | 48 --------- test/pending/run/t5258b.scala | 3 +- test/pending/run/t5258c.scala | 3 +- test/pending/run/t5271_1.check | 0 test/pending/run/t5271_1.scala | 13 +++ test/pending/run/t5271_2.check | 1 + test/pending/run/t5271_2.scala | 15 +++ test/pending/run/t5271_3.check | 1 + test/pending/run/t5271_3.scala | 16 +++ test/pending/run/t5418.scala | 3 +- 111 files changed, 388 insertions(+), 383 deletions(-) create mode 100644 test/files/run/reify_fors.check create mode 100644 test/files/run/reify_fors.scala create mode 100644 test/files/run/reify_maps.check create mode 100644 test/files/run/reify_maps.scala create mode 100644 test/files/run/reify_timeofday.check create mode 100644 test/files/run/reify_timeofday.scala delete mode 100644 test/pending/run/reify_fors.check delete mode 100644 test/pending/run/reify_fors.scala delete mode 100644 test/pending/run/reify_maps.check delete mode 100644 test/pending/run/reify_maps.scala delete mode 100644 test/pending/run/reify_timeofday.check delete mode 100644 test/pending/run/reify_timeofday.scala create mode 100644 test/pending/run/t5271_1.check create mode 100644 test/pending/run/t5271_1.scala create mode 100644 test/pending/run/t5271_2.check create mode 100644 test/pending/run/t5271_2.scala create mode 100644 test/pending/run/t5271_3.check create mode 100644 test/pending/run/t5271_3.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index c232e3b7c1..1ae4f755ed 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -286,7 +286,7 @@ trait Importers { self: SymbolTable => new Modifiers(mods.flags, importName(mods.privateWithin), mods.annotations map importTree) def importImportSelector(sel: from.ImportSelector): ImportSelector = - new ImportSelector(importName(sel.name), sel.namePos, importName(sel.rename), sel.renamePos) + new ImportSelector(importName(sel.name), sel.namePos, if (sel.rename != null) importName(sel.rename) else null, sel.renamePos) def importTree(tree: from.Tree): Tree = { val mytree = tree match { diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 880c68eaa0..f52662ce6f 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -64,7 +64,7 @@ trait ToolBoxes extends { self: Universe => obj setInfo obj.moduleClass.tpe val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName)) def makeParam(fv: Symbol) = meth.newValueParameter(fv.name.toTermName) setInfo fv.tpe - meth setInfo MethodType(fvs map makeParam, expr.tpe) + meth setInfo MethodType(fvs map makeParam, AnyClass.tpe) minfo.decls enter meth trace("wrapping ")(defOwner(expr) -> meth) val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth)) @@ -94,6 +94,20 @@ trait ToolBoxes extends { self: Universe => } def compileExpr(expr: Tree, fvs: List[Symbol]): String = { + // Previously toolboxes used to typecheck their inputs before compiling. + // Actually, the initial demo by Martin first typechecked the reified tree, + // then ran it, which typechecked it again, and only then launched the + // reflective compiler. + // + // However, as observed in https://issues.scala-lang.org/browse/SI-5464 + // current implementation typechecking is not always idempotent. + // That's why we cannot allow inputs of toolboxes to be typechecked, + // at least not until the aforementioned issue is closed. + val typed = expr filter (t => t.tpe != null && t.tpe != NoType && !t.isInstanceOf[TypeTree]) + if (!typed.isEmpty) { + throw new Error("cannot compile trees that are already typed") + } + val mdef = wrapInObject(expr, fvs) val pdef = wrapInPackage(mdef) val unit = wrapInCompilationUnit(pdef) @@ -106,7 +120,6 @@ trait ToolBoxes extends { self: Universe => jclazz.getDeclaredMethods.find(_.getName == name).get def runExpr(expr: Tree): Any = { - val etpe = expr.tpe val fvs = (expr filter isFree map (_.symbol)).distinct reporter.reset() @@ -181,19 +194,13 @@ trait ToolBoxes extends { self: Universe => lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, defaultReflectiveClassLoader) - private def importAndTypeCheck(tree: rm.Tree, expectedType: rm.Type): compiler.Tree = { + def typeCheck(tree: rm.Tree, expectedType: rm.Type): rm.Tree = { + if (compiler.settings.verbose.value) println("typing "+tree+", pt = "+expectedType) val ctree: compiler.Tree = importer.importTree(tree.asInstanceOf[Tree]) val pt: compiler.Type = importer.importType(expectedType.asInstanceOf[Type]) -// val typer = compiler.typer.atOwner(ctree, if (owner.isModule) cowner.moduleClass else cowner) val ttree: compiler.Tree = compiler.typedTopLevelExpr(ctree, pt) - ttree - } - - def typeCheck(tree: rm.Tree, expectedType: rm.Type): rm.Tree = { - if (compiler.settings.verbose.value) println("typing "+tree+", pt = "+expectedType) - val ttree = importAndTypeCheck(tree, expectedType) - val ettree = exporter.importTree(ttree).asInstanceOf[rm.Tree] - ettree + val rmttree = exporter.importTree(ttree).asInstanceOf[rm.Tree] + rmttree } def typeCheck(tree: rm.Tree): rm.Tree = @@ -202,11 +209,10 @@ trait ToolBoxes extends { self: Universe => def showAttributed(tree: rm.Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = compiler.showAttributed(importer.importTree(tree.asInstanceOf[Tree]), printTypes, printIds, printKinds) - def runExpr(tree: rm.Tree, expectedType: rm.Type): Any = { - val ttree = importAndTypeCheck(tree, expectedType) - compiler.runExpr(ttree) + def runExpr(tree: rm.Tree): Any = { + if (compiler.settings.verbose.value) println("running "+tree) + val ctree: compiler.Tree = importer.importTree(tree.asInstanceOf[Tree]) + compiler.runExpr(ctree) } - - def runExpr(tree: rm.Tree): Any = runExpr(tree, WildcardType.asInstanceOf[rm.Type]) } } diff --git a/test/files/neg/reify_ann2a.scala b/test/files/neg/reify_ann2a.scala index 071919eb76..8de0984074 100644 --- a/test/files/neg/reify_ann2a.scala +++ b/test/files/neg/reify_ann2a.scala @@ -26,5 +26,5 @@ object Test extends App { println(ttree.toString) // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/files/neg/reify_ann2b.scala b/test/files/neg/reify_ann2b.scala index 74273ad6ec..b43567c2a7 100644 --- a/test/files/neg/reify_ann2b.scala +++ b/test/files/neg/reify_ann2b.scala @@ -26,5 +26,5 @@ object Test extends App { println(ttree.toString) // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/files/run/reify_ann1a.scala b/test/files/run/reify_ann1a.scala index 933ea21b20..1ca170904b 100644 --- a/test/files/run/reify_ann1a.scala +++ b/test/files/run/reify_ann1a.scala @@ -26,5 +26,5 @@ object Test extends App { println(ttree.toString) // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala index 53dfe08086..9bdc712227 100644 --- a/test/files/run/reify_ann1b.scala +++ b/test/files/run/reify_ann1b.scala @@ -26,5 +26,5 @@ object Test extends App { println(ttree.toString) // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/files/run/reify_anonymous.scala b/test/files/run/reify_anonymous.scala index 1e7f3fe856..af16f2f8fd 100644 --- a/test/files/run/reify_anonymous.scala +++ b/test/files/run/reify_anonymous.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_classfileann_a.scala b/test/files/run/reify_classfileann_a.scala index 6bf4750bbc..c77bd3b8a2 100644 --- a/test/files/run/reify_classfileann_a.scala +++ b/test/files/run/reify_classfileann_a.scala @@ -20,5 +20,5 @@ object Test extends App { println(ttree.toString) // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/files/run/reify_closure1.scala b/test/files/run/reify_closure1.scala index 960f6aec3e..7cb3aff17d 100644 --- a/test/files/run/reify_closure1.scala +++ b/test/files/run/reify_closure1.scala @@ -10,8 +10,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure2a.scala b/test/files/run/reify_closure2a.scala index 6c28514c2b..cf367aa63f 100644 --- a/test/files/run/reify_closure2a.scala +++ b/test/files/run/reify_closure2a.scala @@ -10,8 +10,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure3a.scala b/test/files/run/reify_closure3a.scala index 4444c55ddf..d322b970b6 100644 --- a/test/files/run/reify_closure3a.scala +++ b/test/files/run/reify_closure3a.scala @@ -12,8 +12,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure4a.scala b/test/files/run/reify_closure4a.scala index 886e643a47..bbedd7e092 100644 --- a/test/files/run/reify_closure4a.scala +++ b/test/files/run/reify_closure4a.scala @@ -12,8 +12,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure5a.scala b/test/files/run/reify_closure5a.scala index 20994abff0..193e18103a 100644 --- a/test/files/run/reify_closure5a.scala +++ b/test/files/run/reify_closure5a.scala @@ -10,8 +10,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure6.scala b/test/files/run/reify_closure6.scala index 192c08f701..6aff83cb94 100644 --- a/test/files/run/reify_closure6.scala +++ b/test/files/run/reify_closure6.scala @@ -17,8 +17,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure7.scala b/test/files/run/reify_closure7.scala index 942c2cda9c..46002d8d6c 100644 --- a/test/files/run/reify_closure7.scala +++ b/test/files/run/reify_closure7.scala @@ -19,8 +19,7 @@ object Test extends App { if (clo == null) { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun.tree) clo = dyn.asInstanceOf[Int => Int] } diff --git a/test/files/run/reify_closure8a.scala b/test/files/run/reify_closure8a.scala index 5e54bfc8c7..805d8ff855 100644 --- a/test/files/run/reify_closure8a.scala +++ b/test/files/run/reify_closure8a.scala @@ -10,8 +10,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(10).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(10).fun.tree) val foo = dyn.asInstanceOf[Int] println(foo) } diff --git a/test/files/run/reify_closures10.scala b/test/files/run/reify_closures10.scala index d0f895ae4d..b6ec8e8911 100644 --- a/test/files/run/reify_closures10.scala +++ b/test/files/run/reify_closures10.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - println(toolbox.runExpr(ttree)) + println(toolbox.runExpr(code.tree)) } diff --git a/test/files/run/reify_complex.scala b/test/files/run/reify_complex.scala index aae4d558cf..0d9aeb28c5 100644 --- a/test/files/run/reify_complex.scala +++ b/test/files/run/reify_complex.scala @@ -26,6 +26,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_extendbuiltins.scala b/test/files/run/reify_extendbuiltins.scala index 57acd699ff..0aaec7cdf2 100644 --- a/test/files/run/reify_extendbuiltins.scala +++ b/test/files/run/reify_extendbuiltins.scala @@ -16,6 +16,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_for1.scala b/test/files/run/reify_for1.scala index 4b03330293..d1b60d878b 100644 --- a/test/files/run/reify_for1.scala +++ b/test/files/run/reify_for1.scala @@ -11,6 +11,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_fors.check b/test/files/run/reify_fors.check new file mode 100644 index 0000000000..eefddedc20 --- /dev/null +++ b/test/files/run/reify_fors.check @@ -0,0 +1,5 @@ +Persons over 20: John Richard +divisors(34) = List(1, 2, 17, 34) +findNums(15) = (4,1) (5,2) (6,1) (7,4) (8,3) (8,5) (9,2) (9,4) (10,1) (10,3) (10,7) (11,2) (11,6) (11,8) (12,1) (12,5) (12,7) (13,4) (13,6) (13,10) (14,3) (14,5) (14,9) +average(List(3.5, 5.0, 4.5)) = 4.333333333333333 +scalProd(List(3.5, 5.0, 4.5), List(2.0, 1.0, 3.0)) = 25.5 diff --git a/test/files/run/reify_fors.scala b/test/files/run/reify_fors.scala new file mode 100644 index 0000000000..27ee85d18b --- /dev/null +++ b/test/files/run/reify_fors.scala @@ -0,0 +1,106 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object Persons { + /** A list of persons. To create a list, we use Predef.List + * which takes a variable number of arguments and constructs + * a list out of them. + */ + val persons = List( + new Person("Bob", 17), + new Person("John", 40), + new Person("Richard", 68) + ) + + /** A Person class. 'val' constructor parameters become + * public members of the class. + */ + class Person(val name: String, val age: Int) + + /** Return an iterator over persons that are older than 20. + */ + def olderThan20(xs: Seq[Person]): Iterator[String] = + olderThan20(xs.iterator) + + /** Return an iterator over persons older than 20, given + * an iterator over persons. + */ + def olderThan20(xs: Iterator[Person]): Iterator[String] = { + + // The first expression is called a 'generator' and makes + // 'p' take values from 'xs'. The second expression is + // called a 'filter' and it is a boolean expression which + // selects only persons older than 20. There can be more than + // one generator and filter. The 'yield' expression is evaluated + // for each 'p' which satisfies the filters and used to assemble + // the resulting iterator + for (p <- xs if p.age > 20) yield p.name + } + } + + /** Some functions over lists of numbers which demonstrate + * the use of for comprehensions. + */ + object Numeric { + + /** Return the divisors of n. */ + def divisors(n: Int): List[Int] = + for (i <- List.range(1, n+1) if n % i == 0) yield i + + /** Is 'n' a prime number? */ + def isPrime(n: Int) = divisors(n).length == 2 + + /** Return pairs of numbers whose sum is prime. */ + def findNums(n: Int): Iterable[(Int, Int)] = { + + // a for comprehension using two generators + for (i <- 1 until n; + j <- 1 until (i-1); + if isPrime(i + j)) yield (i, j) + } + + /** Return the sum of the elements of 'xs'. */ + def sum(xs: List[Double]): Double = + xs.foldLeft(0.0) { (x, y) => x + y } + + /** Return the sum of pairwise product of the two lists. */ + def scalProd(xs: List[Double], ys: List[Double]) = + sum(for((x, y) <- xs zip ys) yield x * y); + + /** Remove duplicate elements in 'xs'. */ + def removeDuplicates[A](xs: List[A]): List[A] = + if (xs.isEmpty) + xs + else + xs.head :: removeDuplicates(for (x <- xs.tail if x != xs.head) yield x) + } + + // import all members of object 'persons' in the current scope + import Persons._ + + print("Persons over 20:") + olderThan20(persons) foreach { x => print(" " + x) } + println + + import Numeric._ + + println("divisors(34) = " + divisors(34)) + + print("findNums(15) =") + findNums(15) foreach { x => print(" " + x) } + println + + val xs = List(3.5, 5.0, 4.5) + println("average(" + xs + ") = " + sum(xs) / xs.length) + + val ys = List(2.0, 1.0, 3.0) + println("scalProd(" + xs + ", " + ys +") = " + scalProd(xs, ys)) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/files/run/reify_generic.scala b/test/files/run/reify_generic.scala index aef038b2d8..6a4ff148c4 100644 --- a/test/files/run/reify_generic.scala +++ b/test/files/run/reify_generic.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_generic2.scala b/test/files/run/reify_generic2.scala index d03fe7602b..9413f41eb5 100644 --- a/test/files/run/reify_generic2.scala +++ b/test/files/run/reify_generic2.scala @@ -11,6 +11,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_getter.scala b/test/files/run/reify_getter.scala index 83eaded506..33f36888a7 100644 --- a/test/files/run/reify_getter.scala +++ b/test/files/run/reify_getter.scala @@ -13,7 +13,6 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(code.tree) println("evaluated = " + evaluated) } diff --git a/test/files/run/reify_implicits.scala b/test/files/run/reify_implicits.scala index a15cef9c97..953eabe6c2 100644 --- a/test/files/run/reify_implicits.scala +++ b/test/files/run/reify_implicits.scala @@ -16,6 +16,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_inheritance.scala b/test/files/run/reify_inheritance.scala index 2a1b5f764f..78a64c264e 100644 --- a/test/files/run/reify_inheritance.scala +++ b/test/files/run/reify_inheritance.scala @@ -18,6 +18,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_inner1.scala b/test/files/run/reify_inner1.scala index 69931198e0..546fe36d16 100644 --- a/test/files/run/reify_inner1.scala +++ b/test/files/run/reify_inner1.scala @@ -17,6 +17,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_inner2.scala b/test/files/run/reify_inner2.scala index 0f12fd472a..613614b989 100644 --- a/test/files/run/reify_inner2.scala +++ b/test/files/run/reify_inner2.scala @@ -17,6 +17,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_inner3.scala b/test/files/run/reify_inner3.scala index 6b97b42b34..e9fb636dce 100644 --- a/test/files/run/reify_inner3.scala +++ b/test/files/run/reify_inner3.scala @@ -17,6 +17,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_inner4.scala b/test/files/run/reify_inner4.scala index de8c973b09..33870b0983 100644 --- a/test/files/run/reify_inner4.scala +++ b/test/files/run/reify_inner4.scala @@ -17,6 +17,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_maps.check b/test/files/run/reify_maps.check new file mode 100644 index 0000000000..08cbbb1359 --- /dev/null +++ b/test/files/run/reify_maps.check @@ -0,0 +1,4 @@ +red has code: 16711680 +Unknown color: green +Unknown color: blue +turquoise has code: 65535 diff --git a/test/files/run/reify_maps.scala b/test/files/run/reify_maps.scala new file mode 100644 index 0000000000..d3d95ffa24 --- /dev/null +++ b/test/files/run/reify_maps.scala @@ -0,0 +1,25 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + val colors = Map("red" -> 0xFF0000, + "turquoise" -> 0x00FFFF, + "black" -> 0x000000, + "orange" -> 0xFF8040, + "brown" -> 0x804000) + for (name <- List("red", "green", "blue", "turquoise")) println( + colors.get(name) match { + case Some(code) => + name + " has code: " + code + case None => + "Unknown color: " + name + } + ) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/files/run/reify_printf.scala b/test/files/run/reify_printf.scala index 30901b98c2..cd6052bc5e 100644 --- a/test/files/run/reify_printf.scala +++ b/test/files/run/reify_printf.scala @@ -14,11 +14,10 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter, args mkString " ") - val ttree = toolbox.typeCheck(tree) val output = new ByteArrayOutputStream() Console.setOut(new PrintStream(output)) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(tree) assert(output.toString() == "hello world", output.toString() +" == hello world") diff --git a/test/files/run/reify_sort.scala b/test/files/run/reify_sort.scala index 42991fe5d2..5984a64967 100644 --- a/test/files/run/reify_sort.scala +++ b/test/files/run/reify_sort.scala @@ -52,6 +52,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_sort1.scala b/test/files/run/reify_sort1.scala index 42f4c824a5..6f365dea26 100644 --- a/test/files/run/reify_sort1.scala +++ b/test/files/run/reify_sort1.scala @@ -22,6 +22,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/reify_this.scala b/test/files/run/reify_this.scala index 44a25ae1b6..ee1f116013 100644 --- a/test/files/run/reify_this.scala +++ b/test/files/run/reify_this.scala @@ -11,8 +11,7 @@ trait Eval { val settings = new Settings val reporter = new ConsoleReporter(settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(tree) - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } } diff --git a/test/files/run/reify_timeofday.check b/test/files/run/reify_timeofday.check new file mode 100644 index 0000000000..3fd3b76a62 --- /dev/null +++ b/test/files/run/reify_timeofday.check @@ -0,0 +1 @@ +DateError diff --git a/test/files/run/reify_timeofday.scala b/test/files/run/reify_timeofday.scala new file mode 100644 index 0000000000..122d7a6d52 --- /dev/null +++ b/test/files/run/reify_timeofday.scala @@ -0,0 +1,47 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + class DateError extends Exception + + /** Simulating properties in Scala + * (example 4.2.1 in ScalaReference.pdf) + */ + class TimeOfDayVar { + private var h, m, s: Int = 0 + + def hours = h + + /** A method 'ident_=' is a setter for 'ident'. 'code.ident = ...' will + * be translated to a call to 'ident_=' + */ + def hours_= (h: Int) = + if (0 <= h && h < 24) this.h = h + else throw new DateError() + + def minutes = m + def minutes_= (m: Int) = + if (0 <= m && m < 60) this.m = m + else throw new DateError() + + def seconds = s + def seconds_= (s: Int) = + if (0 <= s && s < 60) this.s = s + else throw new DateError() + } + + val d = new TimeOfDayVar + d.hours = 8; d.minutes = 30; d.seconds = 0 + try { d.hours = 25 // throws a DateError exception + } catch { + case de: DateError => println("DateError") + case e: Exception => println("Exception") + } + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/files/run/reify_varargs.scala b/test/files/run/reify_varargs.scala index d38cbf2aac..175cfb5db0 100644 --- a/test/files/run/reify_varargs.scala +++ b/test/files/run/reify_varargs.scala @@ -12,6 +12,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5229_1.scala b/test/files/run/t5229_1.scala index 1d7bf0590b..d5af569656 100644 --- a/test/files/run/t5229_1.scala +++ b/test/files/run/t5229_1.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5229_2.check b/test/files/run/t5229_2.check index 5db6ec9b38..43c25b96af 100644 --- a/test/files/run/t5229_2.check +++ b/test/files/run/t5229_2.check @@ -1,2 +1,2 @@ 2 -evaluated = null +evaluated = () diff --git a/test/files/run/t5229_2.scala b/test/files/run/t5229_2.scala index 67be7328a6..07f9ac6b84 100644 --- a/test/files/run/t5229_2.scala +++ b/test/files/run/t5229_2.scala @@ -13,7 +13,6 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(code.tree) println("evaluated = " + evaluated) } diff --git a/test/files/run/t5230.check b/test/files/run/t5230.check index 5db6ec9b38..43c25b96af 100644 --- a/test/files/run/t5230.check +++ b/test/files/run/t5230.check @@ -1,2 +1,2 @@ 2 -evaluated = null +evaluated = () diff --git a/test/files/run/t5230.scala b/test/files/run/t5230.scala index 5aab8f9290..d3106ca05c 100644 --- a/test/files/run/t5230.scala +++ b/test/files/run/t5230.scala @@ -13,7 +13,6 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(code.tree) println("evaluated = " + evaluated) } diff --git a/test/files/run/t5258a.scala b/test/files/run/t5258a.scala index deabb8310f..8cc4249e06 100644 --- a/test/files/run/t5258a.scala +++ b/test/files/run/t5258a.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } \ No newline at end of file diff --git a/test/files/run/t5266_1.check b/test/files/run/t5266_1.check index 3feac16a0b..35f20802ee 100644 --- a/test/files/run/t5266_1.check +++ b/test/files/run/t5266_1.check @@ -1,2 +1,2 @@ 2 -evaluated = null \ No newline at end of file +evaluated = () \ No newline at end of file diff --git a/test/files/run/t5266_1.scala b/test/files/run/t5266_1.scala index 18e288e685..4262bc7a7b 100644 --- a/test/files/run/t5266_1.scala +++ b/test/files/run/t5266_1.scala @@ -10,7 +10,6 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(code.tree) println("evaluated = " + evaluated) } \ No newline at end of file diff --git a/test/files/run/t5266_2.check b/test/files/run/t5266_2.check index 3feac16a0b..35f20802ee 100644 --- a/test/files/run/t5266_2.check +++ b/test/files/run/t5266_2.check @@ -1,2 +1,2 @@ 2 -evaluated = null \ No newline at end of file +evaluated = () \ No newline at end of file diff --git a/test/files/run/t5266_2.scala b/test/files/run/t5266_2.scala index eb319583f8..d0f718dbd7 100644 --- a/test/files/run/t5266_2.scala +++ b/test/files/run/t5266_2.scala @@ -11,7 +11,6 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - val evaluated = toolbox.runExpr(ttree) + val evaluated = toolbox.runExpr(code.tree) println("evaluated = " + evaluated) } diff --git a/test/files/run/t5269.scala b/test/files/run/t5269.scala index a30509f3fe..cab99f17e6 100644 --- a/test/files/run/t5269.scala +++ b/test/files/run/t5269.scala @@ -17,6 +17,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5270.scala b/test/files/run/t5270.scala index 10f79790b0..934cc13dea 100644 --- a/test/files/run/t5270.scala +++ b/test/files/run/t5270.scala @@ -21,6 +21,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5271_1.check b/test/files/run/t5271_1.check index e69de29bb2..d4fd544e88 100644 --- a/test/files/run/t5271_1.check +++ b/test/files/run/t5271_1.check @@ -0,0 +1,11 @@ +{ + case class C extends Object with ScalaObject with Product with Serializable { + val foo : Int = _; + val bar : Int = _; + def (foo: Int, bar: Int) = { + super.(); + () + } + }; + () +} diff --git a/test/files/run/t5271_1.scala b/test/files/run/t5271_1.scala index 5f10e64528..fbc57aead7 100644 --- a/test/files/run/t5271_1.scala +++ b/test/files/run/t5271_1.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + println(code.tree) } diff --git a/test/files/run/t5271_2.check b/test/files/run/t5271_2.check index b8626c4cff..5a519f265f 100644 --- a/test/files/run/t5271_2.check +++ b/test/files/run/t5271_2.check @@ -1 +1,12 @@ -4 +{ + case class C extends Object with ScalaObject with Product with Serializable { + val foo : Int = _; + val bar : Int = _; + def (foo: Int, bar: Int) = { + super.(); + () + } + }; + val c = C.apply(2, 2); + scala.this.Predef.println(c.foo.$times(c.bar)) +} diff --git a/test/files/run/t5271_2.scala b/test/files/run/t5271_2.scala index 71967c04ed..4bfc574e00 100644 --- a/test/files/run/t5271_2.scala +++ b/test/files/run/t5271_2.scala @@ -11,6 +11,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + println(code.tree) } diff --git a/test/files/run/t5271_3.check b/test/files/run/t5271_3.check index f32a5804e2..be87696f02 100644 --- a/test/files/run/t5271_3.check +++ b/test/files/run/t5271_3.check @@ -1 +1,19 @@ -true \ No newline at end of file +{ + object C extends Object with ScalaObject with Serializable { + def () = { + super.(); + () + }; + def qwe: Int = 4 + }; + case class C extends Object with ScalaObject with Product with Serializable { + val foo : Int = _; + val bar : Int = _; + def (foo: Int, bar: Int) = { + super.(); + () + } + }; + val c = C.apply(2, 2); + scala.this.Predef.println(c.foo.$times(c.bar).$eq$eq(C.qwe)) +} diff --git a/test/files/run/t5271_3.scala b/test/files/run/t5271_3.scala index bfa116c691..a085bdca4c 100644 --- a/test/files/run/t5271_3.scala +++ b/test/files/run/t5271_3.scala @@ -12,6 +12,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + println(code.tree) } diff --git a/test/files/run/t5271_4.scala b/test/files/run/t5271_4.scala index e5e16033e8..c253b1adca 100644 --- a/test/files/run/t5271_4.scala +++ b/test/files/run/t5271_4.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5272_1.scala b/test/files/run/t5272_1.scala index 3f44d05fb3..882287f033 100644 --- a/test/files/run/t5272_1.scala +++ b/test/files/run/t5272_1.scala @@ -12,6 +12,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5272_2.scala b/test/files/run/t5272_2.scala index 833ee65285..48b6a670bb 100644 --- a/test/files/run/t5272_2.scala +++ b/test/files/run/t5272_2.scala @@ -11,6 +11,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5273_1.scala b/test/files/run/t5273_1.scala index 1175881c9f..80460a4ae6 100644 --- a/test/files/run/t5273_1.scala +++ b/test/files/run/t5273_1.scala @@ -12,6 +12,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5273_2a.scala b/test/files/run/t5273_2a.scala index 12ddbb280a..a7a336d8a7 100644 --- a/test/files/run/t5273_2a.scala +++ b/test/files/run/t5273_2a.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5273_2b.scala b/test/files/run/t5273_2b.scala index 8b75084463..85c40f0607 100644 --- a/test/files/run/t5273_2b.scala +++ b/test/files/run/t5273_2b.scala @@ -11,6 +11,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5274_1.scala b/test/files/run/t5274_1.scala index c501172518..74a5b81bcb 100644 --- a/test/files/run/t5274_1.scala +++ b/test/files/run/t5274_1.scala @@ -15,6 +15,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5274_2.scala b/test/files/run/t5274_2.scala index 42991fe5d2..5984a64967 100644 --- a/test/files/run/t5274_2.scala +++ b/test/files/run/t5274_2.scala @@ -52,6 +52,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5275.scala b/test/files/run/t5275.scala index d419834ded..285d8a18a4 100644 --- a/test/files/run/t5275.scala +++ b/test/files/run/t5275.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5276_1a.scala b/test/files/run/t5276_1a.scala index c8afbba19e..b717675824 100644 --- a/test/files/run/t5276_1a.scala +++ b/test/files/run/t5276_1a.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5276_1b.scala b/test/files/run/t5276_1b.scala index 31582201fb..1ff25504ca 100644 --- a/test/files/run/t5276_1b.scala +++ b/test/files/run/t5276_1b.scala @@ -5,11 +5,10 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { val code = scala.reflect.Code.lift{ implicit lazy val x = 2 - implicitly[Int] + println(implicitly[Int]) }; val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5276_2a.scala b/test/files/run/t5276_2a.scala index 179c14b739..af5ff2a565 100644 --- a/test/files/run/t5276_2a.scala +++ b/test/files/run/t5276_2a.scala @@ -13,6 +13,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5276_2b.scala b/test/files/run/t5276_2b.scala index 6fe2873fef..63904b2898 100644 --- a/test/files/run/t5276_2b.scala +++ b/test/files/run/t5276_2b.scala @@ -14,6 +14,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5277_1.scala b/test/files/run/t5277_1.scala index 57acd699ff..0aaec7cdf2 100644 --- a/test/files/run/t5277_1.scala +++ b/test/files/run/t5277_1.scala @@ -16,6 +16,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5277_2.scala b/test/files/run/t5277_2.scala index 67b6b000bc..91ed55122a 100644 --- a/test/files/run/t5277_2.scala +++ b/test/files/run/t5277_2.scala @@ -13,6 +13,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5279.scala b/test/files/run/t5279.scala index 39e7dd2c66..cef58535d5 100644 --- a/test/files/run/t5279.scala +++ b/test/files/run/t5279.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/files/run/t5334_1.check b/test/files/run/t5334_1.check index e09aedaede..96d80cd6c4 100644 --- a/test/files/run/t5334_1.check +++ b/test/files/run/t5334_1.check @@ -1,2 +1 @@ -C C \ No newline at end of file diff --git a/test/files/run/t5334_1.scala b/test/files/run/t5334_1.scala index 7acf282bb8..9887bebf78 100644 --- a/test/files/run/t5334_1.scala +++ b/test/files/run/t5334_1.scala @@ -10,7 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - println(ttree.tpe) - println(toolbox.runExpr(ttree)) + println(toolbox.runExpr(code.tree)) } diff --git a/test/files/run/t5334_2.check b/test/files/run/t5334_2.check index 2ae76754c0..613d286a18 100644 --- a/test/files/run/t5334_2.check +++ b/test/files/run/t5334_2.check @@ -1,2 +1 @@ -List[(C, C)] List((C,C)) \ No newline at end of file diff --git a/test/files/run/t5334_2.scala b/test/files/run/t5334_2.scala index 26f0778400..775a05aaf7 100644 --- a/test/files/run/t5334_2.scala +++ b/test/files/run/t5334_2.scala @@ -10,7 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - println(ttree.tpe) - println(toolbox.runExpr(ttree)) + println(toolbox.runExpr(code.tree)) } diff --git a/test/files/run/t5335.scala b/test/files/run/t5335.scala index 9a8b91f04d..8e2ed59db6 100644 --- a/test/files/run/t5335.scala +++ b/test/files/run/t5335.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_addressbook.scala b/test/pending/run/reify_addressbook.scala index 225f26b75e..54dd5545bd 100644 --- a/test/pending/run/reify_addressbook.scala +++ b/test/pending/run/reify_addressbook.scala @@ -66,6 +66,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_brainf_ck.scala b/test/pending/run/reify_brainf_ck.scala index 3bfb76c9ea..0034644b81 100644 --- a/test/pending/run/reify_brainf_ck.scala +++ b/test/pending/run/reify_brainf_ck.scala @@ -80,6 +80,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_callccinterpreter.scala b/test/pending/run/reify_callccinterpreter.scala index c10f4f0b4e..96ae9c5c17 100644 --- a/test/pending/run/reify_callccinterpreter.scala +++ b/test/pending/run/reify_callccinterpreter.scala @@ -89,6 +89,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_classfileann_b.scala b/test/pending/run/reify_classfileann_b.scala index b76dd8fc9f..c31826377a 100644 --- a/test/pending/run/reify_classfileann_b.scala +++ b/test/pending/run/reify_classfileann_b.scala @@ -17,12 +17,8 @@ object Test extends App { }.tree println(tree.toString) - // test 2: import and typecheck + // test 2: import and compile val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(tree) - println(ttree.toString) - - // test 3: import and compile - toolbox.runExpr(ttree) + toolbox.runExpr(tree) } \ No newline at end of file diff --git a/test/pending/run/reify_closure2b.scala b/test/pending/run/reify_closure2b.scala index a1fead07ae..b9c0063290 100644 --- a/test/pending/run/reify_closure2b.scala +++ b/test/pending/run/reify_closure2b.scala @@ -12,8 +12,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(y).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(y).fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/pending/run/reify_closure3b.scala b/test/pending/run/reify_closure3b.scala index acf07c4749..8f161dbff3 100644 --- a/test/pending/run/reify_closure3b.scala +++ b/test/pending/run/reify_closure3b.scala @@ -14,8 +14,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(y).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(y).fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/pending/run/reify_closure4b.scala b/test/pending/run/reify_closure4b.scala index ed102298c5..238795d4dd 100644 --- a/test/pending/run/reify_closure4b.scala +++ b/test/pending/run/reify_closure4b.scala @@ -14,8 +14,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(y).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(y).fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/pending/run/reify_closure5b.scala b/test/pending/run/reify_closure5b.scala index 29e911538f..bdb2583e8a 100644 --- a/test/pending/run/reify_closure5b.scala +++ b/test/pending/run/reify_closure5b.scala @@ -12,8 +12,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(ys).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(ys).fun.tree) dyn.asInstanceOf[Int => Int] } diff --git a/test/pending/run/reify_closure8b.scala b/test/pending/run/reify_closure8b.scala index 9e37e4e09a..38031c217b 100644 --- a/test/pending/run/reify_closure8b.scala +++ b/test/pending/run/reify_closure8b.scala @@ -10,8 +10,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(10).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(10).fun.tree) val foo = dyn.asInstanceOf[Int] println(foo) } diff --git a/test/pending/run/reify_closure9a.scala b/test/pending/run/reify_closure9a.scala index f3ee153d3c..185f4ffca1 100644 --- a/test/pending/run/reify_closure9a.scala +++ b/test/pending/run/reify_closure9a.scala @@ -11,8 +11,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(y).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(y).fun.tree) dyn.asInstanceOf[Int] } diff --git a/test/pending/run/reify_closure9b.scala b/test/pending/run/reify_closure9b.scala index 8d349e8701..ad279fac6d 100644 --- a/test/pending/run/reify_closure9b.scala +++ b/test/pending/run/reify_closure9b.scala @@ -11,8 +11,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(new Foo(y).fun.tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(new Foo(y).fun.tree) dyn.asInstanceOf[Int] } diff --git a/test/pending/run/reify_closures11.scala b/test/pending/run/reify_closures11.scala index 42053bd029..2c4177b8f2 100644 --- a/test/pending/run/reify_closures11.scala +++ b/test/pending/run/reify_closures11.scala @@ -11,8 +11,7 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun().tree) - val dyn = toolbox.runExpr(ttree) + val dyn = toolbox.runExpr(fun().tree) val foo = dyn.asInstanceOf[Int] println(foo) } diff --git a/test/pending/run/reify_csv.scala b/test/pending/run/reify_csv.scala index a05a3b55d4..a6a616fab0 100644 --- a/test/pending/run/reify_csv.scala +++ b/test/pending/run/reify_csv.scala @@ -37,6 +37,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_fors.check b/test/pending/run/reify_fors.check deleted file mode 100644 index eefddedc20..0000000000 --- a/test/pending/run/reify_fors.check +++ /dev/null @@ -1,5 +0,0 @@ -Persons over 20: John Richard -divisors(34) = List(1, 2, 17, 34) -findNums(15) = (4,1) (5,2) (6,1) (7,4) (8,3) (8,5) (9,2) (9,4) (10,1) (10,3) (10,7) (11,2) (11,6) (11,8) (12,1) (12,5) (12,7) (13,4) (13,6) (13,10) (14,3) (14,5) (14,9) -average(List(3.5, 5.0, 4.5)) = 4.333333333333333 -scalProd(List(3.5, 5.0, 4.5), List(2.0, 1.0, 3.0)) = 25.5 diff --git a/test/pending/run/reify_fors.scala b/test/pending/run/reify_fors.scala deleted file mode 100644 index f3556514a9..0000000000 --- a/test/pending/run/reify_fors.scala +++ /dev/null @@ -1,107 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - object Persons { - /** A list of persons. To create a list, we use Predef.List - * which takes a variable number of arguments and constructs - * a list out of them. - */ - val persons = List( - new Person("Bob", 17), - new Person("John", 40), - new Person("Richard", 68) - ) - - /** A Person class. 'val' constructor parameters become - * public members of the class. - */ - class Person(val name: String, val age: Int) - - /** Return an iterator over persons that are older than 20. - */ - def olderThan20(xs: Seq[Person]): Iterator[String] = - olderThan20(xs.elements) - - /** Return an iterator over persons older than 20, given - * an iterator over persons. - */ - def olderThan20(xs: Iterator[Person]): Iterator[String] = { - - // The first expression is called a 'generator' and makes - // 'p' take values from 'xs'. The second expression is - // called a 'filter' and it is a boolean expression which - // selects only persons older than 20. There can be more than - // one generator and filter. The 'yield' expression is evaluated - // for each 'p' which satisfies the filters and used to assemble - // the resulting iterator - for (p <- xs if p.age > 20) yield p.name - } - } - - /** Some functions over lists of numbers which demonstrate - * the use of for comprehensions. - */ - object Numeric { - - /** Return the divisors of n. */ - def divisors(n: Int): List[Int] = - for (i <- List.range(1, n+1) if n % i == 0) yield i - - /** Is 'n' a prime number? */ - def isPrime(n: Int) = divisors(n).length == 2 - - /** Return pairs of numbers whose sum is prime. */ - def findNums(n: Int): Iterable[(Int, Int)] = { - - // a for comprehension using two generators - for (i <- 1 until n; - j <- 1 until (i-1); - if isPrime(i + j)) yield (i, j) - } - - /** Return the sum of the elements of 'xs'. */ - def sum(xs: List[Double]): Double = - xs.foldLeft(0.0) { (x, y) => x + y } - - /** Return the sum of pairwise product of the two lists. */ - def scalProd(xs: List[Double], ys: List[Double]) = - sum(for((x, y) <- xs zip ys) yield x * y); - - /** Remove duplicate elements in 'xs'. */ - def removeDuplicates[A](xs: List[A]): List[A] = - if (xs.isEmpty) - xs - else - xs.head :: removeDuplicates(for (x <- xs.tail if x != xs.head) yield x) - } - - // import all members of object 'persons' in the current scope - import Persons._ - - print("Persons over 20:") - olderThan20(persons) foreach { x => print(" " + x) } - println - - import Numeric._ - - println("divisors(34) = " + divisors(34)) - - print("findNums(15) =") - findNums(15) foreach { x => print(" " + x) } - println - - val xs = List(3.5, 5.0, 4.5) - println("average(" + xs + ") = " + sum(xs) / xs.length) - - val ys = List(2.0, 1.0, 3.0) - println("scalProd(" + xs + ", " + ys +") = " + scalProd(xs, ys)) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/reify_gadts.scala b/test/pending/run/reify_gadts.scala index 7077de735c..9feb7a5726 100644 --- a/test/pending/run/reify_gadts.scala +++ b/test/pending/run/reify_gadts.scala @@ -40,6 +40,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_lazyevaluation.scala b/test/pending/run/reify_lazyevaluation.scala index f38af76751..0720a7c979 100644 --- a/test/pending/run/reify_lazyevaluation.scala +++ b/test/pending/run/reify_lazyevaluation.scala @@ -60,6 +60,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_maps.check b/test/pending/run/reify_maps.check deleted file mode 100644 index 08cbbb1359..0000000000 --- a/test/pending/run/reify_maps.check +++ /dev/null @@ -1,4 +0,0 @@ -red has code: 16711680 -Unknown color: green -Unknown color: blue -turquoise has code: 65535 diff --git a/test/pending/run/reify_maps.scala b/test/pending/run/reify_maps.scala deleted file mode 100644 index 589b28d049..0000000000 --- a/test/pending/run/reify_maps.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - val colors = Map("red" -> 0xFF0000, - "turquoise" -> 0x00FFFF, - "black" -> 0x000000, - "orange" -> 0xFF8040, - "brown" -> 0x804000) - for (name <- List("red", "green", "blue", "turquoise")) println( - colors.get(name) match { - case Some(code) => - name + " has code: " + code - case None => - "Unknown color: " + name - } - ) - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/reify_properties.scala b/test/pending/run/reify_properties.scala index 2115a96715..265c344b8e 100644 --- a/test/pending/run/reify_properties.scala +++ b/test/pending/run/reify_properties.scala @@ -58,6 +58,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_simpleinterpreter.scala b/test/pending/run/reify_simpleinterpreter.scala index b39f5583bb..4762afb3cc 100644 --- a/test/pending/run/reify_simpleinterpreter.scala +++ b/test/pending/run/reify_simpleinterpreter.scala @@ -77,6 +77,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } diff --git a/test/pending/run/reify_timeofday.check b/test/pending/run/reify_timeofday.check deleted file mode 100644 index 3fd3b76a62..0000000000 --- a/test/pending/run/reify_timeofday.check +++ /dev/null @@ -1 +0,0 @@ -DateError diff --git a/test/pending/run/reify_timeofday.scala b/test/pending/run/reify_timeofday.scala deleted file mode 100644 index 6bd11b0d30..0000000000 --- a/test/pending/run/reify_timeofday.scala +++ /dev/null @@ -1,48 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val code = scala.reflect.Code.lift{ - class DateError extends Exception - - /** Simulating properties in Scala - * (example 4.2.1 in ScalaReference.pdf) - */ - class TimeOfDayVar { - private var h, m, s: Int = 0 - - def hours = h - - /** A method 'ident_=' is a setter for 'ident'. 'code.ident = ...' will - * be translated to a call to 'ident_=' - */ - def hours_= (h: Int) = - if (0 <= h && h < 24) this.h = h - else throw new DateError() - - def minutes = m - def minutes_= (m: Int) = - if (0 <= m && m < 60) this.m = m - else throw new DateError() - - def seconds = s - def seconds_= (s: Int) = - if (0 <= s && s < 60) this.s = s - else throw new DateError() - } - - val d = new TimeOfDayVar - d.hours = 8; d.minutes = 30; d.seconds = 0 - try { d.hours = 25 // throws a DateError exception - } catch { - case de: DateError => println("DateError") - case e: Exception => println("Exception") - } - }; - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) -} diff --git a/test/pending/run/t5258b.scala b/test/pending/run/t5258b.scala index 70cb4a7f4e..3a603095b3 100644 --- a/test/pending/run/t5258b.scala +++ b/test/pending/run/t5258b.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } \ No newline at end of file diff --git a/test/pending/run/t5258c.scala b/test/pending/run/t5258c.scala index a93170d0d6..b0d16ba0b1 100644 --- a/test/pending/run/t5258c.scala +++ b/test/pending/run/t5258c.scala @@ -10,6 +10,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } \ No newline at end of file diff --git a/test/pending/run/t5271_1.check b/test/pending/run/t5271_1.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5271_1.scala b/test/pending/run/t5271_1.scala new file mode 100644 index 0000000000..afbd8fe465 --- /dev/null +++ b/test/pending/run/t5271_1.scala @@ -0,0 +1,13 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/pending/run/t5271_2.check b/test/pending/run/t5271_2.check new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/test/pending/run/t5271_2.check @@ -0,0 +1 @@ +4 diff --git a/test/pending/run/t5271_2.scala b/test/pending/run/t5271_2.scala new file mode 100644 index 0000000000..d85d945973 --- /dev/null +++ b/test/pending/run/t5271_2.scala @@ -0,0 +1,15 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + case class C(foo: Int, bar: Int) + val c = C(2, 2) + println(c.foo * c.bar) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/pending/run/t5271_3.check b/test/pending/run/t5271_3.check new file mode 100644 index 0000000000..f32a5804e2 --- /dev/null +++ b/test/pending/run/t5271_3.check @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/test/pending/run/t5271_3.scala b/test/pending/run/t5271_3.scala new file mode 100644 index 0000000000..5a624de903 --- /dev/null +++ b/test/pending/run/t5271_3.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val code = scala.reflect.Code.lift{ + object C { def qwe = 4 } + case class C(foo: Int, bar: Int) + val c = C(2, 2) + println(c.foo * c.bar == C.qwe) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + toolbox.runExpr(code.tree) +} diff --git a/test/pending/run/t5418.scala b/test/pending/run/t5418.scala index 065710f15e..fe813cf5ae 100644 --- a/test/pending/run/t5418.scala +++ b/test/pending/run/t5418.scala @@ -9,6 +9,5 @@ object Test extends App { val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - toolbox.runExpr(ttree) + toolbox.runExpr(code.tree) } \ No newline at end of file -- cgit v1.2.3 From bb23d766bceccecc99280b543001bc70e16afbc9 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 14 Feb 2012 22:04:30 -0800 Subject: Specialization action. The crickets at http://www.scala-lang.org/node/11901 were in unanimous agreement that I should proceed as suggested. - No arguments to @specialize gets you 10/10, not 9/10 - Fixed bugs in AnyRef specialization revealed by trying to use it - Specialized Function1 on AnyRef. - Changed AnyRef specialization to use OBJECT_TAG, not TVAR_TAG. - Deprecated SpecializableCompanion in favor of Specializable, which has the virtue of being public so it can be referenced from outside the library. - Cooked up mechanism to group specializable types so we don't have to repeat ourselves quite so much, and create a few groups for illustrative purposes. I'm not too serious about those names but I used up all my name-thinking-up brain for the day. - Updated genprod and friends since I had to regenerate Function1. - Put tests for a bunch of remaining specialization bugs in pending. Closes SI-4740, SI-4770, SI-5267. --- lib/scala-compiler.jar.desired.sha1 | 2 +- lib/scala-library-src.jar.desired.sha1 | 2 +- lib/scala-library.jar.desired.sha1 | 2 +- src/build/genprod.scala | 27 +++++---- .../reflect/internal/ClassfileConstants.scala | 1 + .../scala/reflect/internal/Definitions.scala | 25 ++++++--- .../tools/nsc/transform/SpecializeTypes.scala | 65 +++++++++++++--------- .../scala/tools/nsc/typechecker/Duplicators.scala | 31 +++++++---- src/library/scala/AnyValCompanion.scala | 2 +- src/library/scala/Function0.scala | 14 +++-- src/library/scala/Function1.scala | 14 ++--- src/library/scala/Function10.scala | 4 +- src/library/scala/Function11.scala | 4 +- src/library/scala/Function12.scala | 4 +- src/library/scala/Function13.scala | 4 +- src/library/scala/Function14.scala | 4 +- src/library/scala/Function15.scala | 4 +- src/library/scala/Function16.scala | 4 +- src/library/scala/Function17.scala | 4 +- src/library/scala/Function18.scala | 4 +- src/library/scala/Function19.scala | 4 +- src/library/scala/Function2.scala | 14 +++-- src/library/scala/Function20.scala | 4 +- src/library/scala/Function21.scala | 4 +- src/library/scala/Function22.scala | 4 +- src/library/scala/Function3.scala | 4 +- src/library/scala/Function4.scala | 4 +- src/library/scala/Function5.scala | 4 +- src/library/scala/Function6.scala | 4 +- src/library/scala/Function7.scala | 4 +- src/library/scala/Function8.scala | 4 +- src/library/scala/Function9.scala | 4 +- src/library/scala/Predef.scala | 3 +- src/library/scala/Product1.scala | 4 +- src/library/scala/Product10.scala | 4 +- src/library/scala/Product11.scala | 4 +- src/library/scala/Product12.scala | 4 +- src/library/scala/Product13.scala | 4 +- src/library/scala/Product14.scala | 4 +- src/library/scala/Product15.scala | 4 +- src/library/scala/Product16.scala | 4 +- src/library/scala/Product17.scala | 4 +- src/library/scala/Product18.scala | 4 +- src/library/scala/Product19.scala | 4 +- src/library/scala/Product2.scala | 4 +- src/library/scala/Product20.scala | 4 +- src/library/scala/Product21.scala | 4 +- src/library/scala/Product22.scala | 4 +- src/library/scala/Product3.scala | 4 +- src/library/scala/Product4.scala | 4 +- src/library/scala/Product5.scala | 4 +- src/library/scala/Product6.scala | 4 +- src/library/scala/Product7.scala | 4 +- src/library/scala/Product8.scala | 4 +- src/library/scala/Product9.scala | 4 +- src/library/scala/Specializable.scala | 29 ++++++++++ src/library/scala/SpecializableCompanion.scala | 1 + src/library/scala/Tuple1.scala | 2 +- src/library/scala/Tuple10.scala | 2 +- src/library/scala/Tuple11.scala | 2 +- src/library/scala/Tuple12.scala | 2 +- src/library/scala/Tuple13.scala | 2 +- src/library/scala/Tuple14.scala | 2 +- src/library/scala/Tuple15.scala | 2 +- src/library/scala/Tuple16.scala | 2 +- src/library/scala/Tuple17.scala | 2 +- src/library/scala/Tuple18.scala | 2 +- src/library/scala/Tuple19.scala | 2 +- src/library/scala/Tuple2.scala | 2 +- src/library/scala/Tuple20.scala | 2 +- src/library/scala/Tuple21.scala | 2 +- src/library/scala/Tuple22.scala | 2 +- src/library/scala/Tuple3.scala | 2 +- src/library/scala/Tuple4.scala | 2 +- src/library/scala/Tuple5.scala | 2 +- src/library/scala/Tuple6.scala | 2 +- src/library/scala/Tuple7.scala | 2 +- src/library/scala/Tuple8.scala | 2 +- src/library/scala/Tuple9.scala | 2 +- src/library/scala/package.scala | 8 +++ src/library/scala/runtime/AbstractFunction1.scala | 2 +- src/library/scala/specialized.scala | 13 +++-- test/files/buildmanager/t2652/t2652.check | 2 +- test/files/pos/spec-Function1.scala | 2 +- test/files/pos/spec-groups.scala | 65 ++++++++++++++++++++++ test/files/pos/specialize10.scala | 7 +++ test/files/run/t3575.check | 4 ++ test/files/run/t3575.scala | 12 ++++ test/files/run/t4770.check | 2 + test/files/run/t4770.scala | 15 +++++ test/files/run/t4794.check | 2 +- test/files/specialized/arrays-traits.check | 8 +-- test/files/specialized/arrays-traits.scala | 17 +----- test/files/specialized/arrays.check | 6 +- test/pending/pos/t4012.scala | 7 +++ test/pending/pos/t4541.scala | 10 ++++ test/pending/pos/t4786.scala | 24 ++++++++ test/pending/pos/t4790.scala | 4 ++ test/pending/run/t4511.scala | 10 ++++ test/pending/run/t4971.scala | 16 ++++++ test/pending/run/t5284.scala | 14 +++++ 101 files changed, 458 insertions(+), 236 deletions(-) create mode 100644 src/library/scala/Specializable.scala create mode 100644 test/files/pos/spec-groups.scala create mode 100644 test/files/pos/specialize10.scala create mode 100644 test/files/run/t3575.check create mode 100644 test/files/run/t3575.scala create mode 100644 test/files/run/t4770.check create mode 100644 test/files/run/t4770.scala create mode 100644 test/pending/pos/t4012.scala create mode 100644 test/pending/pos/t4541.scala create mode 100644 test/pending/pos/t4786.scala create mode 100644 test/pending/pos/t4790.scala create mode 100644 test/pending/run/t4511.scala create mode 100644 test/pending/run/t4971.scala create mode 100644 test/pending/run/t5284.scala (limited to 'test/pending/run') diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1 index c7f298f70b..2a56ab3880 100644 --- a/lib/scala-compiler.jar.desired.sha1 +++ b/lib/scala-compiler.jar.desired.sha1 @@ -1 +1 @@ -6e00ec5544e9e363edbdd8f46ff1f08441a46b95 ?scala-compiler.jar +797b3233ce29c4c565118742160c6c5c08800b94 ?scala-compiler.jar diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1 index 258d23a924..b187227638 100644 --- a/lib/scala-library-src.jar.desired.sha1 +++ b/lib/scala-library-src.jar.desired.sha1 @@ -1 +1 @@ -a2554c00ffd660d5ddb564e6a789f2f53080aceb ?scala-library-src.jar +dab2f9528a6135e2026650a86eea7aea542515f9 ?scala-library-src.jar diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1 index d0195909ae..a1c2895ff9 100644 --- a/lib/scala-library.jar.desired.sha1 +++ b/lib/scala-library.jar.desired.sha1 @@ -1 +1 @@ -73ad66b65fa3e609a730270769c0885425782ce9 ?scala-library.jar +c294c9d88e1b65320caf21fc96b65b11785cb381 ?scala-library.jar diff --git a/src/build/genprod.scala b/src/build/genprod.scala index 9e5b6810c1..a43b5e02c7 100644 --- a/src/build/genprod.scala +++ b/src/build/genprod.scala @@ -97,7 +97,7 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */ object FunctionZero extends Function(0) { override def genprodString = "\n// genprod generated these sources at: " + new java.util.Date() override def covariantSpecs = "@specialized " - override def descriptiveComment = functionNTemplate.format("javaVersion", "anonfun0", + override def descriptiveComment = " " + functionNTemplate.format("javaVersion", "anonfun0", """ * val javaVersion = () => sys.props("java.version") * @@ -111,10 +111,10 @@ object FunctionZero extends Function(0) { object FunctionOne extends Function(1) { override def classAnnotation = "@annotation.implicitNotFound(msg = \"No implicit view available from ${T1} => ${R}.\")\n" - override def contravariantSpecs = "@specialized(scala.Int, scala.Long, scala.Float, scala.Double) " - override def covariantSpecs = "@specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) " + override def contravariantSpecs = "@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) " + override def covariantSpecs = "@specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) " - override def descriptiveComment = functionNTemplate.format("succ", "anonfun1", + override def descriptiveComment = " " + functionNTemplate.format("succ", "anonfun1", """ * val succ = (x: Int) => x + 1 * val anonfun1 = new Function1[Int, Int] { @@ -146,7 +146,7 @@ object FunctionTwo extends Function(2) { override def contravariantSpecs = "@specialized(scala.Int, scala.Long, scala.Double) " override def covariantSpecs = "@specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) " - override def descriptiveComment = functionNTemplate.format("max", "anonfun2", + override def descriptiveComment = " " + functionNTemplate.format("max", "anonfun2", """ * val max = (x: Int, y: Int) => if (x < y) y else x * @@ -175,14 +175,20 @@ class Function(val i: Int) extends Group("Function") with Arity { * * {{{ * object Main extends App { %s } - * }}}""" + * }}} + * + * Note that `Function1` does not define a total function, as might + * be suggested by the existence of [[scala.PartialFunction]]. The only + * distinction between `Function1` and `PartialFunction` is that the + * latter can specify inputs which it will not handle. + """ def toStr() = "\"" + ("" format i) + "\"" def apply() = { {header} /** A function of {i} parameter{s}. - * {descriptiveComment} + *{descriptiveComment} */ {classAnnotation}trait {className}{contraCoArgs} extends AnyRef {{ self => /** Apply the body of this function to the argument{s}. @@ -211,12 +217,11 @@ class Function(val i: Int) extends Group("Function") with Arity { ) // f(x1,x2,x3,x4,x5,x6) == (f.curried)(x1)(x2)(x3)(x4)(x5)(x6) - def curryComment = { """ - /** Creates a curried version of this function. + def curryComment = { +"""/** Creates a curried version of this function. * * @return a function `f` such that `f%s == apply%s` - */ -""".format(xdefs map ("(" + _ + ")") mkString, commaXs) + */""".format(xdefs map ("(" + _ + ")") mkString, commaXs) } def tupleMethod = { diff --git a/src/compiler/scala/reflect/internal/ClassfileConstants.scala b/src/compiler/scala/reflect/internal/ClassfileConstants.scala index f1bf41ede9..1c4c007de0 100644 --- a/src/compiler/scala/reflect/internal/ClassfileConstants.scala +++ b/src/compiler/scala/reflect/internal/ClassfileConstants.scala @@ -88,6 +88,7 @@ object ClassfileConstants { final val ARRAY_TAG = '[' final val VOID_TAG = 'V' final val TVAR_TAG = 'T' + final val OBJECT_TAG = 'L' final val ANNOTATION_TAG = '@' final val SCALA_NOTHING = "scala.runtime.Nothing$" final val SCALA_NULL = "scala.runtime.Null$" diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 5b2c61701d..b4b0a7335d 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -71,7 +71,7 @@ trait Definitions extends reflect.api.StandardDefinitions { tpnme.Double -> DOUBLE_TAG, tpnme.Boolean -> BOOL_TAG, tpnme.Unit -> VOID_TAG, - tpnme.Object -> TVAR_TAG + tpnme.Object -> OBJECT_TAG ) private def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f) @@ -128,6 +128,7 @@ trait Definitions extends reflect.api.StandardDefinitions { FloatClass, DoubleClass ) + def ScalaValueClassCompanions: List[Symbol] = ScalaValueClasses map (_.companionSymbol) } object definitions extends AbsDefinitions with ValueClassDefinitions { @@ -209,8 +210,12 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val AnyClass = newClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT) lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.typeConstructor) lazy val ObjectClass = getClass(sn.Object) - lazy val AnyCompanionClass = getRequiredClass("scala.AnyCompanion") initFlags (SEALED | ABSTRACT | TRAIT) - lazy val AnyValCompanionClass = getRequiredClass("scala.AnyValCompanion") initFlags (SEALED | ABSTRACT | TRAIT) + + // Note: this is not the type alias AnyRef, it's a companion-like + // object used by the @specialize annotation. + def AnyRefModule = getMember(ScalaPackageClass, nme.AnyRef) + @deprecated("Use AnyRefModule", "2.10.0") + def Predef_AnyRef = AnyRefModule // bottom types lazy val RuntimeNothingClass = getClass(fulltpnme.RuntimeNothing) @@ -265,9 +270,7 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val PredefModule: Symbol = getRequiredModule("scala.Predef") lazy val PredefModuleClass = PredefModule.moduleClass - // Note: this is not the type alias AnyRef, it's a val defined in Predef - // used by the @specialize annotation. - def Predef_AnyRef = getMember(PredefModule, nme.AnyRef) + def Predef_classOf = getMember(PredefModule, nme.classOf) def Predef_identity = getMember(PredefModule, nme.identity) def Predef_conforms = getMember(PredefModule, nme.conforms) @@ -281,6 +284,11 @@ trait Definitions extends reflect.api.StandardDefinitions { def isPredefMemberNamed(sym: Symbol, name: Name) = ( (sym.name == name) && (sym.owner == PredefModule.moduleClass) ) + + /** Specialization. + */ + lazy val SpecializableModule = getRequiredModule("scala.Specializable") + lazy val GroupOfSpecializable = SpecializableModule.info.member(newTypeName("Group")) lazy val ConsoleModule: Symbol = getRequiredModule("scala.Console") lazy val ScalaRunTimeModule: Symbol = getRequiredModule("scala.runtime.ScalaRunTime") @@ -883,8 +891,9 @@ trait Definitions extends reflect.api.StandardDefinitions { private lazy val boxedValueClassesSet = boxedClass.values.toSet + BoxedUnitClass /** Is symbol a value class? */ - def isValueClass(sym: Symbol) = scalaValueClassesSet(sym) - def isNonUnitValueClass(sym: Symbol) = (sym != UnitClass) && isValueClass(sym) + def isValueClass(sym: Symbol) = scalaValueClassesSet(sym) + def isNonUnitValueClass(sym: Symbol) = isValueClass(sym) && (sym != UnitClass) + def isSpecializableClass(sym: Symbol) = isValueClass(sym) || (sym == AnyRefClass) def isScalaValueType(tp: Type) = scalaValueClassesSet(tp.typeSymbol) /** Is symbol a boxed value class, e.g. java.lang.Integer? */ diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 4012d08e42..05f5dbc379 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -6,12 +6,9 @@ package scala.tools.nsc package transform - import scala.tools.nsc.symtab.Flags import scala.collection.{ mutable, immutable } - - /** Specialize code on types. * * Make sure you've read the thesis: @@ -71,10 +68,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { RootClass, BooleanClass, UnitClass, ArrayClass, ScalaValueClasses, isValueClass, isScalaValueType, SpecializedClass, RepeatedParamClass, JavaRepeatedParamClass, - AnyRefClass, ObjectClass, Predef_AnyRef, - uncheckedVarianceClass + AnyRefClass, ObjectClass, AnyRefModule, + GroupOfSpecializable, uncheckedVarianceClass } - + /** TODO - this is a lot of maps. */ @@ -105,16 +102,26 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def isSpecialized(sym: Symbol) = sym hasAnnotation SpecializedClass private def hasSpecializedFlag(sym: Symbol) = sym hasFlag SPECIALIZED private def specializedTypes(tps: List[Symbol]) = tps filter isSpecialized - private def specializedOn(sym: Symbol) = sym getAnnotation SpecializedClass match { - case Some(AnnotationInfo(_, args, _)) => args - case _ => Nil + private def specializedOn(sym: Symbol): List[Symbol] = { + sym getAnnotation SpecializedClass match { + case Some(ann @ AnnotationInfo(_, args, _)) => + args map (_.tpe) flatMap { tp => + tp baseType GroupOfSpecializable match { + case TypeRef(_, GroupOfSpecializable, arg :: Nil) => + arg.typeArgs map (_.typeSymbol) + case _ => + List(tp.typeSymbol) + } + } + case _ => Nil + } } // If we replace `isBoundedGeneric` with (tp <:< AnyRefClass.tpe), // then pos/spec-List.scala fails - why? Does this kind of check fail // for similar reasons? Does `sym.isAbstractType` make a difference? private def isSpecializedAnyRefSubtype(tp: Type, sym: Symbol) = ( - specializedOn(sym).exists(_.symbol == Predef_AnyRef) // specialized on AnyRef + (specializedOn(sym) contains AnyRefModule) && !isValueClass(tp.typeSymbol) && isBoundedGeneric(tp) ) @@ -322,28 +329,34 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - lazy val primitiveTypes = ScalaValueClasses map (_.tpe) + lazy val specializableTypes = (ScalaValueClasses :+ AnyRefClass) map (_.tpe) sorted + + /** If the symbol is the companion of a value class, the value class. + * Otherwise, AnyRef. + */ + def specializesClass(sym: Symbol): Symbol = { + val c = sym.companionClass + if (isValueClass(c)) c else AnyRefClass + } /** Return the types `sym` should be specialized at. This may be some of the primitive types * or AnyRef. AnyRef means that a new type parameter T will be generated later, known to be a * subtype of AnyRef (T <: AnyRef). * These are in a meaningful order for stability purposes. */ - def concreteTypes(sym: Symbol): List[Type] = ( - if (!isSpecialized(sym)) Nil // no @specialized Annotation - else specializedOn(sym) match { - case Nil => primitiveTypes // specialized on everything - case args => // specialized on args - (args map { tp => - if (tp.symbol == Predef_AnyRef) { - if (isBoundedGeneric(sym.tpe)) - reporter.warning(sym.pos, sym + " is always a subtype of " + AnyRefClass.tpe + ".") - AnyRefClass.tpe - } - else tp.symbol.companionClass.tpe - }).sorted - } - ) + def concreteTypes(sym: Symbol): List[Type] = { + val types = ( + if (!isSpecialized(sym)) Nil // no @specialized Annotation + else specializedOn(sym) match { + case Nil => specializableTypes // specialized on everything + case args => args map (s => specializesClass(s).tpe) sorted // specialized on args + } + ) + if (isBoundedGeneric(sym.tpe) && (types contains AnyRefClass)) + reporter.warning(sym.pos, sym + " is always a subtype of " + AnyRefClass.tpe + ".") + + types + } /** Return a list of all type environments for all specializations * of @specialized types in `tps`. diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 3536608efd..179bea0035 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package typechecker import scala.tools.nsc.symtab.Flags - import scala.collection.{ mutable, immutable } /** Duplicate trees and re-type check them, taking care to replace @@ -18,6 +17,7 @@ import scala.collection.{ mutable, immutable } */ abstract class Duplicators extends Analyzer { import global._ + import definitions.{ AnyRefClass, AnyValClass } def retyped(context: Context, tree: Tree): Tree = { resetClassOwners @@ -308,17 +308,26 @@ abstract class Duplicators extends Analyzer { super.typed(atPos(tree.pos)(tree1)) */ case Match(scrut, cases) => - val scrut1 = typed(scrut, EXPRmode | BYVALmode, WildcardType) + val scrut1 = typed(scrut, EXPRmode | BYVALmode, WildcardType) val scrutTpe = scrut1.tpe.widen - val cases1 = if (scrutTpe.isFinalType) cases filter { - case CaseDef(Bind(_, pat @ Typed(_, tpt)), EmptyTree, body) => - // the typed pattern is not incompatible with the scrutinee type - scrutTpe.matchesPattern(fixType(tpt.tpe)) - case CaseDef(Typed(_, tpt), EmptyTree, body) => - // the typed pattern is not incompatible with the scrutinee type - scrutTpe.matchesPattern(fixType(tpt.tpe)) - case _ => true - } else cases + val cases1 = { + if (scrutTpe.isFinalType) cases filter { + case CaseDef(Bind(_, pat @ Typed(_, tpt)), EmptyTree, body) => + // the typed pattern is not incompatible with the scrutinee type + scrutTpe matchesPattern fixType(tpt.tpe) + case CaseDef(Typed(_, tpt), EmptyTree, body) => + // the typed pattern is not incompatible with the scrutinee type + scrutTpe matchesPattern fixType(tpt.tpe) + case _ => true + } + // Without this, AnyRef specializations crash on patterns like + // case _: Boolean => ... + // Not at all sure this is safe. + else if (scrutTpe <:< AnyRefClass.tpe) + cases filterNot (_.pat.tpe <:< AnyValClass.tpe) + else + cases + } super.typed(atPos(tree.pos)(Match(scrut, cases1)), mode, pt) diff --git a/src/library/scala/AnyValCompanion.scala b/src/library/scala/AnyValCompanion.scala index d6cb498185..47555938a0 100644 --- a/src/library/scala/AnyValCompanion.scala +++ b/src/library/scala/AnyValCompanion.scala @@ -18,4 +18,4 @@ package scala * }}} * */ -private[scala] trait AnyValCompanion extends SpecializableCompanion { } +private[scala] trait AnyValCompanion extends Specializable { } diff --git a/src/library/scala/Function0.scala b/src/library/scala/Function0.scala index f68bbcc454..508ef25e81 100644 --- a/src/library/scala/Function0.scala +++ b/src/library/scala/Function0.scala @@ -6,18 +6,18 @@ ** |/ ** \* */ // GENERATED CODE: DO NOT EDIT. -// genprod generated these sources at: Sun Jul 31 00:37:30 CEST 2011 +// genprod generated these sources at: Tue Feb 14 16:49:03 PST 2012 package scala /** A function of 0 parameters. - * + * * In the following example, the definition of javaVersion is a * shorthand for the anonymous class definition anonfun0: * * {{{ - * object Main extends Application { + * object Main extends App { * val javaVersion = () => sys.props("java.version") * * val anonfun0 = new Function0[String] { @@ -26,12 +26,18 @@ package scala * assert(javaVersion() == anonfun0()) * } * }}} + * + * Note that `Function1` does not define a total function, as might + * be suggested by the existence of [[scala.PartialFunction]]. The only + * distinction between `Function1` and `PartialFunction` is that the + * latter can specify inputs which it will not handle. + */ trait Function0[@specialized +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(): R - + override def toString() = "" } diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala index 7517e6604b..06936e54cb 100644 --- a/src/library/scala/Function1.scala +++ b/src/library/scala/Function1.scala @@ -11,12 +11,12 @@ package scala /** A function of 1 parameter. - * + * * In the following example, the definition of succ is a * shorthand for the anonymous class definition anonfun1: * * {{{ - * object Main extends Application { + * object Main extends App { * val succ = (x: Int) => x + 1 * val anonfun1 = new Function1[Int, Int] { * def apply(x: Int): Int = x + 1 @@ -29,17 +29,15 @@ package scala * be suggested by the existence of [[scala.PartialFunction]]. The only * distinction between `Function1` and `PartialFunction` is that the * latter can specify inputs which it will not handle. - * + */ @annotation.implicitNotFound(msg = "No implicit view available from ${T1} => ${R}.") -trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef { self => - /** Apply the body of this function to the argument. It may throw an - * exception. - * +trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends AnyRef { self => + /** Apply the body of this function to the argument. * @return the result of function application. */ def apply(v1: T1): R - + /** Composes two instances of Function1 in a new Function1, with this function applied last. * * @tparam A the type to which function `g` can be applied diff --git a/src/library/scala/Function10.scala b/src/library/scala/Function10.scala index 6f17606afd..9e107fc53d 100644 --- a/src/library/scala/Function10.scala +++ b/src/library/scala/Function10.scala @@ -18,12 +18,10 @@ trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)).curried } diff --git a/src/library/scala/Function11.scala b/src/library/scala/Function11.scala index 7a73bd35bf..783a86ab5d 100644 --- a/src/library/scala/Function11.scala +++ b/src/library/scala/Function11.scala @@ -18,12 +18,10 @@ trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] ex * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)).curried } diff --git a/src/library/scala/Function12.scala b/src/library/scala/Function12.scala index c099c0436a..7f4dee6216 100644 --- a/src/library/scala/Function12.scala +++ b/src/library/scala/Function12.scala @@ -18,12 +18,10 @@ trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)).curried } diff --git a/src/library/scala/Function13.scala b/src/library/scala/Function13.scala index f13db28f30..23853dde69 100644 --- a/src/library/scala/Function13.scala +++ b/src/library/scala/Function13.scala @@ -18,12 +18,10 @@ trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)).curried } diff --git a/src/library/scala/Function14.scala b/src/library/scala/Function14.scala index d0345cc552..372f1cfafb 100644 --- a/src/library/scala/Function14.scala +++ b/src/library/scala/Function14.scala @@ -18,12 +18,10 @@ trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)).curried } diff --git a/src/library/scala/Function15.scala b/src/library/scala/Function15.scala index 69ff039f5b..47c7309695 100644 --- a/src/library/scala/Function15.scala +++ b/src/library/scala/Function15.scala @@ -18,12 +18,10 @@ trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)).curried } diff --git a/src/library/scala/Function16.scala b/src/library/scala/Function16.scala index d544d89303..8eea42de5b 100644 --- a/src/library/scala/Function16.scala +++ b/src/library/scala/Function16.scala @@ -18,12 +18,10 @@ trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)).curried } diff --git a/src/library/scala/Function17.scala b/src/library/scala/Function17.scala index 16c71e7ada..2d93af34f2 100644 --- a/src/library/scala/Function17.scala +++ b/src/library/scala/Function17.scala @@ -18,12 +18,10 @@ trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)).curried } diff --git a/src/library/scala/Function18.scala b/src/library/scala/Function18.scala index dfd70c2353..ffca98c443 100644 --- a/src/library/scala/Function18.scala +++ b/src/library/scala/Function18.scala @@ -18,12 +18,10 @@ trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)).curried } diff --git a/src/library/scala/Function19.scala b/src/library/scala/Function19.scala index 63decd03ad..f661ea7707 100644 --- a/src/library/scala/Function19.scala +++ b/src/library/scala/Function19.scala @@ -18,12 +18,10 @@ trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)).curried } diff --git a/src/library/scala/Function2.scala b/src/library/scala/Function2.scala index a4ad87fa97..1812f042e0 100644 --- a/src/library/scala/Function2.scala +++ b/src/library/scala/Function2.scala @@ -11,12 +11,12 @@ package scala /** A function of 2 parameters. - * + * * In the following example, the definition of max is a * shorthand for the anonymous class definition anonfun2: * * {{{ - * object Main extends Application { + * object Main extends App { * val max = (x: Int, y: Int) => if (x < y) y else x * * val anonfun2 = new Function2[Int, Int, Int] { @@ -25,18 +25,22 @@ package scala * assert(max(0, 1) == anonfun2(0, 1)) * } * }}} + * + * Note that `Function1` does not define a total function, as might + * be suggested by the existence of [[scala.PartialFunction]]. The only + * distinction between `Function1` and `PartialFunction` is that the + * latter can specify inputs which it will not handle. + */ trait Function2[@specialized(scala.Int, scala.Long, scala.Double) -T1, @specialized(scala.Int, scala.Long, scala.Double) -T2, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends AnyRef { self => /** Apply the body of this function to the arguments. * @return the result of function application. */ def apply(v1: T1, v2: T2): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2) == apply(x1, x2)` - */ - def curried: T1 => T2 => R = { + */ def curried: T1 => T2 => R = { (x1: T1) => (x2: T2) => apply(x1, x2) } diff --git a/src/library/scala/Function20.scala b/src/library/scala/Function20.scala index 7219c9be81..e4fb9f280c 100644 --- a/src/library/scala/Function20.scala +++ b/src/library/scala/Function20.scala @@ -18,12 +18,10 @@ trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)).curried } diff --git a/src/library/scala/Function21.scala b/src/library/scala/Function21.scala index c7d55960db..9823386856 100644 --- a/src/library/scala/Function21.scala +++ b/src/library/scala/Function21.scala @@ -18,12 +18,10 @@ trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20, v21: T21): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)).curried } diff --git a/src/library/scala/Function22.scala b/src/library/scala/Function22.scala index 196421c830..e708f7f49a 100644 --- a/src/library/scala/Function22.scala +++ b/src/library/scala/Function22.scala @@ -18,12 +18,10 @@ trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12, * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9, v10: T10, v11: T11, v12: T12, v13: T13, v14: T14, v15: T15, v16: T16, v17: T17, v18: T18, v19: T19, v20: T20, v21: T21, v22: T22): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21)(x22) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => T22 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => T22 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21, x22: T22) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)).curried } diff --git a/src/library/scala/Function3.scala b/src/library/scala/Function3.scala index 09a5aa5828..62a997c1b5 100644 --- a/src/library/scala/Function3.scala +++ b/src/library/scala/Function3.scala @@ -18,12 +18,10 @@ trait Function3[-T1, -T2, -T3, +R] extends AnyRef { self => * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3) == apply(x1, x2, x3)` - */ - def curried: T1 => T2 => T3 => R = { + */ def curried: T1 => T2 => T3 => R = { (x1: T1) => (x2: T2) => (x3: T3) => apply(x1, x2, x3) } diff --git a/src/library/scala/Function4.scala b/src/library/scala/Function4.scala index 00da84636a..86d2faeac8 100644 --- a/src/library/scala/Function4.scala +++ b/src/library/scala/Function4.scala @@ -18,12 +18,10 @@ trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { self => * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4) == apply(x1, x2, x3, x4)` - */ - def curried: T1 => T2 => T3 => T4 => R = { + */ def curried: T1 => T2 => T3 => T4 => R = { (x1: T1) => (x2: T2) => (x3: T3) => (x4: T4) => apply(x1, x2, x3, x4) } diff --git a/src/library/scala/Function5.scala b/src/library/scala/Function5.scala index 3915048906..bd9af77f12 100644 --- a/src/library/scala/Function5.scala +++ b/src/library/scala/Function5.scala @@ -18,12 +18,10 @@ trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { self => * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5) == apply(x1, x2, x3, x4, x5)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5) => self.apply(x1, x2, x3, x4, x5)).curried } diff --git a/src/library/scala/Function6.scala b/src/library/scala/Function6.scala index 183a7332e1..4f601a468c 100644 --- a/src/library/scala/Function6.scala +++ b/src/library/scala/Function6.scala @@ -18,12 +18,10 @@ trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { self => * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6) == apply(x1, x2, x3, x4, x5, x6)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6) => self.apply(x1, x2, x3, x4, x5, x6)).curried } diff --git a/src/library/scala/Function7.scala b/src/library/scala/Function7.scala index 10f8e9b599..6978b6545d 100644 --- a/src/library/scala/Function7.scala +++ b/src/library/scala/Function7.scala @@ -18,12 +18,10 @@ trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { self => * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7) == apply(x1, x2, x3, x4, x5, x6, x7)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7) => self.apply(x1, x2, x3, x4, x5, x6, x7)).curried } diff --git a/src/library/scala/Function8.scala b/src/library/scala/Function8.scala index 8144b36101..903551d939 100644 --- a/src/library/scala/Function8.scala +++ b/src/library/scala/Function8.scala @@ -18,12 +18,10 @@ trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { sel * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8) == apply(x1, x2, x3, x4, x5, x6, x7, x8)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8)).curried } diff --git a/src/library/scala/Function9.scala b/src/library/scala/Function9.scala index ee04ed0915..0c273ba929 100644 --- a/src/library/scala/Function9.scala +++ b/src/library/scala/Function9.scala @@ -18,12 +18,10 @@ trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef * @return the result of function application. */ def apply(v1: T1, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7, v8: T8, v9: T9): R - /** Creates a curried version of this function. * * @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)` - */ - def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => R = { + */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => R = { (x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)).curried } diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 824e048e73..a2ee76500c 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -95,7 +95,8 @@ object Predef extends LowPriorityImplicits { type Set[A] = immutable.Set[A] val Map = immutable.Map val Set = immutable.Set - val AnyRef = new SpecializableCompanion {} // a dummy used by the specialization annotation + // @deprecated("Use scala.AnyRef instead", "2.10.0") + // def AnyRef = scala.AnyRef // Manifest types, companions, and incantations for summoning type ClassManifest[T] = scala.reflect.ClassManifest[T] diff --git a/src/library/scala/Product1.scala b/src/library/scala/Product1.scala index ab8b0a4505..0106ad34ee 100644 --- a/src/library/scala/Product1.scala +++ b/src/library/scala/Product1.scala @@ -23,7 +23,7 @@ trait Product1[@specialized(Int, Long, Double) +T1] extends Product { */ override def productArity = 1 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product1[@specialized(Int, Long, Double) +T1] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case _ => throw new IndexOutOfBoundsException(n.toString()) } diff --git a/src/library/scala/Product10.scala b/src/library/scala/Product10.scala index 536fb2fed9..ca53b580c0 100644 --- a/src/library/scala/Product10.scala +++ b/src/library/scala/Product10.scala @@ -23,7 +23,7 @@ trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Produ */ override def productArity = 10 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Produ */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product11.scala b/src/library/scala/Product11.scala index 7d49eccc5e..3d5942f3fa 100644 --- a/src/library/scala/Product11.scala +++ b/src/library/scala/Product11.scala @@ -23,7 +23,7 @@ trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends */ override def productArity = 11 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product12.scala b/src/library/scala/Product12.scala index 0e9c4a01a2..803193793c 100644 --- a/src/library/scala/Product12.scala +++ b/src/library/scala/Product12.scala @@ -23,7 +23,7 @@ trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] e */ override def productArity = 12 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] e */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product13.scala b/src/library/scala/Product13.scala index a0629201d0..0c1d889624 100644 --- a/src/library/scala/Product13.scala +++ b/src/library/scala/Product13.scala @@ -23,7 +23,7 @@ trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 13 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product14.scala b/src/library/scala/Product14.scala index 32dda81c3e..0222309a0a 100644 --- a/src/library/scala/Product14.scala +++ b/src/library/scala/Product14.scala @@ -23,7 +23,7 @@ trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 14 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product15.scala b/src/library/scala/Product15.scala index 57851f9870..41be7ec504 100644 --- a/src/library/scala/Product15.scala +++ b/src/library/scala/Product15.scala @@ -23,7 +23,7 @@ trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 15 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product16.scala b/src/library/scala/Product16.scala index 75076f3b3c..accee3f965 100644 --- a/src/library/scala/Product16.scala +++ b/src/library/scala/Product16.scala @@ -23,7 +23,7 @@ trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 16 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product17.scala b/src/library/scala/Product17.scala index 9ee6072ffe..da80ae9a6b 100644 --- a/src/library/scala/Product17.scala +++ b/src/library/scala/Product17.scala @@ -23,7 +23,7 @@ trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 17 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product18.scala b/src/library/scala/Product18.scala index 25d0839af1..ea25647762 100644 --- a/src/library/scala/Product18.scala +++ b/src/library/scala/Product18.scala @@ -23,7 +23,7 @@ trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 18 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product19.scala b/src/library/scala/Product19.scala index 5464de7264..5d4347c1a8 100644 --- a/src/library/scala/Product19.scala +++ b/src/library/scala/Product19.scala @@ -23,7 +23,7 @@ trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 19 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product2.scala b/src/library/scala/Product2.scala index 8097245926..4e6c70f463 100644 --- a/src/library/scala/Product2.scala +++ b/src/library/scala/Product2.scala @@ -23,7 +23,7 @@ trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Doub */ override def productArity = 2 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Doub */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case _ => throw new IndexOutOfBoundsException(n.toString()) diff --git a/src/library/scala/Product20.scala b/src/library/scala/Product20.scala index b094e09aca..f23a0dee3a 100644 --- a/src/library/scala/Product20.scala +++ b/src/library/scala/Product20.scala @@ -23,7 +23,7 @@ trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 20 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product21.scala b/src/library/scala/Product21.scala index fa06cfb438..4a4fe0697f 100644 --- a/src/library/scala/Product21.scala +++ b/src/library/scala/Product21.scala @@ -23,7 +23,7 @@ trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 21 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product22.scala b/src/library/scala/Product22.scala index 46038bf1a2..7ee01b85ae 100644 --- a/src/library/scala/Product22.scala +++ b/src/library/scala/Product22.scala @@ -23,7 +23,7 @@ trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ override def productArity = 22 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, + */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product3.scala b/src/library/scala/Product3.scala index 3a4cd8fc5e..23563c9e23 100644 --- a/src/library/scala/Product3.scala +++ b/src/library/scala/Product3.scala @@ -23,7 +23,7 @@ trait Product3[+T1, +T2, +T3] extends Product { */ override def productArity = 3 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product3[+T1, +T2, +T3] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product4.scala b/src/library/scala/Product4.scala index a4d47457fa..4abaa9051b 100644 --- a/src/library/scala/Product4.scala +++ b/src/library/scala/Product4.scala @@ -23,7 +23,7 @@ trait Product4[+T1, +T2, +T3, +T4] extends Product { */ override def productArity = 4 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product4[+T1, +T2, +T3, +T4] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product5.scala b/src/library/scala/Product5.scala index 9f25e70af0..9aa4af58b7 100644 --- a/src/library/scala/Product5.scala +++ b/src/library/scala/Product5.scala @@ -23,7 +23,7 @@ trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { */ override def productArity = 5 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product5[+T1, +T2, +T3, +T4, +T5] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product6.scala b/src/library/scala/Product6.scala index 87fd318c68..2ca1d7c31e 100644 --- a/src/library/scala/Product6.scala +++ b/src/library/scala/Product6.scala @@ -23,7 +23,7 @@ trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { */ override def productArity = 6 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product7.scala b/src/library/scala/Product7.scala index d074503315..b7af2d3e32 100644 --- a/src/library/scala/Product7.scala +++ b/src/library/scala/Product7.scala @@ -23,7 +23,7 @@ trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { */ override def productArity = 7 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product8.scala b/src/library/scala/Product8.scala index bd6150c235..17b5e48512 100644 --- a/src/library/scala/Product8.scala +++ b/src/library/scala/Product8.scala @@ -23,7 +23,7 @@ trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { */ override def productArity = 8 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Product9.scala b/src/library/scala/Product9.scala index 1f042944cc..784e9a7029 100644 --- a/src/library/scala/Product9.scala +++ b/src/library/scala/Product9.scala @@ -23,7 +23,7 @@ trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { */ override def productArity = 9 - + /** Returns the n-th projection of this product if 0 < n <= productArity, * otherwise throws an `IndexOutOfBoundsException`. * @@ -33,7 +33,7 @@ trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Product { */ @throws(classOf[IndexOutOfBoundsException]) - override def productElement(n: Int) = n match { + override def productElement(n: Int) = n match { case 0 => _1 case 1 => _2 case 2 => _3 diff --git a/src/library/scala/Specializable.scala b/src/library/scala/Specializable.scala new file mode 100644 index 0000000000..811a735110 --- /dev/null +++ b/src/library/scala/Specializable.scala @@ -0,0 +1,29 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala + +/** A common supertype for companions of specializable types. + * Should not be extended in user code. + */ +trait Specializable extends SpecializableCompanion + +object Specializable { + // No type parameter in @specialized annotation. + trait SpecializedGroup { } + + // Smuggle a list of types by way of a tuple upon which Group is parameterized. + class Group[T >: Null](value: T) extends SpecializedGroup { } + + final val Primitives = new Group(Byte, Short, Int, Long, Char, Float, Double, Boolean, Unit) + final val Everything = new Group(Byte, Short, Int, Long, Char, Float, Double, Boolean, Unit, AnyRef) + final val Bits32AndUp = new Group(Int, Long, Float, Double) + final val Integral = new Group(Byte, Short, Int, Long, Char) + final val AllNumeric = new Group(Byte, Short, Int, Long, Char, Float, Double) + final val BestOfBreed = new Group(Int, Double, Boolean, Unit, AnyRef) +} diff --git a/src/library/scala/SpecializableCompanion.scala b/src/library/scala/SpecializableCompanion.scala index fbdf42fd0b..ec797c1f15 100644 --- a/src/library/scala/SpecializableCompanion.scala +++ b/src/library/scala/SpecializableCompanion.scala @@ -10,4 +10,5 @@ package scala /** A common supertype for companion classes which specialization takes into account. */ +@deprecated("Use Specializable instead", "2.10.0") private[scala] trait SpecializableCompanion diff --git a/src/library/scala/Tuple1.scala b/src/library/scala/Tuple1.scala index 6d31d35e51..02fdd0cba5 100644 --- a/src/library/scala/Tuple1.scala +++ b/src/library/scala/Tuple1.scala @@ -19,5 +19,5 @@ case class Tuple1[@specialized(Int, Long, Double) +T1](_1: T1) extends Product1[T1] { override def toString() = "(" + _1 + ")" - + } diff --git a/src/library/scala/Tuple10.scala b/src/library/scala/Tuple10.scala index 10d554d467..ba2a02a8b2 100644 --- a/src/library/scala/Tuple10.scala +++ b/src/library/scala/Tuple10.scala @@ -28,5 +28,5 @@ case class Tuple10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10](_1: T1, _2 extends Product10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + ")" - + } diff --git a/src/library/scala/Tuple11.scala b/src/library/scala/Tuple11.scala index 2065e4f017..7f51d172d4 100644 --- a/src/library/scala/Tuple11.scala +++ b/src/library/scala/Tuple11.scala @@ -29,5 +29,5 @@ case class Tuple11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11](_1: extends Product11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + ")" - + } diff --git a/src/library/scala/Tuple12.scala b/src/library/scala/Tuple12.scala index a463986752..4bbc6a0eab 100644 --- a/src/library/scala/Tuple12.scala +++ b/src/library/scala/Tuple12.scala @@ -31,5 +31,5 @@ case class Tuple12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + ")" - + } diff --git a/src/library/scala/Tuple13.scala b/src/library/scala/Tuple13.scala index 2bee0d69ad..77bd59bf2e 100644 --- a/src/library/scala/Tuple13.scala +++ b/src/library/scala/Tuple13.scala @@ -32,5 +32,5 @@ case class Tuple13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + ")" - + } diff --git a/src/library/scala/Tuple14.scala b/src/library/scala/Tuple14.scala index 60f7c51e64..bf7a4ce016 100644 --- a/src/library/scala/Tuple14.scala +++ b/src/library/scala/Tuple14.scala @@ -33,5 +33,5 @@ case class Tuple14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + ")" - + } diff --git a/src/library/scala/Tuple15.scala b/src/library/scala/Tuple15.scala index fc8e30580b..582c359bc6 100644 --- a/src/library/scala/Tuple15.scala +++ b/src/library/scala/Tuple15.scala @@ -34,5 +34,5 @@ case class Tuple15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + ")" - + } diff --git a/src/library/scala/Tuple16.scala b/src/library/scala/Tuple16.scala index 80181f6648..a1e9a790ff 100644 --- a/src/library/scala/Tuple16.scala +++ b/src/library/scala/Tuple16.scala @@ -35,5 +35,5 @@ case class Tuple16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + ")" - + } diff --git a/src/library/scala/Tuple17.scala b/src/library/scala/Tuple17.scala index 6236122be2..f531766c18 100644 --- a/src/library/scala/Tuple17.scala +++ b/src/library/scala/Tuple17.scala @@ -36,5 +36,5 @@ case class Tuple17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + ")" - + } diff --git a/src/library/scala/Tuple18.scala b/src/library/scala/Tuple18.scala index dd6a819ac5..a96db25e4b 100644 --- a/src/library/scala/Tuple18.scala +++ b/src/library/scala/Tuple18.scala @@ -37,5 +37,5 @@ case class Tuple18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + ")" - + } diff --git a/src/library/scala/Tuple19.scala b/src/library/scala/Tuple19.scala index 65f0fd22cf..718280d68a 100644 --- a/src/library/scala/Tuple19.scala +++ b/src/library/scala/Tuple19.scala @@ -38,5 +38,5 @@ case class Tuple19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + ")" - + } diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala index dd6ac0cfd2..ad3f7df697 100644 --- a/src/library/scala/Tuple2.scala +++ b/src/library/scala/Tuple2.scala @@ -23,7 +23,7 @@ case class Tuple2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, D extends Product2[T1, T2] { override def toString() = "(" + _1 + "," + _2 + ")" - + /** Swaps the elements of this `Tuple`. * @return a new Tuple where the first element is the second element of this Tuple and the * second element is the first element of this Tuple. diff --git a/src/library/scala/Tuple20.scala b/src/library/scala/Tuple20.scala index cf3626909d..4a44c0bb89 100644 --- a/src/library/scala/Tuple20.scala +++ b/src/library/scala/Tuple20.scala @@ -39,5 +39,5 @@ case class Tuple20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + ")" - + } diff --git a/src/library/scala/Tuple21.scala b/src/library/scala/Tuple21.scala index 78b9c585c6..580a169e39 100644 --- a/src/library/scala/Tuple21.scala +++ b/src/library/scala/Tuple21.scala @@ -40,5 +40,5 @@ case class Tuple21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + ")" - + } diff --git a/src/library/scala/Tuple22.scala b/src/library/scala/Tuple22.scala index 0993dfbbc3..fd3392ddea 100644 --- a/src/library/scala/Tuple22.scala +++ b/src/library/scala/Tuple22.scala @@ -41,5 +41,5 @@ case class Tuple22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12 { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + "," + _10 + "," + _11 + "," + _12 + "," + _13 + "," + _14 + "," + _15 + "," + _16 + "," + _17 + "," + _18 + "," + _19 + "," + _20 + "," + _21 + "," + _22 + ")" - + } diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala index dfa0c962a2..0d5399308b 100644 --- a/src/library/scala/Tuple3.scala +++ b/src/library/scala/Tuple3.scala @@ -24,7 +24,7 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3) extends Product3[T1, T2, T3] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")" - + @deprecated("Use `zipped` instead.", "2.9.0") def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1], diff --git a/src/library/scala/Tuple4.scala b/src/library/scala/Tuple4.scala index a919072c88..a859078bcf 100644 --- a/src/library/scala/Tuple4.scala +++ b/src/library/scala/Tuple4.scala @@ -22,5 +22,5 @@ case class Tuple4[+T1, +T2, +T3, +T4](_1: T1, _2: T2, _3: T3, _4: T4) extends Product4[T1, T2, T3, T4] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + ")" - + } diff --git a/src/library/scala/Tuple5.scala b/src/library/scala/Tuple5.scala index 6a94f48ab4..1edfb673ee 100644 --- a/src/library/scala/Tuple5.scala +++ b/src/library/scala/Tuple5.scala @@ -23,5 +23,5 @@ case class Tuple5[+T1, +T2, +T3, +T4, +T5](_1: T1, _2: T2, _3: T3, _4: T4, _5: T extends Product5[T1, T2, T3, T4, T5] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + ")" - + } diff --git a/src/library/scala/Tuple6.scala b/src/library/scala/Tuple6.scala index 34f8224627..5b74937e58 100644 --- a/src/library/scala/Tuple6.scala +++ b/src/library/scala/Tuple6.scala @@ -24,5 +24,5 @@ case class Tuple6[+T1, +T2, +T3, +T4, +T5, +T6](_1: T1, _2: T2, _3: T3, _4: T4, extends Product6[T1, T2, T3, T4, T5, T6] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + ")" - + } diff --git a/src/library/scala/Tuple7.scala b/src/library/scala/Tuple7.scala index 6fc3477ba2..a7f572e9f0 100644 --- a/src/library/scala/Tuple7.scala +++ b/src/library/scala/Tuple7.scala @@ -25,5 +25,5 @@ case class Tuple7[+T1, +T2, +T3, +T4, +T5, +T6, +T7](_1: T1, _2: T2, _3: T3, _4: extends Product7[T1, T2, T3, T4, T5, T6, T7] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + ")" - + } diff --git a/src/library/scala/Tuple8.scala b/src/library/scala/Tuple8.scala index 1e21b684fc..9bb427d689 100644 --- a/src/library/scala/Tuple8.scala +++ b/src/library/scala/Tuple8.scala @@ -26,5 +26,5 @@ case class Tuple8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8](_1: T1, _2: T2, _3: T3 extends Product8[T1, T2, T3, T4, T5, T6, T7, T8] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + ")" - + } diff --git a/src/library/scala/Tuple9.scala b/src/library/scala/Tuple9.scala index 453cea31a1..4d50539e0c 100644 --- a/src/library/scala/Tuple9.scala +++ b/src/library/scala/Tuple9.scala @@ -27,5 +27,5 @@ case class Tuple9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9](_1: T1, _2: T2, _ extends Product9[T1, T2, T3, T4, T5, T6, T7, T8, T9] { override def toString() = "(" + _1 + "," + _2 + "," + _3 + "," + _4 + "," + _5 + "," + _6 + "," + _7 + "," + _8 + "," + _9 + ")" - + } diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 0c5d10b15e..9425eba232 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -28,6 +28,14 @@ package object scala { type NumberFormatException = java.lang.NumberFormatException type AbstractMethodError = java.lang.AbstractMethodError + // A dummy used by the specialization annotation. + // Normally it's bad juju to place objects inside package objects, + // but there's no choice here as we'd have to be AnyRef's companion + // and defined in the same file - except there is no such file. + object AnyRef extends Specializable { + override def toString = "object AnyRef" + } + @deprecated("instead of `@serializable class C`, use `class C extends Serializable`", "2.9.0") type serializable = annotation.serializable diff --git a/src/library/scala/runtime/AbstractFunction1.scala b/src/library/scala/runtime/AbstractFunction1.scala index a9e5e90e20..b2f336fe52 100644 --- a/src/library/scala/runtime/AbstractFunction1.scala +++ b/src/library/scala/runtime/AbstractFunction1.scala @@ -9,6 +9,6 @@ package scala.runtime -abstract class AbstractFunction1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double) +R] extends Function1[T1, R] { +abstract class AbstractFunction1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends Function1[T1, R] { } diff --git a/src/library/scala/specialized.scala b/src/library/scala/specialized.scala index 902faa166e..b24474f35d 100644 --- a/src/library/scala/specialized.scala +++ b/src/library/scala/specialized.scala @@ -6,10 +6,10 @@ ** |/ ** \* */ - - package scala +import Specializable._ + /** Annotate type parameters on which code should be automatically * specialized. For example: * {{{ @@ -24,8 +24,9 @@ package scala * * @since 2.8 */ -class specialized(types: SpecializableCompanion*) extends annotation.StaticAnnotation { - def this() { - this(Unit, Boolean, Byte, Short, Char, Int, Long, Float, Double) - } +// class tspecialized[T](group: Group[T]) extends annotation.StaticAnnotation { + +class specialized(group: SpecializedGroup) extends annotation.StaticAnnotation { + def this(types: Specializable*) = this(new Group(types.toList)) + def this() = this(Everything) } diff --git a/test/files/buildmanager/t2652/t2652.check b/test/files/buildmanager/t2652/t2652.check index 071281c6ff..b84c80205e 100644 --- a/test/files/buildmanager/t2652/t2652.check +++ b/test/files/buildmanager/t2652/t2652.check @@ -3,7 +3,7 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(class A -> List(Added(Definition(A.x$mBc$sp)), Added(Definition(A.x$mCc$sp)), Added(Definition(A.x$mDc$sp)), Added(Definition(A.x$mFc$sp)), Added(Definition(A.x$mIc$sp)), Added(Definition(A.x$mJc$sp)), Added(Definition(A.x$mSc$sp)), Added(Definition(A.x$mVc$sp)), Added(Definition(A.x$mZc$sp)), Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ])) +Changes: Map(class A -> List(Added(Definition(A.x$mBc$sp)), Added(Definition(A.x$mCc$sp)), Added(Definition(A.x$mDc$sp)), Added(Definition(A.x$mFc$sp)), Added(Definition(A.x$mIc$sp)), Added(Definition(A.x$mJc$sp)), Added(Definition(A.x$mLc$sp)), Added(Definition(A.x$mSc$sp)), Added(Definition(A.x$mVc$sp)), Added(Definition(A.x$mZc$sp)), Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ])) invalidate B.scala because it references changed definition [Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ]] compiling Set(B.scala) Changes: Map(object B -> List()) diff --git a/test/files/pos/spec-Function1.scala b/test/files/pos/spec-Function1.scala index 7bdcd072b2..5b6af67a74 100644 --- a/test/files/pos/spec-Function1.scala +++ b/test/files/pos/spec-Function1.scala @@ -8,7 +8,7 @@ // generated by genprod on Wed Apr 23 10:06:16 CEST 2008 (with fancy comment) (with extra methods) -package scala +package scalabip /**

diff --git a/test/files/pos/spec-groups.scala b/test/files/pos/spec-groups.scala new file mode 100644 index 0000000000..9b6359a982 --- /dev/null +++ b/test/files/pos/spec-groups.scala @@ -0,0 +1,65 @@ +import Specializable._ + +class A[@specialized(Primitives) T](x: T) { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class B[@specialized(Everything) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class C[@specialized(Bits32AndUp) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class D[@specialized(Integral) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class E[@specialized(AllNumeric) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class F[@specialized(BestOfBreed) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} +class G[@specialized(Byte, Double, AnyRef) T] { + def f1[@specialized(Primitives) U](x: T, y: U) = ((x, y)) + def f2[@specialized(Everything) U](x: T, y: U) = ((x, y)) + def f3[@specialized(Bits32AndUp) U](x: T, y: U) = ((x, y)) + def f4[@specialized(Integral) U](x: T, y: U) = ((x, y)) + def f5[@specialized(AllNumeric) U](x: T, y: U) = ((x, y)) + def f6[@specialized(BestOfBreed) U](x: T, y: U) = ((x, y)) + def f7[@specialized(Byte, Double, AnyRef) U](x: T, y: U) = ((x, y)) +} diff --git a/test/files/pos/specialize10.scala b/test/files/pos/specialize10.scala new file mode 100644 index 0000000000..bbe197cda2 --- /dev/null +++ b/test/files/pos/specialize10.scala @@ -0,0 +1,7 @@ +trait Bippy[@specialized( + scala.Char, scala.Boolean, scala.Byte, + scala.Short, scala.Int, scala.Long, + scala.Float, scala.Double, scala.Unit, + scala.AnyRef) T] { } + +trait Bippy2[@specialized(Char, Boolean, Byte, Short, Int, Long, Float, Double, Unit, AnyRef) T] { } diff --git a/test/files/run/t3575.check b/test/files/run/t3575.check new file mode 100644 index 0000000000..c240b3d90c --- /dev/null +++ b/test/files/run/t3575.check @@ -0,0 +1,4 @@ +Two +Two +Two +Two$mcII$sp diff --git a/test/files/run/t3575.scala b/test/files/run/t3575.scala new file mode 100644 index 0000000000..56950e62bb --- /dev/null +++ b/test/files/run/t3575.scala @@ -0,0 +1,12 @@ +case class Two[@specialized A, @specialized B](v: A, w: B); + +// This is here to tell me if the behavior changes, not because +// the output is endorsed. +object Test { + def main(args: Array[String]): Unit = { + println(Two("Hello", 12).getClass().getName()) + println(Two(12, "Hello").getClass().getName()) + println(Two("Hello", "World").getClass().getName()) + println(Two(12, 12).getClass().getName()) + } +} diff --git a/test/files/run/t4770.check b/test/files/run/t4770.check new file mode 100644 index 0000000000..38e5a831fa --- /dev/null +++ b/test/files/run/t4770.check @@ -0,0 +1,2 @@ +(a,2) +(2,a) diff --git a/test/files/run/t4770.scala b/test/files/run/t4770.scala new file mode 100644 index 0000000000..25bf3050c3 --- /dev/null +++ b/test/files/run/t4770.scala @@ -0,0 +1,15 @@ +package crasher { + class Z[@specialized A, @specialized(AnyRef) B](var a: A, var b: B) { + override def toString = "" + ((a, b)) + } + object O { + def apply[@specialized A, @specialized(AnyRef) B](a0: A, b0: B) = new Z(a0, b0) + } +} + +object Test { + def main(args: Array[String]): Unit = { + println(crasher.O("a", 2)) + println(crasher.O(2, "a")) + } +} diff --git a/test/files/run/t4794.check b/test/files/run/t4794.check index f599e28b8a..b4de394767 100644 --- a/test/files/run/t4794.check +++ b/test/files/run/t4794.check @@ -1 +1 @@ -10 +11 diff --git a/test/files/specialized/arrays-traits.check b/test/files/specialized/arrays-traits.check index 92af4f13e1..40687a757e 100644 --- a/test/files/specialized/arrays-traits.check +++ b/test/files/specialized/arrays-traits.check @@ -1,6 +1,6 @@ -0 -0 -0 1 2 -1 \ No newline at end of file +1 +3 +4 +2 diff --git a/test/files/specialized/arrays-traits.scala b/test/files/specialized/arrays-traits.scala index de54d22d18..34a1c37a01 100644 --- a/test/files/specialized/arrays-traits.scala +++ b/test/files/specialized/arrays-traits.scala @@ -1,20 +1,12 @@ - - - import runtime.ScalaRunTime._ - - trait SuperS[@specialized(AnyRef) T] { def arr: Array[T] def foo() = arr(0) def bar(b: Array[T]) = b(0) = arr(0) } - -class BaseS[@specialized(AnyRef) T](val arr: Array[T]) extends SuperS[T] { -} - +class BaseS[@specialized(AnyRef) T](val arr: Array[T]) extends SuperS[T] { } trait SuperG[T] { def arr: Array[T] @@ -22,13 +14,9 @@ trait SuperG[T] { def bar(b: Array[T]) = b(0) = arr(0) } - -class BaseG[T](val arr: Array[T]) extends SuperG[T] { -} - +class BaseG[T](val arr: Array[T]) extends SuperG[T] { } object Test { - def main(args: Array[String]) { (new BaseS(new Array[String](1)): SuperS[String]).foo println(arrayApplyCount) @@ -42,5 +30,4 @@ object Test { println(arrayApplyCount) println(arrayUpdateCount) } - } diff --git a/test/files/specialized/arrays.check b/test/files/specialized/arrays.check index d37dfb720d..8df790f413 100644 --- a/test/files/specialized/arrays.check +++ b/test/files/specialized/arrays.check @@ -1,4 +1,4 @@ -0 -0 50 -51 \ No newline at end of file +51 +101 +102 diff --git a/test/pending/pos/t4012.scala b/test/pending/pos/t4012.scala new file mode 100644 index 0000000000..9b8a1b0dbe --- /dev/null +++ b/test/pending/pos/t4012.scala @@ -0,0 +1,7 @@ +trait C1[+A] { + def head: A = sys.error("") +} +trait C2[@specialized +A] extends C1[A] { + override def head: A = super.head +} +class C3 extends C2[Char] \ No newline at end of file diff --git a/test/pending/pos/t4541.scala b/test/pending/pos/t4541.scala new file mode 100644 index 0000000000..c6d9672cc5 --- /dev/null +++ b/test/pending/pos/t4541.scala @@ -0,0 +1,10 @@ +@SerialVersionUID(1L) +final class SparseArray[@specialized T](private var data : Array[T]) extends Serializable { + def use(inData : Array[T]) = { + data = inData; + } + + def set(that : SparseArray[T]) = { + use(that.data.clone) + } +} \ No newline at end of file diff --git a/test/pending/pos/t4786.scala b/test/pending/pos/t4786.scala new file mode 100644 index 0000000000..f0579142b8 --- /dev/null +++ b/test/pending/pos/t4786.scala @@ -0,0 +1,24 @@ +trait Matrix[@specialized A, Repr[C] <: Matrix[C, Repr]] { // crash goes away if @specialize is removed + def duplicate(mb: MatrixBuilder[A, Repr]): Repr[A] = { + mb.zeros + } +} +trait DenseMatrix[@specialized A] extends Matrix[A, DenseMatrix] +trait DenseMatrixFlt extends DenseMatrix[Float] + +trait MatrixBuilder[@specialized A, Repr[C] <: Matrix[C, Repr]] { + def zeros: Repr[A] +} +object DenseFloatBuilder extends MatrixBuilder[Float, DenseMatrix] { + val zeros = new Object with DenseMatrixFlt + // Note: + // - in 2.9 crash goes away if the explicit type "DenseMatrixFlt" is assigned to "zeros" + // - in 2.9 crash goes away if DenseMatrixFlt is a class instead of a trait: + // val zeros = new DenseMatrixFlt +} + +object Test extends App { + val m1 = DenseFloatBuilder.zeros // in 2.9 crash goes away if explicit type "DenseMatrixFlt" is assigned to m1 + val m2 = m1.duplicate(DenseFloatBuilder) +} + diff --git a/test/pending/pos/t4790.scala b/test/pending/pos/t4790.scala new file mode 100644 index 0000000000..e451fe80ab --- /dev/null +++ b/test/pending/pos/t4790.scala @@ -0,0 +1,4 @@ +package spectest { + class Sp[@specialized A, B](val a: A, val b: B) { } + class Fsp[@specialized A, B](a: A, b: B) extends Sp(a,b) { def ab = (a,b) } +} diff --git a/test/pending/run/t4511.scala b/test/pending/run/t4511.scala new file mode 100644 index 0000000000..58d4e0c7b0 --- /dev/null +++ b/test/pending/run/t4511.scala @@ -0,0 +1,10 @@ +class Interval[@specialized T](val high: T) +class Node[@specialized T](val interval: Interval[T]) { + val x1 = Some(interval.high) +} + +object Test { + def main(args: Array[String]): Unit = { + new Node(new Interval(5)).x1 + } +} \ No newline at end of file diff --git a/test/pending/run/t4971.scala b/test/pending/run/t4971.scala new file mode 100644 index 0000000000..c9b6d6f39f --- /dev/null +++ b/test/pending/run/t4971.scala @@ -0,0 +1,16 @@ +trait A[@specialized(Int) K, @specialized(Double) V] { + def doStuff(k: K, v: V): Unit = sys.error("I am overridden, you cannot call me") +} + +trait B[@specialized(Double) V] extends A[Int, V] { + override def doStuff(k: Int, v: V): Unit = println("Hi - I'm calling doStuff in B") +} + +object Test { + def main(args: Array[String]): Unit = delegate(new B[Double]() {}, 1, 0.1) + + def delegate[@specialized(Int) K, @specialized(Double) V](a: A[K, V], k: K, v: V) { + a.doStuff(k, v) + } +} + diff --git a/test/pending/run/t5284.scala b/test/pending/run/t5284.scala new file mode 100644 index 0000000000..b43afed5b8 --- /dev/null +++ b/test/pending/run/t5284.scala @@ -0,0 +1,14 @@ +object Test { + def main(args:Array[String]) { + val a = Blarg(Array(1,2,3)) + println(a.m((x:Int) => x+1)) + } +} + +object Blarg { + def apply[T:Manifest](a:Array[T]) = new Blarg(a) +} +class Blarg [@specialized T:Manifest](val a:Array[T]) { + def m[@specialized W>:T,@specialized S](f:W=>S) = f(a(0)) +} + -- cgit v1.2.3 From 1e648c386216d4c60121321a7ec40e2536bada9c Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 17 Feb 2012 09:52:40 -0800 Subject: Fixed AnyRef specialization. At least for the value of fix which means "better than it was in 2.9." I accidentally spent a long while trying to fix something I didn't realize I hadn't broken. But then I lucked into partially fixing it, so that's good news. See run/t5488-fn.scala if you want to see what still doesn't work. (It's covered at SI-4770, which is now reopened.) Closes SI-5488. --- .../scala/reflect/internal/Definitions.scala | 7 ++- .../tools/nsc/transform/SpecializeTypes.scala | 58 ++++++++++++++-------- src/library/scala/package.scala | 5 +- test/files/buildmanager/t2652/t2652.check | 2 +- test/files/run/t4770.check | 2 - test/files/run/t4770.scala | 15 ------ test/files/run/t4794.check | 2 +- test/files/run/t5488-fn.check | 17 +++++++ test/files/run/t5488-fn.scala | 49 ++++++++++++++++++ test/files/run/t5488.check | 14 ++++++ test/files/run/t5488.scala | 26 ++++++++++ test/pending/run/t4770.check | 2 + test/pending/run/t4770.scala | 15 ++++++ 13 files changed, 165 insertions(+), 49 deletions(-) delete mode 100644 test/files/run/t4770.check delete mode 100644 test/files/run/t4770.scala create mode 100644 test/files/run/t5488-fn.check create mode 100644 test/files/run/t5488-fn.scala create mode 100644 test/files/run/t5488.check create mode 100644 test/files/run/t5488.scala create mode 100644 test/pending/run/t4770.check create mode 100644 test/pending/run/t4770.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index b4b0a7335d..d043230e48 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -70,8 +70,7 @@ trait Definitions extends reflect.api.StandardDefinitions { tpnme.Float -> FLOAT_TAG, tpnme.Double -> DOUBLE_TAG, tpnme.Boolean -> BOOL_TAG, - tpnme.Unit -> VOID_TAG, - tpnme.Object -> OBJECT_TAG + tpnme.Unit -> VOID_TAG ) private def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f) @@ -80,7 +79,7 @@ trait Definitions extends reflect.api.StandardDefinitions { private def boxedName(name: Name) = sn.Boxed(name.toTypeName) - lazy val abbrvTag = symbolsMap(ObjectClass :: ScalaValueClasses, nameToTag) + lazy val abbrvTag = symbolsMap(ScalaValueClasses, nameToTag) withDefaultValue OBJECT_TAG lazy val numericWeight = symbolsMapFilt(ScalaValueClasses, nameToWeight.keySet, nameToWeight) lazy val boxedModule = classesMap(x => getModule(boxedName(x))) lazy val boxedClass = classesMap(x => getClass(boxedName(x))) @@ -213,7 +212,7 @@ trait Definitions extends reflect.api.StandardDefinitions { // Note: this is not the type alias AnyRef, it's a companion-like // object used by the @specialize annotation. - def AnyRefModule = getMember(ScalaPackageClass, nme.AnyRef) + lazy val AnyRefModule = getMember(ScalaPackageClass, nme.AnyRef) @deprecated("Use AnyRefModule", "2.10.0") def Predef_AnyRef = AnyRefModule diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 8c34a9139d..8b1d5b3295 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -121,9 +121,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // then pos/spec-List.scala fails - why? Does this kind of check fail // for similar reasons? Does `sym.isAbstractType` make a difference? private def isSpecializedAnyRefSubtype(tp: Type, sym: Symbol) = ( - (specializedOn(sym) contains AnyRefModule) + // !!! Come back to this, not sure it's recognizing AnyRefModule + (specializedOn(sym) exists (s => !isValueClass(s))) && !isValueClass(tp.typeSymbol) && isBoundedGeneric(tp) + // && (tp <:< AnyRefClass.tpe) ) private def isBoundedGeneric(tp: Type) = tp match { case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe) @@ -279,10 +281,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val pre1 = this(pre) // when searching for a specialized class, take care to map all // type parameters that are subtypes of AnyRef to AnyRef - val args1 = map2(args, sym.typeParams) { - case (tp, orig) if isSpecializedAnyRefSubtype(tp, orig) => AnyRefClass.tpe - case (tp, _) => tp - } + val args1 = map2(args, sym.info.typeParams)((tp, orig) => + if (isSpecializedAnyRefSubtype(tp, orig)) AnyRefClass.tpe + else tp + ) specializedClass.get((sym, TypeEnv.fromSpecialization(sym, args1))) match { case Some(sym1) => typeRef(pre1, sym1, survivingArgs(sym, args)) case None => typeRef(pre1, sym, args) @@ -305,7 +307,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else specializedTypeVars(sym).intersect(env.keySet) ) val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod) - debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars) + log("specName(" + sym + ") env: " + env + " tvars: " + tvars) specializedName(sym.name, methparams map env, others map env) } @@ -322,10 +324,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { nme.getterToLocal(specializedName(nme.localToGetter(name), types1, types2)) else { val (base, cs, ms) = nme.splitSpecializedName(name) - val abbrevs = definitions.abbrvTag withDefaultValue definitions.abbrvTag(ObjectClass) newTermName(base.toString + "$" - + "m" + ms + types1.map(t => abbrevs(t.typeSymbol)).mkString("", "", "") - + "c" + cs + types2.map(t => abbrevs(t.typeSymbol)).mkString("", "", "$sp")) + + "m" + ms + types1.map(t => definitions.abbrvTag(t.typeSymbol)).mkString("", "", "") + + "c" + cs + types2.map(t => definitions.abbrvTag(t.typeSymbol)).mkString("", "", "$sp")) } } @@ -370,8 +371,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case set :: Nil => set map (x => List(x)) case set :: sets => for (x <- set ; xs <- loop(sets)) yield x :: xs } - // zip the keys with each permutation to create a TypeEnv - loop(keys map concreteTypes) map (xss => Map(keys zip xss: _*)) + // zip the keys with each permutation to create a TypeEnv. + // If we don't exclude the "all AnyRef" specialization, we will + // incur duplicate members and crash during mixin. + loop(keys map concreteTypes) filterNot (_ forall (_ <:< AnyRefClass.tpe)) map (xss => Map(keys zip xss: _*)) } /** Does the given 'sym' need to be specialized in the environment 'env'? @@ -962,6 +965,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } case object UnifyError extends scala.util.control.ControlThrowable + private[this] def unifyError(tp1: Any, tp2: Any): Nothing = { + log("unifyError" + ((tp1, tp2))) + throw UnifyError + } /** Return the most general type environment that specializes tp1 to tp2. * It only allows binding of type parameters annotated with @specialized. @@ -972,29 +979,34 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match { case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) => debuglog("Unify - basic case: " + tp1 + ", " + tp2) - if (isValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1)) + if (isValueClass(tp2.typeSymbol)) env + ((sym1, tp2)) + else if (isSpecializedAnyRefSubtype(tp2, sym1)) + env + ((sym1, tp2)) // env + ((sym1, AnyRefClass.tpe)) + else if (strict) + unifyError(tp1, tp2) else - if (strict) throw UnifyError else env + env case (TypeRef(_, sym1, args1), TypeRef(_, sym2, args2)) => debuglog("Unify TypeRefs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - ") - if (strict && args1.length != args2.length) throw UnifyError + if (strict && args1.length != args2.length) unifyError(tp1, tp2) val e = unify(args1, args2, env, strict) debuglog("unified to: " + e) e case (TypeRef(_, sym1, _), _) if sym1.isTypeParameterOrSkolem => env case (MethodType(params1, res1), MethodType(params2, res2)) => - if (strict && params1.length != params2.length) throw UnifyError + if (strict && params1.length != params2.length) unifyError(tp1, tp2) debuglog("Unify MethodTypes: " + tp1 + " and " + tp2) unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict) case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => - if (strict && tparams1.length != tparams2.length) throw UnifyError debuglog("Unify PolyTypes: " + tp1 + " and " + tp2) - unify(res1, res2, env, strict) - case (PolyType(_, res), other) => - unify(res, other, env, strict) - case (ThisType(_), ThisType(_)) => env + if (strict && tparams1.length != tparams2.length) + unifyError(tp1, tp2) + else + unify(res1, res2, env, strict) + case (PolyType(_, res), other) => unify(res, other, env, strict) + case (ThisType(_), ThisType(_)) => env case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict) case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict) case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict) @@ -1016,7 +1028,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (env.keySet intersect nenv.keySet isEmpty) env ++ nenv else { debuglog("could not unify: u(" + args._1 + ", " + args._2 + ") yields " + nenv + ", env: " + env) - throw UnifyError + unifyError(tp1, tp2) } } } @@ -1242,7 +1254,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } } - def doesConform(origSymbol: Symbol, treeType: Type, memberType: Type, env: TypeEnv) = + def doesConform(origSymbol: Symbol, treeType: Type, memberType: Type, env: TypeEnv) = { (treeType =:= memberType) || { // anyref specialization memberType match { case PolyType(_, resTpe) => @@ -1259,6 +1271,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case _ => false } } + } override def transform(tree: Tree): Tree = { val symbol = tree.symbol @@ -1289,6 +1302,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { curTree = tree tree match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => + // log("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", "))) if (findSpec(tpt.tpe).typeSymbol ne tpt.tpe.typeSymbol) { // the ctor can be specialized log("** instantiated specialized type: " + findSpec(tpt.tpe)) diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala index 9425eba232..06d7f46d52 100644 --- a/src/library/scala/package.scala +++ b/src/library/scala/package.scala @@ -29,10 +29,7 @@ package object scala { type AbstractMethodError = java.lang.AbstractMethodError // A dummy used by the specialization annotation. - // Normally it's bad juju to place objects inside package objects, - // but there's no choice here as we'd have to be AnyRef's companion - // and defined in the same file - except there is no such file. - object AnyRef extends Specializable { + val AnyRef = new Specializable { override def toString = "object AnyRef" } diff --git a/test/files/buildmanager/t2652/t2652.check b/test/files/buildmanager/t2652/t2652.check index b84c80205e..071281c6ff 100644 --- a/test/files/buildmanager/t2652/t2652.check +++ b/test/files/buildmanager/t2652/t2652.check @@ -3,7 +3,7 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(class A -> List(Added(Definition(A.x$mBc$sp)), Added(Definition(A.x$mCc$sp)), Added(Definition(A.x$mDc$sp)), Added(Definition(A.x$mFc$sp)), Added(Definition(A.x$mIc$sp)), Added(Definition(A.x$mJc$sp)), Added(Definition(A.x$mLc$sp)), Added(Definition(A.x$mSc$sp)), Added(Definition(A.x$mVc$sp)), Added(Definition(A.x$mZc$sp)), Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ])) +Changes: Map(class A -> List(Added(Definition(A.x$mBc$sp)), Added(Definition(A.x$mCc$sp)), Added(Definition(A.x$mDc$sp)), Added(Definition(A.x$mFc$sp)), Added(Definition(A.x$mIc$sp)), Added(Definition(A.x$mJc$sp)), Added(Definition(A.x$mSc$sp)), Added(Definition(A.x$mVc$sp)), Added(Definition(A.x$mZc$sp)), Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ])) invalidate B.scala because it references changed definition [Changed(Definition(A.x))[method x changed from [T](t: T)T to [T](t: T)T flags: ]] compiling Set(B.scala) Changes: Map(object B -> List()) diff --git a/test/files/run/t4770.check b/test/files/run/t4770.check deleted file mode 100644 index 38e5a831fa..0000000000 --- a/test/files/run/t4770.check +++ /dev/null @@ -1,2 +0,0 @@ -(a,2) -(2,a) diff --git a/test/files/run/t4770.scala b/test/files/run/t4770.scala deleted file mode 100644 index 25bf3050c3..0000000000 --- a/test/files/run/t4770.scala +++ /dev/null @@ -1,15 +0,0 @@ -package crasher { - class Z[@specialized A, @specialized(AnyRef) B](var a: A, var b: B) { - override def toString = "" + ((a, b)) - } - object O { - def apply[@specialized A, @specialized(AnyRef) B](a0: A, b0: B) = new Z(a0, b0) - } -} - -object Test { - def main(args: Array[String]): Unit = { - println(crasher.O("a", 2)) - println(crasher.O(2, "a")) - } -} diff --git a/test/files/run/t4794.check b/test/files/run/t4794.check index b4de394767..f599e28b8a 100644 --- a/test/files/run/t4794.check +++ b/test/files/run/t4794.check @@ -1 +1 @@ -11 +10 diff --git a/test/files/run/t5488-fn.check b/test/files/run/t5488-fn.check new file mode 100644 index 0000000000..196f58d063 --- /dev/null +++ b/test/files/run/t5488-fn.check @@ -0,0 +1,17 @@ +B$mcII$sp +B +B$mcIV$sp +B$mcLI$sp +B +B$mcLV$sp +B$mcVI$sp +B +B$mcVV$sp +C$mcIII$sp +C +C$mcILI$sp +C +C$mcLII$sp +C +C$mcLLI$sp +C diff --git a/test/files/run/t5488-fn.scala b/test/files/run/t5488-fn.scala new file mode 100644 index 0000000000..9e4f60002b --- /dev/null +++ b/test/files/run/t5488-fn.scala @@ -0,0 +1,49 @@ +class B[@specialized(Int, AnyRef, Unit) A, @specialized(Int, Unit) B](f: A => B) +class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int) C](f: (A, B) => C) +// Not yet: +// class B[@specialized(Int, AnyRef, Unit) A, @specialized(Int, AnyRef, Unit) B](f: A => B) +// class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int, AnyRef) C](f: (A, B) => C) + +object Test { + def main(args:Array[String]) { + def show(x: Any) = println(x.getClass.getName) + + show(new B((x: Int) => 1)) + show(new B((x: Int) => "abc")) + show(new B((x: Int) => ())) + show(new B((x: AnyRef) => 1)) + show(new B((x: AnyRef) => "abc")) + show(new B((x: AnyRef) => ())) + show(new B((x: Unit) => 1)) + show(new B((x: Unit) => "abc")) + show(new B((x: Unit) => ())) + + show(new C((x: Int, y: Int) => 1)) + show(new C((x: Int, y: Int) => "abc")) + show(new C((x: Int, y: AnyRef) => 1)) + show(new C((x: Int, y: AnyRef) => "abc")) + show(new C((x: AnyRef, y: Int) => 1)) + show(new C((x: AnyRef, y: Int) => "abc")) + show(new C((x: AnyRef, y: AnyRef) => 1)) + show(new C((x: AnyRef, y: AnyRef) => "abc")) + } +} +/** If the return types are specialized on AnyRef as well: + +files/run/t5488-fn.scala:18: error: type mismatch; + found : Unit => String + required: Unit => B$sp + show(new B((x: Unit) => "abc")) + ^ +files/run/t5488-fn.scala:24: error: type mismatch; + found : (Int, Object) => String + required: (Int, B$sp) => C$sp + show(new C((x: Int, y: AnyRef) => "abc")) + ^ +files/run/t5488-fn.scala:26: error: type mismatch; + found : (Object, Int) => String + required: (A$sp, Int) => C$sp + show(new C((x: AnyRef, y: Int) => "abc")) + ^ +three errors found +**/ diff --git a/test/files/run/t5488.check b/test/files/run/t5488.check new file mode 100644 index 0000000000..ccd98c4dbc --- /dev/null +++ b/test/files/run/t5488.check @@ -0,0 +1,14 @@ +A0$mcI$sp +A0 +B0$mcII$sp +B0$mcIL$sp +B0$mcLI$sp +B0 +C0$mcIII$sp +C0$mcIIL$sp +C0$mcILI$sp +C0$mcILL$sp +C0$mcLII$sp +C0$mcLIL$sp +C0$mcLLI$sp +C0 diff --git a/test/files/run/t5488.scala b/test/files/run/t5488.scala new file mode 100644 index 0000000000..7bab0cdc3c --- /dev/null +++ b/test/files/run/t5488.scala @@ -0,0 +1,26 @@ +class A0[@specialized(Int, AnyRef) A]() +class B0[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B]() +class C0[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int, AnyRef) C]() + +object Test { + def main(args:Array[String]) { + def show(x: Any) = println(x.getClass.getName) + + show(new A0[Int]()) + show(new A0[AnyRef]()) + + show(new B0[Int, Int]()) + show(new B0[Int, AnyRef]()) + show(new B0[AnyRef, Int]()) + show(new B0[AnyRef, AnyRef]()) + + show(new C0[Int, Int, Int]()) + show(new C0[Int, Int, AnyRef]()) + show(new C0[Int, AnyRef, Int]()) + show(new C0[Int, AnyRef, AnyRef]()) + show(new C0[AnyRef, Int, Int]()) + show(new C0[AnyRef, Int, AnyRef]()) + show(new C0[AnyRef, AnyRef, Int]()) + show(new C0[AnyRef, AnyRef, AnyRef]()) + } +} diff --git a/test/pending/run/t4770.check b/test/pending/run/t4770.check new file mode 100644 index 0000000000..38e5a831fa --- /dev/null +++ b/test/pending/run/t4770.check @@ -0,0 +1,2 @@ +(a,2) +(2,a) diff --git a/test/pending/run/t4770.scala b/test/pending/run/t4770.scala new file mode 100644 index 0000000000..25bf3050c3 --- /dev/null +++ b/test/pending/run/t4770.scala @@ -0,0 +1,15 @@ +package crasher { + class Z[@specialized A, @specialized(AnyRef) B](var a: A, var b: B) { + override def toString = "" + ((a, b)) + } + object O { + def apply[@specialized A, @specialized(AnyRef) B](a0: A, b0: B) = new Z(a0, b0) + } +} + +object Test { + def main(args: Array[String]): Unit = { + println(crasher.O("a", 2)) + println(crasher.O(2, "a")) + } +} -- cgit v1.2.3 From e9926a5207aadcfe3831b51b1cd6164757278013 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 17 Feb 2012 17:10:49 +0100 Subject: Fixes miscellaneous macro bugs --- .../tools/nsc/interpreter/MemberHandlers.scala | 5 +- .../tools/nsc/typechecker/ContextErrors.scala | 5 -- .../scala/tools/nsc/typechecker/Macros.scala | 77 ++++++++++++++++++---- .../scala/tools/nsc/typechecker/Typers.scala | 19 +++--- test/files/neg/macro-argtype-mismatch.check | 6 ++ test/files/neg/macro-argtype-mismatch.flags | 1 + .../neg/macro-argtype-mismatch/Macros_1.scala | 3 + test/files/neg/macro-argtype-mismatch/Test_2.scala | 4 ++ test/files/neg/macro-noexpand.check | 4 ++ test/files/neg/macro-noexpand.flags | 1 + test/files/neg/macro-noexpand/Macros_1.scala | 3 + test/files/neg/macro-noexpand/Test_2.scala | 4 ++ test/files/neg/macro-noncompilertree.check | 6 ++ test/files/neg/macro-noncompilertree.flags | 1 + .../files/neg/macro-noncompilertree/Macros_1.scala | 3 + test/files/neg/macro-nontree.check | 6 ++ test/files/neg/macro-nontree.flags | 1 + test/files/neg/macro-nontree/Macros_1.scala | 3 + test/files/run/macro-basic.check | 1 + test/files/run/macro-basic.flags | 1 + test/files/run/macro-basic/Macros_1.scala | 10 +++ test/files/run/macro-basic/Test_2.scala | 4 ++ test/files/run/macro-repl-basic.check | 25 +++++++ test/files/run/macro-repl-basic.scala | 18 +++++ test/files/run/macro-repl-dontexpand.check | 9 +++ test/files/run/macro-repl-dontexpand.scala | 8 +++ test/files/run/macro-rettype-mismatch.check | 5 ++ test/files/run/macro-rettype-mismatch.flags | 1 + .../run/macro-rettype-mismatch/Macros_1.scala | 3 + test/files/run/macro-rettype-mismatch/Test_2.scala | 16 +++++ test/pending/run/macro-overload.check | 4 ++ test/pending/run/macro-overload.flags | 1 + test/pending/run/macro-overload/Macros_1.scala | 9 +++ test/pending/run/macro-overload/Test_2.scala | 6 ++ 34 files changed, 242 insertions(+), 31 deletions(-) create mode 100644 test/files/neg/macro-argtype-mismatch.check create mode 100644 test/files/neg/macro-argtype-mismatch.flags create mode 100644 test/files/neg/macro-argtype-mismatch/Macros_1.scala create mode 100644 test/files/neg/macro-argtype-mismatch/Test_2.scala create mode 100644 test/files/neg/macro-noexpand.check create mode 100644 test/files/neg/macro-noexpand.flags create mode 100644 test/files/neg/macro-noexpand/Macros_1.scala create mode 100644 test/files/neg/macro-noexpand/Test_2.scala create mode 100644 test/files/neg/macro-noncompilertree.check create mode 100644 test/files/neg/macro-noncompilertree.flags create mode 100644 test/files/neg/macro-noncompilertree/Macros_1.scala create mode 100644 test/files/neg/macro-nontree.check create mode 100644 test/files/neg/macro-nontree.flags create mode 100644 test/files/neg/macro-nontree/Macros_1.scala create mode 100644 test/files/run/macro-basic.check create mode 100644 test/files/run/macro-basic.flags create mode 100644 test/files/run/macro-basic/Macros_1.scala create mode 100644 test/files/run/macro-basic/Test_2.scala create mode 100644 test/files/run/macro-repl-basic.check create mode 100644 test/files/run/macro-repl-basic.scala create mode 100644 test/files/run/macro-repl-dontexpand.check create mode 100644 test/files/run/macro-repl-dontexpand.scala create mode 100644 test/files/run/macro-rettype-mismatch.check create mode 100644 test/files/run/macro-rettype-mismatch.flags create mode 100644 test/files/run/macro-rettype-mismatch/Macros_1.scala create mode 100644 test/files/run/macro-rettype-mismatch/Test_2.scala create mode 100644 test/pending/run/macro-overload.check create mode 100644 test/pending/run/macro-overload.flags create mode 100644 test/pending/run/macro-overload/Macros_1.scala create mode 100644 test/pending/run/macro-overload/Test_2.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index c742ab89c0..48a5fa9e34 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -118,8 +118,9 @@ trait MemberHandlers { class DefHandler(member: DefDef) extends MemberDefHandler(member) { private def vparamss = member.vparamss - // true if 0-arity - override def definesValue = vparamss.isEmpty || vparamss.head.isEmpty + private def isMacro = member.mods.hasFlag(scala.reflect.internal.Flags.MACRO) + // true if not a macro and 0-arity + override def definesValue = !isMacro && (vparamss.isEmpty || vparamss.head.isEmpty) override def resultExtractionCode(req: Request) = if (mods.isPublic) codegenln(name, ": ", req.typeOf(name)) else "" } diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 6ee09d064f..09eb504186 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -636,11 +636,6 @@ trait ContextErrors { def CyclicReferenceError(errPos: Position, lockedSym: Symbol) = issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym)) - - def MacroExpandError(tree: Tree, t: Any) = { - issueNormalTypeError(tree, "macros must return a compiler-specific tree; returned class is: " + t.getClass) - setError(tree) - } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 470f3e7117..161e4b7a9a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -90,8 +90,19 @@ trait Macros { self: Analyzer => lazy val mirror = new scala.reflect.runtime.Mirror { lazy val libraryClassLoader = { + // todo. this is more or less okay, but not completely correct + // see https://issues.scala-lang.org/browse/SI-5433 for more info val classpath = global.classPath.asURLs - ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + + // an heuristic to detect REPL + if (global.settings.exposeEmptyPackage.value) { + import scala.tools.nsc.interpreter._ + val virtualDirectory = global.settings.outputDirs.getSingleOutput.get + loader = new AbstractFileClassLoader(virtualDirectory, loader) {} + } + + loader } override def defaultReflectiveClassLoader() = libraryClassLoader @@ -112,19 +123,42 @@ trait Macros { self: Analyzer => if (mmeth == NoSymbol) None else { - val receiverClass: mirror.Symbol = mirror.symbolForName(mmeth.owner.fullName) + trace("loading implementation class: ")(mmeth.owner.fullName) + trace("classloader is: ")("%s of type %s".format(mirror.libraryClassLoader, mirror.libraryClassLoader.getClass)) + def inferClasspath(cl: ClassLoader) = cl match { + case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" + case _ => "" + } + trace("classpath is: ")(inferClasspath(mirror.libraryClassLoader)) + + // @xeno.by: relies on the fact that macros can only be defined in static classes + def classfile(sym: Symbol): String = { + def recur(sym: Symbol): String = sym match { + case sym if sym.owner.isPackageClass => + val suffix = if (sym.isModuleClass) "$" else "" + sym.fullName + suffix + case sym => + val separator = if (sym.owner.isModuleClass) "" else "$" + recur(sym.owner) + separator + sym.javaSimpleName + } + + if (sym.isClass || sym.isModule) recur(sym) + else recur(sym.enclClass) + } + + // @xeno.by: this doesn't work for inner classes + // neither does mmeth.owner.javaClassName, so I had to roll my own implementation + //val receiverName = mmeth.owner.fullName + val receiverName = classfile(mmeth.owner) + val receiverClass: mirror.Symbol = mirror.symbolForName(receiverName) + if (debug) { println("receiverClass is: " + receiverClass.fullNameString) val jreceiverClass = mirror.classToJava(receiverClass) val jreceiverSource = jreceiverClass.getProtectionDomain.getCodeSource println("jreceiverClass is %s from %s".format(jreceiverClass, jreceiverSource)) - - val jreceiverClasspath = jreceiverClass.getClassLoader match { - case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]" - case _ => "" - } - println("jreceiverClassLoader is %s with classpath %s".format(jreceiverClass.getClassLoader, jreceiverClasspath)) + println("jreceiverClassLoader is %s with classpath %s".format(jreceiverClass.getClassLoader, inferClasspath(jreceiverClass.getClassLoader))) } val receiverObj = receiverClass.companionModule @@ -132,7 +166,11 @@ trait Macros { self: Analyzer => if (receiverObj == mirror.NoSymbol) None else { - val receiver = mirror.companionInstance(receiverClass) + // @xeno.by: yet another reflection method that doesn't work for inner classes + //val receiver = mirror.companionInstance(receiverClass) + val clazz = java.lang.Class.forName(receiverName, true, mirror.libraryClassLoader) + val receiver = clazz getField "MODULE$" get null + val rmeth = receiverObj.info.member(mirror.newTermName(mmeth.name.toString)) if (debug) { println("rmeth is: " + rmeth.fullNameString) @@ -147,6 +185,7 @@ trait Macros { self: Analyzer => } } catch { case ex: ClassNotFoundException => + trace("implementation class failed to load: ")(ex.toString) None } } @@ -155,7 +194,7 @@ trait Macros { self: Analyzer => * Or, if that fails, and the macro overrides a method return * tree that calls this method instead of the macro. */ - def macroExpand(tree: Tree, context: Context): Option[Any] = { + def macroExpand(tree: Tree, typer: Typer): Option[Any] = { val trace = scala.tools.nsc.util.trace when settings.Ymacrodebug.value trace("macroExpand: ")(tree) @@ -180,7 +219,19 @@ trait Macros { self: Analyzer => // if one of those children involves macro expansion, things might get nasty // that's why I'm temporarily turning this behavior off nodePrinters.infolevel = nodePrinters.InfoLevel.Quiet - Some(mirror.invoke(receiver, rmeth)(rawArgs: _*)) + val expanded = mirror.invoke(receiver, rmeth)(rawArgs: _*) + expanded match { + case expanded: Tree => + val expectedTpe = tree.tpe + val typed = typer.typed(expanded, EXPRmode, expectedTpe) + Some(typed) + case expanded if expanded.isInstanceOf[Tree] => + typer.context.unit.error(tree.pos, "macro must return a compiler-specific tree; returned value is Tree, but it doesn't belong to this compiler's universe") + None + case expanded => + typer.context.unit.error(tree.pos, "macro must return a compiler-specific tree; returned value is of class: " + expanded.getClass) + None + } } catch { case ex => val realex = ReflectionUtils.unwrapThrowable(ex) @@ -191,14 +242,14 @@ trait Macros { self: Analyzer => } else { realex.getMessage } - context.unit.error(tree.pos, "exception during macro expansion: " + msg) + typer.context.unit.error(tree.pos, "exception during macro expansion: " + msg) None } finally { nodePrinters.infolevel = savedInfolevel } case None => def notFound() = { - context.unit.error(tree.pos, "macro implementation not found: " + macroDef.name) + typer.context.unit.error(tree.pos, "macro implementation not found: " + macroDef.name) None } def fallBackToOverridden(tree: Tree): Option[Tree] = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index ef69e1525e..9275156da7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -941,10 +941,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } if (tree.isType) adaptType() - else if (inExprModeButNot(mode, FUNmode) && tree.symbol != null && tree.symbol.isMacro && !tree.isDef) { - val tree1 = expandMacro(tree) - if (tree1.isErroneous) tree1 else typed(tree1, mode, pt) - } else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) + else if (inExprModeButNot(mode, FUNmode) && tree.symbol != null && tree.symbol.isMacro && !tree.isDef && !(tree exists (_.isErroneous))) + macroExpand(tree, this) match { + case Some(expanded: Tree) => + typed(expanded, mode, pt) + case None => + setError(tree) // error already reported + } + else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) adaptConstrPattern() else if (inAllModes(mode, EXPRmode | FUNmode) && !tree.tpe.isInstanceOf[MethodType] && @@ -4536,13 +4540,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - def expandMacro(tree: Tree): Tree = - macroExpand(tree, context) match { - case Some(t: Tree) => t - case Some(t) => MacroExpandError(tree, t) - case None => setError(tree) // error already reported - } - def atOwner(owner: Symbol): Typer = newTyper(context.make(context.tree, owner)) diff --git a/test/files/neg/macro-argtype-mismatch.check b/test/files/neg/macro-argtype-mismatch.check new file mode 100644 index 0000000000..dd867be804 --- /dev/null +++ b/test/files/neg/macro-argtype-mismatch.check @@ -0,0 +1,6 @@ +Test_2.scala:3: error: type mismatch; + found : String("2") + required: Int + foo("2") + ^ +one error found diff --git a/test/files/neg/macro-argtype-mismatch.flags b/test/files/neg/macro-argtype-mismatch.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/files/neg/macro-argtype-mismatch.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/files/neg/macro-argtype-mismatch/Macros_1.scala b/test/files/neg/macro-argtype-mismatch/Macros_1.scala new file mode 100644 index 0000000000..4b5f98ba37 --- /dev/null +++ b/test/files/neg/macro-argtype-mismatch/Macros_1.scala @@ -0,0 +1,3 @@ +object Macros { + def macro foo(x: Int) = x +} \ No newline at end of file diff --git a/test/files/neg/macro-argtype-mismatch/Test_2.scala b/test/files/neg/macro-argtype-mismatch/Test_2.scala new file mode 100644 index 0000000000..18feb69425 --- /dev/null +++ b/test/files/neg/macro-argtype-mismatch/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + import Macros._ + foo("2") +} \ No newline at end of file diff --git a/test/files/neg/macro-noexpand.check b/test/files/neg/macro-noexpand.check new file mode 100644 index 0000000000..c15d54bb32 --- /dev/null +++ b/test/files/neg/macro-noexpand.check @@ -0,0 +1,4 @@ +Test_2.scala:3: error: not found: value x + foo(x) + ^ +one error found diff --git a/test/files/neg/macro-noexpand.flags b/test/files/neg/macro-noexpand.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/files/neg/macro-noexpand.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/files/neg/macro-noexpand/Macros_1.scala b/test/files/neg/macro-noexpand/Macros_1.scala new file mode 100644 index 0000000000..7a6aadf6a1 --- /dev/null +++ b/test/files/neg/macro-noexpand/Macros_1.scala @@ -0,0 +1,3 @@ +object Macros { + def macro foo(x: Any) = ??? +} \ No newline at end of file diff --git a/test/files/neg/macro-noexpand/Test_2.scala b/test/files/neg/macro-noexpand/Test_2.scala new file mode 100644 index 0000000000..0bed592883 --- /dev/null +++ b/test/files/neg/macro-noexpand/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + import Macros._ + foo(x) +} \ No newline at end of file diff --git a/test/files/neg/macro-noncompilertree.check b/test/files/neg/macro-noncompilertree.check new file mode 100644 index 0000000000..616765a39e --- /dev/null +++ b/test/files/neg/macro-noncompilertree.check @@ -0,0 +1,6 @@ +Macros_1.scala:2: error: type mismatch; + found : reflect.mirror.Literal + required: _context.Tree + def macro foo = scala.reflect.mirror.Literal(scala.reflect.mirror.Constant(2)) + ^ +one error found diff --git a/test/files/neg/macro-noncompilertree.flags b/test/files/neg/macro-noncompilertree.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/files/neg/macro-noncompilertree.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/files/neg/macro-noncompilertree/Macros_1.scala b/test/files/neg/macro-noncompilertree/Macros_1.scala new file mode 100644 index 0000000000..eb1253e5e9 --- /dev/null +++ b/test/files/neg/macro-noncompilertree/Macros_1.scala @@ -0,0 +1,3 @@ +object Macros { + def macro foo = scala.reflect.mirror.Literal(scala.reflect.mirror.Constant(2)) +} \ No newline at end of file diff --git a/test/files/neg/macro-nontree.check b/test/files/neg/macro-nontree.check new file mode 100644 index 0000000000..a1c7139580 --- /dev/null +++ b/test/files/neg/macro-nontree.check @@ -0,0 +1,6 @@ +Macros_1.scala:2: error: type mismatch; + found : Int(2) + required: _context.Tree + def macro foo = 2 + ^ +one error found diff --git a/test/files/neg/macro-nontree.flags b/test/files/neg/macro-nontree.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/files/neg/macro-nontree.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/files/neg/macro-nontree/Macros_1.scala b/test/files/neg/macro-nontree/Macros_1.scala new file mode 100644 index 0000000000..2433974a85 --- /dev/null +++ b/test/files/neg/macro-nontree/Macros_1.scala @@ -0,0 +1,3 @@ +object Macros { + def macro foo = 2 +} \ No newline at end of file diff --git a/test/files/run/macro-basic.check b/test/files/run/macro-basic.check new file mode 100644 index 0000000000..d434014897 --- /dev/null +++ b/test/files/run/macro-basic.check @@ -0,0 +1 @@ +10 diff --git a/test/files/run/macro-basic.flags b/test/files/run/macro-basic.flags new file mode 100644 index 0000000000..06a7b31f11 --- /dev/null +++ b/test/files/run/macro-basic.flags @@ -0,0 +1 @@ +-Xmacros diff --git a/test/files/run/macro-basic/Macros_1.scala b/test/files/run/macro-basic/Macros_1.scala new file mode 100644 index 0000000000..c2ea183abe --- /dev/null +++ b/test/files/run/macro-basic/Macros_1.scala @@ -0,0 +1,10 @@ +object Macros { + object Shmacros { + def macro foo(x: Int): Int = x + } + def macro bar(x: Int): Int = x +} + +class Macros { + def macro quux(x: Int): Int = x +} \ No newline at end of file diff --git a/test/files/run/macro-basic/Test_2.scala b/test/files/run/macro-basic/Test_2.scala new file mode 100644 index 0000000000..e9a10e20c9 --- /dev/null +++ b/test/files/run/macro-basic/Test_2.scala @@ -0,0 +1,4 @@ +object Test extends App { + import Macros.Shmacros._ + println(foo(2) + Macros.bar(2) * new Macros().quux(4)) +} \ No newline at end of file diff --git a/test/files/run/macro-repl-basic.check b/test/files/run/macro-repl-basic.check new file mode 100644 index 0000000000..f8f0d3ad29 --- /dev/null +++ b/test/files/run/macro-repl-basic.check @@ -0,0 +1,25 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> object Macros { + object Shmacros { + def macro foo(x: Int): Int = x + } + def macro bar(x: Int): Int = x +}; class Macros { + def macro quux(x: Int): Int = x +} +defined module Macros +defined class Macros + +scala> + +scala> import Macros.Shmacros._ +import Macros.Shmacros._ + +scala> println(foo(2) + Macros.bar(2) * new Macros().quux(4)) +10 + +scala> diff --git a/test/files/run/macro-repl-basic.scala b/test/files/run/macro-repl-basic.scala new file mode 100644 index 0000000000..9b1a53343b --- /dev/null +++ b/test/files/run/macro-repl-basic.scala @@ -0,0 +1,18 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + override def extraSettings = "-Xmacros" + def code = """ + |object Macros { + | object Shmacros { + | def macro foo(x: Int): Int = x + | } + | def macro bar(x: Int): Int = x + |}; class Macros { + | def macro quux(x: Int): Int = x + |} + | + |import Macros.Shmacros._ + |println(foo(2) + Macros.bar(2) * new Macros().quux(4)) + |""".stripMargin +} \ No newline at end of file diff --git a/test/files/run/macro-repl-dontexpand.check b/test/files/run/macro-repl-dontexpand.check new file mode 100644 index 0000000000..d2bb89b6f7 --- /dev/null +++ b/test/files/run/macro-repl-dontexpand.check @@ -0,0 +1,9 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> def macro foo = ??? +foo: Any + +scala> diff --git a/test/files/run/macro-repl-dontexpand.scala b/test/files/run/macro-repl-dontexpand.scala new file mode 100644 index 0000000000..254bce894c --- /dev/null +++ b/test/files/run/macro-repl-dontexpand.scala @@ -0,0 +1,8 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + override def extraSettings = "-Xmacros" + def code = """ + |def macro foo = ??? + |""".stripMargin +} \ No newline at end of file diff --git a/test/files/run/macro-rettype-mismatch.check b/test/files/run/macro-rettype-mismatch.check new file mode 100644 index 0000000000..f6e4bc09fd --- /dev/null +++ b/test/files/run/macro-rettype-mismatch.check @@ -0,0 +1,5 @@ +error: type mismatch; + found : Int(2) + required: String + +java.lang.Error: reflective compilation has failed diff --git a/test/files/run/macro-rettype-mismatch.flags b/test/files/run/macro-rettype-mismatch.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/files/run/macro-rettype-mismatch.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/files/run/macro-rettype-mismatch/Macros_1.scala b/test/files/run/macro-rettype-mismatch/Macros_1.scala new file mode 100644 index 0000000000..64e5b93468 --- /dev/null +++ b/test/files/run/macro-rettype-mismatch/Macros_1.scala @@ -0,0 +1,3 @@ +object Macros { + def macro foo(x: Int): String = x +} \ No newline at end of file diff --git a/test/files/run/macro-rettype-mismatch/Test_2.scala b/test/files/run/macro-rettype-mismatch/Test_2.scala new file mode 100644 index 0000000000..39a7c7ad1a --- /dev/null +++ b/test/files/run/macro-rettype-mismatch/Test_2.scala @@ -0,0 +1,16 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + import scala.reflect.mirror._ + val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(2)))) + + val stderr = new java.io.ByteArrayOutputStream() + Console.setErr(new java.io.PrintStream(stderr)) + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + try { toolbox.runExpr(tree) } + catch { case ex: Throwable => println(stderr); println(ex) } +} diff --git a/test/pending/run/macro-overload.check b/test/pending/run/macro-overload.check new file mode 100644 index 0000000000..764f914e48 --- /dev/null +++ b/test/pending/run/macro-overload.check @@ -0,0 +1,4 @@ +object-Int +object-String +class-Int +class-String \ No newline at end of file diff --git a/test/pending/run/macro-overload.flags b/test/pending/run/macro-overload.flags new file mode 100644 index 0000000000..7fea2ff901 --- /dev/null +++ b/test/pending/run/macro-overload.flags @@ -0,0 +1 @@ +-Xmacros \ No newline at end of file diff --git a/test/pending/run/macro-overload/Macros_1.scala b/test/pending/run/macro-overload/Macros_1.scala new file mode 100644 index 0000000000..f24c69ea7b --- /dev/null +++ b/test/pending/run/macro-overload/Macros_1.scala @@ -0,0 +1,9 @@ +object Macros { + def macro bar(x: Int): Int = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("object-Int")))) + def macro bar(x: String): String = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("object-String")))) +} + +class Macros { + def macro bar(x: Int): Int = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("class-Int")))) + def macro bar(x: String): String = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("class-String")))) +} \ No newline at end of file diff --git a/test/pending/run/macro-overload/Test_2.scala b/test/pending/run/macro-overload/Test_2.scala new file mode 100644 index 0000000000..75f6572e03 --- /dev/null +++ b/test/pending/run/macro-overload/Test_2.scala @@ -0,0 +1,6 @@ +object Test extends App { + Macros.bar(2) + Macros.bar("2") + new Macros.bar(2) + new Macros.bar("2") +} \ No newline at end of file -- cgit v1.2.3 From ec160bae7e2935d98bf71cfb6dcba61f1979b854 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 18 Feb 2012 22:55:34 -0800 Subject: More on SI-5500. A reimagining of erik's patch in 1df4fc6e59 . He did the hard part, this is the batman reboot. I added more tests and tried to make the anyref caching code less fragile. --- .../scala/reflect/internal/NameManglers.scala | 14 +++--- src/compiler/scala/reflect/internal/StdNames.scala | 1 + src/compiler/scala/reflect/internal/Symbols.scala | 22 +++++++--- .../tools/nsc/transform/SpecializeTypes.scala | 38 +++++++--------- test/files/run/t5488-fn.check | 10 ++--- test/files/run/t5488-fn.scala | 26 +---------- test/files/run/t5500b.check | 28 ++++++++++++ test/files/run/t5500b.scala | 51 ++++++++++++++++++++++ test/pending/run/t4996.scala | 15 +++++++ 9 files changed, 142 insertions(+), 63 deletions(-) create mode 100644 test/files/run/t5500b.check create mode 100644 test/files/run/t5500b.scala create mode 100644 test/pending/run/t4996.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index 97a74c2383..c4ee7254dc 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -76,12 +76,14 @@ trait NameManglers { val PROTECTED_PREFIX = "protected$" val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set" val SINGLETON_SUFFIX = ".type" - val SPECIALIZED_SUFFIX_STRING = "$sp" val SUPER_PREFIX_STRING = "super$" val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" + val SETTER_SUFFIX: TermName = encode("_=") - val SETTER_SUFFIX: TermName = encode("_=") - val SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX_STRING + @deprecated("2.10.0", "Use SPECIALIZED_SUFFIX") + def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString + @deprecated("2.10.0", "Use SPECIALIZED_SUFFIX") + def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX @@ -120,7 +122,7 @@ trait NameManglers { } def unspecializedName(name: Name): Name = ( - if (name endsWith SPECIALIZED_SUFFIX_NAME) + if (name endsWith SPECIALIZED_SUFFIX) name.subName(0, name.lastIndexOf('m') - 1) else name ) @@ -140,8 +142,8 @@ trait NameManglers { * and another one belonging to the enclosing class, on Double. */ def splitSpecializedName(name: Name): (Name, String, String) = - if (name endsWith SPECIALIZED_SUFFIX_NAME) { - val name1 = name dropRight SPECIALIZED_SUFFIX_NAME.length + if (name endsWith SPECIALIZED_SUFFIX) { + val name1 = name dropRight SPECIALIZED_SUFFIX.length val idxC = name1 lastIndexOf 'c' val idxM = name1 lastIndexOf 'm' diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index b4c404a80c..f61fe7a457 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -99,6 +99,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val MODULE_VAR_SUFFIX: NameType = "$module" val ROOT: NameType = "" val PACKAGE: NameType = "package" + val SPECIALIZED_SUFFIX: NameType = "$sp" // value types (and AnyRef) are all used as terms as well // as (at least) arguments to the @specialize annotation. diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index b3ff2c6329..8e9788e8b6 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1383,15 +1383,25 @@ trait Symbols extends api.Symbols { self: SymbolTable => cloneSymbol(owner) /** A clone of this symbol, but with given owner. */ - final def cloneSymbol(owner: Symbol): Symbol = cloneSymbol(owner, this.rawflags) - final def cloneSymbol(owner: Symbol, newFlags: Long): Symbol = { - val newSym = cloneSymbolImpl(owner, newFlags) - ( newSym + final def cloneSymbol(newOwner: Symbol): Symbol = + cloneSymbol(newOwner, this.rawflags) + final def cloneSymbol(newOwner: Symbol, newFlags: Long): Symbol = + cloneSymbol(newOwner, newFlags, nme.NO_NAME) + final def cloneSymbol(newOwner: Symbol, newFlags: Long, newName: Name): Symbol = { + val clone = cloneSymbolImpl(newOwner, newFlags) + ( clone setPrivateWithin privateWithin - setInfo (info cloneInfo newSym) + setInfo (this.info cloneInfo clone) setAnnotations this.annotations ) + if (clone.thisSym != clone) + clone.typeOfThis = (clone.typeOfThis cloneInfo clone) + if (newName != nme.NO_NAME) + clone.name = newName + + clone } + /** Internal method to clone a symbol's implementation with the given flags and no info. */ def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol def cloneSymbolImpl(owner: Symbol): Symbol = cloneSymbolImpl(owner, 0L) @@ -2327,7 +2337,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def existentialBound: Type = abort("unexpected type: "+this.getClass+ " "+debugLocationString) - override def name: TypeName = super.name.asInstanceOf[TypeName] + override def name: TypeName = super.name.toTypeName final override def isType = true override def isNonClassType = true override def isAbstractType = { diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 468518d938..3254844344 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -87,10 +87,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Map class symbols to the type environments where they were created. */ private val typeEnv = mutable.HashMap[Symbol, TypeEnv]() withDefaultValue emptyEnv - // holds mappings from regular type parameter symbols and their class to - // symbols of specialized type parameters which are subtypes of AnyRef - // e.g. (sym, clazz) => specializedSym - private val anyrefSpecCache = perRunCaches.newMap[(Symbol, Symbol), Symbol]() + // Key: a specialized class or method + // Value: a map from tparams in the original class to tparams in the specialized class. + private val anyrefSpecCache = perRunCaches.newMap[Symbol, mutable.Map[Symbol, Symbol]]() // holds mappings from members to the type variables in the class // that they were already specialized for, so that they don't get @@ -432,29 +431,24 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case _ => Set() } - /** Returns the type parameter in the specialized class `clazz` that corresponds to type parameter - * `sym` in the original class. It will create it if needed or use the one from the cache. + /** Returns the type parameter in the specialized class `sClass` that corresponds to type parameter + * `tparam` in the original class. It will create it if needed or use the one from the cache. */ - private def typeParamSubAnyRef(sym: Symbol, clazz: Symbol) = ( - anyrefSpecCache.getOrElseUpdate((sym, clazz), - clazz.newTypeParameter(sym.name append nme.SPECIALIZED_SUFFIX_NAME toTypeName, sym.pos) - setInfo TypeBounds(sym.info.bounds.lo, AnyRefClass.tpe) + private def typeParamSubAnyRef(tparam: Symbol, sClass: Symbol): Type = { + val sClassMap = anyrefSpecCache.getOrElseUpdate(sClass, mutable.Map[Symbol, Symbol]()) + + sClassMap.getOrElseUpdate(tparam, + tparam.cloneSymbol(sClass, tparam.flags, tparam.name append tpnme.SPECIALIZED_SUFFIX) + modifyInfo (info => TypeBounds(info.bounds.lo, AnyRefClass.tpe)) ).tpe - ) + } /** Cleans the anyrefSpecCache of all type parameter symbols of a class. */ - private def cleanAnyRefSpecCache(clazz: Symbol, decls: List[Symbol]) = ( + private def cleanAnyRefSpecCache(clazz: Symbol, decls: List[Symbol]) { // remove class type parameters and those of normalized members. - clazz :: decls foreach { - _.tpe match { - case PolyType(tparams, _) => tparams.foreach { - s => anyrefSpecCache.remove((s, clazz)) - } - case _ => () - } - } - ) + clazz :: decls foreach (anyrefSpecCache remove _) + } /** Type parameters that survive when specializing in the specified environment. */ def survivingParams(params: List[Symbol], env: TypeEnv) = @@ -1710,7 +1704,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * - there is a getter for the specialized field in the same class */ def initializesSpecializedField(f: Symbol) = ( - (f.name endsWith nme.SPECIALIZED_SUFFIX_NAME) + (f.name endsWith nme.SPECIALIZED_SUFFIX) && clazz.info.member(nme.originalName(f.name)).isPublic && clazz.info.decl(f.name).suchThat(_.isGetter) != NoSymbol ) diff --git a/test/files/run/t5488-fn.check b/test/files/run/t5488-fn.check index 196f58d063..18907d0ab8 100644 --- a/test/files/run/t5488-fn.check +++ b/test/files/run/t5488-fn.check @@ -1,17 +1,17 @@ B$mcII$sp -B +B$mcIL$sp B$mcIV$sp B$mcLI$sp B B$mcLV$sp B$mcVI$sp -B +B$mcVL$sp B$mcVV$sp C$mcIII$sp -C +C$mcIIL$sp C$mcILI$sp -C +C$mcILL$sp C$mcLII$sp -C +C$mcLIL$sp C$mcLLI$sp C diff --git a/test/files/run/t5488-fn.scala b/test/files/run/t5488-fn.scala index 9e4f60002b..d17bcf90a5 100644 --- a/test/files/run/t5488-fn.scala +++ b/test/files/run/t5488-fn.scala @@ -1,8 +1,5 @@ -class B[@specialized(Int, AnyRef, Unit) A, @specialized(Int, Unit) B](f: A => B) -class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int) C](f: (A, B) => C) -// Not yet: -// class B[@specialized(Int, AnyRef, Unit) A, @specialized(Int, AnyRef, Unit) B](f: A => B) -// class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int, AnyRef) C](f: (A, B) => C) +class B[@specialized(Int, AnyRef, Unit) A, @specialized(Int, AnyRef, Unit) B](f: A => B) +class C[@specialized(Int, AnyRef) A, @specialized(Int, AnyRef) B, @specialized(Int, AnyRef) C](f: (A, B) => C) object Test { def main(args:Array[String]) { @@ -28,22 +25,3 @@ object Test { show(new C((x: AnyRef, y: AnyRef) => "abc")) } } -/** If the return types are specialized on AnyRef as well: - -files/run/t5488-fn.scala:18: error: type mismatch; - found : Unit => String - required: Unit => B$sp - show(new B((x: Unit) => "abc")) - ^ -files/run/t5488-fn.scala:24: error: type mismatch; - found : (Int, Object) => String - required: (Int, B$sp) => C$sp - show(new C((x: Int, y: AnyRef) => "abc")) - ^ -files/run/t5488-fn.scala:26: error: type mismatch; - found : (Object, Int) => String - required: (A$sp, Int) => C$sp - show(new C((x: AnyRef, y: Int) => "abc")) - ^ -three errors found -**/ diff --git a/test/files/run/t5500b.check b/test/files/run/t5500b.check new file mode 100644 index 0000000000..4259b24b53 --- /dev/null +++ b/test/files/run/t5500b.check @@ -0,0 +1,28 @@ +C1A$mcLI$sp +C1A$mcLD$sp +C1A +C1A$mcII$sp +C1A$mcID$sp +C1A$mcIL$sp +C1A$mcDI$sp +C1A$mcDD$sp +C1A$mcDL$sp +C1B$mcLI$sp +C1B$mcLD$sp +C1B +C1B$mcII$sp +C1B$mcID$sp +C1B$mcIL$sp +C1B$mcDI$sp +C1B$mcDD$sp +C1B$mcDL$sp +C1C$mcLI$sp +C1C$mcLI$sp +C1C$mcLD$sp +C1C +C1C$mcII$sp +C1C$mcID$sp +C1C$mcIL$sp +C1C$mcDI$sp +C1C$mcDD$sp +C1C$mcDL$sp diff --git a/test/files/run/t5500b.scala b/test/files/run/t5500b.scala new file mode 100644 index 0000000000..32de858e7b --- /dev/null +++ b/test/files/run/t5500b.scala @@ -0,0 +1,51 @@ +import scala.{specialized => spec} + +class C1A[ + @spec(Double, Int, AnyRef) A, + @spec(Double, Int, AnyRef) B +] + +class C1B[ + @spec(Double, Int, AnyRef) A, + @spec(Double, Int, AnyRef) B +](v: A) + +class C1C[ + @spec(Double, Int, AnyRef) A, + @spec(Double, Int, AnyRef) B +](v:A, w:B) + +object Test { + def main(args:Array[String]) { + println(new C1A[String, Int].getClass.getName) + println(new C1A[String, Double].getClass.getName) + println(new C1A[String, String].getClass.getName) + println(new C1A[Int, Int].getClass.getName) + println(new C1A[Int, Double].getClass.getName) + println(new C1A[Int, String].getClass.getName) + println(new C1A[Double, Int].getClass.getName) + println(new C1A[Double, Double].getClass.getName) + println(new C1A[Double, String].getClass.getName) + + println(new C1B[String, Int]("abc").getClass.getName) + println(new C1B[String, Double]("abc").getClass.getName) + println(new C1B[String, String]("abc").getClass.getName) + println(new C1B[Int, Int](1).getClass.getName) + println(new C1B[Int, Double](1).getClass.getName) + println(new C1B[Int, String](1).getClass.getName) + println(new C1B[Double, Int](1d).getClass.getName) + println(new C1B[Double, Double](1d).getClass.getName) + println(new C1B[Double, String](1d).getClass.getName) + + println(new C1C("abc", 123).getClass.getName) + println(new C1C("abc", 123).getClass.getName) + println(new C1C("a", 1d).getClass.getName) + println(new C1C("a", "a").getClass.getName) + println(new C1C(1, 1).getClass.getName) + println(new C1C(1, 1d).getClass.getName) + println(new C1C(1, "a").getClass.getName) + println(new C1C(1d, 1).getClass.getName) + println(new C1C(1d, 1d).getClass.getName) + println(new C1C(1d, "a").getClass.getName) + } +} diff --git a/test/pending/run/t4996.scala b/test/pending/run/t4996.scala new file mode 100644 index 0000000000..58a8fe16a3 --- /dev/null +++ b/test/pending/run/t4996.scala @@ -0,0 +1,15 @@ +object SpecializationAbstractOverride { + + trait A[@specialized(Int) T] { def foo(t: T) } + trait B extends A[Int] { def foo(t: Int) { println("B.foo") } } + trait M extends B { abstract override def foo(t: Int) { super.foo(t) ; println ("M.foo") } } + object C extends B with M + + object D extends B { override def foo(t: Int) { super.foo(t); println("M.foo") } } + + def main(args: Array[String]) { + D.foo(42) // OK, prints B.foo M.foo + C.foo(42) // StackOverflowError + } +} + -- cgit v1.2.3 From 87e369ef46bd2ca569ffd1cd6f3a554f1d645dc9 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sun, 19 Feb 2012 00:03:55 -0800 Subject: More specialization tests. Some in pending, some in files. Closes SI-4770. --- test/files/run/t3575.check | 16 +++++++++++++ test/files/run/t3575.scala | 55 +++++++++++++++++++++++++++++++++++++++----- test/files/run/t4770.check | 2 ++ test/files/run/t4770.scala | 15 ++++++++++++ test/pending/pos/t4123.scala | 14 +++++++++++ test/pending/pos/t4436.scala | 3 +++ test/pending/pos/t4717.scala | 7 ++++++ test/pending/pos/t4787.scala | 4 ++++ test/pending/run/t4770.check | 2 -- test/pending/run/t4770.scala | 15 ------------ 10 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 test/files/run/t4770.check create mode 100644 test/files/run/t4770.scala create mode 100644 test/pending/pos/t4123.scala create mode 100644 test/pending/pos/t4436.scala create mode 100644 test/pending/pos/t4717.scala create mode 100644 test/pending/pos/t4787.scala delete mode 100644 test/pending/run/t4770.check delete mode 100644 test/pending/run/t4770.scala (limited to 'test/pending/run') diff --git a/test/files/run/t3575.check b/test/files/run/t3575.check index c240b3d90c..9080fd8674 100644 --- a/test/files/run/t3575.check +++ b/test/files/run/t3575.check @@ -2,3 +2,19 @@ Two Two Two Two$mcII$sp +TwoLong +TwoLong$mcIL$sp +TwoLong$mcLI$sp +TwoLong$mcII$sp +TwoCool +TwoCool$mcIL$sp +TwoCool$mcLI$sp +TwoCool$mcII$sp +TwoShort +TwoShort +TwoShort +TwoShort$mcII$sp +TwoMinimal +TwoMinimal$mcIL$sp +TwoMinimal$mcLI$sp +TwoMinimal$mcII$sp diff --git a/test/files/run/t3575.scala b/test/files/run/t3575.scala index 56950e62bb..9ccd90a8c4 100644 --- a/test/files/run/t3575.scala +++ b/test/files/run/t3575.scala @@ -1,12 +1,55 @@ -case class Two[@specialized A, @specialized B](v: A, w: B); - // This is here to tell me if the behavior changes, not because // the output is endorsed. +case class Two[ + @specialized A, + @specialized B +](v: A, w: B) + +case class TwoLong[ + @specialized(Char, Boolean, Byte, Short, Int, Long, Float, Double, Unit, AnyRef) A, + @specialized(Char, Boolean, Byte, Short, Int, Long, Float, Double, Unit, AnyRef) B +](v: A, w: B) + +case class TwoCool[ + @specialized(Specializable.Everything) A, + @specialized(Specializable.Everything) B +](v: A, w: B) + +case class TwoShort[ + @specialized() A, + @specialized() B +](v: A, w: B) + +case class TwoMinimal[ + @specialized(Int, AnyRef) A, + @specialized(Int, AnyRef) B +](v: A, w: B) + object Test { def main(args: Array[String]): Unit = { - println(Two("Hello", 12).getClass().getName()) - println(Two(12, "Hello").getClass().getName()) - println(Two("Hello", "World").getClass().getName()) - println(Two(12, 12).getClass().getName()) + println(Two("Hello", "World").getClass().getName()); + println(Two(12, "Hello").getClass().getName()); + println(Two("Hello", 12).getClass().getName()); + println(Two(12, 12).getClass().getName()); + + println(TwoLong("Hello", "World").getClass().getName()); + println(TwoLong(12, "Hello").getClass().getName()); + println(TwoLong("Hello", 12).getClass().getName()); + println(TwoLong(12, 12).getClass().getName()); + + println(TwoCool("Hello", "World").getClass().getName()); + println(TwoCool(12, "Hello").getClass().getName()); + println(TwoCool("Hello", 12).getClass().getName()); + println(TwoCool(12, 12).getClass().getName()); + + println(TwoShort("Hello", "World").getClass().getName()); + println(TwoShort(12, "Hello").getClass().getName()); + println(TwoShort("Hello", 12).getClass().getName()); + println(TwoShort(12, 12).getClass().getName()); + + println(TwoMinimal("Hello", "World").getClass().getName()); + println(TwoMinimal(12, "Hello").getClass().getName()); + println(TwoMinimal("Hello", 12).getClass().getName()); + println(TwoMinimal(12, 12).getClass().getName()); } } diff --git a/test/files/run/t4770.check b/test/files/run/t4770.check new file mode 100644 index 0000000000..38e5a831fa --- /dev/null +++ b/test/files/run/t4770.check @@ -0,0 +1,2 @@ +(a,2) +(2,a) diff --git a/test/files/run/t4770.scala b/test/files/run/t4770.scala new file mode 100644 index 0000000000..25bf3050c3 --- /dev/null +++ b/test/files/run/t4770.scala @@ -0,0 +1,15 @@ +package crasher { + class Z[@specialized A, @specialized(AnyRef) B](var a: A, var b: B) { + override def toString = "" + ((a, b)) + } + object O { + def apply[@specialized A, @specialized(AnyRef) B](a0: A, b0: B) = new Z(a0, b0) + } +} + +object Test { + def main(args: Array[String]): Unit = { + println(crasher.O("a", 2)) + println(crasher.O(2, "a")) + } +} diff --git a/test/pending/pos/t4123.scala b/test/pending/pos/t4123.scala new file mode 100644 index 0000000000..82ab16b4e4 --- /dev/null +++ b/test/pending/pos/t4123.scala @@ -0,0 +1,14 @@ +// /scala/trac/4123/a.scala +// Sun Feb 19 00:08:53 PST 2012 + +trait Iter[@specialized(Byte) +A] extends Iterator[A] { + self => + + override def map[B](f: (A) => B) = super.map(f) +} + +class ByteIter extends Iter[Byte] { + var i = 0 + def hasNext = i < 3 + def next = { i += 1 ; i.toByte } +} \ No newline at end of file diff --git a/test/pending/pos/t4436.scala b/test/pending/pos/t4436.scala new file mode 100644 index 0000000000..acbf0beae6 --- /dev/null +++ b/test/pending/pos/t4436.scala @@ -0,0 +1,3 @@ +trait Chunk[@specialized +A] { + def bippy[@specialized B >: A](e: B): Chunk[B] +} \ No newline at end of file diff --git a/test/pending/pos/t4717.scala b/test/pending/pos/t4717.scala new file mode 100644 index 0000000000..43cf412bc6 --- /dev/null +++ b/test/pending/pos/t4717.scala @@ -0,0 +1,7 @@ +trait Bug1[@specialized +A] extends TraversableOnce[A] { + def ++[B >: A](that: TraversableOnce[B]): Iterator[B] = new Iterator[B] { + lazy val it = that.toIterator + def hasNext = it.hasNext + def next = it.next + } +} \ No newline at end of file diff --git a/test/pending/pos/t4787.scala b/test/pending/pos/t4787.scala new file mode 100644 index 0000000000..cf3fe93c50 --- /dev/null +++ b/test/pending/pos/t4787.scala @@ -0,0 +1,4 @@ +trait MatrixImpl[@specialized A, @specialized B] { + def mapTo[ A2, B2, That <: MatrixImpl[A2, B2]](that: That)(f: A => A2) { + } +} diff --git a/test/pending/run/t4770.check b/test/pending/run/t4770.check deleted file mode 100644 index 38e5a831fa..0000000000 --- a/test/pending/run/t4770.check +++ /dev/null @@ -1,2 +0,0 @@ -(a,2) -(2,a) diff --git a/test/pending/run/t4770.scala b/test/pending/run/t4770.scala deleted file mode 100644 index 25bf3050c3..0000000000 --- a/test/pending/run/t4770.scala +++ /dev/null @@ -1,15 +0,0 @@ -package crasher { - class Z[@specialized A, @specialized(AnyRef) B](var a: A, var b: B) { - override def toString = "" + ((a, b)) - } - object O { - def apply[@specialized A, @specialized(AnyRef) B](a0: A, b0: B) = new Z(a0, b0) - } -} - -object Test { - def main(args: Array[String]): Unit = { - println(crasher.O("a", 2)) - println(crasher.O(2, "a")) - } -} -- cgit v1.2.3 From a6a9684f5ba5df146be1f24bd170e97f0b2208ce Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sun, 19 Feb 2012 19:40:08 -0800 Subject: A better error message for inheritance conflict. And some tests for pending. Closes SI-5358. --- .../scala/tools/nsc/typechecker/RefChecks.scala | 10 +++++- test/files/neg/t5358.check | 7 +++++ test/files/neg/t5358.scala | 4 +++ test/pending/pos/bug4704.scala | 36 ++++++++++++++++++++++ test/pending/run/bug4704run.scala | 10 ++++++ 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t5358.check create mode 100644 test/files/neg/t5358.scala create mode 100644 test/pending/pos/bug4704.scala create mode 100644 test/pending/run/bug4704run.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index e313edb3f6..35db38ae77 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -282,6 +282,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def otherTp = self.memberType(other) def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType def isRootOrNone(sym: Symbol) = sym == RootClass || sym == NoSymbol + def isNeitherInClass = (member.owner != clazz) && (other.owner != clazz) def objectOverrideErrorMsg = ( "overriding " + other.fullLocationString + " with " + member.fullLocationString + ":\n" + "an overriding object must conform to the overridden object's class bound" + @@ -383,7 +384,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R overrideError("cannot override final member"); // synthetic exclusion needed for (at least) default getters. } else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) { - overrideError("needs `override' modifier"); + if (isNeitherInClass && !(other.owner isSubClass member.owner)) + emitOverrideError( + clazz + " inherits conflicting members:\n " + + infoStringWithLocation(other) + " and\n " + infoStringWithLocation(member) + + "\n(Note: this can be resolved by declaring an override in " + clazz + ".)" + ) + else + overrideError("needs `override' modifier") } else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) { overrideError("needs `abstract override' modifiers") } else if (member.isAnyOverride && (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.isLazy) { diff --git a/test/files/neg/t5358.check b/test/files/neg/t5358.check new file mode 100644 index 0000000000..59e83bba2f --- /dev/null +++ b/test/files/neg/t5358.check @@ -0,0 +1,7 @@ +t5358.scala:3: error: class C inherits conflicting members: + method hi in trait A of type => String and + method hi in trait B of type => String +(Note: this can be resolved by declaring an override in class C.) +class C extends A with B + ^ +one error found diff --git a/test/files/neg/t5358.scala b/test/files/neg/t5358.scala new file mode 100644 index 0000000000..13d827ed82 --- /dev/null +++ b/test/files/neg/t5358.scala @@ -0,0 +1,4 @@ +trait A { def hi = "A" } +trait B { def hi = "B" } +class C extends A with B + diff --git a/test/pending/pos/bug4704.scala b/test/pending/pos/bug4704.scala new file mode 100644 index 0000000000..6af719adf7 --- /dev/null +++ b/test/pending/pos/bug4704.scala @@ -0,0 +1,36 @@ +trait Bar { + def f1 = super.hashCode + def f2 = super[Object].hashCode + def f3 = super[ScalaObject].hashCode + + override def hashCode = 1 +} +trait Barzoo { + def g1 = super.hashCode + def g2 = super[Object].hashCode + def g3 = super[ScalaObject].hashCode + + override def hashCode = 2 +} + +trait Foo extends Bar with Barzoo { + def f4 = super.hashCode + def f5 = super[Object].hashCode + def f6 = super[ScalaObject].hashCode + def f6b = super[Bar].hashCode + def g4 = super[Barzoo].hashCode + + override def hashCode = super[Bar].hashCode + super[Barzoo].hashCode +} + +class Quux extends Foo { + override def hashCode = super.hashCode + super[Object].hashCode + super[ScalaObject].hashCode + super[Foo].hashCode +} + +trait Borp extends Quux { + def f12 = super.hashCode + def f14 = super[ScalaObject].hashCode + def f15 = super[Quux].hashCode + override def hashCode = super[Quux].hashCode +} + diff --git a/test/pending/run/bug4704run.scala b/test/pending/run/bug4704run.scala new file mode 100644 index 0000000000..af488a56c7 --- /dev/null +++ b/test/pending/run/bug4704run.scala @@ -0,0 +1,10 @@ +trait MM { + protected def method = "bip" +} +trait NN { + protected def method = "bop" +} +trait OOOOO extends MM with NN { + override protected def method = super[MM].method + super[NN].method + override def hashCode = super[MM].hashCode + super[NN].hashCode +} -- cgit v1.2.3 From f3711b634ccfa6ef4ab14ffc8d12d244de6917c2 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 28 Feb 2012 08:08:30 -0800 Subject: Improving error message. Hacked filename into message to alleviate meaningless "_$1 defined twice" error condition. References SI-4893. --- .../tools/nsc/typechecker/ContextErrors.scala | 20 ++++++++++++----- test/files/neg/t200.check | 2 +- test/files/neg/t2779.check | 2 +- test/files/neg/t278.check | 2 +- test/files/neg/t591.check | 2 +- test/files/neg/t800.check | 6 +++--- test/files/neg/t960.check | 4 ++-- test/pending/run/t4511b.scala | 25 ++++++++++++++++++++++ 8 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 test/pending/run/t4511b.scala (limited to 'test/pending/run') diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index ea5223e32f..140df53816 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -624,11 +624,21 @@ trait ContextErrors { setError(tree) } - // checkNoDoubleDefs... - def DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) = - issueSymbolTypeError(sym0, sym1+" is defined twice"+ - {if(!settings.debug.value) "" else " in "+context0.unit}+ - {if (sym0.isMacro && sym1.isMacro) " \n(note that macros cannot be overloaded)" else ""}) + // checkNoDoubleDefs... + // @PP: I hacked the filename in (context0.unit) to work around SI-4893. It would be + // much better if every symbol could offer some idea of where it came from, else + // the obviously untrue claim that something has been defined twice can only frustrate. + // There's no direct test because partest doesn't work, but to reproduce, separately + // compile the next two lines: + // package object foo { val x: Class[_] = null } + // package foo + def DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) = { + val isBug = sym0.isAbstractType && sym1.isAbstractType && (sym0.name startsWith "_$") + issueSymbolTypeError(sym0, sym1+" is defined twice in " + context0.unit + + ( if (sym0.isMacro && sym1.isMacro) "\n(note that macros cannot be overloaded)" else "" ) + + ( if (isBug) "\n(this error is likely due to a bug in the scala compiler involving wildcards in package objects)" else "" ) + ) + } // cyclic errors def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) = diff --git a/test/files/neg/t200.check b/test/files/neg/t200.check index 78701f8533..3ef6665fe5 100644 --- a/test/files/neg/t200.check +++ b/test/files/neg/t200.check @@ -1,4 +1,4 @@ -t200.scala:7: error: method foo is defined twice +t200.scala:7: error: method foo is defined twice in t200.scala def foo: Int; ^ one error found diff --git a/test/files/neg/t2779.check b/test/files/neg/t2779.check index 4f94a780a1..d642541e3e 100644 --- a/test/files/neg/t2779.check +++ b/test/files/neg/t2779.check @@ -1,4 +1,4 @@ -t2779.scala:16: error: method f is defined twice +t2779.scala:16: error: method f is defined twice in t2779.scala override def f = List(M1) ^ one error found diff --git a/test/files/neg/t278.check b/test/files/neg/t278.check index 675ef910ee..0c2dfeb67a 100644 --- a/test/files/neg/t278.check +++ b/test/files/neg/t278.check @@ -4,7 +4,7 @@ t278.scala:5: error: overloaded method value a with alternatives: does not take type parameters println(a[A]) ^ -t278.scala:4: error: method a is defined twice +t278.scala:4: error: method a is defined twice in t278.scala def a = (p:A) => () ^ two errors found diff --git a/test/files/neg/t591.check b/test/files/neg/t591.check index 434c2dd002..5cdeebf079 100644 --- a/test/files/neg/t591.check +++ b/test/files/neg/t591.check @@ -1,4 +1,4 @@ -t591.scala:38: error: method input_= is defined twice +t591.scala:38: error: method input_= is defined twice in t591.scala def input_=(in : Input) = {} ^ one error found diff --git a/test/files/neg/t800.check b/test/files/neg/t800.check index 4bfba5420b..44c316a95b 100644 --- a/test/files/neg/t800.check +++ b/test/files/neg/t800.check @@ -1,13 +1,13 @@ t800.scala:4: error: qualification is already defined as value qualification val qualification = false; ^ -t800.scala:8: error: method qualification is defined twice +t800.scala:8: error: method qualification is defined twice in t800.scala val qualification = false; ^ -t800.scala:12: error: value qualification is defined twice +t800.scala:12: error: value qualification is defined twice in t800.scala var qualification = false; ^ -t800.scala:16: error: method qualification is defined twice +t800.scala:16: error: method qualification is defined twice in t800.scala var qualification = false; ^ four errors found diff --git a/test/files/neg/t960.check b/test/files/neg/t960.check index 4cc76d3602..603b1cb032 100644 --- a/test/files/neg/t960.check +++ b/test/files/neg/t960.check @@ -7,7 +7,7 @@ match argument types (List[a]) t960.scala:22: error: cannot resolve overloaded unapply case List(x, xs) => 7 ^ -t960.scala:12: error: method unapply is defined twice +t960.scala:12: error: method unapply is defined twice in t960.scala def unapply[a](xs: List[a]): Option[Null] = xs match { ^ -three errors found \ No newline at end of file +three errors found diff --git a/test/pending/run/t4511b.scala b/test/pending/run/t4511b.scala new file mode 100644 index 0000000000..3337fb3203 --- /dev/null +++ b/test/pending/run/t4511b.scala @@ -0,0 +1,25 @@ +import scala.{specialized => spec} + +class Interval[@spec(Int) T](high:T) + +class X1[@spec(Int) T](interval:Interval[T]) { val x = interval } +class Y1[@spec(Int) T](interval:Interval[T]) { val y = Some(interval) } + +class X2[T](val interval:Interval[T]) { val x = interval } +class Y2[T](val interval:Interval[T]) { val y = Some(interval) } + +class X3[@spec(Int) T](val interval:Interval[T]) { val x = interval } +class Y3[@spec(Int) T](val interval:Interval[T]) { val y = Some(interval) } + +object Test { + def tryit(o: => Any) = println(try { "ok: " + o.getClass.getName } catch { case e => "FAIL: " + e + "\n" + e.getStackTrace.mkString("\n ") }) + + def main(args: Array[String]) { + tryit(new X1(new Interval(3))) + tryit(new X2(new Interval(3))) + tryit(new X3(new Interval(3))) + tryit(new Y1(new Interval(3))) + tryit(new Y2(new Interval(3))) + tryit(new Y3(new Interval(3))) + } +} -- cgit v1.2.3 From fb87f2de763e558c8639905ea8dfb447b5212cf7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 3 Mar 2012 15:06:02 -0800 Subject: Test case closes SI-4777. And pending tests for most of the other VerifyErrors which still fail to verify. --- test/files/run/si4147.scala | 36 ------------------- test/files/run/si5171.check | 1 - test/files/run/si5171.scala | 7 ---- test/files/run/si5262.check | 2 -- test/files/run/si5262.scala | 26 -------------- test/files/run/si5374.check | 6 ---- test/files/run/si5374.scala | 76 --------------------------------------- test/files/run/si5375.check | 1 - test/files/run/si5375.scala | 19 ---------- test/files/run/si5380.scala | 6 ---- test/files/run/t4147.scala | 36 +++++++++++++++++++ test/files/run/t4777.check | 2 ++ test/files/run/t4777.scala | 8 +++++ test/files/run/t5171.check | 1 + test/files/run/t5171.scala | 7 ++++ test/files/run/t5262.check | 2 ++ test/files/run/t5262.scala | 26 ++++++++++++++ test/files/run/t5374.check | 6 ++++ test/files/run/t5374.scala | 76 +++++++++++++++++++++++++++++++++++++++ test/files/run/t5375.check | 1 + test/files/run/t5375.scala | 19 ++++++++++ test/files/run/t5380.scala | 6 ++++ test/pending/run/t3702.scala | 10 ++++++ test/pending/run/t3705.scala | 17 +++++++++ test/pending/run/t3832.scala | 7 ++++ test/pending/run/t4098.scala | 9 +++++ test/pending/run/t4415.scala | 86 ++++++++++++++++++++++++++++++++++++++++++++ test/pending/run/t4460.scala | 12 +++++++ 28 files changed, 331 insertions(+), 180 deletions(-) delete mode 100644 test/files/run/si4147.scala delete mode 100644 test/files/run/si5171.check delete mode 100644 test/files/run/si5171.scala delete mode 100644 test/files/run/si5262.check delete mode 100644 test/files/run/si5262.scala delete mode 100644 test/files/run/si5374.check delete mode 100644 test/files/run/si5374.scala delete mode 100644 test/files/run/si5375.check delete mode 100644 test/files/run/si5375.scala delete mode 100644 test/files/run/si5380.scala create mode 100644 test/files/run/t4147.scala create mode 100644 test/files/run/t4777.check create mode 100644 test/files/run/t4777.scala create mode 100644 test/files/run/t5171.check create mode 100644 test/files/run/t5171.scala create mode 100644 test/files/run/t5262.check create mode 100644 test/files/run/t5262.scala create mode 100644 test/files/run/t5374.check create mode 100644 test/files/run/t5374.scala create mode 100644 test/files/run/t5375.check create mode 100644 test/files/run/t5375.scala create mode 100644 test/files/run/t5380.scala create mode 100644 test/pending/run/t3702.scala create mode 100644 test/pending/run/t3705.scala create mode 100644 test/pending/run/t3832.scala create mode 100644 test/pending/run/t4098.scala create mode 100644 test/pending/run/t4415.scala create mode 100644 test/pending/run/t4460.scala (limited to 'test/pending/run') diff --git a/test/files/run/si4147.scala b/test/files/run/si4147.scala deleted file mode 100644 index c1e2d746a9..0000000000 --- a/test/files/run/si4147.scala +++ /dev/null @@ -1,36 +0,0 @@ - - - -import scala.collection._ - - - -object Test { - - def main(args: Array[String]) { - checkElementsAreSorted() - checkRangedImpl() - } - - def checkElementsAreSorted() { - val tree = mutable.SortedSet[Int]() - tree ++= List(4, 3, 1, 6, 7, 5, 2) - assert(tree == immutable.SortedSet(1, 2, 3, 4, 5, 6, 7)) - assert(tree.size == 7) - } - - def checkRangedImpl() { - val tree = mutable.SortedSet[Int](3, 1, 6, 7, 5, 2) - val projection = tree.rangeImpl(Some(3), Some(6)) - assert(projection == immutable.SortedSet(3, 5)) - assert(projection.size == 2) - - // Let's check that modification are taken into account - tree add 4 - assert(tree == immutable.SortedSet(1, 2, 3, 4, 5, 6, 7)) - assert(projection == immutable.SortedSet(3, 4, 5)) - assert(tree.size == 7) - assert(projection.size == 3) - } - -} diff --git a/test/files/run/si5171.check b/test/files/run/si5171.check deleted file mode 100644 index 159606d35c..0000000000 --- a/test/files/run/si5171.check +++ /dev/null @@ -1 +0,0 @@ -IsList diff --git a/test/files/run/si5171.scala b/test/files/run/si5171.scala deleted file mode 100644 index eb8029df80..0000000000 --- a/test/files/run/si5171.scala +++ /dev/null @@ -1,7 +0,0 @@ -abstract sealed class ArgNumber -case object IsList extends ArgNumber -case object ArgNumber - -object Test extends App { - println(IsList) -} diff --git a/test/files/run/si5262.check b/test/files/run/si5262.check deleted file mode 100644 index 4c7a875de5..0000000000 --- a/test/files/run/si5262.check +++ /dev/null @@ -1,2 +0,0 @@ -List(1, 2, 3, 4) -List(1, 2, null, 4) \ No newline at end of file diff --git a/test/files/run/si5262.scala b/test/files/run/si5262.scala deleted file mode 100644 index fc4e57aa96..0000000000 --- a/test/files/run/si5262.scala +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - -object Test { - - def serializationDeserialization(obj : Any) { - val bos = new java.io.ByteArrayOutputStream() - val out = new java.io.ObjectOutputStream(bos) - out.writeObject(obj) - - val arr = bos.toByteArray() - val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(arr)) - val o = in.readObject() - println(o) - } - - def main(args : Array[String]) { - serializationDeserialization(List(1,2,3,4)) - serializationDeserialization(List(1,2,null,4)) - } - -} diff --git a/test/files/run/si5374.check b/test/files/run/si5374.check deleted file mode 100644 index 6be88d77ec..0000000000 --- a/test/files/run/si5374.check +++ /dev/null @@ -1,6 +0,0 @@ -ListBuffer(1, 2, 3, 1) -ListBuffer(1, 2, 3, 1) -ListBuffer() -List(1, 2, 3, 4, 5) -List(1, 2, 3) -ok \ No newline at end of file diff --git a/test/files/run/si5374.scala b/test/files/run/si5374.scala deleted file mode 100644 index 9b1671e795..0000000000 --- a/test/files/run/si5374.scala +++ /dev/null @@ -1,76 +0,0 @@ - - - -import collection.mutable.ListBuffer -import java.io._ - - - -object Test { - - def main(args: Array[String]) { - ticketExample() - emptyListBuffer() - list() - legacyList() - objectWithMultipleLists() - } - - def inAndOut[T <: AnyRef](obj: T): T = { - val baos = new ByteArrayOutputStream - val oos = new ObjectOutputStream(baos) - oos.writeObject( obj ) - val bais = new ByteArrayInputStream( baos.toByteArray ) - val ois = new ObjectInputStream(bais) - ois.readObject.asInstanceOf[T] - } - - def ticketExample() { - val lb = inAndOut(ListBuffer(1, 2, 3)) - val lb2 = ListBuffer[Int]() ++= lb - - lb2 ++= List(1) - lb ++= List(1) - println(lb) - println(lb2) - } - - def emptyListBuffer() { - val lb = inAndOut(ListBuffer[Int]()) - - println(lb) - } - - def list() { - val l = inAndOut(List(1, 2, 3, 4, 5)) - - println(l) - } - - // this byte array corresponds to what List(1, 2, 3) used to be serialized to prior to this fix - val listBytes = Array[Byte](-84, -19, 0, 5, 115, 114, 0, 39, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, -118, 92, 99, 91, -10, -40, -7, 109, 3, 0, 2, 76, 0, 43, 115, 99, 97, 108, 97, 36, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 36, 105, 109, 109, 117, 116, 97, 98, 108, 101, 36, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, 36, 36, 104, 100, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 76, 0, 2, 116, 108, 116, 0, 33, 76, 115, 99, 97, 108, 97, 47, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 47, 105, 109, 109, 117, 116, 97, 98, 108, 101, 47, 76, 105, 115, 116, 59, 120, 112, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 1, 115, 113, 0, 126, 0, 4, 0, 0, 0, 2, 115, 113, 0, 126, 0, 4, 0, 0, 0, 3, 115, 114, 0, 44, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 76, 105, 115, 116, 83, 101, 114, 105, 97, 108, 105, 122, 101, 69, 110, 100, 36, -118, 92, 99, 91, -9, 83, 11, 109, 2, 0, 0, 120, 112, 120) - - def legacyList() { - val bais = new ByteArrayInputStream(listBytes) - val ois = new ObjectInputStream(bais) - val l = ois.readObject() - - println(l) - } - - class Foo extends Serializable { - val head = List(1, 2, 3) - val last = head.tail.tail - def structuralSharing: Boolean = head.tail.tail eq last - - assert(structuralSharing) - } - - def objectWithMultipleLists() { - val foo = inAndOut(new Foo) - - if (foo.structuralSharing) println("ok") - else println("no structural sharing") - } - -} diff --git a/test/files/run/si5375.check b/test/files/run/si5375.check deleted file mode 100644 index 7d3002ffda..0000000000 --- a/test/files/run/si5375.check +++ /dev/null @@ -1 +0,0 @@ -Composite throwable \ No newline at end of file diff --git a/test/files/run/si5375.scala b/test/files/run/si5375.scala deleted file mode 100644 index e4b329deae..0000000000 --- a/test/files/run/si5375.scala +++ /dev/null @@ -1,19 +0,0 @@ - - - -import collection.parallel.CompositeThrowable - - - -object Test { - - def main(args: Array[String]) { - val foos = (1 to 1000) toSeq; - try { - foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i) - } catch { - case CompositeThrowable(thr) => println("Composite throwable") - } - } - -} diff --git a/test/files/run/si5380.scala b/test/files/run/si5380.scala deleted file mode 100644 index 6083161a9b..0000000000 --- a/test/files/run/si5380.scala +++ /dev/null @@ -1,6 +0,0 @@ -object Test { - def main(args: Array[String]) { - val f = () => return try { 1 } catch { case _ => 0 } - f() - } -} diff --git a/test/files/run/t4147.scala b/test/files/run/t4147.scala new file mode 100644 index 0000000000..c1e2d746a9 --- /dev/null +++ b/test/files/run/t4147.scala @@ -0,0 +1,36 @@ + + + +import scala.collection._ + + + +object Test { + + def main(args: Array[String]) { + checkElementsAreSorted() + checkRangedImpl() + } + + def checkElementsAreSorted() { + val tree = mutable.SortedSet[Int]() + tree ++= List(4, 3, 1, 6, 7, 5, 2) + assert(tree == immutable.SortedSet(1, 2, 3, 4, 5, 6, 7)) + assert(tree.size == 7) + } + + def checkRangedImpl() { + val tree = mutable.SortedSet[Int](3, 1, 6, 7, 5, 2) + val projection = tree.rangeImpl(Some(3), Some(6)) + assert(projection == immutable.SortedSet(3, 5)) + assert(projection.size == 2) + + // Let's check that modification are taken into account + tree add 4 + assert(tree == immutable.SortedSet(1, 2, 3, 4, 5, 6, 7)) + assert(projection == immutable.SortedSet(3, 4, 5)) + assert(tree.size == 7) + assert(projection.size == 3) + } + +} diff --git a/test/files/run/t4777.check b/test/files/run/t4777.check new file mode 100644 index 0000000000..11f1f59d43 --- /dev/null +++ b/test/files/run/t4777.check @@ -0,0 +1,2 @@ +28 +28 diff --git a/test/files/run/t4777.scala b/test/files/run/t4777.scala new file mode 100644 index 0000000000..4a811d3b9a --- /dev/null +++ b/test/files/run/t4777.scala @@ -0,0 +1,8 @@ +class A(val a: Int = 13) +class DefaultsTest(x: Int = 25) extends A(28) +object DefaultsTest extends DefaultsTest(12) + +object Test extends App { + println(new DefaultsTest() a) + println(DefaultsTest a) +} diff --git a/test/files/run/t5171.check b/test/files/run/t5171.check new file mode 100644 index 0000000000..159606d35c --- /dev/null +++ b/test/files/run/t5171.check @@ -0,0 +1 @@ +IsList diff --git a/test/files/run/t5171.scala b/test/files/run/t5171.scala new file mode 100644 index 0000000000..eb8029df80 --- /dev/null +++ b/test/files/run/t5171.scala @@ -0,0 +1,7 @@ +abstract sealed class ArgNumber +case object IsList extends ArgNumber +case object ArgNumber + +object Test extends App { + println(IsList) +} diff --git a/test/files/run/t5262.check b/test/files/run/t5262.check new file mode 100644 index 0000000000..4c7a875de5 --- /dev/null +++ b/test/files/run/t5262.check @@ -0,0 +1,2 @@ +List(1, 2, 3, 4) +List(1, 2, null, 4) \ No newline at end of file diff --git a/test/files/run/t5262.scala b/test/files/run/t5262.scala new file mode 100644 index 0000000000..fc4e57aa96 --- /dev/null +++ b/test/files/run/t5262.scala @@ -0,0 +1,26 @@ + + + + + + + +object Test { + + def serializationDeserialization(obj : Any) { + val bos = new java.io.ByteArrayOutputStream() + val out = new java.io.ObjectOutputStream(bos) + out.writeObject(obj) + + val arr = bos.toByteArray() + val in = new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(arr)) + val o = in.readObject() + println(o) + } + + def main(args : Array[String]) { + serializationDeserialization(List(1,2,3,4)) + serializationDeserialization(List(1,2,null,4)) + } + +} diff --git a/test/files/run/t5374.check b/test/files/run/t5374.check new file mode 100644 index 0000000000..6be88d77ec --- /dev/null +++ b/test/files/run/t5374.check @@ -0,0 +1,6 @@ +ListBuffer(1, 2, 3, 1) +ListBuffer(1, 2, 3, 1) +ListBuffer() +List(1, 2, 3, 4, 5) +List(1, 2, 3) +ok \ No newline at end of file diff --git a/test/files/run/t5374.scala b/test/files/run/t5374.scala new file mode 100644 index 0000000000..9b1671e795 --- /dev/null +++ b/test/files/run/t5374.scala @@ -0,0 +1,76 @@ + + + +import collection.mutable.ListBuffer +import java.io._ + + + +object Test { + + def main(args: Array[String]) { + ticketExample() + emptyListBuffer() + list() + legacyList() + objectWithMultipleLists() + } + + def inAndOut[T <: AnyRef](obj: T): T = { + val baos = new ByteArrayOutputStream + val oos = new ObjectOutputStream(baos) + oos.writeObject( obj ) + val bais = new ByteArrayInputStream( baos.toByteArray ) + val ois = new ObjectInputStream(bais) + ois.readObject.asInstanceOf[T] + } + + def ticketExample() { + val lb = inAndOut(ListBuffer(1, 2, 3)) + val lb2 = ListBuffer[Int]() ++= lb + + lb2 ++= List(1) + lb ++= List(1) + println(lb) + println(lb2) + } + + def emptyListBuffer() { + val lb = inAndOut(ListBuffer[Int]()) + + println(lb) + } + + def list() { + val l = inAndOut(List(1, 2, 3, 4, 5)) + + println(l) + } + + // this byte array corresponds to what List(1, 2, 3) used to be serialized to prior to this fix + val listBytes = Array[Byte](-84, -19, 0, 5, 115, 114, 0, 39, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, -118, 92, 99, 91, -10, -40, -7, 109, 3, 0, 2, 76, 0, 43, 115, 99, 97, 108, 97, 36, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 36, 105, 109, 109, 117, 116, 97, 98, 108, 101, 36, 36, 99, 111, 108, 111, 110, 36, 99, 111, 108, 111, 110, 36, 36, 104, 100, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 59, 76, 0, 2, 116, 108, 116, 0, 33, 76, 115, 99, 97, 108, 97, 47, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 47, 105, 109, 109, 117, 116, 97, 98, 108, 101, 47, 76, 105, 115, 116, 59, 120, 112, 115, 114, 0, 17, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 73, 110, 116, 101, 103, 101, 114, 18, -30, -96, -92, -9, -127, -121, 56, 2, 0, 1, 73, 0, 5, 118, 97, 108, 117, 101, 120, 114, 0, 16, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 78, 117, 109, 98, 101, 114, -122, -84, -107, 29, 11, -108, -32, -117, 2, 0, 0, 120, 112, 0, 0, 0, 1, 115, 113, 0, 126, 0, 4, 0, 0, 0, 2, 115, 113, 0, 126, 0, 4, 0, 0, 0, 3, 115, 114, 0, 44, 115, 99, 97, 108, 97, 46, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 46, 105, 109, 109, 117, 116, 97, 98, 108, 101, 46, 76, 105, 115, 116, 83, 101, 114, 105, 97, 108, 105, 122, 101, 69, 110, 100, 36, -118, 92, 99, 91, -9, 83, 11, 109, 2, 0, 0, 120, 112, 120) + + def legacyList() { + val bais = new ByteArrayInputStream(listBytes) + val ois = new ObjectInputStream(bais) + val l = ois.readObject() + + println(l) + } + + class Foo extends Serializable { + val head = List(1, 2, 3) + val last = head.tail.tail + def structuralSharing: Boolean = head.tail.tail eq last + + assert(structuralSharing) + } + + def objectWithMultipleLists() { + val foo = inAndOut(new Foo) + + if (foo.structuralSharing) println("ok") + else println("no structural sharing") + } + +} diff --git a/test/files/run/t5375.check b/test/files/run/t5375.check new file mode 100644 index 0000000000..7d3002ffda --- /dev/null +++ b/test/files/run/t5375.check @@ -0,0 +1 @@ +Composite throwable \ No newline at end of file diff --git a/test/files/run/t5375.scala b/test/files/run/t5375.scala new file mode 100644 index 0000000000..e4b329deae --- /dev/null +++ b/test/files/run/t5375.scala @@ -0,0 +1,19 @@ + + + +import collection.parallel.CompositeThrowable + + + +object Test { + + def main(args: Array[String]) { + val foos = (1 to 1000) toSeq; + try { + foos.par.map(i => if (i % 37 == 0) sys.error("i div 37") else i) + } catch { + case CompositeThrowable(thr) => println("Composite throwable") + } + } + +} diff --git a/test/files/run/t5380.scala b/test/files/run/t5380.scala new file mode 100644 index 0000000000..6083161a9b --- /dev/null +++ b/test/files/run/t5380.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]) { + val f = () => return try { 1 } catch { case _ => 0 } + f() + } +} diff --git a/test/pending/run/t3702.scala b/test/pending/run/t3702.scala new file mode 100644 index 0000000000..e08fc12e76 --- /dev/null +++ b/test/pending/run/t3702.scala @@ -0,0 +1,10 @@ +object Test { + def main(args: Array[String]) { + foo(Nil, Nil) + } + + def foo(h: Any, t: List[Any]) = h match { + case 5 :: _ => () + case List(from) => List(from, from, from) + } +} diff --git a/test/pending/run/t3705.scala b/test/pending/run/t3705.scala new file mode 100644 index 0000000000..fcc020f28c --- /dev/null +++ b/test/pending/run/t3705.scala @@ -0,0 +1,17 @@ +// package foo + +import scala.xml._ +object Test { + def updateNodes(ns: Seq[Node]): Seq[Node] = + for(subnode <- ns) yield subnode match { + case {_} if true => abc + case Elem(prefix, label, attribs, scope, children @ _*) => + Elem(prefix, label, attribs, scope, updateNodes(children) : _*) + case other => other + } + def main(args: Array[String]): Unit = { + updateNodes() + + } +} + diff --git a/test/pending/run/t3832.scala b/test/pending/run/t3832.scala new file mode 100644 index 0000000000..f081d5b3af --- /dev/null +++ b/test/pending/run/t3832.scala @@ -0,0 +1,7 @@ +class Test { + def this(un: Int) = { + this() + def test(xs: List[Int]) = xs map (x => x) + () + } +} \ No newline at end of file diff --git a/test/pending/run/t4098.scala b/test/pending/run/t4098.scala new file mode 100644 index 0000000000..b74ccf9bff --- /dev/null +++ b/test/pending/run/t4098.scala @@ -0,0 +1,9 @@ +class A(a: Any) { + def this() = { this(b) ; def b = new {} } +} + +object Test { + def main(args: Array[String]): Unit = { + new A ("") + } +} diff --git a/test/pending/run/t4415.scala b/test/pending/run/t4415.scala new file mode 100644 index 0000000000..f96031d650 --- /dev/null +++ b/test/pending/run/t4415.scala @@ -0,0 +1,86 @@ +/** + * Demonstration of issue with Extractors. If lines 15/16 are not present, get at runtime: + * + * Exception in thread "main" java.lang.VerifyError: (class: ExtractorIssue$$, method: convert signature: (LTopProperty;)LMyProp;) Accessing value from uninitialized register 5 + * at ExtractorIssue.main(ExtractorIssue.scala) + * at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)] + * + * If lines 15/16 are present, the compiler crashes: + * + * fatal error (server aborted): not enough arguments for method body%3: (val p: MyProp[java.lang.String])MyProp[_33]. + * Unspecified value parameter p. + */ +object Test { + + def main(args: Array[String]) { + convert(new SubclassProperty) + } + + def convert(prop: TopProperty): MyProp[_] = { + prop match { + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //case SubclassSecondMatch(p) => p // if these lines are present, the compiler crashes. If commented, unsafe byte + //case SecondMatch(p) => p // byte code is generated, which causes a java.lang.VerifyError at runtime + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + case SubclassMatch(p) => p + case StandardMatch(p) => p + } + } +} + +class TopProperty + +class StandardProperty extends TopProperty +class SubclassProperty extends StandardProperty + +class SecondProperty extends TopProperty +class SubclassSecondProperty extends StandardProperty + +trait MyProp[T] +case class MyPropImpl[T] extends MyProp[T] + +object SubclassMatch { + + def unapply(prop: SubclassProperty) : Option[MyProp[String]] = { + Some(new MyPropImpl) + } + + def apply(prop: MyProp[String]) : SubclassProperty = { + new SubclassProperty() + } +} + +object StandardMatch { + + def unapply(prop: StandardProperty) : Option[MyProp[String]] = { + Some(new MyPropImpl) + } + + def apply(prop: MyProp[String]) : StandardProperty = { + new StandardProperty() + } +} + +object SubclassSecondMatch { + + def unapply(prop: SubclassSecondProperty) : Option[MyProp[BigInt]] = { + Some(new MyPropImpl) + } + + def apply(prop: MyProp[String]) : SubclassSecondProperty = { + new SubclassSecondProperty() + } +} + +object SecondMatch { + + def unapply(prop: SecondProperty) : Option[MyProp[BigInt]] = { + Some(new MyPropImpl) + } + + def apply(prop: MyProp[String]) : SecondProperty = { + new SecondProperty() + } +} \ No newline at end of file diff --git a/test/pending/run/t4460.scala b/test/pending/run/t4460.scala new file mode 100644 index 0000000000..324e2f5bef --- /dev/null +++ b/test/pending/run/t4460.scala @@ -0,0 +1,12 @@ +trait A + +class B(val x: Int) { + self: A => + + def this() = this() +} + +object Test extends B(2) with A { + def main(args: Array[String]) { } +} + -- cgit v1.2.3