@@ -20,6 +20,7 @@ import ast.tpd.*
2020import Synthesizer .*
2121import sbt .ExtractDependencies .*
2222import xsbti .api .DependencyContext .*
23+ import dotty .tools .dotc .core .Definitions .MaxTupleArity
2324
2425/** Synthesize terms for special classes */
2526class Synthesizer (typer : Typer )(using @ constructorOnly c : Context ):
@@ -105,27 +106,84 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
105106 val synthesizedTupleFunction : SpecialHandler = (formal, span) =>
106107 formal match
107108 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+
108116 def functionTypeEqual (baseFun : Type , actualArgs : List [Type ],
109117 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
112162 val arity : Int =
113163 if defn.isFunctionNType(fun) then
114164 // 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
121179 else if defn.isFunctionNType(tupled) then
122180 // TupledFunction[?, (...) => R]
123- tupled.functionArgInfos match
181+ dealiasedTupled.argInfos match
124182 case tupledArgs :: funRet :: Nil =>
183+ // TupledFunction[?, ((...)) => R]
125184 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
129187 case _ => - 1
130188 case _ => - 1
131189 else
0 commit comments