From 640e6c8466eecadf4a888bbed61e9795fa320c99 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Wed, 4 Oct 2023 13:53:17 +0100 Subject: [PATCH] Fix the tparam bounds of exported inherited classes When trying to export M2.F, seeing M1#F from the prefix M2 doesn't change the bounds of F's T type parameter, which still refers to M1.this.A, rather than M2.A. So, we run asSeenFrom against that info, when eta-expanding the class into a hk type lambda. --- .../src/dotty/tools/dotc/typer/Namer.scala | 18 ++++++++++++++++-- tests/pos/i18569.scala | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/pos/i18569.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 8ed881ca0d81..8797d016df98 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1175,8 +1175,22 @@ class Namer { typer: Typer => if mbr.isType then val forwarderName = checkNoConflict(alias.toTypeName, isPrivate = false, span) var target = pathType.select(sym) - if target.typeParams.nonEmpty then - target = target.EtaExpand(target.typeParams) + val tparams = target.typeParams + if tparams.nonEmpty then + // like `target = target.EtaExpand(target.typeParams)` + // except call `asSeenFrom` to fix class type parameter bounds + // e.g. in pos/i18569: + // `Test#F` should have `M2.A` or `Test.A` as bounds, not `M1#A`. + target = HKTypeLambda(tparams.map(_.paramName))( + tl => tparams.map { + case p: Symbol => + val info = p.info.asSeenFrom(pathType, sym.owner) + HKTypeLambda.toPInfo(tl.integrate(tparams, info)) + case p => + val info = p.paramInfo + HKTypeLambda.toPInfo(tl.integrate(tparams, info)) + }, + tl => tl.integrate(tparams, target.appliedTo(tparams.map(_.paramRef)))) newSymbol( cls, forwarderName, Exported | Final, diff --git a/tests/pos/i18569.scala b/tests/pos/i18569.scala new file mode 100644 index 000000000000..1457f6fbe5b6 --- /dev/null +++ b/tests/pos/i18569.scala @@ -0,0 +1,11 @@ +trait M1: + trait A + trait F[T <: A] + type G[T <: A] = F[T] + +object M2 extends M1 + +trait Test: + export M2.* + def y: F[A] + def z: G[A]