@@ -972,18 +972,16 @@ object Parsers {
972
972
followedByToken(LARROW ) // `<-` comes before possible statement starts
973
973
}
974
974
975
- /** Are the next token the "GivenSig" part of a given definition,
976
- * i.e. an identifier followed by type and value parameters, followed by `:`?
975
+ /** Are the next tokens a valid continuation of a named given def?
976
+ * i.e. an identifier, possibly followed by type and value parameters, followed by `:`?
977
977
* @pre The current token is an identifier
978
978
*/
979
- def followingIsOldStyleGivenSig () =
979
+ def followingIsGivenDefWithColon () =
980
980
val lookahead = in.LookaheadScanner ()
981
981
if lookahead.isIdent then
982
982
lookahead.nextToken()
983
- var paramsSeen = false
984
983
def skipParams (): Unit =
985
984
if lookahead.token == LPAREN || lookahead.token == LBRACKET then
986
- paramsSeen = true
987
985
lookahead.skipParens()
988
986
skipParams()
989
987
else if lookahead.isNewLine then
@@ -1002,6 +1000,11 @@ object Parsers {
1002
1000
}
1003
1001
}
1004
1002
1003
+ def followingIsArrow () =
1004
+ val lookahead = in.LookaheadScanner ()
1005
+ lookahead.skipParens()
1006
+ lookahead.token == ARROW
1007
+
1005
1008
def followingIsExtension () =
1006
1009
val next = in.lookahead.token
1007
1010
next == LBRACKET || next == LPAREN
@@ -3441,7 +3444,11 @@ object Parsers {
3441
3444
/** ContextTypes ::= FunArgType {‘,’ FunArgType}
3442
3445
*/
3443
3446
def contextTypes (paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3444
- val tps = commaSeparated(() => paramTypeOf(() => toplevelTyp()))
3447
+ typesToParams(
3448
+ commaSeparated(() => paramTypeOf(() => toplevelTyp())),
3449
+ paramOwner, numLeadParams, impliedMods)
3450
+
3451
+ def typesToParams (tps : List [Tree ], paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3445
3452
var counter = numLeadParams
3446
3453
def nextIdx = { counter += 1 ; counter }
3447
3454
val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
@@ -3468,18 +3475,20 @@ object Parsers {
3468
3475
def termParamClause (
3469
3476
paramOwner : ParamOwner ,
3470
3477
numLeadParams : Int , // number of parameters preceding this clause
3471
- firstClause : Boolean = false // clause is the first in regular list of clauses
3478
+ firstClause : Boolean = false , // clause is the first in regular list of clauses
3479
+ initialMods : Modifiers = EmptyModifiers
3472
3480
): List [ValDef ] = {
3473
- var impliedMods : Modifiers = EmptyModifiers
3481
+ var impliedMods : Modifiers = initialMods
3474
3482
3475
3483
def addParamMod (mod : () => Mod ) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
3476
3484
3477
3485
def paramMods () =
3478
3486
if in.token == IMPLICIT then
3479
3487
addParamMod(() => Mod .Implicit ())
3480
- else
3481
- if isIdent(nme.using) then
3482
- addParamMod(() => Mod .Given ())
3488
+ else if isIdent(nme.using) then
3489
+ if initialMods.is(Given ) then
3490
+ syntaxError(em " `using` is already implied here, should not be given explicitly " , in.offset)
3491
+ addParamMod(() => Mod .Given ())
3483
3492
3484
3493
def param (): ValDef = {
3485
3494
val start = in.offset
@@ -4144,18 +4153,67 @@ object Parsers {
4144
4153
* OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
4145
4154
* StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
4146
4155
*
4147
- * NewGivenDef ::= [GivenConditional '=>'] NewGivenSig
4148
- * GivenConditional ::= [DefTypeParamClause | UsingParamClause] {UsingParamClause}
4149
- * NewGivenSig ::= GivenType ['as' id] ([‘=’ Expr] | TemplateBody)
4150
- * | ConstrApps ['as' id] TemplateBody
4151
- *
4156
+ * NewGivenDef ::= [id ':'] GivenSig
4157
+ * GivenSig ::= GivenImpl
4158
+ * | '(' ')' '=>' GivenImpl
4159
+ * | GivenConditional '=>' GivenSig
4160
+ * GivenImpl ::= GivenType ([‘=’ Expr] | TemplateBody)
4161
+ * | ConstrApps TemplateBody
4162
+ * GivenConditional ::= DefTypeParamClause
4163
+ * | DefTermParamClause
4164
+ * | '(' FunArgTypes ')'
4165
+ * | GivenType
4152
4166
* GivenType ::= AnnotType1 {id [nl] AnnotType1}
4153
4167
*/
4154
4168
def givenDef (start : Offset , mods : Modifiers , givenMod : Mod ) = atSpan(start, nameStart) {
4155
4169
var mods1 = addMod(mods, givenMod)
4156
4170
val nameStart = in.offset
4157
- var name = if isIdent && followingIsOldStyleGivenSig() then ident() else EmptyTermName
4158
4171
var newSyntaxAllowed = in.featureEnabled(Feature .modularity)
4172
+ val hasEmbeddedColon = ! in.isColon && followingIsGivenDefWithColon()
4173
+ val name = if isIdent && hasEmbeddedColon then ident() else EmptyTermName
4174
+
4175
+ def implemented (): List [Tree ] =
4176
+ if isSimpleLiteral then
4177
+ rejectWildcardType(annotType()) :: Nil
4178
+ else constrApp() match
4179
+ case parent : Apply => parent :: moreConstrApps()
4180
+ case parent if in.isIdent && newSyntaxAllowed =>
4181
+ infixTypeRest(parent, _ => annotType1()) :: Nil
4182
+ case parent => parent :: moreConstrApps()
4183
+
4184
+ // The term parameters and parent references */
4185
+ def newTermParamssAndParents (numLeadParams : Int ): (List [List [ValDef ]], List [Tree ]) =
4186
+ if in.token == LPAREN && followingIsArrow() then
4187
+ val params =
4188
+ if in.lookahead.token == RPAREN && numLeadParams == 0 then
4189
+ in.nextToken()
4190
+ in.nextToken()
4191
+ Nil
4192
+ else
4193
+ termParamClause(
4194
+ ParamOwner .Given , numLeadParams, firstClause = true , initialMods = Modifiers (Given ))
4195
+ accept(ARROW )
4196
+ if params.isEmpty then (params :: Nil , implemented())
4197
+ else
4198
+ val (paramss, parents) = newTermParamssAndParents(numLeadParams + params.length)
4199
+ (params :: paramss, parents)
4200
+ else
4201
+ val parents = implemented()
4202
+ if in.token == ARROW && parents.length == 1 && parents.head.isType then
4203
+ in.nextToken()
4204
+ val (paramss, parents1) = newTermParamssAndParents(numLeadParams + parents.length)
4205
+ (typesToParams(parents, ParamOwner .Given , numLeadParams, Modifiers (Given )) :: paramss, parents1)
4206
+ else
4207
+ (Nil , parents)
4208
+
4209
+ /** Type parameters, term parameters and parent clauses */
4210
+ def newSignature (): (List [TypeDef ], (List [List [ValDef ]], List [Tree ])) =
4211
+ val tparams =
4212
+ if in.token == LBRACKET then
4213
+ try typeParamClause(ParamOwner .Given )
4214
+ finally accept(ARROW )
4215
+ else Nil
4216
+ (tparams, newTermParamssAndParents(numLeadParams = 0 ))
4159
4217
4160
4218
def moreConstrApps () =
4161
4219
if newSyntaxAllowed && in.token == COMMA then
@@ -4176,47 +4234,49 @@ object Parsers {
4176
4234
.asInstanceOf [List [ParamClause ]]
4177
4235
4178
4236
val gdef =
4179
- val tparams = typeParamClauseOpt(ParamOwner .Given )
4180
- newLineOpt()
4181
- val vparamss =
4182
- if in.token == LPAREN && (in.lookahead.isIdent(nme.using) || name != EmptyTermName )
4183
- then termParamClauses(ParamOwner .Given )
4184
- else Nil
4185
- newLinesOpt()
4186
- val noParams = tparams.isEmpty && vparamss.isEmpty
4187
- val hasParamsOrId = ! name.isEmpty || ! noParams
4188
- if hasParamsOrId then
4189
- if in.isColon then
4190
- newSyntaxAllowed = false
4237
+ val (tparams, (vparamss0, parents)) =
4238
+ if in.isColon && ! name.isEmpty then
4191
4239
in.nextToken()
4192
- else if newSyntaxAllowed then accept(ARROW )
4193
- else acceptColon()
4194
- val parents =
4195
- if isSimpleLiteral then
4196
- rejectWildcardType(annotType()) :: Nil
4197
- else constrApp() match
4198
- case parent : Apply => parent :: moreConstrApps()
4199
- case parent if in.isIdent && newSyntaxAllowed =>
4200
- infixTypeRest(parent, _ => annotType1()) :: Nil
4201
- case parent => parent :: moreConstrApps()
4202
- if newSyntaxAllowed && in.isIdent(nme.as) then
4203
- in.nextToken()
4204
- name = ident()
4205
-
4240
+ newSignature()
4241
+ else if hasEmbeddedColon then
4242
+ newSyntaxAllowed = false
4243
+ val tparamsOld = typeParamClauseOpt(ParamOwner .Given )
4244
+ newLineOpt()
4245
+ val vparamssOld =
4246
+ if in.token == LPAREN && (in.lookahead.isIdent(nme.using) || name != EmptyTermName )
4247
+ then termParamClauses(ParamOwner .Given )
4248
+ else Nil
4249
+ acceptColon()
4250
+ (tparamsOld, (vparamssOld, implemented()))
4251
+ else
4252
+ newSignature()
4253
+ val hasParams = tparams.nonEmpty || vparamss0.nonEmpty
4254
+ val vparamss = vparamss0 match
4255
+ case Nil :: Nil => Nil
4256
+ case _ => vparamss0
4206
4257
val parentsIsType = parents.length == 1 && parents.head.isType
4207
4258
if in.token == EQUALS && parentsIsType then
4208
4259
// given alias
4209
4260
accept(EQUALS )
4210
4261
mods1 |= Final
4211
- if noParams && ! mods.is(Inline ) then
4262
+ if ! hasParams && ! mods.is(Inline ) then
4212
4263
mods1 |= Lazy
4213
4264
ValDef (name, parents.head, subExpr())
4214
4265
else
4215
4266
DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, subExpr())
4216
- else if (isStatSep || isStatSeqEnd) && parentsIsType && ! newSyntaxAllowed then
4267
+ else if (isStatSep || isStatSeqEnd) && parentsIsType
4268
+ && ! (name.isEmpty && newSyntaxAllowed)
4269
+ // under new syntax, anonymous givens are translated to concrete classes,
4270
+ // so it's treated as a structural instance.
4271
+ then
4217
4272
// old-style abstract given
4218
4273
if name.isEmpty then
4219
- syntaxError(em " anonymous given cannot be abstract " )
4274
+ syntaxError(em " Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument? " , in.lastOffset)
4275
+ if newSyntaxAllowed then
4276
+ warning(
4277
+ em """ This defines an abstract given, which is deprecated. Use a `deferred` given instead.
4278
+ |Or, if you intend to define a concrete given, follow the type with `()` arguments. """ ,
4279
+ in.lastOffset)
4220
4280
DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree )
4221
4281
else
4222
4282
// structural instance
@@ -4228,12 +4288,16 @@ object Parsers {
4228
4288
val templ =
4229
4289
if isStatSep || isStatSeqEnd then
4230
4290
Template (constr, parents, Nil , EmptyValDef , Nil )
4231
- else if ! newSyntaxAllowed || in.token == WITH then
4291
+ else if ! newSyntaxAllowed
4292
+ || in.token == WITH && tparams.isEmpty && vparamss.isEmpty
4293
+ // if new syntax is still allowed and there are parameters, they mist be new style conditions,
4294
+ // so old with-style syntax would not be allowed.
4295
+ then
4232
4296
withTemplate(constr, parents)
4233
4297
else
4234
4298
possibleTemplateStart()
4235
4299
templateBodyOpt(constr, parents, Nil )
4236
- if noParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4300
+ if ! hasParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4237
4301
else TypeDef (name.toTypeName, templ)
4238
4302
end gdef
4239
4303
finalizeDef(gdef, mods1, start)
0 commit comments