Skip to content

Commit fa10d64

Browse files
committed
Fix #1647 Evaluate annotation arguments in proper context
Need to evaluate annotation arguments in an expression context, since classes defined in asuch arguments should not be entered into enclosing class. Fixes #1647
1 parent a7bf3c0 commit fa10d64

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,13 @@ object Contexts {
422422
final def withOwner(owner: Symbol): Context =
423423
if (owner ne this.owner) fresh.setOwner(owner) else this
424424

425+
final def withProperty[T](key: Key[T], value: Option[T]): Context =
426+
if (property(key) == value) this
427+
else value match {
428+
case Some(v) => fresh.setProperty(key, v)
429+
case None => fresh.dropProperty(key)
430+
}
431+
425432
override def toString = {
426433
def iinfo(implicit ctx: Context) = if (ctx.importInfo == null) "" else i"${ctx.importInfo.selectors}%, %"
427434
"Context(\n" +
@@ -470,6 +477,9 @@ object Contexts {
470477
def setProperty[T](key: Key[T], value: T): this.type =
471478
setMoreProperties(moreProperties.updated(key, value))
472479

480+
def dropProperty(key: Key[_]): this.type =
481+
setMoreProperties(moreProperties - key)
482+
473483
def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid))
474484
def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))
475485

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import EtaExpansion.etaExpand
2727
import dotty.tools.dotc.transform.Erasure.Boxing
2828
import util.Positions._
2929
import util.common._
30-
import util.SourcePosition
30+
import util.{SourcePosition, Property}
3131
import collection.mutable
3232
import annotation.tailrec
3333
import Implicits._
@@ -57,6 +57,8 @@ object Typer {
5757
def assertPositioned(tree: untpd.Tree)(implicit ctx: Context) =
5858
if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable)
5959
assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId}")
60+
61+
private val ExprOwner = new Property.Key[Symbol]
6062
}
6163

6264
class Typer extends Namer with TypeAssigner with Applications with Implicits with Dynamic with Checking with Docstrings {
@@ -1133,7 +1135,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
11331135
def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = {
11341136
// necessary to force annotation trees to be computed.
11351137
sym.annotations.foreach(_.ensureCompleted)
1136-
val annotCtx = ctx.outersIterator.dropWhile(_.owner == sym).next
1138+
lazy val annotCtx = {
1139+
val c = ctx.outersIterator.dropWhile(_.owner == sym).next
1140+
c.property(ExprOwner) match {
1141+
case Some(exprOwner) if c.owner.isClass => c.exprContext(mdef, exprOwner)
1142+
case None => c
1143+
}
1144+
}
11371145
// necessary in order to mark the typed ahead annotations as definitely typed:
11381146
untpd.modsDeco(mdef).mods.annotations.foreach(typedAnnotation(_)(annotCtx))
11391147
}
@@ -1552,7 +1560,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
15521560
case nil =>
15531561
buf.toList
15541562
}
1555-
traverse(stats)
1563+
val localCtx = {
1564+
val exprOwnerOpt = if (exprOwner == ctx.owner) None else Some(exprOwner)
1565+
ctx.withProperty(ExprOwner, exprOwnerOpt)
1566+
}
1567+
traverse(stats)(localCtx)
15561568
}
15571569

15581570
/** Given an inline method `mdef`, the method rewritten so that its body

tests/neg/i1647.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class ann {
2+
@ann({ def baz }) // error: missing return type
3+
def foo(): Unit
4+
}

0 commit comments

Comments
 (0)