Skip to content

Commit 1790bb5

Browse files
authored
Clean up categorization of type parameters (#21237)
There are 4 categories, depending on whether (1) context bounds are allowed and (2) variances are allowed ``` Class: yes/yes Type: no/no Hk: no/yes Def: yes/no ``` Furthermore, Type and Hk parameters can be wildcards. The previous grammars confused Type and Hk parameters and contained other errors as well.
2 parents 7f5e4ce + 8c07ebd commit 1790bb5

File tree

3 files changed

+52
-47
lines changed

3 files changed

+52
-47
lines changed

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

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ object Parsers {
5454
enum ParamOwner:
5555
case Class // class or trait or enum
5656
case CaseClass // case class or enum case
57-
case Type // type alias or abstract type
58-
case TypeParam // type parameter
5957
case Def // method
58+
case Type // type alias or abstract type or polyfunction type/expr
59+
case Hk // type parameter (i.e. current parameter is higher-kinded)
6060
case Given // given definition
6161
case ExtensionPrefix // extension clause, up to and including extension parameter
6262
case ExtensionFollow // extension clause, following extension parameter
@@ -66,7 +66,11 @@ object Parsers {
6666
def takesOnlyUsingClauses = // only using clauses allowed for this owner
6767
this == Given || this == ExtensionFollow
6868
def acceptsVariance =
69-
this == Class || this == CaseClass || this == Type
69+
this == Class || this == CaseClass || this == Hk
70+
def acceptsCtxBounds =
71+
!(this == Type || this == Hk)
72+
def acceptsWildcard =
73+
this == Type || this == Hk
7074

7175
end ParamOwner
7276

@@ -1572,15 +1576,15 @@ object Parsers {
15721576
else core()
15731577

15741578
/** Type ::= FunType
1575-
* | HkTypeParamClause ‘=>>’ Type
1579+
* | TypTypeParamClause ‘=>>’ Type
15761580
* | FunParamClause ‘=>>’ Type
15771581
* | MatchType
15781582
* | InfixType
15791583
* FunType ::= (MonoFunType | PolyFunType)
15801584
* MonoFunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type
1581-
* | (‘->’ | ‘?->’ ) [CaptureSet] Type -- under pureFunctions
1582-
* PolyFunType ::= HKTypeParamClause '=>' Type
1583-
* | HKTypeParamClause ‘->’ [CaptureSet] Type -- under pureFunctions
1585+
* | (‘->’ | ‘?->’ ) [CaptureSet] Type -- under pureFunctions
1586+
* PolyFunType ::= TypTypeParamClause '=>' Type
1587+
* | TypTypeParamClause ‘->’ [CaptureSet] Type -- under pureFunctions
15841588
* FunTypeArgs ::= InfixType
15851589
* | `(' [ FunArgType {`,' FunArgType } ] `)'
15861590
* | '(' [ TypedFunParam {',' TypedFunParam } ')'
@@ -1746,7 +1750,7 @@ object Parsers {
17461750
simpleTypeRest(tuple)
17471751
else if in.token == LBRACKET then
17481752
val start = in.offset
1749-
val tparams = typeParamClause(ParamOwner.TypeParam)
1753+
val tparams = typeParamClause(ParamOwner.Type)
17501754
if in.token == TLARROW then
17511755
atSpan(start, in.skipToken()):
17521756
LambdaTypeTree(tparams, toplevelTyp())
@@ -2299,15 +2303,15 @@ object Parsers {
22992303
t
23002304

23012305
/** Expr ::= [`implicit'] FunParams (‘=>’ | ‘?=>’) Expr
2302-
* | HkTypeParamClause ‘=>’ Expr
2306+
* | TypTypeParamClause ‘=>’ Expr
23032307
* | Expr1
23042308
* FunParams ::= Bindings
23052309
* | id
23062310
* | `_'
23072311
* ExprInParens ::= PostfixExpr `:' Type
23082312
* | Expr
23092313
* BlockResult ::= [‘implicit’] FunParams (‘=>’ | ‘?=>’) Block
2310-
* | HkTypeParamClause ‘=>’ Block
2314+
* | TypTypeParamClause ‘=>’ Block
23112315
* | Expr1
23122316
* Expr1 ::= [‘inline’] `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
23132317
* | [‘inline’] `if' Expr `then' Expr [[semi] else Expr]
@@ -2343,7 +2347,7 @@ object Parsers {
23432347
closure(start, location, modifiers(BitSet(IMPLICIT)))
23442348
case LBRACKET =>
23452349
val start = in.offset
2346-
val tparams = typeParamClause(ParamOwner.TypeParam)
2350+
val tparams = typeParamClause(ParamOwner.Type)
23472351
val arrowOffset = accept(ARROW)
23482352
val body = expr(location)
23492353
atSpan(start, arrowOffset) {
@@ -2676,7 +2680,7 @@ object Parsers {
26762680
* ColonArgument ::= colon [LambdaStart]
26772681
* indent (CaseClauses | Block) outdent
26782682
* LambdaStart ::= FunParams (‘=>’ | ‘?=>’)
2679-
* | HkTypeParamClause ‘=>’
2683+
* | TypTypeParamClause ‘=>’
26802684
* ColonArgBody ::= indent (CaseClauses | Block) outdent
26812685
* Quoted ::= ‘'’ ‘{’ Block ‘}’
26822686
* | ‘'’ ‘[’ Type ‘]’
@@ -3409,17 +3413,19 @@ object Parsers {
34093413

34103414
/** ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’
34113415
* ClsTypeParam ::= {Annotation} [‘+’ | ‘-’]
3412-
* id [HkTypeParamClause] TypeParamBounds
3416+
* id [HkTypeParamClause] TypeAndCtxBounds
34133417
*
34143418
* DefTypeParamClause::= ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
34153419
* DefTypeParam ::= {Annotation}
3416-
* id [HkTypeParamClause] TypeParamBounds
3420+
* id [HkTypeParamClause] TypeAndCtxBounds
34173421
*
34183422
* TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’
3419-
* TypTypeParam ::= {Annotation} id [HkTypePamClause] TypeBounds
3423+
* TypTypeParam ::= {Annotation}
3424+
* (id | ‘_’) [HkTypeParamClause] TypeBounds
34203425
*
34213426
* HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
3422-
* HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypePamClause] | ‘_’) TypeBounds
3427+
* HkTypeParam ::= {Annotation} [‘+’ | ‘-’]
3428+
* (id | ‘_’) [HkTypePamClause] TypeBounds
34233429
*/
34243430
def typeParamClause(paramOwner: ParamOwner): List[TypeDef] = inBracketsWithCommas {
34253431

@@ -3430,7 +3436,6 @@ object Parsers {
34303436
ok
34313437

34323438
def typeParam(): TypeDef = {
3433-
val isAbstractOwner = paramOwner == ParamOwner.Type || paramOwner == ParamOwner.TypeParam
34343439
val start = in.offset
34353440
var mods = annotsAsMods() | Param
34363441
if paramOwner.isClass then
@@ -3441,13 +3446,13 @@ object Parsers {
34413446
mods |= Contravariant
34423447
atSpan(start, nameStart) {
34433448
val name =
3444-
if (isAbstractOwner && in.token == USCORE) {
3449+
if paramOwner.acceptsWildcard && in.token == USCORE then
34453450
in.nextToken()
34463451
WildcardParamName.fresh().toTypeName
3447-
}
34483452
else ident().toTypeName
3449-
val hkparams = typeParamClauseOpt(ParamOwner.Type)
3450-
val bounds = if (isAbstractOwner) typeBounds() else typeAndCtxBounds(name)
3453+
val hkparams = typeParamClauseOpt(ParamOwner.Hk)
3454+
val bounds =
3455+
if paramOwner.acceptsCtxBounds then typeAndCtxBounds(name) else typeBounds()
34513456
TypeDef(name, lambdaAbstract(hkparams, bounds)).withMods(mods)
34523457
}
34533458
}
@@ -3963,14 +3968,14 @@ object Parsers {
39633968
argumentExprss(mkApply(Ident(nme.CONSTRUCTOR), argumentExprs()))
39643969
}
39653970

3966-
/** TypeDef ::= id [TypeParamClause] {FunParamClause} TypeAndCtxBounds [‘=’ Type]
3971+
/** TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds [‘=’ Type]
39673972
*/
39683973
def typeDefOrDcl(start: Offset, mods: Modifiers): Tree = {
39693974
newLinesOpt()
39703975
atSpan(start, nameStart) {
39713976
val nameIdent = typeIdent()
39723977
val tname = nameIdent.name.asTypeName
3973-
val tparams = typeParamClauseOpt(ParamOwner.Type)
3978+
val tparams = typeParamClauseOpt(ParamOwner.Hk)
39743979
val vparamss = funParamClauses()
39753980

39763981
def makeTypeDef(rhs: Tree): Tree = {

docs/_docs/internals/syntax.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,12 @@ ClassQualifier ::= ‘[’ id ‘]’
177177
### Types
178178
```ebnf
179179
Type ::= FunType
180-
| HkTypeParamClause ‘=>>’ Type LambdaTypeTree(ps, t)
180+
| TypTypeParamClause ‘=>>’ Type LambdaTypeTree(ps, t)
181181
| FunParamClause ‘=>>’ Type TermLambdaTypeTree(ps, t)
182182
| MatchType
183183
| InfixType
184184
FunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type Function(ts, t) | FunctionWithMods(ts, t, mods, erasedParams)
185-
| HKTypeParamClause '=>' Type PolyFunction(ps, t)
185+
| TypTypeParamClause '=>' Type PolyFunction(ps, t)
186186
FunTypeArgs ::= InfixType
187187
| ‘(’ [ FunArgTypes ] ‘)’
188188
| FunParamClause
@@ -233,10 +233,10 @@ NameAndType ::= id ':' Type
233233
### Expressions
234234
```ebnf
235235
Expr ::= FunParams (‘=>’ | ‘?=>’) Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr)
236-
| HkTypeParamClause ‘=>’ Expr PolyFunction(ts, expr)
236+
| TypTypeParamClause ‘=>’ Expr PolyFunction(ts, expr)
237237
| Expr1
238238
BlockResult ::= FunParams (‘=>’ | ‘?=>’) Block
239-
| HkTypeParamClause ‘=>’ Block
239+
| TypTypeParamClause ‘=>’ Block
240240
| Expr1
241241
FunParams ::= Bindings
242242
| id
@@ -286,7 +286,7 @@ SimpleExpr ::= SimpleRef
286286
ColonArgument ::= colon [LambdaStart]
287287
indent (CaseClauses | Block) outdent
288288
LambdaStart ::= FunParams (‘=>’ | ‘?=>’)
289-
| HkTypeParamClause ‘=>’
289+
| TypTypeParamClause ‘=>’
290290
Quoted ::= ‘'’ ‘{’ Block ‘}’
291291
| ‘'’ ‘[’ TypeBlock ‘]’
292292
ExprSplice ::= spliceId -- if inside quoted block
@@ -364,11 +364,14 @@ ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’
364364
ClsTypeParam ::= {Annotation} [‘+’ | ‘-’] TypeDef(Modifiers, name, tparams, bounds)
365365
id [HkTypeParamClause] TypeAndCtxBounds Bound(below, above, context)
366366
367+
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
368+
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeAndCtxBounds
369+
367370
TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’
368-
TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds
371+
TypTypeParam ::= {Annotation} (id | ‘_’) [HkTypeParamClause] TypeBounds
369372
370373
HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
371-
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypeParamClause] | ‘_’)
374+
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id | ‘_’) [HkTypeParamClause]
372375
TypeBounds
373376
374377
ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’]
@@ -385,9 +388,6 @@ DefParamClause ::= DefTypeParamClause
385388
TypelessClauses ::= TypelessClause {TypelessClause}
386389
TypelessClause ::= DefTermParamClause
387390
| UsingParamClause
388-
389-
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
390-
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeAndCtxBounds
391391
DefTermParamClause::= [nl] ‘(’ [DefTermParams] ‘)’
392392
UsingParamClause ::= [nl] ‘(’ ‘using’ (DefTermParams | FunArgTypes) ‘)’
393393
DefImplicitClause ::= [nl] ‘(’ ‘implicit’ DefTermParams ‘)’
@@ -458,7 +458,7 @@ PatDef ::= ids [‘:’ Type] [‘=’ Expr]
458458
DefDef ::= DefSig [‘:’ Type] [‘=’ Expr] DefDef(_, name, paramss, tpe, expr)
459459
| ‘this’ TypelessClauses [DefImplicitClause] ‘=’ ConstrExpr DefDef(_, <init>, vparamss, EmptyTree, expr | Block)
460460
DefSig ::= id [DefParamClauses] [DefImplicitClause]
461-
TypeDef ::= id [TypeParamClause] {FunParamClause} TypeAndCtxBounds TypeDefTree(_, name, tparams, bound
461+
TypeDef ::= id [HkTypeParamClause] {FunParamClause} TypeAndCtxBounds TypeDefTree(_, name, tparams, bound
462462
[‘=’ Type]
463463
464464
TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef

docs/_docs/reference/syntax.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -178,12 +178,11 @@ ClassQualifier ::= ‘[’ id ‘]’
178178
### Types
179179
```
180180
Type ::= FunType
181-
| HkTypeParamClause ‘=>>’ Type
182-
| FunParamClause ‘=>>’ Type
181+
| TypTypeParamClause ‘=>>’ Type
183182
| MatchType
184183
| InfixType
185184
FunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type
186-
| HKTypeParamClause '=>' Type
185+
| TypTypeParamClause '=>' Type
187186
FunTypeArgs ::= InfixType
188187
| ‘(’ [ FunArgTypes ] ‘)’
189188
| FunParamClause
@@ -215,17 +214,17 @@ ParamValueType ::= Type [‘*’]
215214
TypeArgs ::= ‘[’ Types ‘]’
216215
Refinement ::= :<<< [RefineDcl] {semi [RefineDcl]} >>>
217216
TypeBounds ::= [‘>:’ Type] [‘<:’ Type]
218-
TypeParamBounds ::= TypeBounds {‘:’ Type}
217+
TypeAndCtxBounds ::= TypeBounds {‘:’ Type}
219218
Types ::= Type {‘,’ Type}
220219
```
221220

222221
### Expressions
223222
```
224223
Expr ::= FunParams (‘=>’ | ‘?=>’) Expr
225-
| HkTypeParamClause ‘=>’ Expr
224+
| TypTypeParamClause ‘=>’ Expr
226225
| Expr1
227226
BlockResult ::= FunParams (‘=>’ | ‘?=>’) Block
228-
| HkTypeParamClause ‘=>’ Block
227+
| TypTypeParamClause ‘=>’ Block
229228
| Expr1
230229
FunParams ::= Bindings
231230
| id
@@ -273,7 +272,7 @@ SimpleExpr ::= SimpleRef
273272
ColonArgument ::= colon [LambdaStart]
274273
indent (CaseClauses | Block) outdent
275274
LambdaStart ::= FunParams (‘=>’ | ‘?=>’)
276-
| HkTypeParamClause ‘=>’
275+
| TypTypeParamClause ‘=>’
277276
Quoted ::= ‘'’ ‘{’ Block ‘}’
278277
| ‘'’ ‘[’ TypeBlock ‘]’
279278
ExprSplice ::= spliceId -- if inside quoted block
@@ -339,13 +338,16 @@ ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
339338
### Type and Value Parameters
340339
```
341340
ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’
342-
ClsTypeParam ::= {Annotation} [‘+’ | ‘-’] id [HkTypeParamClause] TypeParamBounds
341+
ClsTypeParam ::= {Annotation} [‘+’ | ‘-’] id [HkTypeParamClause] TypeAndCtxBounds
342+
343+
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
344+
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeAndCtxBounds
343345
344346
TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’
345-
TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds
347+
TypTypeParam ::= {Annotation} (id | ‘_’) [HkTypeParamClause] TypeBounds
346348
347349
HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
348-
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypeParamClause] | ‘_’) TypeBounds
350+
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id | ‘_’) [HkTypeParamClause] TypeBounds
349351
350352
ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’]
351353
ClsParamClause ::= [nl] ‘(’ ClsParams ‘)’
@@ -361,8 +363,6 @@ TypelessClauses ::= TypelessClause {TypelessClause}
361363
TypelessClause ::= DefTermParamClause
362364
| UsingParamClause
363365
364-
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
365-
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds
366366
DefTermParamClause::= [nl] ‘(’ [DefTermParams] ‘)’
367367
UsingParamClause ::= [nl] ‘(’ ‘using’ (DefTermParams | FunArgTypes) ‘)’
368368
DefImplicitClause ::= [nl] ‘(’ ‘implicit’ DefTermParams ‘)’
@@ -431,7 +431,7 @@ PatDef ::= ids [‘:’ Type] [‘=’ Expr]
431431
DefDef ::= DefSig [‘:’ Type] [‘=’ Expr] DefDef(_, name, paramss, tpe, expr)
432432
| ‘this’ TypelessClauses [DefImplicitClause] ‘=’ ConstrExpr DefDef(_, <init>, vparamss, EmptyTree, expr | Block)
433433
DefSig ::= id [DefParamClauses] [DefImplicitClause]
434-
TypeDef ::= id [TypeParamClause] {FunParamClause} TypeBounds TypeDefTree(_, name, tparams, bound
434+
TypeDef ::= id [HkTypeParamClause] {FunParamClause}TypeBounds TypeDefTree(_, name, tparams, bound
435435
[‘=’ Type]
436436
437437
TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef

0 commit comments

Comments
 (0)