From 1b5f73129fc2f678d00905e5d851536251f8821a Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 10 Aug 2013 14:51:34 +0200 Subject: moves compileTimeOnly to scala-library This is the notion that's come to be universally useful, so I suggest we promote it to be universally accessible. Note that the attached test incorrectly fails to report errors for definitions coming from the empty package and for annotations. These are bugs, and they are fixed in subsequent commits of this pull request. --- test/files/neg/compile-time-only-a.check | 19 +++++++++++ test/files/neg/compile-time-only-a.scala | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 test/files/neg/compile-time-only-a.check create mode 100644 test/files/neg/compile-time-only-a.scala (limited to 'test/files/neg') diff --git a/test/files/neg/compile-time-only-a.check b/test/files/neg/compile-time-only-a.check new file mode 100644 index 0000000000..99d7a8e2dd --- /dev/null +++ b/test/files/neg/compile-time-only-a.check @@ -0,0 +1,19 @@ +compile-time-only-a.scala:41: error: C5 + 2.ext + ^ +compile-time-only-a.scala:42: error: C5 + C5(2) + ^ +compile-time-only-a.scala:45: error: C6.x + val _ = c6.x + ^ +compile-time-only-a.scala:46: error: C6.foo + c6.foo + ^ +compile-time-only-a.scala:48: error: C6.y + c6.y = c6.y + ^ +compile-time-only-a.scala:48: error: C6.y + c6.y = c6.y + ^ +6 errors found diff --git a/test/files/neg/compile-time-only-a.scala b/test/files/neg/compile-time-only-a.scala new file mode 100644 index 0000000000..43d36dfab1 --- /dev/null +++ b/test/files/neg/compile-time-only-a.scala @@ -0,0 +1,57 @@ +import scala.annotation.compileTimeOnly + +@compileTimeOnly("C1") class C1 +object C1 + +class C2 +@compileTimeOnly("C2") object C2 + +@compileTimeOnly("C3") case class C3(x: Int) + +@compileTimeOnly("C4") case class C4(x: Int) +object C4 + +object pkg { + @compileTimeOnly("C5") + implicit class C5(val x: Int) { + def ext = ??? + } +} + +class C6(@compileTimeOnly("C6.x") val x: Int) { + @compileTimeOnly("C6.foo") def foo = 2 + @compileTimeOnly("C6.Foo") type Foo = Int + @compileTimeOnly("C6.y") var y = 3 +} + +object Test extends App { + new C1() + C1 + + new C2() + C2 + + new C3(2) + C3(2) + + new C4(2) + C4(2) + + import pkg._ + 2.ext + C5(2) + + val c6 = new C6(2) + val _ = c6.x + c6.foo + type Foo = c6.Foo + c6.y = c6.y +} + +@compileTimeOnly("placebo") +class placebo extends scala.annotation.StaticAnnotation + +@placebo +class Test { + @placebo def x = (2: @placebo) +} \ No newline at end of file -- cgit v1.2.3 From 840ad7656456f014135c2a5e31e0d9ffd63625bd Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 10 Aug 2013 14:52:24 +0200 Subject: marks Expr.splice and Expr.value with @compileTimeOnly Now that @compileTimeOnly is part of the standard library, why don't we use it within the standard library. --- src/reflect/scala/reflect/api/Exprs.scala | 5 +++-- test/files/neg/compile-time-only-b.check | 7 +++++++ test/files/neg/compile-time-only-b.scala | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 test/files/neg/compile-time-only-b.check create mode 100644 test/files/neg/compile-time-only-b.scala (limited to 'test/files/neg') diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala index 009d9dbfdb..5b6ff2325c 100644 --- a/src/reflect/scala/reflect/api/Exprs.scala +++ b/src/reflect/scala/reflect/api/Exprs.scala @@ -8,6 +8,7 @@ package reflect package api import scala.reflect.runtime.{universe => ru} +import scala.annotation.compileTimeOnly /** * EXPERIMENTAL @@ -91,7 +92,7 @@ trait Exprs { self: Universe => * }}} * because expr of type Expr[T] itself does not have a method foo. */ - // @compileTimeOnly("Cannot use splice outside reify") + @compileTimeOnly("splice must be enclosed within a reify {} block") def splice: T /** @@ -108,7 +109,7 @@ trait Exprs { self: Universe => * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } * }}} */ - // @compileTimeOnly("Cannot use value except for signatures of macro implementations") + @compileTimeOnly("cannot use value except for signatures of macro implementations") val value: T override def canEqual(x: Any) = x.isInstanceOf[Expr[_]] diff --git a/test/files/neg/compile-time-only-b.check b/test/files/neg/compile-time-only-b.check new file mode 100644 index 0000000000..8292a0ddeb --- /dev/null +++ b/test/files/neg/compile-time-only-b.check @@ -0,0 +1,7 @@ +compile-time-only-b.scala:13: error: splice must be enclosed within a reify {} block + val ignored3 = reify(fortyTwo).splice + ^ +compile-time-only-b.scala:14: error: cannot use value except for signatures of macro implementations + val ignored4 = reify(fortyTwo).value + ^ +two errors found diff --git a/test/files/neg/compile-time-only-b.scala b/test/files/neg/compile-time-only-b.scala new file mode 100644 index 0000000000..d5568dbe67 --- /dev/null +++ b/test/files/neg/compile-time-only-b.scala @@ -0,0 +1,15 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + // HAHA!!! + // no compileTimeOnly errors here, because scalac does constant folding + // the type of reify(42) is Expr[42.type] + // therefore the type of expr.splice is 42.type, which is then constfolded + val expr = reify(42) + val ignored1 = expr.splice + val ignored2 = expr.value + + val fortyTwo = 42 + val ignored3 = reify(fortyTwo).splice + val ignored4 = reify(fortyTwo).value +} \ No newline at end of file -- cgit v1.2.3 From 4ca45cb4c14595d491cc0cfc509fa88fb4dd5619 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 10 Aug 2013 14:58:09 +0200 Subject: @compileTimeOnly now works for annotations http://docs.scala-lang.org/overviews/macros/annotations.html say sincere "thank you!". --- src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 1 + test/files/neg/compile-time-only-a.check | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (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 1b6963b598..782a2880c2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1414,6 +1414,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def applyRefchecksToAnnotations(tree: Tree): Unit = { def applyChecks(annots: List[AnnotationInfo]) = { + annots foreach (annot => checkCompileTimeOnly(annot.atp.typeSymbol, annot.pos)) checkAnnotations(annots map (_.atp), tree) transformTrees(annots flatMap (_.args)) } diff --git a/test/files/neg/compile-time-only-a.check b/test/files/neg/compile-time-only-a.check index 99d7a8e2dd..3a6ded7cfc 100644 --- a/test/files/neg/compile-time-only-a.check +++ b/test/files/neg/compile-time-only-a.check @@ -16,4 +16,13 @@ compile-time-only-a.scala:48: error: C6.y compile-time-only-a.scala:48: error: C6.y c6.y = c6.y ^ -6 errors found +compile-time-only-a.scala:54: error: placebo +@placebo + ^ +compile-time-only-a.scala:56: error: placebo + @placebo def x = (2: @placebo) + ^ +compile-time-only-a.scala:56: error: placebo + @placebo def x = (2: @placebo) + ^ +9 errors found -- cgit v1.2.3 From 46f17f114bf261dc8757b5b876da50d53bb31172 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 10 Aug 2013 15:02:50 +0200 Subject: @compileTimeOnly now works for symbols from the empty package Looks like we've got the entire language covered now. --- .../scala/tools/nsc/typechecker/RefChecks.scala | 1 + test/files/neg/compile-time-only-a.check | 23 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) (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 782a2880c2..04d03d47cc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1649,6 +1649,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans tree case Ident(name) => + checkCompileTimeOnly(tree.symbol, tree.pos) transformCaseApply(tree, if (name != nme.WILDCARD && name != tpnme.WILDCARD_STAR) { assert(sym != NoSymbol, "transformCaseApply: name = " + name.debugString + " tree = " + tree + " / " + tree.getClass) //debug diff --git a/test/files/neg/compile-time-only-a.check b/test/files/neg/compile-time-only-a.check index 3a6ded7cfc..1c4c72171f 100644 --- a/test/files/neg/compile-time-only-a.check +++ b/test/files/neg/compile-time-only-a.check @@ -1,3 +1,24 @@ +compile-time-only-a.scala:9: error: C3 +@compileTimeOnly("C3") case class C3(x: Int) + ^ +compile-time-only-a.scala:11: error: C4 +@compileTimeOnly("C4") case class C4(x: Int) + ^ +compile-time-only-a.scala:16: error: C5 + implicit class C5(val x: Int) { + ^ +compile-time-only-a.scala:28: error: C1 + new C1() + ^ +compile-time-only-a.scala:32: error: C2 + C2 + ^ +compile-time-only-a.scala:34: error: C3 + new C3(2) + ^ +compile-time-only-a.scala:37: error: C4 + new C4(2) + ^ compile-time-only-a.scala:41: error: C5 2.ext ^ @@ -25,4 +46,4 @@ compile-time-only-a.scala:56: error: placebo compile-time-only-a.scala:56: error: placebo @placebo def x = (2: @placebo) ^ -9 errors found +16 errors found -- cgit v1.2.3