@@ -227,6 +227,7 @@ object Parsers {
227227 def isNumericLit = numericLitTokens contains in.token
228228 def isTemplateIntro = templateIntroTokens contains in.token
229229 def isDclIntro = dclIntroTokens contains in.token
230+ def isDclIntroNext = dclIntroTokens contains in.lookahead.token
230231 def isStatSeqEnd = in.isNestedEnd || in.token == EOF || in.token == RPAREN
231232 def mustStartStat = mustStartStatTokens contains in.token
232233
@@ -1591,8 +1592,7 @@ object Parsers {
15911592 case _ => None
15921593 }
15931594
1594- /** CaptureRef ::= { SimpleRef `.` } SimpleRef [`*`] [`.` rd]
1595- * | [ { SimpleRef `.` } SimpleRef `.` ] id `^`
1595+ /** CaptureRef ::= { SimpleRef `.` } SimpleRef [`*`] [`.` `rd`] -- under captureChecking
15961596 */
15971597 def captureRef (): Tree =
15981598
@@ -1611,22 +1611,17 @@ object Parsers {
16111611 in.nextToken()
16121612 derived(reachRef, nme.CC_READONLY )
16131613 else reachRef
1614- else if isIdent(nme.UPARROW ) then
1615- in.nextToken()
1616- atSpan(startOffset(ref)):
1617- convertToTypeId(ref) match
1618- case ref : RefTree => makeCapsOf(ref)
1619- case ref => ref
16201614 else ref
16211615
16221616 recur(simpleRef())
16231617 end captureRef
16241618
16251619 /** CaptureSet ::= `{` CaptureRef {`,` CaptureRef} `}` -- under captureChecking
16261620 */
1627- def captureSet (): List [Tree ] = inBraces {
1628- if in.token == RBRACE then Nil else commaSeparated(captureRef)
1629- }
1621+ def captureSet (): List [Tree ] =
1622+ inBraces {
1623+ if in.token == RBRACE then Nil else commaSeparated(captureRef)
1624+ }
16301625
16311626 def capturesAndResult (core : () => Tree ): Tree =
16321627 if Feature .ccEnabled && in.token == LBRACE && canStartCaptureSetContentsTokens.contains(in.lookahead.token)
@@ -1640,9 +1635,9 @@ object Parsers {
16401635 * | InfixType
16411636 * FunType ::= (MonoFunType | PolyFunType)
16421637 * MonoFunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type
1643- * | (‘->’ | ‘?->’ ) [CaptureSet] Type -- under pureFunctions
1638+ * | (‘->’ | ‘?->’ ) [CaptureSet] Type -- under pureFunctions and captureChecking
16441639 * PolyFunType ::= TypTypeParamClause '=>' Type
1645- * | TypTypeParamClause ‘->’ [CaptureSet] Type -- under pureFunctions
1640+ * | TypTypeParamClause ‘->’ [CaptureSet] Type -- under pureFunctions and captureChecking
16461641 * FunTypeArgs ::= InfixType
16471642 * | `(' [ FunArgType {`,' FunArgType } ] `)'
16481643 * | '(' [ TypedFunParam {',' TypedFunParam } ')'
@@ -1885,7 +1880,7 @@ object Parsers {
18851880 if in.token == LPAREN then funParamClause() :: funParamClauses() else Nil
18861881
18871882 /** InfixType ::= RefinedType {id [nl] RefinedType}
1888- * | RefinedType `^` // under capture checking
1883+ * | RefinedType `^` -- under captureChecking
18891884 */
18901885 def infixType (inContextBound : Boolean = false ): Tree = infixTypeRest(inContextBound)(refinedType())
18911886
@@ -1916,6 +1911,12 @@ object Parsers {
19161911 || ! canStartInfixTypeTokens.contains(ahead.token)
19171912 || ahead.lineOffset > 0
19181913
1914+ inline def gobbleHat (): Boolean =
1915+ if Feature .ccEnabled && isIdent(nme.UPARROW ) then
1916+ in.nextToken()
1917+ true
1918+ else false
1919+
19191920 def refinedTypeRest (t : Tree ): Tree = {
19201921 argumentStart()
19211922 if in.isNestedStart then
@@ -2172,35 +2173,45 @@ object Parsers {
21722173 atSpan(startOffset(t), startOffset(id)) { Select (t, id.name) }
21732174 }
21742175
2175- /** ArgTypes ::= Type {`,' Type}
2176- * | NamedTypeArg {`,' NamedTypeArg}
2177- * NamedTypeArg ::= id `=' Type
2176+ /** ArgTypes ::= TypeArg {‘,’ TypeArg}
2177+ * | NamedTypeArg {‘,’ NamedTypeArg}
2178+ * TypeArg ::= Type
2179+ * | CaptureSet -- under captureChecking
2180+ * NamedTypeArg ::= id ‘=’ TypeArg
21782181 * NamesAndTypes ::= NameAndType {‘,’ NameAndType}
2179- * NameAndType ::= id ':' Type
2182+ * NameAndType ::= id ‘:’ Type
21802183 */
21812184 def argTypes (namedOK : Boolean , wildOK : Boolean , tupleOK : Boolean ): List [Tree ] =
2182- def argType () =
2183- val t = typ()
2185+ def wildCardCheck ( gen : Tree ) : Tree =
2186+ val t = gen
21842187 if wildOK then t else rejectWildcardType(t)
21852188
2186- def namedArgType () =
2189+ def argType () = wildCardCheck(typ())
2190+
2191+ def typeArg () = wildCardCheck :
2192+ if Feature .ccEnabled && in.token == LBRACE && ! isDclIntroNext then // is this a capture set and not a refinement type?
2193+ // This case is ambiguous w.r.t. an Object literal {}. But since CC is enabled, we probably expect it to designate the empty set
2194+ concreteCapsType(captureSet())
2195+ else typ()
2196+
2197+ def namedTypeArg () =
21872198 atSpan(in.offset):
21882199 val name = ident()
21892200 accept(EQUALS )
2190- NamedArg (name.toTypeName, argType ())
2201+ NamedArg (name.toTypeName, typeArg ())
21912202
2192- def namedElem () =
2203+ def nameAndType () =
21932204 atSpan(in.offset):
21942205 val name = ident()
21952206 acceptColon()
21962207 NamedArg (name, argType())
21972208
2198- if namedOK && isIdent && in.lookahead.token == EQUALS then
2199- commaSeparated(() => namedArgType ())
2209+ if namedOK && ( isIdent && in.lookahead.token == EQUALS ) then
2210+ commaSeparated(() => namedTypeArg ())
22002211 else if tupleOK && isIdent && in.lookahead.isColon && sourceVersion.enablesNamedTuples then
2201- commaSeparated(() => namedElem ())
2212+ commaSeparated(() => nameAndType ())
22022213 else
2203- commaSeparated(() => argType ())
2214+ commaSeparated(() => typeArg ())
22042215 end argTypes
22052216
22062217 def paramTypeOf (core : () => Tree ): Tree =
@@ -2244,7 +2255,7 @@ object Parsers {
22442255 PostfixOp (t, Ident (tpnme.raw.STAR ))
22452256 else t
22462257
2247- /** TypeArgs ::= `[' Type {`,' Type } `]'
2258+ /** TypeArgs ::= `[' TypeArg {`,' TypeArg } `]'
22482259 * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]'
22492260 */
22502261 def typeArgs (namedOK : Boolean , wildOK : Boolean ): List [Tree ] =
@@ -2258,21 +2269,28 @@ object Parsers {
22582269 else
22592270 inBraces(refineStatSeq())
22602271
2261- /** TypeBounds ::= [`>:' Type] [`<:' Type]
2262- * | `^` -- under captureChecking
2272+ /** TypeBounds ::= [`>:' TypeBound ] [`<:' TypeBound ]
2273+ * TypeBound ::= Type
2274+ * | CaptureSet -- under captureChecking
22632275 */
22642276 def typeBounds (): TypeBoundsTree =
22652277 atSpan(in.offset):
2266- if in.isIdent(nme.UPARROW ) && Feature .ccEnabled then
2267- in.nextToken()
2268- makeCapsBound()
2269- else
2270- TypeBoundsTree (bound(SUPERTYPE ), bound(SUBTYPE ))
2278+ TypeBoundsTree (bound(SUPERTYPE ), bound(SUBTYPE ))
22712279
22722280 private def bound (tok : Int ): Tree =
2273- if (in.token == tok) { in.nextToken(); toplevelTyp() }
2281+ if in.token == tok then
2282+ in.nextToken()
2283+ if Feature .ccEnabled && in.token == LBRACE && ! isDclIntroNext then
2284+ capsBound(captureSet(), isLowerBound = tok == SUPERTYPE )
2285+ else toplevelTyp()
22742286 else EmptyTree
22752287
2288+ private def capsBound (refs : List [Tree ], isLowerBound : Boolean = false ): Tree =
2289+ if isLowerBound && refs.isEmpty then // lower bounds with empty capture sets become a pure CapSet
2290+ Select (scalaDot(nme.caps), tpnme.CapSet )
2291+ else
2292+ concreteCapsType(refs)
2293+
22762294 /** TypeAndCtxBounds ::= TypeBounds [`:` ContextBounds]
22772295 */
22782296 def typeAndCtxBounds (pname : TypeName ): Tree = {
@@ -3397,7 +3415,7 @@ object Parsers {
33973415 * | opaque
33983416 * LocalModifier ::= abstract | final | sealed | open | implicit | lazy | erased |
33993417 * inline | transparent | infix |
3400- * mut -- under cc
3418+ * mut -- under captureChecking
34013419 */
34023420 def modifiers (allowed : BitSet = modifierTokens, start : Modifiers = Modifiers ()): Modifiers = {
34033421 @ tailrec
@@ -3486,22 +3504,25 @@ object Parsers {
34863504 recur(numLeadParams, firstClause = true , prevIsTypeClause = false )
34873505 end typeOrTermParamClauses
34883506
3489-
34903507 /** ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’
3491- * ClsTypeParam ::= {Annotation} [‘+’ | ‘-’]
3492- * id [HkTypeParamClause] TypeAndCtxBounds
3508+ * ClsTypeParam ::= {Annotation} [‘+’ | ‘-’]
3509+ * id [HkTypeParamClause] TypeAndCtxBounds
3510+ * | {Annotation} [‘+’ | ‘-’] id `^` TypeAndCtxBounds -- under captureChecking
34933511 *
34943512 * DefTypeParamClause::= ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
3495- * DefTypeParam ::= {Annotation}
3496- * id [HkTypeParamClause] TypeAndCtxBounds
3513+ * DefTypeParam ::= {Annotation}
3514+ * id [HkTypeParamClause] TypeAndCtxBounds
3515+ * | {Annotation} id `^` TypeAndCtxBounds -- under captureChecking
34973516 *
34983517 * TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’
3499- * TypTypeParam ::= {Annotation}
3500- * (id | ‘_’) [HkTypeParamClause] TypeAndCtxBounds
3518+ * TypTypeParam ::= {Annotation}
3519+ * (id | ‘_’) [HkTypeParamClause] TypeAndCtxBounds
3520+ * | {Annotation} (id | ‘_’) `^` TypeAndCtxBounds -- under captureChecking
35013521 *
35023522 * HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
3503- * HkTypeParam ::= {Annotation} [‘+’ | ‘-’]
3504- * (id | ‘_’) [HkTypeParamClause] TypeBounds
3523+ * HkTypeParam ::= {Annotation} [‘+’ | ‘-’]
3524+ * (id | ‘_’) [HkTypePamClause] TypeBounds
3525+ * | {Annotation} [‘+’ | ‘-’] (id | ‘_’) `^` TypeBounds -- under captureChecking
35053526 */
35063527 def typeParamClause (paramOwner : ParamOwner ): List [TypeDef ] = inBracketsWithCommas {
35073528
@@ -3526,12 +3547,18 @@ object Parsers {
35263547 in.nextToken()
35273548 WildcardParamName .fresh().toTypeName
35283549 else ident().toTypeName
3550+ val isCap = gobbleHat()
35293551 val hkparams = typeParamClauseOpt(ParamOwner .Hk )
35303552 val bounds =
35313553 if paramOwner.acceptsCtxBounds then typeAndCtxBounds(name)
35323554 else if sourceVersion.enablesNewGivens && paramOwner == ParamOwner .Type then typeAndCtxBounds(name)
35333555 else typeBounds()
3534- TypeDef (name, lambdaAbstract(hkparams, bounds)).withMods(mods)
3556+ val res = TypeDef (name, lambdaAbstract(hkparams, bounds)).withMods(mods)
3557+ if isCap then
3558+ res.pushAttachment(CaptureVar , ())
3559+ // putting the attachment here as well makes post-processing in the typer easier
3560+ bounds.pushAttachment(CaptureVar , ())
3561+ res
35353562 }
35363563 }
35373564 commaSeparated(() => typeParam())
@@ -4052,33 +4079,47 @@ object Parsers {
40524079 argumentExprss(mkApply(Ident (nme.CONSTRUCTOR ), argumentExprs()))
40534080 }
40544081
4055- /** TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds [‘=’ Type]
4082+ /** TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds [‘=’ TypeDefRHS ]
4083+ * | id `^` TypeAndCtxBounds [‘=’ TypeDefRHS ] -- under captureChecking
4084+ * TypeDefRHS ::= Type
4085+ * | CaptureSet -- under captureChecking
40564086 */
40574087 def typeDefOrDcl (start : Offset , mods : Modifiers ): Tree = {
4088+
4089+ def typeDefRHS (): Tree =
4090+ if Feature .ccEnabled && in.token == LBRACE && ! isDclIntroNext then
4091+ concreteCapsType(captureSet())
4092+ else toplevelTyp()
4093+
40584094 newLinesOpt()
40594095 atSpan(start, nameStart) {
40604096 val nameIdent = typeIdent()
4097+ val isCapDef = gobbleHat()
40614098 val tname = nameIdent.name.asTypeName
40624099 val tparams = typeParamClauseOpt(ParamOwner .Hk )
40634100 val vparamss = funParamClauses()
40644101
40654102 def makeTypeDef (rhs : Tree ): Tree = {
40664103 val rhs1 = lambdaAbstractAll(tparams :: vparamss, rhs)
40674104 val tdef = TypeDef (nameIdent.name.toTypeName, rhs1)
4068- if ( nameIdent.isBackquoted)
4105+ if nameIdent.isBackquoted then
40694106 tdef.pushAttachment(Backquoted , ())
4107+ if isCapDef then
4108+ tdef.pushAttachment(CaptureVar , ())
4109+ // putting the attachment here as well makes post-processing in the typer easier
4110+ rhs.pushAttachment(CaptureVar , ())
40704111 finalizeDef(tdef, mods, start)
40714112 }
40724113
40734114 in.token match {
40744115 case EQUALS =>
40754116 in.nextToken()
4076- makeTypeDef(toplevelTyp ())
4117+ makeTypeDef(typeDefRHS ())
40774118 case SUBTYPE | SUPERTYPE =>
40784119 typeAndCtxBounds(tname) match
40794120 case bounds : TypeBoundsTree if in.token == EQUALS =>
40804121 val eqOffset = in.skipToken()
4081- var rhs = toplevelTyp ()
4122+ var rhs = typeDefRHS ()
40824123 rhs match {
40834124 case mtt : MatchTypeTree =>
40844125 bounds match {
@@ -4107,6 +4148,9 @@ object Parsers {
41074148 }
41084149 }
41094150
4151+ private def concreteCapsType (refs : List [Tree ]): Tree =
4152+ makeRetaining(Select (scalaDot(nme.caps), tpnme.CapSet ), refs, tpnme.retains)
4153+
41104154 /** TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
41114155 * | [‘case’] ‘object’ ObjectDef
41124156 * | ‘enum’ EnumDef
0 commit comments