Skip to content

Commit 9127445

Browse files
committed
Disallow old syntax for captures
1 parent 1415532 commit 9127445

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
@@ -970,29 +970,6 @@ object Parsers {
970970
isArrowIndent()
971971
else false
972972

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

998975
var opStack: List[OpInfo] = Nil
@@ -1504,9 +1481,12 @@ object Parsers {
15041481
val paramSpan = Span(start, in.lastOffset)
15051482
atSpan(start, in.offset) {
15061483
var token = in.token
1484+
var isPure = false
15071485
if isPureArrow(nme.PUREARROW) then
1486+
isPure = true
15081487
token = ARROW
15091488
else if isPureArrow(nme.PURECTXARROW) then
1489+
isPure = true
15101490
token = CTXARROW
15111491
else if token == TLARROW then
15121492
if !imods.flags.isEmpty || params.isEmpty then
@@ -1525,7 +1505,7 @@ object Parsers {
15251505
else
15261506
accept(ARROW)
15271507

1528-
val resultType = capturesAndResult(typ)
1508+
val resultType = if isPure then capturesAndResult(typ) else typ()
15291509
if token == TLARROW then
15301510
for case ValDef(_, tpt, _) <- params do
15311511
if isByNameType(tpt) then
@@ -1618,8 +1598,6 @@ object Parsers {
16181598
}
16191599
else { accept(TLARROW); typ() }
16201600
}
1621-
else if in.token == LBRACE && followingIsCaptureSet() then
1622-
CapturingTypeTree(captureSet(), typ())
16231601
else if (in.token == INDENT) enclosed(INDENT, typ())
16241602
else infixType()
16251603

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

@@ -2069,8 +2025,6 @@ object Parsers {
20692025
def typeDependingOn(location: Location): Tree =
20702026
if location.inParens then typ()
20712027
else if location.inPattern then rejectWildcardType(refinedType())
2072-
else if in.token == LBRACE && followingIsCaptureSet() then
2073-
CapturingTypeTree(captureSet(), infixType())
20742028
else infixType()
20752029

20762030
/* ----------- EXPRESSIONS ------------------------------------------------ */
@@ -4218,10 +4172,7 @@ object Parsers {
42184172
val selfTpt =
42194173
if in.isColon then
42204174
in.nextToken()
4221-
if in.token == LBRACE && followingIsCaptureSet() then
4222-
CapturingTypeTree(captureSet(), infixType())
4223-
else
4224-
infixType()
4175+
infixType()
42254176
else
42264177
if selfName == nme.WILDCARD then accept(COLONfollow)
42274178
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)