Type System

The types are defined in dotty/tools/dotc/core/Types.scala

Class diagram

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
      |              |                +--- TermParamRef
      |              |                +----RecThis
      |              |                +--- SkolemType
      |              +- TypeParamRef
      |              +- RefinedOrRecType -+-- RefinedType
      |              |                   -+-- RecType
      |              +- AppliedType
      |              +- TypeBounds
      |              +- ExprType
      |              +- AnnotatedType
      |              +- TypeVar
      |              +- HKTypeLambda
      |              +- MatchType
      |
      +- GroundType -+- AndType
                     +- OrType
                     +- MethodOrPoly ---+-- PolyType
                     |                  +-- MethodType
                     +- 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

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

Generated byscaladoc
Copyright (c) 2002-2022, LAMP/EPFL
Social links
Mode
Back to top
In this article