@@ -3362,16 +3362,6 @@ object Parsers {
3362
3362
Template (constr, parents, Nil , EmptyValDef , Nil )
3363
3363
}
3364
3364
3365
- /** Check that `vparamss` represents a legal collective parameter list for a given extension
3366
- */
3367
- def checkExtensionParams (start : Offset , vparamss : List [List [ValDef ]]): Unit = vparamss match
3368
- case (vparam :: Nil ) :: vparamss1 if ! vparam.mods.is(Given ) =>
3369
- vparamss1.foreach(_.foreach(vparam =>
3370
- if ! vparam.mods.is(Given ) then
3371
- syntaxError(em " follow-on parameter in extension clause must be `given` " , vparam.span)))
3372
- case _ =>
3373
- syntaxError(em " extension clause must start with a single regular parameter " , start)
3374
-
3375
3365
def checkExtensionMethod (tparams : List [Tree ], stat : Tree ): Unit = stat match {
3376
3366
case stat : DefDef =>
3377
3367
if stat.mods.is(Extension ) then
@@ -3385,22 +3375,23 @@ object Parsers {
3385
3375
3386
3376
/** GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr
3387
3377
* | [GivenSig ‘:’] ConstrApps [[‘with’] TemplateBody]
3388
- * | [id ‘:’] ‘extension’ ExtParamClause {GivenParamClause} ExtMethods
3378
+ * | [id ‘:’] ExtParamClause {GivenParamClause} ‘extended’ ‘with’ ExtMethods
3389
3379
* GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
3390
- * ExtParamClause ::= [DefTypeParamClause] DefParamClause {GivenParamClause}
3380
+ * ExtParamClause ::= [DefTypeParamClause] DefParamClause
3391
3381
* ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
3392
3382
*/
3393
3383
def givenDef (start : Offset , mods : Modifiers , instanceMod : Mod ) = atSpan(start, nameStart) {
3394
3384
var mods1 = addMod(mods, instanceMod)
3395
3385
val hasGivenSig = followingIsGivenSig()
3396
- val (name, isExtension) =
3386
+ val nameStart = in.offset
3387
+ val (name, isOldExtension) =
3397
3388
if isIdent && hasGivenSig then
3398
3389
(ident(), in.token == COLON && in.lookaheadIn(nme.extension))
3399
3390
else
3400
3391
(EmptyTermName , isIdent(nme.extension))
3401
3392
3402
3393
val gdef = in.endMarkerScope(if name.isEmpty then GIVEN else name) {
3403
- if isExtension then
3394
+ if isOldExtension then
3404
3395
if (in.token == COLON ) in.nextToken()
3405
3396
assert(ident() == nme.extension)
3406
3397
val tparams = typeParamClauseOpt(ParamOwner .Def )
@@ -3412,65 +3403,61 @@ object Parsers {
3412
3403
templ.body.foreach(checkExtensionMethod(tparams, _))
3413
3404
ModuleDef (name, templ)
3414
3405
else
3415
- var tparams : List [TypeDef ] = Nil
3416
- var vparamss : List [List [ValDef ]] = Nil
3417
- var hasExtensionParams = false
3418
-
3419
- def parseParams (isExtension : Boolean ): Unit =
3420
- if isExtension && (in.token == LBRACKET || in.token == LPAREN ) then
3421
- hasExtensionParams = true
3422
- if tparams.nonEmpty || vparamss.nonEmpty then
3423
- syntaxError(i " cannot have parameters before and after `:` in extension " )
3424
- if in.token == LBRACKET then
3425
- tparams = typeParamClause(ParamOwner .Def )
3426
- if in.token == LPAREN && followingIsParamOrGivenType() then
3427
- val paramsStart = in.offset
3428
- vparamss = paramClauses(givenOnly = ! isExtension)
3429
- if isExtension then
3430
- checkExtensionParams(paramsStart, vparamss)
3431
-
3432
- parseParams(isExtension = false )
3433
- val parents =
3434
- if in.token == COLON then
3435
- in.nextToken()
3436
- if in.token == LBRACKET
3437
- || in.token == LPAREN && followingIsParamOrGivenType()
3438
- then
3439
- parseParams(isExtension = true )
3440
- Nil
3441
- else
3442
- constrApps(commaOK = true , templateCanFollow = true )
3443
- else if in.token == SUBTYPE then
3444
- if ! mods.is(Inline ) then
3445
- syntaxError(" `<:' is only allowed for given with `inline' modifier" )
3446
- in.nextToken()
3447
- TypeBoundsTree (EmptyTree , toplevelTyp()) :: Nil
3448
- else if name.isEmpty && ! hasExtensionParams then
3449
- constrApps(commaOK = true , templateCanFollow = true )
3406
+ val hasLabel = ! name.isEmpty && in.token == COLON
3407
+ if hasLabel then in.nextToken()
3408
+ val tparams = typeParamClauseOpt(ParamOwner .Def )
3409
+ val paramsStart = in.offset
3410
+ val vparamss =
3411
+ if in.token == LPAREN && followingIsParamOrGivenType()
3412
+ then paramClauses()
3450
3413
else Nil
3451
-
3452
- if in.token == EQUALS && parents.length == 1 && parents.head.isType then
3414
+ val isExtension = isIdent(nme.extended)
3415
+ def checkAllGivens (vparamss : List [List [ValDef ]], what : String ) =
3416
+ vparamss.foreach(_.foreach(vparam =>
3417
+ if ! vparam.mods.is(Given ) then syntaxError(em " $what must be `given` " , vparam.span)))
3418
+ if isExtension then
3419
+ if ! name.isEmpty && ! hasLabel then
3420
+ syntaxError(em " name $name of extension clause must be followed by `:` " , nameStart)
3421
+ vparamss match
3422
+ case (vparam :: Nil ) :: vparamss1 if ! vparam.mods.is(Given ) =>
3423
+ checkAllGivens(vparamss1, " follow-on parameter in extension clause" )
3424
+ case _ =>
3425
+ syntaxError(" extension clause must start with a single regular parameter" , paramsStart)
3453
3426
in.nextToken()
3454
- mods1 |= Final
3455
- DefDef (name, tparams, vparamss, parents.head, subExpr())
3427
+ accept(WITH )
3428
+ val (self, stats) = templateBody()
3429
+ stats.foreach(checkExtensionMethod(tparams, _))
3430
+ ModuleDef (name, Template (makeConstructor(tparams, vparamss), Nil , Nil , self, stats))
3456
3431
else
3457
- parents match
3458
- case TypeBoundsTree (_, _) :: _ => syntaxError(" `=' expected" )
3459
- case _ =>
3460
- possibleTemplateStart()
3461
- if hasExtensionParams then
3462
- in.observeIndented()
3432
+ checkAllGivens(vparamss, " parameter of given instance" )
3433
+ val parents =
3434
+ if hasLabel then
3435
+ constrApps(commaOK = true , templateCanFollow = true )
3436
+ else if in.token == SUBTYPE then
3437
+ if ! mods.is(Inline ) then
3438
+ syntaxError(" `<:' is only allowed for given with `inline' modifier" )
3439
+ in.nextToken()
3440
+ TypeBoundsTree (EmptyTree , toplevelTyp()) :: Nil
3441
+ else
3442
+ if ! (name.isEmpty && tparams.isEmpty && vparamss.isEmpty) then
3443
+ accept(COLON )
3444
+ constrApps(commaOK = true , templateCanFollow = true )
3445
+ if in.token == EQUALS && parents.length == 1 && parents.head.isType then
3446
+ in.nextToken()
3447
+ mods1 |= Final
3448
+ DefDef (name, tparams, vparamss, parents.head, subExpr())
3463
3449
else
3464
- tparams = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal ))
3465
- vparamss = vparamss.map(_.map(vparam =>
3450
+ parents match
3451
+ case TypeBoundsTree (_, _) :: _ => syntaxError(" `=' expected" )
3452
+ case _ =>
3453
+ possibleTemplateStart()
3454
+ val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal ))
3455
+ val vparamss1 = vparamss.map(_.map(vparam =>
3466
3456
vparam.withMods(vparam.mods &~ Param | ParamAccessor | PrivateLocal )))
3467
- val templ = templateBodyOpt(makeConstructor(tparams, vparamss), parents, Nil )
3468
- if hasExtensionParams then
3469
- templ.body.foreach(checkExtensionMethod(tparams, _))
3470
- ModuleDef (name, templ)
3471
- else if tparams.isEmpty && vparamss.isEmpty then ModuleDef (name, templ)
3472
- else TypeDef (name.toTypeName, templ)
3473
- }
3457
+ val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil )
3458
+ if tparams.isEmpty && vparamss.isEmpty then ModuleDef (name, templ)
3459
+ else TypeDef (name.toTypeName, templ)
3460
+ }
3474
3461
finalizeDef(gdef, mods1, start)
3475
3462
}
3476
3463
@@ -3547,8 +3534,8 @@ object Parsers {
3547
3534
checkNextNotIndented()
3548
3535
Template (constr, Nil , Nil , EmptyValDef , Nil )
3549
3536
3550
- /** TemplateBody ::= [nl | `with' ] `{' TemplateStatSeq `}'
3551
- * EnumBody ::= [nl | ‘with’ ] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
3537
+ /** TemplateBody ::= [nl] `{' TemplateStatSeq `}'
3538
+ * EnumBody ::= [nl] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
3552
3539
*/
3553
3540
def templateBodyOpt (constr : DefDef , parents : List [Tree ], derived : List [Tree ]): Template =
3554
3541
val (self, stats) =
0 commit comments