summaryrefslogtreecommitdiff
path: root/spec/03-types.md
diff options
context:
space:
mode:
Diffstat (limited to 'spec/03-types.md')
-rw-r--r--spec/03-types.md133
1 files changed, 78 insertions, 55 deletions
diff --git a/spec/03-types.md b/spec/03-types.md
index 94b7916634..a3167646ca 100644
--- a/spec/03-types.md
+++ b/spec/03-types.md
@@ -105,7 +105,7 @@ forms.
SimpleType ::= Path ‘.’ type
```
-A singleton type is of the form $p.$`type`, where $p$ is a
+A _singleton type_ is of the form $p.$`type`, where $p$ is a
path pointing to a value expected to [conform](06-expressions.html#expression-typing)
to `scala.AnyRef`. The type denotes the set of values
consisting of `null` and the value denoted by $p$.
@@ -119,7 +119,7 @@ declared to be a subtype of trait `scala.Singleton`.
SimpleType ::= SimpleType ‘#’ id
```
-A type projection $T$#$x$ references the type member named
+A _type projection_ $T$#$x$ references the type member named
$x$ of type $T$.
<!--
@@ -134,7 +134,7 @@ If $x$ references an abstract type member, then $T$ must be a
SimpleType ::= StableId
```
-A type designator refers to a named value type. It can be simple or
+A _type designator_ refers to a named value type. It can be simple or
qualified. All such type designators are shorthands for type projections.
Specifically, the unqualified type name $t$ where $t$ is bound in some
@@ -167,7 +167,7 @@ SimpleType ::= SimpleType TypeArgs
TypeArgs ::= ‘[’ Types ‘]’
```
-A parameterized type $T[ T_1 , \ldots , T_n ]$ consists of a type
+A _parameterized type_ $T[ T_1 , \ldots , T_n ]$ consists of a type
designator $T$ and type parameters $T_1 , \ldots , T_n$ where
$n \geq 1$. $T$ must refer to a type constructor which takes $n$ type
parameters $a_1 , \ldots , a_n$.
@@ -227,7 +227,7 @@ G[S, Int] // illegal: S constrains its parameter to
SimpleType ::= ‘(’ Types ‘)’
```
-A tuple type $(T_1 , \ldots , T_n)$ is an alias for the
+A _tuple type_ $(T_1 , \ldots , T_n)$ is an alias for the
class `scala.Tuple$n$[$T_1$, … , $T_n$]`, where $n \geq 2$.
Tuple classes are case classes whose fields can be accessed using
@@ -255,7 +255,7 @@ trait Product_n[+$T_1$, … , +$T_n$] {
AnnotType ::= SimpleType {Annotation}
```
-An annotated type $T$ $a_1, \ldots, a_n$
+An _annotated type_ $T$ $a_1, \ldots, a_n$
attaches [annotations](11-annotations.html#user-defined-annotations)
$a_1 , \ldots , a_n$ to the type $T$.
@@ -278,7 +278,7 @@ RefineStat ::= Dcl
|
```
-A compound type $T_1$ `with` … `with` $T_n \\{ R \\}$
+A _compound type_ $T_1$ `with` … `with` $T_n \\{ R \\}$
represents objects with members as given in the component types
$T_1 , \ldots , T_n$ and the refinement $\\{ R \\}$. A refinement
$\\{ R \\}$ contains declarations and type definitions.
@@ -343,7 +343,7 @@ a value `callsign` and a `fly` method.
InfixType ::= CompoundType {id [nl] CompoundType}
```
-An infix type $T_1$ `op` $T_2$ consists of an infix
+An _infix type_ $T_1$ `op` $T_2$ consists of an infix
operator `op` which gets applied to two type operands $T_1$ and
$T_2$. The type is equivalent to the type application
`op`$[T_1, T_2]$. The infix operator `op` may be an
@@ -410,7 +410,7 @@ ExistentialDcl ::= ‘type’ TypeDcl
| ‘val’ ValDcl
```
-An existential type has the form `$T$ forSome { $Q$ }`
+An _existential type_ has the form `$T$ forSome { $Q$ }`
where $Q$ is a sequence of
[type declarations](04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases).
@@ -507,7 +507,7 @@ Assume the class definitions
```scala
class Ref[T]
-abstract class Outer { type T } .
+abstract class Outer { type T }
```
Here are some examples of existential types:
@@ -530,7 +530,7 @@ Ref[_ <: java.lang.Number]
The type `List[List[_]]` is equivalent to the existential type
```scala
-List[List[t] forSome { type t }] .
+List[List[t] forSome { type t }]
```
###### Example
@@ -564,7 +564,7 @@ report as the internal types of defined identifiers.
### Method Types
-A method type is denoted internally as $(\mathit{Ps})U$, where $(\mathit{Ps})$
+A _method type_ is denoted internally as $(\mathit{Ps})U$, where $(\mathit{Ps})$
is a sequence of parameter names and types $(p_1:T_1 , \ldots , p_n:T_n)$
for some $n \geq 0$ and $U$ is a (value or method) type. This type
represents named methods that take arguments named $p_1 , \ldots , p_n$
@@ -587,7 +587,7 @@ corresponding function type.
The declarations
-```
+```scala
def a: Int
def b (x: Int): Boolean
def c (x: Int) (y: String, z: String): String
@@ -631,7 +631,7 @@ union : [A >: Nothing <: Comparable[A]] (x: Set[A], xs: Set[A]) Set[A]
### Type Constructors
-A type constructor is represented internally much like a polymorphic method type.
+A _type constructor_ is represented internally much like a polymorphic method type.
`[$\pm$ $a_1$ >: $L_1$ <: $U_1 , \ldots , \pm a_n$ >: $L_n$ <: $U_n$] $T$`
represents a type that is expected by a
[type constructor parameter](04-basic-declarations-and-definitions.html#type-parameters) or an
@@ -642,7 +642,7 @@ the corresponding type parameter clause.
Consider this fragment of the `Iterable[+X]` class:
-```
+```scala
trait Iterable[+X] {
def flatMap[newType[+X] <: Iterable[X], S](f: X => newType[S]): newType[S]
}
@@ -660,7 +660,7 @@ same name, we model
An overloaded type consisting of type alternatives $T_1 \commadots T_n (n \geq 2)$ is denoted internally $T_1 \overload \ldots \overload T_n$.
###### Example
-```
+```scala
def println: Unit
def println(s: String): Unit = $\ldots$
def println(x: Float): Unit = $\ldots$
@@ -678,7 +678,7 @@ println: => Unit $\overload$
```
###### Example
-```
+```scala
def f(x: T): T = $\ldots$
val f = 0
```
@@ -778,25 +778,22 @@ These notions are defined mutually recursively as follows.
## Relations between types
-We define two relations between types.
+We define the following relations between types.
-|Name | Symbolically |Interpretation |
-|-----------------|----------------|-------------------------------------------------|
-|Equivalence |$T \equiv U$ |$T$ and $U$ are interchangeable in all contexts. |
-|Conformance |$T <: U$ |Type $T$ conforms to type $U$. |
+| Name | Symbolically | Interpretation |
+|------------------|----------------|----------------------------------------------------|
+| Equivalence | $T \equiv U$ | $T$ and $U$ are interchangeable in all contexts. |
+| Conformance | $T <: U$ | Type $T$ conforms to ("is a subtype of") type $U$. |
+| Weak Conformance | $T <:_w U$ | Augments conformance for primitive numeric types. |
+| Compatibility | | Type $T$ conforms to type $U$ after conversions. |
### Equivalence
-Equivalence $(\equiv)$ between types is the smallest congruence [^congruence] such that
-the following holds:
+Equivalence $(\equiv)$ between types is the smallest congruence [^congruence] such that the following holds:
-- If $t$ is defined by a type alias `type $t$ = $T$`, then $t$ is
- equivalent to $T$.
-- If a path $p$ has a singleton type `$q$.type`, then
- `$p$.type $\equiv q$.type`.
-- If $O$ is defined by an object definition, and $p$ is a path
- consisting only of package or object selectors and ending in $O$, then
- `$O$.this.type $\equiv p$.type`.
+- If $t$ is defined by a type alias `type $t$ = $T$`, then $t$ is equivalent to $T$.
+- If a path $p$ has a singleton type `$q$.type`, then `$p$.type $\equiv q$.type`.
+- If $O$ is defined by an object definition, and $p$ is a path consisting only of package or object selectors and ending in $O$, then `$O$.this.type $\equiv p$.type`.
- Two [compound types](#compound-types) are equivalent if the sequences
of their component are pairwise equivalent, and occur in the same order, and
their refinements are equivalent. Two refinements are equivalent if they
@@ -827,14 +824,11 @@ the following holds:
### Conformance
-The conformance relation $(<:)$ is the smallest
-transitive relation that satisfies the following conditions.
+The conformance relation $(<:)$ is the smallest transitive relation that satisfies the following conditions.
- Conformance includes equivalence. If $T \equiv U$ then $T <: U$.
- For every value type $T$, `scala.Nothing <: $T$ <: scala.Any`.
-- For every type constructor $T$ (with any number of type parameters),
- `scala.Nothing <: $T$ <: scala.Any`.
-
+- For every type constructor $T$ (with any number of type parameters), `scala.Nothing <: $T$ <: scala.Any`.
- For every class type $T$ such that `$T$ <: scala.AnyRef` one has `scala.Null <: $T$`.
- A type variable or abstract type $t$ conforms to its upper bound and
its lower bound conforms to $t$.
@@ -912,15 +906,12 @@ type $C'$, if one of the following holds.
type declaration `type t[$T_1$ , … , $T_n$] >: L <: U` if
$L <: t <: U$.
-The $(<:)$ relation forms pre-order between types,
-i.e. it is transitive and reflexive. _least upper bounds_ and
-_greatest lower bounds_ of a set of types
-are understood to be relative to that order.
-###### Note
-The least upper bound or greatest lower bound
-of a set of types does not always exist. For instance, consider
-the class definitions
+#### Least upper bounds and greatest lower bounds
+The $(<:)$ relation forms pre-order between types, i.e. it is transitive and reflexive.
+This allows us to define _least upper bounds_ and _greatest lower bounds_ of a set of types in terms of that order.
+The least upper bound or greatest lower bound of a set of types does not always exist.
+For instance, consider the class definitions:
```scala
class A[+T] {}
@@ -949,11 +940,9 @@ free to pick any one of them.
### Weak Conformance
-In some situations Scala uses a more general conformance relation. A
-type $S$ _weakly conforms_
-to a type $T$, written $S <:_w
-T$, if $S <: T$ or both $S$ and $T$ are primitive number types
-and $S$ precedes $T$ in the following ordering.
+In some situations Scala uses a more general conformance relation.
+A type $S$ _weakly conforms_ to a type $T$, written $S <:_w T$,
+if $S <: T$ or both $S$ and $T$ are primitive number types and $S$ precedes $T$ in the following ordering.
```scala
Byte $<:_w$ Short
@@ -964,15 +953,49 @@ Long $<:_w$ Float
Float $<:_w$ Double
```
-A _weak least upper bound_ is a least upper bound with respect to
-weak conformance.
+A _weak least upper bound_ is a least upper bound with respect to weak conformance.
+
+### Compatibility
+A type $T$ is _compatible_ to a type $U$ if $T$ (or its corresponding function type) [weakly conforms](#weak-conformance) to $U$
+after applying [eta-expansion](06-expressions.html#eta-expansion). If $T$ is a method type, it's converted to the corresponding function type. If the types do not weakly conform, the following alternatives are checked in order:
+ - [view application](07-implicits.html#views): there's an implicit view from $T$ to $U$;
+ - dropping by-name modifiers: if $U$ is of the shape `$=> U'$` (and $T$ is not), `$T <:_w U'$`;
+ - SAM conversion: if $T$ corresponds to a function type, and $U$ declares a single abstract method whose type [corresponds](06-expressions.html#sam-conversion) to the function type $U'$, `$T <:_w U'$`.
+
+<!--- TODO: include other implicit conversions in addition to view application?
+
+ trait Proc { def go(x: Any): Unit }
+
+ def foo(x: Any => Unit): Unit = ???
+ def foo(x: Proc): Unit = ???
+
+ foo((x: Any) => 1) // works when you drop either foo overload since value discarding is applied
+
+-->
+
+#### Examples
+
+##### Function compatibility via SAM conversion
+
+Given the definitions
+
+```scala
+def foo(x: Int => String): Unit
+def foo(x: ToString): Unit
+
+trait ToString { def convert(x: Int): String }
+```
+
+The application `foo((x: Int) => x.toString)` [resolves](06-expressions.html#overloading-resolution) to the first overload,
+as it's more specific:
+ - `Int => String` is compatible to `ToString` -- when expecting a value of type `ToString`, you may pass a function literal from `Int` to `String`, as it will be SAM-converted to said function;
+ - `ToString` is not compatible to `Int => String` -- when expecting a function from `Int` to `String`, you may not pass a `ToString`.
## Volatile Types
-Type volatility approximates the possibility that a type parameter or abstract
-type instance
-of a type does not have any non-null values. A value member of a volatile type
-cannot appear in a [path](#paths).
+Type volatility approximates the possibility that a type parameter or
+abstract type instance of a type does not have any non-null values.
+A value member of a volatile type cannot appear in a [path](#paths).
A type is _volatile_ if it falls into one of four categories: