Skip to content

Commit 0500452

Browse files
committed
Fix #4758: Revert "New phase for entering annotations"
This reverts commit 2b12868. Since we do not plan to run annotation macros during Namer, there's no need to annotate before completing. This allows again to define an annotation in the same scope as an annotated definition. So i3702.scala goes from neg to pos.
1 parent 7a80060 commit 0500452

File tree

9 files changed

+40
-100
lines changed

9 files changed

+40
-100
lines changed

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ class FrontEnd extends Phase {
5555
typr.println("entered: " + unit.source)
5656
}
5757

58-
def enterAnnotations(implicit ctx: Context) = monitor("annotating") {
59-
val unit = ctx.compilationUnit
60-
ctx.typer.annotate(unit.untpdTree :: Nil)
61-
typr.println("annotated: " + unit.source)
62-
}
63-
6458
def typeCheck(implicit ctx: Context) = monitor("typechecking") {
6559
val unit = ctx.compilationUnit
6660
unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
@@ -91,7 +85,6 @@ class FrontEnd extends Phase {
9185
enterSyms(remaining.head)
9286
remaining = remaining.tail
9387
}
94-
unitContexts.foreach(enterAnnotations(_))
9588
unitContexts.foreach(typeCheck(_))
9689
record("total trees after typer", ast.Trees.ntrees)
9790
unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper)

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

Lines changed: 23 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -687,90 +687,14 @@ class Namer { typer: Typer =>
687687
ctxWithStats
688688
}
689689

690-
/** Add all annotations of definitions in `stats` to the defined symbols */
691-
def annotate(stats: List[Tree])(implicit ctx: Context): Unit = {
692-
def recur(stat: Tree): Unit = stat match {
693-
case pcl: PackageDef =>
694-
annotate(pcl.stats)
695-
case stat: untpd.MemberDef =>
696-
stat.getAttachment(SymOfTree) match {
697-
case Some(sym) =>
698-
sym.infoOrCompleter match {
699-
case info: Completer if !defn.isPredefClass(sym.owner) =>
700-
// Annotate Predef methods only when they are completed;
701-
// This is necessary to break a cyclic dependence between `Predef`
702-
// and `deprecated` in test `compileStdLib`.
703-
addAnnotations(sym, stat)(info.creationContext)
704-
case _ =>
705-
// Annotations were already added as part of the symbol's completion
706-
}
707-
case none =>
708-
assert(stat.typeOpt.exists, i"no symbol for $stat")
709-
}
710-
case stat: untpd.Thicket =>
711-
stat.trees.foreach(recur)
712-
case _ =>
713-
}
714-
715-
for (stat <- stats) recur(expanded(stat))
716-
}
717-
718-
/** Add annotations of `stat` to `sym`.
719-
* This method can be called twice on a symbol (e.g. once
720-
* during the `annotate` phase and then again during completion).
721-
* Therefore, care needs to be taken not to add annotations again
722-
* that are already added to the symbol.
723-
*/
724-
def addAnnotations(sym: Symbol, stat: MemberDef)(implicit ctx: Context) = {
725-
// (1) The context in which an annotation of a top-level class or module is evaluated
726-
// is the closest enclosing context which has the enclosing package as owner.
727-
// (2) The context in which an annotation for any other symbol is evaluated is the
728-
// closest enclosing context which has the owner of the class enclosing the symbol as owner.
729-
// E.g in
730-
//
731-
// package p
732-
// import a.b
733-
// class C {
734-
// import d.e
735-
// @ann m() ...
736-
// }
737-
//
738-
// `@ann` is evaluated in the context just outside `C`, where the `a.b`
739-
// import is visible but the `d.e` import is forgotten. This measure is necessary
740-
// in order to avoid cycles.
741-
lazy val annotCtx = {
742-
var target = sym.owner.lexicallyEnclosingClass
743-
if (!target.is(PackageClass)) target = target.owner
744-
var c = ctx
745-
while (c.owner != target) c = c.outer
746-
c
747-
}
748-
749-
for (annotTree <- untpd.modsDeco(stat).mods.annotations) {
750-
val cls = typedAheadAnnotationClass(annotTree)(annotCtx)
751-
if (sym.unforcedAnnotation(cls).isEmpty) {
752-
val ann = Annotation.deferred(cls, implicit ctx => typedAheadAnnotation(annotTree))
753-
sym.addAnnotation(ann)
754-
if (cls == defn.ForceInlineAnnot && sym.is(Method, butNot = Accessor))
755-
sym.setFlag(Inline)
756-
}
757-
}
758-
}
759-
760-
def indexAndAnnotate(stats: List[Tree])(implicit ctx: Context): Context = {
761-
val localCtx = index(stats)
762-
annotate(stats)
763-
localCtx
764-
}
765-
766-
/** Index and annotate symbols in `tree` while asserting the `lateCompile` flag.
690+
/** Index symbols in `tree` while asserting the `lateCompile` flag.
767691
* This will cause any old top-level symbol with the same fully qualified
768692
* name as a newly created symbol to be replaced.
769693
*/
770694
def lateEnter(tree: Tree)(implicit ctx: Context) = {
771695
val saved = lateCompile
772696
lateCompile = true
773-
try indexAndAnnotate(tree :: Nil) finally lateCompile = saved
697+
try index(tree :: Nil) finally lateCompile = saved
774698
}
775699

776700
def missingType(sym: Symbol, modifier: String)(implicit ctx: Context) = {
@@ -822,6 +746,22 @@ class Namer { typer: Typer =>
822746
else completeInCreationContext(denot)
823747
}
824748

749+
protected def addAnnotations(sym: Symbol): Unit = original match {
750+
case original: untpd.MemberDef =>
751+
var hasInlineAnnot = false
752+
lazy val annotCtx =
753+
if (sym.is(Param)) ctx.outersIterator.dropWhile(_.owner == sym.owner).next
754+
else ctx
755+
for (annotTree <- untpd.modsDeco(original).mods.annotations) {
756+
val cls = typedAheadAnnotationClass(annotTree)(annotCtx)
757+
val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree))
758+
sym.addAnnotation(ann)
759+
if (cls == defn.ForceInlineAnnot && sym.is(Method, butNot = Accessor))
760+
sym.setFlag(Inline)
761+
}
762+
case _ =>
763+
}
764+
825765
private def addInlineInfo(sym: Symbol) = original match {
826766
case original: untpd.DefDef if sym.isInlineableMethod =>
827767
Inliner.registerInlineInfo(
@@ -836,10 +776,7 @@ class Namer { typer: Typer =>
836776
*/
837777
def completeInCreationContext(denot: SymDenotation): Unit = {
838778
val sym = denot.symbol
839-
original match {
840-
case original: MemberDef => addAnnotations(sym, original)
841-
case _ =>
842-
}
779+
addAnnotations(sym)
843780
addInlineInfo(sym)
844781
denot.info = typeSig(sym)
845782
Checking.checkWellFormed(sym)
@@ -955,7 +892,7 @@ class Namer { typer: Typer =>
955892
}
956893
}
957894

958-
addAnnotations(denot.symbol, original)
895+
addAnnotations(denot.symbol)
959896

960897
val selfInfo =
961898
if (self.isEmpty) NoType
@@ -978,9 +915,7 @@ class Namer { typer: Typer =>
978915
// accessors, that's why the constructor needs to be completed before
979916
// the parent types are elaborated.
980917
index(constr)
981-
annotate(constr :: params)
982-
983-
indexAndAnnotate(rest)(ctx.inClassContext(selfInfo))
918+
index(rest)(ctx.inClassContext(selfInfo))
984919
symbolOfTree(constr).ensureCompleted()
985920

986921
val parentTypes = ensureFirstIsClass(parents.map(checkedParentType(_)), cls.pos)
@@ -1025,7 +960,7 @@ class Namer { typer: Typer =>
1025960

1026961
/** Enter and typecheck parameter list */
1027962
def completeParams(params: List[MemberDef])(implicit ctx: Context) = {
1028-
indexAndAnnotate(params)
963+
index(params)
1029964
for (param <- params) typedAheadExpr(param)
1030965
}
1031966

@@ -1222,7 +1157,7 @@ class Namer { typer: Typer =>
12221157
// 3. Info of CP is computed (to be copied to DP).
12231158
// 4. CP is completed.
12241159
// 5. Info of CP is copied to DP and DP is completed.
1225-
indexAndAnnotate(tparams)
1160+
index(tparams)
12261161
if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted())
12271162
for (tparam <- tparams) typedAheadExpr(tparam)
12281163

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ class ReTyper extends Typer with ReChecking {
9191
override def localTyper(sym: Symbol) = this
9292

9393
override def index(trees: List[untpd.Tree])(implicit ctx: Context) = ctx
94-
override def annotate(trees: List[untpd.Tree])(implicit ctx: Context) = ()
9594

9695
override def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType, locked: TypeVars)(fallBack: => Tree)(implicit ctx: Context): Tree =
9796
fallBack

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ class Typer extends Namer
659659
}
660660

661661
def typedBlockStats(stats: List[untpd.Tree])(implicit ctx: Context): (Context, List[tpd.Tree]) =
662-
(indexAndAnnotate(stats), typedStats(stats, ctx.owner))
662+
(index(stats), typedStats(stats, ctx.owner))
663663

664664
def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = track("typedBlock") {
665665
val (exprCtx, stats1) = typedBlockStats(tree.stats)
@@ -1270,7 +1270,7 @@ class Typer extends Namer
12701270

12711271
def typedLambdaTypeTree(tree: untpd.LambdaTypeTree)(implicit ctx: Context): Tree = track("typedLambdaTypeTree") {
12721272
val LambdaTypeTree(tparams, body) = tree
1273-
indexAndAnnotate(tparams)
1273+
index(tparams)
12741274
val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef])
12751275
val body1 = typedType(tree.body)
12761276
assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1)

compiler/src/dotty/tools/repl/ReplFrontEnd.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ private[repl] class REPLFrontEnd extends FrontEnd {
2121

2222
val unitContext = ctx.fresh.setCompilationUnit(units.head)
2323
enterSyms(unitContext)
24-
enterAnnotations(unitContext)
2524
typeCheck(unitContext)
2625
List(unitContext.compilationUnit)
2726
}

tests/neg/i3702.scala renamed to tests/pos/i3702.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ object test {
22
class annot extends scala.annotation.Annotation
33
def foo = {
44
def bar(i: Int): Int = i
5-
@annot class Silly {} // error: not found
5+
@annot class Silly {} // used to be: not found, but now ok after backing out of 2b12868070be50fb70
66
bar(5)
77
}
88
}

tests/pos/i4758/Test1.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package foo.bar
2+
3+
class Bar extends annotation.StaticAnnotation
4+

tests/pos/i4758/Test2.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package foo
2+
3+
import foo.bar.Bar
4+
5+
@Bar
6+
class Foo extends annotation.StaticAnnotation
7+

tests/pos/i4758/Test3.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package object foo {
2+
@Foo class Hello
3+
}

0 commit comments

Comments
 (0)