Skip to content

Commit f16d565

Browse files
committed
Add note and a test to show the prefix rule for path subsuming
1 parent 1b0634a commit f16d565

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

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

+6
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ trait CaptureRef extends TypeProxy, ValueType:
123123
this.subsumes(ypre)
124124
|| this.match
125125
case x @ TermRef(xpre: CaptureRef, _) if x.symbol == y.symbol =>
126+
// To show `{x.f} <:< {y.f}`, it is important to prove `x` and `y`
127+
// are equvalent, which means `x =:= y` in terms for subtyping,
128+
// not just `{x} =:= {y}`.
129+
// It is posible to construct two singleton types `x` and `y`,
130+
// which subumse each other, but are not equal references.
131+
// See `tests/neg-custom-args/captures/path-prefix.scala` for example.
126132
withMode(Mode.IgnoreCaptures) {TypeComparer.isSameRef(xpre, ypre)}
127133
case _ =>
128134
false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import language.experimental.modularity
2+
import language.experimental.captureChecking
3+
import caps.Capability
4+
5+
class F:
6+
val f: AnyRef^ = ???
7+
8+
case class B(tracked val a: A) extends F, Capability
9+
10+
class A extends F, Capability:
11+
val b: B { val a: A.this.type } = B(this)
12+
13+
def test(a: A) =
14+
val x: a.b.type = a.b
15+
val y: x.a.type = x.a
16+
// x and y are two distinct singleton types with following properties:
17+
// x =:= a.b
18+
// y =:= x.a =:= a.b.a =:= a
19+
20+
val cx: AnyRef^{x} = ???
21+
val cy: AnyRef^{y} = ???
22+
val caf: AnyRef^{a.f} = ???
23+
val cabf: AnyRef^{a.b.f} = ???
24+
val cxf: AnyRef^{x.f} = ???
25+
val cyf: AnyRef^{y.f} = ???
26+
27+
// x and y subsume to each other:
28+
// * {x} <:< {y}: the underlying singleton of y is x.a,
29+
// and the underlying singleton of x.a is a,
30+
// which is a prefix for the underlying type of x (a.b),
31+
// hence {x} <:< {y};
32+
// * {y} <:< {x}: by underlying singleton of y is x.a, whose prefix is x.
33+
// Hence, {x} =:= {y}.
34+
val x2y: AnyRef^{y} = cx
35+
val y2x: AnyRef^{x} = cy
36+
37+
val yf2af: AnyRef^{a.f} = cyf
38+
val af2yf: AnyRef^{y.f} = caf
39+
val xf2abf: AnyRef^{a.b.f} = cxf
40+
val abf2xf: AnyRef^{x.f} = cabf
41+
42+
// Since `x !=:= y`, {x.f} !=:= {y.f}
43+
val yf2xf: AnyRef^{x.f} = cyf // error
44+
val xf2yf: AnyRef^{y.f} = cxf // error

0 commit comments

Comments
 (0)