@@ -37,6 +37,7 @@ import dotty.tools.dotc.config.MigrationVersion
3737import dotty .tools .dotc .util .chaining .*
3838import dotty .tools .dotc .config .Feature .ccEnabled
3939import dotty .tools .dotc .core .Types .AndType .make
40+ import dotty .tools .dotc .config .Printers .capt
4041
4142object Parsers {
4243
@@ -2109,7 +2110,7 @@ object Parsers {
21092110 case HASH => simpleTypeRest(typeProjection(t))
21102111 case LBRACKET => simpleTypeRest(atSpan(startOffset(t)) {
21112112 val applied = rejectWildcardType(t)
2112- val args = typeArgs(namedOK = false , wildOK = true )
2113+ val args = if isCapKwNext then captureArgs(namedOK = false , wildOK = false ) else typeArgs(namedOK = false , wildOK = true )
21132114
21142115 if (! ctx.settings.XkindProjector .isDefault) {
21152116 def fail (): Tree = {
@@ -2197,6 +2198,31 @@ object Parsers {
21972198 commaSeparated(() => argType())
21982199 end argTypes
21992200
2201+ def argCaps (namedOK : Boolean , wildOK : Boolean , tupleOK : Boolean ): List [Tree ] = // TODO grammar doc
2202+ def argType () =
2203+ val t = concreteCapsType(captureSetOrRef())
2204+ if wildOK then t else rejectWildcardType(t) // TODO needed?
2205+
2206+ def namedArgType () =
2207+ atSpan(in.offset):
2208+ val name = ident()
2209+ accept(EQUALS )
2210+ NamedArg (name.toTypeName, argType())
2211+
2212+ def namedElem () =
2213+ atSpan(in.offset):
2214+ val name = ident()
2215+ acceptColon()
2216+ NamedArg (name, argType())
2217+
2218+ if namedOK && isIdent && in.lookahead.token == EQUALS then
2219+ commaSeparated(() => namedArgType())
2220+ else if tupleOK && isIdent && in.lookahead.isColon && sourceVersion.enablesNamedTuples then
2221+ commaSeparated(() => namedElem())
2222+ else
2223+ commaSeparated(() => argType())
2224+ end argCaps
2225+
22002226 def paramTypeOf (core : () => Tree ): Tree =
22012227 if in.token == ARROW || isPureArrow(nme.PUREARROW ) then
22022228 val isImpure = in.token == ARROW
@@ -2244,6 +2270,11 @@ object Parsers {
22442270 def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] =
22452271 inBracketsWithCommas(argTypes(namedOK, wildOK, tupleOK = false ))
22462272
2273+ def captureArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] = inBracketsWithCommas {
2274+ in.nextToken() // assumes we are the `cap` soft keyword
2275+ argCaps(namedOK, wildOK, tupleOK = false ) // TODO grammar doc
2276+ }
2277+
22472278 /** Refinement ::= `{' RefineStatSeq `}'
22482279 */
22492280 def refinement (indentOK : Boolean ): List [Tree ] =
@@ -2823,7 +2854,10 @@ object Parsers {
28232854 in.nextToken()
28242855 simpleExprRest(selectorOrMatch(t), location, canApply = true )
28252856 case LBRACKET =>
2826- val tapp = atSpan(startOffset(t), in.offset) { TypeApply (t, typeArgs(namedOK = true , wildOK = false )) }
2857+ val tapp = atSpan(startOffset(t), in.offset) {
2858+ val args = if isCapKwNext then captureArgs(namedOK = true , wildOK = false ) else typeArgs(namedOK = true , wildOK = false )
2859+ TypeApply (t, args)
2860+ }
28272861 simpleExprRest(tapp, location, canApply = true )
28282862 case LPAREN | LBRACE | INDENT if canApply =>
28292863 val app = atSpan(startOffset(t), in.offset) { mkApply(t, argumentExprs()) }
0 commit comments