Skip to content

Commit

Permalink
Fix EtaExpansion extractor, to also honour prefix
Browse files Browse the repository at this point in the history
When looking at the info of the type parameters of a TypeRef, make sure
to honour the reference's prefix.
  • Loading branch information
dwijnand committed Nov 30, 2023
1 parent 0a48fa0 commit 5d07e66
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions compiler/src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ object TypeApplications {
* contain the bounds of the type parameters of `C`. This is necessary to be able to
* contract the hk lambda to `C`.
*/
private def weakerBounds(tp: HKTypeLambda, tparams: List[ParamInfo])(using Context): Boolean =
private def weakerBounds(tp: HKTypeLambda, fn: Type)(using Context): Boolean =
val onlyEmptyBounds = tp.typeParams.forall(_.paramInfo == TypeBounds.empty)
onlyEmptyBounds
// Note: this pre-test helps efficiency. It is also necessary to workaround #9965 since in some cases
Expand All @@ -47,18 +47,21 @@ object TypeApplications {
// In this case, we can still return true if we know that the hk lambda bounds
// are empty anyway.
|| {
val tparams = fn.typeParams
val paramRefs = tparams.map(_.paramRef)
val prefix = fn match { case fn: TypeRef => fn.prefix case _ => NoPrefix }
val owner = fn match { case fn: TypeRef => fn.symbol.owner case _ => NoSymbol }
tp.typeParams.corresponds(tparams) { (param1, param2) =>
param2.paramInfo frozen_<:< param1.paramInfo.substParams(tp, paramRefs)
param2.paramInfo.asSeenFrom(prefix, owner) frozen_<:< param1.paramInfo.substParams(tp, paramRefs)
}
}

def unapply(tp: Type)(using Context): Option[Type] = tp match
case tp @ HKTypeLambda(tparams, AppliedType(fn: Type, args))
case tp @ HKTypeLambda(tparams, AppliedType(fn, args))
if fn.typeSymbol.isClass
&& tparams.hasSameLengthAs(args)
&& args.lazyZip(tparams).forall((arg, tparam) => arg == tparam.paramRef)
&& weakerBounds(tp, fn.typeParams) => Some(fn)
&& weakerBounds(tp, fn) => Some(fn)
case _ => None

end EtaExpansion
Expand Down Expand Up @@ -303,7 +306,6 @@ class TypeApplications(val self: Type) extends AnyVal {
val resType = self.appliedTo(tparams.map(_.paramRef))
self match
case self: TypeRef if tparams.nonEmpty && self.symbol.isClass =>
val prefix = self.prefix
val owner = self.symbol.owner
// Calling asSeenFrom on the type parameter infos is important
// so that class type references within another prefix have
Expand All @@ -318,7 +320,7 @@ class TypeApplications(val self: Type) extends AnyVal {
// So we take the prefix M2.type and the F symbol's owner, M1,
// to call asSeenFrom on T's info.
HKTypeLambda(tparams.map(_.paramName))(
tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo.asSeenFrom(prefix, owner)))),
tl => tparams.map(p => HKTypeLambda.toPInfo(tl.integrate(tparams, p.paramInfo.asSeenFrom(self.prefix, owner)))),
tl => tl.integrate(tparams, resType))
case _ =>
HKTypeLambda.fromParams(tparams, resType)
Expand Down

0 comments on commit 5d07e66

Please sign in to comment.