Skip to content

Commit 8505258

Browse files
committed
refactor and add comments
1 parent 350aad4 commit 8505258

File tree

3 files changed

+49
-27
lines changed

3 files changed

+49
-27
lines changed

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

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -902,28 +902,37 @@ object desugar {
902902
defDef(
903903
cpy.DefDef(mdef)(
904904
name = normalizeName(mdef, ext).asTermName,
905-
paramss = mdef.paramss match
906-
case params1 :: paramss1 if mdef.name.isRightAssocOperatorName =>
907-
def badRightAssoc(problem: String) =
908-
report.error(i"right-associative extension method $problem", mdef.srcPos)
909-
ext.paramss ++ mdef.paramss
910-
def noVParam = badRightAssoc("must start with a single parameter")
911-
def checkVparam(pre: List[ParamClause], params: ParamClause, paramss: List[ParamClause]) = params match
912-
case ValDefs(vparam :: Nil) =>
913-
if !vparam.mods.is(Given) then
914-
val (leadingUsing, otherExtParamss) = ext.paramss.span(isUsingOrTypeParamClause)
915-
leadingUsing ::: pre ::: params :: otherExtParamss ::: paramss
916-
else badRightAssoc("cannot start with using clause")
905+
paramss =
906+
if mdef.name.isRightAssocOperatorName then
907+
val (typaramss, paramss) = mdef.paramss.span(isTypeParamClause) // first extract type parameters
908+
909+
paramss match
910+
case params :: paramss1 => // `params` must have a single parameter and without `given` flag
911+
912+
def badRightAssoc(problem: String) =
913+
report.error(i"right-associative extension method $problem", mdef.srcPos)
914+
ext.paramss ++ mdef.paramss
915+
916+
params match
917+
case ValDefs(vparam :: Nil) =>
918+
if !vparam.mods.is(Given) then
919+
// we merge the extension parameters with the method parameters,
920+
// swapping the operator arguments:
921+
// e.g.
922+
// extension [A](using B)(c: C)(using D)
923+
// def %:[E](f: F)(g: G)(using H): Res = ???
924+
// will be encoded as
925+
// def %:[A](using B)[E](f: F)(c: C)(using D)(g: G)(using H): Res = ???
926+
val (leadingUsing, otherExtParamss) = ext.paramss.span(isUsingOrTypeParamClause)
927+
leadingUsing ::: typaramss ::: params :: otherExtParamss ::: paramss1
928+
else
929+
badRightAssoc("cannot start with using clause")
930+
case _ =>
931+
badRightAssoc("must start with a single parameter")
917932
case _ =>
918-
noVParam
919-
params1 match
920-
case TypeDefs(_) => paramss1 match
921-
case params2 :: paramss2 => checkVparam(params1::Nil, params2, paramss2)
922-
case _ => noVParam
923-
case _ =>
924-
checkVparam(Nil, params1, paramss1)
925-
926-
case _ =>
933+
// no value parameters, so not an infix operator.
934+
ext.paramss ++ mdef.paramss
935+
else
927936
ext.paramss ++ mdef.paramss
928937
).withMods(mdef.mods | ExtensionMethod)
929938
)

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -815,16 +815,30 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
815815
if isExtension then
816816
val paramss =
817817
if tree.name.isRightAssocOperatorName then
818-
// we have the encoding: leadingTy leadingUsing rightTyParamss rightParamss leftParamss trailingUsing
818+
// we have the following encoding of tree.paramss:
819+
// (leadingTyParamss ++ leadingUsing
820+
// ++ rightTyParamss ++ rightParamss
821+
// ++ leftParamss ++ trailingUsing ++ rest)
822+
// e.g.
823+
// extension [A](using B)(c: C)(using D)
824+
// def %:[E](f: F)(g: G)(using H): Res = ???
825+
// will have the following values:
826+
// - leadingTyParamss = List(`[A]`)
827+
// - leadingUsing = List(`(using B)`)
828+
// - rightTyParamss = List(`[E]`)
829+
// - rightParamss = List(`(f: F)`)
830+
// - leftParamss = List(`(c: C)`)
831+
// - trailingUsing = List(`(using D)`)
832+
// - rest = List(`(g: G)`, `(using H)`)
819833
// we need to swap (rightTyParams ++ rightParamss) with (leftParamss ++ trailingUsing)
820-
val (leadingTy, rest1) = tree.paramss.span(isTypeParamClause)
834+
val (leadingTyParamss, rest1) = tree.paramss.span(isTypeParamClause)
821835
val (leadingUsing, rest2) = rest1.span(isUsingClause)
822836
val (rightTyParamss, rest3) = rest2.span(isTypeParamClause)
823837
val (rightParamss, rest4) = rest3.splitAt(1)
824838
val (leftParamss, rest5) = rest4.splitAt(1)
825839
val (trailingUsing, rest6) = rest5.span(isUsingClause)
826840
if leftParamss.nonEmpty then
827-
leadingTy ::: leadingUsing ::: leftParamss ::: trailingUsing ::: rightTyParamss ::: rightParamss ::: rest6
841+
leadingTyParamss ::: leadingUsing ::: leftParamss ::: trailingUsing ::: rightTyParamss ::: rightParamss ::: rest6
828842
else
829843
tree.paramss // it wasn't a binary operator, after all.
830844
else

tests/run/i11583.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ class Env:
1515
extension [Ctx <: Context](using ctx: Ctx)(tpe: String)(using env: Env)
1616
def :#:[T <: Boolean](trm: T)(ext: env.Extra): (String, T, env.Extra) = (tpe, trm, ext)
1717

18-
19-
extension (s: String)
20-
def :*:[T <: Tuple](t: T): String *: T = s *: t
18+
extension [A](a: A)
19+
def :*:[T <: Tuple](t: T): A *: T = a *: t
2120

2221
@main def Test =
2322

0 commit comments

Comments
 (0)