Skip to content

Commit b345b42

Browse files
committed
Merge pull request scala#3246 from xeno-by/topic/compile-time-only
streamlines refchecking undesired symbol properties
2 parents 979f83c + eb78e90 commit b345b42

File tree

3 files changed

+85
-48
lines changed

3 files changed

+85
-48
lines changed

src/compiler/scala/tools/nsc/typechecker/RefChecks.scala

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,22 +1265,22 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
12651265
false
12661266
}
12671267

1268-
/** If symbol is deprecated, and the point of reference is not enclosed
1269-
* in either a deprecated member or a scala bridge method, issue a warning.
1270-
*/
1271-
private def checkDeprecated(sym: Symbol, pos: Position) {
1268+
// Note: if a symbol has both @deprecated and @migration annotations and both
1269+
// warnings are enabled, only the first one checked here will be emitted.
1270+
// I assume that's a consequence of some code trying to avoid noise by suppressing
1271+
// warnings after the first, but I think it'd be better if we didn't have to
1272+
// arbitrarily choose one as more important than the other.
1273+
private def checkUndesiredProperties(sym: Symbol, pos: Position) {
1274+
// If symbol is deprecated, and the point of reference is not enclosed
1275+
// in either a deprecated member or a scala bridge method, issue a warning.
12721276
if (sym.isDeprecated && !currentOwner.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) {
12731277
unit.deprecationWarning(pos, "%s%s is deprecated%s".format(
12741278
sym, sym.locationString, sym.deprecationMessage map (": " + _) getOrElse "")
12751279
)
12761280
}
1277-
}
1278-
1279-
/** Similar to deprecation: check if the symbol is marked with @migration
1280-
* indicating it has changed semantics between versions.
1281-
*/
1282-
private def checkMigration(sym: Symbol, pos: Position) = {
1283-
if (sym.hasMigrationAnnotation) {
1281+
// Similar to deprecation: check if the symbol is marked with @migration
1282+
// indicating it has changed semantics between versions.
1283+
if (sym.hasMigrationAnnotation && settings.Xmigration.value != NoScalaVersion) {
12841284
val changed = try
12851285
settings.Xmigration.value < ScalaVersion(sym.migrationVersion.get)
12861286
catch {
@@ -1292,9 +1292,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
12921292
if (changed)
12931293
unit.warning(pos, s"${sym.fullLocationString} has changed semantics in version ${sym.migrationVersion.get}:\n${sym.migrationMessage.get}")
12941294
}
1295-
}
1296-
1297-
private def checkCompileTimeOnly(sym: Symbol, pos: Position) = {
1295+
// See an explanation of compileTimeOnly in its scaladoc at scala.annotation.compileTimeOnly.
12981296
if (sym.isCompileTimeOnly) {
12991297
def defaultMsg =
13001298
sm"""Reference to ${sym.fullLocationString} should not have survived past type checking,
@@ -1416,8 +1414,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
14161414
case TypeRef(pre, sym, args) =>
14171415
tree match {
14181416
case tt: TypeTree if tt.original == null => // SI-7783 don't warn about inferred types
1419-
case _ =>
1420-
checkDeprecated(sym, tree.pos)
1417+
// FIXME: reconcile this check with one in resetAllAttrs
1418+
case _ => checkUndesiredProperties(sym, tree.pos)
14211419
}
14221420
if(sym.isJavaDefined)
14231421
sym.typeParams foreach (_.cookJavaRawInfo())
@@ -1449,7 +1447,6 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
14491447

14501448
private def applyRefchecksToAnnotations(tree: Tree): Unit = {
14511449
def applyChecks(annots: List[AnnotationInfo]) = {
1452-
annots foreach (annot => checkCompileTimeOnly(annot.atp.typeSymbol, annot.pos))
14531450
checkAnnotations(annots map (_.atp), tree)
14541451
transformTrees(annots flatMap (_.args))
14551452
}
@@ -1541,16 +1538,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
15411538
val Select(qual, _) = tree
15421539
val sym = tree.symbol
15431540

1544-
/* Note: if a symbol has both @deprecated and @migration annotations and both
1545-
* warnings are enabled, only the first one checked here will be emitted.
1546-
* I assume that's a consequence of some code trying to avoid noise by suppressing
1547-
* warnings after the first, but I think it'd be better if we didn't have to
1548-
* arbitrarily choose one as more important than the other.
1549-
*/
1550-
checkDeprecated(sym, tree.pos)
1551-
if(settings.Xmigration.value != NoScalaVersion)
1552-
checkMigration(sym, tree.pos)
1553-
checkCompileTimeOnly(sym, tree.pos)
1541+
checkUndesiredProperties(sym, tree.pos)
15541542
checkDelayedInitSelect(qual, sym, tree.pos)
15551543

15561544
if (!sym.exists)
@@ -1705,7 +1693,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
17051693
tree
17061694

17071695
case Ident(name) =>
1708-
checkCompileTimeOnly(tree.symbol, tree.pos)
1696+
checkUndesiredProperties(sym, tree.pos)
17091697
transformCaseApply(tree,
17101698
if (name != nme.WILDCARD && name != tpnme.WILDCARD_STAR) {
17111699
assert(sym != NoSymbol, "transformCaseApply: name = " + name.debugString + " tree = " + tree + " / " + tree.getClass) //debug
Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,79 @@
1-
compile-time-only-a.scala:9: error: C3
1+
compile-time-only-a.scala:10: error: C3
22
@compileTimeOnly("C3") case class C3(x: Int)
33
^
4-
compile-time-only-a.scala:11: error: C4
4+
compile-time-only-a.scala:12: error: C4
55
@compileTimeOnly("C4") case class C4(x: Int)
66
^
7-
compile-time-only-a.scala:16: error: C5
7+
compile-time-only-a.scala:17: error: C5
88
implicit class C5(val x: Int) {
99
^
10-
compile-time-only-a.scala:28: error: C1
10+
compile-time-only-a.scala:32: error: C1
1111
new C1()
1212
^
13-
compile-time-only-a.scala:32: error: C2
13+
compile-time-only-a.scala:36: error: C2
1414
C2
1515
^
16-
compile-time-only-a.scala:34: error: C3
16+
compile-time-only-a.scala:38: error: C3
1717
new C3(2)
1818
^
19-
compile-time-only-a.scala:37: error: C4
19+
compile-time-only-a.scala:41: error: C4
2020
new C4(2)
2121
^
22-
compile-time-only-a.scala:41: error: C5
22+
compile-time-only-a.scala:45: error: C5
2323
2.ext
2424
^
25-
compile-time-only-a.scala:42: error: C5
25+
compile-time-only-a.scala:46: error: C5
2626
C5(2)
2727
^
28-
compile-time-only-a.scala:45: error: C6.x
28+
compile-time-only-a.scala:49: error: C6.x
2929
val _ = c6.x
3030
^
31-
compile-time-only-a.scala:46: error: C6.foo
31+
compile-time-only-a.scala:50: error: C6.foo
3232
c6.foo
3333
^
34-
compile-time-only-a.scala:48: error: C6.y
34+
compile-time-only-a.scala:51: error: C6.Foo
35+
type Foo = c6.Foo
36+
^
37+
compile-time-only-a.scala:52: error: C6.y
3538
c6.y = c6.y
3639
^
37-
compile-time-only-a.scala:48: error: C6.y
40+
compile-time-only-a.scala:52: error: C6.y
3841
c6.y = c6.y
3942
^
40-
compile-time-only-a.scala:54: error: placebo
41-
@placebo
42-
^
43-
compile-time-only-a.scala:56: error: placebo
43+
compile-time-only-a.scala:54: error: C7
44+
val c701: (C7, C7) = ???
45+
^
46+
compile-time-only-a.scala:55: error: C7
47+
val c702: (C7 => C7) = ???
48+
^
49+
compile-time-only-a.scala:56: error: C7
50+
val c703: { val x: C7 } = ???
51+
^
52+
compile-time-only-a.scala:57: error: C7
53+
val c704: AnyRef with C7 = ???
54+
^
55+
compile-time-only-a.scala:60: error: C7
56+
val c706: C7 Either C7 = ???
57+
^
58+
compile-time-only-a.scala:61: error: C7
59+
val c707a: List[C7] = ???
60+
^
61+
compile-time-only-a.scala:63: error: C7
62+
val c708a: T forSome { type T <: C7 } = ???
63+
^
64+
compile-time-only-a.scala:66: error: C8
65+
val c709: (C8[Int], C8[C7]) = ???
66+
^
67+
compile-time-only-a.scala:67: error: C8
68+
val c710: (C8[_] => C8[_]) = ???
69+
^
70+
compile-time-only-a.scala:74: error: placebo
71+
class Test {
72+
^
73+
compile-time-only-a.scala:75: error: placebo
4474
@placebo def x = (2: @placebo)
45-
^
46-
compile-time-only-a.scala:56: error: placebo
75+
^
76+
compile-time-only-a.scala:75: error: placebo
4777
@placebo def x = (2: @placebo)
4878
^
49-
16 errors found
79+
26 errors found

test/files/neg/compile-time-only-a.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import scala.annotation.compileTimeOnly
2+
import scala.language.existentials
23

34
@compileTimeOnly("C1") class C1
45
object C1
@@ -24,6 +25,9 @@ class C6(@compileTimeOnly("C6.x") val x: Int) {
2425
@compileTimeOnly("C6.y") var y = 3
2526
}
2627

28+
@compileTimeOnly("C7") class C7
29+
@compileTimeOnly("C8") class C8[T]
30+
2731
object Test extends App {
2832
new C1()
2933
C1
@@ -46,6 +50,21 @@ object Test extends App {
4650
c6.foo
4751
type Foo = c6.Foo
4852
c6.y = c6.y
53+
54+
val c701: (C7, C7) = ???
55+
val c702: (C7 => C7) = ???
56+
val c703: { val x: C7 } = ???
57+
val c704: AnyRef with C7 = ???
58+
// https://groups.google.com/forum/#!topic/scala-internals/5n07TiCnBZU
59+
// val c705: ({ @compileTimeOnly("C7") type C7[T] = List[T] })#C7[_] = ???
60+
val c706: C7 Either C7 = ???
61+
val c707a: List[C7] = ???
62+
val c707b = List[C7]()
63+
val c708a: T forSome { type T <: C7 } = ???
64+
// https://groups.google.com/forum/#!topic/scala-internals/5n07TiCnBZU
65+
// val c708b: T forSome { @compileTimeOnly("C7") type T } = ???
66+
val c709: (C8[Int], C8[C7]) = ???
67+
val c710: (C8[_] => C8[_]) = ???
4968
}
5069

5170
@compileTimeOnly("placebo")

0 commit comments

Comments
 (0)