@@ -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
@@ -3441,7 +3444,11 @@ object Parsers {
34413444 /** ContextTypes ::= FunArgType {‘,’ FunArgType}
34423445 */
34433446 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 ] =
34453452 var counter = numLeadParams
34463453 def nextIdx = { counter += 1 ; counter }
34473454 val paramFlags = if paramOwner.isClass then LocalParamAccessor else Param
@@ -3468,18 +3475,20 @@ object Parsers {
34683475 def termParamClause (
34693476 paramOwner : ParamOwner ,
34703477 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
34723480 ): List [ValDef ] = {
3473- var impliedMods : Modifiers = EmptyModifiers
3481+ var impliedMods : Modifiers = initialMods
34743482
34753483 def addParamMod (mod : () => Mod ) = impliedMods = addMod(impliedMods, atSpan(in.skipToken()) { mod() })
34763484
34773485 def paramMods () =
34783486 if in.token == IMPLICIT then
34793487 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 ())
34833492
34843493 def param (): ValDef = {
34853494 val start = in.offset
@@ -4144,18 +4153,67 @@ object Parsers {
41444153 * OldGivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
41454154 * StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
41464155 *
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
41524166 * GivenType ::= AnnotType1 {id [nl] AnnotType1}
41534167 */
41544168 def givenDef (start : Offset , mods : Modifiers , givenMod : Mod ) = atSpan(start, nameStart) {
41554169 var mods1 = addMod(mods, givenMod)
41564170 val nameStart = in.offset
4157- var name = if isIdent && followingIsOldStyleGivenSig() then ident() else EmptyTermName
41584171 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 ))
41594217
41604218 def moreConstrApps () =
41614219 if newSyntaxAllowed && in.token == COMMA then
@@ -4176,47 +4234,49 @@ object Parsers {
41764234 .asInstanceOf [List [ParamClause ]]
41774235
41784236 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
41914239 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
42064257 val parentsIsType = parents.length == 1 && parents.head.isType
42074258 if in.token == EQUALS && parentsIsType then
42084259 // given alias
42094260 accept(EQUALS )
42104261 mods1 |= Final
4211- if noParams && ! mods.is(Inline ) then
4262+ if ! hasParams && ! mods.is(Inline ) then
42124263 mods1 |= Lazy
42134264 ValDef (name, parents.head, subExpr())
42144265 else
42154266 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
42174272 // old-style abstract given
42184273 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)
42204280 DefDef (name, adjustDefParams(joinParams(tparams, vparamss)), parents.head, EmptyTree )
42214281 else
42224282 // structural instance
@@ -4228,12 +4288,16 @@ object Parsers {
42284288 val templ =
42294289 if isStatSep || isStatSeqEnd then
42304290 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
42324296 withTemplate(constr, parents)
42334297 else
42344298 possibleTemplateStart()
42354299 templateBodyOpt(constr, parents, Nil )
4236- if noParams && ! mods.is(Inline ) then ModuleDef (name, templ)
4300+ if ! hasParams && ! mods.is(Inline ) then ModuleDef (name, templ)
42374301 else TypeDef (name.toTypeName, templ)
42384302 end gdef
42394303 finalizeDef(gdef, mods1, start)
0 commit comments