diff options
16 files changed, 150 insertions, 272 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index a60a2c2306..6ec111cf7c 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -53,7 +53,7 @@ trait Errors extends Traces { // not exactly an error generator, but very related // and I dearly wanted to push it away from Macros.scala private def checkConforms(slot: String, rtpe: Type, atpe: Type) = { - val verbose = macroDebugVerbose || settings.explaintypes.value + val verbose = macroDebugVerbose def check(rtpe: Type, atpe: Type): Boolean = { def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true } @@ -70,9 +70,12 @@ trait Errors extends Traces { if (verbose) withTypesExplained(check(rtpe, atpe)) else check(rtpe, atpe) if (!ok) { - if (!macroDebugVerbose) - explainTypes(rtpe, atpe) - compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, abbreviateCoreAliases(rtpe.toString), abbreviateCoreAliases(atpe.toString))) + if (!verbose) explainTypes(rtpe, atpe) + val msg = { + val ss = Seq(rtpe, atpe) map (this abbreviateCoreAliases _.toString) + s"type mismatch for $slot: ${ss(0)} does not conform to ${ss(1)}" + } + compatibilityError(msg) } } @@ -106,8 +109,8 @@ trait Errors extends Traces { def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) = compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value)) - def MacroImplTparamInstantiationError(atparams: List[Symbol], ex: NoInstance) = - compatibilityError( - "type parameters "+(atparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+ - ex.getMessage) -}
\ No newline at end of file + def MacroImplTparamInstantiationError(atparams: List[Symbol], e: NoInstance) = { + val badps = atparams map (_.defString) mkString ", " + compatibilityError(f"type parameters $badps cannot be instantiated%n${e.getMessage}") + } +} diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala index f950b13b78..cdde019cd0 100644 --- a/src/library/scala/concurrent/Promise.scala +++ b/src/library/scala/concurrent/Promise.scala @@ -82,7 +82,7 @@ trait Promise[T] { /** Completes the promise with a value. * - * @param v The value to complete the promise with. + * @param value The value to complete the promise with. * * $promiseCompletion */ @@ -98,7 +98,7 @@ trait Promise[T] { /** Completes the promise with an exception. * - * @param t The throwable to complete the promise with. + * @param cause The throwable to complete the promise with. * * $allowedThrowables * diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala index e6f314b712..4182b7d0ba 100644 --- a/src/reflect/scala/reflect/api/Importers.scala +++ b/src/reflect/scala/reflect/api/Importers.scala @@ -9,7 +9,7 @@ package api * ''Note: this trait should typically be used only rarely.'' * * Reflection artifacts, such as [[scala.reflect.api.Symbols Symbols]] and [[scala.reflect.api.Types Types]], - * are contained in [[scala.reflect.api.Universes Universe]]s. Typically all processing happens + * are contained in [[scala.reflect.api.Universe Universe]]s. Typically all processing happens * within a single `Universe` (e.g. a compile-time macro `Universe` or a runtime reflection `Universe`), but sometimes * there is a need to migrate artifacts from one `Universe` to another. For example, runtime compilation works by * importing runtime reflection trees into a runtime compiler universe, compiling the importees and exporting the @@ -101,4 +101,4 @@ trait Importers { self: Universe => */ def importPosition(pos: from.Position): Position } -}
\ No newline at end of file +} diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala index ef6f4c2920..49bdd69a8b 100644 --- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala +++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala @@ -44,33 +44,78 @@ class JavapClass( val (flags, upgraded) = upgrade(options) import flags.{ app, fun, help, raw } val targets = if (fun && !help) FunFinder(loader, intp).funs(claases) else claases - if (help || claases.isEmpty) List(JpResult(JavapTool.helper(printWriter))) - else if (targets.isEmpty) List(JpResult("No anonfuns found.")) - else tool(raw, upgraded)(targets map (claas => claas -> bytesFor(claas, app))) + if (help || claases.isEmpty) + List(JpResult(JavapTool.helper(printWriter))) + else if (targets.isEmpty) + List(JpResult("No anonfuns found.")) + else + tool(raw, upgraded)(targets map (claas => targeted(claas, app))) } /** Cull our tool options. */ - private def upgrade(options: Seq[String]): (ToolArgs, Seq[String]) = ToolArgs fromArgs options match { - case (t,s) if s.nonEmpty => (t,s) - case (t,s) => (t, JavapTool.DefaultOptions) - } + private def upgrade(options: Seq[String]): (ToolArgs, Seq[String]) = + ToolArgs fromArgs options match { + case (t, s) if s.nonEmpty => (t, s) + case (t, s) => (t, JavapTool.DefaultOptions) + } + + /** Associate the requested path with a possibly failed or empty array of bytes. */ + private def targeted(path: String, app: Boolean): (String, Try[Array[Byte]]) = + bytesFor(path, app) match { + case Success((target, bytes)) => (target, Try(bytes)) + case f: Failure[_] => (path, Failure(f.exception)) + } /** Find bytes. Handle "-", "-app", "Foo#bar" (by ignoring member), "#bar" (by taking "bar"). */ private def bytesFor(path: String, app: Boolean) = Try { def last = intp.get.mostRecentVar // fail if no intp - def req = if (path == "-") last else { - val s = path.splitHashMember - if (s._1.nonEmpty) s._1 - else s._2 getOrElse "#" + def req = path match { + case "-" => last + case HashSplit(prefix, member) => + if (prefix != null) prefix + else if (member != null) member + else "#" + } + val targetedBytes = if (app) findAppBody(req) else (req, findBytes(req)) + if (targetedBytes._2.isEmpty) throw new FileNotFoundException(s"Could not find class bytes for '$path'") + targetedBytes + } + + private def findAppBody(path: String): (String, Array[Byte]) = { + // is this new style delayedEndpoint? then find it. + // the name test is naive. could add $mangled path. + // assumes only the first match is of interest (because only one endpoint is generated). + def findNewStyle(bytes: Array[Byte]) = { + import scala.tools.asm.ClassReader + import scala.tools.asm.tree.ClassNode + import PartialFunction.cond + import JavaConverters._ + val rdr = new ClassReader(bytes) + val nod = new ClassNode + rdr.accept(nod, 0) + //foo/Bar.delayedEndpoint$foo$Bar$1 + val endpoint = "delayedEndpoint".r.unanchored + def isEndPoint(s: String) = (s contains '$') && cond(s) { case endpoint() => true } + nod.methods.asScala collectFirst { case m if isEndPoint(m.name) => m.name } } - def asAppBody(s: String) = { - val (cls, fix) = s.splitSuffix - s"${cls}$$delayedInit$$body${fix}" + // try new style, and add foo#delayedEndpoint$bar$1 to filter on the endpoint + def asNewStyle(bytes: Array[Byte]) = Some(bytes) filter (_.nonEmpty) flatMap { bs => + findNewStyle(bs) map (n => (s"$path#$n", bs)) } - def todo = if (app) asAppBody(req) else req - val bytes = findBytes(todo) - if (bytes.isEmpty) throw new FileNotFoundException(s"Could not find class bytes for '${path}'") - else bytes + // use old style, and add foo# to filter on apply method + def asOldStyle = { + def asAppBody(s: String) = { + val (cls, fix) = s.splitSuffix + s"${cls}$$delayedInit$$body${fix}" + } + val oldStyle = asAppBody(path) + val oldBytes = findBytes(oldStyle) + if (oldBytes.nonEmpty) (s"$oldStyle#", oldBytes) + else (path, oldBytes) + } + + val pathBytes = findBytes(path) + asNewStyle(pathBytes) getOrElse asOldStyle } def findBytes(path: String): Array[Byte] = tryFile(path) getOrElse tryClass(path) @@ -496,6 +541,7 @@ object JavapClass { intp: Option[IMain] = None ) = new JavapClass(loader, printWriter, intp) + val HashSplit = "(.*?)(?:#([^#]*))?".r // We enjoy flexibility in specifying either a fully-qualified class name com.acme.Widget // or a resource path com/acme/Widget.class; but not widget.out implicit class MaybeClassLike(val s: String) extends AnyVal { diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Arrows.scala b/src/scalap/scala/tools/scalap/scalax/rules/Arrows.scala deleted file mode 100644 index f8761ca0ed..0000000000 --- a/src/scalap/scala/tools/scalap/scalax/rules/Arrows.scala +++ /dev/null @@ -1,37 +0,0 @@ -package scala.tools.scalap -package scalax -package rules - -trait Arrows extends UnitFunctors { - type Arr[-A, +B] <: Arrow[A, B] - type M[+B] = Arr[Nothing, B] - - def arrow[A, B](f : A => B) : Arr[A, B] - def diag[A] = arrow[A, (A, A)] { a => (a, a) } - - override def unit[B](b : => B) : M[B] = arrow { any : Any => b } - - trait Arrow[-A, +B] extends Functor[B] { this : Arr[A, B] => - - def map[C](f : B => C) = comp(arrow(f)) - def comp[C](bc : => Arr[B, C]) : Arr[A, C] - def fst[C] : Arr[(A, C), (B, C)] - } -} - -trait ApplicativeArrows extends Arrows { - type Arr[-A, +B] <: ApplicativeArrow[A, B] - - def app[A, B] : Arr[(Arr[A, B], A), B] - - trait ApplicativeArrow[-A, +B] extends Arrow[A, B] { self : Arr[A, B] => - def flatMap[SubA <: A, C](f : B => Arr[SubA, C]) : Arr[SubA, C] = - diag[SubA].comp(map(f).fst[SubA]).comp(app[SubA, C]) - } -} - -trait ArrowMonads extends ApplicativeArrows with Monads { - type Arr[-A, +B] <: ApplicativeArrow[A, B] with Monad[B] - - override def unit[A](a : => A) : M[A] = arrow[Unit, A](Unit => a) -} diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Functors.scala b/src/scalap/scala/tools/scalap/scalax/rules/Functors.scala deleted file mode 100644 index aa852c1e63..0000000000 --- a/src/scalap/scala/tools/scalap/scalax/rules/Functors.scala +++ /dev/null @@ -1,81 +0,0 @@ -// ----------------------------------------------------------------------------- -// -// Scalax - The Scala Community Library -// Copyright (c) 2005-8 The Scalax Project. All rights reserved. -// -// The primary distribution site is http://scalax.scalaforge.org/ -// -// This software is released under the terms of the Revised BSD License. -// There is NO WARRANTY. See the file LICENSE for the full text. -// -// ----------------------------------------------------------------------------- - -package scala.tools.scalap -package scalax -package rules - -trait Functor[+A] { - type M[+A] <: Functor[A] - def map[B](f : A => B) : M[B] -} - -trait Filter[+A] { - type M[+A] <: Filter[A] - def filter(f : A => Boolean) : M[A] -} - -trait Plus[+A] { - type M[+A] <: Plus[A] - def plus[B >: A](other : => M[B]) : M[B] -} - -trait OrElse[+A] { - type M[+A] <: OrElse[A] - def orElse[B >: A](other : => M[B]) : M[B] -} - -trait Units { - type M[+A] - def unit : M[Unit] - def unit[A](a : => A) : M[A] -} - -trait Zero { - type M[+A] - def zero : M[Nothing] -} - -trait Functors { - type M[+A] <: Functor[A] - - trait Functor[+A] extends rules.Functor[A] { this : M[A] => - type M[+A] = Functors.this.M[A] - } - - trait ZeroFunctor extends Functor[Nothing] { this : M[Nothing] => - override def map[B](f : Nothing => B) : M[B] = this - def filter(f : Nothing => Boolean) : M[Nothing] = this - def plus[B](other : => M[B]) : M[B] = other - def orElse[B](other : => M[B]) : M[B] = other - } -} - -/** One of the 'unit' definitions must be overridden in concrete subclasses */ -trait UnitFunctors extends Units with Functors { - def unit : M[Unit] = unit(()) - def unit[A](a : => A) : M[A] = unit map { Unit => a } -} - - -trait Monoidals extends UnitFunctors { - type M[+A] <: Monoidal[A] - - implicit def app[A, B](fab : M[A => B]) = (fa : M[A]) => fa applyTo fab - implicit def appUnit[A, B](a2b : A => B) = app(unit(a2b)) - - /** One of 'and' and 'applyTo' definitions must be overridden in concrete subclasses */ - trait Monoidal[+A] extends Functor[A] { self : M[A] => - def and[B](fb : => M[B]) : M[(A, B)] = ((a : A) => (b : B) => (a, b))(this)(fb) - def applyTo[B](fab : M[A => B]) : M[B] = fab and this map { case (f, a) => f(a) } - } -} diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Input.scala b/src/scalap/scala/tools/scalap/scalax/rules/Input.scala deleted file mode 100644 index 370eb0d054..0000000000 --- a/src/scalap/scala/tools/scalap/scalax/rules/Input.scala +++ /dev/null @@ -1,68 +0,0 @@ -// ----------------------------------------------------------------------------- -// -// Scalax - The Scala Community Library -// Copyright (c) 2005-8 The Scalax Project. All rights reserved. -// -// The primary distribution site is http://scalax.scalaforge.org/ -// -// This software is released under the terms of the Revised BSD License. -// There is NO WARRANTY. See the file LICENSE for the full text. -// -// ----------------------------------------------------------------------------- - -package scala.tools.scalap -package scalax -package rules - -trait Input[+A] extends Iterable[A] { - - def next : Result[Input[A], A, Nothing] - def index : Int - - def iterator = new Iterator[A] { - private var input : Input[A] = Input.this - private var result = input.next - - def hasNext = result != Failure - def next = { - val Success(input, value) = result - this.input = input - this.result = input.next - value - } - } -} - - -class ArrayInput[A](val array : Array[A], val index : Int) extends Input[A] { - def this(array : Array[A]) = this(array, 0) - - lazy val next : Result[ArrayInput[A], A, Nothing] = if (index >= array.length) Failure - else Success(new ArrayInput[A](array, index + 1), array(index)) - - override lazy val toString = this.iterator.mkString("\"", "", "\"") -} - - -class IterableInput[A](iterator : Iterator[A], val index : Int) extends Input[A] { - def this(iterable : Iterable[A]) = this(iterable.iterator, 0) - - lazy val next : Result[IterableInput[A], A, Nothing] = if (!iterator.hasNext) Failure - else Success(new IterableInput(iterator, index + 1), iterator.next) - - override lazy val toString = this.iterator.mkString("\"", "", "\"") -} - - -/** View one type of input as another based on a transformation rule */ -class View[A, B]( - transform : Input[A] => Result[Input[A], B, Nothing], - val input : Input[A], - val index : Int) - extends Input[B] { - - def next : Result[Input[B], B, Nothing] = transform(input) match { - case Success(context, b) => Success(new View(transform, context, index + 1), b) - case _ => Failure - } -} diff --git a/src/scalap/scala/tools/scalap/scalax/rules/Monad.scala b/src/scalap/scala/tools/scalap/scalax/rules/Monad.scala deleted file mode 100644 index 639c414675..0000000000 --- a/src/scalap/scala/tools/scalap/scalax/rules/Monad.scala +++ /dev/null @@ -1,46 +0,0 @@ -// ----------------------------------------------------------------------------- -// -// Scalax - The Scala Community Library -// Copyright (c) 2005-8 The Scalax Project. All rights reserved. -// -// The primary distribution site is http://scalax.scalaforge.org/ -// -// This software is released under the terms of the Revised BSD License. -// There is NO WARRANTY. See the file LICENSE for the full text. -// -// ----------------------------------------------------------------------------- - -package scala.tools.scalap -package scalax -package rules - -trait Monad[+A] extends Functor[A] { - type M[+A] <: Monad[A] - def flatMap[B](f : A => M[B]) : M[B] -} - -trait Monads extends UnitFunctors { - type M[+A] <: Monad[A] - - trait Monad[+A] extends Functor[A] with rules.Monad[A] { this : M[A] => - def map[B](f : A => B) = flatMap { a => unit(f(a)) } - } - - trait ZeroMonad extends Monad[Nothing] with ZeroFunctor { this : M[Nothing] => - def flatMap[B](f : Nothing => M[B]) : M[B] = this - } -} - - -trait StateReader extends Monads { - type S - - def get : M[S] - def read[A](f : S => A) : M[A] - def set(s : => S) : M[S] - def update(f : S => S) : M[S] -} - - - - diff --git a/src/scalap/scala/tools/scalap/scalax/rules/package.scala b/src/scalap/scala/tools/scalap/scalax/rules/package.scala deleted file mode 100644 index b1cc18f90b..0000000000 --- a/src/scalap/scala/tools/scalap/scalax/rules/package.scala +++ /dev/null @@ -1,9 +0,0 @@ -package scala.tools.scalap -package scalax - -package object rules { - implicit lazy val higherKinds = scala.language.higherKinds - implicit lazy val postfixOps = scala.language.postfixOps - implicit lazy val implicitConversions = scala.language.implicitConversions - implicit lazy val reflectiveCalls = scala.language.reflectiveCalls -} diff --git a/test/files/neg/t6123-explaintypes-macros.check b/test/files/neg/t6123-explaintypes-macros.check new file mode 100644 index 0000000000..ebcb8069d5 --- /dev/null +++ b/test/files/neg/t6123-explaintypes-macros.check @@ -0,0 +1,9 @@ +c.universe.Expr[Any]* <: c.universe.Expr[String]*? +false +BadMac_2.scala:6: error: macro implementation has wrong shape: + required: (c: scala.reflect.macros.Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] + found : (c: scala.reflect.macros.Context)(format: c.Expr[String], params: c.Expr[String]*): c.Expr[Unit] +type mismatch for parameter params: c.Expr[Any]* does not conform to c.Expr[String]* + def printf(format: String, params: Any*): Unit = macro printf_impl + ^ +one error found diff --git a/test/files/pos/t6123-explaintypes-macros.flags b/test/files/neg/t6123-explaintypes-macros/BadMac_2.flags index b36707c7cf..b36707c7cf 100644 --- a/test/files/pos/t6123-explaintypes-macros.flags +++ b/test/files/neg/t6123-explaintypes-macros/BadMac_2.flags diff --git a/test/files/neg/t6123-explaintypes-macros/BadMac_2.scala b/test/files/neg/t6123-explaintypes-macros/BadMac_2.scala new file mode 100644 index 0000000000..38b8e24444 --- /dev/null +++ b/test/files/neg/t6123-explaintypes-macros/BadMac_2.scala @@ -0,0 +1,8 @@ +import scala.language.experimental.macros +import scala.reflect.macros.Context + +// explain some macro types to me +object BadMac { + def printf(format: String, params: Any*): Unit = macro printf_impl + def printf_impl(c: Context)(format: c.Expr[String], params: c.Expr[String]*): c.Expr[Unit] = ??? +} diff --git a/test/files/neg/t6123-explaintypes-macros/Macros.flags b/test/files/neg/t6123-explaintypes-macros/Macros.flags new file mode 100644 index 0000000000..b36707c7cf --- /dev/null +++ b/test/files/neg/t6123-explaintypes-macros/Macros.flags @@ -0,0 +1 @@ +-explaintypes diff --git a/test/files/pos/t6123-explaintypes-macros.scala b/test/files/neg/t6123-explaintypes-macros/Macros.scala index e650ad2038..a12c277c86 100644 --- a/test/files/pos/t6123-explaintypes-macros.scala +++ b/test/files/neg/t6123-explaintypes-macros/Macros.scala @@ -5,3 +5,6 @@ object Macros { def printf(format: String, params: Any*): Unit = macro printf_impl def printf_impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = ??? } + +// something trivial to run +object Test extends App diff --git a/test/files/run/repl-javap-app.check b/test/files/run/repl-javap-app.check new file mode 100644 index 0000000000..db1f09b977 --- /dev/null +++ b/test/files/run/repl-javap-app.check @@ -0,0 +1,39 @@ +#partest java6 +Type in expressions to have them evaluated. +Type :help for more information. + +scala> :javap -app MyApp$ +public final void delayedEndpoint$MyApp$1(); + Code: + Stack=2, Locals=1, Args_size=1 + 0: getstatic #61; //Field scala/Console$.MODULE$:Lscala/Console$; + 3: ldc #63; //String Hello, delayed world. + 5: invokevirtual #67; //Method scala/Console$.println:(Ljava/lang/Object;)V + 8: return + LocalVariableTable: + Start Length Slot Name Signature + 0 9 0 this LMyApp$; +} + +scala> +#partest !java6 +Type in expressions to have them evaluated. +Type :help for more information. + +scala> :javap -app MyApp$ + public final void delayedEndpoint$MyApp$1(); + flags: ACC_PUBLIC, ACC_FINAL + Code: + stack=2, locals=1, args_size=1 + 0: getstatic #61 // Field scala/Console$.MODULE$:Lscala/Console$; + 3: ldc #63 // String Hello, delayed world. + 5: invokevirtual #67 // Method scala/Console$.println:(Ljava/lang/Object;)V + 8: return + LocalVariableTable: + Start Length Slot Name Signature + 0 9 0 this LMyApp$; + LineNumberTable: + line 5: 0 +} + +scala> diff --git a/test/files/run/repl-javap-app.scala b/test/files/run/repl-javap-app.scala new file mode 100644 index 0000000000..be04920be1 --- /dev/null +++ b/test/files/run/repl-javap-app.scala @@ -0,0 +1,10 @@ + +import scala.tools.partest.ReplTest + +object MyApp extends App { + Console println "Hello, delayed world." +} + +object Test extends ReplTest { + def code = ":javap -app MyApp$" +} |