Skip to content

Commit 12d3147

Browse files
authored
Merge pull request #6486 from dotty-staging/given-last
Move Given Last in Instance Definitions
2 parents 3a846cd + 944c08b commit 12d3147

File tree

15 files changed

+63
-45
lines changed

15 files changed

+63
-45
lines changed

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,21 @@ object NavigateAST {
7070
*/
7171
def pathTo(span: Span, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = {
7272
def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = {
73+
var bestFit: List[Positioned] = path
7374
while (it.hasNext) {
7475
val path1 = it.next() match {
7576
case p: Positioned => singlePath(p, path)
7677
case m: untpd.Modifiers => childPath(m.productIterator, path)
7778
case xs: List[_] => childPath(xs.iterator, path)
7879
case _ => path
7980
}
80-
if (path1 ne path) return path1
81+
if ((path1 ne path) &&
82+
((bestFit eq path) ||
83+
bestFit.head.span != path1.head.span &&
84+
bestFit.head.span.contains(path1.head.span)))
85+
bestFit = path1
8186
}
82-
path
87+
bestFit
8388
}
8489
def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] =
8590
if (p.span.exists && !(skipZeroExtent && p.span.isZeroExtent) && p.span.contains(span)) {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro
147147
}
148148
}
149149

150+
/** A hook that can be overridden if overlap checking in `checkPos` should be
151+
* disabled for this node.
152+
*/
153+
def disableOverlapChecks = false
154+
150155
/** Check that all positioned items in this tree satisfy the following conditions:
151156
* - Parent spans contain child spans
152157
* - If item is a non-empty tree, it has a position
@@ -169,7 +174,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro
169174
s"position error: position not set for $tree # ${tree.uniqueId}")
170175
case _ =>
171176
}
172-
if (nonOverlapping) {
177+
if (nonOverlapping && !disableOverlapChecks) {
173178
this match {
174179
case _: XMLBlock =>
175180
// FIXME: Trees generated by the XML parser do not satisfy `checkPos`

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,10 @@ object Trees {
747747
assert(tpt != genericEmptyTree)
748748
def unforced: LazyTree = preRhs
749749
protected def force(x: AnyRef): Unit = preRhs = x
750+
751+
override def disableOverlapChecks = rawMods.is(Flags.Implied)
752+
// disable order checks for implicit aliases since their given clause follows
753+
// their for clause, but the two appear swapped in the DefDef.
750754
}
751755

752756
class BackquotedDefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]],
@@ -784,6 +788,10 @@ object Trees {
784788

785789
def parents: List[Tree[T]] = parentsOrDerived // overridden by DerivingTemplate
786790
def derived: List[untpd.Tree] = Nil // overridden by DerivingTemplate
791+
792+
override def disableOverlapChecks = true
793+
// disable overlaps checks since templates of instance definitions have their
794+
// `given` clause come last, which means that the constructor span can contain the parent spans.
787795
}
788796

789797

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,22 +2688,22 @@ object Parsers {
26882688
Template(constr, parents, Nil, EmptyValDef, Nil)
26892689
}
26902690

2691-
/** InstanceDef ::= [id] InstanceParams InstanceBody
2691+
/** InstanceDef ::= [id] [DefTypeParamClause] InstanceBody
26922692
* InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
2693-
* InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
2694-
* | ‘for’ Type ‘=’ Expr
2693+
* InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
2694+
* | ‘for’ Type {GivenParamClause} ‘=’ Expr
26952695
*/
26962696
def instanceDef(start: Offset, mods: Modifiers, instanceMod: Mod) = atSpan(start, nameStart) {
26972697
var mods1 = addMod(mods, instanceMod)
26982698
val name = if (isIdent) ident() else EmptyTermName
26992699
val tparams = typeParamClauseOpt(ParamOwner.Def)
2700-
val vparamss = paramClauses(ofInstance = true)
27012700
val parents =
27022701
if (in.token == FOR) {
27032702
in.nextToken()
27042703
tokenSeparated(COMMA, constrApp)
27052704
}
27062705
else Nil
2706+
val vparamss = paramClauses(ofInstance = true)
27072707
val instDef =
27082708
if (in.token == EQUALS && parents.length == 1 && parents.head.isType) {
27092709
in.nextToken()

docs/docs/internals/syntax.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,10 @@ ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses
378378
ConstrMods ::= {Annotation} [AccessModifier]
379379
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
380380
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
381-
InstanceDef ::= [id] InstanceParams InstanceBody
381+
InstanceDef ::= [id] [DefTypeParamClause] InstanceBody
382382
InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
383-
InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
384-
| ‘for’ Type ‘=’ Expr
383+
InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
384+
| ‘for’ Type {GivenParamClause} ‘=’ Expr
385385
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
386386
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
387387
ConstrApps ::= ConstrApp {‘with’ ConstrApp}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ An implicit instance without type parameters or given clause is created on-deman
7171
Here is the new syntax of implicit instances, seen as a delta from the [standard context free syntax of Scala 3](http://dotty.epfl.ch/docs/internals/syntax.html).
7272
```
7373
TmplDef ::= ...
74-
| ‘implicit’ InstanceDef
74+
| ‘implicit’ InstanceDef
7575
InstanceDef ::= [id] [DefTypeParamClause] InstanceBody
76-
InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
77-
| ‘of’ Type {GivenParamClause} ‘=’ Expr
76+
InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
77+
| ‘for’ Type {GivenParamClause} ‘=’ Expr
7878
ConstrApp ::= AnnotType {ArgumentExprs}
7979
| ‘(’ ConstrApp {‘given’ (InfixExpr | ParArgumentExprs)} ‘)’
8080
GivenParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | GivenTypes)

tests/neg/i5978.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ trait TokenParser[Token, R]
77
object TextParser {
88
implied TP for TokenParser[Char, Position[CharSequence]] {}
99

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

1414

tests/pos/i5978.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ package p1 {
99
object TextParser {
1010
implied TP for TokenParser[Char, Position[CharSequence]] {}
1111

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

1616

tests/pos/multiversal.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
object Test {
22
import scala.Eql
33

4-
implied [X, Y] given Eql[X, Y] for Eql[List[X], List[Y]] = Eql.derived
4+
implied [X, Y] for Eql[List[X], List[Y]] given Eql[X, Y] = Eql.derived
55

66
val b: Byte = 1
77
val c: Char = 2

tests/pos/reference/instances.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ object Instances extends Common {
3737
if (x < y) -1 else if (x > y) +1 else 0
3838
}
3939

40-
implied ListOrd[T] given Ord[T] for Ord[List[T]] {
40+
implied ListOrd[T] for Ord[List[T]] given Ord[T] {
4141
def (xs: List[T]) compareTo (ys: List[T]): Int = (xs, ys) match {
4242
case (Nil, Nil) => 0
4343
case (Nil, _) => -1
@@ -132,7 +132,7 @@ object Instances extends Common {
132132
println(the[D[Int]])
133133
}
134134
locally {
135-
implied given Context for D[Int]
135+
implied for D[Int] given Context
136136
println(the[D[Int]])
137137
}
138138
}
@@ -195,7 +195,7 @@ object AnonymousInstances extends Common {
195195
def (xs: List[T]) second[T] = xs.tail.head
196196
}
197197

198-
implied [From, To] given (c: Convertible[From, To]) for Convertible[List[From], List[To]] {
198+
implied [From, To] for Convertible[List[From], List[To]] given (c: Convertible[From, To]) {
199199
def (x: List[From]) convert: List[To] = x.map(c.convert)
200200
}
201201

tests/run/implicit-specifity.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object Show {
99
class Generic
1010
object Generic {
1111
implied gen for Generic = new Generic
12-
implied showGen[T] given Generic for Show[T] = new Show[T](2)
12+
implied showGen[T] for Show[T] given Generic = new Show[T](2)
1313
}
1414

1515
class Generic2
@@ -25,9 +25,9 @@ object SubGen {
2525
object Contextual {
2626
trait Context
2727
implied ctx for Context
28-
implied showGen[T] given Generic for Show[T] = new Show[T](2)
29-
implied showGen[T] given Generic, Context for Show[T] = new Show[T](3)
30-
implied showGen[T] given SubGen for Show[T] = new Show[T](4)
28+
implied showGen[T] for Show[T] given Generic = new Show[T](2)
29+
implied showGen[T] for Show[T] given Generic, Context = new Show[T](3)
30+
implied showGen[T] for Show[T] given SubGen = new Show[T](4)
3131
}
3232

3333
object Test extends App {

tests/run/implied-divergence.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ implied e for E(null)
66

77
object Test extends App {
88

9-
implied f given (e: E) for E(e)
9+
implied f for E(e) given (e: E)
1010

1111
assert(the[E].toString == "E(E(null))")
1212

tests/run/implied-priority.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class LowPriorityImplicits {
1515
}
1616

1717
object NormalImplicits extends LowPriorityImplicits {
18-
implied t2[T] given Arg[T] for E[T]("norm")
18+
implied t2[T]for E[T]("norm") given Arg[T]
1919
}
2020

2121
def test1 = {
@@ -38,8 +38,8 @@ object Priority {
3838
}
3939

4040
object Impl2 {
41-
implied t1[T] given Priority.Low for E[T]("low")
42-
implied t2[T] given Priority.High given Arg[T] for E[T]("norm")
41+
implied t1[T] for E[T]("low") given Priority.Low
42+
implied t2[T] for E[T]("norm") given Priority.High given Arg[T]
4343
}
4444

4545
def test2 = {
@@ -102,7 +102,7 @@ def test3 = {
102102
*/
103103
object Impl4 {
104104
implied t1 for E[String]("string")
105-
implied t2[T] given Arg[T] for E[T]("generic")
105+
implied t2[T] for E[T]("generic") given Arg[T]
106106
}
107107

108108
object fallback4 {
@@ -133,7 +133,7 @@ object HigherPriority {
133133
}
134134

135135
object fallback5 {
136-
implied [T] given (ev: E[T] = new E[T]("fallback")) for (E[T] & HigherPriority) = HigherPriority.inject(ev)
136+
implied [T] for (E[T] & HigherPriority) given (ev: E[T] = new E[T]("fallback")) = HigherPriority.inject(ev)
137137
}
138138

139139
def test5 = {

tests/run/implied-specifity-2.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,36 @@ class Foo[T](val i: Int)
1515
object Foo {
1616
def apply[T] given (fooT: Foo[T]): Int = fooT.i
1717

18-
implied foo[T] given Low for Foo[T](0)
19-
implied foobar[T] given Low for Foo[Bar[T]](1)
20-
implied foobarbaz given Low for Foo[Bar[Baz]](2)
18+
implied foo[T] for Foo[T](0) given Low
19+
implied foobar[T] for Foo[Bar[T]](1) given Low
20+
implied foobarbaz for Foo[Bar[Baz]](2) given Low
2121
}
2222
class Bar[T]
2323
object Bar {
24-
implied foobar[T] given Medium for Foo[Bar[T]](3)
25-
implied foobarbaz given Medium for Foo[Bar[Baz]](4)
24+
implied foobar[T] for Foo[Bar[T]](3) given Medium
25+
implied foobarbaz for Foo[Bar[Baz]](4) given Medium
2626
}
2727
class Baz
2828
object Baz {
29-
implied baz given High for Foo[Bar[Baz]](5)
29+
implied baz for Foo[Bar[Baz]](5) given High
3030
}
3131

3232
class Arg
3333
implied for Arg
3434

3535
class Bam(val str: String)
36-
implied lo given Low for Bam("lo")
37-
implied hi given High given Arg for Bam("hi")
36+
implied lo for Bam("lo") given Low
37+
implied hi for Bam("hi") given High given Arg
3838

3939
class Bam2(val str: String)
40-
implied lo2 given Low for Bam2("lo")
41-
implied mid2 given High given Arg for Bam2("mid")
40+
implied lo2 for Bam2("lo") given Low
41+
implied mid2 for Bam2("mid") given High given Arg
4242
implied hi2 for Bam2("hi")
4343

4444
class Arg2
4545
class Red(val str: String)
46-
implied normal given Arg2 for Red("normal")
47-
implied reduced given (ev: Arg2 | Low) for Red("reduced")
46+
implied normal for Red("normal") given Arg2
47+
implied reduced for Red("reduced") given (ev: Arg2 | Low)
4848

4949
object Test extends App {
5050
assert(Foo[Int] == 0)

tests/run/tagless.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ object Test extends App {
196196
// Added operation: negation pushdown
197197
enum NCtx { case Pos, Neg }
198198

199-
implied [T] given (e: Exp[T]) for Exp[NCtx => T] {
199+
implied [T] for Exp[NCtx => T] given (e: Exp[T]) {
200200
import NCtx._
201201
def lit(i: Int) = {
202202
case Pos => e.lit(i)
@@ -216,7 +216,7 @@ object Test extends App {
216216
println(pushNeg(tf1[NCtx => String]))
217217
println(pushNeg(pushNeg(pushNeg(tf1))): String)
218218

219-
implied [T] given (e: Mult[T]) for Mult[NCtx => T] {
219+
implied [T] for Mult[NCtx => T] given (e: Mult[T]) {
220220
import NCtx._
221221
def mul(l: NCtx => T, r: NCtx => T): NCtx => T = {
222222
case Pos => e.mul(l(Pos), r(Pos))

0 commit comments

Comments
 (0)