Skip to content

Commit 2cd5721

Browse files
authored
used derived types to type arguments of dependent function type (#19838)
We don't need to repeat the tree twice, instead derive a type tree from the original tree, and reuse its spans. fixes #19629
2 parents 18504b9 + 0d79122 commit 2cd5721

File tree

5 files changed

+45
-4
lines changed

5 files changed

+45
-4
lines changed

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ class TreeUnpickler(reader: TastyReader,
6565
/** A map from addresses of definition entries to the symbols they define */
6666
private val symAtAddr = new mutable.HashMap[Addr, Symbol]
6767

68+
private def addrOfSymbol(sym: Symbol): Option[Addr] = symAtAddr.iterator.collectFirst {
69+
case (addr, s) if s == sym => addr
70+
}
71+
72+
private def locatedSymbol(sym: Symbol)(using Context): String =
73+
addrOfSymbol(sym) match
74+
case Some(addr) => i"local $sym @ ${addr.index}"
75+
case None => i"external $sym"
76+
6877
/** A temporary map from addresses of definition entries to the trees they define.
6978
* Used to remember trees of symbols that are created by a completion. Emptied
7079
* once the tree is inlined into a larger tree.
@@ -297,7 +306,7 @@ class TreeUnpickler(reader: TastyReader,
297306
/** The symbol defined by current definition */
298307
def symbolAtCurrent()(using Context): Symbol = symAtAddr.get(currentAddr) match {
299308
case Some(sym) =>
300-
assert(ctx.owner == sym.owner, i"owner discrepancy for $sym, expected: ${ctx.owner}, found: ${sym.owner}")
309+
assert(ctx.owner == sym.owner, i"owner discrepancy for ${locatedSymbol(sym)}, expected: ${locatedSymbol(ctx.owner)}, found: ${locatedSymbol(sym.owner)}")
301310
sym
302311
case None =>
303312
createSymbol()

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,14 +1463,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14631463
if isErasedClass then arg.withAddedFlags(Erased) else arg
14641464
}
14651465
return typedDependent(newParams)
1466-
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
1467-
val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt
14681466
val core =
14691467
if mt.hasErasedParams then TypeTree(defn.PolyFunctionClass.typeRef)
14701468
else
1469+
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
1470+
val paramTpts = appDef.termParamss.head.map(p => TypeTree(p.tpt.tpe).withSpan(p.tpt.span))
14711471
val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure)
14721472
val tycon = TypeTree(funSym.typeRef)
1473-
AppliedTypeTree(tycon, typeArgs)
1473+
AppliedTypeTree(tycon, paramTpts :+ resTpt)
14741474
RefinedTypeTree(core, List(appDef), ctx.owner.asClass)
14751475
end typedDependent
14761476

tests/pos/i19629.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait CP[A,B]
2+
trait TypeEqK[F[_], G[_]]
3+
4+
trait Knit[CP[_, _], F[_]] {
5+
type Res
6+
7+
def visit[R](
8+
caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R
9+
): R
10+
}

tests/run/i19629/Test_2.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
class Container[Y1, G[_]]:
3+
lazy val outer: Knit[CP, G] = new:
4+
type Res = Y1
5+
def visit[R](caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[G, [x] =>> CP[F1[x], Y]]) => R): R =
6+
caseInFst[G, Res](outer)(new TypeEqK[G, [x] =>> CP[G[x], Res]] {})
7+
8+
@main def Test =
9+
val knit = new Container[Unit, Option].outer
10+
val res = knit.visit:
11+
[F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[Option, [x] =>> CP[F1[x], Y]]) => 42
12+
assert(res == 42)

tests/run/i19629/lib_1.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait CP[A,B]
2+
trait TypeEqK[F[_], G[_]]
3+
4+
trait Knit[CP[_, _], F[_]] {
5+
type Res
6+
7+
def visit[R](
8+
caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R
9+
): R
10+
}

0 commit comments

Comments
 (0)