@@ -20,6 +20,7 @@ import ast.tpd.*
20
20
import Synthesizer .*
21
21
import sbt .ExtractDependencies .*
22
22
import xsbti .api .DependencyContext .*
23
+ import dotty .tools .dotc .core .Definitions .MaxTupleArity
23
24
24
25
/** Synthesize terms for special classes */
25
26
class Synthesizer (typer : Typer )(using @ constructorOnly c : Context ):
@@ -105,27 +106,84 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
105
106
val synthesizedTupleFunction : SpecialHandler = (formal, span) =>
106
107
formal match
107
108
case AppliedType (_, funArgs @ fun :: tupled :: Nil ) =>
109
+ def doesFunctionTupleInto (baseFun : Type , actualArgs : List [Type ],
110
+ actualRet : Type , tupled : Type ) =
111
+ tupled.dealias =:= constructDependentTupleType(actualArgs, actualRet, defn.isContextFunctionType(baseFun))
112
+ def doesFunctionUntupleTo (baseFun : Type , actualArgs : List [Type ],
113
+ actualRet : Type , untupled : Type ) =
114
+ untupled.dealias =:= untupleDependentTupleType(actualArgs, actualRet, defn.isContextFunctionType(baseFun))
115
+
108
116
def functionTypeEqual (baseFun : Type , actualArgs : List [Type ],
109
117
actualRet : Type , expected : Type ) =
110
- expected =:= defn.FunctionNOf (actualArgs, actualRet,
111
- defn.isContextFunctionType(baseFun))
118
+ expected.dealias =:= defn.FunctionNOf (actualArgs, actualRet, defn.isContextFunctionType(baseFun))
119
+ def untupleDependentTupleType (args : List [Type ], ret : Type , contextual : Boolean ): Type =
120
+ val methodKind = if contextual then ContextualMethodType else MethodType
121
+
122
+
123
+ val p = methodKind(args.indices.map(nme.syntheticParamName).toList)(
124
+ mt => args,
125
+ mt =>
126
+ val tpeMap = new TypeMap :
127
+ def apply (tp : Type ): Type =
128
+ tp match
129
+ case TermRef (TermParamRef (_, paramNum), name) =>
130
+ name match
131
+ case x : TermName =>
132
+ x.toString match
133
+ // hack upon hack upon hack
134
+ // please make there be a reverse map so i dont have to do this : (
135
+ case s " _ $id" =>
136
+ mt.paramRefs(id.toInt)
137
+ case _ => ???
138
+ case _ => ???
139
+ case _ => mapOver(tp)
140
+ tpeMap(ret)
141
+ )
142
+ p
143
+
144
+ def constructDependentTupleType (args : List [Type ], ret : Type , contextual : Boolean ): Type =
145
+ val methodKind = if contextual then ContextualMethodType else MethodType
146
+
147
+ val p = methodKind(List (nme.syntheticParamName(0 )))(
148
+ mt => List (defn.tupleType(args)),
149
+ mt =>
150
+ val tpeMap = new TypeMap :
151
+ def apply (tp : Type ): Type =
152
+ tp match
153
+ case TermParamRef (binder, paramNum) =>
154
+ mt.paramRefs(0 ).select(nme.selectorName(paramNum))
155
+ case _ =>
156
+ mapOver(tp)
157
+ tpeMap(ret)
158
+ ).toFunctionType()
159
+ p
160
+ val dealiasedFun = fun.dealias
161
+ val dealiasedTupled = tupled.dealias
112
162
val arity : Int =
113
163
if defn.isFunctionNType(fun) then
114
164
// TupledFunction[(...) => R, ?]
115
- fun.functionArgInfos match
116
- case funArgs :+ funRet
117
- if functionTypeEqual(fun, defn.tupleType(funArgs) :: Nil , funRet, tupled) =>
118
- // TupledFunction[(...funArgs...) => funRet, ?]
119
- funArgs.size
120
- case _ => - 1
165
+ // dont use functionArgInfos it dealiases and drops dependents
166
+
167
+ dealiasedFun match
168
+ case defn.RefinedFunctionOf (method : MethodType ) if doesFunctionTupleInto(dealiasedFun, method.paramInfos, method.resType, dealiasedTupled) =>
169
+ method.paramInfos.size
170
+ // poly types are unsupported
171
+ case defn.RefinedFunctionOf (_) => - 1
172
+ case _ =>
173
+ fun.functionArgInfos match
174
+ case funArgs :+ funRet
175
+ if functionTypeEqual(dealiasedFun, defn.tupleType(funArgs) :: Nil , funRet, dealiasedTupled) =>
176
+ // TupledFunction[(...funArgs...) => funRet, ?]
177
+ funArgs.size
178
+ case _ => - 1
121
179
else if defn.isFunctionNType(tupled) then
122
180
// TupledFunction[?, (...) => R]
123
- tupled.functionArgInfos match
181
+ dealiasedTupled.argInfos match
124
182
case tupledArgs :: funRet :: Nil =>
183
+ // TupledFunction[?, ((...)) => R]
125
184
tupledArgs.tupleElementTypes match
126
- case Some (funArgs) if functionTypeEqual(tupled, funArgs, funRet, fun) =>
127
- // TupledFunction[?, ((...funArgs...)) => funRet]
128
- funArgs.size
185
+ case Some (args) if doesFunctionUntupleTo(dealiasedTupled, args, funRet, dealiasedFun) =>
186
+ args.size
129
187
case _ => - 1
130
188
case _ => - 1
131
189
else
0 commit comments