@@ -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
@@ -3432,7 +3435,11 @@ object Parsers {
3432
3435
/** ContextTypes ::= FunArgType {‘,’ FunArgType}
3433
3436
*/
3434
3437
def contextTypes (paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3435
- val tps = commaSeparated(() => paramTypeOf(() => toplevelTyp()))
3438
+ typesToParams(
3439
+ commaSeparated(() => paramTypeOf(() => toplevelTyp())),
3440
+ paramOwner, numLeadParams, impliedMods)
3441
+
3442
+ def typesToParams (tps : List [Tree ], paramOwner : ParamOwner , numLeadParams : Int , impliedMods : Modifiers ): List [ValDef ] =
3436
3443
var counter = numLeadParams
3437
3444
def nextIdx = { counter += 1 ; counter }
3438
3445
val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
@@ -3459,18 +3466,20 @@ object Parsers {
3459
3466
def termParamClause (
3460
3467
paramOwner : ParamOwner ,
3461
3468
numLeadParams : Int , // number of parameters preceding this clause
3462
- firstClause : Boolean = false // clause is the first in regular list of clauses
3469
+ firstClause : Boolean = false , // clause is the first in regular list of clauses
3470
+ initialMods : Modifiers = EmptyModifiers
3463
3471
): List [ValDef ] = {
3464
- var impliedMods : Modifiers = EmptyModifiers
3472
+ var impliedMods : Modifiers = initialMods
3465
3473
3466
3474
def addParamMod (mod : () => Mod ) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
3467
3475
3468
3476
def paramMods () =
3469
3477
if in.token == IMPLICIT then
3470
3478
addParamMod(() => Mod .Implicit ())
3471
- else
3472
- if isIdent(nme.using) then
3473
- addParamMod(() => Mod .Given ())
3479
+ else if isIdent(nme.using) then
3480
+ if initialMods.is(Given ) then
3481
+ syntaxError(em " `using` is already implied here, should not be given explicitly " , in.offset)
3482
+ addParamMod(() => Mod .Given ())
3474
3483
3475
3484
def param (): ValDef = {
3476
3485
val start = in.offset
@@ -4135,18 +4144,67 @@ object Parsers {
4135
4144
* OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
4136
4145
* StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
4137
4146
*
4138
- * NewGivenDef ::= [GivenConditional '=>'] NewGivenSig
4139
- * GivenConditional ::= [DefTypeParamClause | UsingParamClause] {UsingParamClause}
4140
- * NewGivenSig ::= GivenType ['as' id] ([‘=’ Expr] | TemplateBody)
4141
- * | ConstrApps ['as' id] TemplateBody
4142
- *
4147
+ * NewGivenDef ::= [id ':'] GivenSig
4148
+ * GivenSig ::= GivenImpl
4149
+ * | '(' ')' '=>' GivenImpl
4150
+ * | GivenConditional '=>' GivenSig
4151
+ * GivenImpl ::= GivenType ([‘=’ Expr] | TemplateBody)
4152
+ * | ConstrApps TemplateBody
4153
+ * GivenConditional ::= DefTypeParamClause
4154
+ * | DefTermParamClause
4155
+ * | '(' FunArgTypes ')'
4156
+ * | GivenType
4143
4157
* GivenType ::= AnnotType1 {id [nl] AnnotType1}
4144
4158
*/
4145
4159
def givenDef (start : Offset , mods : Modifiers , givenMod : Mod ) = atSpan(start, nameStart) {
4146
4160
var mods1 = addMod(mods, givenMod)
4147
4161
val nameStart = in.offset
4148
- var name = if isIdent && followingIsOldStyleGivenSig() then ident() else EmptyTermName
4149
4162
var newSyntaxAllowed = in.featureEnabled(Feature .modularity)
4163
+ val hasEmbeddedColon = ! in.isColon && followingIsGivenDefWithColon()
4164
+ val name = if isIdent && hasEmbeddedColon then ident() else EmptyTermName
4165
+
4166
+ def implemented (): List [Tree ] =
4167
+ if isSimpleLiteral then
4168
+ rejectWildcardType(annotType()) :: Nil
4169
+ else constrApp() match
4170
+ case parent : Apply => parent :: moreConstrApps()
4171
+ case parent if in.isIdent && newSyntaxAllowed =>
4172
+ infixTypeRest(parent, _ => annotType1()) :: Nil
4173
+ case parent => parent :: moreConstrApps()
4174
+
4175
+ // The term parameters and parent references */
4176
+ def newTermParamssAndParents (numLeadParams : Int ): (List [List [ValDef ]], List [Tree ]) =
4177
+ if in.token == LPAREN && followingIsArrow() then
4178
+ val params =
4179
+ if in.lookahead.token == RPAREN && numLeadParams == 0 then
4180
+ in.nextToken()
4181
+ in.nextToken()
4182
+ Nil
4183
+ else
4184
+ termParamClause(
4185
+ ParamOwner .Given , numLeadParams, firstClause = true , initialMods = Modifiers (Given ))
4186
+ accept(ARROW )
4187
+ if params.isEmpty then (params :: Nil , implemented())
4188
+ else
4189
+ val (paramss, parents) = newTermParamssAndParents(numLeadParams + params.length)
4190
+ (params :: paramss, parents)
4191
+ else
4192
+ val parents = implemented()
4193
+ if in.token == ARROW && parents.length == 1 && parents.head.isType then
4194
+ in.nextToken()
4195
+ val (paramss, parents1) = newTermParamssAndParents(numLeadParams + parents.length)
4196
+ (typesToParams(parents, ParamOwner .Given , numLeadParams, Modifiers (Given )) :: paramss, parents1)
4197
+ else
4198
+ (Nil , parents)
4199
+
4200
+ /** Type parameters, term parameters and parent clauses */
4201
+ def newSignature (): (List [TypeDef ], (List [List [ValDef ]], List [Tree ])) =
4202
+ val tparams =
4203
+ if in.token == LBRACKET then
4204
+ try typeParamClause(ParamOwner .Given )
4205
+ finally accept(ARROW )
4206
+ else Nil
4207
+ (tparams, newTermParamssAndParents(numLeadParams = 0 ))
4150
4208
4151
4209
def moreConstrApps () =
4152
4210
if newSyntaxAllowed && in.token == COMMA then
@@ -4167,47 +4225,49 @@ object Parsers {
4167
4225
.asInstanceOf [List [ParamClause ]]
4168
4226
4169
4227
val gdef =
4170
- val tparams = typeParamClauseOpt(ParamOwner .Given )
4171
- newLineOpt()
4172
- val vparamss =
4173
- if in.token == LPAREN && (in.lookahead.isIdent(nme.using) || name != EmptyTermName )
4174
- then termParamClauses(ParamOwner .Given )
4175
- else Nil
4176
- newLinesOpt()
4177
- val noParams = tparams.isEmpty && vparamss.isEmpty
4178
- val hasParamsOrId = ! name.isEmpty || ! noParams
4179
- if hasParamsOrId then
4180
- if in.isColon then
4181
- newSyntaxAllowed = false
4228
+ val (tparams, (vparamss0, parents)) =
4229
+ if in.isColon && ! name.isEmpty then
4182
4230
in.nextToken()
4183
- else if newSyntaxAllowed then accept(ARROW )
4184
- else acceptColon()
4185
- val parents =
4186
- if isSimpleLiteral then
4187
- rejectWildcardType(annotType()) :: Nil
4188
- else constrApp() match
4189
- case parent : Apply => parent :: moreConstrApps()
4190
- case parent if in.isIdent && newSyntaxAllowed =>
4191
- infixTypeRest(parent, _ => annotType1()) :: Nil
4192
- case parent => parent :: moreConstrApps()
4193
- if newSyntaxAllowed && in.isIdent(nme.as) then
4194
- in.nextToken()
4195
- name = ident()
4196
-
4231
+ newSignature()
4232
+ else if hasEmbeddedColon then
4233
+ newSyntaxAllowed = false
4234
+ val tparamsOld = typeParamClauseOpt(ParamOwner .Given )
4235
+ newLineOpt()
4236
+ val vparamssOld =
4237
+ if in.token == LPAREN && (in.lookahead.isIdent(nme.using) || name != EmptyTermName )
4238
+ then termParamClauses(ParamOwner .Given )
4239
+ else Nil
4240
+ acceptColon()
4241
+ (tparamsOld, (vparamssOld, implemented()))
4242
+ else
4243
+ newSignature()
4244
+ val hasParams = tparams.nonEmpty || vparamss0.nonEmpty
4245
+ val vparamss = vparamss0 match
4246
+ case Nil :: Nil => Nil
4247
+ case _ => vparamss0
4197
4248
val parentsIsType = parents.length == 1 && parents.head.isType
4198
4249
if in.token == EQUALS && parentsIsType then
4199
4250
// given alias
4200
4251
accept(EQUALS )
4201
4252
mods1 |= Final
4202
- if noParams && ! mods.is(Inline ) then
4253
+ if ! hasParams && ! mods.is(Inline ) then
4203
4254
mods1 |= Lazy
4204
4255
ValDef (name, parents.head, subExpr())
4205
4256
else
4206
4257
DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, subExpr())
4207
- else if (isStatSep || isStatSeqEnd) && parentsIsType && ! newSyntaxAllowed then
4258
+ else if (isStatSep || isStatSeqEnd) && parentsIsType
4259
+ && ! (name.isEmpty && newSyntaxAllowed)
4260
+ // under new syntax, anonymous givens are translated to concrete classes,
4261
+ // so it's treated as a structural instance.
4262
+ then
4208
4263
// old-style abstract given
4209
4264
if name.isEmpty then
4210
- syntaxError(em " anonymous given cannot be abstract " )
4265
+ syntaxError(em " Anonymous given cannot be abstract, or maybe you want to define a concrete given and are missing a `()` argument? " , in.lastOffset)
4266
+ if newSyntaxAllowed then
4267
+ warning(
4268
+ em """ This defines an abstract given, which is deprecated. Use a `deferred` given instead.
4269
+ |Or, if you intend to define a concrete given, follow the type with `()` arguments. """ ,
4270
+ in.lastOffset)
4211
4271
DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree )
4212
4272
else
4213
4273
// structural instance
@@ -4219,12 +4279,16 @@ object Parsers {
4219
4279
val templ =
4220
4280
if isStatSep || isStatSeqEnd then
4221
4281
Template (constr, parents, Nil , EmptyValDef , Nil )
4222
- else if ! newSyntaxAllowed || in.token == WITH then
4282
+ else if ! newSyntaxAllowed
4283
+ || in.token == WITH && tparams.isEmpty && vparamss.isEmpty
4284
+ // if new syntax is still allowed and there are parameters, they mist be new style conditions,
4285
+ // so old with-style syntax would not be allowed.
4286
+ then
4223
4287
withTemplate(constr, parents)
4224
4288
else
4225
4289
possibleTemplateStart()
4226
4290
templateBodyOpt(constr, parents, Nil )
4227
- if noParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4291
+ if ! hasParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4228
4292
else TypeDef (name.toTypeName, templ)
4229
4293
end gdef
4230
4294
finalizeDef(gdef, mods1, start)
0 commit comments