Skip to content

Commit 135eab0

Browse files
committed
Apply existential-types.md
1 parent f552c88 commit 135eab0

File tree

5 files changed

+29
-123
lines changed

5 files changed

+29
-123
lines changed

docs/_spec/03-types.md

Lines changed: 5 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -349,50 +349,12 @@ trait Function´_n´[-´T_1´, ..., -´T_n´, +´U´] {
349349

350350
Hence, function types are [covariant](04-basic-declarations-and-definitions.html#variance-annotations) in their result type and contravariant in their argument types.
351351

352-
### Existential Types
353-
354-
```ebnf
355-
Type ::= InfixType ExistentialClauses
356-
ExistentialClauses ::= ‘forSome’ ‘{’ ExistentialDcl
357-
{semi ExistentialDcl} ‘}’
358-
ExistentialDcl ::= ‘type’ TypeDcl
359-
| ‘val’ ValDcl
360-
```
361-
362-
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).
363-
364-
Let ´t_1[\mathit{tps}\_1] >: L_1 <: U_1 , \ldots , t_n[\mathit{tps}\_n] >: L_n <: U_n´ be the types declared in ´Q´ (any of the type parameter sections `[ ´\mathit{tps}_i´ ]` might be missing).
365-
The scope of each type ´t_i´ includes the type ´T´ and the existential clause ´Q´.
366-
The type variables ´t_i´ are said to be _bound_ in the type `´T´ forSome { ´Q´ }`.
367-
Type variables which occur in a type ´T´ but which are not bound in ´T´ are said to be _free_ in ´T´.
368-
369-
A _type instance_ of `´T´ forSome { ´Q´ }` is a type ´\sigma T´ where ´\sigma´ is a substitution over ´t_1 , \ldots , t_n´ such that, for each ´i´, ´\sigma L_i <: \sigma t_i <: \sigma U_i´.
370-
The set of values denoted by the existential type `´T´ forSome {´\,Q\,´}` is the union of the set of values of all its type instances.
371-
372-
A _skolemization_ of `´T´ forSome { ´Q´ }` is a type instance ´\sigma T´, where ´\sigma´ is the substitution ´[t_1'/t_1 , \ldots , t_n'/t_n]´ and each ´t_i'´ is a fresh abstract type with lower bound ´\sigma L_i´ and upper bound ´\sigma U_i´.
373-
374-
#### Simplification Rules
375-
376-
Existential types obey the following four equivalences:
377-
378-
1. Multiple for-clauses in an existential type can be merged. E.g., `´T´ forSome { ´Q´ } forSome { ´Q'´ }` is equivalent to `´T´ forSome { ´Q´ ; ´Q'´}`.
379-
1. Unused quantifications can be dropped.
380-
E.g., `´T´ forSome { ´Q´ ; ´Q'´}` where none of the types defined in ´Q'´ are referred to by ´T´ or ´Q´, is equivalent to `´T´ forSome {´ Q ´}`.
381-
1. An empty quantification can be dropped. E.g., `´T´ forSome { }` is equivalent to ´T´.
382-
1. An existential type `´T´ forSome { ´Q´ }` where ´Q´ contains a clause `type ´t[\mathit{tps}] >: L <: U´` is equivalent to the type `´T'´ forSome { ´Q´ }` where ´T'´ results from ´T´ by replacing every [covariant occurrence](04-basic-declarations-and-definitions.html#variance-annotations) of ´t´ in ´T´ by ´U´ and by replacing every contravariant occurrence of ´t´ in ´T´ by ´L´.
383-
384-
#### Existential Quantification over Values
385-
386-
As a syntactic convenience, the bindings clause in an existential type may also contain value declarations `val ´x´: ´T´`.
387-
An existential type `´T´ forSome { ´Q´; val ´x´: ´S\,´;´\,Q'´ }` is treated as a shorthand for the type `´T'´ forSome { ´Q´; type ´t´ <: ´S´ with Singleton; ´Q'´ }`, where ´t´ is a fresh type name and ´T'´ results from ´T´ by replacing every occurrence of `´x´.type` with ´t´.
388-
389-
#### Placeholder Syntax for Existential Types
352+
#### Wildcard Types
390353

391354
```ebnf
392355
WildcardType ::= ‘_’ TypeBounds
393356
```
394-
395-
Scala supports a placeholder syntax for existential types.
357+
<!-- TODO: Update this to use new mechanism -->
396358
A _wildcard type_ is of the form `_´\;´>:´\,L\,´<:´\,U´`.
397359
Both bound clauses may be omitted.
398360
If a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed.
@@ -411,60 +373,6 @@ where ´t´ is some fresh type variable.
411373
Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types).
412374
Their expansion is then the expansion in the equivalent parameterized type.
413375

414-
###### Example
415-
416-
Assume the class definitions
417-
418-
```scala
419-
class Ref[T]
420-
abstract class Outer { type T }
421-
```
422-
423-
Here are some examples of existential types:
424-
425-
```scala
426-
Ref[T] forSome { type T <: java.lang.Number }
427-
Ref[x.T] forSome { val x: Outer }
428-
Ref[x_type # T] forSome { type x_type <: Outer with Singleton }
429-
```
430-
431-
The last two types in this list are equivalent.
432-
An alternative formulation of the first type above using wildcard syntax is:
433-
434-
```scala
435-
Ref[_ <: java.lang.Number]
436-
```
437-
438-
###### Example
439-
440-
The type `List[List[_]]` is equivalent to the existential type
441-
442-
```scala
443-
List[List[t] forSome { type t }]
444-
```
445-
446-
###### Example
447-
448-
Assume a covariant type
449-
450-
```scala
451-
class List[+T]
452-
```
453-
454-
The type
455-
456-
```scala
457-
List[T] forSome { type T <: java.lang.Number }
458-
```
459-
460-
is equivalent (by simplification rule 4 above) to
461-
462-
```scala
463-
List[java.lang.Number] forSome { type T <: java.lang.Number }
464-
```
465-
466-
which is in turn equivalent (by simplification rules 2 and 3 above) to `List[java.lang.Number]`.
467-
468376
## Non-Value Types
469377

470378
The types explained in the following do not denote sets of values, nor do they appear explicitly in programs.
@@ -599,18 +507,15 @@ These notions are defined mutually recursively as follows.
599507
If ´T´ is an alias or abstract type, the previous clauses apply.
600508
Otherwise, ´T´ must be a (possibly parameterized) class type, which is defined in some class ´B´.
601509
Then the base types of `´S´#´T´` are the base types of ´T´ in ´B´ seen from the prefix type ´S´.
602-
- The base types of an existential type `´T´ forSome { ´Q´ }` are all types `´S´ forSome { ´Q´ }` where ´S´ is a base type of ´T´.
603510

604511
1. The notion of a type ´T´ _in class ´C´ seen from some prefix type ´S´_ makes sense only if the prefix type ´S´ has a type instance of class ´C´ as a base type, say `´S'´#´C´[´T_1, ..., T_n´]`.
605512
Then we define as follows.
606513
- If `´S´ = ´\epsilon´.type`, then ´T´ in ´C´ seen from ´S´ is ´T´ itself.
607-
- Otherwise, if ´S´ is an existential type `´S'´ forSome { ´Q´ }`, and ´T´ in ´C´ seen from ´S'´ is ´T'´, then ´T´ in ´C´ seen from ´S´ is `´T'´ forSome {´\,Q\,´}`.
608514
- Otherwise, if ´T´ is the ´i´'th type parameter of some class ´D´, then
609515
- If ´S´ has a base type `´D´[´U_1, ..., U_n´]`, for some type parameters `[´U_1, ..., U_n´]`, then ´T´ in ´C´ seen from ´S´ is ´U_i´.
610516
- Otherwise, if ´C´ is defined in a class ´C'´, then ´T´ in ´C´ seen from ´S´ is the same as ´T´ in ´C'´ seen from ´S'´.
611517
- Otherwise, if ´C´ is not defined in another class, then ´T´ in ´C´ seen from ´S´ is ´T´ itself.
612-
- Otherwise, if ´T´ is the singleton type `´D´.this.type` for some class ´D´
613-
then
518+
- Otherwise, if ´T´ is the singleton type `´D´.this.type` for some class ´D´ then
614519
- If ´D´ is a subclass of ´C´ and ´S´ has a type instance of class ´D´ among its base types, then ´T´ in ´C´ seen from ´S´ is ´S´.
615520
- Otherwise, if ´C´ is defined in a class ´C'´, then ´T´ in ´C´ seen from ´S´ is the same as ´T´ in ´C'´ seen from ´S'´.
616521
- Otherwise, if ´C´ is not defined in another class, then ´T´ in ´C´ seen from ´S´ is ´T´ itself.
@@ -676,11 +581,10 @@ The conformance relation ´(<:)´ is the smallest transitive relation that satis
676581
1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant, then ´U_i \equiv T_i´.
677582
- A compound type `´T_1´ with ... with ´T_n´ {´R\,´}` conforms to each of its component types ´T_i´.
678583
- 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\,´}`.
679-
- The existential type `´T´ forSome {´\,Q\,´}` conforms to ´U´ if its [skolemization](#existential-types) conforms to ´U´.
680-
- The type ´T´ conforms to the existential type `´U´ forSome {´\,Q\,´}` if ´T´ conforms to one of the [type instances](#existential-types) of `´U´ forSome {´\,Q\,´}`.
681584
- 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'´.
682585
- The polymorphic type ´[a_1 >: L_1 <: U_1, ..., a_n >: L_n <: U_n] T´ conforms to the polymorphic type ´[a_1 >: L_1' <: U_1', ..., a_n >: L_n' <: U_n'] T'´ if, assuming ´L_1' <: a_1 <: U_1', ..., L_n' <: a_n <: U_n'´ one has ´T <: T'´ and ´L_i <: L_i'´ and ´U_i' <: U_i´ for ´i \in \{ 1, ..., n \}´.
683-
- Type constructors ´T´ and ´T'´ follow a similar discipline. We characterize ´T´ and ´T'´ by their type parameter clauses ´[a_1, ..., a_n]´ and ´[a_1', ..., a_n']´, where an ´a_i´ or ´a_i'´ may include a variance annotation, a higher-order type parameter clause, and bounds.
586+
- Type constructors ´T´ and ´T'´ follow a similar discipline.
587+
We characterize ´T´ and ´T'´ by their type parameter clauses ´[a_1, ..., a_n]´ and ´[a_1', ..., a_n']´, where an ´a_i´ or ´a_i'´ may include a variance annotation, a higher-order type parameter clause, and bounds.
684588
Then, ´T´ conforms to ´T'´ if any list ´[t_1, ..., t_n]´ -- with declared variances, bounds and higher-order type parameter clauses -- of valid type arguments for ´T'´ is also a valid list of type arguments for ´T´ and ´T[t_1, ..., t_n] <: T'[t_1, ..., t_n]´.
685589
Note that this entails that:
686590
- The bounds on ´a_i´ must be weaker than the corresponding bounds declared for ´a'_i´.
@@ -790,8 +694,6 @@ A type designator is volatile if it is an alias of a volatile type, or if it des
790694

791695
A singleton type `´p´.type` is volatile, if the underlying type of path ´p´ is volatile.
792696

793-
An existential type `´T´ forSome {´\,Q\,´}` is volatile if ´T´ is volatile.
794-
795697
## Type Erasure
796698

797699
A type is called _generic_ if it contains type arguments or type variables.
@@ -806,7 +708,6 @@ The erasure mapping is defined as follows.
806708
- The erasure of a singleton type `´p´.type` is the erasure of the type of ´p´.
807709
- The erasure of a type projection `´T´#´x´` is `|´T´|#´x´`.
808710
- The erasure of a compound type `´T_1´ with ... with ´T_n´ {´R\,´}` is the erasure of the intersection dominator of ´T_1, ..., T_n´.
809-
- The erasure of an existential type `´T´ forSome {´\,Q\,´}` is ´|T|´.
810711

811712
The _intersection dominator_ of a list of types ´T_1, ..., T_n´ is computed as follows.
812713
Let ´T_{i_1}, ..., T_{i_m}´ be the subsequence of types ´T_i´ which are not supertypes of some other type ´T_j´.

docs/_spec/06-expressions.md

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ When we write "expression ´e´ is expected to conform to type ´T´", we mean:
5959
The following skolemization rule is applied universally for every expression:
6060
If the type of an expression would be an existential type ´T´, then the type of the expression is assumed instead to be a [skolemization](03-types.html#existential-types) of ´T´.
6161

62+
<!-- TODO: Replace by description of Scala 3 skolemization -->
6263
Skolemization is reversed by type packing.
6364
Assume an expression ´e´ of type ´T´ and let ´t_1[\mathit{tps}\_1] >: L_1 <: U_1, ..., t_n[\mathit{tps}\_n] >: L_n <: U_n´ be all the type variables created by skolemization of some part of ´e´ which are free in ´T´.
6465
Then the _packed type_ of ´e´ is
@@ -454,6 +455,7 @@ The final expression can be omitted, in which case the unit value `()` is assume
454455
The expected type of the final expression ´e´ is the expected type of the block.
455456
The expected type of all preceding statements is undefined.
456457

458+
<!-- TODO: Rewrite when type avoidance section is done -->
457459
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´.
458460
We say the existential clause _binds_ the occurrence of the value or type name.
459461
Specifically,
@@ -467,23 +469,7 @@ It is an error if ´c´ carries type parameters.
467469

468470
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.
469471

470-
A block expression `{´c_1´; ...; ´c_n´}` where ´s_1, ..., s_n´ are case clauses forms a [pattern matching anonymous function](08-pattern-matching.html#pattern-matching-anonymous-functions).
471-
472-
###### Example
473-
Assuming a class `Ref[T](x: T)`, the block
474-
475-
```scala
476-
{ class C extends B\ldots´} ; new Ref(new C) }
477-
```
478-
479-
has the type `Ref[_1] forSome { type _1 <: B }`.
480-
The block
481-
482-
```scala
483-
{ class C extends B\ldots´} ; new C }
484-
```
485-
486-
simply has type `B`, because with the rules [here](03-types.html#simplification-rules) the existentially quantified type `_1 forSome { type _1 <: B }` can be simplified to `B`.
472+
A block expression `{´c_1´; ...; ´c_n´}` where ´c_1, ..., c_n´ are case clauses forms a [pattern matching anonymous function](08-pattern-matching.html#pattern-matching-anonymous-functions).
487473

488474
## Prefix, Infix, and Postfix Operations
489475

@@ -1190,6 +1176,7 @@ question: given
11901176
- 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´.
11911177
- 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´.
11921178
- A member of any other type is always as specific as a parameterized method or a polymorphic method.
1179+
<!-- 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´." -->
11931180
- 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´.
11941181
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´}`.
11951182
The existential dual of every other type is the type itself.

docs/_spec/07-implicits.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ If there are no eligible identifiers under this rule, then, second, eligible are
5454

5555
The _implicit scope_ of a type ´T´ consists of all [companion modules](05-classes-and-objects.html#object-definitions) of classes that are associated with the implicit parameter's type.
5656
Here, we say a class ´C´ is _associated_ with a type ´T´ if it is a [base class](05-classes-and-objects.html#class-linearization) of some part of ´T´.
57-
57+
<!-- TODO: Check if this is still accurate -->
5858
The _parts_ of a type ´T´ are:
5959

6060
- if ´T´ is a compound type `´T_1´ with ... with ´T_n´`, the union of the parts of ´T_1, ..., T_n´, as well as ´T´ itself;
@@ -64,7 +64,6 @@ The _parts_ of a type ´T´ are:
6464
- if ´T´ is a type alias, the parts of its expansion;
6565
- if ´T´ is an abstract type, the parts of its upper bound;
6666
- if ´T´ denotes an implicit conversion to a type with a method with argument types ´T_1, ..., T_n´ and result type ´U´, the union of the parts of ´T_1, ..., T_n´ and ´U´;
67-
- the parts of quantified (existential or universal) and annotated types are defined as the parts of the underlying types (e.g., the parts of `T forSome { ... }` are the parts of `T`);
6867
- in all other cases, just ´T´ itself.
6968

7069
Note that packages are internally represented as classes with companion modules to hold the package members.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
### Existential Types
3+
4+
Existential types using `forSome` (as in [SLS §3.2.12](https://www.scala-lang.org/files/archive/spec/2.13/03-types.html#existential-types)) are not available in Scala 3.
5+
Therefore when reading an existential type from Scala 2, the following happens:
6+
7+
Existential types that can be expressed using only wildcards (but not
8+
`forSome`) are treated as refined types.
9+
For instance, the type
10+
```scala
11+
Map[_ <: AnyRef, Int]
12+
```
13+
is treated as the type `Map`, where the first type parameter
14+
is upper-bounded by `AnyRef` and the second type parameter is an alias
15+
of `Int`.
16+
17+
When reading class files compiled with Scala 2, Scala 3 will do a best
18+
effort to approximate existential types with its own types. It will
19+
issue a warning that a precise emulation is not possible.

0 commit comments

Comments
 (0)