@@ -972,18 +972,16 @@ object Parsers {
972972 followedByToken(LARROW ) // `<-` comes before possible statement starts
973973 }
974974
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 `:`?
977977 * @pre The current token is an identifier
978978 */
979- def followingIsOldStyleGivenSig () =
979+ def followingIsGivenDefWithColon () =
980980 val lookahead = in.LookaheadScanner ()
981981 if lookahead.isIdent then
982982 lookahead.nextToken()
983- var paramsSeen = false
984983 def skipParams (): Unit =
985984 if lookahead.token == LPAREN || lookahead.token == LBRACKET then
986- paramsSeen = true
987985 lookahead.skipParens()
988986 skipParams()
989987 else if lookahead.isNewLine then
@@ -1002,6 +1000,11 @@ object Parsers {
10021000 }
10031001 }
10041002
1003+ def followingIsArrow () =
1004+ val lookahead = in.LookaheadScanner ()
1005+ lookahead.skipParens()
1006+ lookahead.token == ARROW
1007+
10051008 def followingIsExtension () =
10061009 val next = in.lookahead.token
10071010 next == LBRACKET || next == LPAREN
@@ -3432,7 +3435,11 @@ object Parsers {
34323435 /** ContextTypes ::= FunArgType {‘,’ FunArgType}
34333436 */
34343437 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 ] =
34363443 var counter = numLeadParams
34373444 def nextIdx = { counter += 1 ; counter }
34383445 val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
@@ -3459,18 +3466,20 @@ object Parsers {
34593466 def termParamClause (
34603467 paramOwner : ParamOwner ,
34613468 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
34633471 ): List [ValDef ] = {
3464- var impliedMods : Modifiers = EmptyModifiers
3472+ var impliedMods : Modifiers = initialMods
34653473
34663474 def addParamMod (mod : () => Mod ) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
34673475
34683476 def paramMods () =
34693477 if in.token == IMPLICIT then
34703478 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 ())
34743483
34753484 def param (): ValDef = {
34763485 val start = in.offset
@@ -4135,18 +4144,67 @@ object Parsers {
41354144 * OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
41364145 * StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
41374146 *
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
41434157 * GivenType ::= AnnotType1 {id [nl] AnnotType1}
41444158 */
41454159 def givenDef (start : Offset , mods : Modifiers , givenMod : Mod ) = atSpan(start, nameStart) {
41464160 var mods1 = addMod(mods, givenMod)
41474161 val nameStart = in.offset
4148- var name = if isIdent && followingIsOldStyleGivenSig() then ident() else EmptyTermName
41494162 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 ))
41504208
41514209 def moreConstrApps () =
41524210 if newSyntaxAllowed && in.token == COMMA then
@@ -4167,47 +4225,49 @@ object Parsers {
41674225 .asInstanceOf [List [ParamClause ]]
41684226
41694227 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
41824230 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
41974248 val parentsIsType = parents.length == 1 && parents.head.isType
41984249 if in.token == EQUALS && parentsIsType then
41994250 // given alias
42004251 accept(EQUALS )
42014252 mods1 |= Final
4202- if noParams && ! mods.is(Inline ) then
4253+ if ! hasParams && ! mods.is(Inline ) then
42034254 mods1 |= Lazy
42044255 ValDef (name, parents.head, subExpr())
42054256 else
42064257 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
42084263 // old-style abstract given
42094264 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)
42114271 DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree )
42124272 else
42134273 // structural instance
@@ -4219,12 +4279,16 @@ object Parsers {
42194279 val templ =
42204280 if isStatSep || isStatSeqEnd then
42214281 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
42234287 withTemplate(constr, parents)
42244288 else
42254289 possibleTemplateStart()
42264290 templateBodyOpt(constr, parents, Nil )
4227- if noParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4291+ if ! hasParams && ! mods.is(Inline ) then ModuleDef (name, templ)
42284292 else TypeDef (name.toTypeName, templ)
42294293 end gdef
42304294 finalizeDef(gdef, mods1, start)
0 commit comments