Skip to content

Commit 323e39b

Browse files
committed
Implement syntax change from delegate to given
1 parent 7a4ea9f commit 323e39b

File tree

9 files changed

+75
-65
lines changed

9 files changed

+75
-65
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ object desugar {
825825
*/
826826
def normalizeName(mdef: MemberDef, impl: Tree)(implicit ctx: Context): Name = {
827827
var name = mdef.name
828-
if (name.isEmpty) name = name.likeSpaced(s"${inventName(impl)}_instance".toTermName)
828+
if (name.isEmpty) name = name.likeSpaced(s"${inventName(impl)}_given".toTermName)
829829
if (ctx.owner == defn.ScalaPackageClass && defn.reservedScalaClassNames.contains(name.toTypeName)) {
830830
def kind = if (name.isTypeName) "class" else "object"
831831
ctx.error(em"illegal redefinition of standard $kind $name", mdef.sourcePos)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ object StdNames {
386386
val array_length : N = "array_length"
387387
val array_update : N = "array_update"
388388
val arraycopy: N = "arraycopy"
389+
val as: N = "as"
389390
val asTerm: N = "asTerm"
390391
val asModule: N = "asModule"
391392
val asMethod: N = "asMethod"

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

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,16 @@ object Parsers {
194194
/** Is current token a hard or soft modifier (in modifier position or not)? */
195195
def isModifier: Boolean = modifierTokens.contains(in.token) || in.isSoftModifier
196196

197-
def isBindingIntro: Boolean =
198-
canStartBindingTokens.contains(in.token) &&
199-
!in.isSoftModifierInModifierPosition
197+
def isBindingIntro: Boolean = {
198+
in.token match {
199+
case USCORE | LPAREN => true
200+
case IDENTIFIER | BACKQUOTED_IDENT => in.lookaheadIn(BitSet(COLON, ARROW))
201+
case _ => false
202+
}
203+
} && !in.isSoftModifierInModifierPosition
200204

201205
def isExprIntro: Boolean =
202-
if (in.token == IMPLIED) in.lookaheadIn(BitSet(MATCH))
206+
if (in.token == IMPLIED || in.token == GIVEN) in.lookaheadIn(BitSet(MATCH))
203207
else (canStartExpressionTokens.contains(in.token) && !in.isSoftModifierInModifierPosition)
204208

205209
def isDefIntro(allowedMods: BitSet, excludedSoftModifiers: Set[TermName] = Set.empty): Boolean =
@@ -1293,7 +1297,7 @@ object Parsers {
12931297
if (in.token == MATCH) impliedMatch(start, imods)
12941298
else implicitClosure(start, location, imods)
12951299
}
1296-
else if(in.token == IMPLIED) {
1300+
else if (in.token == IMPLIED || in.token == GIVEN) {
12971301
in.nextToken()
12981302
if (in.token == MATCH)
12991303
impliedMatch(start, EmptyModifiers)
@@ -2359,12 +2363,12 @@ object Parsers {
23592363

23602364
type ImportConstr = (Boolean, Tree, List[Tree]) => Tree
23612365

2362-
/** Import ::= import [delegate] [ImportExpr {`,' ImportExpr}
2363-
* Export ::= export [delegate] [ImportExpr {`,' ImportExpr}
2366+
/** Import ::= `import' [`given'] [ImportExpr {`,' ImportExpr}
2367+
* Export ::= `export' [`given'] [ImportExpr {`,' ImportExpr}
23642368
*/
23652369
def importClause(leading: Token, mkTree: ImportConstr): List[Tree] = {
23662370
val offset = accept(leading)
2367-
val importDelegate = in.token == IMPLIED
2371+
val importDelegate = in.token == IMPLIED || in.token == GIVEN
23682372
if (importDelegate) in.nextToken()
23692373
commaSeparated(importExpr(importDelegate, mkTree)) match {
23702374
case t :: rest =>
@@ -2706,8 +2710,8 @@ object Parsers {
27062710
objectDef(start, posMods(start, mods | Case | Module))
27072711
case ENUM =>
27082712
enumDef(start, posMods(start, mods | Enum))
2709-
case IMPLIED =>
2710-
instanceDef(start, mods, atSpan(in.skipToken()) { Mod.Delegate() })
2713+
case IMPLIED | GIVEN =>
2714+
instanceDef(in.token == GIVEN, start, mods, atSpan(in.skipToken()) { Mod.Delegate() })
27112715
case _ =>
27122716
syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition())
27132717
EmptyTree
@@ -2804,12 +2808,12 @@ object Parsers {
28042808
* InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
28052809
* | ‘for’ Type {GivenParamClause} ‘=’ Expr
28062810
*/
2807-
def instanceDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) {
2811+
def instanceDef(newStyle: Boolean, start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) {
28082812
var mods1 = addMod(mods, instanceMod)
2809-
val name = if (isIdent) ident() else EmptyTermName
2813+
val name = if (isIdent && (!newStyle || in.name != nme.as)) ident() else EmptyTermName
28102814
val tparams = typeParamClauseOpt(ParamOwner.Def)
28112815
val parents =
2812-
if (in.token == FOR) {
2816+
if (!newStyle && in.token == FOR || newStyle && isIdent(nme.as)) {
28132817
in.nextToken()
28142818
tokenSeparated(COMMA, constrApp)
28152819
}
@@ -3116,8 +3120,16 @@ object Parsers {
31163120
setLastStatOffset()
31173121
if (in.token == IMPORT)
31183122
stats ++= importClause(IMPORT, Import)
3119-
else if (in.token == GIVEN)
3120-
stats += implicitClosure(in.offset, Location.InBlock, modifiers(closureMods))
3123+
else if (in.token == GIVEN) {
3124+
val start = in.offset
3125+
val mods = modifiers(closureMods)
3126+
mods.mods match {
3127+
case givenMod :: Nil if !isBindingIntro =>
3128+
stats += instanceDef(true, start, EmptyModifiers, Mod.Delegate().withSpan(givenMod.span))
3129+
case _ =>
3130+
stats += implicitClosure(in.offset, Location.InBlock, mods)
3131+
}
3132+
}
31213133
else if (isExprIntro)
31223134
stats += expr(Location.InBlock)
31233135
else if (isDefIntro(localModifierTokens, excludedSoftModifiers = Set(nme.`opaque`)))

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,16 +216,14 @@ object Tokens extends TokensCommon {
216216
USCORE, NULL, THIS, SUPER, TRUE, FALSE, RETURN, QUOTEID, XMLSTART)
217217

218218
final val canStartExpressionTokens: TokenSet = atomicExprTokens | BitSet(
219-
LBRACE, LPAREN, QUOTE, IF, DO, WHILE, FOR, NEW, TRY, THROW, IMPLIED)
219+
LBRACE, LPAREN, QUOTE, IF, DO, WHILE, FOR, NEW, TRY, THROW, IMPLIED, GIVEN)
220220

221221
final val canStartTypeTokens: TokenSet = literalTokens | identifierTokens | BitSet(
222222
THIS, SUPER, USCORE, LPAREN, AT)
223223

224-
final val canStartBindingTokens: TokenSet = identifierTokens | BitSet(USCORE, LPAREN)
225-
226224
final val templateIntroTokens: TokenSet = BitSet(CLASS, TRAIT, OBJECT, ENUM, CASECLASS, CASEOBJECT)
227225

228-
final val dclIntroTokens: TokenSet = BitSet(DEF, VAL, VAR, TYPE, IMPLIED)
226+
final val dclIntroTokens: TokenSet = BitSet(DEF, VAL, VAR, TYPE, IMPLIED, GIVEN)
229227

230228
final val defIntroTokens: TokenSet = templateIntroTokens | dclIntroTokens
231229

docs/docs/reference/contextual/delegates.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ given ListOrd[T] as Ord[List[T]] given (ord: Ord[T]) {
3131
}
3232
}
3333
```
34-
This code defines a trait `Ord` with two givens. `IntOrd` defines
34+
This code defines a trait `Ord` with two given instances. `IntOrd` defines
3535
a given for the type `Ord[Int]` whereas `ListOrd[T]` defines givens
3636
for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]` themselves.
3737
The `given (ord: Ord[T])` clause in `ListOrd` defines an implicit parameter.
3838
Given clauses are further explained in the [next section](./given-clauses.html).
3939

4040
## Anonymous Given Instances
4141

42-
The name of a given instance can be left out. So the given definitions
42+
The name of a given instance can be left out. So the definitions
4343
of the last section can also be expressed like this:
4444
```scala
4545
given as Ord[Int] { ... }

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object B {
1818
In the code above, the `import A._` clause of object `B` will import all members
1919
of `A` _except_ the given instance `tc`. Conversely, the second import `import given A._` will import _only_ that given instance.
2020

21-
Generally, a normal import clause brings all definitions except given instances into scope whereas a `given` import brings only given instances into scope.
21+
Generally, a normal import clause brings definitions other than given instances into scope whereas a `given` import brings only given instances into scope.
2222

2323
There are two main benefits arising from these rules:
2424

@@ -62,7 +62,7 @@ would import `im`, `intOrd`, and `listOrd` but leave out `ec`. By-type imports c
6262

6363
The rules for imports given above have the consequence that a library
6464
would have to migrate in lockstep with all its users from old style implicits and
65-
normal imports to given definitions and imports.
65+
normal imports to given instances and imports.
6666

6767
The following modifications avoid this hurdle to migration.
6868

tests/neg/i5978.scala

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

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

10-
delegate FromCharToken for Conversion[Char, Position[CharSequence]]
11-
given (T: TokenParser[Char, Position[CharSequence]]) = ???
10+
given FromCharToken as Conversion[Char, Position[CharSequence]]
11+
given (T: TokenParser[Char, Position[CharSequence]]) = ???
1212
}
1313

1414

@@ -22,7 +22,7 @@ object Testcase {
2222
val co_x : Position[CharSequence] = 'x' // error
2323

2424
{
25-
delegate XXX for 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
}

tests/pos/i5978.scala

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ trait TokenParser[Token, R]
77
package p1 {
88

99
object TextParser {
10-
delegate TP for TokenParser[Char, Position[CharSequence]] {}
10+
given TP as TokenParser[Char, Position[CharSequence]] {}
1111

12-
delegate FromCharToken for Conversion[Char, Position[CharSequence]]
13-
given (T: TokenParser[Char, Position[CharSequence]])= ???
12+
given FromCharToken as Conversion[Char, Position[CharSequence]]
13+
given (T: TokenParser[Char, Position[CharSequence]]) = ???
1414
}
1515

16-
1716
object Testcase {
1817
def main(args: Array[String]): Unit = {
19-
import delegate TextParser._
18+
import given TextParser._
2019
import TextParser._
2120

2221
val tp_v: TokenParser[Char, Position[CharSequence]] = TextParser.TP
@@ -25,7 +24,7 @@ package p1 {
2524
val co_x : Position[CharSequence] = 'x'
2625

2726
{
28-
delegate XXX for Conversion[Char, Position[CharSequence]] = co_i
27+
given XXX as Conversion[Char, Position[CharSequence]] = co_i
2928
val co_y : Position[CharSequence] = 'x'
3029
}
3130
}
@@ -42,7 +41,7 @@ package p2 {
4241
object Testcase {
4342
def main(args: Array[String]): Unit = {
4443
import TextParser._
45-
import delegate TextParser._
44+
import given TextParser._
4645

4746
val tp_v: TokenParser[Char, Position[CharSequence]] = TextParser.TP
4847
val tp_i = the[TokenParser[Char, Position[CharSequence]]]
@@ -60,19 +59,19 @@ package p3 {
6059

6160
object Testcase {
6261
def main(args: Array[String]): Unit = {
63-
import delegate TextParser._
62+
import given TextParser._
6463
import TextParser._
6564

6665
val co_i: Conversion[Char, Position[CharSequence]] = the[Conversion[Char, Position[CharSequence]]]
6766

6867
{
6968
val tp_v: TokenParser[Char, Position[CharSequence]] = TextParser.TP
7069
val tp_i = the[TokenParser[Char, Position[CharSequence]]]
71-
delegate for Conversion[Char, Position[CharSequence]] = co_i
70+
given as Conversion[Char, Position[CharSequence]] = co_i
7271
val co_x : Position[CharSequence] = 'x'
7372

7473
{
75-
delegate XXX for Conversion[Char, Position[CharSequence]] = co_i
74+
given XXX as Conversion[Char, Position[CharSequence]] = co_i
7675
val co_y : Position[CharSequence] = 'x'
7776
}
7877
}

0 commit comments

Comments
 (0)