Skip to content

Commit 3a4e1cc

Browse files
julienrfsjrd
authored andcommitted
Move “Wildcard Types” to a subsection of “Parameterized Types”.
Specify them independently of `forSome`.
1 parent 100f7bf commit 3a4e1cc

File tree

2 files changed

+73
-58
lines changed

2 files changed

+73
-58
lines changed

docs/_spec/03-types.md

Lines changed: 62 additions & 43 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,50 @@ 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+
A wildcard type must appear as a type argument of a parameterized type.
218+
The parameterized type to which the wildcard type is applied cannot be an abstract type constructor.
219+
220+
Both bound clauses may be omitted.
221+
If both bounds are omitted, the real bounds are inferred from the bounds of the corresponding type parameter in the target type constructor.
222+
Otherwise, if a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed.
223+
Otherwise, if an upper bound clause `<:´\,U´` is missing, `<:´\,´scala.Any` is assumed.
224+
225+
Given the [above type definitions](#example-parameterized-types), the following types are well-formed:
226+
227+
```scala
228+
List[_] // inferred as List[_ >: Nothing <: Any]
229+
List[_ <: java.lang.Number]
230+
S[_ <: String]
231+
F[_, Boolean]
232+
```
233+
234+
and the following code contains an ill-formed type:
235+
236+
```scala
237+
trait H[F[A]]:
238+
def f: F[_] // illegal : an abstract type constructor
239+
// cannot be applied to wildcard arguments.
240+
```
241+
242+
Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types).
243+
Their expansion is then the expansion in the equivalent parameterized type.
244+
245+
##### Simplification Rules
246+
247+
Let ´T[T_1, ..., T_n]´ be a parameterized type.
248+
Then, applying a wildcard type argument ´t´ of the form ´\\_ >: L <: U´ at the ´i´'th position obeys the following equivalences:
249+
250+
- If the type parameter ´T_i´ is declared covariant, then ´t \equiv U´
251+
- If the type parameter ´T_i´ is declared contravariant, then ´t \equiv L´
252+
214253
### Tuple Types
215254

216255
```ebnf
@@ -355,30 +394,6 @@ trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
355394

356395
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.
357396

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-
382397
## Non-Value Types
383398

384399
The types explained in the following do not denote sets of values, nor do they appear explicitly in programs.
@@ -563,7 +578,6 @@ Equivalence ´(\equiv)´ between types is the smallest congruence [^congruence]
563578
- corresponding parameters have equivalent types.
564579
Note that the names of parameters do not matter for method type equivalence.
565580
- 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.
567581
- 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.
568582

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

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

576-
- Conformance includes equivalence. If `T \equiv U` then `T <: U`.
590+
- Conformance includes equivalence. If ´T \equiv U´ then ´T <: U´.
577591
- For every value type `T`, `scala.Nothing <: ´T´ <: scala.Any`.
578592
- For every type constructor ´T´ (with any number of type parameters), `scala.Nothing <: ´T´ <: scala.Any`.
579593
- For every value type ´T´, `scala.Null <: ´T´` unless `´T´ <: scala.AnyVal`.
@@ -582,10 +596,13 @@ The conformance relation ´(<:)´ is the smallest transitive relation that satis
582596
- A singleton type `´p´.type` conforms to the type of the path ´p´.
583597
- A singleton type `´p´.type` conforms to the type `scala.Singleton`.
584598
- 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 \}´:
586-
1. If the ´i´'th type parameter of ´T´ is declared covariant, then ´T_i <: U_i´.
587-
1. If the ´i´'th type parameter of ´T´ is declared contravariant, then ´U_i <: T_i´.
588-
1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant, then ´U_i \equiv T_i´.
599+
- 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 \}´:
600+
1. If the ´i´'th type parameter of ´T´ is declared covariant, then ´T_i <: U_i´. [^argisnotwildcard]
601+
1. If the ´i´'th type parameter of ´T´ is declared contravariant, then ´U_i <: T_i´. [^argisnotwildcard]
602+
1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant:
603+
1. If neither ´T_i´ nor ´U_i´ are wildcard type arguments, then ´U_i \equiv T_i´.
604+
1. If ´T_i´ is a wildcard type argument of the form ´\\_ >: L_1 <: U_1´ and ´U_i´ is a wildcard argument of the form ´\\_ >: L_2 <: U_2´, then ´L_2 <: L_1´ and ´H_1 <: H_2´ (i.e., the ´T_i´ "interval" is contained in the ´U_i´ "interval").
605+
1. If ´U_i´ is a wildcard type argument of the form ´\\_ >: L_2 <: U_2´, then ´L_2 <: T_i´ and ´T_i <: U_2´.
589606
- A compound type `´T_1´ with ... with ´T_n´ {´R\,´}` conforms to each of its component types ´T_i´.
590607
- 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\,´}`.
591608
- 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'´.
@@ -598,6 +615,8 @@ Note that this entails that:
598615
- The variance of ´a_i´ must match the variance of ´a'_i´, where covariance matches covariance, contravariance matches contravariance and any variance matches invariance.
599616
- Recursively, these restrictions apply to the corresponding higher-order type parameter clauses of ´a_i´ and ´a'_i´.
600617

618+
[^argisnotwildcard]: In these cases, if `T_i` and/or `U_i` are wildcard type arguments, the [simplification rules](#simplification-rules) for parameterized types allow to reduce them to real types.
619+
601620
A declaration or definition in some compound type of class type ´C´ _subsumes_ another declaration of the same name in some compound type or class type ´C'´, if one of the following holds.
602621

603622
- A value declaration or definition that defines a name ´x´ with type ´T´ subsumes a value or method declaration that defines ´x´ with type ´T'´, provided ´T <: T'´.

docs/_spec/06-expressions.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -460,16 +460,13 @@ The expected type of the final expression ´e´ is the expected type of the bloc
460460
The expected type of all preceding statements is undefined.
461461

462462
<!-- TODO: Rewrite when type avoidance section is done -->
463-
The type of a block `´s_1´; ...; ´s_n´; ´e´` is `´T´ forSome {´\,Q\,´}`, where ´T´ is the type of ´e´ and ´Q´ contains [existential clauses](03-types.html#existential-types) for every value or type name which is free in ´T´ and which is defined locally in one of the statements ´s_1, ..., s_n´.
464-
We say the existential clause _binds_ the occurrence of the value or type name.
465-
Specifically,
463+
The type of a block `´s_1´; ...; ´s_n´; ´e´` is some type ´T´ such that:
466464

467-
- A locally defined type definition `type´\;t = T´` is bound by the existential clause `type´\;t >: T <: T´`.
468-
It is an error if ´t´ carries type parameters.
469-
- A locally defined value definition `val´\;x: T = e´` is bound by the existential clause `val´\;x: T´`.
470-
- A locally defined class definition `class´\;c´ extends´\;t´` is bound by the existential clause `type´\;c <: T´` where ´T´ is the least class type or refinement type which is a proper supertype of the type ´c´.
471-
It is an error if ´c´ carries type parameters.
472-
- A locally defined object definition `object´\;x\;´extends´\;t´` is bound by the existential clause `val´\;x: T´` where ´T´ is the least class type or refinement type which is a proper supertype of the type `´x´.type`.
465+
- ´U <: T´ where ´U´ is the type of ´e´.
466+
- No value or type name is free in ´T´, i.e., ´T´ does not refer to any value or type locally defined in one of the statements ´s_1, ..., s_n´.
467+
- ´T´ is "as small as possible" (this is a soft requirement).
468+
469+
The precise way in which we compute ´T´, called _type avoidance_, is currently not defined in this specification.
473470

474471
Evaluation of the block entails evaluation of its statement sequence, followed by an evaluation of the final expression ´e´, which defines the result of the block.
475472

@@ -1181,12 +1178,11 @@ question: given
11811178
-->
11821179

11831180
- A parameterized method ´m´ of type `(´p_1:T_1, ..., p_n:T_n´)´U´` is _as specific as_ some other member ´m'´ of type ´S´ if ´m'´ is [applicable](#method-applications) to arguments `(´p_1, ..., p_n´)` of types ´T_1, ..., T_n´.
1184-
- A polymorphic method of type `[´a_1´ >: ´L_1´ <: ´U_1, ..., a_n´ >: ´L_n´ <: ´U_n´]´T´` is as specific as some other member of type ´S´ if ´T´ is as specific as ´S´ under the assumption that for ´i = 1, ..., n´ each ´a_i´ is an abstract type name bounded from below by ´L_i´ and from above by ´U_i´.
1185-
- A member of any other type is always as specific as a parameterized method or a polymorphic method.
1186-
<!-- TODO: check the following, as it reduces to "the member of type ´T´ is as specific as the member of type ´U´ if the ´T´ conforms to ´U´." -->
1187-
- Given two members of types ´T´ and ´U´ which are neither parameterized nor polymorphic method types, the member of type ´T´ is as specific as the member of type ´U´ if the existential dual of ´T´ conforms to the existential dual of ´U´.
1188-
Here, the existential dual of a polymorphic type `[´a_1´ >: ´L_1´ <: ´U_1, ..., a_n´ >: ´L_n´ <: ´U_n´]´T´` is `´T´ forSome { type ´a_1´ >: ´L_1´ <: ´U_1´, ..., type ´a_n´ >: ´L_n´ <: ´U_n´}`.
1189-
The existential dual of every other type is the type itself.
1181+
If the last parameter `´p_n´` has a vararg type `´T*´`, then `m` must be applicable to arbitrary numbers of `´T´` parameters (which implies that it must be a varargs method as well).
1182+
- A polymorphic method of type `[´a_1´ >: ´L_1´ <: ´U_1, ..., a_n´ >: ´L_n´ <: ´U_n´]´T´` is as specific as some other member ´m'´ of type ´S´ if ´T´ is as specific as ´S´ under the assumption that for ´i = 1, ..., n´ each ´a_i´ is an abstract type name bounded from below by ´L_i´ and from above by ´U_i´.
1183+
- A member of any other type ´T´ is:
1184+
- always as specific as a parameterized method or a polymorphic method.
1185+
- as specific as a member ´m'´ of any other type ´S´ if ´T´ is [compatible](03-types.html#compatibility) with ´S´.
11901186

11911187
The _relative weight_ of an alternative ´A´ over an alternative ´B´ is a
11921188
number from 0 to 2, defined as the sum of

0 commit comments

Comments
 (0)