Skip to content

Commit 37e624f

Browse files
authored
Fix mapping TypeMaps over annotations (#15948)
Avoids orphan parameters when pickling Fixes #15922 I am not sure about the status of the test in custome-args/captures. Should it pass or be rejected? But in any case it does not crash anymore.
2 parents 3f0c6d3 + 198c4c3 commit 37e624f

File tree

6 files changed

+35
-5
lines changed

6 files changed

+35
-5
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class TreeTypeMap(
5656
/** Replace occurrences of `This(oldOwner)` in some prefix of a type
5757
* by the corresponding `This(newOwner)`.
5858
*/
59-
private val mapOwnerThis = new TypeMap {
59+
private val mapOwnerThis = new TypeMap with cc.CaptureSet.IdempotentCaptRefMap {
6060
private def mapPrefix(from: List[Symbol], to: List[Symbol], tp: Type): Type = from match {
6161
case Nil => tp
6262
case (cls: ClassSymbol) :: from1 => mapPrefix(from1, to.tail, tp.substThis(cls, to.head.thisType))

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ object CaptureSet:
523523

524524
private def mapIsIdempotent = tm.isInstanceOf[IdempotentCaptRefMap]
525525

526-
assert(ccAllowUnsoundMaps || mapIsIdempotent)
526+
assert(ccAllowUnsoundMaps || mapIsIdempotent, tm.getClass)
527527

528528
private def whereCreated(using Context): String =
529529
if stack == null then ""

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
package dotty.tools.dotc
1+
package dotty.tools
2+
package dotc
23
package core
34

45
import Symbols._, Types._, Contexts._, Constants._
@@ -58,7 +59,7 @@ object Annotations {
5859
if tm.isRange(x) then x
5960
else
6061
val tp1 = tm(tree.tpe)
61-
foldOver(if tp1 =:= tree.tpe then x else tp1, tree)
62+
foldOver(if tp1 frozen_=:= tree.tpe then x else tp1, tree)
6263
val diff = findDiff(NoType, args)
6364
if tm.isRange(diff) then EmptyAnnotation
6465
else if diff.exists then derivedAnnotation(tm.mapOver(tree))
@@ -69,7 +70,7 @@ object Annotations {
6970
val args = arguments
7071
if args.isEmpty then false
7172
else tree.existsSubTree {
72-
case id: Ident => id.tpe match
73+
case id: Ident => id.tpe.stripped match
7374
case TermParamRef(tl1, _) => tl eq tl1
7475
case _ => false
7576
case _ => false

compiler/test/dotc/pos-test-pickling.blacklist

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ i6507b.scala
1919
i12299a.scala
2020
i13871.scala
2121
i15181.scala
22+
i15922.scala
2223

2324
# Tree is huge and blows stack for printing Text
2425
i7034.scala
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait Cap { def use(): Int }
2+
type Id[X] = [T] -> (op: X => T) -> T
3+
def mkId[X](x: X): Id[X] = [T] => (op: X => T) => op(x)
4+
5+
def withCap[X](op: ({*} Cap) => X): X = {
6+
val cap: {*} Cap = new Cap { def use() = { println("cap is used"); 0 } }
7+
val result = op(cap)
8+
result
9+
}
10+
11+
def leaking(c: {*} Cap): Id[{c} Cap] = mkId(c)
12+
13+
def test =
14+
val bad = withCap(leaking)

tests/pos/i15922.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
trait Cap:
2+
type M
3+
class Id[X]
4+
5+
object Test:
6+
def withCap[X](op: Cap => X): X = ???
7+
8+
class retains1(xs: Any*) extends annotation.StaticAnnotation
9+
10+
def leaking1(c: Cap): Id[Cap @retains1(c)] = ??? // used to crash with orphan parameter on pickling
11+
def leaking2(c: Cap): Id[c.type] = ???
12+
13+
val bad1 = withCap(leaking1)
14+
val bad2 = withCap(leaking2)

0 commit comments

Comments
 (0)