Skip to content

Commit 7eed544

Browse files
committed
Accept using in rightAssocParams
1 parent 0133141 commit 7eed544

File tree

4 files changed

+33
-38
lines changed

4 files changed

+33
-38
lines changed

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

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,37 +1193,37 @@ object desugar {
11931193
val (rightTyParams, paramss) = mdef.paramss.span(isTypeParamClause) // first extract type parameters
11941194

11951195
paramss match
1196-
case rightParam :: paramss1 => // `rightParam` must have a single parameter and without `given` flag
1197-
rightParam match
1198-
case ValDefs(vparam :: Nil) =>
1199-
if !vparam.mods.is(Given) then
1200-
// we merge the extension parameters with the method parameters,
1201-
// swapping the operator arguments:
1202-
// e.g.
1203-
// extension [A](using B)(c: C)(using D)
1204-
// def %:[E](f: F)(g: G)(using H): Res = ???
1205-
// will be encoded as
1206-
// def %:[A](using B)[E](f: F)(c: C)(using D)(g: G)(using H): Res = ???
1207-
//
1208-
// If you change the names of the clauses below, also change them in right-associative-extension-methods.md
1209-
val (leftTyParamsAndLeadingUsing, leftParamAndTrailingUsing) = extParamss.span(isUsingOrTypeParamClause)
1210-
1211-
val names = (for ps <- mdef.paramss; p <- ps yield p.name).toSet[Name]
1212-
1213-
val tt = new untpd.UntypedTreeTraverser:
1214-
def traverse(tree: Tree)(using Context): Unit = tree match
1215-
case tree: Ident if names.contains(tree.name) =>
1216-
finish(s"cannot have a forward reference to ${tree.name}", tree.srcPos)
1217-
case _ => traverseChildren(tree)
1196+
case (rightParam @ ValDefs(vparam :: Nil)) :: paramss if !vparam.mods.is(Given) =>
1197+
// must be a single parameter without `given` flag for rassoc rewrite
1198+
// we merge the extension parameters with the method parameters,
1199+
// swapping the operator arguments:
1200+
// e.g.
1201+
// extension [A](using B)(c: C)(using D)
1202+
// def %:[E](f: F)(g: G)(using H): Res = ???
1203+
// will be encoded as
1204+
// def %:[A](using B)[E](f: F)(c: C)(using D)(g: G)(using H): Res = ???
1205+
//
1206+
// If you change the names in the clauses below, also change them in right-associative-extension-methods.md
1207+
val (leftTyParamsAndLeadingUsing, leftParamAndTrailingUsing) = extParamss.span(isUsingOrTypeParamClause)
1208+
1209+
val names = (for ps <- mdef.paramss; p <- ps yield p.name).toSet[Name]
1210+
1211+
val tt = new untpd.UntypedTreeTraverser:
1212+
def traverse(tree: Tree)(using Context): Unit = tree match
1213+
case tree: Ident if names.contains(tree.name) =>
1214+
finish(s"cannot have a forward reference to ${tree.name}", tree.srcPos)
1215+
case _ => traverseChildren(tree)
12181216

1219-
for ts <- leftParamAndTrailingUsing; t <- ts do
1220-
tt.traverse(t)
1217+
for ts <- leftParamAndTrailingUsing; t <- ts do
1218+
tt.traverse(t)
12211219

1222-
leftTyParamsAndLeadingUsing ::: rightTyParams ::: rightParam :: leftParamAndTrailingUsing ::: paramss1
1223-
else
1224-
finish("cannot start with using clause", mdef.srcPos)
1225-
case _ =>
1226-
finish("must start with a single parameter", mdef.srcPos)
1220+
leftTyParamsAndLeadingUsing ::: rightTyParams ::: rightParam :: leftParamAndTrailingUsing ::: paramss
1221+
case ValDefs(vparam :: _) :: _ =>
1222+
if vparam.mods.is(Given) then
1223+
// no explicit value parameters, so not an infix operator.
1224+
finish()
1225+
else
1226+
finish("must start with a single parameter, consider a tupled parameter instead", mdef.srcPos)
12271227
case _ =>
12281228
// no value parameters, so not an infix operator.
12291229
finish()

tests/neg/i24745.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extension (s: String)
2-
def f_::(using DummyImplicit): String = s.reverse // error
2+
def f_::(using DummyImplicit): String = s.reverse
33
def g_::(x: (suffix: String, n: Int)): String = s"$s${x.suffix * x.n}"
4-
def ok_::(using suffix: String, n: Int): String = s"$s${suffix * n}" // error
4+
def ok_::(using suffix: String, n: Int): String = s"$s${suffix * n}"
55
def no_::(suffix: String, n: Int): String = s"$s${suffix * n}" // error
66

77
@main def Test =
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
-- Error: tests/neg/rightassoc-extmethod.scala:1:23 --------------------------------------------------------------------
2-
1 |extension (x: Int) def +: (using String): Int = x // error
3-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4-
| right-associative extension method cannot start with using clause
51
-- Error: tests/neg/rightassoc-extmethod.scala:2:23 --------------------------------------------------------------------
62
2 |extension (x: Int) def *: (y: Int, z: Int) = x // error
73
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
8-
| right-associative extension method must start with a single parameter
4+
| right-associative extension method must start with a single parameter, consider a tupled parameter instead
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
extension (x: Int) def +: (using String): Int = x // error
1+
extension (x: Int) def +: (using String): Int = x
22
extension (x: Int) def *: (y: Int, z: Int) = x // error
3-

0 commit comments

Comments
 (0)