Skip to content

Commit abca391

Browse files
committed
Tweak position where synthetic evidence parameters are added
Make sure that any references to a synthetic evidence parameter come after that parameter is introduced.
1 parent aba63cd commit abca391

File tree

8 files changed

+61
-31
lines changed

8 files changed

+61
-31
lines changed

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -407,21 +407,38 @@ object desugar {
407407
(Nil, tree)
408408

409409
/** Add all evidence parameters in `params` as implicit parameters to `meth`.
410-
* If the parameters of `meth` end in an implicit parameter list or using clause,
411-
* evidence parameters are added in front of that list. Otherwise they are added
412-
* as a separate parameter clause.
410+
* The position of the added parameters is determined as follows:
411+
*
412+
* - If there is an existing parameter list that refers to one of the added
413+
* parameters in one of its parameter types, add the new parameters
414+
* in front of the first such parameter list.
415+
* - Otherwise, if the last parameter list consists implicit or using parameters,
416+
* join the new parameters in front of this parameter list, creating one
417+
* parameter list (this is equilavent to Scala 2's scheme).
418+
* - Otherwise, add the new parameter list at the end as a separate parameter clause.
413419
*/
414420
private def addEvidenceParams(meth: DefDef, params: List[ValDef])(using Context): DefDef =
415-
params match
421+
if params.isEmpty then return meth
422+
423+
val boundNames = params.map(_.name).toSet
424+
425+
def references(vdef: ValDef): Boolean =
426+
vdef.tpt.existsSubTree:
427+
case Ident(name: TermName) => boundNames.contains(name)
428+
case _ => false
429+
430+
def recur(mparamss: List[ParamClause]): List[ParamClause] = mparamss match
431+
case ValDefs(mparams) :: _ if mparams.exists(references) =>
432+
params :: mparamss
433+
case ValDefs(mparams @ (mparam :: _)) :: Nil if mparam.mods.isOneOf(GivenOrImplicit) =>
434+
(params ++ mparams) :: Nil
435+
case mparams :: mparamss1 =>
436+
mparams :: recur(mparamss1)
416437
case Nil =>
417-
meth
418-
case evidenceParams =>
419-
val paramss1 = meth.paramss.reverse match
420-
case ValDefs(vparams @ (vparam :: _)) :: rparamss if vparam.mods.isOneOf(GivenOrImplicit) =>
421-
((evidenceParams ++ vparams) :: rparamss).reverse
422-
case _ =>
423-
meth.paramss :+ evidenceParams
424-
cpy.DefDef(meth)(paramss = paramss1)
438+
params :: Nil
439+
440+
cpy.DefDef(meth)(paramss = recur(meth.paramss))
441+
end addEvidenceParams
425442

426443
/** The parameters generated from the contextual bounds of `meth`, as generated by `desugar.defDef` */
427444
private def evidenceParams(meth: DefDef)(using Context): List[ValDef] =

tests/pos/dep-context-bounds.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//> using options -language:experimental.modularity -source future
2+
trait A:
3+
type Self
4+
5+
object Test1:
6+
def foo[X: A](x: X.Self) = ???
7+
8+
def bar[X: A](a: Int) = ???
9+
10+
def baz[X: A](a: Int)(using String) = ???
11+
12+
object Test2:
13+
def foo[X: A as x](a: x.Self) = ???
14+
15+
def bar[X: A as x](a: Int) = ???
16+
17+
def baz[X: A as x](a: Int)(using String) = ???

tests/pos/hylolib/AnyCollection.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class AnyCollection[Element] private (
1414
object AnyCollection {
1515

1616
/** Creates an instance forwarding its operations to `base`. */
17-
def apply[Base](using b: Collection[Base])(base: Base): AnyCollection[b.Element] =
17+
def apply[Base: Collection as b](base: Base): AnyCollection[b.Element] =
1818
// NOTE: This evidence is redefined so the compiler won't report ambiguity between `intIsValue`
1919
// and `anyValueIsValue` when the method is called on a collection of `Int`s. None of these
2020
// choices is even correct! Note also that the ambiguity is suppressed if the constructor of
@@ -42,7 +42,7 @@ object AnyCollection {
4242

4343
}
4444

45-
given anyCollectionIsCollection[T](using tIsValue: Value[T]): Collection[AnyCollection[T]] with {
45+
given anyCollectionIsCollection[T: Value]: Collection[AnyCollection[T]] with {
4646

4747
type Element = T
4848
type Position = AnyValue

tests/pos/hylolib/AnyValue.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ final class AnyValue private (
4444
object AnyValue {
4545

4646
/** Creates an instance wrapping `wrapped`. */
47-
def apply[T](using Value[T])(wrapped: T): AnyValue =
47+
def apply[T: Value](wrapped: T): AnyValue =
4848
def copy(a: AnyRef): AnyValue =
4949
AnyValue(a.asInstanceOf[Ref[T]].value.copy())
5050

tests/pos/hylolib/Collection.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ trait Collection[Self] {
8989

9090
}
9191

92-
extension [Self](self: Self)(using s: Collection[Self]) {
92+
extension [Self: Collection as s](self: Self) {
9393

9494
/** Returns the first element of `self` along with a slice containing the suffix after this
9595
* element, or `None` if `self` is empty.
@@ -148,7 +148,7 @@ extension [Self](self: Self)(using s: Collection[Self]) {
148148
* @complexity
149149
* O(n) where n is the number of elements in `self`.
150150
*/
151-
def map[T](using Value[T])(transform: (s.Element) => T): HyArray[T] =
151+
def map[T: Value](transform: (s.Element) => T): HyArray[T] =
152152
self.reduce(
153153
HyArray[T](),
154154
(r, e) => r.append(transform(e), assumeUniqueness = true)
@@ -257,9 +257,8 @@ extension [Self](self: Self)(using s: Collection[Self]) {
257257

258258
}
259259

260-
extension [Self](self: Self)(using
261-
s: Collection[Self],
262-
e: Value[s.Element]
260+
extension [Self: Collection as s](self: Self)(using
261+
Value[s.Element]
263262
) {
264263

265264
/** Returns `true` if `self` contains the same elements as `other`, in the same order. */

tests/pos/hylolib/HyArray.scala

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1+
//> using options -language:experimental.modularity -source future
12
package hylo
23

34
import java.util.Arrays
45
import scala.collection.mutable
56

67
/** An ordered, random-access collection. */
7-
final class HyArray[Element] private (using
8-
elementIsValue: Value[Element]
9-
)(
8+
final class HyArray[Element: Value as elementIsCValue](
109
private var _storage: scala.Array[AnyRef | Null] | Null,
1110
private var _count: Int // NOTE: where do I document private fields
1211
) {
@@ -155,14 +154,14 @@ final class HyArray[Element] private (using
155154
object HyArray {
156155

157156
/** Creates an array with the given `elements`. */
158-
def apply[T](using t: Value[T])(elements: T*): HyArray[T] =
157+
def apply[T: Value](elements: T*): HyArray[T] =
159158
var a = new HyArray[T](null, 0)
160159
for (e <- elements) a = a.append(e, assumeUniqueness = true)
161160
a
162161

163162
}
164163

165-
given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with {
164+
given [T: Value] => Value[HyArray[T]] with {
166165

167166
extension (self: HyArray[T]) {
168167

@@ -179,7 +178,7 @@ given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with {
179178

180179
}
181180

182-
given hyArrayIsCollection[T](using tIsValue: Value[T]): Collection[HyArray[T]] with {
181+
given [T: Value] => Collection[HyArray[T]] with {
183182

184183
type Element = T
185184
type Position = Int

tests/pos/hylolib/Range.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ object Range {
3030
* @requires
3131
* `lowerBound` is lesser than or equal to `upperBound`.
3232
*/
33-
def apply[Bound](lowerBound: Bound, upperBound: Bound)(using Comparable[Bound]) =
33+
def apply[Bound: Comparable](lowerBound: Bound, upperBound: Bound) =
3434
require(lowerBound `le` upperBound)
3535
new Range(lowerBound, upperBound)
3636

tests/pos/hylolib/Slice.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package hylo
22

33
/** A view into a collection. */
4-
final class Slice[Base](using
5-
val b: Collection[Base]
6-
)(
4+
final class Slice[Base: Collection as b](
75
val base: Base,
86
val bounds: Range[b.Position]
97
) {
@@ -26,7 +24,7 @@ final class Slice[Base](using
2624

2725
}
2826

29-
given sliceIsCollection[T](using c: Collection[T]): Collection[Slice[T]] with {
27+
given sliceIsCollection[T: Collection as c]: Collection[Slice[T]] with {
3028

3129
type Element = c.Element
3230
type Position = c.Position

0 commit comments

Comments
 (0)