Skip to content

Commit 23c8b74

Browse files
committed
Support for cap arguments
1 parent 76112f3 commit 23c8b74

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

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

+36-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import dotty.tools.dotc.config.MigrationVersion
3737
import dotty.tools.dotc.util.chaining.*
3838
import dotty.tools.dotc.config.Feature.ccEnabled
3939
import dotty.tools.dotc.core.Types.AndType.make
40+
import dotty.tools.dotc.config.Printers.capt
4041

4142
object Parsers {
4243

@@ -2102,7 +2103,7 @@ object Parsers {
21022103
case HASH => simpleTypeRest(typeProjection(t))
21032104
case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
21042105
val applied = rejectWildcardType(t)
2105-
val args = typeArgs(namedOK = false, wildOK = true)
2106+
val args = if isCapKwNext then captureArgs(namedOK = false, wildOK = false) else typeArgs(namedOK = false, wildOK = true)
21062107

21072108
if (!ctx.settings.XkindProjector.isDefault) {
21082109
def fail(): Tree = {
@@ -2190,6 +2191,31 @@ object Parsers {
21902191
commaSeparated(() => argType())
21912192
end argTypes
21922193

2194+
def argCaps(namedOK: Boolean, wildOK: Boolean, tupleOK: Boolean): List[Tree] = // TODO grammar doc
2195+
def argType() =
2196+
val t = concreteCapsType(captureSetOrRef())
2197+
if wildOK then t else rejectWildcardType(t) // TODO needed?
2198+
2199+
def namedArgType() =
2200+
atSpan(in.offset):
2201+
val name = ident()
2202+
accept(EQUALS)
2203+
NamedArg(name.toTypeName, argType())
2204+
2205+
def namedElem() =
2206+
atSpan(in.offset):
2207+
val name = ident()
2208+
acceptColon()
2209+
NamedArg(name, argType())
2210+
2211+
if namedOK && isIdent && in.lookahead.token == EQUALS then
2212+
commaSeparated(() => namedArgType())
2213+
else if tupleOK && isIdent && in.lookahead.isColon && in.featureEnabled(Feature.namedTuples) then
2214+
commaSeparated(() => namedElem())
2215+
else
2216+
commaSeparated(() => argType())
2217+
end argCaps
2218+
21932219
def paramTypeOf(core: () => Tree): Tree =
21942220
if in.token == ARROW || isPureArrow(nme.PUREARROW) then
21952221
val isImpure = in.token == ARROW
@@ -2237,6 +2263,11 @@ object Parsers {
22372263
def typeArgs(namedOK: Boolean, wildOK: Boolean): List[Tree] =
22382264
inBracketsWithCommas(argTypes(namedOK, wildOK, tupleOK = false))
22392265

2266+
def captureArgs(namedOK: Boolean, wildOK: Boolean): List[Tree] = inBracketsWithCommas {
2267+
in.nextToken() // assumes we are the `cap` soft keyword
2268+
argCaps(namedOK, wildOK, tupleOK = false) //TODO grammar doc
2269+
}
2270+
22402271
/** Refinement ::= `{' RefineStatSeq `}'
22412272
*/
22422273
def refinement(indentOK: Boolean): List[Tree] =
@@ -2816,7 +2847,10 @@ object Parsers {
28162847
in.nextToken()
28172848
simpleExprRest(selectorOrMatch(t), location, canApply = true)
28182849
case LBRACKET =>
2819-
val tapp = atSpan(startOffset(t), in.offset) { TypeApply(t, typeArgs(namedOK = true, wildOK = false)) }
2850+
val tapp = atSpan(startOffset(t), in.offset) {
2851+
val args = if isCapKwNext then captureArgs(namedOK = true, wildOK = false) else typeArgs(namedOK = true, wildOK = false)
2852+
TypeApply(t, args)
2853+
}
28202854
simpleExprRest(tapp, location, canApply = true)
28212855
case LPAREN | LBRACE | INDENT if canApply =>
28222856
val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }

tests/pos-custom-args/captures/cap-paramlists.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ def test =
3030
trait Foo[cap U,V,W]:
3131
cap C = caps.cap
3232
cap D = {caps.cap}
33-
cap E >: {V,W} <: U
33+
cap E >: {V,W} <: U
34+
35+
def test2 =
36+
val x: Any^ = ???
37+
def foo[cap A, B >: A](x: Int) = 1
38+
foo[cap x, x](0)
39+
foo[cap A = x, B = {x}](0)
40+
foo[cap A = {x}](0)

0 commit comments

Comments
 (0)