Skip to content

Commit

Permalink
Merge pull request #181 from sjrd/introduce-matchable
Browse files Browse the repository at this point in the history
Introduce `Matchable` in the top type hierarchy.
  • Loading branch information
bishabosha authored Nov 3, 2022
2 parents 1601e90 + 391e958 commit 751e48b
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ final class Definitions private[tastyquery] (ctx: Context, rootPackage: PackageS
// Cached TypeRef's for core types

val AnyType: TypeRef = TypeRef(scalaPackage.packageRef, typeName("Any"))
val MatchableType: TypeRef = TypeRef(scalaPackage.packageRef, typeName("Matchable"))
val AnyRefType: TypeRef = TypeRef(scalaPackage.packageRef, typeName("AnyRef"))
val AnyValType: TypeRef = TypeRef(scalaPackage.packageRef, typeName("AnyVal"))

Expand Down Expand Up @@ -69,7 +70,11 @@ final class Definitions private[tastyquery] (ctx: Context, rootPackage: PackageS
val AnyClass = createSpecialClass(typeName("Any"), Nil, Abstract)
.withSpecialErasure(() => ErasedTypeRef.ClassRef(ObjectClass))

val NullClass = createSpecialClass(typeName("Null"), AnyClass.typeRef :: Nil, Abstract | Final)
val MatchableClass = createSpecialClass(typeName("Matchable"), AnyClass.typeRef :: Nil, Trait)
.withSpecialErasure(() => ErasedTypeRef.ClassRef(ObjectClass))

val NullClass =
createSpecialClass(typeName("Null"), AnyClass.typeRef :: MatchableClass.typeRef :: Nil, Abstract | Final)

val NothingClass = createSpecialClass(typeName("Nothing"), AnyClass.typeRef :: Nil, Abstract | Final)

Expand Down
1 change: 1 addition & 0 deletions tasty-query/shared/src/main/scala/tastyquery/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ object Names {

object tpnme {
val Any: TypeName = typeName("Any")
val AnyVal: TypeName = typeName("AnyVal")
val Nothing: TypeName = typeName("Nothing")
val Null: TypeName = typeName("Null")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ private[classfiles] object Descriptors:

def parseSupers(cls: ClassSymbol, superClass: Option[String], interfaces: IArray[String])(using Context): List[Type] =
cls.withTypeParams(Nil)
val superRef = superClass.map(classRef).getOrElse {
// More efficient would be to only do this check once in Definitions,
// but parents are immutable currently.
// !!! Cannot access `defn.ObjectClass` here, because that's a cycle when initializing defn.ObjectClass itself
if cls.owner == defn.javaLangPackage && cls.name == tpnme.Object then defn.AnyType
else defn.ObjectType
}
superRef :: interfaces.map(classRef).toList
// !!! Cannot access `defn.ObjectClass` here, because that's a cycle when initializing defn.ObjectClass itself
if cls.owner == defn.javaLangPackage && cls.name == tpnme.Object then defn.AnyType :: defn.MatchableType :: Nil
else
val superRef = superClass.map(classRef).getOrElse(defn.ObjectType)
superRef :: interfaces.map(classRef).toList

private def classRef(binaryName: String)(using Context): TypeRef =
def followPackages(acc: PackageSymbol, parts: List[String]): TypeRef =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,18 @@ private[pickles] class PickleReader {
val tpe = readSymType()
val typeParams = atNoCache(infoRef)(readTypeParams())
if isRefinementClass(cls) then return cls // by-pass further assignments, including Flags
val parentTypes = tpe match
case TempPolyType(tparams, restpe: TempClassInfoType) =>
assert(tparams.corresponds(typeParams)(_ eq _)) // should reuse the class type params
restpe.parentTypes
case tpe: TempClassInfoType => tpe.parentTypes
case tpe =>
throw AssertionError(s"unexpected type $tpe for $cls, owner is $owner")
val parentTypes =
if cls.owner == defn.scalaPackage && tname == tpnme.AnyVal then
// Patch the superclasses of AnyVal to contain Matchable
defn.AnyType :: defn.MatchableType :: Nil
else
tpe match
case TempPolyType(tparams, restpe: TempClassInfoType) =>
assert(tparams.corresponds(typeParams)(_ eq _)) // should reuse the class type params
restpe.parentTypes
case tpe: TempClassInfoType => tpe.parentTypes
case tpe =>
throw AssertionError(s"unexpected type $tpe for $cls, owner is $owner")
cls.withParentsDirect(parentTypes)
cls.withTypeParams(typeParams)
cls
Expand Down
11 changes: 10 additions & 1 deletion tasty-query/shared/src/test/scala/tastyquery/TypeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,15 @@ class TypeSuite extends UnrestrictedUnpicklingSuite {
)
}

testWithContext("Parents of special classes") {
assert(clue(defn.AnyClass.parentClasses) == Nil)
assert(clue(defn.MatchableClass.parentClasses) == List(defn.AnyClass))
assert(clue(defn.ObjectClass.parentClasses) == List(defn.AnyClass, defn.MatchableClass))
assert(clue(defn.AnyValClass.parentClasses) == List(defn.AnyClass, defn.MatchableClass))
assert(clue(defn.NullClass.parentClasses) == List(defn.AnyClass, defn.MatchableClass))
assert(clue(defn.NothingClass.parentClasses) == List(defn.AnyClass))
}

testWithContext("java-class-signatures-[RecClass]") {
val RecClass = resolve(name"javadefined" / tname"RecClass").asClass
val ObjectClass = resolve(name"java" / name"lang" / tname"Object")
Expand Down Expand Up @@ -796,7 +805,7 @@ class TypeSuite extends UnrestrictedUnpicklingSuite {
val MidMonoClass = resolve(OverridesPath / tname"MidMono").asClass
val ChildMonoClass = resolve(OverridesPath / tname"ChildMono").asClass

val linTail = defn.ObjectClass :: defn.AnyClass :: Nil
val linTail = defn.ObjectClass :: defn.MatchableClass :: defn.AnyClass :: Nil

assert(clue(SuperMonoClass.linearization) == SuperMonoClass :: linTail)
assert(clue(SuperMonoTraitClass.linearization) == SuperMonoTraitClass :: linTail)
Expand Down

0 comments on commit 751e48b

Please sign in to comment.