Skip to content

Commit 24e43b9

Browse files
try to fix i21808 (doesnt work)
1 parent 73b935c commit 24e43b9

File tree

6 files changed

+108
-12
lines changed

6 files changed

+108
-12
lines changed

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

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import ast.tpd.*
2020
import Synthesizer.*
2121
import sbt.ExtractDependencies.*
2222
import xsbti.api.DependencyContext.*
23+
import dotty.tools.dotc.core.Definitions.MaxTupleArity
2324

2425
/** Synthesize terms for special classes */
2526
class 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

tests/neg/i21808a.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- [E172] Type Error: tests/neg/i21808a.scala:9:63 ---------------------------------------------------------------------
2+
9 | summon[TupledFunction[(x: T, y: T) => x.type, ((T, T)) => T]] // error
3+
| ^
4+
| (x: Test.T, y: Test.T) => x.type cannot be tupled as ((Test.T, Test.T)) => Test.T

tests/neg/i21808a.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//> using options -experimental
2+
3+
import scala.util.TupledFunction
4+
import scala.util.NotGiven
5+
6+
object Test {
7+
type T
8+
9+
summon[TupledFunction[(x: T, y: T) => x.type, ((T, T)) => T]] // error
10+
}

tests/neg/i21808b.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- [E172] Type Error: tests/neg/i21808b.scala:9:63 ---------------------------------------------------------------------
2+
9 | summon[TupledFunction[(T, T) => T, (x: (T, T)) => x._1.type]] // error
3+
| ^
4+
| (Test.T, Test.T) => Test.T cannot be tupled as (x: (Test.T, Test.T)) => (x._1 : Test.T)

tests/neg/i21808b.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//> using options -experimental
2+
3+
import scala.util.TupledFunction
4+
import scala.util.NotGiven
5+
6+
object Test {
7+
type T
8+
9+
summon[TupledFunction[(T, T) => T, (x: (T, T)) => x._1.type]] // error
10+
}

tests/pos/i21808.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//> using options -experimental
2+
3+
import scala.util.TupledFunction
4+
import scala.util.NotGiven
5+
6+
object Test {
7+
type T
8+
9+
summon[TupledFunction[(x: T, y: T) => x.type, (x: (T, T)) => x._1.type]]
10+
}

0 commit comments

Comments
 (0)