Skip to content

Commit

Permalink
Merge pull request #237 from sjrd/subtyping-typelambda
Browse files Browse the repository at this point in the history
Subtyping for TypeLambda's.
  • Loading branch information
bishabosha authored Jan 3, 2023
2 parents 3f11495 + 9af598d commit 4504775
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
18 changes: 18 additions & 0 deletions tasty-query/shared/src/main/scala/tastyquery/Subtyping.scala
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@ private[tastyquery] object Subtyping:
case tp2: AppliedType =>
compareAppliedType2(tp1, tp2)

case tp2: TypeLambda =>
tp1 match
case tp1: TypeLambda =>
// TODO Check bounds and variances
tp1.paramRefs.lengthCompare(tp2.paramRefs) == 0
&& isSubtype(tp1.resultType, tp2.appliedTo(tp1.paramRefs))
case _ =>
// TODO? Eta-expand polymorphic type constructors?
level4(tp1, tp2)

case tp2: OrType =>
isSubtype(tp1, tp2.first) || isSubtype(tp1, tp2.second)
|| level4(tp1, tp2)
Expand Down Expand Up @@ -269,6 +279,14 @@ private[tastyquery] object Subtyping:

comparePaths || proceedWithWidenedType

case tp1: TypeLambda =>
tp2 match
case tp2: TypeLambda =>
false // this case is already handled in level3
case _ =>
tp2.typeParams.lengthCompare(tp1.paramRefs) == 0
&& isSubtype(tp1.resultType, tp2.appliedTo(tp1.paramRefs))

case tp1: AndType =>
// TODO Try and simplify first
isSubtype(tp1.first, tp2) || isSubtype(tp1.second, tp2)
Expand Down
22 changes: 22 additions & 0 deletions tasty-query/shared/src/test/scala/tastyquery/SubtypingSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ class SubtypingSuite extends UnrestrictedUnpicklingSuite:
def findTypesFromTASTyNamed(name: String)(using Context): Type =
ctx.findTopLevelClass("subtyping.TypesFromTASTy").findDecl(termName(name)).declaredType

def findTypesFromTASTyNamed(name: TypeName)(using Context): Type =
ctx.findTopLevelClass("subtyping.TypesFromTASTy").findDecl(name).asInstanceOf[TypeMemberSymbol].aliasedType

testWithContext("same-monomorphic-class") {
assertEquiv(defn.IntType, defn.IntClass.typeRef).withRef[Int, scala.Int]
assertEquiv(defn.IntType, defn.IntClass.newTypeRef)
Expand Down Expand Up @@ -560,4 +563,23 @@ class SubtypingSuite extends UnrestrictedUnpicklingSuite:
.withRef[mutable.Seq[? <: Option[Any]], mutable.Seq[? <: Product]]
}

testWithContext("type-lambdas") {
val Function1Class = ctx.findTopLevelClass("scala.Function1")
def fun1Type(argType: Type, resultType: Type): Type =
AppliedType(Function1Class.typeRef, argType :: resultType :: Nil)

def makeTToTTypeLambda() = TypeLambda(typeName("T") :: Nil)(
_ => List(defn.NothingAnyBounds),
tl => fun1Type(tl.paramRefs(0), tl.paramRefs(0))
)
val tToTTypeLambda = makeTToTTypeLambda()

val fromTasty = findTypesFromTASTyNamed(typeName("TToTType"))

type TToTType = [T] => T => T

assertEquiv(tToTTypeLambda, makeTToTTypeLambda()).withRef[TToTType, TToTType]
assertEquiv(tToTTypeLambda, fromTasty)
}

end SubtypingSuite
2 changes: 2 additions & 0 deletions test-sources/src/main/scala/subtyping/TypesFromTASTy.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ class TypesFromTASTy:

val orType: Int | String = 1
val andType: Product & Serializable = Nil

type TToTType[T] = T => T
end TypesFromTASTy

0 comments on commit 4504775

Please sign in to comment.