Skip to content

Commit 1b55f8e

Browse files
authored
Merge pull request #6290 from dotty-staging/fix-given-syntax
Disallow refinements in GivenTypes
2 parents dc690a2 + 48e515f commit 1b55f8e

File tree

10 files changed

+74
-23
lines changed

10 files changed

+74
-23
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ object desugar {
158158
vparamss = (setterParam :: Nil) :: Nil,
159159
tpt = TypeTree(defn.UnitType),
160160
rhs = setterRhs
161-
).withMods((mods | Accessor) &~ CaseAccessor)
161+
).withMods((mods | Accessor) &~ (CaseAccessor | Implicit | Given | Lazy))
162162
Thicket(vdef, setter)
163163
}
164164
else vdef

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

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,12 +2082,12 @@ object Parsers {
20822082
if (in.token == LBRACKET) typeParamClause(ownerKind) else Nil
20832083

20842084
/** ClsParamClause ::= [nl] [‘erased’] ‘(’ [ClsParams] ‘)’
2085-
* | ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | ContextTypes)
2085+
* | ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | GivenTypes)
20862086
* ClsParams ::= ClsParam {`' ClsParam}
20872087
* ClsParam ::= {Annotation} [{ParamModifier} (`val' | `var') | `inline'] Param
20882088
* DefParamClause ::= [nl] [‘erased’] ‘(’ [DefParams] ‘)’ | GivenParamClause
2089-
* GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | ContextTypes)
2090-
* ContextTypes ::= RefinedType {`,' RefinedType}
2089+
* GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | GivenTypes)
2090+
* GivenTypes ::= RefinedType {`,' RefinedType}
20912091
* DefParams ::= DefParam {`,' DefParam}
20922092
* DefParam ::= {Annotation} [`inline'] Param
20932093
* Param ::= id `:' ParamType [`=' Expr]
@@ -2190,7 +2190,19 @@ object Parsers {
21902190
}
21912191
val isContextual = initialMods.is(Given)
21922192
newLineOptWhenFollowedBy(LPAREN)
2193-
if (in.token == LPAREN) {
2193+
def isParamClause: Boolean =
2194+
!isContextual || {
2195+
val lookahead = in.lookaheadScanner
2196+
lookahead.nextToken()
2197+
paramIntroTokens.contains(lookahead.token) && {
2198+
lookahead.token != IDENTIFIER ||
2199+
lookahead.name == nme.inline || {
2200+
lookahead.nextToken()
2201+
lookahead.token == COLON
2202+
}
2203+
}
2204+
}
2205+
if (in.token == LPAREN && isParamClause) {
21942206
if (ofInstance && !isContextual)
21952207
syntaxError(em"parameters of instance definitions must come after `given'")
21962208
val params = paramClause(
@@ -2203,7 +2215,7 @@ object Parsers {
22032215
params :: (if (lastClause) Nil else recur(firstClause = false, nparams + params.length))
22042216
}
22052217
else if (isContextual) {
2206-
val tps = commaSeparated(refinedType)
2218+
val tps = commaSeparated(() => annotType())
22072219
var counter = nparams
22082220
def nextIdx = { counter += 1; counter }
22092221
val params = tps.map(makeSyntheticParameter(nextIdx, _, Given | Implicit))
@@ -2612,8 +2624,8 @@ object Parsers {
26122624

26132625
/** InstanceDef ::= [id] InstanceParams InstanceBody
26142626
* InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
2615-
* InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
2616-
* | ‘of’ Type ‘=’ Expr
2627+
* InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
2628+
* | ‘for’ Type ‘=’ Expr
26172629
*/
26182630
def instanceDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) {
26192631
var mods1 = addMod(mods, instanceMod)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ object Tokens extends TokensCommon {
240240

241241
final val modifierFollowers = modifierTokens | defIntroTokens
242242

243+
final val paramIntroTokens: TokenSet = modifierTokens | identifierTokens | BitSet(AT, VAL, VAR, IMPLICIT)
244+
243245
/** Is token only legal as start of statement (eof also included)? */
244246
final val mustStartStatTokens: TokenSet = defIntroTokens | modifierTokens | BitSet(IMPORT, EXPORT, PACKAGE)
245247

compiler/test/dotc/run-from-tasty.blacklist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ eff-dependent.scala
33

44
# It seems we still harmonize types in fromTasty. Not sure where this happens
55
puzzle.scala
6+
7+
# We get: class Foo needs to be abstract, since implicit val x$1: TC is not defined
8+
i2567.scala

docs/docs/internals/syntax.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] |
292292
293293
ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’]
294294
ClsParamClause ::= [nl] [‘erased’] ‘(’ [ClsParams] ‘)’
295-
| ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | ContextTypes)
295+
| ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | GivenTypes)
296296
ClsParams ::= ClsParam {‘,’ ClsParam}
297297
ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var
298298
[{Modifier} (‘val’ | ‘var’) | ‘inline’] Param
@@ -301,10 +301,10 @@ Param ::= id ‘:’ ParamType [‘=’ Expr]
301301
302302
DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [‘implicit’] DefParams ‘)’]
303303
DefParamClause ::= [nl] [‘erased’] ‘(’ [DefParams] ‘)’ | GivenParamClause
304-
GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | ContextTypes)
304+
GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | GivenTypes)
305305
DefParams ::= DefParam {‘,’ DefParam}
306306
DefParam ::= {Annotation} [‘inline’] Param ValDef(mods, id, tpe, expr) -- point of mods at id.
307-
ContextTypes ::= RefinedType {‘,’ RefinedType}
307+
GivenTypes ::= AnnotType {‘,’ AnnotType}
308308
ClosureMods ::= { ‘implicit’ | ‘erased’ | ‘given’}
309309
```
310310

@@ -356,7 +356,6 @@ Def ::= ‘val’ PatDef
356356
| ‘var’ VarDef
357357
| ‘def’ DefDef
358358
| ‘type’ {nl} TypeDcl
359-
| ‘instance’ {nl} InstanceDef
360359
| TmplDef
361360
| INT
362361
PatDef ::= Pattern2 {‘,’ Pattern2} [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr)
@@ -379,8 +378,8 @@ ObjectDef ::= id [Template]
379378
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
380379
InstanceDef ::= [id] InstanceParams InstanceBody
381380
InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
382-
InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
383-
| ‘of’ Type ‘=’ Expr
381+
InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
382+
| ‘for’ Type ‘=’ Expr
384383
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
385384
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
386385
ConstrApps ::= ConstrApp {‘with’ ConstrApp}

docs/docs/reference/contextual/inferable-params.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ def maximum[T](xs: List[T]) given Ord[T]: T =
4141
inferred argument to `max`. The name of the parameter is left out.
4242

4343
Generally, inferable parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)`
44-
or as a sequence of types, separated by commas. To distinguish the two, a leading
45-
`(` always indicates a parameter list.
44+
or as a sequence of types, separated by commas.
4645

4746
## Inferring Complex Arguments
4847

@@ -101,11 +100,11 @@ Functions like `the` that have only inferable parameters are also called _contex
101100
Here is the new syntax of parameters and arguments seen as a delta from the [standard context free syntax of Scala 3](http://dotty.epfl.ch/docs/internals/syntax.html).
102101
```
103102
ClsParamClause ::= ...
104-
| ‘given’ (‘(’ [ClsParams] ‘)’ | ContextTypes)
103+
| ‘given’ (‘(’ [ClsParams] ‘)’ | GivenTypes)
105104
DefParamClause ::= ...
106-
| InferParamClause
107-
InferParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | ContextTypes)
108-
ContextTypes ::= RefinedType {‘,’ RefinedType}
105+
| GivenParamClause
106+
GivenParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | GivenTypes)
107+
GivenTypes ::= AnnotType {‘,’ AnnotType}
109108
110109
InfixExpr ::= ...
111110
| InfixExpr ‘given’ (InfixExpr | ParArgumentExprs)

docs/docs/reference/contextual/instance-defs.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ Here is the new syntax of implied instance definitions, seen as a delta from the
6767
TmplDef ::= ...
6868
| ‘implied’ InstanceDef
6969
InstanceDef ::= [id] InstanceParams InstanceBody
70-
InstanceParams ::= [DefTypeParamClause] {InferParamClause}
71-
InferParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | ContextTypes)
70+
InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
71+
GivenParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | GivenTypes)
7272
InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
7373
| ‘for’ Type ‘=’ Expr
74-
ContextTypes ::= RefinedType {‘,’ RefinedType}
74+
GivenTypes ::= AnnotType {‘,’ AnnotType}
7575
```
7676
The identifier `id` can be omitted only if either the `for` part or the template body is present.
7777
If the `for` part is missing, the template body must define at least one extension method.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class TC { type T }
2+
3+
class C given (TC { type T = Int })
4+
5+
def f1 given (x: TC) = ???
6+
def f2 given (@unchecked x: TC) = ???
7+
inline def f3 given (inline x: TC) = ???
8+
9+
class C1 given (x: TC)
10+
class C2 given (@unchecked x: TC)
11+
class C3 given (val x: TC)
12+
class C4 given (var x: TC)
13+
class C5 given (private val x: TC)
14+
class C6 given (private[this] val x: TC)
15+

tests/run/i2567.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
hi
2+
hi
3+
hi
4+
hi
5+
hi
6+
hi

tests/run/i2567.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class TC
2+
implied tc for TC
3+
4+
class Foo given TC {
5+
println("hi")
6+
}
7+
8+
object Test extends App {
9+
new Foo
10+
new Foo given tc
11+
new Foo()
12+
new Foo() given tc
13+
Foo()
14+
Foo() given tc
15+
}

0 commit comments

Comments
 (0)