Skip to content

Commit 33d7e96

Browse files
committed
Use TupledFunction[F, G] as function tupling instead of application
Also added support for tupled implicit functions ``` TupledFunction[given (Int, Int) => Int, given ((Int, Int)) => Int] ```
1 parent c9e5c2b commit 33d7e96

File tree

8 files changed

+222
-189
lines changed

8 files changed

+222
-189
lines changed

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -711,18 +711,22 @@ trait Implicits { self: Typer =>
711711

712712
def synthesizedTupleFunction(formal: Type): Tree = {
713713
formal match {
714-
case AppliedType(_, fun :: args :: ret :: Nil) if defn.isFunctionType(fun) =>
715-
val funTypes = fun.dropDependentRefinement.dealias.argInfos
716-
if (defn.tupleType(funTypes.init) =:= args && funTypes.last =:= ret) {
714+
case AppliedType(_, funArgs @ fun :: tupled :: Nil) if defn.isFunctionType(fun) && defn.isFunctionType(tupled) =>
715+
lazy val funTypes = fun.dropDependentRefinement.dealias.argInfos
716+
lazy val tupledTypes = tupled.dropDependentRefinement.dealias.argInfos
717+
if (
718+
defn.isImplicitFunctionType(fun) == defn.isImplicitFunctionType(tupled) &&
719+
tupledTypes.size == 2 &&
720+
defn.tupleType(funTypes.init) =:= tupledTypes.head &&
721+
funTypes.last =:= tupledTypes.last
722+
) {
717723
val arity = funTypes.size - 1
718724
if (defn.isErasedFunctionType(fun))
719725
EmptyTree // TODO support?
720-
else if (defn.isImplicitFunctionType(fun))
721-
EmptyTree // TODO support
722726
else if (arity <= Definitions.MaxImplementedFunctionArity)
723-
ref(defn.InternalTupleFunctionModule).select(s"tupledFunction$arity".toTermName).appliedToTypes(funTypes)
727+
ref(defn.InternalTupleFunctionModule).select(s"tupledFunction$arity".toTermName).appliedToTypes(funArgs)
724728
else
725-
ref(defn.InternalTupleFunctionModule).select("tupledFunctionXXL".toTermName).appliedToTypes(fun :: args :: ret :: Nil)
729+
ref(defn.InternalTupleFunctionModule).select("tupledFunctionXXL".toTermName).appliedToTypes(funArgs)
726730
} else EmptyTree
727731
case _ =>
728732
EmptyTree

library/src-3.x/dotty/DottyPredef.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ object DottyPredef {
4545
* @tparam Args the tuple type with the same types as the function arguments of F
4646
* @tparam R the return type of F
4747
*/
48-
def (f: F) tupled[F, Args <: Tuple, R] given (tf: TupledFunction[F, Args, R]): Args => R = {
49-
x => tf.applyFunctionTo(f, x)
50-
}
48+
def (f: F) tupled[F, Args <: Tuple, R] given (tupled: TupledFunction[F, Args => R]): Args => R = tupled(f)
5149

5250
}

library/src-3.x/scala/TupledFunction.scala

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import scala.annotation.implicitNotFound
55
/** Type class relating a `FunctionN[..., R]` with an equvalent tupled function `Function1[TupleN[...], R]`
66
*
77
* @tparam F a function type
8-
* @tparam Args a tuple type with the same types as the function arguments of F
9-
* @tparam R the return type of F
8+
* @tparam G a tupled function type (function of arity 1 receiving a tuple as argument)
109
*/
11-
@implicitNotFound("${F} cannot be tupled as ${Args} => ${R}")
12-
trait TupledFunction[F, Args <: Tuple, R] {
13-
def applyFunctionTo(f: F, args: Args): R
10+
@implicitNotFound("${F} cannot be tupled as ${G}")
11+
trait TupledFunction[F, G] {
12+
def apply(f: F): G
1413
}
1514

1615
/** Module of TupledFunction containing methods for auto function tupling
@@ -37,8 +36,8 @@ object TupledFunction {
3736
* @tparam Args the tuple type with the same types as the function arguments of F
3837
* @tparam R the return type of F
3938
*/
40-
def (f: F) apply[F, Args <: Tuple, R](args: Args) given (tf: TupledFunction[F, Args, R]): R =
41-
tf.applyFunctionTo(f, args)
39+
def (f: F) apply[F, Args <: Tuple, R](args: Args) given (tupled: TupledFunction[F, Args => R]): R =
40+
tupled(f)(args)
4241

4342
/** Composes two instances of TupledFunctions in a new TupledFunctions, with this function applied last
4443
*
@@ -48,7 +47,7 @@ object TupledFunction {
4847
* @tparam GArgs the tuple type with the same types as the function arguments of G
4948
* @tparam R the return type of F
5049
*/
51-
def (f: F) compose[F, G, FArgs <: Tuple, GArgs <: Tuple, R](g: G) given TupledFunction[G, GArgs, FArgs], TupledFunction[F, FArgs, R]: GArgs => R = {
50+
def (f: F) compose[F, G, FArgs <: Tuple, GArgs <: Tuple, R](g: G) given TupledFunction[G, GArgs => FArgs], TupledFunction[F, FArgs => R]: GArgs => R = {
5251
x => f(g(x))
5352
}
5453

@@ -60,7 +59,7 @@ object TupledFunction {
6059
* @tparam GArgs the tuple type with the same types as the function arguments of G and return type of F
6160
* @tparam R the return type of G
6261
*/
63-
def (f: F) andThen[F, G, FArgs <: Tuple, GArgs <: Tuple, R](g: G) given TupledFunction[F, FArgs, GArgs], TupledFunction[G, GArgs, R]: FArgs => R = {
62+
def (f: F) andThen[F, G, FArgs <: Tuple, GArgs <: Tuple, R](g: G) given TupledFunction[F, FArgs => GArgs], TupledFunction[G, GArgs => R]: FArgs => R = {
6463
x => g(f(x))
6564
}
6665

0 commit comments

Comments
 (0)