Skip to content

Commit 4e57df2

Browse files
committed
Go back to given ... as for instances
1 parent dd6b326 commit 4e57df2

Some content is hidden

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

58 files changed

+190
-172
lines changed

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ object StdNames {
412412
val array_length : N = "array_length"
413413
val array_update : N = "array_update"
414414
val arraycopy: N = "arraycopy"
415+
val as: N = "as"
415416
val asTerm: N = "asTerm"
416417
val asModule: N = "asModule"
417418
val asMethod: N = "asMethod"

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,15 @@ object Parsers {
344344
offset
345345
}
346346

347+
def accept(name: Name): Int = {
348+
val offset = in.offset
349+
if !isIdent(name) then
350+
syntaxErrorOrIncomplete(em"`$name` expected")
351+
if isIdent(name) then
352+
in.nextToken()
353+
offset
354+
}
355+
347356
def reportMissing(expected: Token): Unit =
348357
syntaxError(ExpectedTokenButFound(expected, in.token))
349358

@@ -932,7 +941,7 @@ object Parsers {
932941
if lookahead.token == COLON then
933942
lookahead.nextToken()
934943
!lookahead.isAfterLineEnd
935-
else lookahead.token == SUBTYPE
944+
else lookahead.token == SUBTYPE || lookahead.isIdent(nme.as)
936945

937946
def followingIsExtension() =
938947
val lookahead = in.LookaheadScanner()
@@ -3404,9 +3413,9 @@ object Parsers {
34043413
syntaxError(i"extension clause can only define methods", stat.span)
34053414
}
34063415

3407-
/** GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr
3408-
* | [GivenSig ‘:’] ConstrApps [TemplateBody]
3409-
* GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
3416+
/** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
3417+
* | [GivenSig] ConstrApps [TemplateBody]
3418+
* GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause} ‘as’
34103419
* ExtParamClause ::= [DefTypeParamClause] DefParamClause
34113420
* ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
34123421
*/
@@ -3433,7 +3442,7 @@ object Parsers {
34333442
templ.body.foreach(checkExtensionMethod(tparams, _))
34343443
ModuleDef(name, templ)
34353444
else
3436-
val hasLabel = !name.isEmpty && in.token == COLON
3445+
val hasLabel = !name.isEmpty && in.token == COLON || in.isIdent(nme.as)
34373446
if hasLabel then in.nextToken()
34383447
val tparams = typeParamClauseOpt(ParamOwner.Def)
34393448
val paramsStart = in.offset
@@ -3446,17 +3455,21 @@ object Parsers {
34463455
if !vparam.mods.is(Given) then syntaxError(em"$what must be `given`", vparam.span)))
34473456
checkAllGivens(vparamss, "parameter of given instance")
34483457
val parents =
3449-
if hasLabel then
3450-
constrApps(commaOK = true, templateCanFollow = true)
3451-
else if in.token == SUBTYPE then
3458+
if in.token == SUBTYPE && !hasLabel then
34523459
if !mods.is(Inline) then
34533460
syntaxError("`<:` is only allowed for given with `inline` modifier")
34543461
in.nextToken()
34553462
TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil
34563463
else
3457-
if !(name.isEmpty && tparams.isEmpty && vparamss.isEmpty) then
3458-
accept(COLON)
3459-
constrApps(commaOK = true, templateCanFollow = true)
3464+
if !hasLabel && !(name.isEmpty && tparams.isEmpty && vparamss.isEmpty) then
3465+
if in.token == COLON then in.nextToken()
3466+
else accept(nme.as)
3467+
if in.token == USCORE then
3468+
in.nextToken()
3469+
accept(SUBTYPE)
3470+
TypeBoundsTree(EmptyTree, toplevelTyp()) :: Nil
3471+
else
3472+
constrApps(commaOK = true, templateCanFollow = true)
34603473

34613474
if in.token == EQUALS && parents.length == 1 && parents.head.isType then
34623475
in.nextToken()

docs/blog/_posts/2019-11-04-20th-dotty-milestone-release.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,15 @@ It is now possible to specialize `inline given`s with the help of `<:` as follow
9696
trait A
9797
class B extends A
9898

99-
inline given tc <: A = B()
99+
inline given wb as _ <: A = B()
100100

101101
val x: B = summon[A]
102102
```
103-
104-
This change brings `given`s even with the ordinary `inline def`s.
103+
In this example, the inline given `wb` will return a result of a subtype of the declared upper bound `A` as determined by `B`. In our terminology, `wb` is a whitebox macro. Contrast with the following definition of a blackbox given macro `bb`:
104+
```
105+
inline given bb as A = B()
106+
```
107+
Here, the type of `bb` will always be `A`, no matter what `B` returns.
105108

106109
## Normal parameters can follow `given` parameters
107110
Previously normal parameters after `given` parameter was disallowed mainly because they looked awkward with the old syntax. With the syntax being improved, this restriction is now lifted and you can write, e.g., the following program:

docs/docs/internals/syntax.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,9 @@ ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
384384
ConstrMods ::= {Annotation} [AccessModifier]
385385
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
386386
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
387-
GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr
388-
| [GivenSig ‘:’] ConstrApps [TemplateBody]
389-
GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
387+
GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
388+
| [GivenSig] ConstrApps [TemplateBody]
389+
GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause} ‘as’
390390
ExtensionDef ::= [id] ‘on’ ExtParamClause {GivenParamClause} ExtMethods
391391
ExtMethods ::= [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
392392
ExtParamClause ::= [DefTypeParamClause] ‘(’ DefParam ‘)’

docs/docs/reference/contextual/implicit-function-types.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,13 @@ with implicit function types as parameters to avoid the plumbing boilerplate
8383
that would otherwise be necessary.
8484
```scala
8585
def table(init: (given Table) => Unit) = {
86-
given t: Table
86+
given t as Table
8787
init
8888
t
8989
}
9090

9191
def row(init: (given Row) => Unit)(given t: Table) = {
92-
given r: Row
92+
given r as Row
9393
init
9494
t.add(r)
9595
}

docs/docs/reference/contextual/import-delegate.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A special form of import wildcard selector is used to import given instances. Ex
77
```scala
88
object A {
99
class TC
10-
given tc: TC
10+
given tc as TC
1111
def f(given TC) = ???
1212
}
1313
object B {
@@ -50,8 +50,8 @@ Importing all given instances of a parameterized type is expressed by wildcard a
5050
For instance, assuming the object
5151
```scala
5252
object Instances {
53-
given intOrd: Ordering[Int]
54-
given [T: Ordering] listOrd: Ordering[List[T]]
53+
given intOrd as Ordering[Int]
54+
given [T as Ordering] listOrd as Ordering[List[T]]
5555
given ec: ExecutionContext = ...
5656
given im: Monoid[Int]
5757
}

library/src/scala/IArray.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ object opaques
88
opaque type IArray[+T] = Array[_ <: T]
99

1010
/** Defines extension methods for immutable arrays */
11-
given arrayOps: Object with
11+
given arrayOps: Object {
1212

1313
/** The selection operation on an immutable array.
1414
*
@@ -255,6 +255,7 @@ object opaques
255255
* If one of the two collections is longer than the other, its remaining elements are ignored. */
256256
def [T, U: ClassTag](arr: IArray[T]) zip(that: IArray[U]): IArray[(T, U)] =
257257
genericArrayOps(arr).zip(that).asInstanceOf[IArray[(T, U)]]
258+
}
258259
end opaques
259260

260261
type IArray[+T] = opaques.IArray[T]

tests/neg-custom-args/fatal-warnings/i7821.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ object XObject {
33

44
def anX: X = 5
55

6-
given ops: Object {
6+
given ops as Object {
77
def (x: X) + (y: X): X = x + y
88
}
99
}
@@ -13,7 +13,7 @@ object MyXObject {
1313

1414
def anX: MyX = XObject.anX
1515

16-
given ops: Object {
16+
given ops as Object {
1717
def (x: MyX) + (y: MyX): MyX = x + y // error: warring: Infinite recursive call
1818
}
1919
}

tests/neg/exports.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
type PrinterType
66
def print(bits: BitMap): Unit = ???
77
def status: List[String] = ???
8-
given bitmap : BitMap
8+
given bitmap as BitMap
99
}
1010

1111
class Scanner {

tests/neg/i5978.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ opaque type Position[Buffer] = Int
55
trait TokenParser[Token, R]
66

77
object TextParser {
8-
given TP : TokenParser[Char, Position[CharSequence]] {}
8+
given TP as TokenParser[Char, Position[CharSequence]] {}
99

1010
given FromCharToken(given T: TokenParser[Char, Position[CharSequence]])
1111
: Conversion[Char, Position[CharSequence]] = ???
@@ -22,7 +22,7 @@ object Testcase {
2222
val co_x : Position[CharSequence] = 'x' // error
2323

2424
{
25-
given XXX : Conversion[Char, Position[CharSequence]] = co_i
25+
given XXX as Conversion[Char, Position[CharSequence]] = co_i
2626
val co_y : Position[CharSequence] = 'x'
2727
}
2828
}

0 commit comments

Comments
 (0)