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

0 commit comments

Comments
 (0)