Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ class TreeUnpickler(reader: TastyReader,
else
newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
}
registerSym(start, sym)
Copy link
Member Author

@hamzaremmal hamzaremmal Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to register the symbol before we resolve the annotations (2 lines below)

val annotOwner =
if sym.owner.isClass then newLocalDummy(sym.owner) else sym.owner
sym.annotations = annotFns.map(_(annotOwner))
Expand All @@ -685,7 +686,6 @@ class TreeUnpickler(reader: TastyReader,
cls.enter(sym)
case _ =>
}
registerSym(start, sym)
if (isClass) {
if sym.owner.is(Package) && withCaptureChecks then
sym.setFlag(CaptureChecked)
Expand Down Expand Up @@ -768,7 +768,10 @@ class TreeUnpickler(reader: TastyReader,
addFlag(Protected)
privateWithin = readWithin
case ANNOTATION =>
annotFns = readAnnot :: annotFns
val annotFn =
val annot = readAnnot
(sym: Symbol) => annot.complete(sym)
annotFns = annotFn :: annotFns
case tag =>
assert(false, s"illegal modifier tag $tag at $currentAddr, end = $end")
}
Expand All @@ -778,21 +781,23 @@ class TreeUnpickler(reader: TastyReader,

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

private def readAnnot(using Context): Symbol => Annotation =
private def readAnnot(using Context): Trees.Lazy[Symbol => Annotation] =
readByte()
val end = readEnd()
val tp = readType()
val lazyAnnotTree = readLaterWithOwner(end, _.readTree())
owner =>
new DeferredSymAndTree(tp.typeSymbol, lazyAnnotTree(owner).complete):
// Only force computation of symbol if it has the right name. This added
// amount of laziness is sometimes necessary to avid cycles. Test case pos/i15980.
override def hasSymbol(sym: Symbol)(using Context) = tp match
case tp: TypeRef =>
tp.designator match
case name: Name => name == sym.name && tp.symbol == sym
case _ => tp.symbol == sym
case _ => this.symbol == sym
readLater(end, reader =>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We delay it because reading the type of the annotation tp will fail; we prepare this call before registering the symbol and we cannot do it after.

val tp = reader.readType()
val lazyAnnotTree = reader.readLaterWithOwner(end, _.readTree())
owner =>
new DeferredSymAndTree(tp.typeSymbol, lazyAnnotTree(owner).complete):
// Only force computation of symbol if it has the right name. This added
// amount of laziness is sometimes necessary to avoid cycles. Test case pos/i15980.
override def hasSymbol(sym: Symbol)(using Context) = tp match
case tp: TypeRef =>
tp.designator match
case name: Name => name == sym.name && tp.symbol == sym
case _ => tp.symbol == sym
case _ => this.symbol == sym
)

/** Create symbols for the definitions in the statement sequence between
* current address and `end`.
Expand Down
16 changes: 6 additions & 10 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -896,16 +896,12 @@ class Namer { typer: Typer =>
original.mods.withAnnotations:
original.mods.annotations.mapConserve: annotTree =>
val cls = typedAheadAnnotationClass(annotTree)(using annotCtx)
if (cls eq sym)
report.error(em"An annotation class cannot be annotated with iself", annotTree.srcPos)
annotTree
else
val ann =
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
else annotTree
val ann1 = Annotation.deferred(cls)(typedAheadExpr(ann)(using annotCtx))
sym.addAnnotation(ann1)
ann
val ann =
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
else annotTree
val ann1 = Annotation.deferred(cls)(typedAheadExpr(ann)(using annotCtx))
sym.addAnnotation(ann1)
ann
case _ =>
}

Expand Down
1 change: 0 additions & 1 deletion tests/neg/i1212.scala

This file was deleted.

1 change: 1 addition & 0 deletions tests/pos/i1212.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@ann class ann extends scala.annotation.Annotation
Loading