Skip to content

Commit 0ba8d7d

Browse files
authored
Merge pull request #1409 from dotty-staging/fix-hk-typdefs-of-lambdas
Fix parameterized typedefs with lambdas as rhs
2 parents b6882d6 + 006748d commit 0ba8d7d

File tree

5 files changed

+43
-17
lines changed

5 files changed

+43
-17
lines changed

src/dotty/tools/dotc/core/TypeApplications.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,12 @@ class TypeApplications(val self: Type) extends AnyVal {
223223
self.parent.typeParams.filterNot(_.paramName == self.refinedName)
224224
case self: RecType =>
225225
self.parent.typeParams
226-
case _: HKApply | _: SingletonType =>
226+
case _: SingletonType =>
227227
Nil
228228
case self: WildcardType =>
229229
self.optBounds.typeParams
230230
case self: TypeProxy =>
231-
self.underlying.typeParams
231+
self.superType.typeParams
232232
case _ =>
233233
Nil
234234
}
@@ -312,14 +312,13 @@ class TypeApplications(val self: Type) extends AnyVal {
312312
case self: TypeRef => self.info.isHK
313313
case self: RefinedType => false
314314
case self: TypeLambda => true
315-
case self: HKApply => false
316315
case self: SingletonType => false
317316
case self: TypeVar =>
318317
// Using `origin` instead of `underlying`, as is done for typeParams,
319318
// avoids having to set ephemeral in some cases.
320319
self.origin.isHK
321320
case self: WildcardType => self.optBounds.isHK
322-
case self: TypeProxy => self.underlying.isHK
321+
case self: TypeProxy => self.superType.isHK
323322
case _ => false
324323
}
325324

src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
665665
}
666666
}
667667

668+
/** Fall back to comparing either with `fourthTry` or against the lower
669+
* approximation of the rhs.
670+
* @param tyconLo The type constructor's lower approximation.
671+
*/
672+
def fallback(tyconLo: Type) =
673+
either(fourthTry(tp1, tp2), isSubType(tp1, tyconLo.applyIfParameterized(args2)))
674+
668675
/** Let `tycon2bounds` be the bounds of the RHS type constructor `tycon2`.
669676
* Let `app2 = tp2` where the type constructor of `tp2` is replaced by
670677
* `tycon2bounds.lo`.
@@ -674,13 +681,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
674681
* tp1 <:< tp2 using fourthTry (this might instantiate params in tp1)
675682
* tp1 <:< app2 using isSubType (this might instantiate params in tp2)
676683
*/
677-
def compareLower(tycon2bounds: TypeBounds, tyconIsTypeRef: Boolean): Boolean = {
678-
def app2 = tycon2bounds.lo.applyIfParameterized(args2)
684+
def compareLower(tycon2bounds: TypeBounds, tyconIsTypeRef: Boolean): Boolean =
679685
if (tycon2bounds.lo eq tycon2bounds.hi)
680-
isSubType(tp1, if (tyconIsTypeRef) tp2.superType else app2)
686+
isSubType(tp1,
687+
if (tyconIsTypeRef) tp2.superType
688+
else tycon2bounds.lo.applyIfParameterized(args2))
681689
else
682-
either(fourthTry(tp1, tp2), isSubType(tp1, app2))
683-
}
690+
fallback(tycon2bounds.lo)
684691

685692
tycon2 match {
686693
case param2: PolyParam =>
@@ -693,6 +700,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
693700
compareLower(tycon2.info.bounds, tyconIsTypeRef = true)
694701
case _: TypeVar | _: AnnotatedType =>
695702
isSubType(tp1, tp2.superType)
703+
case tycon2: HKApply =>
704+
fallback(tycon2.lowerBound)
696705
case _ =>
697706
false
698707
}

src/dotty/tools/dotc/core/Types.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2653,7 +2653,6 @@ object Types {
26532653
cachedSuper
26542654
}
26552655

2656-
/* (Not needed yet) */
26572656
def lowerBound(implicit ctx: Context) = tycon.stripTypeVar match {
26582657
case tycon: TypeRef =>
26592658
tycon.info match {

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -936,13 +936,8 @@ class Namer { typer: Typer =>
936936
}
937937

938938
def typeDefSig(tdef: TypeDef, sym: Symbol, tparamSyms: List[TypeSymbol])(implicit ctx: Context): Type = {
939-
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
940-
//val toParameterize = tparamSyms.nonEmpty && !isDerived
941-
//val needsLambda = sym.allOverriddenSymbols.exists(_ is HigherKinded) && !isDerived
942939
def abstracted(tp: Type): Type =
943-
if (tparamSyms.nonEmpty && !tp.isHK) tp.LambdaAbstract(tparamSyms)
944-
//else if (toParameterize) tp.parameterizeWith(tparamSyms)
945-
else tp
940+
if (tparamSyms.nonEmpty) tp.LambdaAbstract(tparamSyms) else tp
946941

947942
val dummyInfo = abstracted(TypeBounds.empty)
948943
sym.info = dummyInfo
@@ -956,7 +951,10 @@ class Namer { typer: Typer =>
956951
//
957952
// The scheme critically relies on an implementation detail of isRef, which
958953
// inspects a TypeRef's info, instead of simply dealiasing alias types.
959-
val rhsType = abstracted(typedAheadType(tdef.rhs).tpe)
954+
955+
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
956+
val rhsBodyType = typedAheadType(tdef.rhs).tpe
957+
val rhsType = if (isDerived) rhsBodyType else abstracted(rhsBodyType)
960958
val unsafeInfo = rhsType match {
961959
case bounds: TypeBounds => bounds
962960
case alias => TypeAlias(alias, if (sym is Local) sym.variance else 0)

tests/pos/nestedLambdas.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Test {
2+
3+
type T = [X] -> [Y] -> (X, Y)
4+
5+
type A[X] = [Y] -> (X, Y)
6+
7+
type B[X] = (X, X)
8+
9+
val x: T[Int][Boolean] = ???
10+
11+
val y: A[Int][Boolean] = x
12+
13+
def f[X <: T[Int]] = ???
14+
15+
f[A[Int]]
16+
17+
def g[X <: T] = ???
18+
19+
g[A]
20+
21+
}

0 commit comments

Comments
 (0)