diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index b95e4df663a1..57c0b2217e9d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -65,6 +65,15 @@ class TreeUnpickler(reader: TastyReader, /** A map from addresses of definition entries to the symbols they define */ private val symAtAddr = new mutable.HashMap[Addr, Symbol] + private def addrOfSymbol(sym: Symbol): Option[Addr] = symAtAddr.iterator.collectFirst { + case (addr, s) if s == sym => addr + } + + private def locatedSymbol(sym: Symbol)(using Context): String = + addrOfSymbol(sym) match + case Some(addr) => i"local $sym @ ${addr.index}" + case None => i"external $sym" + /** A temporary map from addresses of definition entries to the trees they define. * Used to remember trees of symbols that are created by a completion. Emptied * once the tree is inlined into a larger tree. @@ -297,7 +306,7 @@ class TreeUnpickler(reader: TastyReader, /** The symbol defined by current definition */ def symbolAtCurrent()(using Context): Symbol = symAtAddr.get(currentAddr) match { case Some(sym) => - assert(ctx.owner == sym.owner, i"owner discrepancy for $sym, expected: ${ctx.owner}, found: ${sym.owner}") + assert(ctx.owner == sym.owner, i"owner discrepancy for ${locatedSymbol(sym)}, expected: ${locatedSymbol(ctx.owner)}, found: ${locatedSymbol(sym.owner)}") sym case None => createSymbol() diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1f0adc9f1421..9ef075f95e3a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1463,14 +1463,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if isErasedClass then arg.withAddedFlags(Erased) else arg } return typedDependent(newParams) - val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span) - val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt val core = if mt.hasErasedParams then TypeTree(defn.PolyFunctionClass.typeRef) else + val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span) + val paramTpts = appDef.termParamss.head.map(p => TypeTree(p.tpt.tpe).withSpan(p.tpt.span)) val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure) val tycon = TypeTree(funSym.typeRef) - AppliedTypeTree(tycon, typeArgs) + AppliedTypeTree(tycon, paramTpts :+ resTpt) RefinedTypeTree(core, List(appDef), ctx.owner.asClass) end typedDependent diff --git a/tests/pos/i19629.scala b/tests/pos/i19629.scala new file mode 100644 index 000000000000..ec96e94e70dd --- /dev/null +++ b/tests/pos/i19629.scala @@ -0,0 +1,10 @@ +trait CP[A,B] +trait TypeEqK[F[_], G[_]] + +trait Knit[CP[_, _], F[_]] { + type Res + + def visit[R]( + caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R + ): R +} diff --git a/tests/run/i19629/Test_2.scala b/tests/run/i19629/Test_2.scala new file mode 100644 index 000000000000..c9d1ee7f79e5 --- /dev/null +++ b/tests/run/i19629/Test_2.scala @@ -0,0 +1,12 @@ + +class Container[Y1, G[_]]: + lazy val outer: Knit[CP, G] = new: + type Res = Y1 + def visit[R](caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[G, [x] =>> CP[F1[x], Y]]) => R): R = + caseInFst[G, Res](outer)(new TypeEqK[G, [x] =>> CP[G[x], Res]] {}) + +@main def Test = + val knit = new Container[Unit, Option].outer + val res = knit.visit: + [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[Option, [x] =>> CP[F1[x], Y]]) => 42 + assert(res == 42) diff --git a/tests/run/i19629/lib_1.scala b/tests/run/i19629/lib_1.scala new file mode 100644 index 000000000000..ec96e94e70dd --- /dev/null +++ b/tests/run/i19629/lib_1.scala @@ -0,0 +1,10 @@ +trait CP[A,B] +trait TypeEqK[F[_], G[_]] + +trait Knit[CP[_, _], F[_]] { + type Res + + def visit[R]( + caseInFst: [F1[_], Y] => (k: Knit[CP, F1]) => (ev: TypeEqK[F, [x] =>> CP[F1[x], Y]]) => R + ): R +}