Skip to content

Commit 3e10366

Browse files
committed
Allow labels naming an augment
1 parent da5f314 commit 3e10366

File tree

8 files changed

+67
-31
lines changed

8 files changed

+67
-31
lines changed

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

+18-13
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ object desugar {
771771
(elimTypeDefs.transform(tree), bindingsBuf.toList)
772772
}
773773

774-
/** augment <type-pattern> <params> extends <parents> { <body>} }
774+
/** augment [<id> @] <type-pattern> <params> extends <parents> { <body>} }
775775
* ->
776776
* implicit class <deconame> <type-params> ($this: <decorated>) <combined-params>
777777
* extends <parents> { <body1> }
@@ -781,7 +781,8 @@ object desugar {
781781
* (<decorated>, <type-params0>) = decomposeTypePattern(<type-pattern>)
782782
* (<type-params>, <evidence-params>) = desugarTypeBindings(<type-params0>)
783783
* <combined-params> = <params> concatenated with <evidence-params> in one clause
784-
* <deconame> = <from>To<parent>_in_<location>$$<n> where <parent> is first extended class name
784+
* <deconame> = <id> if there is a `id @` binding
785+
* = <from>To<parent>_in_<location>$$<n> where <parent> is first extended class name
785786
*
786787
* = <from>Augmentation_in_<location>$$<n> if no such <parent> exists
787788
* <from> = underlying type name of <decorated>
@@ -791,7 +792,7 @@ object desugar {
791792
*
792793
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
793794
*
794-
* augment <type-pattern> <params> { <body> }
795+
* augment [<id> @] <type-pattern> <params> { <body> }
795796
* ->
796797
* implicit class <deconame> <type-params> ($this: <decorated>)
797798
* extends AnyVal { <body2> }
@@ -802,22 +803,26 @@ object desugar {
802803
* <deconame>, <type-params> are as above.
803804
*/
804805
def augmentation(tree: Augment)(implicit ctx: Context): Tree = {
805-
val Augment(augmented, impl) = tree
806+
val Augment(id, augmented, impl) = tree
806807
val isSimpleExtension =
807808
impl.parents.isEmpty &&
808809
impl.self.isEmpty &&
809810
impl.body.forall(_.isInstanceOf[DefDef])
810811
val (decorated, bindings) = decomposeTypePattern(augmented)
811812
val (typeParams, evidenceParams) =
812813
desugarTypeBindings(bindings, forPrimaryConstructor = !isSimpleExtension)
813-
val decoName = {
814-
def clsName(tree: Tree): String = leadingName("", tree)
815-
val fromName = clsName(augmented)
816-
val toName = impl.parents match {
817-
case parent :: _ if !clsName(parent).isEmpty => "To" + clsName(parent)
818-
case _ => str.Augmentation
819-
}
820-
s"${fromName}${toName}_in_${ctx.owner.topLevelClass.flatName}"
814+
val decoName = id match {
815+
case Ident(name) =>
816+
name.asTypeName
817+
case EmptyTree =>
818+
def clsName(tree: Tree): String = leadingName("", tree)
819+
val fromName = clsName(augmented)
820+
val toName = impl.parents match {
821+
case parent :: _ if !clsName(parent).isEmpty => "To" + clsName(parent)
822+
case _ => "Augmentation"
823+
}
824+
val prefix = s"${fromName}${toName}_in_${ctx.owner.topLevelClass.flatName}"
825+
UniqueName.fresh(prefix.toTermName).toTypeName
821826
}
822827

823828
val firstParam = ValDef(nme.SELF, decorated, EmptyTree).withFlags(Private | Local | ParamAccessor)
@@ -842,7 +847,7 @@ object desugar {
842847
constr1 = addEvidenceParams(constr1, evidenceParams)
843848

844849
val icls =
845-
TypeDef(UniqueName.fresh(decoName.toTermName).toTypeName,
850+
TypeDef(decoName,
846851
cpy.Template(impl)(constr = constr1, parents = parents1, body = body1))
847852
.withFlags(Implicit)
848853
desugr.println(i"desugar $augmented --> $icls")

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
4040
def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl)
4141
}
4242

43-
/** augment augmented impl */
44-
case class Augment(augmented: Tree, impl: Template) extends DefTree
43+
/** augment id @ augmented impl */
44+
case class Augment(id: Tree, augmented: Tree, impl: Template) extends DefTree
4545

4646
case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree
4747

@@ -414,9 +414,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
414414
case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree
415415
case _ => finalize(tree, untpd.ModuleDef(name, impl))
416416
}
417-
def Augment(tree: Tree)(augmented: Tree, impl: Template) = tree match {
418-
case tree: Augment if (augmented eq tree.augmented) && (impl eq tree.impl) => tree
419-
case _ => finalize(tree, untpd.Augment(augmented, impl))
417+
def Augment(tree: Tree)(id: Tree, augmented: Tree, impl: Template) = tree match {
418+
case tree: Augment if (id eq tree.id) && (augmented eq tree.augmented) && (impl eq tree.impl) => tree
419+
case _ => finalize(tree, untpd.Augment(id, augmented, impl))
420420
}
421421
def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree) = tree match {
422422
case tree: ParsedTry

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

-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ object StdNames {
4242
final val AbstractFunction = "AbstractFunction"
4343
final val Tuple = "Tuple"
4444
final val Product = "Product"
45-
final val Augmentation = "Augmentation"
4645

4746
def sanitize(str: String) = str.replaceAll("""[<>]""", """\$""")
4847
}

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -2303,13 +2303,18 @@ object Parsers {
23032303
Template(constr, parents, EmptyValDef, Nil)
23042304
}
23052305

2306-
/** Augmentation ::= ‘augment’ BindingTypePattern
2306+
/** Augmentation ::= ‘augment’ [id @] BindingTypePattern
23072307
* [[nl] ImplicitParamClause] Additions
23082308
* BindingTypePattern ::= AnnotType
23092309
* Additions ::= ‘extends’ Template
23102310
* | [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’
23112311
*/
23122312
def augmentation(): Augment = atPos(in.skipToken(), nameStart) {
2313+
var id: Tree = EmptyTree
2314+
if (isIdent && lookaheadIn(AT)) {
2315+
id = typeIdent()
2316+
in.nextToken()
2317+
}
23132318
val augmented = withinTypePattern(binding = true)(annotType())
23142319
val vparamss = paramClauses(tpnme.EMPTY, ofAugmentation = true).take(1)
23152320
val constr = makeConstructor(Nil, vparamss)
@@ -2323,7 +2328,7 @@ object Parsers {
23232328
checkDef(templ.self)
23242329
templ.body.foreach(checkDef)
23252330
}
2326-
Augment(augmented, templ)
2331+
Augment(id, augmented, templ)
23272332
}
23282333

23292334
/* -------- TEMPLATES ------------------------------------------- */

docs/docs/internals/syntax.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ Patterns ::= Pattern {‘,’ Pattern}
247247
ArgumentPatterns ::= ‘(’ [Patterns] ‘)’ Apply(fn, pats)
248248
| ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’
249249
250-
Augmentation ::= ‘augment’ BindingTypePattern
250+
Augmentation ::= ‘augment’ [id ‘@’] BindingTypePattern
251251
[[nl] ImplicitParamClause] AugmentClause Augment(name, templ)
252252
AugmentClause ::= ‘extends’ Template
253253
| [nl] ‘{’ ‘def’ DefDef {semi ‘def’ DefDef} ‘}’

tests/neg/augment.scala

+9-4
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,24 @@ object augments {
7373
this.width == that.width &&
7474
this.height == that.height
7575
}
76+
}
7677

77-
// Generic augments with additional parameters
78+
object augments2 {
79+
import augments.Eql
80+
// Nested generic arguments
7881

79-
augment List[List[type U]] {
82+
augment flatLists @ List[List[type U]] {
8083
def flattened: List[U] = (this :\ (Nil: List[U]))(_ ++ _)
8184
}
8285

83-
augment (type T: Eql, T) {
84-
def isSame = this._1 === this._2
86+
augment samePairs @ (type T: Eql, T) {
87+
def isSame: Boolean = this._1 === this._2 // error: === is not a member
8588
}
89+
8690
}
8791

8892
import augments._
93+
import augments2._
8994
object Test extends App {
9095
val c = Circle(0, 1, 2)
9196
println(c.area)

tests/run/augment.check

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
12.566370614359172
2+
(1,a)
3+
true
4+
false
5+
true
6+
false
7+
true
8+
false
9+
true
10+
false
11+
2
12+
List(1, 2, 3)
13+
3
14+
3
15+
false
16+
true

tests/pos/augment.scala renamed to tests/run/augment.scala

+11-5
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ object augments {
6363
def === (that: T): Boolean
6464
}
6565

66-
augment (type T: Eql) extends HasEql[T] {
66+
augment eqlToHasEql @ (type T: Eql) extends HasEql[T] {
6767
def === (that: T): Boolean = implicitly[Eql[T]].eql(this, that)
6868
}
6969

@@ -79,18 +79,24 @@ object augments {
7979
this.height == that.height
8080
}
8181

82-
// Generic augments with additional parameters
82+
}
83+
84+
object augments2 {
85+
import augments.{Eql, eqlToHasEql}
86+
// Nested generic arguments
8387

84-
augment List[List[type U]] {
88+
augment flatLists @ List[List[type U]] {
8589
def flattened: List[U] = (this :\ (Nil: List[U]))(_ ++ _)
8690
}
8791

88-
augment (type T: Eql, T) {
92+
augment samePairs @ (type T: Eql, T) {
8993
def isSame = this._1 === this._2
9094
}
95+
9196
}
9297

9398
import augments._
99+
import augments2.{flatLists, samePairs}
94100
object Test extends App {
95101
val c = Circle(0, 1, 2)
96102
println(c.area)
@@ -116,5 +122,5 @@ object Test extends App {
116122
println(List(List(1), List(2, 3)).flattened.maxx)
117123
println(Array(1, 2, 3).maxx)
118124
println((2, 3).isSame)
119-
println((3, 3).isSame)
125+
println(samePairs((3, 3)).isSame)
120126
}

0 commit comments

Comments
 (0)