Skip to content

Commit fb45ece

Browse files
committed
By default don't include span captures in the underlying capset
What is the underlying capture set of a function? CC says the capture set on the first arrow but we experimented with the capture of the span of the function instead. This however causes a lot of complications if we want to push it to a logical conclusion. So we now make it configurable and by default span capture set is not used.
1 parent 0abc0d3 commit fb45ece

File tree

12 files changed

+41
-82
lines changed

12 files changed

+41
-82
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ object CaptureSet:
15651565
// `ref` will not seem subsumed by other capabilities in a `++`.
15661566
universal
15671567
case c: CoreCapability =>
1568-
ofType(c.underlying, followResult = true)
1568+
ofType(c.underlying, followResult = ccConfig.useSpanCapset)
15691569

15701570
/** Capture set of a type
15711571
* @param followResult If true, also include capture sets of function results.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ class CheckCaptures extends Recheck, SymTransformer:
496496
case _ => c.core match
497497
case c1: RootCapability => c1.singletonCaptureSet
498498
case c1: CoreCapability =>
499-
CaptureSet.ofType(c1.widen, followResult = true)
499+
CaptureSet.ofType(c1.widen, followResult = ccConfig.useSpanCapset)
500500
capt.println(i"Widen reach $c to $underlying in ${env.owner}")
501501
underlying.disallowBadRoots(NoSymbol): () =>
502502
report.error(em"Local capability $c${env.owner.qualString("in")} cannot have `cap` as underlying capture set", tree.srcPos)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ object ccConfig:
4343
*/
4444
inline val postCheckCapturesets = false
4545

46+
/** If true take as the underlying capture set of a capability of function type
47+
* the capture set along the span, including capture sets of function results.
48+
*/
49+
inline val useSpanCapset = false
50+
4651
/** If true, do level checking for FreshCap instances */
4752
def useFreshLevels(using Context): Boolean =
4853
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.7`)

library/src/scala/collection/Iterator.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
* See the NOTICE file distributed with this work for
1010
* additional information regarding copyright ownership.
1111
*/
12-
1312
package scala.collection
1413

1514
import scala.language.`2.13`

tests/neg-custom-args/captures/eta.check

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,3 @@
77
| Note that capability f is not included in capture set {}.
88
|
99
| longer explanation available when compiling with `-explain`
10-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/eta.scala:7:7 --------------------------------------------
11-
7 | () => { stowaway.apply().apply() } // error (was ok)
12-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13-
| Found: () ->{stowaway} Unit
14-
| Required: () -> Unit
15-
|
16-
| Note that capability stowaway is not included in capture set {}.
17-
|
18-
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/eta.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
g // error
55
val stowaway: () -> Proc^{f} =
66
bar( () => f ) // was error now OK
7-
() => { stowaway.apply().apply() } // error (was ok)
7+
() => { stowaway.apply().apply() }

tests/neg-custom-args/captures/scoped-caps.check

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,17 @@
4949
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:12:20 ----------------------------------
5050
12 | val _: A^ -> B^ = x => g(x) // error: g is no longer pure, since it contains the ^ of B
5151
| ^^^^^^^^^
52-
| Found: (x: A^) ->{g} B^²
52+
| Found: (x: A^) ->'s1 B^²
5353
| Required: A^ -> B^³
5454
|
55-
| Note that capability g is not included in capture set {}.
55+
| Note that capability cap is not included in capture set {cap²}
56+
| because cap is not visible from cap² in value _$5.
5657
|
57-
| where: ^ refers to the universal root capability
58-
| ^² refers to a root capability associated with the result type of (x: A^): B^²
59-
| ^³ refers to a fresh root capability in the type of value _$5
58+
| where: ^ refers to the universal root capability
59+
| ^² refers to a root capability associated with the result type of (x: A^): B^²
60+
| ^³ refers to a fresh root capability in the type of value _$5
61+
| cap is a root capability associated with the result type of (x: A^): B^²
62+
| cap² is a fresh root capability in the type of value _$5
6063
|
6164
| longer explanation available when compiling with `-explain`
6265
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:16:24 ----------------------------------
@@ -75,61 +78,35 @@
7578
| cap is a root capability associated with the result type of (x: S^): B^²
7679
|
7780
| longer explanation available when compiling with `-explain`
78-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:17:24 ----------------------------------
79-
17 | val _: (x: S) -> B^ = (x: S) => h(x) // error: eta expansion fails
80-
| ^^^^^^^^^^^^^^
81-
| Found: (x: S^) ->{h} B^²
82-
| Required: (x: S^) -> B^³
83-
|
84-
| Note that capability h is not included in capture set {}.
85-
|
86-
| where: ^ refers to the universal root capability
87-
| ^² refers to a root capability associated with the result type of (x: S^): B^²
88-
| ^³ refers to a root capability associated with the result type of (x: S^): B^³
89-
|
90-
| longer explanation available when compiling with `-explain`
91-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:21:23 ----------------------------------
92-
21 | val _: (x: S) -> S = (x: S) => h2(x) // error: eta conversion fails since `h2` is now impure (result type S is a capability)
93-
| ^^^^^^^^^^^^^^^
94-
| Found: (x: S^) ->{h2} S^²
95-
| Required: (x: S^) -> S^³
96-
|
97-
| Note that capability h2 is not included in capture set {}.
98-
|
99-
| where: ^ refers to the universal root capability
100-
| ^² refers to a root capability associated with the result type of (x: S^): S^²
101-
| ^³ refers to a root capability associated with the result type of (x: S^): S^³
102-
|
103-
| longer explanation available when compiling with `-explain`
104-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:27:19 ----------------------------------
105-
27 | val _: S -> B^ = j // error
81+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:26:19 ----------------------------------
82+
26 | val _: S -> B^ = j // error
10683
| ^
10784
| Found: (j : (x: S) -> B^)
10885
| Required: S^² -> B^³
10986
|
11087
| Note that capability cap is not included in capture set {cap²}
111-
| because cap is not visible from cap² in value _$14.
88+
| because cap is not visible from cap² in value _$13.
11289
|
11390
| where: ^ refers to a root capability associated with the result type of (x: S^²): B^
11491
| ^² refers to the universal root capability
115-
| ^³ refers to a fresh root capability in the type of value _$14
92+
| ^³ refers to a fresh root capability in the type of value _$13
11693
| cap is a root capability associated with the result type of (x: S^²): B^
117-
| cap² is a fresh root capability in the type of value _$14
94+
| cap² is a fresh root capability in the type of value _$13
11895
|
11996
| longer explanation available when compiling with `-explain`
120-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:28:19 ----------------------------------
121-
28 | val _: S -> B^ = x => j(x) // error
97+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps.scala:27:19 ----------------------------------
98+
27 | val _: S -> B^ = x => j(x) // error
12299
| ^^^^^^^^^
123-
| Found: (x: S^) ->'s1 B^²
100+
| Found: (x: S^) ->'s2 B^²
124101
| Required: S^ -> B^³
125102
|
126103
| Note that capability cap is not included in capture set {cap²}
127-
| because cap is not visible from cap² in value _$15.
104+
| because cap is not visible from cap² in value _$14.
128105
|
129106
| where: ^ refers to the universal root capability
130107
| ^² refers to a root capability associated with the result type of (x: S^): B^²
131-
| ^³ refers to a fresh root capability in the type of value _$15
108+
| ^³ refers to a fresh root capability in the type of value _$14
132109
| cap is a root capability associated with the result type of (x: S^): B^²
133-
| cap² is a fresh root capability in the type of value _$15
110+
| cap² is a fresh root capability in the type of value _$14
134111
|
135112
| longer explanation available when compiling with `-explain`

tests/neg-custom-args/captures/scoped-caps.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ def test(io: Object^): Unit =
1414

1515
val h: S -> B^ = ???
1616
val _: (x: S) -> B^ = h // error: direct conversion fails
17-
val _: (x: S) -> B^ = (x: S) => h(x) // error: eta expansion fails
17+
val _: (x: S) -> B^ = (x: S) => h(x) // eta expansion is ok
1818

1919
val h2: S -> S = ???
2020
val _: (x: S) -> S = h2 // direct conversion OK for shared S
21-
val _: (x: S) -> S = (x: S) => h2(x) // error: eta conversion fails since `h2` is now impure (result type S is a capability)
22-
val _: (x: S) ->{h2} S = (x: S) => h2(x) // eta expansion OK
21+
val _: (x: S) -> S = (x: S) => h2(x) // eta conversion is also OK
2322

2423
val j: (x: S) -> B^ = ???
2524
val _: (x: S) -> B^ = j

tests/neg-custom-args/captures/scoped-caps2.check

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
| Note that the existential capture root in C^
88
| cannot subsume the capability cap..
99
|
10-
| Note that capability cap is not included in capture set {cap²}.
10+
| Note that capability cap² is not included in capture set {cap³}.
1111
|
1212
| where: => refers to a fresh root capability in the type of value b
1313
| =>² refers to a fresh root capability in the type of value _$1
1414
| ^ refers to the universal root capability
1515
| ^² refers to a root capability associated with the result type of (x: C^): C^²
1616
| cap is a fresh root capability classified as SharedCapability in the type of value b
1717
| cap² is a fresh root capability in the type of value b
18+
| cap³ is a fresh root capability in the type of value _$1
1819
|
1920
| longer explanation available when compiling with `-explain`
2021
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps2.scala:6:18 ----------------------------------
@@ -65,19 +66,6 @@
6566
| cap² is a fresh root capability classified as SharedCapability in the type of value _$6
6667
|
6768
| longer explanation available when compiling with `-explain`
68-
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps2.scala:15:23 ---------------------------------
69-
15 | val _: (x: C) -> C = (x: C) => b(x) // error
70-
| ^^^^^^^^^^^^^^
71-
| Found: (x: C^) ->{b} C^²
72-
| Required: (x: C^) -> C^³
73-
|
74-
| Note that capability b is not included in capture set {}.
75-
|
76-
| where: ^ refers to the universal root capability
77-
| ^² refers to a root capability associated with the result type of (x: C^): C^²
78-
| ^³ refers to a root capability associated with the result type of (x: C^): C^³
79-
|
80-
| longer explanation available when compiling with `-explain`
8169
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/scoped-caps2.scala:16:29 ---------------------------------
8270
16 | val _: C -> C = (x: C) => a(x) // error
8371
| ^^^^

tests/neg-custom-args/captures/scoped-caps2.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ def test1(c: C) =
44
val b: C => C = ???
55
val _: (x: C) => C = b // error
66
val _: C => C = a // error
7-
val _: (x: C) => C = (x: C) => b(x) // OK
7+
val _: (x: C) => C = (x: C) => (b(x): C) // OK
88
val _: C => C = (x: C) => a(x) // error
99

1010
def test2(c: C) =
1111
val a: (x: C) -> C = ???
1212
val b: C -> C = ???
1313
val _: (x: C) -> C = b // OK
1414
val _: C -> C = a // error
15-
val _: (x: C) -> C = (x: C) => b(x) // error
15+
val _: (x: C) -> C = (x: C) => b(x) // ok
1616
val _: C -> C = (x: C) => a(x) // error
1717

0 commit comments

Comments
 (0)