From 396c01b2c10fe361e92b060e9d524921bd3849d6 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sun, 29 Jan 2012 15:59:08 +0100 Subject: Test for https://issues.scala-lang.org/browse/SI-5418 --- test/pending/run/t5418.check | 0 test/pending/run/t5418.scala | 14 ++++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 test/pending/run/t5418.check create mode 100644 test/pending/run/t5418.scala (limited to 'test/pending') diff --git a/test/pending/run/t5418.check b/test/pending/run/t5418.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5418.scala b/test/pending/run/t5418.scala new file mode 100644 index 0000000000..065710f15e --- /dev/null +++ b/test/pending/run/t5418.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{ + new Object().getClass + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} \ No newline at end of file -- cgit v1.2.3 From 41ce53e3e643e85a022393e54c952ec4dee2cb57 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 31 Jan 2012 19:23:00 +0100 Subject: Tests for https://issues.scala-lang.org/browse/SI-5427 --- test/pending/run/t5427a.check | 1 + test/pending/run/t5427a.scala | 10 ++++++++++ test/pending/run/t5427b.check | 1 + test/pending/run/t5427b.scala | 11 +++++++++++ test/pending/run/t5427c.check | 1 + test/pending/run/t5427c.scala | 13 +++++++++++++ test/pending/run/t5427d.check | 1 + test/pending/run/t5427d.scala | 11 +++++++++++ 8 files changed, 49 insertions(+) create mode 100644 test/pending/run/t5427a.check create mode 100644 test/pending/run/t5427a.scala create mode 100644 test/pending/run/t5427b.check create mode 100644 test/pending/run/t5427b.scala create mode 100644 test/pending/run/t5427c.check create mode 100644 test/pending/run/t5427c.scala create mode 100644 test/pending/run/t5427d.check create mode 100644 test/pending/run/t5427d.scala (limited to 'test/pending') diff --git a/test/pending/run/t5427a.check b/test/pending/run/t5427a.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/pending/run/t5427a.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/pending/run/t5427a.scala b/test/pending/run/t5427a.scala new file mode 100644 index 0000000000..27b28da0ac --- /dev/null +++ b/test/pending/run/t5427a.scala @@ -0,0 +1,10 @@ +import scala.reflect.mirror._ + +object Foo { val bar = 2 } + +object Test extends App { + val tpe = getType(Foo) + val bar = tpe.nonPrivateMember(newTermName("bar")) + val value = getValue(Foo, bar) + println(value) +} \ No newline at end of file diff --git a/test/pending/run/t5427b.check b/test/pending/run/t5427b.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/pending/run/t5427b.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/pending/run/t5427b.scala b/test/pending/run/t5427b.scala new file mode 100644 index 0000000000..7a92b6ebbe --- /dev/null +++ b/test/pending/run/t5427b.scala @@ -0,0 +1,11 @@ +import scala.reflect.mirror._ + +class Foo { val bar = 2 } + +object Test extends App { + val foo = new Foo + val tpe = getType(foo) + val bar = tpe.nonPrivateMember(newTermName("bar")) + val value = getValue(foo, bar) + println(value) +} \ No newline at end of file diff --git a/test/pending/run/t5427c.check b/test/pending/run/t5427c.check new file mode 100644 index 0000000000..32c91abbd6 --- /dev/null +++ b/test/pending/run/t5427c.check @@ -0,0 +1 @@ +no public member \ No newline at end of file diff --git a/test/pending/run/t5427c.scala b/test/pending/run/t5427c.scala new file mode 100644 index 0000000000..ab41d8b8cd --- /dev/null +++ b/test/pending/run/t5427c.scala @@ -0,0 +1,13 @@ +import scala.reflect.mirror._ + +class Foo(bar: Int) + +object Test extends App { + val foo = new Foo(2) + val tpe = getType(foo) + val bar = tpe.nonPrivateMember(newTermName("bar")) + bar match { + case NoSymbol => println("no public member") + case _ => println("i'm screwed") + } +} \ No newline at end of file diff --git a/test/pending/run/t5427d.check b/test/pending/run/t5427d.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/pending/run/t5427d.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/pending/run/t5427d.scala b/test/pending/run/t5427d.scala new file mode 100644 index 0000000000..fd4c62e876 --- /dev/null +++ b/test/pending/run/t5427d.scala @@ -0,0 +1,11 @@ +import scala.reflect.mirror._ + +class Foo(val bar: Int) + +object Test extends App { + val foo = new Foo(2) + val tpe = getType(foo) + val bar = tpe.nonPrivateMember(newTermName("bar")) + val value = getValue(foo, bar) + println(value) +} \ No newline at end of file -- cgit v1.2.3 From 1e0707786b118e3e33379e7acdc75306b45e6547 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 31 Jan 2012 12:12:23 +0100 Subject: Hardens classToType logic Reflection now correctly processes classes, objects and inner classes that are declared in classes and objects. However classToType still crashes on compound types and local classes. For more information on those, follow the links: * Compound types: https://issues.scala-lang.org/browse/SI-5430 * Local classes: https://issues.scala-lang.org/browse/SI-5431 Fixes https://issues.scala-lang.org/browse/SI-5256. Review by @paulp, @odersky. --- .../scala/reflect/runtime/JavaToScala.scala | 118 +++++++++++++++------ .../nsc/interpreter/AbstractFileClassLoader.scala | 39 ++++++- .../scala/tools/nsc/interpreter/IMain.scala | 30 +----- test/files/run/t5256a.check | 2 + test/files/run/t5256a.scala | 9 ++ test/files/run/t5256b.check | 2 + test/files/run/t5256b.scala | 8 ++ test/files/run/t5256d.check | 20 ++++ test/files/run/t5256d.scala | 10 ++ test/files/run/t5256e.check | 2 + test/files/run/t5256e.scala | 9 ++ test/files/run/t5256f.check | 4 + test/files/run/t5256f.scala | 19 ++++ test/pending/run/t5256c.check | 0 test/pending/run/t5256c.scala | 10 ++ test/pending/run/t5256g.check | 0 test/pending/run/t5256g.scala | 11 ++ test/pending/run/t5256h.check | 8 ++ test/pending/run/t5256h.scala | 8 ++ 19 files changed, 247 insertions(+), 62 deletions(-) create mode 100644 test/files/run/t5256a.check create mode 100644 test/files/run/t5256a.scala create mode 100644 test/files/run/t5256b.check create mode 100644 test/files/run/t5256b.scala create mode 100644 test/files/run/t5256d.check create mode 100644 test/files/run/t5256d.scala create mode 100644 test/files/run/t5256e.check create mode 100644 test/files/run/t5256e.scala create mode 100644 test/files/run/t5256f.check create mode 100644 test/files/run/t5256f.scala create mode 100644 test/pending/run/t5256c.check create mode 100644 test/pending/run/t5256c.scala create mode 100644 test/pending/run/t5256g.check create mode 100644 test/pending/run/t5256g.scala create mode 100644 test/pending/run/t5256h.check create mode 100644 test/pending/run/t5256h.scala (limited to 'test/pending') diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index b4bcc52a23..4c49c0221f 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -241,16 +241,32 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => * The Scala owner of the Scala class corresponding to the Java class `jclazz` */ private def sOwner(jclazz: jClass[_]): Symbol = { - if (jclazz.isMemberClass) - followStatic(classToScala(jclazz.getEnclosingClass), jclazz.getModifiers) - else if (jclazz.isLocalClass) - methodToScala(jclazz.getEnclosingMethod) orElse constrToScala(jclazz.getEnclosingConstructor) - else if (jclazz.isPrimitive || jclazz.isArray) + if (jclazz.isMemberClass) { + val jEnclosingClass = jclazz.getEnclosingClass + val sEnclosingClass = classToScala(jEnclosingClass) + followStatic(sEnclosingClass, jclazz.getModifiers) + } else if (jclazz.isLocalClass) { + val jEnclosingMethod = jclazz.getEnclosingMethod + if (jEnclosingMethod != null) { + methodToScala(jEnclosingMethod) + } else { + val jEnclosingConstructor = jclazz.getEnclosingConstructor + constrToScala(jEnclosingConstructor) + } + } else if (jclazz.isPrimitive || jclazz.isArray) { ScalaPackageClass - else if (jclazz.getPackage != null) - packageToScala(jclazz.getPackage) - else + } else if (jclazz.getPackage != null) { + val jPackage = jclazz.getPackage + packageToScala(jPackage) + } else { + // @eb: a weird classloader might return a null package for something with a non-empty package name + // for example, http://groups.google.com/group/scala-internals/browse_thread/thread/7be09ff8f67a1e5c + // in that case we could invoke packageNameToScala(jPackageName) and, probably, be okay + // however, I think, it's better to blow up, since weirdness of the class loader might bite us elsewhere + val jPackageName = jclazz.getName.substring(0, Math.max(jclazz.getName.lastIndexOf("."), 0)) + assert(jPackageName == "") EmptyPackageClass + } } /** @@ -295,8 +311,10 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => * @return A Scala method object that corresponds to `jmeth`. */ def methodToScala(jmeth: jMethod): Symbol = methodCache.toScala(jmeth) { - val owner = followStatic(classToScala(jmeth.getDeclaringClass), jmeth.getModifiers) - lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth) + val jOwner = jmeth.getDeclaringClass + var sOwner = classToScala(jOwner) + sOwner = followStatic(sOwner, jmeth.getModifiers) + lookup(sOwner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth) } /** @@ -344,6 +362,18 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => pkg.moduleClass } + private def scalaSimpleName(jclazz: jClass[_]): TypeName = { + val owner = sOwner(jclazz) + val enclosingClass = jclazz.getEnclosingClass + var prefix = if (enclosingClass != null) enclosingClass.getName else "" + val isObject = owner.isModuleClass && !owner.isPackageClass + if (isObject && !prefix.endsWith(nme.MODULE_SUFFIX_STRING)) prefix += nme.MODULE_SUFFIX_STRING + assert(jclazz.getName.startsWith(prefix)) + var name = jclazz.getName.substring(prefix.length) + name = name.substring(name.lastIndexOf(".") + 1) + newTypeName(name) + } + /** * The Scala class that corresponds to a given Java class. * @param jclazz The Java class @@ -353,28 +383,54 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => */ def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) { val jname = javaTypeName(jclazz) - def lookup = sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)) - - if (jclazz.isMemberClass && !nme.isImplClassName(jname)) { - val sym = lookup - assert(sym.isType, sym+"/"+jclazz+"/"+sOwner(jclazz)+"/"+jclazz.getSimpleName) - sym.asInstanceOf[ClassSymbol] - } - else if (jclazz.isLocalClass || invalidClassName(jname)) { - // local classes and implementation classes not preserved by unpickling - treat as Java - jclassAsScala(jclazz) - } - else if (jclazz.isArray) { - ArrayClass + val owner = sOwner(jclazz) + val simpleName = scalaSimpleName(jclazz) + + val sym = { + def lookup = { + def coreLookup(name: Name): Symbol = { + val sym = owner.info.decl(name) + sym orElse { + if (name.startsWith(nme.NAME_JOIN_STRING)) + coreLookup(name.subName(1, name.length)) + else + NoSymbol + } + } + + if (nme.isModuleName(simpleName)) { + val moduleName = nme.stripModuleSuffix(simpleName).toTermName + val sym = coreLookup(moduleName) + if (sym == NoSymbol) sym else sym.moduleClass + } else { + coreLookup(simpleName) + } + } + + if (jclazz.isMemberClass && !nme.isImplClassName(jname)) { + lookup + } else if (jclazz.isLocalClass || invalidClassName(jname)) { + // local classes and implementation classes not preserved by unpickling - treat as Java + jclassAsScala(jclazz) + } else if (jclazz.isArray) { + ArrayClass + } else javaTypeToValueClass(jclazz) orElse { + // jclazz is top-level - get signature + lookup + // val (clazz, module) = createClassModule( + // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _)) + // classCache enter (jclazz, clazz) + // clazz + } } - else javaTypeToValueClass(jclazz) orElse { - // jclazz is top-level - get signature - lookup - // val (clazz, module) = createClassModule( - // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _)) - // classCache enter (jclazz, clazz) - // clazz + + if (!sym.isType) { + def msgNoSym = "no symbol could be loaded from %s (scala equivalent is %s) by name %s".format(owner, jclazz, simpleName) + def msgIsNotType = "not a type: symbol %s loaded from %s (scala equivalent is %s) by name %s".format(sym, owner, jclazz, simpleName) + assert(false, if (sym == NoSymbol) msgNoSym else msgIsNotType) } + + sym.asInstanceOf[ClassSymbol] } /** @@ -453,7 +509,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz)) private def jclassAsScala(jclazz: jClass[_], owner: Symbol): Symbol = { - val name = newTypeName(jclazz.getSimpleName) + val name = scalaSimpleName(jclazz) val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) val (clazz, module) = createClassModule(owner, name, completer) classCache enter (jclazz, clazz) diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala index 70fa740eeb..3a605975f4 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala @@ -21,9 +21,6 @@ class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) { // private val defined = mutable.Map[String, Class[_]]() - // Widening to public - override def getPackage(name: String) = super.getPackage(name) - override protected def trace = sys.props contains "scala.debug.classloader" @@ -47,6 +44,22 @@ class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) } } + protected def dirNameToPath(name: String): String = + name.replace('.', '/') + + protected def findAbstractDir(name: String): AbstractFile = { + var file: AbstractFile = root + val pathParts = dirNameToPath(name) split '/' + + for (dirPart <- pathParts) { + file = file.lookupName(dirPart, true) + if (file == null) + return null + } + + return file + } + override def getResourceAsStream(name: String) = findAbstractFile(name) match { case null => super.getResourceAsStream(name) case file => file.input @@ -78,4 +91,24 @@ class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) // case null => super.getResource(name) // case file => new URL(...) // } + + private val packages = mutable.Map[String, Package]() + + override def definePackage(name: String, specTitle: String, specVersion: String, specVendor: String, implTitle: String, implVersion: String, implVendor: String, sealBase: URL): Package = { + throw new UnsupportedOperationException() + } + + override def getPackage(name: String): Package = { + findAbstractDir(name) match { + case null => super.getPackage(name) + case file => packages.getOrElseUpdate(name, { + val ctor = classOf[Package].getDeclaredConstructor(classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[String], classOf[URL], classOf[ClassLoader]) + ctor.setAccessible(true) + ctor.newInstance(name, null, null, null, null, null, null, null, this) + }) + } + } + + override def getPackages(): Array[Package] = + root.iterator.filter(_.isDirectory).map(dir => getPackage(dir.name)).toArray } diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 4ccea8afd6..6ae8d0e7d0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -196,7 +196,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def foreach[U](f: Tree => U): Unit = t foreach { x => f(x) ; () } }).toList } - + implicit def installReplTypeOps(tp: Type): ReplTypeOps = new ReplTypeOps(tp) class ReplTypeOps(tp: Type) { def orElse(other: => Type): Type = if (tp ne NoType) tp else other @@ -314,26 +314,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(virtualDirectory, parent) { private[IMain] var traceClassLoading = isReplTrace override protected def trace = super.trace || traceClassLoading - - private val packages = mutable.HashMap[String, Package]() - private def enclosingPackageNames(name: String): List[String] = - (name split '.').inits.toList drop 1 dropRight 1 map (_ mkString ".") reverse - - // Here's what all those params to definePackage are after the package name: - // - // specTitle - The specification title - // specVersion - The specification version - // specVendor - The specification vendor - // implTitle - The implementation title - // implVersion - The implementation version - // implVendor - The implementation vendor - // sealBase - If not null, then this package is sealed with respect to the given code source URL object. Otherwise, the package is not sealed. - private def addPackageNames(name: String) { - enclosingPackageNames(name) filterNot (packages contains _) foreach { p => - packages(p) = definePackage(p, "", "", "", "", "", "", null) - repltrace("Added " + packages(p) + " to repl classloader.") - } - } /** Overridden here to try translating a simple name to the generated * class name if the original attempt fails. This method is used by @@ -348,12 +328,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends file } } - override def findClass(name: String): JClass = { - val clazz = super.findClass(name) - if (clazz ne null) - addPackageNames(clazz.getName) - clazz - } } private def makeClassLoader(): AbstractFileClassLoader = new TranslatingClassLoader(parentClassLoader match { @@ -1104,7 +1078,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val clazz = classOfTerm(id) getOrElse { return NoType } val staticSym = tpe.typeSymbol val runtimeSym = getClassIfDefined(clazz.getName) - + if ((runtimeSym != NoSymbol) && (runtimeSym != staticSym) && (runtimeSym isSubClass staticSym)) runtimeSym.info else NoType diff --git a/test/files/run/t5256a.check b/test/files/run/t5256a.check new file mode 100644 index 0000000000..304f4ddd79 --- /dev/null +++ b/test/files/run/t5256a.check @@ -0,0 +1,2 @@ +A +true diff --git a/test/files/run/t5256a.scala b/test/files/run/t5256a.scala new file mode 100644 index 0000000000..05a935c770 --- /dev/null +++ b/test/files/run/t5256a.scala @@ -0,0 +1,9 @@ +import scala.reflect.mirror._ + +class A + +object Test extends App { + val c = classToType(classOf[A]) + println(c) + println(c.typeSymbol == classToSymbol(classOf[A])) +} diff --git a/test/files/run/t5256b.check b/test/files/run/t5256b.check new file mode 100644 index 0000000000..64f4c01166 --- /dev/null +++ b/test/files/run/t5256b.check @@ -0,0 +1,2 @@ +Test.A +true \ No newline at end of file diff --git a/test/files/run/t5256b.scala b/test/files/run/t5256b.scala new file mode 100644 index 0000000000..5575211641 --- /dev/null +++ b/test/files/run/t5256b.scala @@ -0,0 +1,8 @@ +import scala.reflect.mirror._ + +object Test extends App { + class A + val c = classToType(classOf[A]) + println(c) + println(c.typeSymbol == classToSymbol(classOf[A])) +} diff --git a/test/files/run/t5256d.check b/test/files/run/t5256d.check new file mode 100644 index 0000000000..7924c15c5c --- /dev/null +++ b/test/files/run/t5256d.check @@ -0,0 +1,20 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> import scala.reflect.mirror._ +import scala.reflect.mirror._ + +scala> class A +defined class A + +scala> val c = classToType(classOf[A]) +c: reflect.mirror.Type = A + +scala> println(c.typeSymbol == classToSymbol(classOf[A])) +true + +scala> + +scala> diff --git a/test/files/run/t5256d.scala b/test/files/run/t5256d.scala new file mode 100644 index 0000000000..86404a9b63 --- /dev/null +++ b/test/files/run/t5256d.scala @@ -0,0 +1,10 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ +import scala.reflect.mirror._ +class A +val c = classToType(classOf[A]) +println(c.typeSymbol == classToSymbol(classOf[A])) + """ +} diff --git a/test/files/run/t5256e.check b/test/files/run/t5256e.check new file mode 100644 index 0000000000..e50f917e14 --- /dev/null +++ b/test/files/run/t5256e.check @@ -0,0 +1,2 @@ +C.this.A +true \ No newline at end of file diff --git a/test/files/run/t5256e.scala b/test/files/run/t5256e.scala new file mode 100644 index 0000000000..9ed422ca44 --- /dev/null +++ b/test/files/run/t5256e.scala @@ -0,0 +1,9 @@ +import scala.reflect.mirror._ + +class C { class A } + +object Test extends App { + val c = classToType(classOf[C#A]) + println(c) + println(c.typeSymbol == classToSymbol(classOf[C#A])) +} diff --git a/test/files/run/t5256f.check b/test/files/run/t5256f.check new file mode 100644 index 0000000000..ad2f375d9a --- /dev/null +++ b/test/files/run/t5256f.check @@ -0,0 +1,4 @@ +Test.A1 +true +Test.this.A2 +true diff --git a/test/files/run/t5256f.scala b/test/files/run/t5256f.scala new file mode 100644 index 0000000000..45c80cbd63 --- /dev/null +++ b/test/files/run/t5256f.scala @@ -0,0 +1,19 @@ +import scala.reflect.mirror._ + +object Test extends App { + class A1 + + val c1 = classToType(classOf[A1]) + println(c1) + println(c1.typeSymbol == classToSymbol(classOf[A1])) + + new Test +} + +class Test { + class A2 + + val c2 = classToType(classOf[A2]) + println(c2) + println(c2.typeSymbol == classToSymbol(classOf[A2])) +} diff --git a/test/pending/run/t5256c.check b/test/pending/run/t5256c.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5256c.scala b/test/pending/run/t5256c.scala new file mode 100644 index 0000000000..8ebb51a009 --- /dev/null +++ b/test/pending/run/t5256c.scala @@ -0,0 +1,10 @@ +import scala.reflect.mirror._ + +object Test extends App { + { + class A + val c = classToType(classOf[A]) + println(c) + println(c.typeSymbol == classToSymbol(classOf[A])) + } +} diff --git a/test/pending/run/t5256g.check b/test/pending/run/t5256g.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5256g.scala b/test/pending/run/t5256g.scala new file mode 100644 index 0000000000..6158a9281d --- /dev/null +++ b/test/pending/run/t5256g.scala @@ -0,0 +1,11 @@ +import scala.reflect.mirror._ + +class A +trait B + +object Test extends App { + val mutant = new A with B + val c = classToType(mutant.getClass) + println(c) + println(c.typeSymbol == classToSymbol(mutant.getClass)) +} diff --git a/test/pending/run/t5256h.check b/test/pending/run/t5256h.check new file mode 100644 index 0000000000..4f9b8faf71 --- /dev/null +++ b/test/pending/run/t5256h.check @@ -0,0 +1,8 @@ +import scala.reflect.mirror._ + +object Test extends App { + val mutant = new { val x = 2 } + val c = classToType(mutant.getClass) + println(c) + println(c.typeSymbol == classToSymbol(mutant.getClass)) +} diff --git a/test/pending/run/t5256h.scala b/test/pending/run/t5256h.scala new file mode 100644 index 0000000000..4f9b8faf71 --- /dev/null +++ b/test/pending/run/t5256h.scala @@ -0,0 +1,8 @@ +import scala.reflect.mirror._ + +object Test extends App { + val mutant = new { val x = 2 } + val c = classToType(mutant.getClass) + println(c) + println(c.typeSymbol == classToSymbol(mutant.getClass)) +} -- cgit v1.2.3 From 610027b3c50c6a46b26bcfe71013cebc172c146b Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 31 Jan 2012 15:02:48 +0100 Subject: Hardens reification against rare kinds of Constants Importers now correctly process constants that carry types and symbols. However, it is still impossible to reify classOf for a class/trait that is defined inside a quasiquote. Theoretically, this can be implemented, but will require attaching original trees to classOf constants, which needs much more effort. --- .../scala/reflect/internal/Constants.scala | 2 +- .../scala/reflect/internal/Importers.scala | 17 ++++++++----- .../scala/tools/nsc/transform/LiftCode.scala | 28 +++++++++++++++++++--- test/files/run/t5258a.check | 1 + test/files/run/t5258a.scala | 14 +++++++++++ test/pending/run/t5258b.check | 1 + test/pending/run/t5258b.scala | 15 ++++++++++++ test/pending/run/t5258c.check | 1 + test/pending/run/t5258c.scala | 15 ++++++++++++ 9 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 test/files/run/t5258a.check create mode 100644 test/files/run/t5258a.scala create mode 100644 test/pending/run/t5258b.check create mode 100644 test/pending/run/t5258b.scala create mode 100644 test/pending/run/t5258c.check create mode 100644 test/pending/run/t5258c.scala (limited to 'test/pending') diff --git a/src/compiler/scala/reflect/internal/Constants.scala b/src/compiler/scala/reflect/internal/Constants.scala index 9c4b2b2245..c328cc49cb 100644 --- a/src/compiler/scala/reflect/internal/Constants.scala +++ b/src/compiler/scala/reflect/internal/Constants.scala @@ -45,7 +45,7 @@ trait Constants extends api.Constants { case x: Char => CharTag case x: Type => ClassTag case x: Symbol => EnumTag - case _ => throw new Error("bad constant value: " + value) + case _ => throw new Error("bad constant value: " + value + " of class " + value.getClass) } def isByteRange: Boolean = isIntRange && Byte.MinValue <= intValue && intValue <= Byte.MaxValue diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 23b443919a..4f5b28d370 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -145,8 +145,8 @@ trait Importers { self: SymbolTable => PolyType(tparams map importSymbol, importType(restpe)) case from.NullaryMethodType(restpe) => NullaryMethodType(importType(restpe)) - case from.ConstantType(from.Constant(value)) => - ConstantType(Constant(value)) + case from.ConstantType(constant @ from.Constant(_)) => + ConstantType(importConstant(constant)) case from.SuperType(thistpe, supertpe) => SuperType(importType(thistpe), importType(supertpe)) case from.TypeBounds(lo, hi) => @@ -194,8 +194,8 @@ trait Importers { self: SymbolTable => }) def importAnnotArg(arg: from.ClassfileAnnotArg): ClassfileAnnotArg = arg match { - case from.LiteralAnnotArg(from.Constant(value)) => - LiteralAnnotArg(Constant(value)) + case from.LiteralAnnotArg(constant @ from.Constant(_)) => + LiteralAnnotArg(importConstant(constant)) case from.ArrayAnnotArg(args) => ArrayAnnotArg(args map importAnnotArg) case from.ScalaSigBytes(bytes) => @@ -303,8 +303,8 @@ trait Importers { self: SymbolTable => case _ => new Ident(importName(name)) } - case from.Literal(from.Constant(value)) => - new Literal(Constant(value)) + case from.Literal(constant @ from.Constant(_)) => + new Literal(importConstant(constant)) case from.TypeTree() => new TypeTree() case from.Annotated(annot, arg) => @@ -339,5 +339,10 @@ trait Importers { self: SymbolTable => def importRefTree(tree: from.RefTree): RefTree = importTree(tree).asInstanceOf[RefTree] def importIdent(tree: from.Ident): Ident = importTree(tree).asInstanceOf[Ident] def importCaseDef(tree: from.CaseDef): CaseDef = importTree(tree).asInstanceOf[CaseDef] + def importConstant(constant: from.Constant): Constant = new Constant(constant.tag match { + case ClassTag => importType(constant.value.asInstanceOf[from.Type]) + case EnumTag => importSymbol(constant.value.asInstanceOf[from.Symbol]) + case _ => constant.value + }) } } diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index c5475fa0f2..f1182fc2a9 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -129,7 +129,13 @@ abstract class LiftCode extends Transform with TypingTransformers { if (reifyCopypaste) printCopypaste(result) result } - } finally printTypings = saved + } catch { + case ex: ReifierError => + unit.error(ex.pos, ex.msg) + tree + } finally { + printTypings = saved + } case _ => super.transform(tree) } @@ -396,6 +402,10 @@ abstract class LiftCode extends Transform with TypingTransformers { if (thereAreOnlyTTs && ttsAreNotEssential) reifyTree(hk) else reifyProduct(ta) case global.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) boundSyms += tree.symbol @@ -494,8 +504,20 @@ abstract class LiftCode extends Transform with TypingTransformers { symDefs.toList ++ fillIns.toList } + } + + /** A throwable signalling a reification error */ + class ReifierError(var pos: Position, val msg: String) extends Throwable(msg) { + def this(msg: String) = this(NoPosition, 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) + } - private def cannotReify(value: Any): Nothing = - abort("don't know how to reify " + value + " of " + value.getClass) + 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/test/files/run/t5258a.check b/test/files/run/t5258a.check new file mode 100644 index 0000000000..4e0b2da04c --- /dev/null +++ b/test/files/run/t5258a.check @@ -0,0 +1 @@ +int \ No newline at end of file diff --git a/test/files/run/t5258a.scala b/test/files/run/t5258a.scala new file mode 100644 index 0000000000..deabb8310f --- /dev/null +++ b/test/files/run/t5258a.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{ + println(classOf[Int]) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/pending/run/t5258b.check b/test/pending/run/t5258b.check new file mode 100644 index 0000000000..283b4225fb --- /dev/null +++ b/test/pending/run/t5258b.check @@ -0,0 +1 @@ +TBI \ No newline at end of file diff --git a/test/pending/run/t5258b.scala b/test/pending/run/t5258b.scala new file mode 100644 index 0000000000..70cb4a7f4e --- /dev/null +++ b/test/pending/run/t5258b.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{ + class C + println(classOf[C]) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} \ No newline at end of file diff --git a/test/pending/run/t5258c.check b/test/pending/run/t5258c.check new file mode 100644 index 0000000000..283b4225fb --- /dev/null +++ b/test/pending/run/t5258c.check @@ -0,0 +1 @@ +TBI \ No newline at end of file diff --git a/test/pending/run/t5258c.scala b/test/pending/run/t5258c.scala new file mode 100644 index 0000000000..a93170d0d6 --- /dev/null +++ b/test/pending/run/t5258c.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{ + object E extends Enumeration { val foo, bar = Value } + println(E.foo) + }; + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + toolbox.runExpr(ttree) +} \ No newline at end of file -- cgit v1.2.3 From d940371bd50098c4146e52941880ccdbcb4ea47a Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Thu, 2 Feb 2012 14:39:44 +0100 Subject: Miscellaneous fixes to reification More specifically: * Importers now preserve wasEmpty and original * ToolBoxes no longer auto-evaluate nullary functions returned by runExpr * All local symbols from previous typechecks are now correctly erased by ResetAttrs * Originals are now reified --- .../scala/reflect/internal/Importers.scala | 15 ++- src/compiler/scala/reflect/runtime/ToolBoxes.scala | 49 ++++++---- src/compiler/scala/tools/nsc/ast/Trees.scala | 107 ++++++++++++--------- .../scala/tools/nsc/settings/ScalaSettings.scala | 4 +- .../scala/tools/nsc/transform/LiftCode.scala | 62 +++++++++--- .../scala/tools/nsc/typechecker/Typers.scala | 2 +- .../scala/reflect/api/StandardDefinitions.scala | 7 +- .../scala/tools/partest/utils/CodeTest.scala | 10 +- test/files/run/code.check | 7 ++ test/files/run/reify_complex.check | 1 + test/files/run/reify_complex.scala | 31 ++++++ test/files/run/reify_extendbuiltins.check | 1 + test/files/run/reify_extendbuiltins.scala | 21 ++++ test/files/run/reify_generic2.check | 1 + test/files/run/reify_generic2.scala | 16 +++ test/files/run/reify_getter.check | 1 + test/files/run/reify_getter.scala | 19 ++++ test/files/run/reify_sort1.check | 2 + test/files/run/reify_sort1.scala | 27 ++++++ test/files/run/t5269.check | 1 + test/files/run/t5269.scala | 22 +++++ test/files/run/t5274_1.check | 3 + test/files/run/t5274_1.scala | 20 ++++ test/files/run/t5275.check | 1 + test/files/run/t5275.scala | 15 +++ test/files/run/t5277_1.check | 1 + test/files/run/t5277_1.scala | 21 ++++ test/files/run/t5277_2.check | 2 + test/files/run/t5277_2.scala | 18 ++++ test/files/run/t5335.check | 1 + test/files/run/t5335.scala | 14 +++ test/pending/run/reify_closure6.check | 6 +- test/pending/run/reify_closure6.scala | 2 + test/pending/run/reify_closure7.check | 6 ++ test/pending/run/reify_closure7.scala | 32 ++++++ test/pending/run/reify_closure8a.check | 1 + test/pending/run/reify_closure8a.scala | 17 ++++ test/pending/run/reify_closure8b.check | 1 + test/pending/run/reify_closure8b.scala | 17 ++++ test/pending/run/reify_closure9a.check | 1 + test/pending/run/reify_closure9a.scala | 20 ++++ test/pending/run/reify_closure9b.check | 1 + test/pending/run/reify_closure9b.scala | 20 ++++ test/pending/run/reify_closures10.check | 2 + test/pending/run/reify_closures10.scala | 15 +++ test/pending/run/reify_closures11.check | 1 + test/pending/run/reify_closures11.scala | 18 ++++ test/pending/run/reify_complex.check | 1 - test/pending/run/reify_complex.scala | 31 ------ test/pending/run/reify_extendbuiltins.check | 1 - test/pending/run/reify_extendbuiltins.scala | 21 ---- test/pending/run/reify_sort1.check | 2 - test/pending/run/reify_sort1.scala | 27 ------ test/pending/run/reify_this.check | 5 + test/pending/run/reify_this.scala | 31 ++++++ test/pending/run/t5269.check | 1 - test/pending/run/t5269.scala | 22 ----- test/pending/run/t5274_1.check | 3 - test/pending/run/t5274_1.scala | 20 ---- test/pending/run/t5275.check | 1 - test/pending/run/t5275.scala | 15 --- test/pending/run/t5277_1.check | 1 - test/pending/run/t5277_1.scala | 21 ---- test/pending/run/t5277_2.check | 2 - test/pending/run/t5277_2.scala | 18 ---- test/pending/run/t5415.check | 0 test/pending/run/t5415.scala | 14 +++ 67 files changed, 625 insertions(+), 274 deletions(-) create mode 100644 test/files/run/reify_complex.check create mode 100644 test/files/run/reify_complex.scala create mode 100644 test/files/run/reify_extendbuiltins.check create mode 100644 test/files/run/reify_extendbuiltins.scala create mode 100644 test/files/run/reify_generic2.check create mode 100644 test/files/run/reify_generic2.scala create mode 100644 test/files/run/reify_getter.check create mode 100644 test/files/run/reify_getter.scala create mode 100644 test/files/run/reify_sort1.check create mode 100644 test/files/run/reify_sort1.scala create mode 100644 test/files/run/t5269.check create mode 100644 test/files/run/t5269.scala create mode 100644 test/files/run/t5274_1.check create mode 100644 test/files/run/t5274_1.scala create mode 100644 test/files/run/t5275.check create mode 100644 test/files/run/t5275.scala create mode 100644 test/files/run/t5277_1.check create mode 100644 test/files/run/t5277_1.scala create mode 100644 test/files/run/t5277_2.check create mode 100644 test/files/run/t5277_2.scala create mode 100644 test/files/run/t5335.check create mode 100644 test/files/run/t5335.scala create mode 100644 test/pending/run/reify_closure7.check create mode 100644 test/pending/run/reify_closure7.scala create mode 100644 test/pending/run/reify_closure8a.check create mode 100644 test/pending/run/reify_closure8a.scala create mode 100644 test/pending/run/reify_closure8b.check create mode 100644 test/pending/run/reify_closure8b.scala create mode 100644 test/pending/run/reify_closure9a.check create mode 100644 test/pending/run/reify_closure9a.scala create mode 100644 test/pending/run/reify_closure9b.check create mode 100644 test/pending/run/reify_closure9b.scala create mode 100644 test/pending/run/reify_closures10.check create mode 100644 test/pending/run/reify_closures10.scala create mode 100644 test/pending/run/reify_closures11.check create mode 100644 test/pending/run/reify_closures11.scala delete mode 100644 test/pending/run/reify_complex.check delete mode 100644 test/pending/run/reify_complex.scala delete mode 100644 test/pending/run/reify_extendbuiltins.check delete mode 100644 test/pending/run/reify_extendbuiltins.scala delete mode 100644 test/pending/run/reify_sort1.check delete mode 100644 test/pending/run/reify_sort1.scala create mode 100644 test/pending/run/reify_this.check create mode 100644 test/pending/run/reify_this.scala delete mode 100644 test/pending/run/t5269.check delete mode 100644 test/pending/run/t5269.scala delete mode 100644 test/pending/run/t5274_1.check delete mode 100644 test/pending/run/t5274_1.scala delete mode 100644 test/pending/run/t5275.check delete mode 100644 test/pending/run/t5275.scala delete mode 100644 test/pending/run/t5277_1.check delete mode 100644 test/pending/run/t5277_1.scala delete mode 100644 test/pending/run/t5277_2.check delete mode 100644 test/pending/run/t5277_2.scala create mode 100644 test/pending/run/t5415.check create mode 100644 test/pending/run/t5415.scala (limited to 'test/pending') diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 4f5b28d370..6c843e6f15 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -327,8 +327,19 @@ trait Importers { self: SymbolTable => null } if (mytree != null) { - if (mytree hasSymbol) mytree.symbol = importSymbol(tree.symbol) - mytree.tpe = importType(tree.tpe) + 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 } diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 46d890c5d1..6e671ae06e 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -44,17 +44,19 @@ 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)) val ownerClass = EmptyPackageClass.newClassWithInfo(newTypeName(""), List(ObjectClass.tpe), newScope) val owner = ownerClass.newLocalDummy(tree.pos) - - typer.atOwner(tree, owner).typed(tree, analyzer.EXPRmode, pt) + val ttree = typer.atOwner(tree, owner).typed(tree, analyzer.EXPRmode, pt) + trace("typed: ")(showAttributed(ttree)) + ttree } - + def defOwner(tree: Tree): Symbol = tree find (_.isDef) map (_.symbol) match { case Some(sym) if sym != null && sym != NoSymbol => sym.owner case _ => NoSymbol } - + def wrapInObject(expr: Tree, fvs: List[Symbol]): ModuleDef = { val obj = EmptyPackageClass.newModule(nextWrapperModuleName()) val minfo = ClassInfoType(List(ObjectClass.tpe, ScalaObjectClass.tpe), newScope, obj.moduleClass) @@ -66,9 +68,7 @@ trait ToolBoxes extends { self: Universe => minfo.decls enter meth trace("wrapping ")(defOwner(expr) -> meth) val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth)) - trace("wrapped: ")(showAttributed(methdef)) - resetAllAttrs( - ModuleDef( + val moduledef = ModuleDef( obj, Template( List(TypeTree(ObjectClass.tpe)), @@ -77,7 +77,11 @@ trait ToolBoxes extends { self: Universe => List(), List(List()), List(methdef), - NoPosition))) + NoPosition)) + trace("wrapped: ")(showAttributed(moduledef)) + val cleanedUp = resetLocalAttrs(moduledef) + trace("cleaned up: ")(showAttributed(cleanedUp)) + cleanedUp } def wrapInPackage(clazz: Tree): PackageDef = @@ -91,7 +95,7 @@ trait ToolBoxes extends { self: Universe => def compileExpr(expr: Tree, fvs: List[Symbol]): String = { val mdef = wrapInObject(expr, fvs) - val pdef = trace("wrapped: ")(wrapInPackage(mdef)) + val pdef = wrapInPackage(mdef) val unit = wrapInCompilationUnit(pdef) val run = new Run run.compileUnits(List(unit), run.namerPhase) @@ -104,24 +108,27 @@ trait ToolBoxes extends { self: Universe => def runExpr(expr: Tree): Any = { val etpe = expr.tpe val fvs = (expr filter isFree map (_.symbol)).distinct - + reporter.reset() val className = compileExpr(expr, fvs) if (reporter.hasErrors) { throw new Error("reflective compilation has failed") } - + if (settings.debug.value) println("generated: "+className) val jclazz = jClass.forName(moduleFileName(className), true, classLoader) val jmeth = jclazz.getDeclaredMethods.find(_.getName == wrapperMethodName).get val jfield = jclazz.getDeclaredFields.find(_.getName == NameTransformer.MODULE_INSTANCE_NAME).get val singleton = jfield.get(null) - val result = jmeth.invoke(singleton, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*) - if (etpe.typeSymbol != FunctionClass(0)) result - else { - val applyMeth = result.getClass.getMethod("apply") - applyMeth.invoke(result) - } + // @odersky writes: Not sure we will be able to drop this. I forgot the reason why we dereference () functions, + // but there must have been one. So I propose to leave old version in comments to be resurrected if the problem resurfaces. +// val result = jmeth.invoke(singleton, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*) +// if (etpe.typeSymbol != FunctionClass(0)) result +// else { +// val applyMeth = result.getClass.getMethod("apply") +// applyMeth.invoke(result) +// } + jmeth.invoke(singleton, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*) } def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { @@ -131,7 +138,7 @@ trait ToolBoxes extends { self: Universe => try { settings.printtypes.value = printTypes settings.uniqid.value = printIds - settings.uniqid.value = printKinds + settings.Yshowsymkinds.value = printKinds tree.toString } finally { settings.printtypes.value = saved1 @@ -167,7 +174,7 @@ trait ToolBoxes extends { self: Universe => lazy val exporter = importer.reverse lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, defaultReflectiveClassLoader) - + private def importAndTypeCheck(tree: rm.Tree, expectedType: rm.Type): compiler.Tree = { // need to establish a run an phase because otherwise we run into an assertion in TypeHistory // that states that the period must be different from NoPeriod @@ -189,8 +196,8 @@ trait ToolBoxes extends { self: Universe => def typeCheck(tree: rm.Tree): rm.Tree = typeCheck(tree, WildcardType.asInstanceOf[rm.Type]) - def showAttributed(tree: rm.Tree): String = - compiler.showAttributed(importer.importTree(tree.asInstanceOf[Tree])) + 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) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index c80b07c44d..83b6252b26 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -42,8 +42,8 @@ trait Trees extends reflect.internal.Trees { self: Global => /** emitted by typer, eliminated by refchecks */ case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree - - /** Marks underlying reference to id as boxed. + + /** Marks underlying reference to id as boxed. * @pre: id must refer to a captured variable * A reference such marked will refer to the boxed entity, no dereferencing * with `.elem` is done on it. @@ -208,7 +208,7 @@ trait Trees extends reflect.internal.Trees { self: Global => case _ => this.treeCopy.SelectFromArray(tree, qualifier, selector, erasure) } def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match { - case t @ ReferenceToBoxed(idt0) + case t @ ReferenceToBoxed(idt0) if (idt0 == idt) => t case _ => this.treeCopy.ReferenceToBoxed(tree, idt) } @@ -251,62 +251,79 @@ trait Trees extends reflect.internal.Trees { self: Global => } } - /** resets symbol and tpe fields in a tree, @see ResetAttrsTraverse + /** resets symbol and tpe fields in a tree, @see ResetAttrs */ // def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x } // def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x } - - def resetAllAttrs[A<:Tree](x:A): A = new ResetAttrsTransformer(false).transformPoly(x) - def resetLocalAttrs[A<:Tree](x:A): A = new ResetAttrsTransformer(true).transformPoly(x) + + def resetAllAttrs[A<:Tree](x:A): A = new ResetAttrs(false).transform(x) + def resetLocalAttrs[A<:Tree](x:A): A = new ResetAttrs(true).transform(x) /** A transformer which resets symbol and tpe fields of all nodes in a given tree, * with special treatment of: * TypeTree nodes: are replaced by their original if it exists, otherwise tpe field is reset * to empty if it started out empty or refers to local symbols (which are erased). * TypeApply nodes: are deleted if type arguments end up reverted to empty - * This(pkg) notes where pkg is a pckage: these are kept. + * This(pkg) nodes where pkg is a package: these are kept. * - * (bq:) This traverser has mutable state and should be discarded after use + * (bq:) This transformer has mutable state and should be discarded after use */ - private class ResetAttrsTransformer(localOnly: Boolean) extends Transformer { - private val erasedSyms = util.HashSet[Symbol](8) - private def resetDef(tree: Tree) { - if (tree.symbol != null && tree.symbol != NoSymbol) - erasedSyms addEntry tree.symbol - tree.symbol = NoSymbol + private class ResetAttrs(localOnly: Boolean) { + val locals = util.HashSet[Symbol](8) + + class MarkLocals extends self.Traverser { + def markLocal(tree: Tree) = + if (tree.symbol != null && tree.symbol != NoSymbol) + locals addEntry tree.symbol + + override def traverse(tree: Tree) = { + tree match { + case _: DefTree | Function(_, _) | Template(_, _, _) => + markLocal(tree) + case _ if tree.symbol.isInstanceOf[FreeVar] => + markLocal(tree) + case _ => + ; + } + + super.traverse(tree) + } } - override def transform(tree: Tree): Tree = super.transform { - tree match { - case Template(_, _, body) => - body foreach resetDef - resetDef(tree) - tree.tpe = null - tree - case _: DefTree | Function(_, _) | Template(_, _, _) => - resetDef(tree) - tree.tpe = null - tree - case tpt: TypeTree => - if (tpt.original != null) - tpt.original - else if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => erasedSyms contains tp.typeSymbol)))) - tpt.tpe = null - tree - case TypeApply(fn, args) if args map transform exists (_.isEmpty) => - fn - case This(_) if tree.symbol != null && tree.symbol.isPackageClass => - tree - case EmptyTree => - tree - case _ => - if (tree.hasSymbol && (!localOnly || (erasedSyms contains tree.symbol))) - tree.symbol = NoSymbol - tree.tpe = null - tree + + class Transformer extends self.Transformer { + override def transform(tree: Tree): Tree = super.transform { + tree match { + case tpt: TypeTree => + if (tpt.original != null) { + transform(tpt.original) + } else { + if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => locals contains tp.typeSymbol)))) + tpt.tpe = null + tree + } + case TypeApply(fn, args) if args map transform exists (_.isEmpty) => + transform(fn) + case This(_) if tree.symbol != null && tree.symbol.isPackageClass => + tree + case EmptyTree => + tree + case _ => + if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol))) + tree.symbol = NoSymbol + tree.tpe = null + tree + } } } - def transformPoly[T <: Tree](x: T): T = { - val x1 = transform(x) + + 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) + + val x1 = new Transformer().transform(x) assert(x.getClass isInstance x1) x1.asInstanceOf[T] } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 107ffc35c6..d1ce460eb9 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -166,7 +166,9 @@ trait ScalaSettings extends AbsScalaSettings val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") - val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification actions.") + val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification.") + val Yreifytyperdebug + = BooleanSetting ("-Yreifytyper-debug", "Trace typings of reified trees.") 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/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index f1182fc2a9..197a52f011 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -55,10 +55,16 @@ abstract class LiftCode extends Transform with TypingTransformers { class Codifier(unit: CompilationUnit) extends TypingTransformer(unit) { val reifyDebug = settings.Yreifydebug.value + val reifyTyperDebug = settings.Yreifytyperdebug.value val debugTrace = util.trace when reifyDebug val reifyCopypaste = settings.Yreifycopypaste.value def printCopypaste(tree: Tree) { + if (reifyDebug) println("=======================") + printCopypaste1(tree) + if (reifyDebug) println("=======================") + } + def printCopypaste1(tree: Tree) { import scala.reflect.api.Modifier import scala.reflect.api.Modifier._ @@ -123,11 +129,14 @@ abstract class LiftCode extends Transform with TypingTransformers { case Apply(_, List(tree)) if sym == Code_lift => // reify Code.lift[T](expr) instances val saved = printTypings try { - printTypings = reifyDebug + debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) debugTrace("transformed = ") { - val result = localTyper.typedPos(tree.pos)(codify(super.transform(tree))) - if (reifyCopypaste) printCopypaste(result) - result + val untyped = codify(super.transform(tree)) + if (reifyCopypaste) printCopypaste(untyped) + + printTypings = reifyTyperDebug + val typed = localTyper.typedPos(tree.pos)(untyped) + typed } } catch { case ex: ReifierError => @@ -145,7 +154,8 @@ abstract class LiftCode extends Transform with TypingTransformers { val targetType = definitions.CodeClass.primaryConstructor.info.paramTypes.head val reifier = new Reifier() val arg = gen.mkAsInstanceOf(reifier.reifyTopLevel(tree), targetType, wrapInApply = false) - val treetpe = + val treetpe = // this really should use packedType(tree.tpe, context.owner) + // where packedType is defined in Typers. But we can do that only if liftCode is moved to Typers. if (tree.tpe.typeSymbol.isAnonymousClass) tree.tpe.typeSymbol.classBound else tree.tpe New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(treetpe.widen))), @@ -274,6 +284,14 @@ abstract class LiftCode extends Transform with TypingTransformers { 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 == EmptyPackageClass) + mirrorSelect("definitions.EmptyPackageClass") else if (sym.isModuleClass) Select(reifySymRef(sym.sourceModule), "moduleClass") else if (sym.isStatic && sym.isClass) @@ -300,7 +318,7 @@ abstract class LiftCode extends Transform with TypingTransformers { if (sym.isTerm) { if (reifyDebug) println("Free: " + sym) val symtpe = lambdaLift.boxIfCaptured(sym, sym.tpe, erasedTypes = false) - def markIfCaptured(arg: Ident): Tree = + def markIfCaptured(arg: Ident): Tree = if (sym.isCapturedVariable) referenceCapturedVariable(arg) else arg mirrorCall("freeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym))) } else { @@ -381,6 +399,14 @@ abstract class LiftCode extends Transform with TypingTransformers { } } + private def definedInLiftedCode(tpe: Type) = + tpe exists (tp => boundSyms contains tp.typeSymbol) + + private def isErased(tree: Tree) = tree match { + case tt: TypeTree => definedInLiftedCode(tt.tpe) && tt.original == null + case _ => false + } + /** Reify a tree */ private def reifyTree(tree: Tree): Tree = tree match { case EmptyTree => @@ -393,13 +419,21 @@ abstract class LiftCode extends Transform with TypingTransformers { mirrorCall("Select", reifyFree(tree), reifyName(nme.elem)) } else reifyFree(tree) case tt: TypeTree if (tt.tpe != null) => - if (!(boundSyms exists (tt.tpe contains _))) mirrorCall("TypeTree", reifyType(tt.tpe)) - else if (tt.original != null) reify(tt.original) - else mirrorCall(nme.TypeTree) + if (definedInLiftedCode(tt.tpe)) { + // erase non-essential (i.e. inferred) types + // reify symless counterparts of essential types + if (tt.original != null) reify(tt.original) else mirrorCall("TypeTree") + } else { + var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe)) + if (tt.original != null) { + val setOriginal = Select(rtt, newTermName("setOriginal")) + val reifiedOriginal = reify(tt.original) + rtt = Apply(setOriginal, List(reifiedOriginal)) + } + rtt + } case ta @ TypeApply(hk, ts) => - val thereAreOnlyTTs = ts collect { case t if !t.isInstanceOf[TypeTree] => t } isEmpty; - val ttsAreNotEssential = ts collect { case tt: TypeTree => tt } find { tt => tt.original != null } isEmpty; - if (thereAreOnlyTTs && ttsAreNotEssential) reifyTree(hk) else reifyProduct(ta) + if (ts exists isErased) reifyTree(hk) else reifyProduct(ta) case global.emptyValDef => mirrorSelect(nme.emptyValDef) case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) => @@ -407,8 +441,10 @@ abstract class LiftCode extends Transform with TypingTransformers { case Literal(constant @ Constant(sym: Symbol)) if boundSyms contains sym => CannotReifyClassOfBoundEnum(tree, constant.tpe) case _ => - if (tree.isDef) + if (tree.isDef) { + if (reifyDebug) println("boundSym: " + tree.symbol) boundSyms += tree.symbol + } reifyProduct(tree) /* diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d3ff331f98..4cf134d58b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2915,7 +2915,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { existentialAbstraction(captured.toList, tpe) } - /** convert skolems to existentials */ + /** convert local symbols and skolems to existentials */ def packedType(tree: Tree, owner: Symbol): Type = { def defines(tree: Tree, sym: Symbol) = sym.isExistentialSkolem && sym.unpackLocation == tree || diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala index 08071660a2..3526cf259d 100755 --- a/src/library/scala/reflect/api/StandardDefinitions.scala +++ b/src/library/scala/reflect/api/StandardDefinitions.scala @@ -12,7 +12,7 @@ trait StandardDefinitions { self: Universe => abstract class AbsDefinitions { // outer packages and their classes - def RootPackage: Symbol + def RootPackage: Symbol // under consideration def RootClass: Symbol def EmptyPackage: Symbol def EmptyPackageClass: Symbol @@ -46,6 +46,11 @@ trait StandardDefinitions { self: Universe => def StringClass : Symbol def ClassClass : Symbol + // product, tuple, function + def TupleClass : Array[Symbol] + def ProductClass : Array[Symbol] + def FunctionClass : Array[Symbol] + // fundamental modules def PredefModule: Symbol diff --git a/src/partest/scala/tools/partest/utils/CodeTest.scala b/src/partest/scala/tools/partest/utils/CodeTest.scala index c90168a313..c236d89bbd 100644 --- a/src/partest/scala/tools/partest/utils/CodeTest.scala +++ b/src/partest/scala/tools/partest/utils/CodeTest.scala @@ -24,11 +24,17 @@ object CodeTest { def apply[T](code: Code[T], args: Array[String] = Array()) = { println("testing: "+code.tree) + println("type is: "+code.manifest.tpe) + val isNullary = code.manifest.tpe.typeSymbol == scala.reflect.mirror.definitions.FunctionClass(0) val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter, args mkString " ") val ttree = toolbox.typeCheck(code.tree, code.manifest.tpe) - println("result = " + toolbox.showAttributed(ttree)) - val evaluated = toolbox.runExpr(ttree) + println("result = " + toolbox.showAttributed(ttree, printTypes = true, printIds = false)) + var evaluated = toolbox.runExpr(ttree) + if (evaluated != null && isNullary) { + val applyMeth = evaluated.getClass.getMethod("apply") + evaluated = applyMeth.invoke(evaluated) + } println("evaluated = "+evaluated) evaluated } diff --git a/test/files/run/code.check b/test/files/run/code.check index b946554fda..9b0351bbf9 100644 --- a/test/files/run/code.check +++ b/test/files/run/code.check @@ -1,29 +1,36 @@ testing: ((x: Int) => x.$plus(ys.length)) +type is: Int => Int result = ((x: Int) => x.+{(x: )Int}(ys.length{Int}){Int}){Int => Int} evaluated = testing: (() => { val e: Element = new Element("someName"); e }) +type is: () => Element result = (() => { val e: Element = new Element{Element}{(name: )Element}("someName"{String("someName")}){Element}; e{Element} }{Element}){() => Element} evaluated = Element(someName) testing: (() => truc.elem = 6) +type is: () => Unit result = (() => truc.elem{Int} = 6{Int(6)}{Unit}){() => Unit} evaluated = null testing: (() => truc.elem = truc.elem.$plus(6)) +type is: () => Unit result = (() => truc.elem{Int} = truc.elem.+{(x: )Int}(6{Int(6)}){Int}{Unit}){() => Unit} evaluated = null testing: (() => new baz.BazElement("someName")) +type is: () => baz.BazElement result = (() => new baz.BazElement{baz.BazElement}{(name: )baz.BazElement}("someName"{String("someName")}){baz.BazElement}){() => baz.BazElement} evaluated = BazElement(someName) testing: ((x: Int) => x.$plus(ys.length)) +type is: Int => Int result = ((x: Int) => x.+{(x: )Int}(ys.length{Int}){Int}){Int => Int} evaluated = static: 2 testing: (() => x.$plus(1)) +type is: () => Int result = (() => x.+{(x: )Int}(1{Int(1)}){Int}){() => Int} evaluated = 2 1+1 = 2 diff --git a/test/files/run/reify_complex.check b/test/files/run/reify_complex.check new file mode 100644 index 0000000000..7df35e33a0 --- /dev/null +++ b/test/files/run/reify_complex.check @@ -0,0 +1 @@ +3.0+4.0*i diff --git a/test/files/run/reify_complex.scala b/test/files/run/reify_complex.scala new file mode 100644 index 0000000000..aae4d558cf --- /dev/null +++ b/test/files/run/reify_complex.scala @@ -0,0 +1,31 @@ +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 Complex(val re: Double, val im: Double) { + def + (that: Complex) = + new Complex(re + that.re, im + that.im) + def - (that: Complex) = + new Complex(re - that.re, im - that.im) + def * (that: Complex) = + new Complex(re * that.re - im * that.im, + re * that.im + im * that.re) + def / (that: Complex) = { + val denom = that.re * that.re + that.im * that.im + new Complex((re * that.re + im * that.im) / denom, + (im * that.re - re * that.im) / denom) + } + override def toString = + re + (if (im < 0) "-" + (-im) else "+" + im) + "*i" + } + val x = new Complex(2, 1); val y = new Complex(1, 3) + println(x + 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/files/run/reify_extendbuiltins.check b/test/files/run/reify_extendbuiltins.check new file mode 100644 index 0000000000..a48033a30d --- /dev/null +++ b/test/files/run/reify_extendbuiltins.check @@ -0,0 +1 @@ +10! = 3628800 diff --git a/test/files/run/reify_extendbuiltins.scala b/test/files/run/reify_extendbuiltins.scala new file mode 100644 index 0000000000..57acd699ff --- /dev/null +++ b/test/files/run/reify_extendbuiltins.scala @@ -0,0 +1,21 @@ +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{ + def fact(n: Int): BigInt = + if (n == 0) 1 else fact(n-1) * n + class Factorizer(n: Int) { + def ! = fact(n) + } + implicit def int2fact(n: Int) = new Factorizer(n) + + println("10! = " + (10!)) + }; + + 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_generic2.check b/test/files/run/reify_generic2.check new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/test/files/run/reify_generic2.check @@ -0,0 +1 @@ +4 diff --git a/test/files/run/reify_generic2.scala b/test/files/run/reify_generic2.scala new file mode 100644 index 0000000000..d03fe7602b --- /dev/null +++ b/test/files/run/reify_generic2.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 + val product = List(new C, new C).length * List[C](new C, new C).length + println(product) + }; + + 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_getter.check b/test/files/run/reify_getter.check new file mode 100644 index 0000000000..5ef4ff4d04 --- /dev/null +++ b/test/files/run/reify_getter.check @@ -0,0 +1 @@ +evaluated = 2 diff --git a/test/files/run/reify_getter.scala b/test/files/run/reify_getter.scala new file mode 100644 index 0000000000..83eaded506 --- /dev/null +++ b/test/files/run/reify_getter.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 { + val x = 2 + } + + new 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/reify_sort1.check b/test/files/run/reify_sort1.check new file mode 100644 index 0000000000..0d30805141 --- /dev/null +++ b/test/files/run/reify_sort1.check @@ -0,0 +1,2 @@ +List(6, 2, 8, 5, 1) +List(1, 2, 5, 6, 8) diff --git a/test/files/run/reify_sort1.scala b/test/files/run/reify_sort1.scala new file mode 100644 index 0000000000..42f4c824a5 --- /dev/null +++ b/test/files/run/reify_sort1.scala @@ -0,0 +1,27 @@ +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{ + def sort(a: List[Int]): List[Int] = { + if (a.length < 2) + a + else { + val pivot = a(a.length / 2) + sort(a.filter(_ < pivot)) ::: + a.filter(_ == pivot) ::: + sort(a.filter(_ > pivot)) + } + } + + val xs = List(6, 2, 8, 5, 1) + println(xs) + println(sort(xs)) + }; + + 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/t5269.check b/test/files/run/t5269.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/files/run/t5269.check @@ -0,0 +1 @@ +2 diff --git a/test/files/run/t5269.scala b/test/files/run/t5269.scala new file mode 100644 index 0000000000..a30509f3fe --- /dev/null +++ b/test/files/run/t5269.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{ + trait Z { + val z = 2 + } + + class X extends 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/files/run/t5274_1.check b/test/files/run/t5274_1.check new file mode 100644 index 0000000000..fca8bc3d3e --- /dev/null +++ b/test/files/run/t5274_1.check @@ -0,0 +1,3 @@ +50! = 30414093201713378043612608166064768844377641568960512000000000000 +49! = 608281864034267560872252163321295376887552831379210240000000000 +50!/49! = 50 diff --git a/test/files/run/t5274_1.scala b/test/files/run/t5274_1.scala new file mode 100644 index 0000000000..c501172518 --- /dev/null +++ b/test/files/run/t5274_1.scala @@ -0,0 +1,20 @@ +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{ + def factorial(n: BigInt): BigInt = + if (n == 0) 1 else n * factorial(n-1) + + val f50 = factorial(50); val f49 = factorial(49) + println("50! = " + f50) + println("49! = " + f49) + println("50!/49! = " + (f50 / f49)) + }; + + 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/t5275.check b/test/files/run/t5275.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/files/run/t5275.check @@ -0,0 +1 @@ +2 diff --git a/test/files/run/t5275.scala b/test/files/run/t5275.scala new file mode 100644 index 0000000000..d419834ded --- /dev/null +++ b/test/files/run/t5275.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{ + class C(val foo: Int) + println(new C(2).foo) + }; + + 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/t5277_1.check b/test/files/run/t5277_1.check new file mode 100644 index 0000000000..a48033a30d --- /dev/null +++ b/test/files/run/t5277_1.check @@ -0,0 +1 @@ +10! = 3628800 diff --git a/test/files/run/t5277_1.scala b/test/files/run/t5277_1.scala new file mode 100644 index 0000000000..57acd699ff --- /dev/null +++ b/test/files/run/t5277_1.scala @@ -0,0 +1,21 @@ +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{ + def fact(n: Int): BigInt = + if (n == 0) 1 else fact(n-1) * n + class Factorizer(n: Int) { + def ! = fact(n) + } + implicit def int2fact(n: Int) = new Factorizer(n) + + println("10! = " + (10!)) + }; + + 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/t5277_2.check b/test/files/run/t5277_2.check new file mode 100644 index 0000000000..ca017e2a40 --- /dev/null +++ b/test/files/run/t5277_2.check @@ -0,0 +1,2 @@ +2() +1() diff --git a/test/files/run/t5277_2.scala b/test/files/run/t5277_2.scala new file mode 100644 index 0000000000..67b6b000bc --- /dev/null +++ b/test/files/run/t5277_2.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{ + def p(implicit i: Int) = print(i) + implicit val v = 2 + + println(p) + println(p(1)) + }; + + 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/t5335.check b/test/files/run/t5335.check new file mode 100644 index 0000000000..0cfbf08886 --- /dev/null +++ b/test/files/run/t5335.check @@ -0,0 +1 @@ +2 diff --git a/test/files/run/t5335.scala b/test/files/run/t5335.scala new file mode 100644 index 0000000000..9a8b91f04d --- /dev/null +++ b/test/files/run/t5335.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{ + println(new {def x = 2}.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/reify_closure6.check b/test/pending/run/reify_closure6.check index 3526d04b0e..e521ea874d 100644 --- a/test/pending/run/reify_closure6.check +++ b/test/pending/run/reify_closure6.check @@ -1,3 +1,7 @@ +q = 1 +y = 1 first invocation = 15 -second invocation = 18 +q = 2 +y = 1 +second invocation = 17 q after second invocation = 2 diff --git a/test/pending/run/reify_closure6.scala b/test/pending/run/reify_closure6.scala index 909071aa44..43ddfde28d 100644 --- a/test/pending/run/reify_closure6.scala +++ b/test/pending/run/reify_closure6.scala @@ -10,6 +10,8 @@ object Test extends App { val fun: reflect.Code[Int => Int] = x => { y += 1 q += 1 + println("q = " + q) + println("y = " + y) x + ys.length * z + q + y } diff --git a/test/pending/run/reify_closure7.check b/test/pending/run/reify_closure7.check new file mode 100644 index 0000000000..bf58b52bce --- /dev/null +++ b/test/pending/run/reify_closure7.check @@ -0,0 +1,6 @@ +q = 1 +y = 1 +first invocation = 15 +q = 2 +y = 2 +second invocation = 17 diff --git a/test/pending/run/reify_closure7.scala b/test/pending/run/reify_closure7.scala new file mode 100644 index 0000000000..8933df23fa --- /dev/null +++ b/test/pending/run/reify_closure7.scala @@ -0,0 +1,32 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + var q = 0 + var clo: Int => Int = null + def foo[T](ys: List[T]): Int => Int = { + val z = 1 + var y = 0 + val fun: reflect.Code[Int => Int] = x => { + y += 1 + q += 1 + println("q = " + q) + println("y = " + y) + x + ys.length * z + q + y + } + + 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) + clo = dyn.asInstanceOf[Int => Int] + } + + clo + } + + println("first invocation = " + foo(List(1, 2, 3))(10)) + println("second invocation = " + foo(List(1, 2, 3, 4))(10)) +} diff --git a/test/pending/run/reify_closure8a.check b/test/pending/run/reify_closure8a.check new file mode 100644 index 0000000000..9a037142aa --- /dev/null +++ b/test/pending/run/reify_closure8a.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/test/pending/run/reify_closure8a.scala b/test/pending/run/reify_closure8a.scala new file mode 100644 index 0000000000..5e54bfc8c7 --- /dev/null +++ b/test/pending/run/reify_closure8a.scala @@ -0,0 +1,17 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + class Foo(val y: Int) { + def fun = lift{y} + } + + 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 foo = dyn.asInstanceOf[Int] + println(foo) +} diff --git a/test/pending/run/reify_closure8b.check b/test/pending/run/reify_closure8b.check new file mode 100644 index 0000000000..9a037142aa --- /dev/null +++ b/test/pending/run/reify_closure8b.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/test/pending/run/reify_closure8b.scala b/test/pending/run/reify_closure8b.scala new file mode 100644 index 0000000000..9e37e4e09a --- /dev/null +++ b/test/pending/run/reify_closure8b.scala @@ -0,0 +1,17 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + class Foo(y: Int) { + def fun = lift{y} + } + + 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 foo = dyn.asInstanceOf[Int] + println(foo) +} diff --git a/test/pending/run/reify_closure9a.check b/test/pending/run/reify_closure9a.check new file mode 100644 index 0000000000..9a037142aa --- /dev/null +++ b/test/pending/run/reify_closure9a.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/test/pending/run/reify_closure9a.scala b/test/pending/run/reify_closure9a.scala new file mode 100644 index 0000000000..f3ee153d3c --- /dev/null +++ b/test/pending/run/reify_closure9a.scala @@ -0,0 +1,20 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo(y: Int) = { + class Foo(val y: Int) { + def fun = lift{y} + } + + 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) + dyn.asInstanceOf[Int] + } + + println(foo(10)) +} diff --git a/test/pending/run/reify_closure9b.check b/test/pending/run/reify_closure9b.check new file mode 100644 index 0000000000..9a037142aa --- /dev/null +++ b/test/pending/run/reify_closure9b.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/test/pending/run/reify_closure9b.scala b/test/pending/run/reify_closure9b.scala new file mode 100644 index 0000000000..8d349e8701 --- /dev/null +++ b/test/pending/run/reify_closure9b.scala @@ -0,0 +1,20 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo(y: Int) = { + class Foo(y: Int) { + def fun = lift{y} + } + + 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) + dyn.asInstanceOf[Int] + } + + println(foo(10)) +} diff --git a/test/pending/run/reify_closures10.check b/test/pending/run/reify_closures10.check new file mode 100644 index 0000000000..fd3c81a4d7 --- /dev/null +++ b/test/pending/run/reify_closures10.check @@ -0,0 +1,2 @@ +5 +5 diff --git a/test/pending/run/reify_closures10.scala b/test/pending/run/reify_closures10.scala new file mode 100644 index 0000000000..d0f895ae4d --- /dev/null +++ b/test/pending/run/reify_closures10.scala @@ -0,0 +1,15 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val x = 2 + val y = 3 + val code = lift{println(x + y); x + y} + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + println(toolbox.runExpr(ttree)) +} diff --git a/test/pending/run/reify_closures11.check b/test/pending/run/reify_closures11.check new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/test/pending/run/reify_closures11.check @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/test/pending/run/reify_closures11.scala b/test/pending/run/reify_closures11.scala new file mode 100644 index 0000000000..42053bd029 --- /dev/null +++ b/test/pending/run/reify_closures11.scala @@ -0,0 +1,18 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def fun() = { + def z() = 2 + lift{z} + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun().tree) + val dyn = toolbox.runExpr(ttree) + val foo = dyn.asInstanceOf[Int] + println(foo) +} diff --git a/test/pending/run/reify_complex.check b/test/pending/run/reify_complex.check deleted file mode 100644 index 7df35e33a0..0000000000 --- a/test/pending/run/reify_complex.check +++ /dev/null @@ -1 +0,0 @@ -3.0+4.0*i diff --git a/test/pending/run/reify_complex.scala b/test/pending/run/reify_complex.scala deleted file mode 100644 index aae4d558cf..0000000000 --- a/test/pending/run/reify_complex.scala +++ /dev/null @@ -1,31 +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 Complex(val re: Double, val im: Double) { - def + (that: Complex) = - new Complex(re + that.re, im + that.im) - def - (that: Complex) = - new Complex(re - that.re, im - that.im) - def * (that: Complex) = - new Complex(re * that.re - im * that.im, - re * that.im + im * that.re) - def / (that: Complex) = { - val denom = that.re * that.re + that.im * that.im - new Complex((re * that.re + im * that.im) / denom, - (im * that.re - re * that.im) / denom) - } - override def toString = - re + (if (im < 0) "-" + (-im) else "+" + im) + "*i" - } - val x = new Complex(2, 1); val y = new Complex(1, 3) - println(x + 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/reify_extendbuiltins.check b/test/pending/run/reify_extendbuiltins.check deleted file mode 100644 index a48033a30d..0000000000 --- a/test/pending/run/reify_extendbuiltins.check +++ /dev/null @@ -1 +0,0 @@ -10! = 3628800 diff --git a/test/pending/run/reify_extendbuiltins.scala b/test/pending/run/reify_extendbuiltins.scala deleted file mode 100644 index 57acd699ff..0000000000 --- a/test/pending/run/reify_extendbuiltins.scala +++ /dev/null @@ -1,21 +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{ - def fact(n: Int): BigInt = - if (n == 0) 1 else fact(n-1) * n - class Factorizer(n: Int) { - def ! = fact(n) - } - implicit def int2fact(n: Int) = new Factorizer(n) - - println("10! = " + (10!)) - }; - - 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_sort1.check b/test/pending/run/reify_sort1.check deleted file mode 100644 index 0d30805141..0000000000 --- a/test/pending/run/reify_sort1.check +++ /dev/null @@ -1,2 +0,0 @@ -List(6, 2, 8, 5, 1) -List(1, 2, 5, 6, 8) diff --git a/test/pending/run/reify_sort1.scala b/test/pending/run/reify_sort1.scala deleted file mode 100644 index 42f4c824a5..0000000000 --- a/test/pending/run/reify_sort1.scala +++ /dev/null @@ -1,27 +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{ - def sort(a: List[Int]): List[Int] = { - if (a.length < 2) - a - else { - val pivot = a(a.length / 2) - sort(a.filter(_ < pivot)) ::: - a.filter(_ == pivot) ::: - sort(a.filter(_ > pivot)) - } - } - - val xs = List(6, 2, 8, 5, 1) - println(xs) - println(sort(xs)) - }; - - 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_this.check b/test/pending/run/reify_this.check new file mode 100644 index 0000000000..af3d0652a9 --- /dev/null +++ b/test/pending/run/reify_this.check @@ -0,0 +1,5 @@ +foo +false +2 +bar +2 \ No newline at end of file diff --git a/test/pending/run/reify_this.scala b/test/pending/run/reify_this.scala new file mode 100644 index 0000000000..38ef72b6eb --- /dev/null +++ b/test/pending/run/reify_this.scala @@ -0,0 +1,31 @@ +import scala.reflect._ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +trait Eval { + def eval(code: Code[_]): Any = eval(code.tree) + + def eval(tree: Tree): Any = { + val settings = new Settings + val reporter = new ConsoleReporter(settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + toolbox.runExpr(ttree) + } +} + +object Test extends App with Eval { + // select a value from package + eval(lift{println("foo")}) + eval(lift{println((new Object).toString == (new Object).toString)}) + + // select a type from package + eval(lift{val x: Any = 2; println(x)}) + eval(lift{val x: Object = "bar"; println(x)}) + + // select a value from module + val x = 2 + eval(lift{println(x)}) +} diff --git a/test/pending/run/t5269.check b/test/pending/run/t5269.check deleted file mode 100644 index 0cfbf08886..0000000000 --- a/test/pending/run/t5269.check +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/test/pending/run/t5269.scala b/test/pending/run/t5269.scala deleted file mode 100644 index a30509f3fe..0000000000 --- a/test/pending/run/t5269.scala +++ /dev/null @@ -1,22 +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{ - trait Z { - val z = 2 - } - - class X extends 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/t5274_1.check b/test/pending/run/t5274_1.check deleted file mode 100644 index fca8bc3d3e..0000000000 --- a/test/pending/run/t5274_1.check +++ /dev/null @@ -1,3 +0,0 @@ -50! = 30414093201713378043612608166064768844377641568960512000000000000 -49! = 608281864034267560872252163321295376887552831379210240000000000 -50!/49! = 50 diff --git a/test/pending/run/t5274_1.scala b/test/pending/run/t5274_1.scala deleted file mode 100644 index c501172518..0000000000 --- a/test/pending/run/t5274_1.scala +++ /dev/null @@ -1,20 +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{ - def factorial(n: BigInt): BigInt = - if (n == 0) 1 else n * factorial(n-1) - - val f50 = factorial(50); val f49 = factorial(49) - println("50! = " + f50) - println("49! = " + f49) - println("50!/49! = " + (f50 / f49)) - }; - - 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/t5275.check b/test/pending/run/t5275.check deleted file mode 100644 index 0cfbf08886..0000000000 --- a/test/pending/run/t5275.check +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/test/pending/run/t5275.scala b/test/pending/run/t5275.scala deleted file mode 100644 index d419834ded..0000000000 --- a/test/pending/run/t5275.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(val foo: Int) - println(new C(2).foo) - }; - - 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/t5277_1.check b/test/pending/run/t5277_1.check deleted file mode 100644 index a48033a30d..0000000000 --- a/test/pending/run/t5277_1.check +++ /dev/null @@ -1 +0,0 @@ -10! = 3628800 diff --git a/test/pending/run/t5277_1.scala b/test/pending/run/t5277_1.scala deleted file mode 100644 index 57acd699ff..0000000000 --- a/test/pending/run/t5277_1.scala +++ /dev/null @@ -1,21 +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{ - def fact(n: Int): BigInt = - if (n == 0) 1 else fact(n-1) * n - class Factorizer(n: Int) { - def ! = fact(n) - } - implicit def int2fact(n: Int) = new Factorizer(n) - - println("10! = " + (10!)) - }; - - 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/t5277_2.check b/test/pending/run/t5277_2.check deleted file mode 100644 index 5f1d0ecea5..0000000000 --- a/test/pending/run/t5277_2.check +++ /dev/null @@ -1,2 +0,0 @@ -2 -1 diff --git a/test/pending/run/t5277_2.scala b/test/pending/run/t5277_2.scala deleted file mode 100644 index 67b6b000bc..0000000000 --- a/test/pending/run/t5277_2.scala +++ /dev/null @@ -1,18 +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{ - def p(implicit i: Int) = print(i) - implicit val v = 2 - - println(p) - println(p(1)) - }; - - 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/t5415.check b/test/pending/run/t5415.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/pending/run/t5415.scala b/test/pending/run/t5415.scala new file mode 100644 index 0000000000..3db356da86 --- /dev/null +++ b/test/pending/run/t5415.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import scala.reflect.runtime.Mirror.ToolBox + +object Test extends App{ + case class Queryable2[T]() { def filter(predicate: T => Boolean) = ??? } + trait CoffeesTable{ def sales : Int } + val q = Queryable2[CoffeesTable]() + val code = scala.reflect.Code.lift{q.filter(_.sales > 5)} + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) +} -- cgit v1.2.3 From 363f8af6a8c157485a644d00d75e2df10e71e661 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Thu, 2 Feb 2012 15:29:55 +0100 Subject: Fixes reifyThis --- src/compiler/scala/reflect/internal/StdNames.scala | 1 + src/compiler/scala/reflect/internal/Trees.scala | 2 - .../scala/tools/nsc/transform/LiftCode.scala | 15 +++++- src/library/scala/reflect/api/Trees.scala | 3 ++ test/files/run/reify_closure1.check | 2 + test/files/run/reify_closure1.scala | 20 ++++++++ test/files/run/reify_closure2a.check | 2 + test/files/run/reify_closure2a.scala | 20 ++++++++ test/files/run/reify_closure3a.check | 2 + test/files/run/reify_closure3a.scala | 22 +++++++++ test/files/run/reify_closure4a.check | 2 + test/files/run/reify_closure4a.scala | 22 +++++++++ test/files/run/reify_closure5a.check | 2 + test/files/run/reify_closure5a.scala | 20 ++++++++ test/files/run/reify_closure6.check | 7 +++ test/files/run/reify_closure6.scala | 28 +++++++++++ test/files/run/reify_closure7.check | 6 +++ test/files/run/reify_closure7.scala | 32 ++++++++++++ test/files/run/reify_closure8a.check | 1 + test/files/run/reify_closure8a.scala | 17 +++++++ test/files/run/reify_closures10.check | 2 + test/files/run/reify_closures10.scala | 15 ++++++ test/files/run/reify_implicits.check | 1 + test/files/run/reify_implicits.scala | 21 ++++++++ test/files/run/reify_sort.check | 2 + test/files/run/reify_sort.scala | 57 ++++++++++++++++++++++ test/files/run/reify_this.check | 5 ++ test/files/run/reify_this.scala | 31 ++++++++++++ test/files/run/t5274_2.check | 2 + test/files/run/t5274_2.scala | 57 ++++++++++++++++++++++ test/files/run/t5279.check | 1 + test/files/run/t5279.scala | 14 ++++++ test/files/run/t5415.check | 0 test/files/run/t5415.scala | 14 ++++++ test/pending/run/reify_closure1.check | 2 - test/pending/run/reify_closure1.scala | 20 -------- test/pending/run/reify_closure2a.check | 2 - test/pending/run/reify_closure2a.scala | 20 -------- test/pending/run/reify_closure3a.check | 2 - test/pending/run/reify_closure3a.scala | 22 --------- test/pending/run/reify_closure4a.check | 2 - test/pending/run/reify_closure4a.scala | 22 --------- test/pending/run/reify_closure5a.check | 2 - test/pending/run/reify_closure5a.scala | 20 -------- test/pending/run/reify_closure6.check | 7 --- test/pending/run/reify_closure6.scala | 28 ----------- test/pending/run/reify_closure7.check | 6 --- test/pending/run/reify_closure7.scala | 32 ------------ test/pending/run/reify_closure8a.check | 1 - test/pending/run/reify_closure8a.scala | 17 ------- test/pending/run/reify_closures10.check | 2 - test/pending/run/reify_closures10.scala | 15 ------ test/pending/run/reify_implicits.check | 1 - test/pending/run/reify_implicits.scala | 21 -------- test/pending/run/reify_sort.check | 2 - test/pending/run/reify_sort.scala | 57 ---------------------- test/pending/run/reify_this.check | 5 -- test/pending/run/reify_this.scala | 31 ------------ test/pending/run/t5274_2.check | 2 - test/pending/run/t5274_2.scala | 57 ---------------------- test/pending/run/t5279.check | 1 - test/pending/run/t5279.scala | 14 ------ test/pending/run/t5415.check | 0 test/pending/run/t5415.scala | 14 ------ 64 files changed, 444 insertions(+), 431 deletions(-) create mode 100644 test/files/run/reify_closure1.check create mode 100644 test/files/run/reify_closure1.scala create mode 100644 test/files/run/reify_closure2a.check create mode 100644 test/files/run/reify_closure2a.scala create mode 100644 test/files/run/reify_closure3a.check create mode 100644 test/files/run/reify_closure3a.scala create mode 100644 test/files/run/reify_closure4a.check create mode 100644 test/files/run/reify_closure4a.scala create mode 100644 test/files/run/reify_closure5a.check create mode 100644 test/files/run/reify_closure5a.scala create mode 100644 test/files/run/reify_closure6.check create mode 100644 test/files/run/reify_closure6.scala create mode 100644 test/files/run/reify_closure7.check create mode 100644 test/files/run/reify_closure7.scala create mode 100644 test/files/run/reify_closure8a.check create mode 100644 test/files/run/reify_closure8a.scala create mode 100644 test/files/run/reify_closures10.check create mode 100644 test/files/run/reify_closures10.scala create mode 100644 test/files/run/reify_implicits.check create mode 100644 test/files/run/reify_implicits.scala create mode 100644 test/files/run/reify_sort.check create mode 100644 test/files/run/reify_sort.scala create mode 100644 test/files/run/reify_this.check create mode 100644 test/files/run/reify_this.scala create mode 100644 test/files/run/t5274_2.check create mode 100644 test/files/run/t5274_2.scala create mode 100644 test/files/run/t5279.check create mode 100644 test/files/run/t5279.scala create mode 100644 test/files/run/t5415.check create mode 100644 test/files/run/t5415.scala delete mode 100644 test/pending/run/reify_closure1.check delete mode 100644 test/pending/run/reify_closure1.scala delete mode 100644 test/pending/run/reify_closure2a.check delete mode 100644 test/pending/run/reify_closure2a.scala delete mode 100644 test/pending/run/reify_closure3a.check delete mode 100644 test/pending/run/reify_closure3a.scala delete mode 100644 test/pending/run/reify_closure4a.check delete mode 100644 test/pending/run/reify_closure4a.scala delete mode 100644 test/pending/run/reify_closure5a.check delete mode 100644 test/pending/run/reify_closure5a.scala delete mode 100644 test/pending/run/reify_closure6.check delete mode 100644 test/pending/run/reify_closure6.scala delete mode 100644 test/pending/run/reify_closure7.check delete mode 100644 test/pending/run/reify_closure7.scala delete mode 100644 test/pending/run/reify_closure8a.check delete mode 100644 test/pending/run/reify_closure8a.scala delete mode 100644 test/pending/run/reify_closures10.check delete mode 100644 test/pending/run/reify_closures10.scala delete mode 100644 test/pending/run/reify_implicits.check delete mode 100644 test/pending/run/reify_implicits.scala delete mode 100644 test/pending/run/reify_sort.check delete mode 100644 test/pending/run/reify_sort.scala delete mode 100644 test/pending/run/reify_this.check delete mode 100644 test/pending/run/reify_this.scala delete mode 100644 test/pending/run/t5274_2.check delete mode 100644 test/pending/run/t5274_2.scala delete mode 100644 test/pending/run/t5279.check delete mode 100644 test/pending/run/t5279.scala delete mode 100644 test/pending/run/t5415.check delete mode 100644 test/pending/run/t5415.scala (limited to 'test/pending') diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index b3069adfb4..b1a24c0be2 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -271,6 +271,7 @@ trait StdNames extends NameManglers { self: SymbolTable => // Compiler utilized names // val productElementName: NameType = "productElementName" val Ident: NameType = "Ident" + val This: NameType = "This" val StringContext: NameType = "StringContext" val TYPE_ : NameType = "TYPE" val TypeTree: NameType = "TypeTree" diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 5bb0c98bfb..ca7801ac9d 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -251,8 +251,6 @@ trait Trees extends api.Trees { self: SymbolTable => def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix) - def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym - /** Block factory that flattens directly nested blocks. */ def Block(stats: Tree*): Block = { diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index 197a52f011..d0ed92f8ba 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -460,8 +460,19 @@ abstract class LiftCode extends Transform with TypingTransformers { * 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 = - mirrorCall(nme.Ident, reifySymRef(tree.symbol)) + 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("freeVar", 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 = diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 03b043c188..0a38fb45bf 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -537,6 +537,9 @@ trait Trees { self: Universe => // The symbol of a This is the class to which the this refers. // For instance in C.this, it would be C. + def This(sym: Symbol): Tree = + This(sym.name.toTypeName) setSymbol sym + /** Designator . */ case class Select(qualifier: Tree, name: Name) extends RefTree diff --git a/test/files/run/reify_closure1.check b/test/files/run/reify_closure1.check new file mode 100644 index 0000000000..b2f7f08c17 --- /dev/null +++ b/test/files/run/reify_closure1.check @@ -0,0 +1,2 @@ +10 +10 diff --git a/test/files/run/reify_closure1.scala b/test/files/run/reify_closure1.scala new file mode 100644 index 0000000000..825a38dc1d --- /dev/null +++ b/test/files/run/reify_closure1.scala @@ -0,0 +1,20 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo[T](ys: List[T]): Int => Int = { + val fun: reflect.Code[Int => Int] = x => { + x + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println(foo(List(1, 2, 3))(10)) + println(foo(List(1, 2, 3, 4))(10)) +} diff --git a/test/files/run/reify_closure2a.check b/test/files/run/reify_closure2a.check new file mode 100644 index 0000000000..c1f3abd7e6 --- /dev/null +++ b/test/files/run/reify_closure2a.check @@ -0,0 +1,2 @@ +11 +12 diff --git a/test/files/run/reify_closure2a.scala b/test/files/run/reify_closure2a.scala new file mode 100644 index 0000000000..b88bec005d --- /dev/null +++ b/test/files/run/reify_closure2a.scala @@ -0,0 +1,20 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo(y: Int): Int => Int = { + val fun: reflect.Code[Int => Int] = x => { + x + y + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println(foo(1)(10)) + println(foo(2)(10)) +} diff --git a/test/files/run/reify_closure3a.check b/test/files/run/reify_closure3a.check new file mode 100644 index 0000000000..c1f3abd7e6 --- /dev/null +++ b/test/files/run/reify_closure3a.check @@ -0,0 +1,2 @@ +11 +12 diff --git a/test/files/run/reify_closure3a.scala b/test/files/run/reify_closure3a.scala new file mode 100644 index 0000000000..6414fa58a3 --- /dev/null +++ b/test/files/run/reify_closure3a.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo(y: Int): Int => Int = { + def y1 = y + + val fun: reflect.Code[Int => Int] = x => { + x + y1 + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println(foo(1)(10)) + println(foo(2)(10)) +} diff --git a/test/files/run/reify_closure4a.check b/test/files/run/reify_closure4a.check new file mode 100644 index 0000000000..c1f3abd7e6 --- /dev/null +++ b/test/files/run/reify_closure4a.check @@ -0,0 +1,2 @@ +11 +12 diff --git a/test/files/run/reify_closure4a.scala b/test/files/run/reify_closure4a.scala new file mode 100644 index 0000000000..99e9d82706 --- /dev/null +++ b/test/files/run/reify_closure4a.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo(y: Int): Int => Int = { + val y1 = y + + val fun: reflect.Code[Int => Int] = x => { + x + y1 + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println(foo(1)(10)) + println(foo(2)(10)) +} diff --git a/test/files/run/reify_closure5a.check b/test/files/run/reify_closure5a.check new file mode 100644 index 0000000000..df9e19c591 --- /dev/null +++ b/test/files/run/reify_closure5a.check @@ -0,0 +1,2 @@ +13 +14 diff --git a/test/files/run/reify_closure5a.scala b/test/files/run/reify_closure5a.scala new file mode 100644 index 0000000000..0ac53d5479 --- /dev/null +++ b/test/files/run/reify_closure5a.scala @@ -0,0 +1,20 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + def foo[T](ys: List[T]): Int => Int = { + val fun: reflect.Code[Int => Int] = x => { + x + ys.length + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println(foo(List(1, 2, 3))(10)) + println(foo(List(1, 2, 3, 4))(10)) +} diff --git a/test/files/run/reify_closure6.check b/test/files/run/reify_closure6.check new file mode 100644 index 0000000000..b9de4c6baf --- /dev/null +++ b/test/files/run/reify_closure6.check @@ -0,0 +1,7 @@ +q = 1 +y = 1 +first invocation = 15 +q = 2 +y = 1 +second invocation = 17 +q after second invocation = 2 \ No newline at end of file diff --git a/test/files/run/reify_closure6.scala b/test/files/run/reify_closure6.scala new file mode 100644 index 0000000000..54f1791bf2 --- /dev/null +++ b/test/files/run/reify_closure6.scala @@ -0,0 +1,28 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + var q = 0 + def foo[T](ys: List[T]): Int => Int = { + val z = 1 + var y = 0 + val fun: reflect.Code[Int => Int] = x => { + y += 1 + q += 1 + println("q = " + q) + println("y = " + y) + x + ys.length * z + q + y + } + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(fun.tree) + val dyn = toolbox.runExpr(ttree) + dyn.asInstanceOf[Int => Int] + } + + println("first invocation = " + foo(List(1, 2, 3))(10)) + println("second invocation = " + foo(List(1, 2, 3, 4))(10)) + println("q after second invocation = " + q) +} \ No newline at end of file diff --git a/test/files/run/reify_closure7.check b/test/files/run/reify_closure7.check new file mode 100644 index 0000000000..bf58b52bce --- /dev/null +++ b/test/files/run/reify_closure7.check @@ -0,0 +1,6 @@ +q = 1 +y = 1 +first invocation = 15 +q = 2 +y = 2 +second invocation = 17 diff --git a/test/files/run/reify_closure7.scala b/test/files/run/reify_closure7.scala new file mode 100644 index 0000000000..8933df23fa --- /dev/null +++ b/test/files/run/reify_closure7.scala @@ -0,0 +1,32 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + var q = 0 + var clo: Int => Int = null + def foo[T](ys: List[T]): Int => Int = { + val z = 1 + var y = 0 + val fun: reflect.Code[Int => Int] = x => { + y += 1 + q += 1 + println("q = " + q) + println("y = " + y) + x + ys.length * z + q + y + } + + 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) + clo = dyn.asInstanceOf[Int => Int] + } + + clo + } + + println("first invocation = " + foo(List(1, 2, 3))(10)) + println("second invocation = " + foo(List(1, 2, 3, 4))(10)) +} diff --git a/test/files/run/reify_closure8a.check b/test/files/run/reify_closure8a.check new file mode 100644 index 0000000000..9a037142aa --- /dev/null +++ b/test/files/run/reify_closure8a.check @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/test/files/run/reify_closure8a.scala b/test/files/run/reify_closure8a.scala new file mode 100644 index 0000000000..5e54bfc8c7 --- /dev/null +++ b/test/files/run/reify_closure8a.scala @@ -0,0 +1,17 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + class Foo(val y: Int) { + def fun = lift{y} + } + + 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 foo = dyn.asInstanceOf[Int] + println(foo) +} diff --git a/test/files/run/reify_closures10.check b/test/files/run/reify_closures10.check new file mode 100644 index 0000000000..fd3c81a4d7 --- /dev/null +++ b/test/files/run/reify_closures10.check @@ -0,0 +1,2 @@ +5 +5 diff --git a/test/files/run/reify_closures10.scala b/test/files/run/reify_closures10.scala new file mode 100644 index 0000000000..d0f895ae4d --- /dev/null +++ b/test/files/run/reify_closures10.scala @@ -0,0 +1,15 @@ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +object Test extends App { + val x = 2 + val y = 3 + val code = lift{println(x + y); x + y} + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) + println(toolbox.runExpr(ttree)) +} diff --git a/test/files/run/reify_implicits.check b/test/files/run/reify_implicits.check new file mode 100644 index 0000000000..e3aeb20f6b --- /dev/null +++ b/test/files/run/reify_implicits.check @@ -0,0 +1 @@ +x = List(1, 2, 3, 4) diff --git a/test/files/run/reify_implicits.scala b/test/files/run/reify_implicits.scala new file mode 100644 index 0000000000..a15cef9c97 --- /dev/null +++ b/test/files/run/reify_implicits.scala @@ -0,0 +1,21 @@ +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 def arrayWrapper[A : ClassManifest](x: Array[A]) = + new { + def sort(p: (A, A) => Boolean) = { + util.Sorting.stableSort(x, p); x + } + } + val x = Array(2, 3, 1, 4) + println("x = "+ x.sort((x: Int, y: Int) => x < y).toList) + }; + + 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_sort.check b/test/files/run/reify_sort.check new file mode 100644 index 0000000000..375536cc29 --- /dev/null +++ b/test/files/run/reify_sort.check @@ -0,0 +1,2 @@ +[6,2,8,5,1] +[1,2,5,6,8] diff --git a/test/files/run/reify_sort.scala b/test/files/run/reify_sort.scala new file mode 100644 index 0000000000..42991fe5d2 --- /dev/null +++ b/test/files/run/reify_sort.scala @@ -0,0 +1,57 @@ +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{ + /** Nested methods can use and even update everything + * visible in their scope (including local variables or + * arguments of enclosing methods). + */ + def sort(a: Array[Int]) { + + def swap(i: Int, j: Int) { + val t = a(i); a(i) = a(j); a(j) = t + } + + def sort1(l: Int, r: Int) { + val pivot = a((l + r) / 2) + var i = l + var j = r + while (i <= j) { + while (a(i) < pivot) i += 1 + while (a(j) > pivot) j -= 1 + if (i <= j) { + swap(i, j) + i += 1 + j -= 1 + } + } + if (l < j) sort1(l, j) + if (j < r) sort1(i, r) + } + + if (a.length > 0) + sort1(0, a.length - 1) + } + + def println(ar: Array[Int]) { + def print1 = { + def iter(i: Int): String = + ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") + if (ar.length == 0) "" else iter(0) + } + Console.println("[" + print1 + "]") + } + + val ar = Array(6, 2, 8, 5, 1) + println(ar) + sort(ar) + println(ar) + }; + + 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_this.check b/test/files/run/reify_this.check new file mode 100644 index 0000000000..af3d0652a9 --- /dev/null +++ b/test/files/run/reify_this.check @@ -0,0 +1,5 @@ +foo +false +2 +bar +2 \ No newline at end of file diff --git a/test/files/run/reify_this.scala b/test/files/run/reify_this.scala new file mode 100644 index 0000000000..38ef72b6eb --- /dev/null +++ b/test/files/run/reify_this.scala @@ -0,0 +1,31 @@ +import scala.reflect._ +import scala.reflect.Code._ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import reflect.runtime.Mirror.ToolBox + +trait Eval { + def eval(code: Code[_]): Any = eval(code.tree) + + def eval(tree: Tree): Any = { + val settings = new Settings + val reporter = new ConsoleReporter(settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(tree) + toolbox.runExpr(ttree) + } +} + +object Test extends App with Eval { + // select a value from package + eval(lift{println("foo")}) + eval(lift{println((new Object).toString == (new Object).toString)}) + + // select a type from package + eval(lift{val x: Any = 2; println(x)}) + eval(lift{val x: Object = "bar"; println(x)}) + + // select a value from module + val x = 2 + eval(lift{println(x)}) +} diff --git a/test/files/run/t5274_2.check b/test/files/run/t5274_2.check new file mode 100644 index 0000000000..375536cc29 --- /dev/null +++ b/test/files/run/t5274_2.check @@ -0,0 +1,2 @@ +[6,2,8,5,1] +[1,2,5,6,8] diff --git a/test/files/run/t5274_2.scala b/test/files/run/t5274_2.scala new file mode 100644 index 0000000000..42991fe5d2 --- /dev/null +++ b/test/files/run/t5274_2.scala @@ -0,0 +1,57 @@ +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{ + /** Nested methods can use and even update everything + * visible in their scope (including local variables or + * arguments of enclosing methods). + */ + def sort(a: Array[Int]) { + + def swap(i: Int, j: Int) { + val t = a(i); a(i) = a(j); a(j) = t + } + + def sort1(l: Int, r: Int) { + val pivot = a((l + r) / 2) + var i = l + var j = r + while (i <= j) { + while (a(i) < pivot) i += 1 + while (a(j) > pivot) j -= 1 + if (i <= j) { + swap(i, j) + i += 1 + j -= 1 + } + } + if (l < j) sort1(l, j) + if (j < r) sort1(i, r) + } + + if (a.length > 0) + sort1(0, a.length - 1) + } + + def println(ar: Array[Int]) { + def print1 = { + def iter(i: Int): String = + ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") + if (ar.length == 0) "" else iter(0) + } + Console.println("[" + print1 + "]") + } + + val ar = Array(6, 2, 8, 5, 1) + println(ar) + sort(ar) + println(ar) + }; + + 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/t5279.check b/test/files/run/t5279.check new file mode 100644 index 0000000000..f599e28b8a --- /dev/null +++ b/test/files/run/t5279.check @@ -0,0 +1 @@ +10 diff --git a/test/files/run/t5279.scala b/test/files/run/t5279.scala new file mode 100644 index 0000000000..39e7dd2c66 --- /dev/null +++ b/test/files/run/t5279.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{ + println(new Integer(10)) + }; + + 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/t5415.check b/test/files/run/t5415.check new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/files/run/t5415.scala b/test/files/run/t5415.scala new file mode 100644 index 0000000000..3db356da86 --- /dev/null +++ b/test/files/run/t5415.scala @@ -0,0 +1,14 @@ +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings +import scala.reflect.runtime.Mirror.ToolBox + +object Test extends App{ + case class Queryable2[T]() { def filter(predicate: T => Boolean) = ??? } + trait CoffeesTable{ def sales : Int } + val q = Queryable2[CoffeesTable]() + val code = scala.reflect.Code.lift{q.filter(_.sales > 5)} + + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter) + val ttree = toolbox.typeCheck(code.tree) +} diff --git a/test/pending/run/reify_closure1.check b/test/pending/run/reify_closure1.check deleted file mode 100644 index b2f7f08c17..0000000000 --- a/test/pending/run/reify_closure1.check +++ /dev/null @@ -1,2 +0,0 @@ -10 -10 diff --git a/test/pending/run/reify_closure1.scala b/test/pending/run/reify_closure1.scala deleted file mode 100644 index 825a38dc1d..0000000000 --- a/test/pending/run/reify_closure1.scala +++ /dev/null @@ -1,20 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - def foo[T](ys: List[T]): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { - x - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println(foo(List(1, 2, 3))(10)) - println(foo(List(1, 2, 3, 4))(10)) -} diff --git a/test/pending/run/reify_closure2a.check b/test/pending/run/reify_closure2a.check deleted file mode 100644 index c1f3abd7e6..0000000000 --- a/test/pending/run/reify_closure2a.check +++ /dev/null @@ -1,2 +0,0 @@ -11 -12 diff --git a/test/pending/run/reify_closure2a.scala b/test/pending/run/reify_closure2a.scala deleted file mode 100644 index b88bec005d..0000000000 --- a/test/pending/run/reify_closure2a.scala +++ /dev/null @@ -1,20 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - def foo(y: Int): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { - x + y - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println(foo(1)(10)) - println(foo(2)(10)) -} diff --git a/test/pending/run/reify_closure3a.check b/test/pending/run/reify_closure3a.check deleted file mode 100644 index c1f3abd7e6..0000000000 --- a/test/pending/run/reify_closure3a.check +++ /dev/null @@ -1,2 +0,0 @@ -11 -12 diff --git a/test/pending/run/reify_closure3a.scala b/test/pending/run/reify_closure3a.scala deleted file mode 100644 index 6414fa58a3..0000000000 --- a/test/pending/run/reify_closure3a.scala +++ /dev/null @@ -1,22 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - def foo(y: Int): Int => Int = { - def y1 = y - - val fun: reflect.Code[Int => Int] = x => { - x + y1 - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println(foo(1)(10)) - println(foo(2)(10)) -} diff --git a/test/pending/run/reify_closure4a.check b/test/pending/run/reify_closure4a.check deleted file mode 100644 index c1f3abd7e6..0000000000 --- a/test/pending/run/reify_closure4a.check +++ /dev/null @@ -1,2 +0,0 @@ -11 -12 diff --git a/test/pending/run/reify_closure4a.scala b/test/pending/run/reify_closure4a.scala deleted file mode 100644 index 99e9d82706..0000000000 --- a/test/pending/run/reify_closure4a.scala +++ /dev/null @@ -1,22 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - def foo(y: Int): Int => Int = { - val y1 = y - - val fun: reflect.Code[Int => Int] = x => { - x + y1 - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println(foo(1)(10)) - println(foo(2)(10)) -} diff --git a/test/pending/run/reify_closure5a.check b/test/pending/run/reify_closure5a.check deleted file mode 100644 index df9e19c591..0000000000 --- a/test/pending/run/reify_closure5a.check +++ /dev/null @@ -1,2 +0,0 @@ -13 -14 diff --git a/test/pending/run/reify_closure5a.scala b/test/pending/run/reify_closure5a.scala deleted file mode 100644 index 0ac53d5479..0000000000 --- a/test/pending/run/reify_closure5a.scala +++ /dev/null @@ -1,20 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - def foo[T](ys: List[T]): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { - x + ys.length - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println(foo(List(1, 2, 3))(10)) - println(foo(List(1, 2, 3, 4))(10)) -} diff --git a/test/pending/run/reify_closure6.check b/test/pending/run/reify_closure6.check deleted file mode 100644 index e521ea874d..0000000000 --- a/test/pending/run/reify_closure6.check +++ /dev/null @@ -1,7 +0,0 @@ -q = 1 -y = 1 -first invocation = 15 -q = 2 -y = 1 -second invocation = 17 -q after second invocation = 2 diff --git a/test/pending/run/reify_closure6.scala b/test/pending/run/reify_closure6.scala deleted file mode 100644 index 43ddfde28d..0000000000 --- a/test/pending/run/reify_closure6.scala +++ /dev/null @@ -1,28 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - var q = 0 - def foo[T](ys: List[T]): Int => Int = { - val z = 1 - var y = 0 - val fun: reflect.Code[Int => Int] = x => { - y += 1 - q += 1 - println("q = " + q) - println("y = " + y) - x + ys.length * z + q + y - } - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(fun.tree) - val dyn = toolbox.runExpr(ttree) - dyn.asInstanceOf[Int => Int] - } - - println("first invocation = " + foo(List(1, 2, 3))(10)) - println("second invocation = " + foo(List(1, 2, 3, 4))(10)) - println("q after second invocation = " + q) -} diff --git a/test/pending/run/reify_closure7.check b/test/pending/run/reify_closure7.check deleted file mode 100644 index bf58b52bce..0000000000 --- a/test/pending/run/reify_closure7.check +++ /dev/null @@ -1,6 +0,0 @@ -q = 1 -y = 1 -first invocation = 15 -q = 2 -y = 2 -second invocation = 17 diff --git a/test/pending/run/reify_closure7.scala b/test/pending/run/reify_closure7.scala deleted file mode 100644 index 8933df23fa..0000000000 --- a/test/pending/run/reify_closure7.scala +++ /dev/null @@ -1,32 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - var q = 0 - var clo: Int => Int = null - def foo[T](ys: List[T]): Int => Int = { - val z = 1 - var y = 0 - val fun: reflect.Code[Int => Int] = x => { - y += 1 - q += 1 - println("q = " + q) - println("y = " + y) - x + ys.length * z + q + y - } - - 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) - clo = dyn.asInstanceOf[Int => Int] - } - - clo - } - - println("first invocation = " + foo(List(1, 2, 3))(10)) - println("second invocation = " + foo(List(1, 2, 3, 4))(10)) -} diff --git a/test/pending/run/reify_closure8a.check b/test/pending/run/reify_closure8a.check deleted file mode 100644 index 9a037142aa..0000000000 --- a/test/pending/run/reify_closure8a.check +++ /dev/null @@ -1 +0,0 @@ -10 \ No newline at end of file diff --git a/test/pending/run/reify_closure8a.scala b/test/pending/run/reify_closure8a.scala deleted file mode 100644 index 5e54bfc8c7..0000000000 --- a/test/pending/run/reify_closure8a.scala +++ /dev/null @@ -1,17 +0,0 @@ -import scala.reflect.Code._ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - class Foo(val y: Int) { - def fun = lift{y} - } - - 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 foo = dyn.asInstanceOf[Int] - println(foo) -} diff --git a/test/pending/run/reify_closures10.check b/test/pending/run/reify_closures10.check deleted file mode 100644 index fd3c81a4d7..0000000000 --- a/test/pending/run/reify_closures10.check +++ /dev/null @@ -1,2 +0,0 @@ -5 -5 diff --git a/test/pending/run/reify_closures10.scala b/test/pending/run/reify_closures10.scala deleted file mode 100644 index d0f895ae4d..0000000000 --- a/test/pending/run/reify_closures10.scala +++ /dev/null @@ -1,15 +0,0 @@ -import scala.reflect.Code._ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -object Test extends App { - val x = 2 - val y = 3 - val code = lift{println(x + y); x + y} - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) - println(toolbox.runExpr(ttree)) -} diff --git a/test/pending/run/reify_implicits.check b/test/pending/run/reify_implicits.check deleted file mode 100644 index e3aeb20f6b..0000000000 --- a/test/pending/run/reify_implicits.check +++ /dev/null @@ -1 +0,0 @@ -x = List(1, 2, 3, 4) diff --git a/test/pending/run/reify_implicits.scala b/test/pending/run/reify_implicits.scala deleted file mode 100644 index a15cef9c97..0000000000 --- a/test/pending/run/reify_implicits.scala +++ /dev/null @@ -1,21 +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{ - implicit def arrayWrapper[A : ClassManifest](x: Array[A]) = - new { - def sort(p: (A, A) => Boolean) = { - util.Sorting.stableSort(x, p); x - } - } - val x = Array(2, 3, 1, 4) - println("x = "+ x.sort((x: Int, y: Int) => x < y).toList) - }; - - 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_sort.check b/test/pending/run/reify_sort.check deleted file mode 100644 index 375536cc29..0000000000 --- a/test/pending/run/reify_sort.check +++ /dev/null @@ -1,2 +0,0 @@ -[6,2,8,5,1] -[1,2,5,6,8] diff --git a/test/pending/run/reify_sort.scala b/test/pending/run/reify_sort.scala deleted file mode 100644 index 42991fe5d2..0000000000 --- a/test/pending/run/reify_sort.scala +++ /dev/null @@ -1,57 +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{ - /** Nested methods can use and even update everything - * visible in their scope (including local variables or - * arguments of enclosing methods). - */ - def sort(a: Array[Int]) { - - def swap(i: Int, j: Int) { - val t = a(i); a(i) = a(j); a(j) = t - } - - def sort1(l: Int, r: Int) { - val pivot = a((l + r) / 2) - var i = l - var j = r - while (i <= j) { - while (a(i) < pivot) i += 1 - while (a(j) > pivot) j -= 1 - if (i <= j) { - swap(i, j) - i += 1 - j -= 1 - } - } - if (l < j) sort1(l, j) - if (j < r) sort1(i, r) - } - - if (a.length > 0) - sort1(0, a.length - 1) - } - - def println(ar: Array[Int]) { - def print1 = { - def iter(i: Int): String = - ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") - if (ar.length == 0) "" else iter(0) - } - Console.println("[" + print1 + "]") - } - - val ar = Array(6, 2, 8, 5, 1) - println(ar) - sort(ar) - println(ar) - }; - - 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_this.check b/test/pending/run/reify_this.check deleted file mode 100644 index af3d0652a9..0000000000 --- a/test/pending/run/reify_this.check +++ /dev/null @@ -1,5 +0,0 @@ -foo -false -2 -bar -2 \ No newline at end of file diff --git a/test/pending/run/reify_this.scala b/test/pending/run/reify_this.scala deleted file mode 100644 index 38ef72b6eb..0000000000 --- a/test/pending/run/reify_this.scala +++ /dev/null @@ -1,31 +0,0 @@ -import scala.reflect._ -import scala.reflect.Code._ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import reflect.runtime.Mirror.ToolBox - -trait Eval { - def eval(code: Code[_]): Any = eval(code.tree) - - def eval(tree: Tree): Any = { - val settings = new Settings - val reporter = new ConsoleReporter(settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(tree) - toolbox.runExpr(ttree) - } -} - -object Test extends App with Eval { - // select a value from package - eval(lift{println("foo")}) - eval(lift{println((new Object).toString == (new Object).toString)}) - - // select a type from package - eval(lift{val x: Any = 2; println(x)}) - eval(lift{val x: Object = "bar"; println(x)}) - - // select a value from module - val x = 2 - eval(lift{println(x)}) -} diff --git a/test/pending/run/t5274_2.check b/test/pending/run/t5274_2.check deleted file mode 100644 index 375536cc29..0000000000 --- a/test/pending/run/t5274_2.check +++ /dev/null @@ -1,2 +0,0 @@ -[6,2,8,5,1] -[1,2,5,6,8] diff --git a/test/pending/run/t5274_2.scala b/test/pending/run/t5274_2.scala deleted file mode 100644 index 42991fe5d2..0000000000 --- a/test/pending/run/t5274_2.scala +++ /dev/null @@ -1,57 +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{ - /** Nested methods can use and even update everything - * visible in their scope (including local variables or - * arguments of enclosing methods). - */ - def sort(a: Array[Int]) { - - def swap(i: Int, j: Int) { - val t = a(i); a(i) = a(j); a(j) = t - } - - def sort1(l: Int, r: Int) { - val pivot = a((l + r) / 2) - var i = l - var j = r - while (i <= j) { - while (a(i) < pivot) i += 1 - while (a(j) > pivot) j -= 1 - if (i <= j) { - swap(i, j) - i += 1 - j -= 1 - } - } - if (l < j) sort1(l, j) - if (j < r) sort1(i, r) - } - - if (a.length > 0) - sort1(0, a.length - 1) - } - - def println(ar: Array[Int]) { - def print1 = { - def iter(i: Int): String = - ar(i) + (if (i < ar.length-1) "," + iter(i+1) else "") - if (ar.length == 0) "" else iter(0) - } - Console.println("[" + print1 + "]") - } - - val ar = Array(6, 2, 8, 5, 1) - println(ar) - sort(ar) - println(ar) - }; - - 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/t5279.check b/test/pending/run/t5279.check deleted file mode 100644 index f599e28b8a..0000000000 --- a/test/pending/run/t5279.check +++ /dev/null @@ -1 +0,0 @@ -10 diff --git a/test/pending/run/t5279.scala b/test/pending/run/t5279.scala deleted file mode 100644 index 39e7dd2c66..0000000000 --- a/test/pending/run/t5279.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{ - println(new Integer(10)) - }; - - 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/t5415.check b/test/pending/run/t5415.check deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/pending/run/t5415.scala b/test/pending/run/t5415.scala deleted file mode 100644 index 3db356da86..0000000000 --- a/test/pending/run/t5415.scala +++ /dev/null @@ -1,14 +0,0 @@ -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings -import scala.reflect.runtime.Mirror.ToolBox - -object Test extends App{ - case class Queryable2[T]() { def filter(predicate: T => Boolean) = ??? } - trait CoffeesTable{ def sales : Int } - val q = Queryable2[CoffeesTable]() - val code = scala.reflect.Code.lift{q.filter(_.sales > 5)} - - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter) - val ttree = toolbox.typeCheck(code.tree) -} -- cgit v1.2.3 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. --- .../scala/reflect/internal/Definitions.scala | 3 - src/compiler/scala/reflect/internal/StdNames.scala | 10 +- src/compiler/scala/reflect/internal/Trees.scala | 9 - src/compiler/scala/tools/ant/Scalac.scala | 2 +- src/compiler/scala/tools/nsc/Global.scala | 14 +- src/compiler/scala/tools/nsc/ast/Reifiers.scala | 445 ++++++++++++++++ .../scala/tools/nsc/ast/ReifyPrinters.scala | 85 +++ .../scala/tools/nsc/settings/ScalaSettings.scala | 2 - .../scala/tools/nsc/transform/LiftCode.scala | 570 --------------------- .../scala/tools/nsc/typechecker/Implicits.scala | 2 +- .../scala/tools/nsc/typechecker/Infer.scala | 8 +- .../scala/tools/nsc/typechecker/Macros.scala | 7 +- .../scala/tools/nsc/typechecker/Typers.scala | 15 +- src/library/scala/reflect/Code.scala | 2 + src/library/scala/reflect/api/StandardNames.scala | 21 + src/library/scala/reflect/api/Trees.scala | 15 +- src/library/scala/reflect/api/Universe.scala | 3 +- src/library/scala/reflect/macro/Context.scala | 21 + src/partest/scala/tools/partest/PartestTask.scala | 12 +- .../scala/tools/partest/nest/CompileManager.scala | 2 + .../scala/tools/partest/nest/PathSettings.scala | 7 + .../tools/partest/nest/ReflectiveRunner.scala | 8 +- .../scala/tools/partest/nest/TestFile.scala | 4 + src/partest/scala/tools/partest/nest/Worker.scala | 4 +- .../scala/tools/partest/utils/CodeTest.scala | 41 -- test/files/codelib/code.jar.desired.sha1 | 1 + test/files/pos/t531.scala | 4 +- test/files/pos/t532.scala | 4 +- test/files/run/code.check | 36 -- test/files/run/code.scala | 60 --- test/files/run/programmatic-main.check | 37 +- test/files/run/reify_closure1.scala | 4 +- test/files/run/reify_closure2a.scala | 4 +- test/files/run/reify_closure3a.scala | 4 +- test/files/run/reify_closure4a.scala | 4 +- test/files/run/reify_closure5a.scala | 4 +- test/files/run/reify_closure6.scala | 4 +- test/files/run/reify_closure7.scala | 4 +- test/files/run/reify_this.scala | 2 +- test/files/run/t4875.check | 17 - test/files/run/t4875.scala | 12 - 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 +- 45 files changed, 687 insertions(+), 842 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/ast/Reifiers.scala create mode 100644 src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala delete mode 100644 src/compiler/scala/tools/nsc/transform/LiftCode.scala create mode 100644 src/library/scala/reflect/api/StandardNames.scala delete mode 100644 src/partest/scala/tools/partest/utils/CodeTest.scala create mode 100644 test/files/codelib/code.jar.desired.sha1 delete mode 100644 test/files/run/code.check delete mode 100644 test/files/run/code.scala delete mode 100644 test/files/run/t4875.check delete mode 100644 test/files/run/t4875.scala (limited to 'test/pending') diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 8114be20d5..6871822562 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -402,9 +402,6 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val FullManifestModule = getRequiredModule("scala.reflect.Manifest") lazy val OptManifestClass = getRequiredClass("scala.reflect.OptManifest") lazy val NoManifest = getRequiredModule("scala.reflect.NoManifest") - lazy val CodeClass = getClass(sn.Code) - lazy val CodeModule = getModule(sn.Code) - lazy val Code_lift = getMember(CodeModule, nme.lift_) lazy val ScalaSignatureAnnotation = getRequiredClass("scala.reflect.ScalaSignature") lazy val ScalaLongSignatureAnnotation = getRequiredClass("scala.reflect.ScalaLongSignature") diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index b1a24c0be2..045daa7eb1 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -271,8 +271,9 @@ trait StdNames extends NameManglers { self: SymbolTable => // Compiler utilized names // val productElementName: NameType = "productElementName" val Ident: NameType = "Ident" - val This: NameType = "This" val StringContext: NameType = "StringContext" + val This: NameType = "This" + val Tree : NameType = "Tree" val TYPE_ : NameType = "TYPE" val TypeTree: NameType = "TypeTree" val UNIT : NameType = "UNIT" @@ -427,7 +428,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val toInteger: NameType = "toInteger" } - object tpnme extends TypeNames /*with LibraryTypeNames*/ with TypeNameMangling { + object tpnme extends AbsTypeNames with TypeNames /*with LibraryTypeNames*/ with TypeNameMangling { type NameType = TypeName protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) @@ -464,7 +465,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val javanme = nme.javaKeywords - object nme extends TermNames /*with LibraryTermNames*/ with TermNameMangling { + object nme extends AbsTermNames with TermNames /*with LibraryTermNames*/ with TermNameMangling { type NameType = TermName protected implicit def createNameType(name: String): TermName = newTermNameCached(name) @@ -711,7 +712,6 @@ trait StdNames extends NameManglers { self: SymbolTable => val BoxedCharacter : TypeName val BoxedNumber : TypeName val Class : TypeName - val Code : TypeName val Delegate : TypeName val IOOBException : TypeName // IndexOutOfBoundsException val InvTargetException : TypeName // InvocationTargetException @@ -846,7 +846,6 @@ trait StdNames extends NameManglers { self: SymbolTable => final val BoxedCharacter: TypeName = "System.IConvertible" final val BoxedNumber: TypeName = "System.IConvertible" final val Class: TypeName = "System.Type" - final val Code: TypeName = tpnme.NO_NAME final val Delegate: TypeName = "System.MulticastDelegate" final val IOOBException: TypeName = "System.IndexOutOfRangeException" final val InvTargetException: TypeName = "System.Reflection.TargetInvocationException" @@ -880,7 +879,6 @@ trait StdNames extends NameManglers { self: SymbolTable => private class J2SENames extends JavaNames { final val BeanProperty: TypeName = "scala.beans.BeanProperty" final val BooleanBeanProperty: TypeName = "scala.beans.BooleanBeanProperty" - final val Code: TypeName = "scala.reflect.Code" final val JavaSerializable: TypeName = "java.io.Serializable" } diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index ca7801ac9d..076a7722ae 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -231,15 +231,6 @@ trait Trees extends api.Trees { self: SymbolTable => def Bind(sym: Symbol, body: Tree): Bind = Bind(sym.name, body) setSymbol sym - - /** Factory method for object creation `new tpt(args_1)...(args_n)` - * A `New(t, as)` is expanded to: `(new t).(as)` - */ - def New(tpt: Tree, argss: List[List[Tree]]): Tree = { - assert(!argss.isEmpty) - val superRef: Tree = Select(New(tpt), nme.CONSTRUCTOR) - (superRef /: argss) (Apply) - } /** 0-1 argument list new, based on a symbol. */ def New(sym: Symbol, args: Tree*): Tree = diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala index 04ff0c440d..3c79fcd3fb 100644 --- a/src/compiler/scala/tools/ant/Scalac.scala +++ b/src/compiler/scala/tools/ant/Scalac.scala @@ -90,7 +90,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared { /** Defines valid values for properties that refer to compiler phases. */ object CompilerPhase extends PermissibleValue { - val values = List("namer", "typer", "pickler", "refchecks", "liftcode", + val values = List("namer", "typer", "pickler", "refchecks", "uncurry", "tailcalls", "specialize", "explicitouter", "erasure", "lazyvals", "lambdalift", "constructors", "flatten", "mixin", "cleanup", "icode", "inliner", diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 797ed7e047..d4152dffdc 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -37,6 +37,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb with Plugins with PhaseAssembly with Trees + with Reifiers with TreePrinters with DocComments with MacroContext @@ -124,7 +125,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb /** Print tree in detailed form */ object nodePrinters extends { val global: Global.this.type = Global.this - } with NodePrinters { + } with NodePrinters with ReifyPrinters { infolevel = InfoLevel.Verbose } @@ -134,6 +135,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb } with TreeBrowsers val nodeToString = nodePrinters.nodeToString + val reifiedNodeToString = nodePrinters.reifiedNodeToString val treeBrowser = treeBrowsers.create() // ------------ Hooks for interactive mode------------------------- @@ -457,17 +459,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val runsRightAfter = None } with RefChecks - // phaseName = "liftcode" - object liftcode extends { - val global: Global.this.type = Global.this - val runsAfter = List[String]("refchecks") - val runsRightAfter = None - } with LiftCode - // phaseName = "uncurry" override object uncurry extends { val global: Global.this.type = Global.this - val runsAfter = List[String]("refchecks", "liftcode") + val runsAfter = List[String]("refchecks") val runsRightAfter = None } with UnCurry @@ -652,7 +647,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb superAccessors -> "add super accessors in traits and nested classes", pickler -> "serialize symbol tables", refChecks -> "reference/override checking, translate nested objects", - liftcode -> "reify trees", uncurry -> "uncurry, translate function values to anonymous classes", tailCalls -> "replace tail calls by jumps", specializeTypes -> "@specialized-driven class and method specialization", diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala new file mode 100644 index 0000000000..952110ade2 --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/Reifiers.scala @@ -0,0 +1,445 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Gilles Dubochet + */ + +package scala.tools.nsc +package ast + +import symtab._ +import Flags._ +import scala.collection.{ mutable, immutable } +import scala.collection.mutable.ListBuffer +import scala.tools.nsc.util.FreshNameCreator +import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } + +/** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type. + * See more info in the comments to `reify' in scala.reflect.macro.Context. + * + * @author Martin Odersky + * @version 2.10 + */ +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 + } + } 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 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 == EmptyPackageClass) + mirrorSelect("definitions.EmptyPackageClass") + 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 (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("freeVar", 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))) + ) + ) + } + + /** + * 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.setTypeSig), 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 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) + } + } + + private def definedInLiftedCode(tpe: Type) = + tpe exists (tp => boundSyms contains tp.typeSymbol) + + private def isErased(tree: Tree) = tree match { + case tt: TypeTree => definedInLiftedCode(tt.tpe) && tt.original == null + case _ => false + } + + /** Reify a tree */ + private def reifyTree(tree: Tree): Tree = tree match { + case EmptyTree => + reifyMirrorObject(EmptyTree) + case This(_) if !(boundSyms contains tree.symbol) => + reifyFree(tree) + case Ident(_) if !(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) => + if (definedInLiftedCode(tt.tpe)) { + // erase non-essential (i.e. inferred) types + // reify symless counterparts of essential types + if (tt.original != null) reify(tt.original) else mirrorCall("TypeTree") + } else { + var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe)) + if (tt.original != null) { + val setOriginal = Select(rtt, newTermName("setOriginal")) + val reifiedOriginal = reify(tt.original) + rtt = Apply(setOriginal, List(reifiedOriginal)) + } + 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 + } + + 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))) +*/ + } + + /** + * 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("freeVar", 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 = + 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) + } + + /** 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) + } + + /** + * 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 + } + + symDefs.toList ++ fillIns.toList + } + } + + /** A throwable signalling a reification error */ + 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 new file mode 100644 index 0000000000..aebde18703 --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala @@ -0,0 +1,85 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.tools.nsc +package ast + +import compat.Platform.EOL +import symtab._ +import Flags._ + +trait ReifyPrinters { self: NodePrinters => + + val global: Global + import global._ + + object reifiedNodeToString extends Function1[Tree, String] { + def apply(tree: Tree): String = { + import scala.reflect.api.Modifier + import scala.reflect.api.Modifier._ + + def copypasteModifier(mod: Modifier.Value): String = mod match { + case mod @ ( + `protected` | `private` | `override` | + `abstract` | `final` | `sealed` | + `implicit` | `lazy` | `macro` | + `case` | `trait`) => "`" + mod.toString + "`" + case mod => mod.toString + } + + // @PP: I fervently hope this is a test case or something, not anything being + // depended upon. Of more fragile code I cannot conceive. + // @eb: This stuff is only needed to debug-print out reifications in human-readable format + // Rolling a full-fledged, robust TreePrinter would be several times more code. + (for (line <- (tree.toString.split(EOL) drop 2 dropRight 1)) yield { + var s = line.trim + s = s.replace("$mr.", "") + s = s.replace(".apply", "") + s = s.replace("scala.collection.immutable.", "") + s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List") + s = "List\\[.*?\\]".r.replaceAllIn(s, "List") + s = s.replace("immutable.this.Nil", "List()") + 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 flags = m.group(1).toLong + val s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier mkString ", " + if (s_flags != "") + buf.append("Set(" + s_flags + ")") + + val privateWithin = "" + m.group(2) + if (privateWithin != "") + buf.append(", newTypeName(\"" + privateWithin + "\")") + + val annotations = m.group(3) + if (annotations.nonEmpty) + buf.append(", List(" + annotations + ")") + + "Modifiers(" + buf.toString + ")" + }) + s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => { + val flags = m.group(1).toLong + val mods = Flags.modifiersOfFlags(flags) map copypasteModifier + "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))" + }) + + s + }) mkString EOL + } + } + + + def printReifyCopypaste(tree: Tree) { + val reifyDebug = settings.Yreifydebug.value + if (reifyDebug) println("=======================") + printReifyCopypaste1(tree) + if (reifyDebug) println("=======================") + } + + def printReifyCopypaste1(tree: Tree) { + } +} \ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index d1ce460eb9..485a1f3a5c 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -167,8 +167,6 @@ trait ScalaSettings extends AbsScalaSettings val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification.") - val Yreifytyperdebug - = BooleanSetting ("-Yreifytyper-debug", "Trace typings of reified trees.") 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/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala deleted file mode 100644 index d0ed92f8ba..0000000000 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ /dev/null @@ -1,570 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2011 LAMP/EPFL - * @author Gilles Dubochet - */ - -package scala.tools.nsc -package transform - -import symtab._ -import Flags._ -import scala.collection.{ mutable, immutable } -import scala.collection.mutable.ListBuffer -import scala.tools.nsc.util.FreshNameCreator -import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple } - -/** - * Translate expressions of the form reflect.Code.lift(exp) - * to the reified "reflect trees" representation of exp. - * Also: mutable variables that are accessed from a local function are wrapped in refs. - * - * @author Martin Odersky - * @version 2.10 - */ -abstract class LiftCode extends Transform with TypingTransformers { - - import global._ // the global environment - import definitions._ // standard classes and methods - import typer.{ typed, atOwner } // methods to type trees - - val symbols: global.type = global - - /** the following two members override abstract members in Transform */ - val phaseName: String = "liftcode" - - def newTransformer(unit: CompilationUnit): Transformer = - new Codifier(unit) - - private lazy val MirrorMemberNames = - ReflectRuntimeMirror.info.nonPrivateMembers filter (_.isTerm) map (_.toString) toSet - - // Would be nice if we could use something like this to check the names, - // but it seems that info is unavailable when I need it. - private def mirrorFactoryName(value: Any): Option[String] = value match { - // Modest (inadequate) sanity check that there's a member by this name. - case x: Product if MirrorMemberNames(x.productPrefix) => - Some(x.productPrefix) - case _ => - Some(value.getClass.getName split """[$.]""" last) filter MirrorMemberNames - } - private def isMirrorMemberObject(value: Product) = value match { - case NoType | NoPrefix | NoPosition | EmptyTree => true - case _ => false - } - - class Codifier(unit: CompilationUnit) extends TypingTransformer(unit) { - - val reifyDebug = settings.Yreifydebug.value - val reifyTyperDebug = settings.Yreifytyperdebug.value - val debugTrace = util.trace when reifyDebug - - val reifyCopypaste = settings.Yreifycopypaste.value - def printCopypaste(tree: Tree) { - if (reifyDebug) println("=======================") - printCopypaste1(tree) - if (reifyDebug) println("=======================") - } - def printCopypaste1(tree: Tree) { - import scala.reflect.api.Modifier - import scala.reflect.api.Modifier._ - - def copypasteModifier(mod: Modifier.Value): String = mod match { - case mod @ ( - `protected` | `private` | `override` | - `abstract` | `final` | `sealed` | - `implicit` | `lazy` | `macro` | - `case` | `trait`) => "`" + mod.toString + "`" - case mod => mod.toString - } - - // I fervently hope this is a test case or something, not anything being - // depended upon. Of more fragile code I cannot conceive. - for (line <- (tree.toString.split(Properties.lineSeparator) drop 2 dropRight 1)) { - var s = line.trim - s = s.replace("$mr.", "") - s = s.replace(".apply", "") - s = s.replace("scala.collection.immutable.", "") - s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List") - s = "List\\[.*?\\]".r.replaceAllIn(s, "List") - s = s.replace("immutable.this.Nil", "List()") - 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 flags = m.group(1).toLong - val s_flags = Flags.modifiersOfFlags(flags) map copypasteModifier mkString ", " - if (s_flags != "") - buf.append("Set(" + s_flags + ")") - - val privateWithin = "" + m.group(2) - if (privateWithin != "") - buf.append(", newTypeName(\"" + privateWithin + "\")") - - val annotations = m.group(3) - if (annotations.nonEmpty) - buf.append(", List(" + annotations + ")") - - "Modifiers(" + buf.toString + ")" - }) - s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => { - val flags = m.group(1).toLong - val mods = Flags.modifiersOfFlags(flags) map copypasteModifier - "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))" - }) - - println(s) - } - } - - override def transformUnit(unit: CompilationUnit) { - atPhase(phase.next) { - super.transformUnit(unit) - } - } - - override def transform(tree: Tree): Tree = { - val sym = tree.symbol - tree match { - case Apply(_, List(tree)) if sym == Code_lift => // reify Code.lift[T](expr) instances - val saved = printTypings - try { - debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString) - debugTrace("transformed = ") { - val untyped = codify(super.transform(tree)) - if (reifyCopypaste) printCopypaste(untyped) - - printTypings = reifyTyperDebug - val typed = localTyper.typedPos(tree.pos)(untyped) - typed - } - } catch { - case ex: ReifierError => - unit.error(ex.pos, ex.msg) - tree - } finally { - printTypings = saved - } - case _ => - super.transform(tree) - } - } - - def codify(tree: Tree): Tree = debugTrace("codified " + tree + " -> ") { - val targetType = definitions.CodeClass.primaryConstructor.info.paramTypes.head - val reifier = new Reifier() - val arg = gen.mkAsInstanceOf(reifier.reifyTopLevel(tree), targetType, wrapInApply = false) - val treetpe = // this really should use packedType(tree.tpe, context.owner) - // where packedType is defined in Typers. But we can do that only if liftCode is moved to Typers. - if (tree.tpe.typeSymbol.isAnonymousClass) tree.tpe.typeSymbol.classBound - else tree.tpe - New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(treetpe.widen))), - List(List(arg))) - } - } - - /** - * Given a tree or type, generate a tree that when executed at runtime produces the original tree or type. - * For instance: Given - * - * var x = 1; Code(x + 1) - * - * The `x + 1` expression is reified to - * - * $mr.Apply($mr.Select($mr.Ident($mr.freeVar("x". , x), "+"), List($mr.Literal($mr.Constant(1)))))) - * - * Or, the term name 'abc' is reified to: - * - * $mr.Apply($mr.Select($mr.Ident("newTermName")), List(Literal(Constant("abc"))))) - * - * todo: Treat embedded Code blocks by merging them into containing block - * - */ - class 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 - - /** - * 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 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 == EmptyPackageClass) - mirrorSelect("definitions.EmptyPackageClass") - 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 (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("freeVar", 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))) - ) - ) - } - - /** - * 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.setTypeSig), 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 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) - } - } - - private def definedInLiftedCode(tpe: Type) = - tpe exists (tp => boundSyms contains tp.typeSymbol) - - private def isErased(tree: Tree) = tree match { - case tt: TypeTree => definedInLiftedCode(tt.tpe) && tt.original == null - case _ => false - } - - /** Reify a tree */ - private def reifyTree(tree: Tree): Tree = tree match { - case EmptyTree => - reifyMirrorObject(EmptyTree) - case This(_) if !(boundSyms contains tree.symbol) => - reifyFree(tree) - case Ident(_) if !(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) => - if (definedInLiftedCode(tt.tpe)) { - // erase non-essential (i.e. inferred) types - // reify symless counterparts of essential types - if (tt.original != null) reify(tt.original) else mirrorCall("TypeTree") - } else { - var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe)) - if (tt.original != null) { - val setOriginal = Select(rtt, newTermName("setOriginal")) - val reifiedOriginal = reify(tt.original) - rtt = Apply(setOriginal, List(reifiedOriginal)) - } - rtt - } - case ta @ TypeApply(hk, ts) => - if (ts exists isErased) reifyTree(hk) else reifyProduct(ta) - case global.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 - } - - 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))) -*/ - } - - /** - * 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("freeVar", 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 = - 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) - } - - /** 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) - } - - /** - * 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, TypeTree(), 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 - } - - symDefs.toList ++ fillIns.toList - } - } - - /** A throwable signalling a reification error */ - class ReifierError(var pos: Position, val msg: String) extends Throwable(msg) { - def this(msg: String) = this(NoPosition, 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/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 036e7fc750..3d2f86d54d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1163,7 +1163,7 @@ trait Implicits { /* !!! the following is almost right, but we have to splice nested manifest * !!! types into this type. This requires a substantial extension of * !!! reifiers. - val reifier = new liftcode.Reifier() + val reifier = new Reifier() val rtree = reifier.reifyTopLevel(tp1) manifestFactoryCall("apply", tp, rtree) */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index eac657da19..e8c03aff66 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -640,13 +640,7 @@ trait Infer { case ExistentialType(tparams, qtpe) => isApplicable(undetparams, qtpe, argtpes0, pt) case MethodType(params, _) => - val formals0 = params map { param => - param.tpe match { - case TypeRef(_, sym, List(tpe)) if sym isNonBottomSubClass CodeClass => tpe - case tpe => tpe - } - } - val formals = formalTypes(formals0, argtpes0.length) + val formals = formalTypes(params map { _.tpe }, argtpes0.length) def tryTupleApply: Boolean = { // if 1 formal, 1 argtpe (a tuple), otherwise unmodified argtpes0 diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index c63ae90ef6..4c790bfc34 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -108,11 +108,14 @@ trait Macros { self: Analyzer => else { val receiverClass: mirror.Symbol = mirror.classWithName(mmeth.owner.fullName) val receiverObj = receiverClass.companionModule - if (receiverObj == NoSymbol) None + if (receiverObj == mirror.NoSymbol) None else { val receiver = mirror.getCompanionObject(receiverClass) val rmeth = receiverObj.info.member(mirror.newTermName(mmeth.name.toString)) - Some((receiver, rmeth)) + if (rmeth == mirror.NoSymbol) None + else { + Some((receiver, rmeth)) + } } } } catch { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d039515320..eb0bed035c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -708,8 +708,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } } - def isCodeType(tpe: Type) = tpe.typeSymbol isNonBottomSubClass CodeClass - /** Perform the following adaptations of expression, pattern or type `tree` wrt to * given mode `mode` and given prototype `pt`: * (-1) For expressions with annotated types, let AnnotationCheckers decide what to do @@ -1993,8 +1991,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { */ def typedFunction(fun: Function, mode: Int, pt: Type): Tree = { val numVparams = fun.vparams.length - val codeExpected = !forMSIL && (pt.typeSymbol isNonBottomSubClass CodeClass) - if (numVparams > definitions.MaxFunctionArity) return MaxFunctionArityError(fun) @@ -2011,7 +2007,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { else (FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType) - val (clazz, argpts, respt) = decompose(if (codeExpected) pt.normalize.typeArgs.head else pt) + val (clazz, argpts, respt) = decompose(pt) if (argpts.lengthCompare(numVparams) != 0) WrongNumberOfParametersError(fun, argpts) else { @@ -2021,7 +2017,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (isFullyDefined(argpt)) argpt else { fun match { - case etaExpansion(vparams, fn, args) if !codeExpected => + case etaExpansion(vparams, fn, args) => silent(_.typed(fn, forFunMode(mode), pt)) match { case SilentResultValue(fn1) if context.undetparams.isEmpty => // if context,undetparams is not empty, the function was polymorphic, @@ -2053,13 +2049,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val restpe = packedType(body1, fun.symbol).deconst.resultType val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe) // body = checkNoEscaping.locals(context.scope, restpe, body) - val fun1 = treeCopy.Function(fun, vparams, body1).setType(funtpe) - if (codeExpected) lifted(fun1) else fun1 - } + treeCopy.Function(fun, vparams, body1).setType(funtpe) } - - def lifted(tree: Tree): Tree = typedPos(tree.pos) { - Apply(Select(Ident(CodeModule), nme.lift_), List(tree)) } def typedRefinement(stats: List[Tree]) { diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala index 52705d302c..f28264c7a2 100644 --- a/src/library/scala/reflect/Code.scala +++ b/src/library/scala/reflect/Code.scala @@ -11,12 +11,14 @@ package scala.reflect /** This type is required by the compiler and should not be used in client code. */ +@deprecated("Replaced with scala.reflect.macro.Context#reify, will be completely removed soon", "2.10") class Code[T: Manifest](val tree: scala.reflect.mirror.Tree) { val manifest = implicitly[Manifest[T]] override def toString = "Code(tree = "+tree+", manifest = "+manifest+")" } /** This type is required by the compiler and should not be used in client code. */ +@deprecated("Replaced with scala.reflect.macro.Context#reify, will be completely removed soon", "2.10") object Code { def lift[A](tree: A): Code[A] = throw new Error("Code was not lifted by compiler") diff --git a/src/library/scala/reflect/api/StandardNames.scala b/src/library/scala/reflect/api/StandardNames.scala new file mode 100644 index 0000000000..81517d2a6b --- /dev/null +++ b/src/library/scala/reflect/api/StandardNames.scala @@ -0,0 +1,21 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.reflect +package api + +trait StandardNames { self: Universe => + + val nme: AbsTermNames + + abstract class AbsTermNames { + val CONSTRUCTOR: TermName + } + + val tpnme: AbsTypeNames + + abstract class AbsTypeNames { + } +} diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 0a38fb45bf..b8b32477dd 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -476,6 +476,17 @@ trait Trees { self: Universe => */ case class New(tpt: Tree) extends TermTree + /** Factory method for object creation `new tpt(args_1)...(args_n)` + * A `New(t, as)` is expanded to: `(new t).(as)` + */ + def New(tpt: Tree, argss: List[List[Tree]]): Tree = { + assert(!argss.isEmpty) + // todo. we need to expose names in scala.reflect.api +// val superRef: Tree = Select(New(tpt), nme.CONSTRUCTOR) + val superRef: Tree = Select(New(tpt), "") + (superRef /: argss) (Apply) + } + /** Type annotation, eliminated by explicit outer */ case class Typed(expr: Tree, tpt: Tree) extends TermTree @@ -632,10 +643,10 @@ trait Trees { self: Universe => } def TypeTree(tp: Type): TypeTree = TypeTree() setType tp - + /** An empty deferred value definition corresponding to: * val _: _ - * This is used as a placeholder in the `self` parameter Template if there is + * This is used as a placeholder in the `self` parameter Template if there is * no definition of a self value of self type. */ def emptyValDef: ValDef diff --git a/src/library/scala/reflect/api/Universe.scala b/src/library/scala/reflect/api/Universe.scala index 03acbdda2c..a3cec3271b 100755 --- a/src/library/scala/reflect/api/Universe.scala +++ b/src/library/scala/reflect/api/Universe.scala @@ -10,7 +10,8 @@ abstract class Universe extends Symbols with Positions with TreePrinters with AnnotationInfos - with StandardDefinitions { + with StandardDefinitions + with StandardNames { type Position val NoPosition: Position diff --git a/src/library/scala/reflect/macro/Context.scala b/src/library/scala/reflect/macro/Context.scala index d0a2787fdf..3b6f96d7a8 100644 --- a/src/library/scala/reflect/macro/Context.scala +++ b/src/library/scala/reflect/macro/Context.scala @@ -12,4 +12,25 @@ trait Context extends api.Universe { */ def referenceCapturedVariable(id: Ident): Tree + /** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type. + * For instance, given the abstract syntax tree representation of the `x + 1` expression: + * + * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1)))) + * + * The reifier transforms it to the following tree: + * + * $mr.Apply($mr.Select($mr.Ident($mr.freeVar("x", , x), "+"), List($mr.Literal($mr.Constant(1)))))) + * + * The transformation looks mostly straightforward, but it has its tricky parts: + * * Reifier retains symbols and types defined outside the reified tree, however + * locally defined entities get erased and replaced with their original trees + * * Free variables are detected and wrapped in symbols of the type FreeVar + * * Mutable variables that are accessed from a local function are wrapped in refs + * * Since reified trees can be compiled outside of the scope they've been created in, + * special measures are taken to ensure that all freeVars remain visible + * + * Typical usage of this function is to retain some of the trees received/created by a macro + * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime. + */ + def reify(tree: Tree): Tree } diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala index a90a61a9aa..524dc06327 100644 --- a/src/partest/scala/tools/partest/PartestTask.scala +++ b/src/partest/scala/tools/partest/PartestTask.scala @@ -15,10 +15,8 @@ import scala.tools.nsc.io.{ Directory, Path => SPath } import nsc.util.ClassPath import util.PathResolver import scala.tools.ant.sabbus.CompilationPathProperty - import java.io.File import java.lang.reflect.Method - import org.apache.tools.ant.Task import org.apache.tools.ant.types.{Path, Reference, FileSet} import org.apache.tools.ant.types.Commandline.Argument @@ -309,6 +307,16 @@ class PartestTask extends Task with CompilationPathProperty { val antRunner = new scala.tools.partest.nest.AntRunner val antFileManager = antRunner.fileManager + // this is a workaround for https://issues.scala-lang.org/browse/SI-5433 + // when that bug is fixed, this paragraph of code can be safely removed + // we hack into the classloader that will become parent classloader for scalac + // this way we ensure that reflective macro lookup will pick correct Code.lift + val loader = getClass.getClassLoader.asInstanceOf[org.apache.tools.ant.AntClassLoader] + val path = new org.apache.tools.ant.types.Path(getProject()) + val newClassPath = ClassPath.join(nest.PathSettings.srcCodeLib.toString, loader.getClasspath) + path.setPath(newClassPath) + loader.setClassPath(path) + antFileManager.showDiff = showDiff antFileManager.showLog = showLog antFileManager.failed = runFailed diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index 6604bc551d..7aaa7bab00 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -12,6 +12,7 @@ import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io } import scala.tools.nsc.interactive.RangePositions import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter } import scala.tools.nsc.util.{ ClassPath, FakePos } +import scala.tools.nsc.Properties.{ setProp, propOrEmpty } import scala.tools.util.PathResolver import io.Path import java.io.{ File, BufferedReader, PrintWriter, FileReader, Writer, FileWriter, StringWriter } @@ -112,6 +113,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler { try { NestUI.verbose("compiling "+toCompile) NestUI.verbose("with classpath: "+global.classPath.toString) + NestUI.verbose("and java classpath: "+ propOrEmpty("java.class.path")) try new global.Run compile toCompile catch { case FatalError(msg) => diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala index 04f36ffa11..e0a2f65b80 100644 --- a/src/partest/scala/tools/partest/nest/PathSettings.scala +++ b/src/partest/scala/tools/partest/nest/PathSettings.scala @@ -40,6 +40,13 @@ object PathSettings { sys.error("No instrumented.jar found in %s".format(srcSpecLibDir)) } + // Directory /test/files/codelib + lazy val srcCodeLibDir = Directory(srcDir / "codelib") + + lazy val srcCodeLib: File = findJar(srcCodeLibDir, "code") getOrElse { + sys.error("No code.jar found in %s".format(srcCodeLibDir)) + } + // Directory /build lazy val buildDir: Directory = { val bases = testRoot :: testRoot.parents diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala index 7c6dd0848f..5cde63dc81 100644 --- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -53,7 +53,13 @@ class ReflectiveRunner { Array(latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile, latestScalapFile) map (x => io.File(x)) val sepUrls = files map (_.toURL) - val sepLoader = new URLClassLoader(sepUrls, null) + var sepLoader = new URLClassLoader(sepUrls, null) + + // this is a workaround for https://issues.scala-lang.org/browse/SI-5433 + // when that bug is fixed, this paragraph of code can be safely removed + // we hack into the classloader that will become parent classloader for scalac + // this way we ensure that reflective macro lookup will pick correct Code.lift + sepLoader = new URLClassLoader((PathSettings.srcCodeLib +: files) map (_.toURL), null) if (isPartestDebug) println("Loading classes from:\n" + sepUrls.mkString("\n")) diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala index 3e5fe35f9e..fc5792e886 100644 --- a/src/partest/scala/tools/partest/nest/TestFile.scala +++ b/src/partest/scala/tools/partest/nest/TestFile.scala @@ -35,6 +35,10 @@ abstract class TestFile(val kind: String) extends TestFileCommon { if (setOutDir) settings.outputDirs setSingleOutput setOutDirTo.path + // adding code.jar to the classpath (to provide Code.lift services for reification tests) + settings.classpath prepend PathSettings.srcCodeLib.toString + if (propIsSet("java.class.path")) setProp("java.class.path", PathSettings.srcCodeLib.toString + ";" + propOrElse("java.class.path", "")) + // have to catch bad flags somewhere (flags forall (f => settings.processArgumentString(f)._1)) && { settings.classpath append fileManager.CLASSPATH diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 952d99c318..3f2cb16082 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -520,7 +520,9 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor runTestCommon(file, expectFailure = false)((logFile, outDir) => { val dir = file.getParentFile - execTest(outDir, logFile) && diffCheck(compareOutput(dir, logFile)) + // adding code.jar to the classpath (to provide Code.lift services for reification tests) + execTest(outDir, logFile, PathSettings.srcCodeLib.toString) && + diffCheck(compareOutput(dir, logFile)) }) // Apache Ant 1.6 or newer diff --git a/src/partest/scala/tools/partest/utils/CodeTest.scala b/src/partest/scala/tools/partest/utils/CodeTest.scala deleted file mode 100644 index c236d89bbd..0000000000 --- a/src/partest/scala/tools/partest/utils/CodeTest.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala Parallel Testing ** -** / __/ __// _ | / / / _ | (c) 2007-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - - -package scala.tools.partest -package utils - -import scala.reflect.Code -import reflect.runtime.Mirror.ToolBox -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings - -/** Runner for testing code tree liftingg - */ -object CodeTest { - def static[T](code: () => T, args: Array[String] = Array()) = { - println("static: "+code()) - } - - def apply[T](code: Code[T], args: Array[String] = Array()) = { - println("testing: "+code.tree) - println("type is: "+code.manifest.tpe) - val isNullary = code.manifest.tpe.typeSymbol == scala.reflect.mirror.definitions.FunctionClass(0) - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter, args mkString " ") - val ttree = toolbox.typeCheck(code.tree, code.manifest.tpe) - println("result = " + toolbox.showAttributed(ttree, printTypes = true, printIds = false)) - var evaluated = toolbox.runExpr(ttree) - if (evaluated != null && isNullary) { - val applyMeth = evaluated.getClass.getMethod("apply") - evaluated = applyMeth.invoke(evaluated) - } - println("evaluated = "+evaluated) - evaluated - } -} diff --git a/test/files/codelib/code.jar.desired.sha1 b/test/files/codelib/code.jar.desired.sha1 new file mode 100644 index 0000000000..5e7acf3b90 --- /dev/null +++ b/test/files/codelib/code.jar.desired.sha1 @@ -0,0 +1 @@ +5880dd44ee9fedec44fed3f223842e42d8a63959 ?code.jar diff --git a/test/files/pos/t531.scala b/test/files/pos/t531.scala index 02763e08f1..856926de4f 100644 --- a/test/files/pos/t531.scala +++ b/test/files/pos/t531.scala @@ -2,9 +2,9 @@ object Test extends App { import scala.reflect._; def titi = { var truc = 0 - val tata: Code[()=>Unit] = () => { + val tata = Code.lift{() => { truc = 6 - } + }} () } } diff --git a/test/files/pos/t532.scala b/test/files/pos/t532.scala index 32649b1629..f864bbf45e 100644 --- a/test/files/pos/t532.scala +++ b/test/files/pos/t532.scala @@ -2,9 +2,9 @@ object Test extends App { import scala.reflect._; def titi: Unit = { var truc = 0 - val tata: Code[()=>Unit] = () => { + val tata = Code.lift{() => { truc = truc + 6 - } + }} () } } diff --git a/test/files/run/code.check b/test/files/run/code.check deleted file mode 100644 index 9b0351bbf9..0000000000 --- a/test/files/run/code.check +++ /dev/null @@ -1,36 +0,0 @@ -testing: ((x: Int) => x.$plus(ys.length)) -type is: Int => Int -result = ((x: Int) => x.+{(x: )Int}(ys.length{Int}){Int}){Int => Int} -evaluated = -testing: (() => { - val e: Element = new Element("someName"); - e -}) -type is: () => Element -result = (() => { - val e: Element = new Element{Element}{(name: )Element}("someName"{String("someName")}){Element}; - e{Element} -}{Element}){() => Element} -evaluated = Element(someName) -testing: (() => truc.elem = 6) -type is: () => Unit -result = (() => truc.elem{Int} = 6{Int(6)}{Unit}){() => Unit} -evaluated = null -testing: (() => truc.elem = truc.elem.$plus(6)) -type is: () => Unit -result = (() => truc.elem{Int} = truc.elem.+{(x: )Int}(6{Int(6)}){Int}{Unit}){() => Unit} -evaluated = null -testing: (() => new baz.BazElement("someName")) -type is: () => baz.BazElement -result = (() => new baz.BazElement{baz.BazElement}{(name: )baz.BazElement}("someName"{String("someName")}){baz.BazElement}){() => baz.BazElement} -evaluated = BazElement(someName) -testing: ((x: Int) => x.$plus(ys.length)) -type is: Int => Int -result = ((x: Int) => x.+{(x: )Int}(ys.length{Int}){Int}){Int => Int} -evaluated = -static: 2 -testing: (() => x.$plus(1)) -type is: () => Int -result = (() => x.+{(x: )Int}(1{Int(1)}){Int}){() => Int} -evaluated = 2 -1+1 = 2 diff --git a/test/files/run/code.scala b/test/files/run/code.scala deleted file mode 100644 index 162f796c63..0000000000 --- a/test/files/run/code.scala +++ /dev/null @@ -1,60 +0,0 @@ -import scala.tools.partest.utils.CodeTest - -case class Element(name: String) - -object Test extends App { - case class InnerElement(name: String) - def foo[T](ys: List[T]) = { - val fun: reflect.Code[Int => Int] = x => x + ys.length - fun - } - CodeTest(foo(List(2)), args) - CodeTest({() => val e = Element("someName"); e}, args) -// CodeTest({() => val e = InnerElement("someName"); e}, args) // (does not work yet) - def titi() = { - var truc = 0 - CodeTest(() => { - truc = 6 - }, args) - } - def tata(): Unit = { - var truc = 0 - CodeTest(() => { - truc = truc + 6 - }, args) - } - titi() - tata() - new baz.A(args) - - def show() { - def foo[T](ys: List[T]) = { - val fun: reflect.Code[Int => Int] = x => x + ys.length - CodeTest(fun, args) - } - foo(List(1, 2, 3)) - } - - show() - - def evaltest(x: Int) = { - CodeTest.static(() => x + 1, args) - CodeTest(() => x + 1, args) - } - - println("1+1 = "+evaltest(1)) -} - - -package baz { - - case class BazElement(name: String) { } - - class A(args: Array[String]) { - CodeTest(() => new baz.BazElement("someName"), args) - } - -} - - - diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check index 4aeb3ab60c..6f253f5de1 100644 --- a/test/files/run/programmatic-main.check +++ b/test/files/run/programmatic-main.check @@ -7,23 +7,22 @@ superaccessors 5 add super accessors in traits and nested classes pickler 6 serialize symbol tables refchecks 7 reference/override checking, translate nested objects - liftcode 8 reify trees - uncurry 9 uncurry, translate function values to anonymous classes - tailcalls 10 replace tail calls by jumps - specialize 11 @specialized-driven class and method specialization - explicitouter 12 this refs to outer pointers, translate patterns - erasure 13 erase types, add interfaces for traits - lazyvals 14 allocate bitmaps, translate lazy vals into lazified defs - lambdalift 15 move nested functions to top level - constructors 16 move field definitions into constructors - flatten 17 eliminate inner classes - mixin 18 mixin composition - cleanup 19 platform-specific cleanups, generate reflective calls - icode 20 generate portable intermediate code - inliner 21 optimization: do inlining -inlineExceptionHandlers 22 optimization: inline exception handlers - closelim 23 optimization: eliminate uncalled closures - dce 24 optimization: eliminate dead code - jvm 25 generate JVM bytecode - terminal 26 The last phase in the compiler chain + uncurry 8 uncurry, translate function values to anonymous classes + tailcalls 9 replace tail calls by jumps + specialize 10 @specialized-driven class and method specialization + explicitouter 11 this refs to outer pointers, translate patterns + erasure 12 erase types, add interfaces for traits + lazyvals 13 allocate bitmaps, translate lazy vals into lazified defs + lambdalift 14 move nested functions to top level + constructors 15 move field definitions into constructors + flatten 16 eliminate inner classes + mixin 17 mixin composition + cleanup 18 platform-specific cleanups, generate reflective calls + icode 19 generate portable intermediate code + inliner 20 optimization: do inlining +inlineExceptionHandlers 21 optimization: inline exception handlers + closelim 22 optimization: eliminate uncalled closures + dce 23 optimization: eliminate dead code + jvm 24 generate JVM bytecode + terminal 25 The last phase in the compiler chain diff --git a/test/files/run/reify_closure1.scala b/test/files/run/reify_closure1.scala index 825a38dc1d..960f6aec3e 100644 --- a/test/files/run/reify_closure1.scala +++ b/test/files/run/reify_closure1.scala @@ -4,9 +4,9 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { def foo[T](ys: List[T]): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x - } + }} val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure2a.scala b/test/files/run/reify_closure2a.scala index b88bec005d..6c28514c2b 100644 --- a/test/files/run/reify_closure2a.scala +++ b/test/files/run/reify_closure2a.scala @@ -4,9 +4,9 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { def foo(y: Int): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + y - } + }} val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure3a.scala b/test/files/run/reify_closure3a.scala index 6414fa58a3..4444c55ddf 100644 --- a/test/files/run/reify_closure3a.scala +++ b/test/files/run/reify_closure3a.scala @@ -6,9 +6,9 @@ object Test extends App { def foo(y: Int): Int => 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) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure4a.scala b/test/files/run/reify_closure4a.scala index 99e9d82706..886e643a47 100644 --- a/test/files/run/reify_closure4a.scala +++ b/test/files/run/reify_closure4a.scala @@ -6,9 +6,9 @@ object Test extends App { def foo(y: Int): Int => 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) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure5a.scala b/test/files/run/reify_closure5a.scala index 0ac53d5479..20994abff0 100644 --- a/test/files/run/reify_closure5a.scala +++ b/test/files/run/reify_closure5a.scala @@ -4,9 +4,9 @@ import reflect.runtime.Mirror.ToolBox object Test extends App { def foo[T](ys: List[T]): Int => Int = { - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { x + ys.length - } + }} val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure6.scala b/test/files/run/reify_closure6.scala index 54f1791bf2..192c08f701 100644 --- a/test/files/run/reify_closure6.scala +++ b/test/files/run/reify_closure6.scala @@ -7,13 +7,13 @@ object Test extends App { def foo[T](ys: List[T]): Int => Int = { val z = 1 var y = 0 - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { y += 1 q += 1 println("q = " + q) println("y = " + y) x + ys.length * z + q + y - } + }} val reporter = new ConsoleReporter(new Settings) val toolbox = new ToolBox(reporter) diff --git a/test/files/run/reify_closure7.scala b/test/files/run/reify_closure7.scala index 8933df23fa..942c2cda9c 100644 --- a/test/files/run/reify_closure7.scala +++ b/test/files/run/reify_closure7.scala @@ -8,13 +8,13 @@ object Test extends App { def foo[T](ys: List[T]): Int => Int = { val z = 1 var y = 0 - val fun: reflect.Code[Int => Int] = x => { + val fun = reflect.Code.lift{(x: Int) => { y += 1 q += 1 println("q = " + q) println("y = " + y) x + ys.length * z + q + y - } + }} if (clo == null) { val reporter = new ConsoleReporter(new Settings) diff --git a/test/files/run/reify_this.scala b/test/files/run/reify_this.scala index 38ef72b6eb..44a25ae1b6 100644 --- a/test/files/run/reify_this.scala +++ b/test/files/run/reify_this.scala @@ -5,7 +5,7 @@ import scala.tools.nsc.Settings import reflect.runtime.Mirror.ToolBox trait Eval { - def eval(code: Code[_]): Any = eval(code.tree) + def eval(code: Code): Any = eval(code.tree) def eval(tree: Tree): Any = { val settings = new Settings diff --git a/test/files/run/t4875.check b/test/files/run/t4875.check deleted file mode 100644 index f7609d5ca5..0000000000 --- a/test/files/run/t4875.check +++ /dev/null @@ -1,17 +0,0 @@ -Type in expressions to have them evaluated. -Type :help for more information. - -scala> - -scala> import scala.reflect.Code -import scala.reflect.Code - -scala> def codeOf[A](code: Code[A]) = code -codeOf: [A](code: scala.reflect.Code[A])scala.reflect.Code[A] - -scala> codeOf((x: Iterable[_]) => throw new Exception) -res0: scala.reflect.Code[Iterable[_] => Nothing] = Code(tree = ((x: Iterable[Any]) => throw new scala.`package`.Exception()), manifest = scala.Function1[scala.collection.Iterable[Any], Nothing]) - -scala> - -scala> diff --git a/test/files/run/t4875.scala b/test/files/run/t4875.scala deleted file mode 100644 index c17211aede..0000000000 --- a/test/files/run/t4875.scala +++ /dev/null @@ -1,12 +0,0 @@ -import scala.tools.nsc.interpreter._ -import scala.tools.partest.ReplTest - -object Test extends ReplTest { - class M[@specialized T] { } - - def code = """ - |import scala.reflect.Code - |def codeOf[A](code: Code[A]) = code - |codeOf((x: Iterable[_]) => throw new Exception) - """.stripMargin -} 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') 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') 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 a209868820942c1f5b6333d2a0604c7a63b7d0d1 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 10 Feb 2012 03:51:36 -0800 Subject: Failing tests for pending. --- test/pending/pos/t5259.scala | 14 ++++++++++++++ test/pending/pos/t5399.scala | 15 +++++++++++++++ test/pending/pos/t5400.scala | 14 ++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 test/pending/pos/t5259.scala create mode 100644 test/pending/pos/t5399.scala create mode 100644 test/pending/pos/t5400.scala (limited to 'test/pending') diff --git a/test/pending/pos/t5259.scala b/test/pending/pos/t5259.scala new file mode 100644 index 0000000000..317e28a9dc --- /dev/null +++ b/test/pending/pos/t5259.scala @@ -0,0 +1,14 @@ +object DefaultArgBogusTypeMismatch { + + class A[T] + class B { + type T = this.type + def m(implicit a : A[T] = new A[T]) = a + } + + def newB = new B + val a1 = newB.m // Bogus type mismatch + + val stableB = new B + val a2 = stableB.m // OK +} diff --git a/test/pending/pos/t5399.scala b/test/pending/pos/t5399.scala new file mode 100644 index 0000000000..d8c1d5e51c --- /dev/null +++ b/test/pending/pos/t5399.scala @@ -0,0 +1,15 @@ +class Test { + type AnyCyclic = Execute[Task]#CyclicException[_] + + trait Task[T] + + trait Execute[A[_] <: AnyRef] { + class CyclicException[T](val caller: A[T], val target: A[T]) + } + + def convertCyclic(c: AnyCyclic): String = + (c.caller, c.target) match { + case (caller: Task[_], target: Task[_]) => "bazinga!" + } +} + diff --git a/test/pending/pos/t5400.scala b/test/pending/pos/t5400.scala new file mode 100644 index 0000000000..cb4be4bde5 --- /dev/null +++ b/test/pending/pos/t5400.scala @@ -0,0 +1,14 @@ +trait TFn1B { + type In + type Out + type Apply[T <: In] <: Out +} + +trait TFn1[I, O] extends TFn1B { + type In = I + type Out = O +} + +trait >>[F1 <: TFn1[_, _], F2 <: TFn1[_, _]] extends TFn1[F1#In, F2#Out] { + type Apply[T] = F2#Apply[F1#Apply[T]] +} -- cgit v1.2.3 From 7a6fa80937dec6c60efe53c915dfa3ba76b3af87 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 11 Feb 2012 13:16:06 -0800 Subject: Another existential problem down. There is a window of danger when multiple related elements are being typed where something which is conceptually one thing can slip into two things, and those two things can be incompatible with one another. Less mysteriously, c478eb770d fixed this: def f = { object Bob ; Bob } ; val g = f But, it did not fix this: def f = { case class Bob() ; Bob } ; val g = f See test case pos/existentials-harmful.scala for an "in the wild" code example fixed by this commit. The root of the problem was that the getter and the field would each independently derive the same existential type to describe Bob, but those existentials were not the same as one another. This has been the most elusive bug I have ever fixed. I want to cry when I think of how much time I've put into it over the past half decade or so. Unfortunately the way the repl works it is particularly good at eliciting those grotesque found/required error messages and so I was never able to let the thing go. There is still a cosmetic issue (from the last commit really) where compound types wind up with repeated parents. Closes SI-1195, SI-1201. --- .../tools/nsc/typechecker/MethodSynthesis.scala | 43 ++++++++----- test/files/neg/t935.check | 5 +- test/files/pos/existentials-harmful.scala | 54 ++++++++++++++++ test/files/pos/existentials.scala | 9 +++ test/files/run/existentials3.check | 22 +++++++ test/files/run/existentials3.scala | 73 ++++++++++++++++++++++ test/files/run/repl-existentials.check | 63 ------------------- test/files/run/repl-existentials.scala | 31 --------- test/files/run/t1195.check | 6 ++ test/files/run/t1195.scala | 26 ++++++++ test/pending/pos/existentials-harmful.scala | 54 ---------------- 11 files changed, 222 insertions(+), 164 deletions(-) create mode 100644 test/files/pos/existentials-harmful.scala create mode 100644 test/files/pos/existentials.scala create mode 100644 test/files/run/existentials3.check create mode 100644 test/files/run/existentials3.scala delete mode 100644 test/files/run/repl-existentials.check delete mode 100644 test/files/run/repl-existentials.scala create mode 100644 test/files/run/t1195.check create mode 100644 test/files/run/t1195.scala delete mode 100644 test/pending/pos/existentials-harmful.scala (limited to 'test/pending') diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 0c32ff32c0..915d7a98db 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -326,22 +326,35 @@ trait MethodSynthesis { super.validate() } - // keep type tree of original abstract field - private def fixTypeTree(dd: DefDef): DefDef = { - dd.tpt match { - case tt: TypeTree if dd.rhs == EmptyTree => - tt setOriginal tree.tpt - case tpt => - tpt setPos tree.tpt.pos.focus - } - dd - } override def derivedTree: DefDef = { - fixTypeTree { - DefDef(derivedSym, - if (mods.isDeferred) EmptyTree - else gen.mkCheckInit(fieldSelection) - ) + // For existentials, don't specify a type for the getter, even one derived + // from the symbol! This leads to incompatible existentials for the field and + // the getter. Let the typer do all the work. You might think "why only for + // existentials, why not always," and you would be right, except: a single test + // fails, but it looked like some work to deal with it. Test neg/t0606.scala + // starts compiling (instead of failing like it's supposed to) because the typer + // expects to be able to identify escaping locals in typedDefDef, and fails to + // spot that brand of them. In other words it's an artifact of the implementation. + val tpt = derivedSym.tpe.finalResultType match { + case ExistentialType(_, _) => TypeTree() + case tp => TypeTree(tp) + } + tpt setPos focusPos(derivedSym.pos) + // keep type tree of original abstract field + if (mods.isDeferred) + tpt setOriginal tree.tpt + + // TODO - reconcile this with the DefDef creator in Trees (which + // at this writing presented no way to pass a tree in for tpt.) + atPos(derivedSym.pos) { + DefDef( + Modifiers(derivedSym.flags), + derivedSym.name.toTermName, + Nil, + Nil, + tpt, + if (mods.isDeferred) EmptyTree else gen.mkCheckInit(fieldSelection) + ) setSymbol derivedSym } } } diff --git a/test/files/neg/t935.check b/test/files/neg/t935.check index af634a2630..8b73700187 100644 --- a/test/files/neg/t935.check +++ b/test/files/neg/t935.check @@ -4,4 +4,7 @@ t935.scala:7: error: type arguments [Test3.B] do not conform to class E's type p t935.scala:13: error: type arguments [Test4.B] do not conform to class E's type parameter bounds [T <: String] val b: String @E[B](new B) = "hi" ^ -two errors found +t935.scala:13: error: type arguments [Test4.B] do not conform to class E's type parameter bounds [T <: String] + val b: String @E[B](new B) = "hi" + ^ +three errors found diff --git a/test/files/pos/existentials-harmful.scala b/test/files/pos/existentials-harmful.scala new file mode 100644 index 0000000000..8722852e8a --- /dev/null +++ b/test/files/pos/existentials-harmful.scala @@ -0,0 +1,54 @@ +// a.scala +// Mon Jul 11 14:18:26 PDT 2011 + +object ExistentialsConsideredHarmful { + class Animal(val name: String) + object Dog extends Animal("Dog") + object Sheep extends Animal("Sheep") + + trait Tools[A] { + def shave(a: A): A + } + def tools[A](a: A): Tools[A] = null // dummy + + case class TransportBox[A <: Animal](animal: A, tools: Tools[A]) { + def label: String = animal.name + } + + // 1. + def carry[A <: Animal](box: TransportBox[A]): Unit = { + println(box.animal.name+" got carried away") + } + + val aBox = + if (math.random < 0.5) + TransportBox(Dog, tools(Dog)) + else + TransportBox(Sheep, tools(Sheep)) + + // 2. + //aBox.tools.shave(aBox.animal) + + // Use pattern match to avoid opening the existential twice + aBox match { + case TransportBox(animal, tools) => tools.shave(animal) + } + + abstract class BoxCarrier[R <: Animal](box: TransportBox[R]) { + def speed: Int + + def talkToAnimal: Unit = println("The carrier says hello to"+box.animal.name) + } + + // 3. + //val bc = new BoxCarrier(aBox) { + + // Use pattern match to avoid opening the existential twice + // Type annotation on bc is required ... possible compiler bug? + // val bc : BoxCarrier[_ <: Animal] = aBox match { + val bc = aBox match { + case tb : TransportBox[a] => new BoxCarrier(tb) { + def speed: Int = 12 + } + } +} diff --git a/test/files/pos/existentials.scala b/test/files/pos/existentials.scala new file mode 100644 index 0000000000..c51f60b546 --- /dev/null +++ b/test/files/pos/existentials.scala @@ -0,0 +1,9 @@ +class A { + def f() = { case class Bob(); Bob } + + val quux0 = f() + def quux1 = f() + + val bippy0 = f _ + def bippy1 = f _ +} diff --git a/test/files/run/existentials3.check b/test/files/run/existentials3.check new file mode 100644 index 0000000000..41dc1f767c --- /dev/null +++ b/test/files/run/existentials3.check @@ -0,0 +1,22 @@ +_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.ScalaObject with scala.Product with scala.Serializable] with scala.ScalaObject with scala.Serializable with java.lang.Object +_ <: Object with Test$ToS with scala.ScalaObject with scala.Product with scala.Serializable +Object with Test$ToS with scala.ScalaObject +Object with Test$ToS with scala.ScalaObject +Object with Test$ToS with scala.ScalaObject +scala.Function0[Object with Test$ToS with scala.ScalaObject] +scala.Function0[Object with Test$ToS with scala.ScalaObject] +_ <: Object with _ <: Object with Object with Test$ToS with scala.ScalaObject +_ <: Object with _ <: Object with _ <: Object with Test$ToS with scala.ScalaObject +scala.collection.immutable.List[Object with scala.collection.Seq[Int] with scala.ScalaObject] +scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int] with scala.ScalaObject] +_ <: scala.runtime.AbstractFunction0[_ <: Object with Test$ToS with scala.ScalaObject with scala.Product with scala.Serializable] with scala.ScalaObject with scala.Serializable with java.lang.Object +_ <: Object with Test$ToS with scala.ScalaObject with scala.Product with scala.Serializable +Object with Test$ToS with scala.ScalaObject +Object with Test$ToS with scala.ScalaObject +Object with Test$ToS with scala.ScalaObject +scala.Function0[Object with Test$ToS with scala.ScalaObject] +scala.Function0[Object with Test$ToS with scala.ScalaObject] +_ <: Object with _ <: Object with Object with Test$ToS with scala.ScalaObject +_ <: Object with _ <: Object with _ <: Object with Test$ToS with scala.ScalaObject +scala.collection.immutable.List[Object with scala.collection.Seq[Int] with scala.ScalaObject] +scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int] with scala.ScalaObject] diff --git a/test/files/run/existentials3.scala b/test/files/run/existentials3.scala new file mode 100644 index 0000000000..bb80d366cc --- /dev/null +++ b/test/files/run/existentials3.scala @@ -0,0 +1,73 @@ +object Test { + trait ToS { final override def toString = getClass.getName } + + def f1 = { case class Bar() extends ToS; Bar } + def f2 = { case class Bar() extends ToS; Bar() } + def f3 = { class Bar() extends ToS; object Bar extends ToS; Bar } + def f4 = { class Bar() extends ToS; new Bar() } + def f5 = { object Bar extends ToS; Bar } + def f6 = { () => { object Bar extends ToS ; Bar } } + def f7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f } + + def f8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } } + def f9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } } + + def f10 = { class A { type T1 } ; List[A#T1]() } + def f11 = { abstract class A extends Seq[Int] ; List[A]() } + def f12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() } + + val g1 = { case class Bar() extends ToS; Bar } + val g2 = { case class Bar() extends ToS; Bar() } + val g3 = { class Bar() extends ToS; object Bar extends ToS; Bar } + val g4 = { class Bar() extends ToS; new Bar() } + val g5 = { object Bar extends ToS; Bar } + val g6 = { () => { object Bar extends ToS ; Bar } } + val g7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f } + + val g8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } } + val g9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } } + + val g10 = { class A { type T1 } ; List[A#T1]() } + val g11 = { abstract class A extends Seq[Int] ; List[A]() } + val g12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() } + + def m[T: Manifest](x: T) = println(manifest[T]) + + // manifests don't work for f10/g10 + def main(args: Array[String]): Unit = { + m(f1) + m(f2) + m(f3) + m(f4) + m(f5) + m(f6) + m(f7) + m(f8) + m(f9) + // m(f10) + m(f11) + m(f12) + m(g1) + m(g2) + m(g3) + m(g4) + m(g5) + m(g6) + m(g7) + m(g8) + m(g9) + // m(g10) + m(g11) + m(g12) + } +} + +object Misc { + trait Bippy { def bippy = "I'm Bippy!" } + object o1 { + def f1 = { trait A extends Seq[U forSome { type U <: Bippy }] ; abstract class B extends A ; trait C extends B ; (null: C) } + def f2 = f1.head.bippy + } + def g1 = o1.f1 _ + def g2 = o1.f2 _ +} diff --git a/test/files/run/repl-existentials.check b/test/files/run/repl-existentials.check deleted file mode 100644 index 7093b428e8..0000000000 --- a/test/files/run/repl-existentials.check +++ /dev/null @@ -1,63 +0,0 @@ -Type in expressions to have them evaluated. -Type :help for more information. - -scala> trait ToS { final override def toString = getClass.getName } -defined trait ToS - -scala> - -scala> // def f1 = { case class Bar() extends ToS; Bar } - -scala> def f2 = { case class Bar() extends ToS; Bar() } -f2: Bar forSome { type Bar <: Object with ToS with ScalaObject with Product with Serializable{def copy(): Bar} } - -scala> def f3 = { class Bar() extends ToS; object Bar extends ToS; Bar } -f3: Object with ToS with ScalaObject - -scala> def f4 = { class Bar() extends ToS; new Bar() } -f4: Object with ToS with ScalaObject - -scala> def f5 = { object Bar extends ToS; Bar } -f5: Object with ToS with ScalaObject - -scala> def f6 = { () => { object Bar extends ToS ; Bar } } -f6: () => Object with ToS with ScalaObject - -scala> def f7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f } -f7: () => Object with ToS with ScalaObject - -scala> - -scala> // def f8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } } - -scala> // def f9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } } - -scala> - -scala> def f10 = { class A { type T1 } ; List[A#T1]() } -f10: List[Object with ScalaObject{type T1}#T1] - -scala> def f11 = { abstract class A extends Seq[Int] ; List[A]() } -f11: List[Object with Seq[Int] with ScalaObject] - -scala> def f12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() } -f12: List[Object with Seq[U forSome { type U <: Int }] with ScalaObject] - -scala> - -scala> trait Bippy { def bippy = "I'm Bippy!" } -defined trait Bippy - -scala> object o1 { - def f1 = { trait A extends Seq[U forSome { type U <: Bippy }] ; abstract class B extends A ; trait C extends B ; (null: C) } - def f2 = f1.head.bippy -} -defined module o1 - -scala> o1.f1 _ -res0: () => C forSome { type C <: Object with A with ScalaObject; type A <: Object with Seq[U forSome { type U <: Bippy }] } = - -scala> o1.f2 _ -res1: () => String = - -scala> diff --git a/test/files/run/repl-existentials.scala b/test/files/run/repl-existentials.scala deleted file mode 100644 index 31034b49a0..0000000000 --- a/test/files/run/repl-existentials.scala +++ /dev/null @@ -1,31 +0,0 @@ -import scala.tools.partest.ReplTest - -object Test extends ReplTest { - def code = """ -trait ToS { final override def toString = getClass.getName } - -// def f1 = { case class Bar() extends ToS; Bar } -def f2 = { case class Bar() extends ToS; Bar() } -def f3 = { class Bar() extends ToS; object Bar extends ToS; Bar } -def f4 = { class Bar() extends ToS; new Bar() } -def f5 = { object Bar extends ToS; Bar } -def f6 = { () => { object Bar extends ToS ; Bar } } -def f7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f } - -// def f8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } } -// def f9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } } - -def f10 = { class A { type T1 } ; List[A#T1]() } -def f11 = { abstract class A extends Seq[Int] ; List[A]() } -def f12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() } - -trait Bippy { def bippy = "I'm Bippy!" } -object o1 { - def f1 = { trait A extends Seq[U forSome { type U <: Bippy }] ; abstract class B extends A ; trait C extends B ; (null: C) } - def f2 = f1.head.bippy -} -o1.f1 _ -o1.f2 _ - -""".trim -} diff --git a/test/files/run/t1195.check b/test/files/run/t1195.check new file mode 100644 index 0000000000..dc521fb8ca --- /dev/null +++ b/test/files/run/t1195.check @@ -0,0 +1,6 @@ +_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.ScalaObject with scala.Product with scala.Serializable] with scala.ScalaObject with scala.Serializable with java.lang.Object +_ <: Object with scala.ScalaObject with scala.Product with scala.Serializable +Object with scala.ScalaObject with scala.Product with scala.Serializable +_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.ScalaObject with scala.Product with scala.Serializable] with scala.ScalaObject with scala.Serializable with java.lang.Object +_ <: Object with scala.ScalaObject with scala.Product with scala.Serializable +Object with scala.ScalaObject with scala.Product with scala.Serializable diff --git a/test/files/run/t1195.scala b/test/files/run/t1195.scala new file mode 100644 index 0000000000..81ef5bdb0e --- /dev/null +++ b/test/files/run/t1195.scala @@ -0,0 +1,26 @@ +object Test { + def f() = { case class Bar(x: Int); Bar } + def g() = { case class Bar(x: Int); Bar(5) } + def h() = { case object Bar ; Bar } + + val f1 = f() + val g1 = g() + val h1 = h() + + def m[T: Manifest](x: T) = println(manifest[T]) + + def main(args: Array[String]): Unit = { + m(f) + m(g) + m(h) + m(f1) + m(g1) + m(h1) + } +} + +class A1[T] { + class B1[U] { + def f = { case class D(x: Int) extends A1[String] ; new D(5) } + } +} diff --git a/test/pending/pos/existentials-harmful.scala b/test/pending/pos/existentials-harmful.scala deleted file mode 100644 index 8722852e8a..0000000000 --- a/test/pending/pos/existentials-harmful.scala +++ /dev/null @@ -1,54 +0,0 @@ -// a.scala -// Mon Jul 11 14:18:26 PDT 2011 - -object ExistentialsConsideredHarmful { - class Animal(val name: String) - object Dog extends Animal("Dog") - object Sheep extends Animal("Sheep") - - trait Tools[A] { - def shave(a: A): A - } - def tools[A](a: A): Tools[A] = null // dummy - - case class TransportBox[A <: Animal](animal: A, tools: Tools[A]) { - def label: String = animal.name - } - - // 1. - def carry[A <: Animal](box: TransportBox[A]): Unit = { - println(box.animal.name+" got carried away") - } - - val aBox = - if (math.random < 0.5) - TransportBox(Dog, tools(Dog)) - else - TransportBox(Sheep, tools(Sheep)) - - // 2. - //aBox.tools.shave(aBox.animal) - - // Use pattern match to avoid opening the existential twice - aBox match { - case TransportBox(animal, tools) => tools.shave(animal) - } - - abstract class BoxCarrier[R <: Animal](box: TransportBox[R]) { - def speed: Int - - def talkToAnimal: Unit = println("The carrier says hello to"+box.animal.name) - } - - // 3. - //val bc = new BoxCarrier(aBox) { - - // Use pattern match to avoid opening the existential twice - // Type annotation on bc is required ... possible compiler bug? - // val bc : BoxCarrier[_ <: Animal] = aBox match { - val bc = aBox match { - case tb : TransportBox[a] => new BoxCarrier(tb) { - def speed: Int = 12 - } - } -} -- 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') 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') 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') 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') 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') 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