From 6902da3168c02448387edc000dedfe97ef5f7cd9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 6 Nov 2012 22:23:09 +0100 Subject: SI-6539 Annotation for methods unfit for post-typer ASTs Motivated by the `.value` method in the SBT task-syntax branch, which should only be called within the context of the argument to a setting initialization macro. The facility is akin to a fatal deprecation. --- test/files/neg/t6539.check | 10 ++++++++++ test/files/neg/t6539/Macro_1.scala | 10 ++++++++++ test/files/neg/t6539/Test_2.scala | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 test/files/neg/t6539.check create mode 100644 test/files/neg/t6539/Macro_1.scala create mode 100644 test/files/neg/t6539/Test_2.scala (limited to 'test/files/neg') diff --git a/test/files/neg/t6539.check b/test/files/neg/t6539.check new file mode 100644 index 0000000000..a5d5a7244d --- /dev/null +++ b/test/files/neg/t6539.check @@ -0,0 +1,10 @@ +Test_2.scala:2: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m + M.cto // error + ^ +Test_2.scala:3: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m + M.m(M.cto, ()) // error + ^ +Test_2.scala:5: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m + M.cto // error + ^ +three errors found diff --git a/test/files/neg/t6539/Macro_1.scala b/test/files/neg/t6539/Macro_1.scala new file mode 100644 index 0000000000..69bd53fe07 --- /dev/null +++ b/test/files/neg/t6539/Macro_1.scala @@ -0,0 +1,10 @@ +import language.experimental.macros +import reflect.macros.Context + +object M { + def m(a: Any, b: Any): Any = macro mImpl + def mImpl(c: Context)(a: c.Expr[Any], b: c.Expr[Any]) = a + + @reflect.macros.compileTimeOnly("cto may only be used as an argument to m") + def cto = 0 +} diff --git a/test/files/neg/t6539/Test_2.scala b/test/files/neg/t6539/Test_2.scala new file mode 100644 index 0000000000..1569c79788 --- /dev/null +++ b/test/files/neg/t6539/Test_2.scala @@ -0,0 +1,6 @@ +object Test { + M.cto // error + M.m(M.cto, ()) // error + M.m((), M.cto) // okay + M.cto // error +} \ No newline at end of file -- cgit v1.2.3 From 48ee29aa26e4e5358cb1de7890565095420177b4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 6 Nov 2012 23:43:44 +0100 Subject: Refine @compileTimeOnly - Don't default the message, and show it exclusively. - Fix cut-and-pasto in the @since tag - Be tolerant if the annotaion class is missing, as seems to have been the case compiling the continuations plugin. - s/\t/ / in the test file to show the errors are positioned correctly. - Use defensive getOrElse --- .../scala/tools/nsc/typechecker/RefChecks.scala | 9 +++++++-- src/reflect/scala/reflect/internal/Definitions.scala | 2 +- src/reflect/scala/reflect/macros/compileTimeOnly.scala | 4 ++-- test/files/neg/t6539.check | 18 +++++++++--------- test/files/neg/t6539/Macro_1.scala | 8 ++++---- test/files/neg/t6539/Test_2.scala | 10 +++++----- 6 files changed, 28 insertions(+), 23 deletions(-) (limited to 'test/files/neg') diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 726c8d3b24..ee7805cb3d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1377,8 +1377,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } private def checkCompileTimeOnly(sym: Symbol, pos: Position) = { - if (sym.isCompileTimeOnly) - unit.error(pos, s"reference to ${sym.fullLocationString} should not survive typechecking: ${sym.compileTimeOnlyMessage.get}") + if (sym.isCompileTimeOnly) { + def defaultMsg = + s"""|Reference to ${sym.fullLocationString} should not have survived past type checking, + |it should have been processed and eliminated during expansion of an enclosing macro.""".stripMargin + // The getOrElse part should never happen, it's just here as a backstop. + unit.error(pos, sym.compileTimeOnlyMessage getOrElse defaultMsg) + } } private def lessAccessible(otherSym: Symbol, memberSym: Symbol): Boolean = ( diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 4c7694c319..2a7b55cb5a 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -944,7 +944,7 @@ trait Definitions extends api.StandardDefinitions { lazy val BeanPropertyAttr = requiredClass[scala.beans.BeanProperty] lazy val BooleanBeanPropertyAttr = requiredClass[scala.beans.BooleanBeanProperty] lazy val CloneableAttr = requiredClass[scala.annotation.cloneable] - lazy val CompileTimeOnlyAttr = requiredClass[scala.reflect.macros.compileTimeOnly] + lazy val CompileTimeOnlyAttr = getClassIfDefined("scala.reflect.macros.compileTimeOnly") lazy val DeprecatedAttr = requiredClass[scala.deprecated] lazy val DeprecatedNameAttr = requiredClass[scala.deprecatedName] lazy val DeprecatedInheritanceAttr = requiredClass[scala.deprecatedInheritance] diff --git a/src/reflect/scala/reflect/macros/compileTimeOnly.scala b/src/reflect/scala/reflect/macros/compileTimeOnly.scala index 4018e7db71..5a3a352a53 100644 --- a/src/reflect/scala/reflect/macros/compileTimeOnly.scala +++ b/src/reflect/scala/reflect/macros/compileTimeOnly.scala @@ -10,7 +10,7 @@ import scala.annotation.meta._ * * @param message the error message to print during compilation if a reference remains * after type checking - * @since 2.10.0 + * @since 2.10.1 */ @getter @setter @beanGetter @beanSetter -final class compileTimeOnly(message: String = "") extends scala.annotation.StaticAnnotation +final class compileTimeOnly(message: String) extends scala.annotation.StaticAnnotation diff --git a/test/files/neg/t6539.check b/test/files/neg/t6539.check index a5d5a7244d..b647636338 100644 --- a/test/files/neg/t6539.check +++ b/test/files/neg/t6539.check @@ -1,10 +1,10 @@ -Test_2.scala:2: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m - M.cto // error - ^ -Test_2.scala:3: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m - M.m(M.cto, ()) // error - ^ -Test_2.scala:5: error: reference to method cto in object M should not survive typechecking: cto may only be used as an argument to m - M.cto // error - ^ +Test_2.scala:2: error: cto may only be used as an argument to m + M.cto // error + ^ +Test_2.scala:3: error: cto may only be used as an argument to m + M.m(M.cto, ()) // error + ^ +Test_2.scala:5: error: cto may only be used as an argument to m + M.cto // error + ^ three errors found diff --git a/test/files/neg/t6539/Macro_1.scala b/test/files/neg/t6539/Macro_1.scala index 69bd53fe07..ed52776d95 100644 --- a/test/files/neg/t6539/Macro_1.scala +++ b/test/files/neg/t6539/Macro_1.scala @@ -2,9 +2,9 @@ import language.experimental.macros import reflect.macros.Context object M { - def m(a: Any, b: Any): Any = macro mImpl - def mImpl(c: Context)(a: c.Expr[Any], b: c.Expr[Any]) = a + def m(a: Any, b: Any): Any = macro mImpl + def mImpl(c: Context)(a: c.Expr[Any], b: c.Expr[Any]) = a - @reflect.macros.compileTimeOnly("cto may only be used as an argument to m") - def cto = 0 + @reflect.macros.compileTimeOnly("cto may only be used as an argument to " + "m") + def cto = 0 } diff --git a/test/files/neg/t6539/Test_2.scala b/test/files/neg/t6539/Test_2.scala index 1569c79788..5a602879ec 100644 --- a/test/files/neg/t6539/Test_2.scala +++ b/test/files/neg/t6539/Test_2.scala @@ -1,6 +1,6 @@ object Test { - M.cto // error - M.m(M.cto, ()) // error - M.m((), M.cto) // okay - M.cto // error -} \ No newline at end of file + M.cto // error + M.m(M.cto, ()) // error + M.m((), M.cto) // okay + M.cto // error +} -- cgit v1.2.3