Skip to content

Commit

Permalink
Keep using frozen_=:=, copy annotations symbols in PostTyper
Browse files Browse the repository at this point in the history
  • Loading branch information
mbovel committed May 22, 2024
1 parent 30f6f65 commit 062492e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 13 deletions.
15 changes: 12 additions & 3 deletions compiler/src/dotty/tools/dotc/ast/TreeTypeMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import Decorators.*
* @param newOwners New owners, replacing previous owners.
* @param substFrom The symbols that need to be substituted.
* @param substTo The substitution targets.
* @param cpy A tree copier that is used to create new trees.
* @param alwaysCopySymbols If set, symbols are always copied, even when they
* are not impacted by the transformation.
*
* The reason the substitution is broken out from the rest of the type map is
* that all symbols have to be substituted at the same time. If we do not do this,
Expand All @@ -38,7 +41,9 @@ class TreeTypeMap(
val newOwners: List[Symbol] = Nil,
val substFrom: List[Symbol] = Nil,
val substTo: List[Symbol] = Nil,
cpy: tpd.TreeCopier = tpd.cpy)(using Context) extends tpd.TreeMap(cpy) {
cpy: tpd.TreeCopier = tpd.cpy,
alwaysCopySymbols: Boolean = false,
)(using Context) extends tpd.TreeMap(cpy) {
import tpd.*

def copy(
Expand All @@ -48,7 +53,7 @@ class TreeTypeMap(
newOwners: List[Symbol],
substFrom: List[Symbol],
substTo: List[Symbol])(using Context): TreeTypeMap =
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo, cpy, alwaysCopySymbols)

/** If `sym` is one of `oldOwners`, replace by corresponding symbol in `newOwners` */
def mapOwner(sym: Symbol): Symbol = sym.subst(oldOwners, newOwners)
Expand Down Expand Up @@ -202,7 +207,7 @@ class TreeTypeMap(
* between original and mapped symbols.
*/
def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
withMappedSyms(syms, mapSymbols(syms, this))
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = alwaysCopySymbols))

/** The tree map with the substitution between originals `syms`
* and mapped symbols `mapped`. Also goes into mapped classes
Expand All @@ -224,6 +229,10 @@ class TreeTypeMap(
tmap1
}

def withAlwaysCopySymbols: TreeTypeMap =
if alwaysCopySymbols then this
else new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo, cpy, alwaysCopySymbols = true)

override def toString =
def showSyms(syms: List[Symbol]) =
syms.map(sym => s"$sym#${sym.id}").mkString(", ")
Expand Down
14 changes: 6 additions & 8 deletions compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,15 @@ object Annotations {
if tm.isRange(x) then x
else
val tp1 = tm(tree.tpe)
foldOver(if tp1 == tree.tpe then x else tp1, tree)
foldOver(if !tp1.exists || (tp1 frozen_=:= tree.tpe) then x else tp1, tree)
val diff = findDiff(NoType, args)
if tm.isRange(diff) then EmptyAnnotation
else if diff.exists then
// In case of changes, the symbol in the annotation's tree should be
// copied so that the same symbol is not used for different trees.
val ttm =
new TreeTypeMap(typeMap = tm):
final override def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = true))
derivedAnnotation(ttm.transform(tree))
// If the annotation has been transformed, we need to make sure that the
// symbol are copied so that we don't end up with the same symbol in different
// trees, which would lead to a crash in pickling.
val mappedTree = TreeTypeMap(typeMap = tm, alwaysCopySymbols = true).transform(tree)
derivedAnnotation(mappedTree)
else this

/** Does this annotation refer to a parameter of `tl`? */
Expand Down
11 changes: 9 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dotty.tools
package dotc
package transform

import dotty.tools.dotc.ast.{Trees, tpd, untpd, desugar}
import dotty.tools.dotc.ast.{Trees, TreeTypeMap, tpd, untpd, desugar}
import scala.collection.mutable
import core.*
import dotty.tools.dotc.typer.Checking
Expand Down Expand Up @@ -157,7 +157,14 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
val saved = inJavaAnnot
inJavaAnnot = annot.symbol.is(JavaDefined)
if (inJavaAnnot) checkValidJavaAnnotation(annot)
try transform(annot)
try
val res = transform(annot)
if res ne annot then
// If the annotation has been transformed, we need to make sure that the
// symbol are copied so that we don't end up with the same symbol in different
// trees, which would lead to a crash in pickling.
TreeTypeMap(alwaysCopySymbols = true)(res)
else res
finally inJavaAnnot = saved
}

Expand Down
5 changes: 5 additions & 0 deletions tests/pos/annot-17939c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class qualified(f: Int => Boolean) extends annotation.StaticAnnotation
class Box[T](val y: T)
def Test =
val x: String @qualified((x: Int) => Box(42).y == 2) = ???
val y = x

0 comments on commit 062492e

Please sign in to comment.