Skip to content

Commit ff184cc

Browse files
authored
Merge pull request #4776 from dotty-staging/undo-annotations-phase
Fix #4758: Revert "New phase for entering annotations"
2 parents 08c022a + 0c35b8f commit ff184cc

File tree

9 files changed

+54
-111
lines changed

9 files changed

+54
-111
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: 20 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,19 @@ 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+
lazy val annotCtx = annotContext(original, sym)
752+
for (annotTree <- untpd.modsDeco(original).mods.annotations) {
753+
val cls = typedAheadAnnotationClass(annotTree)(annotCtx)
754+
val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree))
755+
sym.addAnnotation(ann)
756+
if (cls == defn.ForceInlineAnnot && sym.is(Method, butNot = Accessor))
757+
sym.setFlag(Inline)
758+
}
759+
case _ =>
760+
}
761+
825762
private def addInlineInfo(sym: Symbol) = original match {
826763
case original: untpd.DefDef if sym.isInlineableMethod =>
827764
Inliner.registerInlineInfo(
@@ -836,10 +773,7 @@ class Namer { typer: Typer =>
836773
*/
837774
def completeInCreationContext(denot: SymDenotation): Unit = {
838775
val sym = denot.symbol
839-
original match {
840-
case original: MemberDef => addAnnotations(sym, original)
841-
case _ =>
842-
}
776+
addAnnotations(sym)
843777
addInlineInfo(sym)
844778
denot.info = typeSig(sym)
845779
Checking.checkWellFormed(sym)
@@ -955,7 +889,7 @@ class Namer { typer: Typer =>
955889
}
956890
}
957891

958-
addAnnotations(denot.symbol, original)
892+
addAnnotations(denot.symbol)
959893

960894
val selfInfo =
961895
if (self.isEmpty) NoType
@@ -978,9 +912,7 @@ class Namer { typer: Typer =>
978912
// accessors, that's why the constructor needs to be completed before
979913
// the parent types are elaborated.
980914
index(constr)
981-
annotate(constr :: params)
982-
983-
indexAndAnnotate(rest)(ctx.inClassContext(selfInfo))
915+
index(rest)(ctx.inClassContext(selfInfo))
984916
symbolOfTree(constr).ensureCompleted()
985917

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

1026958
/** Enter and typecheck parameter list */
1027959
def completeParams(params: List[MemberDef])(implicit ctx: Context) = {
1028-
indexAndAnnotate(params)
960+
index(params)
1029961
for (param <- params) typedAheadExpr(param)
1030962
}
1031963

@@ -1222,7 +1154,7 @@ class Namer { typer: Typer =>
12221154
// 3. Info of CP is computed (to be copied to DP).
12231155
// 4. CP is completed.
12241156
// 5. Info of CP is copied to DP and DP is completed.
1225-
indexAndAnnotate(tparams)
1157+
index(tparams)
12261158
if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted())
12271159
for (tparam <- tparams) typedAheadExpr(tparam)
12281160

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: 19 additions & 13 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)
@@ -1339,20 +1339,26 @@ class Typer extends Namer
13391339
assignType(cpy.Alternative(tree)(trees1), trees1)
13401340
}
13411341

1342+
/** The context to be used for an annotation of `mdef`.
1343+
* This should be the context enclosing `mdef`, or if `mdef` defines a parameter
1344+
* the context enclosing the owner of `mdef`.
1345+
* Furthermore, we need to evaluate annotation arguments in an expression context,
1346+
* since classes defined in a such arguments should not be entered into the
1347+
* enclosing class.
1348+
*/
1349+
def annotContext(mdef: untpd.Tree, sym: Symbol)(implicit ctx: Context): Context = {
1350+
def isInner(owner: Symbol) = owner == sym || sym.is(Param) && owner == sym.owner
1351+
val c = ctx.outersIterator.dropWhile(c => isInner(c.owner)).next()
1352+
c.property(ExprOwner) match {
1353+
case Some(exprOwner) if c.owner.isClass => c.exprContext(mdef, exprOwner)
1354+
case _ => c
1355+
}
1356+
}
1357+
13421358
def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = {
13431359
// necessary to force annotation trees to be computed.
13441360
sym.annotations.foreach(_.ensureCompleted)
1345-
lazy val annotCtx = {
1346-
val c = ctx.outersIterator.dropWhile(_.owner == sym).next()
1347-
c.property(ExprOwner) match {
1348-
case Some(exprOwner) if c.owner.isClass =>
1349-
// We need to evaluate annotation arguments in an expression context, since
1350-
// classes defined in a such arguments should not be entered into the
1351-
// enclosing class.
1352-
c.exprContext(mdef, exprOwner)
1353-
case _ => c
1354-
}
1355-
}
1361+
lazy val annotCtx = annotContext(mdef, sym)
13561362
// necessary in order to mark the typed ahead annotations as definitely typed:
13571363
untpd.modsDeco(mdef).mods.annotations.foreach(typedAnnotation(_)(annotCtx))
13581364
}

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)