From 1ca9e8f96f08eec8a837a691c8afb418fceae5da Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 14:19:46 +0200 Subject: [PATCH 01/19] Apply delayed-init.md --- docs/_spec/05-classes-and-objects.md | 10 ---------- .../dropped-features/delayed-init.md | 0 2 files changed, 10 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/delayed-init.md (100%) diff --git a/docs/_spec/05-classes-and-objects.md b/docs/_spec/05-classes-and-objects.md index c40bd49cae16..c6cb1dc113de 100644 --- a/docs/_spec/05-classes-and-objects.md +++ b/docs/_spec/05-classes-and-objects.md @@ -96,16 +96,6 @@ If this is not a template of a trait, then its _evaluation_ consists of the foll Mixin-evaluation happens in reverse order of occurrence in the linearization. - Finally, the statement sequence ´\mathit{stats}\,´ is evaluated. -###### Delayed Initialization -This statement sequence constitutes the initialization code for an object or class after the superclass constructor invocation and the mixin-evaluation of the template's base classes as described above. -Normally, this code is passed to a special hook, inaccessible to user code, which simply executes it. - -However, in objects and classes (but not traits) which extend `scala.DelayedInit`, the initialization code is passed to a `delayedInit` method which can be overridden to implement arbitrary semantics. - -```scala -def delayedInit(body: => Unit): Unit -``` - ### Constructor Invocations ```ebnf diff --git a/docs/_spec/TODOreference/dropped-features/delayed-init.md b/docs/_spec/APPLIEDreference/dropped-features/delayed-init.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/delayed-init.md rename to docs/_spec/APPLIEDreference/dropped-features/delayed-init.md From eb2a02133eff6c54699c33b35870815c5c5170cd Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 14:25:31 +0200 Subject: [PATCH 02/19] Apply do-while.md --- docs/_spec/06-expressions.md | 10 ---------- .../dropped-features/do-while.md | 0 2 files changed, 10 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/do-while.md (100%) diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index 92697e64f0ac..c2c4d1f56afa 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -12,7 +12,6 @@ Expr ::= (Bindings | id | ‘_’) ‘=>’ Expr Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr] | ‘while’ ‘(’ Expr ‘)’ {nl} Expr | ‘try’ Expr [‘catch’ Expr] [‘finally’ Expr] - | ‘do’ Expr [semi] ‘while’ ‘(’ Expr ‘)’ | ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’) {nl} [‘yield’] Expr | ‘throw’ Expr | ‘return’ [Expr] @@ -717,15 +716,6 @@ def whileLoop(cond: => Boolean)(body: => Unit): Unit = if (cond) { body ; whileLoop(cond)(body) } else {} ``` -## Do Loop Expressions - -```ebnf -Expr1 ::= ‘do’ Expr [semi] ‘while’ ‘(’ Expr ‘)’ -``` - -The _do loop expression_ `do ´e_1´ while (´e_2´)` is typed and evaluated as if it was the expression `(´e_1´ ; while (´e_2´) ´e_1´)`. -A semicolon preceding the `while` symbol of a do loop expression is ignored. - ## For Comprehensions and For Loops ```ebnf diff --git a/docs/_spec/TODOreference/dropped-features/do-while.md b/docs/_spec/APPLIEDreference/dropped-features/do-while.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/do-while.md rename to docs/_spec/APPLIEDreference/dropped-features/do-while.md From 3ab8ae822f845d04ff9b45e977471a3715921e74 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 14:25:59 +0200 Subject: [PATCH 03/19] Cleanup --- .../dropped-features/dropped-features.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/dropped-features.md (100%) diff --git a/docs/_spec/TODOreference/dropped-features/dropped-features.md b/docs/_spec/APPLIEDreference/dropped-features/dropped-features.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/dropped-features.md rename to docs/_spec/APPLIEDreference/dropped-features/dropped-features.md From 1ab9d9bfda87492f0ac642b120276dbd975c8d9b Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 14:33:47 +0200 Subject: [PATCH 04/19] Apply early-initializers.md --- docs/_spec/05-classes-and-objects.md | 53 +------------------ .../dropped-features/early-initializers.md | 0 2 files changed, 1 insertion(+), 52 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/early-initializers.md (100%) diff --git a/docs/_spec/05-classes-and-objects.md b/docs/_spec/05-classes-and-objects.md index c6cb1dc113de..b73a4aa56071 100644 --- a/docs/_spec/05-classes-and-objects.md +++ b/docs/_spec/05-classes-and-objects.md @@ -295,57 +295,6 @@ It is a static error if the inheritance closure of a class type consists of an i [^kennedy]: Kennedy, Pierce. [On Decidability of Nominal Subtyping with Variance.]( https://research.microsoft.com/pubs/64041/fool2007.pdf) in FOOL 2007 -### Early Definitions - -```ebnf -EarlyDefs ::= ‘{’ [EarlyDef {semi EarlyDef}] ‘}’ ‘with’ -EarlyDef ::= {Annotation} {Modifier} PatVarDef -``` - -A template may start with an _early field definition_ clause, which serves to define certain field values before the supertype constructor is called. -In a template - -```scala -{ val ´p_1´: ´T_1´ = ´e_1´ - ... - val ´p_n´: ´T_n´ = ´e_n´ -} with ´sc´ with ´mt_1´ with ´mt_n´ { ´\mathit{stats}´ } -``` - -The initial pattern definitions of ´p_1 , \ldots , p_n´ are called _early definitions_. -They define fields which form part of the template. -Every early definition must define at least one variable. - -An early definition is type-checked and evaluated in the scope which is in effect just before the template being defined, augmented by any type parameters of the enclosing class and by any early definitions preceding the one being defined. -In particular, any reference to `this` in an early definition refers to the identity of `this` just outside the template. -Consequently, it is impossible for an early definition to refer to the object being constructed by the template, or to refer to one of its fields and methods, except for any other preceding early definition in the same section. -Furthermore, references to preceding early definitions always refer to the value that's defined there and do not take into account overriding definitions. -In other words, a block of early definitions is evaluated exactly as if it were a local block containing a number of value definitions. - -Early definitions are evaluated before the superclass constructor of the template is called, in the order they are defined. - -###### Example -Early definitions are particularly useful for traits, which do not have normal constructor parameters. -Example: - -```scala -trait Greeting { - val name: String - val msg = "How are you, "+name -} -class C extends { - val name = "Bob" -} with Greeting { - println(msg) -} -``` - -In the code above, the field `name` is initialized before the constructor of `Greeting` is called. -Therefore, field `msg` in class `Greeting` is properly initialized to `"How are you, Bob"`. - -If `name` had been initialized instead in `C`'s normal class body, it would be initialized after the constructor of `Greeting`. -In that case, `msg` would be initialized to `"How are you, "`. - ## Modifiers ```ebnf @@ -592,7 +541,7 @@ A constructor expression is either a self constructor invocation `this(´\mathit The self constructor invocation must construct a generic instance of the class. I.e. if the class in question has name ´C´ and type parameters `[´\mathit{tps}\,´]`, then a self constructor invocation must generate an instance of `´C´[´\mathit{tps}\,´]`; it is not permitted to instantiate formal type parameters. -The signature and the self constructor invocation of a constructor definition are type-checked and evaluated in the scope which is in effect at the point of the enclosing class definition, augmented by any type parameters of the enclosing class and by any [early definitions](#early-definitions) of the enclosing template. +The signature and the self constructor invocation of a constructor definition are type-checked and evaluated in the scope which is in effect at the point of the enclosing class definition, augmented by any type parameters of the enclosing class. The rest of the constructor expression is type-checked and evaluated as a method body in the current class. If there are auxiliary constructors of a class ´C´, they form together with ´C´'s primary [constructor](#class-definitions) an overloaded constructor definition. diff --git a/docs/_spec/TODOreference/dropped-features/early-initializers.md b/docs/_spec/APPLIEDreference/dropped-features/early-initializers.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/early-initializers.md rename to docs/_spec/APPLIEDreference/dropped-features/early-initializers.md From 1578032e99e0fb6133a80913072ef26f25c8d163 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 15:22:55 +0200 Subject: [PATCH 05/19] Apply existential-types.md --- docs/_spec/03-types.md | 109 +----------------- docs/_spec/06-expressions.md | 21 +--- docs/_spec/07-implicits.md | 3 +- docs/_spec/A2-scala-2-compatibility.md | 19 +++ .../dropped-features/existential-types.md | 0 5 files changed, 29 insertions(+), 123 deletions(-) create mode 100644 docs/_spec/A2-scala-2-compatibility.md rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/existential-types.md (100%) diff --git a/docs/_spec/03-types.md b/docs/_spec/03-types.md index 42157b176888..29427bafbfce 100644 --- a/docs/_spec/03-types.md +++ b/docs/_spec/03-types.md @@ -349,50 +349,12 @@ trait Function´_n´[-´T_1´, ..., -´T_n´, +´U´] { Hence, function types are [covariant](04-basic-declarations-and-definitions.html#variance-annotations) in their result type and contravariant in their argument types. -### Existential Types - -```ebnf -Type ::= InfixType ExistentialClauses -ExistentialClauses ::= ‘forSome’ ‘{’ ExistentialDcl - {semi ExistentialDcl} ‘}’ -ExistentialDcl ::= ‘type’ TypeDcl - | ‘val’ ValDcl -``` - -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). - -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). -The scope of each type ´t_i´ includes the type ´T´ and the existential clause ´Q´. -The type variables ´t_i´ are said to be _bound_ in the type `´T´ forSome { ´Q´ }`. -Type variables which occur in a type ´T´ but which are not bound in ´T´ are said to be _free_ in ´T´. - -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´. -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. - -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´. - -#### Simplification Rules - -Existential types obey the following four equivalences: - -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'´}`. -1. Unused quantifications can be dropped. -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 ´}`. -1. An empty quantification can be dropped. E.g., `´T´ forSome { }` is equivalent to ´T´. -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´. - -#### Existential Quantification over Values - -As a syntactic convenience, the bindings clause in an existential type may also contain value declarations `val ´x´: ´T´`. -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´. - -#### Placeholder Syntax for Existential Types +#### Wildcard Types ```ebnf WildcardType ::= ‘_’ TypeBounds ``` - -Scala supports a placeholder syntax for existential types. + A _wildcard type_ is of the form `_´\;´>:´\,L\,´<:´\,U´`. Both bound clauses may be omitted. If a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed. @@ -411,60 +373,6 @@ where ´t´ is some fresh type variable. Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types). Their expansion is then the expansion in the equivalent parameterized type. -###### Example - -Assume the class definitions - -```scala -class Ref[T] -abstract class Outer { type T } -``` - -Here are some examples of existential types: - -```scala -Ref[T] forSome { type T <: java.lang.Number } -Ref[x.T] forSome { val x: Outer } -Ref[x_type # T] forSome { type x_type <: Outer with Singleton } -``` - -The last two types in this list are equivalent. -An alternative formulation of the first type above using wildcard syntax is: - -```scala -Ref[_ <: java.lang.Number] -``` - -###### Example - -The type `List[List[_]]` is equivalent to the existential type - -```scala -List[List[t] forSome { type t }] -``` - -###### Example - -Assume a covariant type - -```scala -class List[+T] -``` - -The type - -```scala -List[T] forSome { type T <: java.lang.Number } -``` - -is equivalent (by simplification rule 4 above) to - -```scala -List[java.lang.Number] forSome { type T <: java.lang.Number } -``` - -which is in turn equivalent (by simplification rules 2 and 3 above) to `List[java.lang.Number]`. - ## Non-Value Types 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. If ´T´ is an alias or abstract type, the previous clauses apply. Otherwise, ´T´ must be a (possibly parameterized) class type, which is defined in some class ´B´. Then the base types of `´S´#´T´` are the base types of ´T´ in ´B´ seen from the prefix type ´S´. - - The base types of an existential type `´T´ forSome { ´Q´ }` are all types `´S´ forSome { ´Q´ }` where ´S´ is a base type of ´T´. 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´]`. Then we define as follows. - If `´S´ = ´\epsilon´.type`, then ´T´ in ´C´ seen from ´S´ is ´T´ itself. - - 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\,´}`. - Otherwise, if ´T´ is the ´i´'th type parameter of some class ´D´, then - 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´. - 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'´. - Otherwise, if ´C´ is not defined in another class, then ´T´ in ´C´ seen from ´S´ is ´T´ itself. - - Otherwise, if ´T´ is the singleton type `´D´.this.type` for some class ´D´ - then + - Otherwise, if ´T´ is the singleton type `´D´.this.type` for some class ´D´ then - 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´. - 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'´. - 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 1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant, then ´U_i \equiv T_i´. - A compound type `´T_1´ with ... with ´T_n´ {´R\,´}` conforms to each of its component types ´T_i´. - 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\,´}`. -- The existential type `´T´ forSome {´\,Q\,´}` conforms to ´U´ if its [skolemization](#existential-types) conforms to ´U´. -- 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\,´}`. - 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'´. - 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 \}´. -- 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. +- 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. 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]´. Note that this entails that: - 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 A singleton type `´p´.type` is volatile, if the underlying type of path ´p´ is volatile. -An existential type `´T´ forSome {´\,Q\,´}` is volatile if ´T´ is volatile. - ## Type Erasure A type is called _generic_ if it contains type arguments or type variables. @@ -806,7 +708,6 @@ The erasure mapping is defined as follows. - The erasure of a singleton type `´p´.type` is the erasure of the type of ´p´. - The erasure of a type projection `´T´#´x´` is `|´T´|#´x´`. - 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´. -- The erasure of an existential type `´T´ forSome {´\,Q\,´}` is ´|T|´. The _intersection dominator_ of a list of types ´T_1, ..., T_n´ is computed as follows. Let ´T_{i_1}, ..., T_{i_m}´ be the subsequence of types ´T_i´ which are not supertypes of some other type ´T_j´. diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index c2c4d1f56afa..3b39dec25829 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -59,6 +59,7 @@ When we write "expression ´e´ is expected to conform to type ´T´", we mean: The following skolemization rule is applied universally for every expression: 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´. + Skolemization is reversed by type packing. 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´. 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 The expected type of the final expression ´e´ is the expected type of the block. The expected type of all preceding statements is undefined. + 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´. We say the existential clause _binds_ the occurrence of the value or type name. Specifically, @@ -467,23 +469,7 @@ It is an error if ´c´ carries type parameters. 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. -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). - -###### Example -Assuming a class `Ref[T](x: T)`, the block - -```scala -{ class C extends B {´\ldots´} ; new Ref(new C) } -``` - -has the type `Ref[_1] forSome { type _1 <: B }`. -The block - -```scala -{ class C extends B {´\ldots´} ; new C } -``` - -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`. +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). ## Prefix, Infix, and Postfix Operations @@ -1190,6 +1176,7 @@ question: given - 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´. - 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´. - A member of any other type is always as specific as a parameterized method or a polymorphic method. + - 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´. 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´}`. The existential dual of every other type is the type itself. diff --git a/docs/_spec/07-implicits.md b/docs/_spec/07-implicits.md index a0db9dd9b418..85aaadda87e1 100644 --- a/docs/_spec/07-implicits.md +++ b/docs/_spec/07-implicits.md @@ -54,7 +54,7 @@ If there are no eligible identifiers under this rule, then, second, eligible are 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. 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´. - + The _parts_ of a type ´T´ are: - 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: - if ´T´ is a type alias, the parts of its expansion; - if ´T´ is an abstract type, the parts of its upper bound; - 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´; -- 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`); - in all other cases, just ´T´ itself. Note that packages are internally represented as classes with companion modules to hold the package members. diff --git a/docs/_spec/A2-scala-2-compatibility.md b/docs/_spec/A2-scala-2-compatibility.md new file mode 100644 index 000000000000..f4a4970cb81a --- /dev/null +++ b/docs/_spec/A2-scala-2-compatibility.md @@ -0,0 +1,19 @@ + +### Existential Types + +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. +Therefore when reading an existential type from Scala 2, the following happens: + +Existential types that can be expressed using only wildcards (but not +`forSome`) are treated as refined types. +For instance, the type +```scala +Map[_ <: AnyRef, Int] +``` +is treated as the type `Map`, where the first type parameter +is upper-bounded by `AnyRef` and the second type parameter is an alias +of `Int`. + +When reading class files compiled with Scala 2, Scala 3 will do a best +effort to approximate existential types with its own types. It will +issue a warning that a precise emulation is not possible. \ No newline at end of file diff --git a/docs/_spec/TODOreference/dropped-features/existential-types.md b/docs/_spec/APPLIEDreference/dropped-features/existential-types.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/existential-types.md rename to docs/_spec/APPLIEDreference/dropped-features/existential-types.md From 4ef7f6047a65179d0b6baa7c65969048c385c478 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 12 Oct 2022 17:11:27 +0200 Subject: [PATCH 06/19] Add TODOs for later, Cleanup --- docs/_spec/03-types.md | 16 ++------ .../04-basic-declarations-and-definitions.md | 40 +------------------ 2 files changed, 4 insertions(+), 52 deletions(-) diff --git a/docs/_spec/03-types.md b/docs/_spec/03-types.md index 29427bafbfce..95da81d19850 100644 --- a/docs/_spec/03-types.md +++ b/docs/_spec/03-types.md @@ -63,7 +63,7 @@ StableId ::= id | [id ‘.’] ‘super’ [ClassQualifier] ‘.’ id ClassQualifier ::= ‘[’ id ‘]’ ``` - + Paths are not types themselves, but they can be a part of named types and in that function form a central role in Scala's type system. A path is one of the following. @@ -388,6 +388,7 @@ Method types associate to the right: ´(\mathit{Ps}\_1)(\mathit{Ps}\_2)U´ is tr A special case are types of methods without any parameters. They are written here `=> T`. Parameterless methods name expressions that are re-evaluated each time the parameterless method name is referenced. + Method types do not exist as types of values. If a method name is used as a value, its type is [implicitly converted](06-expressions.html#implicit-conversions) to a corresponding function type. @@ -642,20 +643,9 @@ A _weak least upper bound_ is a least upper bound with respect to weak conforman 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'´`. - - +- [implicit conversion](07-implicits.html#views): there's an implicit conversion from ´T´ to ´U´ in scope; #### Examples diff --git a/docs/_spec/04-basic-declarations-and-definitions.md b/docs/_spec/04-basic-declarations-and-definitions.md index af98eef2a37d..a4f5b6d307c2 100644 --- a/docs/_spec/04-basic-declarations-and-definitions.md +++ b/docs/_spec/04-basic-declarations-and-definitions.md @@ -40,53 +40,15 @@ by commas. These are expanded according to the following scheme: \VAL;x, y: T = e && \VAL; x: T = e \\ && \VAL; y: T = x \\[0.5em] -\LET;x, y: T = e && \LET; x: T = e \\ - && \VAL; y: T = x \\[0.5em] - -\DEF;x, y (ps): T = e &\tab\mbox{expands to}\tab& \DEF; x(ps): T = e \\ - && \DEF; y(ps): T = x(ps)\\[0.5em] - \VAR;x, y: T := e && \VAR;x: T := e\\ && \VAR;y: T := x\\[0.5em] - -\TYPE;t,u = T && \TYPE; t = T\\ - && \TYPE; u = t\\[0.5em] \eda -All definitions have a ``repeated form`` where the initial -definition keyword is followed by several constituent definitions -which are separated by commas. A repeated definition is -always interpreted as a sequence formed from the -constituent definitions. E.g. the function definition -`def f(x) = x, g(y) = y` expands to -`def f(x) = x; def g(y) = y` and -the type definition -`type T, U <: B` expands to -`type T; type U <: B`. -} -\comment{ -If an element in such a sequence introduces only the defined name, -possibly with some type or value parameters, but leaves out any -additional parts in the definition, then those parts are implicitly -copied from the next subsequent sequence element which consists of -more than just a defined name and parameters. Examples: - -- [] The variable declaration `var x, y: Int` expands to `var x: Int; var y: Int`. -- [] + The value definition `val x, y: Int = 1` expands to `val x: Int = 1; val y: Int = 1`. -- [] -The class definition `case class X(), Y(n: Int) extends Z` expands to -`case class X extends Z; case class Y(n: Int) extends Z`. -- The object definition `case object Red, Green, Blue extends Color`~ -expands to -```scala -case object Red extends Color -case object Green extends Color -case object Blue extends Color -``` --> ## Value Declarations and Definitions From d5e2a69cc3eaa17dc04e3937d3ba072d2f02e0aa Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Wed, 19 Oct 2022 14:55:57 +0200 Subject: [PATCH 07/19] Apply limit22.md --- docs/_spec/03-types.md | 38 +++++++++++-------- docs/_spec/06-expressions.md | 13 ++++++- docs/_spec/08-pattern-matching.md | 10 ++++- docs/_spec/12-the-scala-standard-library.md | 36 ++++++++++++++---- .../dropped-features/limit22.md | 0 5 files changed, 70 insertions(+), 27 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/limit22.md (100%) diff --git a/docs/_spec/03-types.md b/docs/_spec/03-types.md index 95da81d19850..acb3a37faf14 100644 --- a/docs/_spec/03-types.md +++ b/docs/_spec/03-types.md @@ -217,22 +217,27 @@ G[S, Int] // illegal: S constrains its parameter to SimpleType ::= ‘(’ Types ‘)’ ``` -A _tuple type_ ´(T_1 , ... , T_n)´ is an alias for the class `scala.Tuple´n´[´T_1´, ... , ´T_n´]`, where ´n \geq 2´. +A _tuple type_ ´(T_1, ..., T_n)´ where ´n \geq 2´ is an alias for the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple`. + +Note: +`(´T´)` is just the type ´T´, and not `´T´ *: scala.EmptyTuple`. +`()` is not a valid type, and not `scala.EmptyTuple`. + +If ´n \leq 22´, the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple` is both a subtype and a supertype of tuple class `scala.Tuple´_n´[´T_1´, ..., ´T_n´]`. Tuple classes are case classes whose fields can be accessed using selectors `_1`, ..., `_n`. -Their functionality is abstracted in a corresponding `Product` trait. +Their functionality is abstracted in the corresponding `scala.Product_´n´` trait. The _n_-ary tuple class and product trait are defined at least as follows in the standard Scala library (they might also add other methods and implement other traits). ```scala case class Tuple´_n´[+´T_1´, ..., +´T_n´](_1: ´T_1´, ..., _n: ´T_n´) extends Product´_n´[´T_1´, ..., ´T_n´] -trait Product´_n´[+´T_1´, ..., +´T_n´] { +trait Product´_n´[+´T_1´, ..., +´T_n´] extends Product: override def productArity = ´n´ def _1: ´T_1´ ... def _n: ´T_n´ -} ``` ### Annotated Types @@ -329,25 +334,26 @@ FunctionArgs ::= InfixType | ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’ ``` -The type ´(T_1, ..., T_n) \Rightarrow U´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´U´. -In the case of exactly one argument type ´T \Rightarrow U´ is a shorthand for ´(T) \Rightarrow U´. -An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.html#by-name-parameters) of type ´T´. +The type ´(T_1, ..., T_n) \Rightarrow R´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´R´. +The case of exactly one argument type ´T \Rightarrow R´ is a shorthand for ´(T) \Rightarrow R´. +An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.md#by-name-parameters) of type ´T´. -Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow U´ is the same as ´S \Rightarrow (T \Rightarrow U)´. +Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow R´ is the same as ´S \Rightarrow (T \Rightarrow R)´. + +Function types are [covariant](04-basic-declarations-and-definitions.md#variance-annotations) in their result type and [contravariant](04-basic-declarations-and-definitions.md#variance-annotations) in their argument types. Function types are shorthands for class types that define an `apply` method. -Specifically, the ´n´-ary function type ´(T_1 , \ldots , T_n) \Rightarrow U´ is a shorthand for the class type `Function´_n´[´T_1´ , … , ´T_n´, ´U´]`. -Such class types are defined in the Scala library for ´n´ between 0 and 22 as follows. +Specifically, the ´n´-ary function type ´(T_1, ..., T_n) \Rightarrow R´ is a shorthand for the class type `Function´_n´[´T_1´, ..., ´T_n´, ´R´]`. +In particular ´() \Rightarrow R´ is a shorthand for class type `Function´_0´[´R´]`. + +Such class types behave as if they were instances of the following trait: ```scala -package scala -trait Function´_n´[-´T_1´, ..., -´T_n´, +´U´] { - def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´U´ - override def toString = "" -} +trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]: + def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´ ``` -Hence, function types are [covariant](04-basic-declarations-and-definitions.html#variance-annotations) in their result type and contravariant in their argument types. +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. #### Wildcard Types diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index 3b39dec25829..8db2c1e66c98 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -381,9 +381,15 @@ Type applications can be omitted if [local type inference](#local-type-inference ```ebnf SimpleExpr ::= ‘(’ [Exprs] ‘)’ ``` +A _tuple expression_ `(´e_1´, ..., ´e_n´)` where ´n \geq 2´ is equivalent to the expression `´e_1´ *: ... *: ´e_n´ *: scala.EmptyTuple`. -A _tuple expression_ `(´e_1´, ..., ´e_n´)` is an alias for the class instance creation `scala.Tuple´n´(´e_1´, ..., ´e_n´)`, where ´n \geq 2´. -The empty tuple `()` is the unique value of type `scala.Unit`. +Note: +As calls to `*:` are slow, a more efficient translation is free to be implemented. +For example, `(´e_1´, ´e_2´)` could be translated to `scala.Tuple2(´e_1´, ´e_2´)`, which is indeed equivalent to `´e_1´ *: ´e_2´ *: scala.EmptyTuple`. + +Note: +The expression `(´e_1´)` is not equivalent to `´e_1´ *: scala.EmptyTuple`, but instead a regular parenthesized expression. +The expression `()` is not an alias for `scala.EmptyTuple`, but instead the unique value of type `scala.Unit`. ## Instance Creation Expressions @@ -909,6 +915,9 @@ Binding ::= (id | ‘_’) [‘:’ Type] The anonymous function of arity ´n´, `(´x_1´: ´T_1, ..., x_n´: ´T_n´) => e` maps parameters ´x_i´ of types ´T_i´ to a result given by expression ´e´. The scope of each formal parameter ´x_i´ is ´e´. Formal parameters must have pairwise distinct names. +Type bindings can be omitted, in which case the compiler will attempt to infer valid bindings. + +Note: `() => ´e´` defines a nullary function (´n´ = 0), and not for example `(_: Unit) => ´e´`. In the case of a single untyped formal parameter, `(´x\,´) => ´e´` can be abbreviated to `´x´ => ´e´`. If an anonymous function `(´x´: ´T\,´) => ´e´` with a single typed parameter appears as the result expression of a block, it can be abbreviated to `´x´: ´T´ => e`. diff --git a/docs/_spec/08-pattern-matching.md b/docs/_spec/08-pattern-matching.md index 97fb73d58b06..df1c396631ea 100644 --- a/docs/_spec/08-pattern-matching.md +++ b/docs/_spec/08-pattern-matching.md @@ -185,7 +185,15 @@ This is further discussed [here](#pattern-sequences). SimplePattern ::= ‘(’ [Patterns] ‘)’ ``` -A _tuple pattern_ `(´p_1´, ..., ´p_n´)` is an alias for the constructor pattern `scala.Tuple´n´(´p_1´, ..., ´p_n´)`, where ´n \geq 2´. The empty tuple `()` is the unique value of type `scala.Unit`. +A _tuple pattern_ `(´p_1´, ..., ´p_n´)` where ´n \geq 2´ is equivalent to `´p_1´ *: ... *: ´p_n´ *: scala.EmptyTuple`. + +Note: +`()` is equivalent to `_: scala.Unit`, and not `scala.EmptyTuple`. +`(´pat´)` is a pattern matching ´pat´, and not `´pat´ *: scala.EmptyTuple`. + +Note: +As such patterns with `*:` are slow, a more efficient translation is free to be implemented. +For example, `(´p_1´, ´p_2´)` could be translated to `scala.Tuple2(´p_1´, ´p_2´)`, which is indeed equivalent to `´p_1´ *: ´p_2´ *: scala.EmptyTuple`. ### Extractor Patterns diff --git a/docs/_spec/12-the-scala-standard-library.md b/docs/_spec/12-the-scala-standard-library.md index 401735286a51..bea9c9c574d4 100644 --- a/docs/_spec/12-the-scala-standard-library.md +++ b/docs/_spec/12-the-scala-standard-library.md @@ -288,6 +288,7 @@ def + (that: Any): String which concatenates its left operand with the textual representation of its right operand. + ### The `Function` Classes -Scala defines function classes `Function´n´` for ´n = 1 , \ldots , 22´. -These are defined as follows. +For each class type `Function´n´` where ´n = 0, ..., 22´, Scala defines the following function class: ```scala package scala -trait Function´n´[-T_1, ..., -T_´n´, +R] { - def apply(x_1: T_1, ..., x_´n´: T_´n´): R - def toString = "" -} +trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]: + def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´ + override def toString = "" + def curried: ´T_1´ => ... => ´T_n´ => R = ... + def tupled: ((´T_1´, ..., ´T_n´)) => R = ... +``` + +For function types `Function´n´` where ´n > 22´, Scala defines a unique function class: + +```scala +package scala +trait FunctionXXL: + def apply(xs: IArray[Object]): Object + override def toString = "" ``` +There is no loss of type safety, as the internal representation is still `Function´n´` for all ´n´. +However this means methods `curried` and `tupled` are not available on functions with more than 22 parameters. + +The implicitly imported [`Predef`](#the-predef-object) object defines the name +`Function` as an alias of `Function1`. + + The `PartialFunction` subclass of `Function1` represents functions that (indirectly) specify their domain. Use the `isDefined` method to query whether the partial function is defined for a given input (i.e., whether the input is part of the function's domain). @@ -322,7 +339,10 @@ class PartialFunction[-A, +B] extends Function1[A, B] { } ``` -The implicitly imported [`Predef`](#the-predef-object) object defines the name `Function` as an alias of `Function1`. +### Trait `Product` + + +All case classes automatically extend the `Product` trait (and generate synthetic methods to conform to it) (but not `Product´n´`), and define a `_´n´` method for each of their arguments. ### Class `Array` diff --git a/docs/_spec/TODOreference/dropped-features/limit22.md b/docs/_spec/APPLIEDreference/dropped-features/limit22.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/limit22.md rename to docs/_spec/APPLIEDreference/dropped-features/limit22.md From 3b27b5793c615bda71e69fc4a947bc218f9723d4 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Fri, 14 Oct 2022 14:00:21 +0200 Subject: [PATCH 08/19] Small fixes --- docs/_spec/06-expressions.md | 2 +- docs/_spec/12-the-scala-standard-library.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index 8db2c1e66c98..16f2f527a9dc 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -967,7 +967,7 @@ x => x // The identity function f => g => x => f(g(x)) // Curried function composition -(x: Int,y: Int) => x + y // A summation function +(x: Int, y: Int) => x + y // A summation function () => { count += 1; count } // The function which takes an // empty parameter list ´()´, diff --git a/docs/_spec/12-the-scala-standard-library.md b/docs/_spec/12-the-scala-standard-library.md index bea9c9c574d4..631596e0d272 100644 --- a/docs/_spec/12-the-scala-standard-library.md +++ b/docs/_spec/12-the-scala-standard-library.md @@ -621,7 +621,7 @@ object Predef { def assume(assumption: Boolean, message: => Any) { if (!assumption) - throw new IllegalArgumentException(message.toString) + throw new IllegalArgumentException("assumption failed: " + message.toString) } def require(requirement: Boolean) { From 7cd5073b7b8251e76354c56b94fe982a7c5a86c1 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Fri, 14 Oct 2022 14:00:39 +0200 Subject: [PATCH 09/19] Add TODO: Update as Implicit Conversion --- docs/_spec/07-implicits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_spec/07-implicits.md b/docs/_spec/07-implicits.md index 85aaadda87e1..2cd80f227cd4 100644 --- a/docs/_spec/07-implicits.md +++ b/docs/_spec/07-implicits.md @@ -270,6 +270,7 @@ Throwable => Ordered[Throwable], Since the second type in the sequence is equal to the first, the compiler will issue an error signalling a divergent implicit expansion. + ## Views Implicit parameters and methods can also define implicit conversions called views. From d88f3b86d48bdf88f592f249cb352e18e24d462a Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Thu, 20 Oct 2022 14:07:36 +0200 Subject: [PATCH 10/19] Apply macros.md As Scala 2 macros were an experimental feature, they were not included in the spec, and the macro keyword is still a keyword there is thus nothing to do (Scala 3 macros will get their own commits through the corresponding pages) --- .../dropped-features/macros.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/macros.md (100%) diff --git a/docs/_spec/TODOreference/dropped-features/macros.md b/docs/_spec/APPLIEDreference/dropped-features/macros.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/macros.md rename to docs/_spec/APPLIEDreference/dropped-features/macros.md From 04ceaefa9b49d2f19883b5d34435809d70eeb82c Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Thu, 20 Oct 2022 15:38:52 +0200 Subject: [PATCH 11/19] Apply procedure-syntax.md --- .../04-basic-declarations-and-definitions.md | 37 ------------------- docs/_spec/A2-scala-2-compatibility.md | 18 ++++++++- .../dropped-features/procedure-syntax.md | 0 3 files changed, 17 insertions(+), 38 deletions(-) rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/procedure-syntax.md (100%) diff --git a/docs/_spec/04-basic-declarations-and-definitions.md b/docs/_spec/04-basic-declarations-and-definitions.md index a4f5b6d307c2..4145f2b8c2e0 100644 --- a/docs/_spec/04-basic-declarations-and-definitions.md +++ b/docs/_spec/04-basic-declarations-and-definitions.md @@ -609,43 +609,6 @@ By contrast, the following application is well formed and yields again the resul sum(xs: _*) ``` -### Procedures - -```ebnf -FunDcl ::= FunSig -FunDef ::= FunSig [nl] ‘{’ Block ‘}’ -``` - -Special syntax exists for procedures, i.e. methods that return the `Unit` value `()`. -A _procedure declaration_ is a method declaration where the result type is omitted. -The result type is then implicitly completed to the `Unit` type. E.g., `def ´f´(´\mathit{ps}´)` is equivalent to `def ´f´(´\mathit{ps}´): Unit`. - -A _procedure definition_ is a method definition where the result type and the equals sign are omitted; its defining expression must be a block. -E.g., `def ´f´(´\mathit{ps}´) {´\mathit{stats}´}` is equivalent to `def ´f´(´\mathit{ps}´): Unit = {´\mathit{stats}´}`. - -###### Example -Here is a declaration and a definition of a procedure named `write`: - -```scala -trait Writer { - def write(str: String) -} -object Terminal extends Writer { - def write(str: String) { System.out.println(str) } -} -``` - -The code above is implicitly completed to the following code: - -```scala -trait Writer { - def write(str: String): Unit -} -object Terminal extends Writer { - def write(str: String): Unit = { System.out.println(str) } -} -``` - ### Method Return Type Inference A class member definition ´m´ that overrides some other method ´m'´ in a base class of ´C´ may leave out the return type, even if it is recursive. diff --git a/docs/_spec/A2-scala-2-compatibility.md b/docs/_spec/A2-scala-2-compatibility.md index f4a4970cb81a..3621887581a6 100644 --- a/docs/_spec/A2-scala-2-compatibility.md +++ b/docs/_spec/A2-scala-2-compatibility.md @@ -16,4 +16,20 @@ of `Int`. When reading class files compiled with Scala 2, Scala 3 will do a best effort to approximate existential types with its own types. It will -issue a warning that a precise emulation is not possible. \ No newline at end of file +issue a warning that a precise emulation is not possible. + +### Procedure Syntax + +Procedure syntax +```scala +def f() { ... } +``` +has been dropped. You need to write one of the following instead: +```scala +def f() = { ... } +def f(): Unit = { ... } +``` +Scala 3 accepts the old syntax under the `-source:3.0-migration` option. +If the `-migration` option is set, it can even rewrite old syntax to new. +The [Scalafix](https://scalacenter.github.io/scalafix/) tool also +can rewrite procedure syntax to make it Scala 3 compatible. \ No newline at end of file diff --git a/docs/_spec/TODOreference/dropped-features/procedure-syntax.md b/docs/_spec/APPLIEDreference/dropped-features/procedure-syntax.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/procedure-syntax.md rename to docs/_spec/APPLIEDreference/dropped-features/procedure-syntax.md From d76177002f03b14dea11721f939a6e6b05eed119 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Thu, 20 Oct 2022 16:07:09 +0200 Subject: [PATCH 12/19] Update return type inference Scala 3 does not infer more precise types for the return type of overriding methods. This can be seen in the following example: ```scala type T type U <: T abstract class A{ def m: T } class B extends A{ def m = ??? : U } val res: U = (new B).m ``` --- docs/_spec/04-basic-declarations-and-definitions.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/_spec/04-basic-declarations-and-definitions.md b/docs/_spec/04-basic-declarations-and-definitions.md index 4145f2b8c2e0..1d50fd649efd 100644 --- a/docs/_spec/04-basic-declarations-and-definitions.md +++ b/docs/_spec/04-basic-declarations-and-definitions.md @@ -612,9 +612,7 @@ sum(xs: _*) ### Method Return Type Inference A class member definition ´m´ that overrides some other method ´m'´ in a base class of ´C´ may leave out the return type, even if it is recursive. -In this case, the return type ´R'´ of the overridden method ´m'´, seen as a member of ´C´, is taken as the return type of ´m´ for each recursive invocation of ´m´. -That way, a type ´R´ for the right-hand side of ´m´ can be determined, which is then taken as the return type of ´m´. -Note that ´R´ may be different from ´R'´, as long as ´R´ conforms to ´R'´. +In this case, whether or not `m` is recursive, its return type will be the return type of ´m'´. ###### Example Assume the following definitions: From b61f22bf8af0128b47b1dcbd22d560ee1ba7f7fb Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Thu, 20 Oct 2022 16:20:30 +0200 Subject: [PATCH 13/19] Apply symlits.md --- docs/_spec/01-lexical-syntax.md | 13 +----------- docs/_spec/A1-deprecated.md | 21 +++++++++++++++++++ .../dropped-features/symlits.md | 0 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 docs/_spec/A1-deprecated.md rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/symlits.md (100%) diff --git a/docs/_spec/01-lexical-syntax.md b/docs/_spec/01-lexical-syntax.md index 862e85a014be..e2470e27d2e0 100644 --- a/docs/_spec/01-lexical-syntax.md +++ b/docs/_spec/01-lexical-syntax.md @@ -259,7 +259,7 @@ A single new line token is accepted ## Literals -There are literals for integer numbers, floating point numbers, characters, booleans, symbols, strings. +There are literals for integer numbers, floating point numbers, characters, booleans, strings. The syntax of these literals is in each case as in Java. ## Root Classes The root of this hierarchy is formed by class `Any`. From 60f528abc5ebe7fd8116b14461503ead44aeec5c Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Mon, 24 Oct 2022 16:03:41 +0200 Subject: [PATCH 15/19] Apply this-qualifier.md As the feature is not actually deprecated, no changes to the spec are needed --- docs/_spec/A3-to-be-deprecated.md | 4 ++++ .../dropped-features/this-qualifier.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 docs/_spec/A3-to-be-deprecated.md rename docs/_spec/{TODOreference => APPLIEDreference}/dropped-features/this-qualifier.md (93%) diff --git a/docs/_spec/A3-to-be-deprecated.md b/docs/_spec/A3-to-be-deprecated.md new file mode 100644 index 000000000000..adc37111520c --- /dev/null +++ b/docs/_spec/A3-to-be-deprecated.md @@ -0,0 +1,4 @@ +This is a simple list of feature that are not deprecated yet, but will be in the future. +They should emit warnings or errors only when using the `-source:future` compiler flag. + +- [private[this] and protected[this]](../_docs/reference/dropped-features/this-qualifier.md) \ No newline at end of file diff --git a/docs/_spec/TODOreference/dropped-features/this-qualifier.md b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md similarity index 93% rename from docs/_spec/TODOreference/dropped-features/this-qualifier.md rename to docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md index 4fcadff8fae3..3fcaefb7e0d8 100644 --- a/docs/_spec/TODOreference/dropped-features/this-qualifier.md +++ b/docs/_spec/APPLIEDreference/dropped-features/this-qualifier.md @@ -4,7 +4,7 @@ title: "Dropped: private[this] and protected[this]" nightlyOf: https://docs.scala-lang.org/scala3/reference/dropped-features/this-qualifier.html --- -The `private[this]` and `protected[this]` access modifiers are deprecated and will be phased out. +The `private[this]` and `protected[this]` access modifiers will be deprecated and phased out. Previously, these modifiers were needed for From d546f59f56021dabf7c7cb954d6700210d51ce14 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Mon, 24 Oct 2022 18:08:07 +0200 Subject: [PATCH 16/19] TOFIXUP Disable indented blocks --- docs/_spec/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_spec/_config.yml b/docs/_spec/_config.yml index bd1f691c65d0..3cb9c8f0d440 100644 --- a/docs/_spec/_config.yml +++ b/docs/_spec/_config.yml @@ -8,4 +8,4 @@ highlighter: false markdown: redcarpet encoding: utf-8 redcarpet: - extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data", "strikethrough", "lax_spacing", "space_after_headers", "superscript", "footnotes"] + extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data", "strikethrough", "lax_spacing", "space_after_headers", "superscript", "footnotes", "disable_indented_code_blocks"] From 0ed921586903da9be28ccb732a77088b29442b11 Mon Sep 17 00:00:00 2001 From: Quentin Bernet Date: Fri, 3 Feb 2023 16:46:54 +0100 Subject: [PATCH 17/19] Reword section Method Application Will make it easier to explain later what happens when you apply a using method to explicit parameters --- docs/_spec/06-expressions.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index 16f2f527a9dc..662f460af0e1 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -201,8 +201,8 @@ ArgumentExprs ::= ‘(’ [Exprs] ‘)’ Exprs ::= Expr {‘,’ Expr} ``` -An application `´f(e_1, ..., e_m)´` applies the expression `´f´` to the argument expressions `´e_1, ..., e_m´`. -For the overal expression to be well-typed, ´f´ must be *applicable* to its arguments, which is defined next by case analysis on ´f´'s type. +An application `´f(e_1, ..., e_m)´` applies the method `´f´` to the argument expressions `´e_1, ..., e_m´`. +For this expression to be well-typed, the method must be *applicable* to its arguments: If ´f´ has a method type `(´p_1´:´T_1, ..., p_n´:´T_n´)´U´`, each argument expression ´e_i´ is typed with the corresponding parameter type ´T_i´ as expected type. Let ´S_i´ be the type of argument ´e_i´ ´(i = 1, ..., m)´. @@ -214,12 +214,12 @@ Once the types ´S_i´ have been determined, the method ´f´ of the above metho - for every positional argument ´e_i´ the type ´S_i´ is [compatible](03-types.html#compatibility) with ´T_i´; - if the expected type is defined, the result type ´U´ is [compatible](03-types.html#compatibility) to it. -If ´f´ is a polymorphic method, [local type inference](#local-type-inference) is used to instantiate ´f´'s type parameters. -The polymorphic method is applicable if type inference can determine type arguments so that the instantiated method is applicable. - -If ´f´ has some value type, the application is taken to be equivalent to `´f´.apply(´e_1, ..., e_m´)`, i.e. the application of an `apply` method defined by ´f´. -The value `´f´` is applicable to the given arguments if `´f´.apply` is applicable. +If ´f´ is instead of some value type, the application is taken to be equivalent to `´f´.apply(´e_1, ..., e_m´)`, i.e. the application of an `apply` method defined by ´f´. +Value `´f´` is applicable to the given arguments if `´f´.apply` is applicable. +Note: +In the case where ´f´ or `´f´.apply` is a polymorphic method, this is taken as an [ommitted type application](#type-applications). +`´f´` is applicable to the given arguments if the result of this type application is applicable. The application `´f´(´e_1, ..., e_n´)` evaluates ´f´ and then each argument ´e_1, ..., e_n´ from left to right, except for arguments that correspond to a by-name parameter (see below). Each argument expression is converted to the type of its corresponding formal parameter. From 100f7bf48093644717b3363144722ee39938b6f4 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Fri, 28 Apr 2023 11:36:10 +0200 Subject: [PATCH 18/19] fixup formatting --- docs/_spec/03-types.md | 6 +++--- docs/_spec/06-expressions.md | 16 +++++++--------- docs/_spec/08-pattern-matching.md | 11 ++++------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/docs/_spec/03-types.md b/docs/_spec/03-types.md index acb3a37faf14..5e1da82f1f11 100644 --- a/docs/_spec/03-types.md +++ b/docs/_spec/03-types.md @@ -219,9 +219,9 @@ SimpleType ::= ‘(’ Types ‘)’ A _tuple type_ ´(T_1, ..., T_n)´ where ´n \geq 2´ is an alias for the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple`. -Note: -`(´T´)` is just the type ´T´, and not `´T´ *: scala.EmptyTuple`. -`()` is not a valid type, and not `scala.EmptyTuple`. +Notes: +- `(´T´)` is just the type ´T´, and not `´T´ *: scala.EmptyTuple`. +- `()` is not a valid type, and not `scala.EmptyTuple`. If ´n \leq 22´, the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple` is both a subtype and a supertype of tuple class `scala.Tuple´_n´[´T_1´, ..., ´T_n´]`. diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index 662f460af0e1..bb90c2b071a4 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -217,9 +217,9 @@ Once the types ´S_i´ have been determined, the method ´f´ of the above metho If ´f´ is instead of some value type, the application is taken to be equivalent to `´f´.apply(´e_1, ..., e_m´)`, i.e. the application of an `apply` method defined by ´f´. Value `´f´` is applicable to the given arguments if `´f´.apply` is applicable. -Note: -In the case where ´f´ or `´f´.apply` is a polymorphic method, this is taken as an [ommitted type application](#type-applications). -`´f´` is applicable to the given arguments if the result of this type application is applicable. +Notes: +- In the case where ´f´ or `´f´.apply` is a polymorphic method, this is taken as an [ommitted type application](#type-applications). +- `´f´` is applicable to the given arguments if the result of this type application is applicable. The application `´f´(´e_1, ..., e_n´)` evaluates ´f´ and then each argument ´e_1, ..., e_n´ from left to right, except for arguments that correspond to a by-name parameter (see below). Each argument expression is converted to the type of its corresponding formal parameter. @@ -383,13 +383,11 @@ SimpleExpr ::= ‘(’ [Exprs] ‘)’ ``` A _tuple expression_ `(´e_1´, ..., ´e_n´)` where ´n \geq 2´ is equivalent to the expression `´e_1´ *: ... *: ´e_n´ *: scala.EmptyTuple`. -Note: -As calls to `*:` are slow, a more efficient translation is free to be implemented. -For example, `(´e_1´, ´e_2´)` could be translated to `scala.Tuple2(´e_1´, ´e_2´)`, which is indeed equivalent to `´e_1´ *: ´e_2´ *: scala.EmptyTuple`. +Note: as calls to `*:` are slow, a more efficient translation is free to be implemented. For example, `(´e_1´, ´e_2´)` could be translated to `scala.Tuple2(´e_1´, ´e_2´)`, which is indeed equivalent to `´e_1´ *: ´e_2´ *: scala.EmptyTuple`. -Note: -The expression `(´e_1´)` is not equivalent to `´e_1´ *: scala.EmptyTuple`, but instead a regular parenthesized expression. -The expression `()` is not an alias for `scala.EmptyTuple`, but instead the unique value of type `scala.Unit`. +Notes: +- The expression `(´e_1´)` is not equivalent to `´e_1´ *: scala.EmptyTuple`, but instead a regular parenthesized expression. +- The expression `()` is not an alias for `scala.EmptyTuple`, but instead the unique value of type `scala.Unit`. ## Instance Creation Expressions diff --git a/docs/_spec/08-pattern-matching.md b/docs/_spec/08-pattern-matching.md index df1c396631ea..f16f4c3dfa88 100644 --- a/docs/_spec/08-pattern-matching.md +++ b/docs/_spec/08-pattern-matching.md @@ -187,13 +187,10 @@ This is further discussed [here](#pattern-sequences). A _tuple pattern_ `(´p_1´, ..., ´p_n´)` where ´n \geq 2´ is equivalent to `´p_1´ *: ... *: ´p_n´ *: scala.EmptyTuple`. -Note: -`()` is equivalent to `_: scala.Unit`, and not `scala.EmptyTuple`. -`(´pat´)` is a pattern matching ´pat´, and not `´pat´ *: scala.EmptyTuple`. - -Note: -As such patterns with `*:` are slow, a more efficient translation is free to be implemented. -For example, `(´p_1´, ´p_2´)` could be translated to `scala.Tuple2(´p_1´, ´p_2´)`, which is indeed equivalent to `´p_1´ *: ´p_2´ *: scala.EmptyTuple`. +Notes: +- `()` is equivalent to `_: scala.Unit`, and not `scala.EmptyTuple`. +- `(´pat´)` is a pattern matching ´pat´, and not `´pat´ *: scala.EmptyTuple`. +- As such patterns with `*:` are slow, a more efficient translation is free to be implemented. For example, `(´p_1´, ´p_2´)` could be translated to `scala.Tuple2(´p_1´, ´p_2´)`, which is indeed equivalent to `´p_1´ *: ´p_2´ *: scala.EmptyTuple`. ### Extractor Patterns From 3a4e1ccca3a49268ac5a348becd5d9657586469b Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Fri, 28 Apr 2023 15:17:02 +0200 Subject: [PATCH 19/19] =?UTF-8?q?Move=20=E2=80=9CWildcard=20Types=E2=80=9D?= =?UTF-8?q?=20to=20a=20subsection=20of=20=E2=80=9CParameterized=20Types?= =?UTF-8?q?=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specify them independently of `forSome`. --- docs/_spec/03-types.md | 105 +++++++++++++++++++++-------------- docs/_spec/06-expressions.md | 26 ++++----- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/docs/_spec/03-types.md b/docs/_spec/03-types.md index 5e1da82f1f11..a1ad1ddffa57 100644 --- a/docs/_spec/03-types.md +++ b/docs/_spec/03-types.md @@ -8,13 +8,9 @@ chapter: 3 ```ebnf Type ::= FunctionArgTypes ‘=>’ Type - | InfixType [ExistentialClause] + | InfixType FunctionArgTypes ::= InfixType | ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’ - ExistentialClause ::= ‘forSome’ ‘{’ ExistentialDcl - {semi ExistentialDcl} ‘}’ - ExistentialDcl ::= ‘type’ TypeDcl - | ‘val’ ValDcl InfixType ::= CompoundType {id [nl] CompoundType} CompoundType ::= AnnotType {‘with’ AnnotType} [Refinement] | Refinement @@ -163,13 +159,14 @@ SimpleType ::= SimpleType TypeArgs TypeArgs ::= ‘[’ Types ‘]’ ``` -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´. +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´. ´T´ must refer to a type constructor which takes ´n´ type parameters ´a_1, ..., a_n´. + Say the type parameters have lower bounds ´L_1, ..., L_n´ and upper bounds ´U_1, ..., U_n´. -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 ]´. +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 ]´. -###### Example Parameterized Types +#### Example Parameterized Types Given the partial type definitions: @@ -178,9 +175,9 @@ class TreeMap[A <: Comparable[A], B] { ... } class List[A] { ... } class I extends Comparable[I] { ... } -class F[M[_], X] { ... } +class F[M[A], X] { ... } class S[K <: String] { ... } -class G[M[ Z <: I ], I] { ... } +class G[M[Z <: I], I] { ... } ``` the following parameterized types are well-formed: @@ -194,9 +191,7 @@ F[List, Int] G[S, String] ``` -###### Example - -Given the [above type definitions](#example-parameterized-types), the following types are ill-formed: +and the following types are ill-formed: ```scala TreeMap[I] // illegal: wrong number of parameters @@ -211,6 +206,50 @@ G[S, Int] // illegal: S constrains its parameter to // that conforms to Int ``` +#### Wildcard Type Argument + + +```ebnf +WildcardType ::= ‘_’ TypeBounds +``` + +A _wildcard type argument_ is of the form `_´\;´>:´\,L\,´<:´\,U´`. +A wildcard type must appear as a type argument of a parameterized type. +The parameterized type to which the wildcard type is applied cannot be an abstract type constructor. + +Both bound clauses may be omitted. +If both bounds are omitted, the real bounds are inferred from the bounds of the corresponding type parameter in the target type constructor. +Otherwise, if a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed. +Otherwise, if an upper bound clause `<:´\,U´` is missing, `<:´\,´scala.Any` is assumed. + +Given the [above type definitions](#example-parameterized-types), the following types are well-formed: + +```scala +List[_] // inferred as List[_ >: Nothing <: Any] +List[_ <: java.lang.Number] +S[_ <: String] +F[_, Boolean] +``` + +and the following code contains an ill-formed type: + +```scala +trait H[F[A]]: + def f: F[_] // illegal : an abstract type constructor + // cannot be applied to wildcard arguments. +``` + +Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types). +Their expansion is then the expansion in the equivalent parameterized type. + +##### Simplification Rules + +Let ´T[T_1, ..., T_n]´ be a parameterized type. +Then, applying a wildcard type argument ´t´ of the form ´\\_ >: L <: U´ at the ´i´'th position obeys the following equivalences: + +- If the type parameter ´T_i´ is declared covariant, then ´t \equiv U´ +- If the type parameter ´T_i´ is declared contravariant, then ´t \equiv L´ + ### Tuple Types ```ebnf @@ -355,30 +394,6 @@ trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]: 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. -#### Wildcard Types - -```ebnf -WildcardType ::= ‘_’ TypeBounds -``` - -A _wildcard type_ is of the form `_´\;´>:´\,L\,´<:´\,U´`. -Both bound clauses may be omitted. -If a lower bound clause `>:´\,L´` is missing, `>:´\,´scala.Nothing` is assumed. -If an upper bound clause `<:´\,U´` is missing, `<:´\,´scala.Any` is assumed. -A wildcard type is a shorthand for an existentially quantified type variable, where the existential quantification is implicit. - -A wildcard type must appear as a type argument of a parameterized type. -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´`. -Then ´T´ is equivalent to the existential type - -```scala -´p.c[\mathit{targs},t,\mathit{targs}']´ forSome { type ´t´ >: ´L´ <: ´U´ } -``` - -where ´t´ is some fresh type variable. -Wildcard types may also appear as parts of [infix types](#infix-types), [function types](#function-types), or [tuple types](#tuple-types). -Their expansion is then the expansion in the equivalent parameterized type. - ## Non-Value Types 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] - corresponding parameters have equivalent types. Note that the names of parameters do not matter for method type equivalence. - 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. -- 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. - 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. [^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] The conformance relation ´(<:)´ is the smallest transitive relation that satisfies the following conditions. -- Conformance includes equivalence. If `T \equiv U` then `T <: U`. +- 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 value type ´T´, `scala.Null <: ´T´` unless `´T´ <: scala.AnyVal`. @@ -582,10 +596,13 @@ The conformance relation ´(<:)´ is the smallest transitive relation that satis - A singleton type `´p´.type` conforms to the type of the path ´p´. - A singleton type `´p´.type` conforms to the type `scala.Singleton`. - A type projection `´T´#´t´` conforms to `´U´#´t´` if ´T´ conforms to ´U´. -- 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 \}´: - 1. If the ´i´'th type parameter of ´T´ is declared covariant, then ´T_i <: U_i´. - 1. If the ´i´'th type parameter of ´T´ is declared contravariant, then ´U_i <: T_i´. - 1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant, then ´U_i \equiv T_i´. +- 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 \}´: + 1. If the ´i´'th type parameter of ´T´ is declared covariant, then ´T_i <: U_i´. [^argisnotwildcard] + 1. If the ´i´'th type parameter of ´T´ is declared contravariant, then ´U_i <: T_i´. [^argisnotwildcard] + 1. If the ´i´'th type parameter of ´T´ is declared neither covariant nor contravariant: + 1. If neither ´T_i´ nor ´U_i´ are wildcard type arguments, then ´U_i \equiv T_i´. + 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"). + 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´. - A compound type `´T_1´ with ... with ´T_n´ {´R\,´}` conforms to each of its component types ´T_i´. - 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\,´}`. - 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: - The variance of ´a_i´ must match the variance of ´a'_i´, where covariance matches covariance, contravariance matches contravariance and any variance matches invariance. - Recursively, these restrictions apply to the corresponding higher-order type parameter clauses of ´a_i´ and ´a'_i´. + [^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. + 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. - 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'´. diff --git a/docs/_spec/06-expressions.md b/docs/_spec/06-expressions.md index bb90c2b071a4..5adb58ec626c 100644 --- a/docs/_spec/06-expressions.md +++ b/docs/_spec/06-expressions.md @@ -460,16 +460,13 @@ The expected type of the final expression ´e´ is the expected type of the bloc The expected type of all preceding statements is undefined. -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´. -We say the existential clause _binds_ the occurrence of the value or type name. -Specifically, +The type of a block `´s_1´; ...; ´s_n´; ´e´` is some type ´T´ such that: -- A locally defined type definition `type´\;t = T´` is bound by the existential clause `type´\;t >: T <: T´`. -It is an error if ´t´ carries type parameters. -- A locally defined value definition `val´\;x: T = e´` is bound by the existential clause `val´\;x: T´`. -- 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´. -It is an error if ´c´ carries type parameters. -- 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`. +- ´U <: T´ where ´U´ is the type of ´e´. +- 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´. +- ´T´ is "as small as possible" (this is a soft requirement). + +The precise way in which we compute ´T´, called _type avoidance_, is currently not defined in this specification. 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. @@ -1181,12 +1178,11 @@ question: given --> - 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´. -- 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´. -- A member of any other type is always as specific as a parameterized method or a polymorphic method. - -- 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´. -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´}`. -The existential dual of every other type is the type itself. + 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). +- 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´. +- A member of any other type ´T´ is: + - always as specific as a parameterized method or a polymorphic method. + - as specific as a member ´m'´ of any other type ´S´ if ´T´ is [compatible](03-types.html#compatibility) with ´S´. The _relative weight_ of an alternative ´A´ over an alternative ´B´ is a number from 0 to 2, defined as the sum of