@@ -9,7 +9,7 @@ import Decorators.*
99import Annotations .Annotation
1010import NameKinds .{UniqueName , ContextBoundParamName , ContextFunctionParamName , DefaultGetterName , WildcardParamName }
1111import typer .{Namer , Checking }
12- import util .{Property , SourceFile , SourcePosition , SrcPos , Chars }
12+ import util .{Chars , NoSourcePosition , Property , SourceFile , SourcePosition , SrcPos }
1313import config .{Feature , Config }
1414import config .Feature .{sourceVersion , migrateTo3 , enabled }
1515import 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