Skip to content

Commit 0133141

Browse files
committed
Refactor extMethod
1 parent 707f0c9 commit 0133141

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

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

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Decorators.*
99
import Annotations.Annotation
1010
import NameKinds.{UniqueName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
1111
import typer.{Namer, Checking}
12-
import util.{Property, SourceFile, SourcePosition, SrcPos, Chars}
12+
import util.{Chars, NoSourcePosition, Property, SourceFile, SourcePosition, SrcPos}
1313
import config.{Feature, Config}
1414
import config.Feature.{sourceVersion, migrateTo3, enabled}
1515
import config.SourceVersion.*
@@ -1185,55 +1185,59 @@ object desugar {
11851185
}
11861186

11871187
def extMethod(mdef: DefDef, extParamss: List[ParamClause])(using Context): DefDef =
1188+
def finish(problem: String = "", pos: SrcPos = NoSourcePosition) =
1189+
if !problem.isEmpty then
1190+
report.error(em"right-associative extension method $problem", pos)
1191+
extParamss ++ mdef.paramss
1192+
def rightAssocParams =
1193+
val (rightTyParams, paramss) = mdef.paramss.span(isTypeParamClause) // first extract type parameters
1194+
1195+
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)
1218+
1219+
for ts <- leftParamAndTrailingUsing; t <- ts do
1220+
tt.traverse(t)
1221+
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)
1227+
case _ =>
1228+
// no value parameters, so not an infix operator.
1229+
finish()
1230+
end rightAssocParams
1231+
11881232
cpy.DefDef(mdef)(
11891233
name = normalizeName(mdef, mdef.tpt).asTermName,
11901234
paramss =
11911235
if mdef.name.isRightAssocOperatorName then
1192-
val (rightTyParams, paramss) = mdef.paramss.span(isTypeParamClause) // first extract type parameters
1193-
1194-
paramss match
1195-
case rightParam :: paramss1 => // `rightParam` must have a single parameter and without `given` flag
1196-
1197-
def badRightAssoc(problem: String, pos: SrcPos) =
1198-
report.error(em"right-associative extension method $problem", pos)
1199-
extParamss ++ mdef.paramss
1200-
1201-
rightParam match
1202-
case ValDefs(vparam :: Nil) =>
1203-
if !vparam.mods.is(Given) then
1204-
// we merge the extension parameters with the method parameters,
1205-
// swapping the operator arguments:
1206-
// e.g.
1207-
// extension [A](using B)(c: C)(using D)
1208-
// def %:[E](f: F)(g: G)(using H): Res = ???
1209-
// will be encoded as
1210-
// def %:[A](using B)[E](f: F)(c: C)(using D)(g: G)(using H): Res = ???
1211-
//
1212-
// If you change the names of the clauses below, also change them in right-associative-extension-methods.md
1213-
val (leftTyParamsAndLeadingUsing, leftParamAndTrailingUsing) = extParamss.span(isUsingOrTypeParamClause)
1214-
1215-
val names = (for ps <- mdef.paramss; p <- ps yield p.name).toSet[Name]
1216-
1217-
val tt = new untpd.UntypedTreeTraverser:
1218-
def traverse(tree: Tree)(using Context): Unit = tree match
1219-
case tree: Ident if names.contains(tree.name) =>
1220-
badRightAssoc(s"cannot have a forward reference to ${tree.name}", tree.srcPos)
1221-
case _ => traverseChildren(tree)
1222-
1223-
for ts <- leftParamAndTrailingUsing; t <- ts do
1224-
tt.traverse(t)
1225-
1226-
leftTyParamsAndLeadingUsing ::: rightTyParams ::: rightParam :: leftParamAndTrailingUsing ::: paramss1
1227-
else
1228-
badRightAssoc("cannot start with using clause", mdef.srcPos)
1229-
case _ =>
1230-
badRightAssoc("must start with a single parameter", mdef.srcPos)
1231-
case _ =>
1232-
// no value parameters, so not an infix operator.
1233-
extParamss ++ mdef.paramss
1236+
rightAssocParams
12341237
else
1235-
extParamss ++ mdef.paramss
1238+
finish()
12361239
).withMods(mdef.mods | ExtensionMethod)
1240+
end extMethod
12371241

12381242
/** Transform extension construct to list of extension methods */
12391243
def extMethods(ext: ExtMethods)(using Context): Tree = flatTree {

0 commit comments

Comments
 (0)