Skip to content

Commit c9be468

Browse files
committed
Ignore double-flip occurrences for freezing
1 parent 248fbbd commit c9be468

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,10 @@ class CheckCaptures extends Recheck, SymTransformer:
813813
val arg :: Nil = tree.args: @unchecked
814814
def imm = new TypeMap:
815815
def apply(t: Type) = t match
816+
case t if variance <= 0 =>
817+
// Skip double-flip occurrences of mutable types.
818+
// Example: tests/neg-custom-args/captures/freeze-double-flip.scala.
819+
t
816820
case t @ CapturingType(parent, refs) =>
817821
// If the capturing type is boxed, we skip it. Since it could capture
818822
// existing values of a mutable type without charging anything to the
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/freeze-double-flip.scala:16:48 ---------------------------
2+
16 | val reallybad: Ref^ -> Ref^{} = x => magic(x)(x => x) // error
3+
| ^^^^^^
4+
|Found: (x: Ref^'s1) ->'s2 Ref^{x.rd}
5+
|Required: Ref^ => Ref^{cap.rd}
6+
|
7+
|Note that capability x.rd is not included in capture set {cap.rd}.
8+
|
9+
|where: => refers to a fresh root capability created in anonymous function of type (x: Ref^): Ref^{} when checking argument to parameter x$0 of method apply
10+
| ^ refers to the universal root capability
11+
| cap is a fresh root capability created in anonymous function of type (x: Ref^): Ref^{} when checking argument to parameter x$0 of method apply
12+
|
13+
| longer explanation available when compiling with `-explain`
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import language.experimental.captureChecking
2+
import language.experimental.separationChecking
3+
import caps.{Mutable, freeze}
4+
5+
// A mutable ref and its immutable version
6+
class Ref extends Mutable:
7+
private var data: Int = 0
8+
def get: Int = data
9+
update def set(x: Int): Unit = data = x
10+
def allocRef(): Ref^ = Ref()
11+
type IRef = Ref^{}
12+
13+
def test1(): Unit =
14+
val magic = freeze:
15+
(x: Ref^) => (op: Ref^ => IRef) => op(x)
16+
val reallybad: Ref^ -> Ref^{} = x => magic(x)(x => x) // error

0 commit comments

Comments
 (0)