@@ -37,6 +37,7 @@ import dotty.tools.dotc.config.MigrationVersion
37
37
import dotty .tools .dotc .util .chaining .*
38
38
import dotty .tools .dotc .config .Feature .ccEnabled
39
39
import dotty .tools .dotc .core .Types .AndType .make
40
+ import dotty .tools .dotc .config .Printers .capt
40
41
41
42
object Parsers {
42
43
@@ -2102,7 +2103,7 @@ object Parsers {
2102
2103
case HASH => simpleTypeRest(typeProjection(t))
2103
2104
case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
2104
2105
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 )
2106
2107
2107
2108
if (! ctx.settings.XkindProjector .isDefault) {
2108
2109
def fail (): Tree = {
@@ -2190,6 +2191,31 @@ object Parsers {
2190
2191
commaSeparated(() => argType())
2191
2192
end argTypes
2192
2193
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
+
2193
2219
def paramTypeOf (core : () => Tree ): Tree =
2194
2220
if in.token == ARROW || isPureArrow(nme.PUREARROW ) then
2195
2221
val isImpure = in.token == ARROW
@@ -2237,6 +2263,11 @@ object Parsers {
2237
2263
def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] =
2238
2264
inBracketsWithCommas(argTypes(namedOK, wildOK, tupleOK = false ))
2239
2265
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
+
2240
2271
/** Refinement ::= `{' RefineStatSeq `}'
2241
2272
*/
2242
2273
def refinement (indentOK : Boolean ): List [Tree ] =
@@ -2816,7 +2847,10 @@ object Parsers {
2816
2847
in.nextToken()
2817
2848
simpleExprRest(selectorOrMatch(t), location, canApply = true )
2818
2849
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
+ }
2820
2854
simpleExprRest(tapp, location, canApply = true )
2821
2855
case LPAREN | LBRACE | INDENT if canApply =>
2822
2856
val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }
0 commit comments