Skip to content

Commit 7b0fefa

Browse files
committed
Move “Wildcard Types” to a subsection of “Parameterized Types”, and describe them independently of forSome.
1 parent 100f7bf commit 7b0fefa

File tree

1 file changed

+58
-40
lines changed

1 file changed

+58
-40
lines changed

docs/_spec/03-types.md

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@ chapter: 3
88

99
```ebnf
1010
Type ::= FunctionArgTypes ‘=>’ Type
11-
| InfixType [ExistentialClause]
11+
| InfixType
1212
FunctionArgTypes ::= InfixType
1313
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
14-
ExistentialClause ::= ‘forSome’ ‘{’ ExistentialDcl
15-
{semi ExistentialDcl} ‘}’
16-
ExistentialDcl ::= ‘type’ TypeDcl
17-
| ‘val’ ValDcl
1814
InfixType ::= CompoundType {id [nl] CompoundType}
1915
CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement]
2016
| Refinement
@@ -163,13 +159,14 @@ SimpleType ::= SimpleType TypeArgs
163159
TypeArgs ::= ‘[’ Types ‘]’
164160
```
165161

166-
A _parameterized type_ ´T[ T_1, ..., T_n ]´ consists of a type designator ´T´ and type parameters ´T_1, ..., T_n´ where ´n \geq 1´.
162+
A _parameterized type_ ´T[ T_1, ..., T_n ]´ consists of a type designator ´T´ and type arguments ´T_1, ..., T_n´ where ´n \geq 1´.
167163
´T´ must refer to a type constructor which takes ´n´ type parameters ´a_1, ..., a_n´.
168164

165+
<!-- TODO Mention well-kinded conformance when we introduce kind-polymorphism -->
169166
Say the type parameters have lower bounds ´L_1, ..., L_n´ and upper bounds ´U_1, ..., U_n´.
170-
The parameterized type is well-formed if each actual type parameter _conforms to its bounds_, i.e. ´\sigma L_i <: T_i <: \sigma U_i´ where ´\sigma´ is the substitution ´[ a_1 := T_1, ..., a_n := T_n ]´.
167+
The parameterized type is well-formed if each type argument _conforms to its bounds_, i.e. ´\sigma L_i <: T_i <: \sigma U_i´ where ´\sigma´ is the substitution ´[ a_1 := T_1, ..., a_n := T_n ]´.
171168

172-
###### Example Parameterized Types
169+
#### Example Parameterized Types
173170

174171
Given the partial type definitions:
175172

@@ -178,9 +175,9 @@ class TreeMap[A <: Comparable[A], B] { ... }
178175
class List[A] { ... }
179176
class I extends Comparable[I] { ... }
180177

181-
class F[M[_], X] { ... }
178+
class F[M[A], X] { ... }
182179
class S[K <: String] { ... }
183-
class G[M[ Z <: I ], I] { ... }
180+
class G[M[Z <: I], I] { ... }
184181
```
185182

186183
the following parameterized types are well-formed:
@@ -194,9 +191,7 @@ F[List, Int]
194191
G[S, String]
195192
```
196193

197-
###### Example
198-
199-
Given the [above type definitions](#example-parameterized-types), the following types are ill-formed:
194+
and the following types are ill-formed:
200195

201196
```scala
202197
TreeMap[I] // illegal: wrong number of parameters
@@ -211,6 +206,51 @@ G[S, Int] // illegal: S constrains its parameter to
211206
// that conforms to Int
212207
```
213208

209+
#### Wildcard Type Argument
210+
211+
<!-- TODO Update the syntax to use '?' -->
212+
```ebnf
213+
WildcardType ::= ‘_’ TypeBounds
214+
```
215+
216+
A _wildcard type argument_ is of the form `_´\;´>:´\,L\,´<:´\,U´`.
217+
Both bound clauses may be omitted.
218+
If a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed.
219+
If an upper bound clause `<:´\,U´` is missing, `<:´\,´scala.Any` is assumed.
220+
A wildcard type is a shorthand for an existentially quantified type variable, where the existential quantification is implicit.
221+
222+
A wildcard type must appear as a type argument of a parameterized type.
223+
The parameterized type to which the wildcard type is applied cannot be an abstract type constructor.
224+
The wildcard type argument is kind-polymorphic.
225+
226+
Given the [above type definitions](#example-parameterized-types), the following types are well-formed:
227+
228+
```scala
229+
List[_]
230+
List[_ <: java.lang.Number]
231+
S[_ <: String]
232+
F[_, Boolean]
233+
```
234+
235+
and the following code contains an ill-formed type:
236+
237+
```scala
238+
trait H[F[A]]:
239+
def f: F[_] // illegal : an abstract type constructor
240+
// cannot be applied to wildcard arguments.
241+
```
242+
243+
Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types).
244+
Their expansion is then the expansion in the equivalent parameterized type.
245+
246+
##### Simplification Rules
247+
248+
Let ´T[T_1, ..., T_n]´ be a parameterized type.
249+
Then, applying a wildcard type argument ´t´ of the form ´\\_ >: L <: U´ at the ´i´'th position obeys the following equivalences:
250+
251+
- If the type parameter ´T_i´ is declared covariant, then ´t \equiv U´
252+
- If the type parameter ´T_i´ is declared contravariant, then ´t \equiv L´
253+
214254
### Tuple Types
215255

216256
```ebnf
@@ -355,30 +395,6 @@ trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
355395

356396
Their exact supertype and implementation can be consulted in the [function classes section](./12-the-scala-standard-library.md#the-function-classes) of the standard library page in this document.
357397

358-
#### Wildcard Types
359-
360-
```ebnf
361-
WildcardType ::= ‘_’ TypeBounds
362-
```
363-
<!-- TODO: Update this to use new mechanism -->
364-
A _wildcard type_ is of the form `_´\;´>:´\,L\,´<:´\,U´`.
365-
Both bound clauses may be omitted.
366-
If a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed.
367-
If an upper bound clause `<:´\,U´` is missing, `<:´\,´scala.Any` is assumed.
368-
A wildcard type is a shorthand for an existentially quantified type variable, where the existential quantification is implicit.
369-
370-
A wildcard type must appear as a type argument of a parameterized type.
371-
Let ´T = p.c[\mathit{targs},T,\mathit{targs}']´ be a parameterized type where ´\mathit{targs}, \mathit{targs}'´ may be empty and ´T´ is a wildcard type `_´\ ´>:´\,L\,´<:´\,U´`.
372-
Then ´T´ is equivalent to the existential type
373-
374-
```scala
375-
´p.c[\mathit{targs},t,\mathit{targs}']´ forSome { type ´t´ >: ´L´ <: ´U´ }
376-
```
377-
378-
where ´t´ is some fresh type variable.
379-
Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types).
380-
Their expansion is then the expansion in the equivalent parameterized type.
381-
382398
## Non-Value Types
383399

384400
The types explained in the following do not denote sets of values, nor do they appear explicitly in programs.
@@ -563,7 +579,6 @@ Equivalence ´(\equiv)´ between types is the smallest congruence [^congruence]
563579
- corresponding parameters have equivalent types.
564580
Note that the names of parameters do not matter for method type equivalence.
565581
- Two [polymorphic method types](#polymorphic-method-types) are equivalent if they have the same number of type parameters, and, after renaming one set of type parameters by another, the result types as well as lower and upper bounds of corresponding type parameters are equivalent.
566-
- Two [existential types](#existential-types) are equivalent if they have the same number of quantifiers, and, after renaming one list of type quantifiers by another, the quantified types as well as lower and upper bounds of corresponding quantifiers are equivalent.
567582
- Two [type constructors](#type-constructors) are equivalent if they have the same number of type parameters, and, after renaming one list of type parameters by another, the result types as well as variances, lower and upper bounds of corresponding type parameters are equivalent.
568583

569584
[^congruence]: A congruence is an equivalence relation which is closed under formation of contexts.
@@ -573,7 +588,7 @@ Equivalence ´(\equiv)´ between types is the smallest congruence [^congruence]
573588

574589
The conformance relation ´(<:)´ is the smallest transitive relation that satisfies the following conditions.
575590

576-
- Conformance includes equivalence. If `T \equiv U` then `T <: U`.
591+
- Conformance includes equivalence. If ´T \equiv U´ then ´T <: U´.
577592
- For every value type `T`, `scala.Nothing <: ´T´ <: scala.Any`.
578593
- For every type constructor ´T´ (with any number of type parameters), `scala.Nothing <: ´T´ <: scala.Any`.
579594
- For every value type ´T´, `scala.Null <: ´T´` unless `´T´ <: scala.AnyVal`.
@@ -582,10 +597,13 @@ The conformance relation ´(<:)´ is the smallest transitive relation that satis
582597
- A singleton type `´p´.type` conforms to the type of the path ´p´.
583598
- A singleton type `´p´.type` conforms to the type `scala.Singleton`.
584599
- A type projection `´T´#´t´` conforms to `´U´#´t´` if ´T´ conforms to ´U´.
585-
- A parameterized type `´T´[´T_1´, ..., ´T_n´]` conforms to `´T´[´U_1´, ..., ´U_n´]` if the following three conditions hold for ´i \in \{ 1, ..., n \}´:
600+
- A parameterized type `´T´[´T_1´, ..., ´T_n´]` conforms to `´T´[´U_1´, ..., ´U_n´]` if the following conditions hold for ´i \in \{ 1, ..., n \}´:
586601
1. If the ´i´'th type parameter of ´T´ is declared covariant, then ´T_i <: U_i´.
587602
1. If the ´i´'th type parameter of ´T´ is declared contravariant, then ´U_i <: T_i´.
588603
1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant, then ´U_i \equiv T_i´.
604+
1. If ´U_i´ is a wildcard type argument of the form ´\\_ >: L <: U´, then ´T_i >: L´ and ´T_i <: U´.
605+
1. If ´U_i´ is a wildcard type argument of the form ´\\_ >: L_1 <: U_1´ and ´T_i´ is a wildcard argument of the form ´\\_ >: L_2 <: U_2´, then ´L_1 <: L_2´ and ´H_2 <: H_1´.
606+
1. If ´U_i´ is a wildcard type argument of the form ´\\_ >: L <: U´ and the ´i´'th type parameter is declared covariant, then
589607
- A compound type `´T_1´ with ... with ´T_n´ {´R\,´}` conforms to each of its component types ´T_i´.
590608
- If ´T <: U_i´ for ´i \in \{ 1, ..., n \}´ and for every binding ´d´ of a type or value ´x´ in ´R´ there exists a member binding of ´x´ in ´T´ which subsumes ´d´, then ´T´ conforms to the compound type `´U_1´ with ... with ´U_n´ {´R\,´}`.
591609
- If ´T_i \equiv T_i'´ for ´i \in \{ 1, ..., n\}´ and ´U´ conforms to ´U'´ then the method type ´(p_1:T_1, ..., p_n:T_n) U´ conforms to ´(p_1':T_1', ..., p_n':T_n') U'´.

0 commit comments

Comments
 (0)