--- layout: doc-page title: "Type System" --- The types are defined in [dotty/tools/dotc/core/Types.scala][1] ## Class diagram ## - [PDF][2], generated with [a fork of scaladiagrams][3] ## Proxy types and ground types ## A type which inherits `TypeProxy` is a proxy for another type accessible using the `underlying` method, other types are called _ground_ types and inherit `CachedGroundType` or `UncachedGroundType`. Here's a diagram, copied from [dotty/tools/dotc/core/Types.scala][1]: ``` Type -+- ProxyType --+- NamedType ----+--- TypeRef | | \ | +- SingletonType-+-+- TermRef | | | | | +--- ThisType | | +--- SuperType | | +--- ConstantType | | +--- MethodParam | | +----RecThis | | +--- SkolemType | +- PolyParam | +- RefinedOrRecType -+-- RefinedType | | -+-- RecType | +- HKApply | +- TypeBounds | +- ExprType | +- AnnotatedType | +- TypeVar | +- PolyType | +- GroundType -+- AndType +- OrType +- MethodType -----+- ImplicitMethodType | +- JavaMethodType +- ClassInfo | +- NoType +- NoPrefix +- ErrorType +- WildcardType ``` ## Representations of types ## Type | Representation ------------------------- | ----------------------------- `p.x.type` | `TermRef(p, x)` `p#T` | `TypeRef(p, T)` `p.x.T` == `p.x.type#T` | `TypeRef(TermRef(p, x), T)` `this.type` | `ThisType` `A & B` | `AndType(A, B)` `A | B` | `OrType(A, B)` `=> T` | `ExprType(T)` `p { refinedName }` | `RefinedType(p, refinedName)` type of the value `super` | `SuperType` `type T >: A <: B` | `TypeRef` with underlying type `RealTypeBounds(A, B)` `type T = A` | `TypeRef` with underlying type `TypeAlias(A)` `class p.C ...` | `ClassInfo(p, C, ...)` ### Representation of methods ### ```scala def f[A, B <: Ord[A]](x: A, y: B): Unit ``` is represented as: ```scala val p = PolyType(List("A", "B"))( List(TypeBounds(Nothing, Any), TypeBounds(Nothing, RefinedType(Ordering, scala$math$Ordering$$T, TypeAlias(PolyParam(p, 0))))), m) val m = MethodType(List("x", "y"), List(PolyParam(p, 0), PolyParam(p, 1)))(Unit) ``` (This is a slightly simplified version, e.g. we write `Unit` instead of `TypeRef(TermRef(ThisType(TypeRef(NoPrefix,)),scala),Unit)`). Note that a PolyParam refers to a type parameter using its index (here A is 0 and B is 1). ## Subtyping checks ## `topLevelSubType(tp1, tp2)` in [dotty/tools/dotc/core/TypeComparer.scala][4] checks if `tp1` is a subtype of `tp2`. ### Type rebasing ### **FIXME**: This section is no longer accurate because https://github.com/lampepfl/dotty/pull/331 changed the handling of refined types. Consider [tests/pos/refinedSubtyping.scala][5] ```scala class Test { class C { type T; type Coll } type T1 = C { type T = Int } type T11 = T1 { type Coll = Set[Int] } type T2 = C { type Coll = Set[T] } type T22 = T2 { type T = Int } var x: T11 = _ var y: T22 = _ x = y y = x } ``` We want to do the subtyping checks recursively, since it would be nice if we could check if `T22 <: T11` by first checking if `T2 <: T1`. To achieve this recursive subtyping check, we remember that `T2#T` is really `T22#T`. This procedure is called rebasing and is done by storing refined names in `pendingRefinedBases` and looking them up using `rebase`. ## Type caching ## TODO ## Type inference via constraint solving ## TODO [1]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Types.scala [2]: https://github.com/samuelgruetter/dotty/blob/classdiagrampdf/dotty-types.pdf [3]: https://github.com/samuelgruetter/scaladiagrams/tree/print-descendants [4]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/TypeComparer.scala [5]: https://github.com/lampepfl/dotty/blob/master/tests/pos/refinedSubtyping.scala