Skip to content

Commit ae35b5e

Browse files
committed
Fix #6419: Support @compileTimeOnly
1 parent 837c7a2 commit ae35b5e

File tree

5 files changed

+44
-5
lines changed

5 files changed

+44
-5
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ class Definitions {
858858
lazy val TransientParamAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.constructorOnly")
859859
def TransientParamAnnot(implicit ctx: Context): ClassSymbol = TransientParamAnnotType.symbol.asClass
860860
lazy val CompileTimeOnlyAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.compileTimeOnly")
861-
def CompileTimeOnlyParamAnnot(implicit ctx: Context): ClassSymbol = CompileTimeOnlyAnnotType.symbol.asClass
861+
def CompileTimeOnlyAnnot(implicit ctx: Context): ClassSymbol = CompileTimeOnlyAnnotType.symbol.asClass
862862
lazy val SwitchAnnotType: TypeRef = ctx.requiredClassRef("scala.annotation.switch")
863863
def SwitchAnnot(implicit ctx: Context): ClassSymbol = SwitchAnnotType.symbol.asClass
864864
lazy val ThrowsAnnotType: TypeRef = ctx.requiredClassRef("scala.throws")

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,23 @@ object Erasure {
326326
}
327327

328328
private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = {
329-
if (isErased(tree) && !ctx.mode.is(Mode.Type))
330-
ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.sourcePos)
329+
if (!ctx.mode.is(Mode.Type)) {
330+
if (isErased(tree))
331+
ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.sourcePos)
332+
tree.symbol.getAnnotation(defn.CompileTimeOnlyAnnot) match {
333+
case Some(annot) =>
334+
if (ctx.scala2Mode) {
335+
// Scala 2 macros cannot be expanded for which we emit warnings. The best we can do is warn as well.
336+
ctx.error("Reference to member with @compileTimeOnly", tree.sourcePos)
337+
} else {
338+
annot.tree match {
339+
case Apply(_, Literal(msg) :: Nil) => ctx.error(msg.stringValue, tree.sourcePos)
340+
case _ => ctx.error("Reference to member with @compileTimeOnly", tree.sourcePos)
341+
}
342+
}
343+
case _ => // OK
344+
}
345+
}
331346
tree
332347
}
333348

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ object Checking {
401401
if (!sym.is(Deferred))
402402
fail(NativeMembersMayNotHaveImplementation(sym))
403403
}
404-
if (sym.hasAnnotation(defn.CompileTimeOnlyParamAnnot))
405-
ctx.migrationWarning("`@compileTimeOnly(msg)` will be replaced by `scala.compiletime.error(msg)`", sym.sourcePos)
404+
if (sym.hasAnnotation(defn.CompileTimeOnlyAnnot))
405+
ctx.migrationWarning("`@compileTimeOnly(msg)` should be replaced with `scala.compiletime.error(msg)`", sym.sourcePos)
406406
else if (sym.is(Deferred, butNot = Param) && !sym.isType && !sym.isSelfSym) {
407407
if (!sym.owner.isClass || sym.owner.is(Module) || sym.owner.isAnonymousClass)
408408
fail(OnlyClassesCanHaveDeclaredButUndefinedMembers(sym))

tests/neg/i6419.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait A {
2+
@scala.annotation.compileTimeOnly("oops") def f: Int
3+
}
4+
5+
class B extends A {
6+
def f = 0
7+
}
8+
9+
object App {
10+
(new B).f
11+
(new B: A).f // error
12+
}

tests/neg/i6419b.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait A {
2+
inline def f: Int = scala.compiletime.error("oops")
3+
}
4+
5+
class B extends A {
6+
override def f = 0
7+
}
8+
9+
object App {
10+
(new B).f
11+
(new B: A).f // error
12+
}

0 commit comments

Comments
 (0)