# Intersection Types - More Details

## Syntax

Syntactically, the type `S & T` is an infix type, where the infix operator is `&`. The operator `&` is a normal identifier with the usual precedence and subject to usual resolving rules. Unless shadowed by another definition, it resolves to the type `scala.&`, which acts as a type alias to an internal representation of intersection types.

``````Type              ::=  ...| InfixType
InfixType         ::=  RefinedType {id [nl] RefinedType}
``````

## Subtyping Rules

``````T <: A    T <: B
----------------
T <: A & B

A <: T
----------------
A & B <: T

B <: T
----------------
A & B <: T
``````

From the rules above, we can show that `&` is commutative: `A & B <: B & A` for any type `A` and `B`.

``````   B <: B           A <: A
----------       -----------
A & B <: B       A & B <: A
---------------------------
A & B  <:  B & A
``````

In another word, `A & B` is the same type as `B & A`, in the sense that the two types have the same values and are subtypes of each other.

If `C` is a type constructor, then `C[A] & C[B]` can be simplified using the following three rules:

• If `C` is covariant, `C[A] & C[B] ~> C[A & B]`
• If `C` is contravariant, `C[A] & C[B] ~> C[A | B]`
• If `C` is non-variant, emit a compile error

When `C` is covariant, `C[A & B] <: C[A] & C[B]` can be derived:

``````    A <: A                  B <: B
----------               ---------
A & B <: A               A & B <: B
---------------         -----------------
C[A & B] <: C[A]          C[A & B] <: C[B]
------------------------------------------
C[A & B] <: C[A] & C[B]
``````

When `C` is contravariant, `C[A | B] <: C[A] & C[B]` can be derived:

``````    A <: A                        B <: B
----------                     ---------
A <: A | B                     B <: A | B
-------------------           ----------------
C[A | B] <: C[A]              C[A | B] <: C[B]
--------------------------------------------------
C[A | B] <: C[A] & C[B]
``````

## Erasure

The erased type for `S & T` is the erased glb (greatest lower bound) of the erased type of `S` and `T`. The rules for erasure of intersection types are given below in pseudocode:

``````|S & T| = glb(|S|, |T|)

glb(JArray(A), JArray(B)) = JArray(glb(A, B))
glb(JArray(T), _)         = JArray(T)
glb(_, JArray(T))         = JArray(T)
glb(A, B)                 = A                     if A extends B
glb(A, B)                 = B                     if B extends A
glb(A, _)                 = A                     if A is not a trait
glb(_, B)                 = B                     if B is not a trait
glb(A, _)                 = A                     // use first
``````

In the above, `|T|` means the erased type of `T`, `JArray` refers to the type of Java Array.

See also: `TypeErasure#erasedGlb`.

## Relationship with Compound Type (`with`)

Intersection types `A & B` replace compound types `A with B` in Scala 2. For the moment, the syntax `A with B` is still allowed and interpreted as `A & B`, but its usage as a type (as opposed to in a `new` or `extends` clause) will be deprecated and removed in the future.