Skip to content

Commit 3e283a7

Browse files
committed
Make sure annotations are typed in expression contexts
The previous logic tried but had holes. A local context was established in `typedStats#localCtx` but that context was not found in annotations that were typechecked in the completer of the definition they decorated. We are now more through and always allocate a localDummy as new owner if the owner would otherwise we a class. This means that closures in annotation arguments will have a term as owner, and therefore will be allocated in distinct local scopes. Fixes #15054
1 parent ed81385 commit 3e283a7

File tree

3 files changed

+28
-13
lines changed

3 files changed

+28
-13
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,9 @@ class TreeUnpickler(reader: TastyReader,
625625
else
626626
newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
627627
}
628-
val annots = annotFns.map(_(sym.owner))
628+
val annotOwner =
629+
if sym.owner.isClass then newLocalDummy(sym.owner) else sym.owner
630+
val annots = annotFns.map(_(annotOwner))
629631
sym.annotations = annots
630632
if sym.isOpaqueAlias then sym.setFlag(Deferred)
631633
val isScala2MacroDefinedInScala3 = flags.is(Macro, butNot = Inline) && flags.is(Erased)

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2238,25 +2238,23 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22382238
* since classes defined in a such arguments should not be entered into the
22392239
* enclosing class.
22402240
*/
2241-
def annotContext(mdef: untpd.Tree, sym: Symbol)(using Context): Context = {
2241+
def annotContext(mdef: untpd.Tree, sym: Symbol)(using Context): Context =
22422242
def isInner(owner: Symbol) = owner == sym || sym.is(Param) && owner == sym.owner
22432243
val outer = ctx.outersIterator.dropWhile(c => isInner(c.owner)).next()
2244-
var adjusted = outer.property(ExprOwner) match {
2244+
val adjusted = outer.property(ExprOwner) match {
22452245
case Some(exprOwner) if outer.owner.isClass => outer.exprContext(mdef, exprOwner)
22462246
case _ => outer
22472247
}
2248+
def local: FreshContext = adjusted.fresh.setOwner(newLocalDummy(sym.owner))
22482249
sym.owner.infoOrCompleter match
2249-
case completer: Namer#Completer if sym.is(Param) =>
2250-
val tparams = completer.completerTypeParams(sym)
2251-
if tparams.nonEmpty then
2252-
// Create a new local context with a dummy owner and a scope containing the
2253-
// type parameters of the enclosing method or class. Thus annotations can see
2254-
// these type parameters. See i12953.scala for a test case.
2255-
val dummyOwner = newLocalDummy(sym.owner)
2256-
adjusted = adjusted.fresh.setOwner(dummyOwner).setScope(newScopeWith(tparams*))
2250+
case completer: Namer#Completer
2251+
if sym.is(Param) && completer.completerTypeParams(sym).nonEmpty =>
2252+
// Create a new local context with a dummy owner and a scope containing the
2253+
// type parameters of the enclosing method or class. Thus annotations can see
2254+
// these type parameters. See i12953.scala for a test case.
2255+
local.setScope(newScopeWith(completer.completerTypeParams(sym)*))
22572256
case _ =>
2258-
adjusted
2259-
}
2257+
if outer.owner.isClass then local else adjusted
22602258

22612259
def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(using Context): Unit = {
22622260
// necessary to force annotation trees to be computed.

tests/pos/i15054.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import scala.annotation.Annotation
2+
3+
class AnAnnotation(function: Int => String) extends Annotation
4+
5+
@AnAnnotation(_.toString)
6+
val a = 1
7+
@AnAnnotation(_.toString.length.toString)
8+
val b = 2
9+
10+
def test =
11+
@AnAnnotation(_.toString)
12+
val a = 1
13+
@AnAnnotation(_.toString.length.toString)
14+
val b = 2
15+
a + b

0 commit comments

Comments
 (0)