Skip to content

Commit ec35b84

Browse files
committed
Tweak the way annotations are represented in desugaring
Need to be careful not to read a classfile before a compilation unit defining the annotation is entered.
1 parent cf4f773 commit ec35b84

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, F
77
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
88
import Decorators._
99
import language.higherKinds
10+
import typer.FrontEnd
1011
import collection.mutable.ListBuffer
1112
import util.Property
1213
import reporting.diagnostic.messages._
@@ -363,7 +364,7 @@ object desugar {
363364
if (mods.is(Abstract) || hasRepeatedParam) Nil // cannot have default arguments for repeated parameters, hence copy method is not issued
364365
else {
365366
def copyDefault(vparam: ValDef) =
366-
makeAnnotated(defn.UncheckedVarianceAnnot, refOfDef(vparam))
367+
makeAnnotated("scala.annotation.unchecked.uncheckedVariance", refOfDef(vparam))
367368
val copyFirstParams = derivedVparamss.head.map(vparam =>
368369
cpy.ValDef(vparam)(rhs = copyDefault(vparam)))
369370
val copyRestParamss = derivedVparamss.tail.nestedMap(vparam =>
@@ -559,7 +560,7 @@ object desugar {
559560
case VarPattern(named, tpt) =>
560561
derivedValDef(original, named, tpt, rhs, mods)
561562
case _ =>
562-
val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs)
563+
val rhsUnchecked = makeAnnotated("scala.unchecked", rhs)
563564
val vars = getVariables(pat)
564565
val isMatchingTuple: Tree => Boolean = {
565566
case Tuple(es) => es.length == vars.length
@@ -688,11 +689,28 @@ object desugar {
688689
new ImplicitFunction(params, body)
689690
}
690691

691-
/** Add annotation with class `cls` to tree:
692-
* tree @cls
692+
/** Add annotation to tree:
693+
* tree @fullName
694+
*
695+
* The annotation is usually represented as a TypeTree referring to the class
696+
* with the given name `fullName`. However, if the annotation matches a file name
697+
* that is still to be entered, the annotation is represented as a cascade of `Selects`
698+
* following `fullName`. This is necessary so that we avoid reading an annotation from
699+
* the classpath that is also compiled from source.
693700
*/
694-
def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) =
695-
Annotated(tree, untpd.New(untpd.TypeTree(cls.typeRef), Nil))
701+
def makeAnnotated(fullName: String, tree: Tree)(implicit ctx: Context) = {
702+
val parts = fullName.split('.')
703+
val ttree = ctx.typerPhase match {
704+
case phase: FrontEnd if phase.stillToBeEntered(parts.last) =>
705+
val prefix =
706+
((Ident(nme.ROOTPKG): Tree) /: parts.init)((qual, name) =>
707+
Select(qual, name.toTermName))
708+
Select(prefix, parts.last.toTypeName)
709+
case _ =>
710+
TypeTree(ctx.requiredClass(fullName).typeRef)
711+
}
712+
Annotated(tree, untpd.New(ttree, Nil))
713+
}
696714

697715
private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = {
698716
val vdef = ValDef(named.name.asTermName, tpt, rhs)

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ class FrontEnd extends Phase {
1919
override def isTyper = true
2020
import ast.tpd
2121

22+
/** The contexts for compilation units that are parsed but not yet entered */
23+
private var remaining: List[Context] = Nil
24+
25+
/** Does a source file ending with `<name>.scala` belong to a compilation unit
26+
* that is parsed but not yet entered?
27+
*/
28+
def stillToBeEntered(name: String): Boolean =
29+
remaining.exists(_.compilationUnit.toString.endsWith(name + ".scala"))
30+
2231
def monitor(doing: String)(body: => Unit)(implicit ctx: Context) =
2332
try body
2433
catch {
@@ -75,7 +84,12 @@ class FrontEnd extends Phase {
7584
}
7685
unitContexts foreach (parse(_))
7786
record("parsedTrees", ast.Trees.ntrees)
78-
unitContexts.foreach(enterSyms(_))
87+
unitContexts.foreach(ctx => println(ctx.compilationUnit))
88+
remaining = unitContexts
89+
while (remaining.nonEmpty) {
90+
enterSyms(remaining.head)
91+
remaining = remaining.tail
92+
}
7993
unitContexts.foreach(enterAnnotations(_))
8094
unitContexts.foreach(typeCheck(_))
8195
record("total trees after typer", ast.Trees.ntrees)

compiler/test/dotc/scala-collections.blacklist

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
## Errors having to do with bootstrap
22

3-
../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala
4-
#java.lang.AssertionError: assertion failed: data race? overwriting symbol of type scala.annotation.unchecked.uncheckedVariance,
5-
63
../scala-scala/src/library/scala/Function1.scala
74
../scala-scala/src/library/scala/Function2.scala
85
# Cyclic reference because of @specialized annotation

compiler/test/dotc/scala-collections.whitelist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@
537537
../scala-scala/src/library/scala/annotation/tailrec.scala
538538
../scala-scala/src/library/scala/annotation/TypeConstraint.scala
539539
../scala-scala/src/library/scala/annotation/unchecked/uncheckedStable.scala
540-
#../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala
540+
../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala
541541
../scala-scala/src/library/scala/annotation/unspecialized.scala
542542
../scala-scala/src/library/scala/annotation/varargs.scala
543543

0 commit comments

Comments
 (0)