From 9b6a269b6af0da9a89d39578402bed82c47f4ab7 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 22 Oct 2013 23:23:49 +0200 Subject: better macro impl shape errors With the advent of quasiquotes, we allowed both arguments and return types of macro impls to be c.Tree's (as opposed to traditional c.Expr[T]'s). This warrants an update of macro def <-> macro impl signature mismatch errors that include a printout of suggested macro impl signatures. Now along with a signature that contains exprs, we suggest another signature that has all exprs replaced by trees --- .../scala/reflect/macros/compiler/Errors.scala | 21 +++++++++++++-------- .../scala/reflect/macros/util/Helpers.scala | 7 +++++++ test/files/neg/macro-bundle-object.check | 1 + test/files/neg/macro-invalidimpl.check | 2 ++ test/files/neg/macro-invalidret.check | 2 ++ .../files/neg/macro-invalidsig-params-badtype.check | 1 + test/files/neg/macro-invalidsig.check | 11 +++++++++++ test/files/neg/macro-quasiquotes.check | 3 ++- test/files/neg/t5689.check | 1 + test/files/neg/t6123-explaintypes-macros.check | 1 + 10 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index 9b56e417e2..45bb87fc47 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -44,14 +44,18 @@ trait Errors extends Traces { message + suffix } - private def abbreviateCoreAliases(s: String): String = List("WeakTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x)) + private def abbreviateCoreAliases(s: String): String = { + val coreAliases = List("WeakTypeTag", "Expr", "Tree") + coreAliases.foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x)) + } - private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = { - var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString - if (abbreviate) argsPart = abbreviateCoreAliases(argsPart) - var retPart = restpe.toString + private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean, untype: Boolean) = { + def preprocess(tpe: Type) = if (untype) untypeMetalevel(tpe) else tpe + var pssPart = (pss map (ps => ps map (p => p.defStringSeenAs(preprocess(p.info))) mkString ("(", ", ", ")"))).mkString + if (abbreviate) pssPart = abbreviateCoreAliases(pssPart) + var retPart = preprocess(restpe).toString if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart) - argsPart + ": " + retPart + pssPart + ": " + retPart } // not exactly an error generator, but very related @@ -86,8 +90,9 @@ trait Errors extends Traces { private def compatibilityError(message: String) = implRefError( "macro implementation has wrong shape:"+ - "\n required: " + showMeth(rparamss, rret, abbreviate = true) + - "\n found : " + showMeth(aparamss, aret, abbreviate = false) + + "\n required: " + showMeth(rparamss, rret, abbreviate = true, untype = false) + + "\n or : " + showMeth(rparamss, rret, abbreviate = true, untype = true) + + "\n found : " + showMeth(aparamss, aret, abbreviate = false, untype = false) + "\n" + message) def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences") diff --git a/src/compiler/scala/reflect/macros/util/Helpers.scala b/src/compiler/scala/reflect/macros/util/Helpers.scala index f40c6bb7e6..dd23b0fc32 100644 --- a/src/compiler/scala/reflect/macros/util/Helpers.scala +++ b/src/compiler/scala/reflect/macros/util/Helpers.scala @@ -55,6 +55,13 @@ trait Helpers { case tp => typeRef(pre, MacroContextExprClass, List(tp)) } + /** Transforms c.Expr[T] types into c.Tree and leaves the rest unchanged. + */ + def untypeMetalevel(tp: Type): Type = transparentShallowTransform(RepeatedParamClass, tp) { + case ExprClassOf(_) => typeRef(tp.prefix, TreesTreeType, Nil) + case tp => tp + } + /** Decreases metalevel of the type, i.e. transforms: * * c.Expr[T] to T * * Anything else to Any diff --git a/test/files/neg/macro-bundle-object.check b/test/files/neg/macro-bundle-object.check index e122001427..8c19271b51 100644 --- a/test/files/neg/macro-bundle-object.check +++ b/test/files/neg/macro-bundle-object.check @@ -1,5 +1,6 @@ macro-bundle-object.scala:11: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : : Nothing number of parameter sections differ def foo = macro Bundle.impl diff --git a/test/files/neg/macro-invalidimpl.check b/test/files/neg/macro-invalidimpl.check index aaf4f88fc2..e39cc8105b 100644 --- a/test/files/neg/macro-invalidimpl.check +++ b/test/files/neg/macro-invalidimpl.check @@ -32,12 +32,14 @@ match expected type ? ^ Macros_Test_2.scala:31: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Unit] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(): c.Expr[Unit] number of parameter sections differ def foo1 = macro Impls6.fooEmpty ^ Macros_Test_2.scala:32: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(): c.Expr[Unit] + or : (c: scala.reflect.macros.Context)(): c.Tree found : (c: scala.reflect.macros.Context): c.Expr[Unit] number of parameter sections differ def bar1() = macro Impls6.fooNullary diff --git a/test/files/neg/macro-invalidret.check b/test/files/neg/macro-invalidret.check index 8c6ed4eb45..6cf62c292b 100644 --- a/test/files/neg/macro-invalidret.check +++ b/test/files/neg/macro-invalidret.check @@ -1,11 +1,13 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context): Int type mismatch for return type: Int does not conform to c.Expr[Any] def foo1 = macro Impls.foo1 ^ Macros_Test_2.scala:3: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context): reflect.runtime.universe.Literal type mismatch for return type: reflect.runtime.universe.Literal does not conform to c.Expr[Any] def foo2 = macro Impls.foo2 diff --git a/test/files/neg/macro-invalidsig-params-badtype.check b/test/files/neg/macro-invalidsig-params-badtype.check index 3cc1c9abf1..86aa08291f 100644 --- a/test/files/neg/macro-invalidsig-params-badtype.check +++ b/test/files/neg/macro-invalidsig-params-badtype.check @@ -1,5 +1,6 @@ Impls_Macros_1.scala:8: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: Int): Nothing type mismatch for parameter x: c.Expr[Int] does not conform to Int def foo(x: Int) = macro Impls.foo diff --git a/test/files/neg/macro-invalidsig.check b/test/files/neg/macro-invalidsig.check index cbdaf51081..732380d4b3 100644 --- a/test/files/neg/macro-invalidsig.check +++ b/test/files/neg/macro-invalidsig.check @@ -1,65 +1,76 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(implicit evidence$2: Numeric[U]): c.universe.Literal macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U] = macro Impls1.foo[U] ^ Macros_Test_2.scala:6: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : : Nothing number of parameter sections differ def foo = macro Impls2.foo ^ Macros_Test_2.scala:10: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.api.Universe): Nothing type mismatch for parameter c: scala.reflect.macros.Context does not conform to scala.reflect.api.Universe def foo = macro Impls3.foo ^ Macros_Test_2.scala:14: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (cs: scala.reflect.macros.Context*): Nothing types incompatible for parameter cs: corresponding is not a vararg parameter def foo = macro Impls4.foo ^ Macros_Test_2.scala:18: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Any]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context): Nothing number of parameter sections differ def foo(x: Any) = macro Impls5.foo ^ Macros_Test_2.scala:22: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Unit] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(implicit x: c.Expr[Int]): c.Expr[Unit] macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U](x: Int) = macro Impls6.foo[T, U] ^ Macros_Test_2.scala:26: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): Nothing parameter lists have different length, found extra parameter y: c.Expr[Int] def foo(x: Int) = macro Impls7.foo ^ Macros_Test_2.scala:30: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(x: c.universe.Symbol): Nothing type mismatch for parameter x: c.Expr[Int] does not conform to c.universe.Symbol def foo(x: Int) = macro Impls8.foo ^ Macros_Test_2.scala:34: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree, y: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(xs: c.Expr[Int]*): Nothing parameter lists have different length, required extra parameter y: c.Expr[Int] def foo(x: Int, y: Int) = macro Impls9.foo ^ Macros_Test_2.scala:38: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] + or : (c: scala.reflect.macros.Context)(x: c.Tree, y: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(y: c.Expr[Int], x: c.Expr[Int]): Nothing parameter names differ: x != y def foo(x: Int, y: Int) = macro Impls10.foo ^ Macros_Test_2.scala:42: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] + or : (c: scala.reflect.macros.Context): c.Tree found : (c: scala.reflect.macros.Context)(U: c.universe.Type): Nothing number of parameter sections differ def foo[U] = macro Impls11.foo[U] diff --git a/test/files/neg/macro-quasiquotes.check b/test/files/neg/macro-quasiquotes.check index 96ef75dd32..d000bb5316 100644 --- a/test/files/neg/macro-quasiquotes.check +++ b/test/files/neg/macro-quasiquotes.check @@ -1,6 +1,7 @@ Macros_1.scala:14: error: macro implementation has wrong shape: required: (x: Impls.this.c.Expr[Int]): Impls.this.c.Expr[Any] - found : (x: Impls.this.c.universe.Block): Impls.this.c.universe.Tree + or : (x: Impls.this.c.Tree): Impls.this.c.Tree + found : (x: Impls.this.c.universe.Block): Impls.this.c.Tree type mismatch for parameter x: Impls.this.c.Expr[Int] does not conform to Impls.this.c.universe.Block def m3(x: Int) = macro Impls.impl3 ^ diff --git a/test/files/neg/t5689.check b/test/files/neg/t5689.check index ad9b79cdcb..8cf0534e77 100644 --- a/test/files/neg/t5689.check +++ b/test/files/neg/t5689.check @@ -1,5 +1,6 @@ t5689.scala:4: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(i: c.Expr[Double]): c.Expr[String] + or : (c: scala.reflect.macros.Context)(i: c.Tree): c.Tree found : (c: scala.reflect.macros.Context)(i: c.Expr[Double]): c.Expr[Int] type mismatch for return type: c.Expr[Int] does not conform to c.Expr[String] def returnsString(i: Double): String = macro returnsIntImpl diff --git a/test/files/neg/t6123-explaintypes-macros.check b/test/files/neg/t6123-explaintypes-macros.check index ebcb8069d5..43f8371326 100644 --- a/test/files/neg/t6123-explaintypes-macros.check +++ b/test/files/neg/t6123-explaintypes-macros.check @@ -2,6 +2,7 @@ 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] + or : (c: scala.reflect.macros.Context)(format: c.Tree, params: Tree*): c.Tree 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 -- cgit v1.2.3