Skip to content

Commit 24cb35b

Browse files
committed
Disallow old syntax for captures
1 parent 14b1d11 commit 24cb35b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+232
-262
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 7 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -966,29 +966,6 @@ object Parsers {
966966
isArrowIndent()
967967
else false
968968

969-
/** Under captureChecking language import: is the following token sequence a
970-
* capture set `{ref1, ..., refN}` followed by a token that can start a type?
971-
*/
972-
def followingIsCaptureSet(): Boolean =
973-
Feature.ccEnabled && {
974-
val lookahead = in.LookaheadScanner()
975-
def followingIsTypeStart() =
976-
lookahead.nextToken()
977-
canStartInfixTypeTokens.contains(lookahead.token)
978-
|| lookahead.token == LBRACKET
979-
def recur(): Boolean =
980-
(lookahead.isIdent || lookahead.token == THIS) && {
981-
lookahead.nextToken()
982-
if lookahead.token == COMMA then
983-
lookahead.nextToken()
984-
recur()
985-
else
986-
lookahead.token == RBRACE && followingIsTypeStart()
987-
}
988-
lookahead.nextToken()
989-
if lookahead.token == RBRACE then followingIsTypeStart() else recur()
990-
}
991-
992969
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
993970

994971
var opStack: List[OpInfo] = Nil
@@ -1503,9 +1480,12 @@ object Parsers {
15031480
val paramSpan = Span(start, in.lastOffset)
15041481
atSpan(start, in.offset) {
15051482
var token = in.token
1483+
var isPure = false
15061484
if isPureArrow(nme.PUREARROW) then
1485+
isPure = true
15071486
token = ARROW
15081487
else if isPureArrow(nme.PURECTXARROW) then
1488+
isPure = true
15091489
token = CTXARROW
15101490
else if token == TLARROW then
15111491
if !imods.flags.isEmpty || params.isEmpty then
@@ -1524,7 +1504,7 @@ object Parsers {
15241504
else
15251505
accept(ARROW)
15261506

1527-
val resultType = capturesAndResult(typ)
1507+
val resultType = if isPure then capturesAndResult(typ) else typ()
15281508
if token == TLARROW then
15291509
for case ValDef(_, tpt, _) <- params do
15301510
if isByNameType(tpt) then
@@ -1617,8 +1597,6 @@ object Parsers {
16171597
}
16181598
else { accept(TLARROW); typ() }
16191599
}
1620-
else if in.token == LBRACE && followingIsCaptureSet() then
1621-
CapturingTypeTree(captureSet(), typ())
16221600
else if (in.token == INDENT) enclosed(INDENT, typ())
16231601
else infixType()
16241602

@@ -1957,31 +1935,9 @@ object Parsers {
19571935
def paramTypeOf(core: () => Tree): Tree =
19581936
if in.token == ARROW || isPureArrow(nme.PUREARROW) then
19591937
val isImpure = in.token == ARROW
1960-
val tp = atSpan(in.skipToken()) { ByNameTypeTree(capturesAndResult(core)) }
1938+
val tp = atSpan(in.skipToken()):
1939+
ByNameTypeTree(if isImpure then core() else capturesAndResult(core))
19611940
if isImpure && Feature.pureFunsEnabled then ImpureByNameTypeTree(tp) else tp
1962-
else if in.token == LBRACE && followingIsCaptureSet() then
1963-
val start = in.offset
1964-
val cs = captureSet()
1965-
val endCsOffset = in.lastOffset
1966-
val startTpOffset = in.offset
1967-
val tp = paramTypeOf(core)
1968-
val tp1 = tp match
1969-
case ImpureByNameTypeTree(tp1) =>
1970-
syntaxError(em"explicit captureSet is superfluous for impure call-by-name type", start)
1971-
tp1
1972-
case CapturingTypeTree(_, tp1: ByNameTypeTree) =>
1973-
syntaxError(em"only one captureSet is allowed here", start)
1974-
tp1
1975-
case _: ByNameTypeTree if startTpOffset > endCsOffset =>
1976-
report.warning(
1977-
i"""Style: by-name `->` should immediately follow closing `}` of capture set
1978-
|to avoid confusion with function type.
1979-
|That is, `{c}-> T` instead of `{c} -> T`.""",
1980-
source.atSpan(Span(startTpOffset, startTpOffset)))
1981-
tp
1982-
case _ =>
1983-
tp
1984-
CapturingTypeTree(cs, tp1)
19851941
else
19861942
core()
19871943

@@ -2068,8 +2024,6 @@ object Parsers {
20682024
def typeDependingOn(location: Location): Tree =
20692025
if location.inParens then typ()
20702026
else if location.inPattern then rejectWildcardType(refinedType())
2071-
else if in.token == LBRACE && followingIsCaptureSet() then
2072-
CapturingTypeTree(captureSet(), infixType())
20732027
else infixType()
20742028

20752029
/* ----------- EXPRESSIONS ------------------------------------------------ */
@@ -4217,10 +4171,7 @@ object Parsers {
42174171
val selfTpt =
42184172
if in.isColon then
42194173
in.nextToken()
4220-
if in.token == LBRACE && followingIsCaptureSet() then
4221-
CapturingTypeTree(captureSet(), infixType())
4222-
else
4223-
infixType()
4174+
infixType()
42244175
else
42254176
if selfName == nme.WILDCARD then accept(COLONfollow)
42264177
TypeTree()

tests/neg-custom-args/capt-wf.scala

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
class C
2-
type Cap = {*} C
2+
type Cap = C^
33

44
object foo
55

66
def test(c: Cap, other: String): Unit =
7-
val x1: {*} C = ??? // OK
8-
val x2: {other} C = ??? // error: cs is empty
7+
val x1: C^ = ??? // OK
8+
val x2: C^{other} = ??? // error: cs is empty
99
val s1 = () => "abc"
10-
val x3: {s1} C = ??? // error: cs is empty
10+
val x3: C^{s1} = ??? // error: cs is empty
1111
val x3a: () -> String = s1
1212
val s2 = () => if x1 == null then "" else "abc"
13-
val x4: {s2} C = ??? // OK
14-
val x5: {c, c} C = ??? // error: redundant
15-
val x6: {c} {c} C = ??? // error: redundant
16-
val x7: {c} Cap = ??? // error: redundant
17-
val x8: {*} {c} C = ??? // OK
18-
val x9: {c, *} C = ??? // error: redundant
19-
val x10: {*, c} C = ??? // error: redundant
13+
val x4: C^{s2} = ??? // OK
14+
val x5: C^{c, c} = ??? // error: redundant
15+
// val x6: C^{c}^{c} = ??? // would be syntax error
16+
val x7: Cap^{c} = ??? // error: redundant
17+
// val x8: C^{c}^{*} = ??? // would be syntax error
18+
val x9: C^{c, *} = ??? // error: redundant
19+
val x10: C^{*, c} = ??? // error: redundant
2020

2121
def even(n: Int): Boolean = if n == 0 then true else odd(n - 1)
2222
def odd(n: Int): Boolean = if n == 1 then true else even(n - 1)
2323
val e1 = even
2424
val o1 = odd
2525

26-
val y1: {e1} String = ??? // error cs is empty
27-
val y2: {o1} String = ??? // error cs is empty
26+
val y1: String^{e1} = ??? // error cs is empty
27+
val y2: String^{o1} = ??? // error cs is empty
2828

2929
lazy val ev: (Int -> Boolean) = (n: Int) =>
3030
lazy val od: (Int -> Boolean) = (n: Int) =>
3131
if n == 1 then true else ev(n - 1)
3232
if n == 0 then true else od(n - 1)
33-
val y3: {ev} String = ??? // error cs is empty
33+
val y3: String^{ev} = ??? // error cs is empty
3434

3535
()

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ object test {
66

77
class C[X <: Tree](x: X)
88

9-
def foo(t: {*} Tree) =
9+
def foo(t: Tree^) =
1010
f(t) // error
11-
f[{*} Tree](t) // error
11+
f[Tree^](t) // error
1212
f[Tree](t) // error
1313
val c1 = C(t) // error
14-
val c2 = C[{*} Tree](t) // error
14+
val c2 = C[Tree^](t) // error
1515
val c3 = C[Tree](t) // error
1616

17-
val foo: C[{*} Tree] = ???
17+
val foo: C[Tree^] = ???
1818
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ object test {
66

77
class C[X <: Tree](x: X)
88

9-
val foo: C[{*} Tree] = ??? // error
10-
type T = C[{*} Tree] // error
9+
val foo: C[Tree^] = ??? // error
10+
type T = C[Tree^] // error
1111
val bar: T -> T = ???
12-
val baz: C[{*} Tree] -> Unit = ??? // error
12+
val baz: C[Tree^] -> Unit = ??? // error
1313
}
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
trait Cap
22

3-
def main(io: {*} Cap, fs: {*} Cap): Unit = {
4-
val test1: {} Unit -> Unit = _ => { // error
5-
type Op = [T] -> ({io} T -> Unit) -> Unit
6-
val f: ({io} Cap) -> Unit = ???
3+
def main(io: Cap^, fs: Cap^): Unit = {
4+
val test1: Unit -> Unit = _ => { // error
5+
type Op = [T] -> (T ->{io} Unit) -> Unit
6+
val f: (Cap^{io}) -> Unit = ???
77
val op: Op = ???
8-
op[{io} Cap](f)
8+
op[Cap^{io}](f)
99
// expected type of f: {io} (box {io} Cap) -> Unit
1010
// actual type: ({io} Cap) -> Unit
1111
// adapting f to the expected type will also
1212
// charge the environment with {io}
1313
}
1414

15-
val test2: {} Unit -> Unit = _ => {
15+
val test2: Unit -> Unit = _ => {
1616
type Box[X] = X
1717
type Op0[X] = Box[X] -> Unit
1818
type Op1[X] = Unit -> Box[X]
19-
val f: Unit -> ({io} Cap) -> Unit = ???
20-
val test: {} Op1[{io} Op0[{io} Cap]] = f
19+
val f: Unit -> (Cap^{io}) -> Unit = ???
20+
val test: Op1[Op0[Cap^{io}]^{io}]^{} = f
2121
// expected: {} Unit -> box {io} (box {io} Cap) -> Unit
2222
// actual: Unit -> ({io} Cap) -> Unit
2323
//
@@ -31,8 +31,8 @@ def main(io: {*} Cap, fs: {*} Cap): Unit = {
3131
type Box[X] = X
3232
type Id[X] = Box[X] -> Unit
3333
type Op[X] = Unit -> Box[X]
34-
val f: Unit -> ({io} Cap) -> Unit = ???
35-
val g: Op[{fs} Id[{io} Cap]] = f // error
36-
val h: {} Op[{io} Id[{io} Cap]] = f
34+
val f: Unit -> (Cap^{io}) -> Unit = ???
35+
val g: Op[Id[Cap^{io}]^{fs}] = f // error
36+
val h: Op[Id[Cap^{io}]^{io}] = f
3737
}
3838
}

tests/neg-custom-args/captures/box-adapt-cases.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@ trait Cap { def use(): Int }
33
def test1(): Unit = {
44
type Id[X] = [T] -> (op: X => T) -> T
55

6-
val x: Id[{*} Cap] = ???
6+
val x: Id[Cap^] = ???
77
x(cap => cap.use()) // error
88
}
99

10-
def test2(io: {*} Cap): Unit = {
10+
def test2(io: Cap^{*}): Unit = {
1111
type Id[X] = [T] -> (op: X -> T) -> T
1212

13-
val x: Id[{io} Cap] = ???
13+
val x: Id[Cap^{io}] = ???
1414
x(cap => cap.use()) // error
1515
}
1616

17-
def test3(io: {*} Cap): Unit = {
18-
type Id[X] = [T] -> (op: {io} X -> T) -> T
17+
def test3(io: Cap^{*}): Unit = {
18+
type Id[X] = [T] -> (op: X ->{io} T) -> T
1919

20-
val x: Id[{io} Cap] = ???
20+
val x: Id[Cap^{io}] = ???
2121
x(cap => cap.use()) // ok
2222
}
2323

24-
def test4(io: {*} Cap, fs: {*} Cap): Unit = {
25-
type Id[X] = [T] -> (op: {io} X -> T) -> T
24+
def test4(io: Cap^{*}, fs: Cap^{*}): Unit = {
25+
type Id[X] = [T] -> (op: X ->{io} T) -> T
2626

27-
val x: Id[{io, fs} Cap] = ???
27+
val x: Id[Cap^{io, fs}] = ???
2828
x(cap => cap.use()) // error
2929
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
trait Cap
22

3-
def test1(io: {*} Cap) = {
3+
def test1(io: Cap^{*}) = {
44
type Op[X] = [T] -> Unit -> X
5-
val f: Op[{io} Cap] = ???
6-
val x: [T] -> Unit -> ({io} Cap) = f // error
5+
val f: Op[Cap^{io}] = ???
6+
val x: [T] -> Unit -> Cap^{io} = f // error
77
}
88

9-
def test2(io: {*} Cap) = {
10-
type Op[X] = [T] -> Unit -> {io} X
11-
val f: Op[{io} Cap] = ???
12-
val x: Unit -> ({io} Cap) = f[Unit] // error
13-
val x1: {io} Unit -> ({io} Cap) = f[Unit] // ok
9+
def test2(io: Cap^{*}) = {
10+
type Op[X] = [T] -> Unit -> X^{io}
11+
val f: Op[Cap^{io}] = ???
12+
val x: Unit -> Cap^{io} = f[Unit] // error
13+
val x1: Unit ->{io} Cap^{io} = f[Unit] // ok
1414
}
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
trait Cap { def use(): Int }
22

3-
def test1(io: {*} Cap): Unit = {
4-
type Id[X] = [T] -> (op: {io} X -> T) -> T
3+
def test1(io: Cap^{*}): Unit = {
4+
type Id[X] = [T] -> (op: X ->{io} T) -> T
55

6-
val x: Id[{io} Cap] = ???
7-
val f: ({*} Cap) -> Unit = ???
6+
val x: Id[Cap^{io}] = ???
7+
val f: (Cap^{*}) -> Unit = ???
88
x(f) // ok
9-
// actual: {*} Cap -> Unit
10-
// expected: {io} box {io} Cap -> Unit
119
}
1210

13-
def test2(io: {*} Cap): Unit = {
14-
type Id[X] = [T] -> (op: {*} X -> T) -> T
11+
def test2(io: Cap^{*}): Unit = {
12+
type Id[X] = [T] -> (op: X => T) -> T
1513

16-
val x: Id[{*} Cap] = ???
17-
val f: ({io} Cap) -> Unit = ???
14+
val x: Id[Cap^] = ???
15+
val f: Cap^{io} -> Unit = ???
1816
x(f) // error
1917
}
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
trait Cap { def use(): Int }
22

3-
def test1(io: {*} Cap): Unit = {
4-
type Id[X] = [T] -> (op: {io} X -> T) -> T
3+
def test1(io: Cap^): Unit = {
4+
type Id[X] = [T] -> (op: X ->{io} T) -> T
55

6-
val x: Id[{io} Cap] = ???
6+
val x: Id[Cap]^{io} = ???
77
x(cap => cap.use()) // ok
88
}
99

10-
def test2(io: {*} Cap): Unit = {
11-
type Id[X] = [T] -> (op: {io} (x: X) -> T) -> T
10+
def test2(io: Cap^): Unit = {
11+
type Id[X] = [T] -> (op: (x: X) ->{io} T) -> T
1212

13-
val x: Id[{io} Cap] = ???
13+
val x: Id[Cap^{io}] = ???
1414
x(cap => cap.use())
1515
// should work when the expected type is a dependent function
1616
}
1717

18-
def test3(io: {*} Cap): Unit = {
19-
type Id[X] = [T] -> (op: {} (x: X) -> T) -> T
18+
def test3(io: Cap^{*}): Unit = {
19+
type Id[X] = [T] -> (op: (x: X) ->{} T) -> T
2020

21-
val x: Id[{io} Cap] = ???
21+
val x: Id[Cap^{io}] = ???
2222
x(cap => cap.use()) // error
2323
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
trait Cap { def use(): Int }
22

3-
def test1(io: {*} Cap): Unit = {
3+
def test1(io: Cap^{*}): Unit = {
44
type Op[X] = [T] -> X -> Unit
5-
val f: [T] -> ({io} Cap) -> Unit = ???
6-
val op: Op[{io} Cap] = f // error
5+
val f: [T] -> (Cap^{io}) -> Unit = ???
6+
val op: Op[Cap^{io}] = f // error
77
}
88

9-
def test2(io: {*} Cap): Unit = {
9+
def test2(io: Cap^{*}): Unit = {
1010
type Lazy[X] = [T] -> Unit -> X
11-
val f: Lazy[{io} Cap] = ???
12-
val test: [T] -> Unit -> ({io} Cap) = f // error
11+
val f: Lazy[Cap^{io}] = ???
12+
val test: [T] -> Unit -> (Cap^{io}) = f // error
1313
}

tests/neg-custom-args/captures/capt-depfun.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ class Str
66
def f(y: Cap, z: Cap) =
77
def g(): C @retains(y, z) = ???
88
val ac: ((x: Cap) => Str @retains(x) => Str @retains(x)) = ???
9-
val dc: (({y, z} Str) => {y, z} Str) = ac(g()) // error
9+
val dc: ((Str^{y, z}) => Str^{y, z}) = ac(g()) // error

tests/neg-custom-args/captures/capt-env.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class C
2-
type Cap = {*} C
2+
type Cap = C^
33

44
class Pair[+A, +B](x: A, y: B):
55
def fst: A = x

0 commit comments

Comments
 (0)