Skip to content

Commit 062492e

Browse files
committed
Keep using frozen_=:=, copy annotations symbols in PostTyper
1 parent 30f6f65 commit 062492e

File tree

4 files changed

+32
-13
lines changed

4 files changed

+32
-13
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import Decorators.*
2121
* @param newOwners New owners, replacing previous owners.
2222
* @param substFrom The symbols that need to be substituted.
2323
* @param substTo The substitution targets.
24+
* @param cpy A tree copier that is used to create new trees.
25+
* @param alwaysCopySymbols If set, symbols are always copied, even when they
26+
* are not impacted by the transformation.
2427
*
2528
* The reason the substitution is broken out from the rest of the type map is
2629
* that all symbols have to be substituted at the same time. If we do not do this,
@@ -38,7 +41,9 @@ class TreeTypeMap(
3841
val newOwners: List[Symbol] = Nil,
3942
val substFrom: List[Symbol] = Nil,
4043
val substTo: List[Symbol] = Nil,
41-
cpy: tpd.TreeCopier = tpd.cpy)(using Context) extends tpd.TreeMap(cpy) {
44+
cpy: tpd.TreeCopier = tpd.cpy,
45+
alwaysCopySymbols: Boolean = false,
46+
)(using Context) extends tpd.TreeMap(cpy) {
4247
import tpd.*
4348

4449
def copy(
@@ -48,7 +53,7 @@ class TreeTypeMap(
4853
newOwners: List[Symbol],
4954
substFrom: List[Symbol],
5055
substTo: List[Symbol])(using Context): TreeTypeMap =
51-
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
56+
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo, cpy, alwaysCopySymbols)
5257

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

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

232+
def withAlwaysCopySymbols: TreeTypeMap =
233+
if alwaysCopySymbols then this
234+
else new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo, cpy, alwaysCopySymbols = true)
235+
227236
override def toString =
228237
def showSyms(syms: List[Symbol]) =
229238
syms.map(sym => s"$sym#${sym.id}").mkString(", ")

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,15 @@ object Annotations {
6666
if tm.isRange(x) then x
6767
else
6868
val tp1 = tm(tree.tpe)
69-
foldOver(if tp1 == tree.tpe then x else tp1, tree)
69+
foldOver(if !tp1.exists || (tp1 frozen_=:= tree.tpe) then x else tp1, tree)
7070
val diff = findDiff(NoType, args)
7171
if tm.isRange(diff) then EmptyAnnotation
7272
else if diff.exists then
73-
// In case of changes, the symbol in the annotation's tree should be
74-
// copied so that the same symbol is not used for different trees.
75-
val ttm =
76-
new TreeTypeMap(typeMap = tm):
77-
final override def withMappedSyms(syms: List[Symbol]): TreeTypeMap =
78-
withMappedSyms(syms, mapSymbols(syms, this, mapAlways = true))
79-
derivedAnnotation(ttm.transform(tree))
73+
// If the annotation has been transformed, we need to make sure that the
74+
// symbol are copied so that we don't end up with the same symbol in different
75+
// trees, which would lead to a crash in pickling.
76+
val mappedTree = TreeTypeMap(typeMap = tm, alwaysCopySymbols = true).transform(tree)
77+
derivedAnnotation(mappedTree)
8078
else this
8179

8280
/** Does this annotation refer to a parameter of `tl`? */

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package transform
44

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

tests/pos/annot-17939c.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class qualified(f: Int => Boolean) extends annotation.StaticAnnotation
2+
class Box[T](val y: T)
3+
def Test =
4+
val x: String @qualified((x: Int) => Box(42).y == 2) = ???
5+
val y = x

0 commit comments

Comments
 (0)