Type System
The types are defined in dotty/tools/dotc/core/Types.scala
Class diagram
- PDF, generated with a fork of scaladiagrams
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:
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` | 
| => T | ExprType(T) | 
| p { refinedName } | RefinedType(p, refinedName) | 
| type of the value super | SuperType | 
| type T >: A <: B | TypeRefwith underlying typeRealTypeBounds(A, B) | 
| type T = A | TypeRefwith underlying typeTypeAlias(A) | 
| class p.C ... | ClassInfo(p, C, ...) | 
Representation of methods
def f[A, B <: Ord[A]](x: A, y: B): Unit
is represented as:
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,<root>)),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
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
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