Skip to content

Commit ef71dcb

Browse files
committed
Allow types in given definitions to be infix types
A type implemented in a given definition can now be an infix type, without enclosing parens being necessary. By contrast, it cannot anymore be a refined type. Refined types have to be enclosed in parens. This second point aligns the dotty parser with the published syntax and the scala meta parser. # Conflicts: # tests/pos/typeclasses-this.scala
1 parent f96a769 commit ef71dcb

File tree

8 files changed

+45
-35
lines changed

8 files changed

+45
-35
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+18-8
Original file line numberDiff line numberDiff line change
@@ -1806,8 +1806,8 @@ object Parsers {
18061806
*/
18071807
def infixType(): Tree = infixTypeRest(refinedType())
18081808

1809-
def infixTypeRest(t: Tree): Tree =
1810-
infixOps(t, canStartInfixTypeTokens, refinedTypeFn, Location.ElseWhere, ParseKind.Type,
1809+
def infixTypeRest(t: Tree, operand: Location => Tree = refinedTypeFn): Tree =
1810+
infixOps(t, canStartInfixTypeTokens, operand, Location.ElseWhere, ParseKind.Type,
18111811
isOperator = !followingIsVararg() && !isPureArrow
18121812
&& nextCanFollowOperator(canStartInfixTypeTokens))
18131813

@@ -1872,6 +1872,10 @@ object Parsers {
18721872
*/
18731873
def annotType(): Tree = annotTypeRest(simpleType())
18741874

1875+
/** AnnotType1 ::= SimpleType1 {Annotation}
1876+
*/
1877+
def annotType1(): Tree = annotTypeRest(simpleType1())
1878+
18751879
def annotTypeRest(t: Tree): Tree =
18761880
if (in.token == AT)
18771881
annotTypeRest(atSpan(startOffset(t)) {
@@ -4097,8 +4101,10 @@ object Parsers {
40974101
syntaxError(em"extension clause can only define methods", stat.span)
40984102
}
40994103

4100-
/** GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
4101-
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
4104+
/** GivenDef ::= [GivenSig] (GivenType [‘=’ Expr] | StructuralInstance)
4105+
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘:’
4106+
* GivenType ::= AnnotType1 {id [nl] AnnotType1}
4107+
* StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
41024108
*/
41034109
def givenDef(start: Offset, mods: Modifiers, givenMod: Mod) = atSpan(start, nameStart) {
41044110
var mods1 = addMod(mods, givenMod)
@@ -4124,8 +4130,12 @@ object Parsers {
41244130
val noParams = tparams.isEmpty && vparamss.isEmpty
41254131
if !(name.isEmpty && noParams) then acceptColon()
41264132
val parents =
4127-
if isSimpleLiteral then rejectWildcardType(annotType()) :: Nil
4128-
else refinedTypeRest(constrApp()) :: withConstrApps()
4133+
if isSimpleLiteral then
4134+
rejectWildcardType(annotType()) :: Nil
4135+
else constrApp() match
4136+
case parent: Apply => parent :: withConstrApps()
4137+
case parent if in.isIdent => infixTypeRest(parent, _ => annotType1()) :: Nil
4138+
case parent => parent :: withConstrApps()
41294139
val parentsIsType = parents.length == 1 && parents.head.isType
41304140
if in.token == EQUALS && parentsIsType then
41314141
accept(EQUALS)
@@ -4219,10 +4229,10 @@ object Parsers {
42194229

42204230
/* -------- TEMPLATES ------------------------------------------- */
42214231

4222-
/** ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs}
4232+
/** ConstrApp ::= AnnotType1 {ParArgumentExprs}
42234233
*/
42244234
val constrApp: () => Tree = () =>
4225-
val t = rejectWildcardType(annotTypeRest(simpleType1()),
4235+
val t = rejectWildcardType(annotType1(),
42264236
fallbackTree = Ident(tpnme.ERROR))
42274237
// Using Ident(tpnme.ERROR) to avoid causing cascade errors on non-user-written code
42284238
if in.token == LPAREN then parArgumentExprss(wrapNew(t)) else t

docs/_docs/internals/syntax.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ MatchType ::= InfixType `match` <<< TypeCaseClauses >>>
191191
InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2)
192192
RefinedType ::= AnnotType {[nl] Refinement} RefinedTypeTree(t, ds)
193193
AnnotType ::= SimpleType {Annotation} Annotated(t, annot)
194+
AnnotType1 ::= SimpleType1 {Annotation} Annotated(t, annot)
194195
195196
SimpleType ::= SimpleLiteral SingletonTypeTree(l)
196197
| ‘?’ TypeBounds
@@ -466,8 +467,9 @@ ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
466467
ConstrMods ::= {Annotation} [AccessModifier]
467468
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
468469
EnumDef ::= id ClassConstr InheritClauses EnumBody
469-
GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
470+
GivenDef ::= [GivenSig] (GivenType [‘=’ Expr] | StructuralInstance)
470471
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
472+
GivenType ::= AnnotType1 {id [nl] AnnotType1}
471473
StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
472474
Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause}
473475
‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods

docs/_docs/reference/syntax.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ SimpleType ::= SimpleLiteral
200200
| Singleton ‘.’ ‘type’
201201
| ‘(’ [Types] ‘)’
202202
| Refinement
203-
| SimpleType1 TypeArgs
204-
| SimpleType1 ‘#’ id
203+
| SimpleType TypeArgs
204+
| SimpleType ‘#’ id
205205
Singleton ::= SimpleRef
206206
| SimpleLiteral
207207
| Singleton ‘.’ id
@@ -392,7 +392,7 @@ LocalModifier ::= ‘abstract’
392392
AccessModifier ::= (‘private’ | ‘protected’) [AccessQualifier]
393393
AccessQualifier ::= ‘[’ id ‘]’
394394
395-
Annotation ::= ‘@’ SimpleType1 {ParArgumentExprs}
395+
Annotation ::= ‘@’ SimpleType {ParArgumentExprs}
396396
397397
Import ::= ‘import’ ImportExpr {‘,’ ImportExpr}
398398
Export ::= ‘export’ ImportExpr {‘,’ ImportExpr}
@@ -444,6 +444,7 @@ ObjectDef ::= id [Template]
444444
EnumDef ::= id ClassConstr InheritClauses EnumBody
445445
GivenDef ::= [GivenSig] (AnnotType [‘=’ Expr] | StructuralInstance)
446446
GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ‘:’ -- one of `id`, `DefTypeParamClause`, `UsingParamClause` must be present
447+
GivenType ::= AnnotType {id [nl] AnnotType}
447448
StructuralInstance ::= ConstrApp {‘with’ ConstrApp} [‘with’ WithTemplateBody]
448449
Extension ::= ‘extension’ [DefTypeParamClause] {UsingParamClause}
449450
‘(’ DefTermParam ‘)’ {UsingParamClause} ExtMethods
@@ -453,7 +454,7 @@ ExtMethod ::= {Annotation [nl]} {Modifier} ‘def’ DefDef
453454
Template ::= InheritClauses [TemplateBody]
454455
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
455456
ConstrApps ::= ConstrApp ({‘,’ ConstrApp} | {‘with’ ConstrApp})
456-
ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs}
457+
ConstrApp ::= SimpleType {Annotation} {ParArgumentExprs}
457458
ConstrExpr ::= SelfInvocation
458459
| <<< SelfInvocation {semi BlockStat} >>>
459460
SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs}

tests/neg/i12348.check

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
-- [E040] Syntax Error: tests/neg/i12348.scala:2:15 --------------------------------------------------------------------
2-
2 | given inline x: Int = 0 // error
3-
| ^
4-
| 'with' expected, but identifier found
5-
-- [E040] Syntax Error: tests/neg/i12348.scala:3:10 --------------------------------------------------------------------
6-
3 |} // error
7-
| ^
8-
| '}' expected, but eof found
1+
-- [E040] Syntax Error: tests/neg/i12348.scala:2:16 --------------------------------------------------------------------
2+
2 | given inline x: Int = 0 // error // error
3+
| ^
4+
| an identifier expected, but ':' found
5+
-- [E067] Syntax Error: tests/neg/i12348.scala:2:8 ---------------------------------------------------------------------
6+
2 | given inline x: Int = 0 // error // error
7+
| ^
8+
|Declaration of given instance given_x_inline_<error> not allowed here: only classes can have declared but undefined members

tests/neg/i12348.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
object A {
2-
given inline x: Int = 0 // error
3-
} // error
2+
given inline x: Int = 0 // error // error

tests/neg/i7045.scala

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait Bar { type Y }
2+
trait Foo { type X }
3+
4+
class Test:
5+
given a1(using b: Bar): Foo = new Foo { type X = b.Y } // ok
6+
given a2(using b: Bar): (Foo { type X = b.Y }) = new Foo { type X = b.Y } // ok
7+
given a3(using b: Bar): Foo { type X = b.Y } = new Foo { type X = b.Y } // error

tests/pos/i7045.scala

-9
This file was deleted.

tests/pos/typeclass-aggregates.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ trait OrdWithMonoid extends Ord, Monoid
3030
def ordWithMonoid2(ord: Ord, monoid: Monoid{ type This = ord.This }) = //: OrdWithMonoid { type This = ord.This} =
3131
new OrdWithMonoid with ord.OrdProxy with monoid.MonoidProxy {}
3232

33-
given intOrd: Ord { type This = Int } = ???
34-
given intMonoid: Monoid { type This = Int } = ???
33+
given intOrd: (Ord { type This = Int }) = ???
34+
given intMonoid: (Monoid { type This = Int }) = ???
3535

3636
//given (using ord: Ord, monoid: Monoid{ type This = ord.This }): (Ord & Monoid { type This = ord.This}) =
3737
// ordWithMonoid2(ord, monoid)
@@ -42,6 +42,6 @@ val y: Int = ??? : x.This
4242
// given [A, B](using ord: A is Ord, monoid: A is Monoid) => A is Ord & Monoid =
4343
// new ord.OrdProxy with monoid.MonoidProxy {}
4444

45-
given [A](using ord: Ord { type This = A }, monoid: Monoid { type This = A}): (Ord & Monoid) { type This = A} =
45+
given [A](using ord: Ord { type This = A }, monoid: Monoid { type This = A}): ((Ord & Monoid) { type This = A}) =
4646
new ord.OrdProxy with monoid.MonoidProxy {}
4747

0 commit comments

Comments
 (0)