Skip to content

Commit 7caac8e

Browse files
committed
feat: allow annotations to annotate themselves
1 parent 473246e commit 7caac8e

File tree

4 files changed

+27
-26
lines changed

4 files changed

+27
-26
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ class TreeUnpickler(reader: TastyReader,
668668
else
669669
newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
670670
}
671+
registerSym(start, sym)
671672
val annotOwner =
672673
if sym.owner.isClass then newLocalDummy(sym.owner) else sym.owner
673674
sym.annotations = annotFns.map(_(annotOwner))
@@ -685,7 +686,6 @@ class TreeUnpickler(reader: TastyReader,
685686
cls.enter(sym)
686687
case _ =>
687688
}
688-
registerSym(start, sym)
689689
if (isClass) {
690690
if sym.owner.is(Package) && withCaptureChecks then
691691
sym.setFlag(CaptureChecked)
@@ -768,7 +768,10 @@ class TreeUnpickler(reader: TastyReader,
768768
addFlag(Protected)
769769
privateWithin = readWithin
770770
case ANNOTATION =>
771-
annotFns = readAnnot :: annotFns
771+
val annotFn =
772+
val annot = readAnnot
773+
(sym: Symbol) => annot.complete(sym)
774+
annotFns = annotFn :: annotFns
772775
case tag =>
773776
assert(false, s"illegal modifier tag $tag at $currentAddr, end = $end")
774777
}
@@ -778,21 +781,23 @@ class TreeUnpickler(reader: TastyReader,
778781

779782
private def readWithin(using Context): Symbol = readType().typeSymbol
780783

781-
private def readAnnot(using Context): Symbol => Annotation =
784+
private def readAnnot(using Context): Trees.Lazy[Symbol => Annotation] =
782785
readByte()
783786
val end = readEnd()
784-
val tp = readType()
785-
val lazyAnnotTree = readLaterWithOwner(end, _.readTree())
786-
owner =>
787-
new DeferredSymAndTree(tp.typeSymbol, lazyAnnotTree(owner).complete):
788-
// Only force computation of symbol if it has the right name. This added
789-
// amount of laziness is sometimes necessary to avid cycles. Test case pos/i15980.
790-
override def hasSymbol(sym: Symbol)(using Context) = tp match
791-
case tp: TypeRef =>
792-
tp.designator match
793-
case name: Name => name == sym.name && tp.symbol == sym
794-
case _ => tp.symbol == sym
795-
case _ => this.symbol == sym
787+
readLater(end, reader =>
788+
val tp = reader.readType()
789+
val lazyAnnotTree = reader.readLaterWithOwner(end, _.readTree())
790+
owner =>
791+
new DeferredSymAndTree(tp.typeSymbol, lazyAnnotTree(owner).complete):
792+
// Only force computation of symbol if it has the right name. This added
793+
// amount of laziness is sometimes necessary to avoid cycles. Test case pos/i15980.
794+
override def hasSymbol(sym: Symbol)(using Context) = tp match
795+
case tp: TypeRef =>
796+
tp.designator match
797+
case name: Name => name == sym.name && tp.symbol == sym
798+
case _ => tp.symbol == sym
799+
case _ => this.symbol == sym
800+
)
796801

797802
/** Create symbols for the definitions in the statement sequence between
798803
* current address and `end`.

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -896,16 +896,12 @@ class Namer { typer: Typer =>
896896
original.mods.withAnnotations:
897897
original.mods.annotations.mapConserve: annotTree =>
898898
val cls = typedAheadAnnotationClass(annotTree)(using annotCtx)
899-
if (cls eq sym)
900-
report.error(em"An annotation class cannot be annotated with iself", annotTree.srcPos)
901-
annotTree
902-
else
903-
val ann =
904-
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
905-
else annotTree
906-
val ann1 = Annotation.deferred(cls)(typedAheadExpr(ann)(using annotCtx))
907-
sym.addAnnotation(ann1)
908-
ann
899+
val ann =
900+
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
901+
else annotTree
902+
val ann1 = Annotation.deferred(cls)(typedAheadExpr(ann)(using annotCtx))
903+
sym.addAnnotation(ann1)
904+
ann
909905
case _ =>
910906
}
911907

tests/neg/i1212.scala

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/pos/i1212.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@ann class ann extends scala.annotation.Annotation

0 commit comments

Comments
 (0)