Skip to content

Commit 6beb2f4

Browse files
authored
Merge pull request #8283 from dotty-staging/change-given-as
Drop outdated syntax for given instances
2 parents a29178c + 6b676fc commit 6beb2f4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+185
-215
lines changed

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

Lines changed: 37 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -910,28 +910,6 @@ object Parsers {
910910
followedByToken(LARROW) // `<-` comes before possible statement starts
911911
}
912912

913-
/** Are the next tokens a prefix of a formal parameter or given type?
914-
* @pre: current token is LPAREN
915-
* TODO: Drop once syntax has stabilized
916-
*/
917-
def followingIsParamOrGivenType() =
918-
val lookahead = in.LookaheadScanner()
919-
lookahead.nextToken()
920-
if startParamTokens.contains(lookahead.token)
921-
|| lookahead.isIdent(nme.using)
922-
then true
923-
else if lookahead.token == IDENTIFIER then
924-
if lookahead.name == nme.inline then
925-
lookahead.nextToken()
926-
if lookahead.token == IDENTIFIER then
927-
lookahead.nextToken()
928-
if lookahead.token == COLON then
929-
lookahead.nextToken()
930-
!lookahead.isAfterLineEnd
931-
else false
932-
else false
933-
else false
934-
935913
/** Are the next token the "GivenSig" part of a given definition,
936914
* i.e. an identifier followed by type and value parameters, followed by `:`?
937915
* @pre The current token is an identifier
@@ -940,14 +918,15 @@ object Parsers {
940918
val lookahead = in.LookaheadScanner()
941919
if lookahead.isIdent then
942920
lookahead.nextToken()
943-
while lookahead.token == LPAREN || lookahead.token == LBRACKET do
944-
lookahead.skipParens()
945-
if lookahead.token == COLON then // TODO: remove
946-
lookahead.nextToken()
947-
!lookahead.isAfterLineEnd
948-
else
949-
lookahead.token == SUBTYPE // TODO: remove
950-
|| lookahead.isIdent(nme.as)
921+
def skipParams(): Unit =
922+
if lookahead.token == LPAREN || lookahead.token == LBRACKET then
923+
lookahead.skipParens()
924+
skipParams()
925+
else if lookahead.isNewLine then
926+
lookahead.nextToken()
927+
skipParams()
928+
skipParams()
929+
lookahead.isIdent(nme.as)
951930

952931
def followingIsExtension() =
953932
val lookahead = in.LookaheadScanner()
@@ -3502,57 +3481,44 @@ object Parsers {
35023481
* | [GivenSig] ConstrApps [TemplateBody]
35033482
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
35043483
*/
3505-
def givenDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) {
3506-
var mods1 = addMod(mods, instanceMod)
3484+
def givenDef(start: Offset, mods: Modifiers, givenMod: Mod) = atSpan(start, nameStart) {
3485+
var mods1 = addMod(mods, givenMod)
35073486
val hasGivenSig = followingIsGivenSig()
35083487
val nameStart = in.offset
35093488
val name = if isIdent && hasGivenSig then ident() else EmptyTermName
35103489

35113490
val gdef = in.endMarkerScope(if name.isEmpty then GIVEN else name) {
3512-
val hasLabel = !name.isEmpty && in.token == COLON || isIdent(nme.as)
3513-
if hasLabel then in.nextToken()
35143491
val tparams = typeParamClauseOpt(ParamOwner.Def)
3515-
val paramsStart = in.offset
3492+
newLineOpt()
35163493
val vparamss =
3517-
if in.token == LPAREN && followingIsParamOrGivenType()
3518-
then paramClauses()
3494+
if in.token == LPAREN && in.lookaheadIn(nme.using)
3495+
then paramClauses(givenOnly = true)
35193496
else Nil
3520-
def checkAllGivens(vparamss: List[List[ValDef]], what: String) =
3521-
vparamss.foreach(_.foreach(vparam =>
3522-
if !vparam.mods.is(Given) then syntaxError(em"$what must be preceded by `using`", vparam.span)))
3523-
checkAllGivens(vparamss, "parameter of given instance")
3524-
val parents =
3525-
if in.token == SUBTYPE && !hasLabel then
3526-
if !mods.is(Inline) then
3527-
syntaxError("`<:` is only allowed for given with `inline` modifier")
3528-
in.nextToken()
3529-
TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil
3530-
else
3531-
if !hasLabel && !(name.isEmpty && tparams.isEmpty && vparamss.isEmpty) then
3532-
if in.token == COLON then in.nextToken()
3533-
else accept(nme.as)
3534-
if in.token == USCORE then
3535-
in.nextToken()
3536-
accept(SUBTYPE)
3537-
TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil
3538-
else
3539-
constrApps(commaOK = true, templateCanFollow = true)
3540-
3541-
if in.token == EQUALS && parents.length == 1 && parents.head.isType then
3542-
in.nextToken()
3497+
newLinesOpt()
3498+
if isIdent(nme.as) || !name.isEmpty || !tparams.isEmpty || !vparamss.isEmpty then
3499+
accept(nme.as)
3500+
def givenAlias(tpt: Tree) =
3501+
accept(EQUALS)
35433502
mods1 |= Final
3544-
DefDef(name, tparams, vparamss, parents.head, subExpr())
3503+
DefDef(name, tparams, vparamss, tpt, subExpr())
3504+
if in.token == USCORE then
3505+
if !mods.is(Inline) then
3506+
syntaxError("`_ <:` is only allowed for given with `inline` modifier")
3507+
in.nextToken()
3508+
accept(SUBTYPE)
3509+
givenAlias(TypeBoundsTree(EmptyTree, toplevelTyp()))
35453510
else
3546-
parents match
3547-
case (_: TypeBoundsTree) :: _ => syntaxError("`=` expected")
3548-
case _ =>
3549-
possibleTemplateStart()
3550-
val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal))
3551-
val vparamss1 = vparamss.map(_.map(vparam =>
3552-
vparam.withMods(vparam.mods &~ Param | ParamAccessor | PrivateLocal)))
3553-
val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil)
3554-
if tparams.isEmpty && vparamss.isEmpty then ModuleDef(name, templ)
3555-
else TypeDef(name.toTypeName, templ)
3511+
val parents = constrApps(commaOK = true, templateCanFollow = true)
3512+
if in.token == EQUALS && parents.length == 1 && parents.head.isType then
3513+
givenAlias(parents.head)
3514+
else
3515+
possibleTemplateStart()
3516+
val tparams1 = tparams.map(tparam => tparam.withMods(tparam.mods | PrivateLocal))
3517+
val vparamss1 = vparamss.map(_.map(vparam =>
3518+
vparam.withMods(vparam.mods &~ Param | ParamAccessor | PrivateLocal)))
3519+
val templ = templateBodyOpt(makeConstructor(tparams1, vparamss1), parents, Nil)
3520+
if tparams.isEmpty && vparamss.isEmpty then ModuleDef(name, templ)
3521+
else TypeDef(name.toTypeName, templ)
35563522
}
35573523
finalizeDef(gdef, mods1, start)
35583524
}

compiler/src/dotty/tools/dotc/semanticdb/Scala3.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ object Scala3 with
212212
// end RangeOps
213213

214214
/** Sort symbol occurrences by their start position. */
215-
given OccurrenceOrdering: Ordering[SymbolOccurrence] = (x, y) =>
215+
given OccurrenceOrdering as Ordering[SymbolOccurrence] = (x, y) =>
216216
x.range -> y.range match
217217
case None -> _ | _ -> None => 0
218218
case Some(a) -> Some(b) =>

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,7 +1412,7 @@ trait Applications extends Compatibility {
14121412
/** Widen the result type of synthetic given methods from the implementation class to the
14131413
* type that's implemented. Example
14141414
*
1415-
* given I[X] : T { ... }
1415+
* given I[X] as T { ... }
14161416
*
14171417
* This desugars to
14181418
*
@@ -1422,7 +1422,7 @@ trait Applications extends Compatibility {
14221422
* To compare specificity we should compare with `T`, not with its implementation `I[X]`.
14231423
* No such widening is performed for given aliases, which are not synthetic. E.g.
14241424
*
1425-
* given J[X] : T = rhs
1425+
* given J[X] as T = rhs
14261426
*
14271427
* already has the right result type `T`. Neither is widening performed for given
14281428
* objects, since these are anyway taken to be more specific than methods

compiler/src/dotty/tools/dotc/typer/Deriving.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ trait Deriving {
122122
//
123123
// ADT: C[A, B] (A, B have same kinds at T, U)
124124
//
125-
// given derived$TC : TC[ C ] // a "natural" instance
125+
// given derived$TC as TC[ C ] // a "natural" instance
126126
//
127127
// ADT: C[A] (A has same kind as U)
128128
//
129-
// given derived$TC : TC[[t, u] =>> C[ u]]
129+
// given derived$TC as TC[[t, u] =>> C[ u]]
130130
//
131131
// (b) The type class and all ADT type parameters are of kind *
132132
//

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,7 @@ class Typer extends Namer
13021302
}
13031303

13041304
def typedWhileDo(tree: untpd.WhileDo)(implicit ctx: Context): Tree = {
1305-
given whileCtx: Context = Nullables.whileContext(tree.span)(using ctx)
1305+
given whileCtx as Context = Nullables.whileContext(tree.span)(using ctx)
13061306
val cond1 =
13071307
if (tree.cond eq EmptyTree) EmptyTree
13081308
else typed(tree.cond, defn.BooleanType)

compiler/test/dotty/tools/repl/ReplCompilerTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class ReplCompilerTests extends ReplTest {
151151
| def (x: T) > (y: T) = compare(x, y) > 0
152152
|}
153153
|
154-
|given IntOrd : Ord[Int] {
154+
|given IntOrd as Ord[Int] {
155155
| def compare(x: Int, y: Int) =
156156
| if (x < y) -1 else if (x > y) +1 else 0
157157
|}

docs/docs/contributing/debugging.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ But you can also do:
8888
assertPositioned(tree.reporting(s"Tree is: $result"))
8989
```
9090

91-
`def (a: A).reporting(f: given WrappedResult[T] => String, p: Printer = Printers.default): A` is defined on all types. The function `f` can be written without the argument since the argument is `given`. The `result` variable is a part of the `WrapperResult` – a tiny framework powering the `reporting` function. Basically, whenever you are using `reporting` on an object `A`, you can use the `result: A` variable from this function and it will be equal to the object you are calling `reporting` on.
91+
`def (a: A).reporting(f: WrappedResult[T] ?=> String, p: Printer = Printers.default): A` is defined on all types. The function `f` can be written without the argument since it is a context function`. The `result` variable is a part of the `WrapperResult` – a tiny framework powering the `reporting` function. Basically, whenever you are using `reporting` on an object `A`, you can use the `result: A` variable from this function and it will be equal to the object you are calling `reporting` on.
9292

9393
## Printing out trees after phases
9494
To print out the trees you are compiling after the FrontEnd (scanner, parser, namer, typer) phases:

docs/docs/internals/syntax.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (id [HkTypeParamClause]
296296
SubtypeBounds
297297
298298
ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’]
299-
ClsParamClause ::= [nl] ‘(’ ClsParams ‘)’
299+
ClsParamClause ::= [nl] ‘(’ ClsParams ‘)’
300300
| [nl] ‘(’ ‘using’ (ClsParams | Types) ‘)’
301301
ClsParams ::= ClsParam {‘,’ ClsParam}
302302
ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var

docs/docs/reference/changed-features/eta-expansion-spec.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ val bar = foo // val bar: Int => Float = ...
5050

5151
## Automatic Eta-Expansion and query types
5252

53-
A method with inferable parameters can be expanded to a value of query type by writing the expected query type explicitly.
53+
A method with context parameters can be expanded to a value of a context type by writing the expected context type explicitly.
5454

5555
```scala
56-
def foo(x: Int) given (p: Double): Float = ???
57-
val bar: given Double => Float = foo(3) // val bar: given Double => Float = ...
56+
def foo(x: Int)(using p: Double): Float = ???
57+
val bar: Double ?=> Float = foo(3)
5858
```
5959

6060
## Rules

docs/docs/reference/changed-features/implicit-resolution.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ affect implicits on the language level.
4343
Example:
4444
```scala
4545
package p
46-
given a : A
46+
given a as A
4747

4848
object o {
49-
given b : B
49+
given b as B
5050
type C
5151
}
5252
```

docs/docs/reference/changed-features/numeric-literals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ object BigFloat {
156156
To accept `BigFloat` literals, all that's needed in addition is a given instance of type
157157
`FromDigits.Floating[BigFloat]`:
158158
```scala
159-
given FromDigits : FromDigits.Floating[BigFloat] {
159+
given FromDigits as FromDigits.Floating[BigFloat] {
160160
def fromDigits(digits: String) = apply(digits)
161161
}
162162
} // end BigFloat

docs/docs/reference/contextual/derivation-macro.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ we need to implement a method `Eq.derived` on the companion object of `Eq` that
2525
produces a quoted instance for `Eq[T]`. Here is a possible signature,
2626

2727
```scala
28-
given derived[T: Type](using qctx: QuoteContext): Expr[Eq[T]]
28+
given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]]
2929
```
3030

3131
and for comparison reasons we give the same signature we had with `inline`:
3232

3333
```scala
34-
inline given derived[T]: (m: Mirror.Of[T]) => Eq[T] = ???
34+
inline given derived[T] as (m: Mirror.Of[T]) => Eq[T] = ???
3535
```
3636

3737
Note, that since a type is used in a subsequent stage it will need to be lifted
@@ -41,7 +41,7 @@ from the signature. The body of the `derived` method is shown below:
4141

4242

4343
```scala
44-
given derived[T: Type](using qctx: QuoteContext): Expr[Eq[T]] = {
44+
given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = {
4545
import qctx.tasty.{_, given}
4646

4747
val ev: Expr[Mirror.Of[T]] = summonExpr(using '[Mirror.Of[T]]).get
@@ -175,7 +175,7 @@ object Eq {
175175
case '[Unit] => Nil
176176
}
177177

178-
given derived[T: Type](using qctx: QuoteContext): Expr[Eq[T]] = {
178+
given derived[T: Type](using qctx: QuoteContext) as Expr[Eq[T]] = {
179179
import qctx.tasty.{_, given}
180180

181181
val ev: Expr[Mirror.Of[T]] = summonExpr(using '[Mirror.Of[T]]).get

docs/docs/reference/metaprogramming/erased-terms-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ title: "Erased Terms Spec"
3232

3333
3. Functions
3434
* `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R`
35-
* `(given erased x1: T1, x2: T2, ..., xN: TN) => y : (given erased T1, T2, ..., TN) => R`
35+
* `(given erased x1: T1, x2: T2, ..., xN: TN) => y as (given erased T1, T2, ..., TN) => R`
3636
* `(given erased T1) => R <:< erased T1 => R`
3737
* `(given erased T1, T2) => R <:< (erased T1, T2) => R`
3838
* ...

docs/docs/reference/metaprogramming/macros-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ With the right extractors, the "AsFunction" conversion
191191
that maps expressions over functions to functions over expressions can
192192
be implemented in user code:
193193
```scala
194-
given AsFunction1[T, U] : Conversion[Expr[T => U], Expr[T] => Expr[U]] {
194+
given AsFunction1[T, U] as Conversion[Expr[T => U], Expr[T] => Expr[U]] {
195195
def apply(f: Expr[T => U]): Expr[T] => Expr[U] =
196196
(x: Expr[T]) => f match {
197197
case Lambda(g) => g(x)

docs/docs/reference/metaprogramming/macros.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ given Liftable[Int] {
289289
Since `Liftable` is a type class, its instances can be conditional. For example,
290290
a `List` is liftable if its element type is:
291291
```scala
292-
given [T: Liftable : Type] : Liftable[List[T]] {
292+
given [T: Liftable : Type] as Liftable[List[T]] {
293293
def toExpr(xs: List[T]) = xs match {
294294
case head :: tail => '{ ${ Expr(head) } :: ${ toExpr(tail) } }
295295
case Nil => '{ Nil: List[T] }

docs/docs/reference/other-new-features/quoted-pattern-spec.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Splices can be of two forms:
1212
* A splice `${ ... : Bind[T] }` that can be placed on names of `val`s, `var`s or `def`s
1313

1414
```scala
15-
def foo(x: Expr[Int]) given tasty.Reflect: Expr[Int] = x match {
15+
def foo(x: Expr[Int])(using tasty.Reflect): Expr[Int] = x match {
1616
case '{ val $a: Int = $x; (${Bind(`a`)}: Int) + 1 } => '{ $x + 1 } // TODO needs fix for #6328, `a` is currently not in scope while typing
1717
}
1818
```
@@ -21,7 +21,7 @@ In the example above we have `$a` which provides a `Bind[Int]`, `$x` which provi
2121
Quoted patterns are transformed during typer to a call of `scala.internal.quoted.Expr.unapply` which splits the quoted code into the patterns and a reifiable quote that will be used as witnesses at runtime.
2222

2323
```scala
24-
def foo(x: Expr[Int]) given tasty.Reflect: Expr[Int] = x match {
24+
def foo(x: Expr[Int])(using tasty.Reflect): Expr[Int] = x match {
2525
case scala.internal.quoted.Expr.unapply[Tuple3[Bind[Int], Expr[Int], Expr[Int]]](Tuple3(a, x, Bind(`a`), y))('{ @patternBindHole val a: Int = patternHole[Int]; patternHole[Int] + 1 }) =>
2626
}
2727
```

library/src/scala/IArray.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object opaques:
1111
private[scala] type Sup[A] >: IArray[A] <: Array[_ <: A]
1212

1313
/** Defines extension methods for immutable arrays */
14-
given arrayOps: Object {
14+
given arrayOps as Object {
1515

1616
/** The selection operation on an immutable array.
1717
*

0 commit comments

Comments
 (0)