diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 384659030c51..78f28f55ad96 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -907,7 +907,7 @@ object Parsers { lookahead.nextToken() while lookahead.token == LPAREN || lookahead.token == LBRACKET do lookahead.skipParens() - lookahead.token == COLON + lookahead.token == COLON || lookahead.token == SUBTYPE /* --------- OPERAND/OPERATOR STACK --------------------------------------- */ @@ -3232,7 +3232,7 @@ object Parsers { case ENUM => enumDef(start, posMods(start, mods | Enum)) case GIVEN => - instanceDef(start, mods, atSpan(in.skipToken()) { Mod.Given() }) + givenDef(start, mods, atSpan(in.skipToken()) { Mod.Given() }) case _ => syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition()) EmptyTree @@ -3336,19 +3336,13 @@ object Parsers { syntaxError(em"extension clause must start with a single regular parameter", start) - /** OLD: - * GivenDef ::= [id] [DefTypeParamClause] GivenBody - * GivenBody ::= [‘as ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody] - * | ‘as’ Type {GivenParamClause} ‘=’ Expr - * | ‘(’ DefParam ‘)’ TemplateBody - * NEW: - * GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr + /** GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr * | [GivenSig ‘:’] [ConstrApp {‘,’ ConstrApp }] [TemplateBody] * | [id ‘:’] [ExtParamClause] TemplateBody * GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause} * ExtParamClause ::= [DefTypeParamClause] DefParamClause {GivenParamClause} */ - def instanceDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) { + def givenDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) { var mods1 = addMod(mods, instanceMod) val hasGivenSig = followingIsGivenSig() val name = if isIdent && hasGivenSig then ident() else EmptyTermName @@ -3382,6 +3376,11 @@ object Parsers { Nil else tokenSeparated(COMMA, constrApp) + else if in.token == SUBTYPE then + if !mods.is(Inline) then + syntaxError("`<:' is only allowed for given with `inline' modifier") + in.nextToken() + TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil else if name.isEmpty && in.token != LBRACE then tokenSeparated(COMMA, constrApp) else Nil @@ -3392,7 +3391,9 @@ object Parsers { mods1 |= Final DefDef(name, tparams, vparamss, parents.head, subExpr()) else - //println(i"given $name $hasExtensionParams $hasGivenSig") + parents match + case TypeBoundsTree(_, _) :: _ => syntaxError("`=' expected") + case _ => possibleTemplateStart() if !hasExtensionParams then tparams = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal)) diff --git a/tests/neg/i7078.scala b/tests/neg/i7078.scala new file mode 100644 index 000000000000..d612f7f2104b --- /dev/null +++ b/tests/neg/i7078.scala @@ -0,0 +1,8 @@ +trait A +class B extends A + +given g1 <: A = B() // error: `<:' is only allowed for given with `inline' modifier // error + +inline given g2 <: A // error: <: A is not a class type + def foo = 2 // error: `=' expected + diff --git a/tests/pos/i7078.scala b/tests/pos/i7078.scala new file mode 100644 index 000000000000..e1299efa5e0b --- /dev/null +++ b/tests/pos/i7078.scala @@ -0,0 +1,7 @@ +trait A +class B extends A + +inline given tc <: A = B() + +val x: B = summon[A] +