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. 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. @@ -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,28 +206,77 @@ 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 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`. + +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´]`. 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,141 +373,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 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. - -```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 = "" -} -``` - -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 -``` +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. -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 - -```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. -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. - -###### 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 } -``` +Function types are shorthands for class types that define an `apply` method. +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´]`. -is equivalent (by simplification rule 4 above) to +Such class types behave as if they were instances of the following trait: ```scala -List[java.lang.Number] forSome { type T <: java.lang.Number } +trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]: + def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´ ``` -which is in turn equivalent (by simplification rules 2 and 3 above) to `List[java.lang.Number]`. +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. ## Non-Value Types @@ -480,6 +409,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. @@ -599,18 +529,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. @@ -651,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. @@ -661,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`. @@ -670,23 +596,27 @@ 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\,´}`. -- 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´. - 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'´. @@ -738,20 +668,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 @@ -790,8 +709,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 +723,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/04-basic-declarations-and-definitions.md b/docs/_spec/04-basic-declarations-and-definitions.md index af98eef2a37d..1d50fd649efd 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 @@ -647,49 +609,10 @@ 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. -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: diff --git a/docs/_spec/05-classes-and-objects.md b/docs/_spec/05-classes-and-objects.md index c40bd49cae16..b73a4aa56071 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 @@ -305,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 @@ -602,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/06-expressions.md b/docs/_spec/06-expressions.md index 92697e64f0ac..5adb58ec626c 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] @@ -60,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 @@ -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. +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. @@ -381,9 +381,13 @@ 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`. + +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`. -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`. +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 @@ -455,36 +459,18 @@ 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, - -- 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`. - -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 + +The type of a block `´s_1´; ...; ´s_n´; ´e´` is some type ´T´ such that: -```scala -{ class C extends B {´\ldots´} ; new Ref(new C) } -``` +- ´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). -has the type `Ref[_1] forSome { type _1 <: B }`. -The block +The precise way in which we compute ´T´, called _type avoidance_, is currently not defined in this specification. -```scala -{ class C extends B {´\ldots´} ; new C } -``` +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. -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 @@ -717,15 +703,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 @@ -933,6 +910,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`. @@ -982,7 +962,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 ´()´, @@ -1198,11 +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 diff --git a/docs/_spec/07-implicits.md b/docs/_spec/07-implicits.md index a0db9dd9b418..2cd80f227cd4 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. @@ -271,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. diff --git a/docs/_spec/08-pattern-matching.md b/docs/_spec/08-pattern-matching.md index 97fb73d58b06..f16f4c3dfa88 100644 --- a/docs/_spec/08-pattern-matching.md +++ b/docs/_spec/08-pattern-matching.md @@ -185,7 +185,12 @@ 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`. + +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 diff --git a/docs/_spec/12-the-scala-standard-library.md b/docs/_spec/12-the-scala-standard-library.md index 401735286a51..14d1fb82aea4 100644 --- a/docs/_spec/12-the-scala-standard-library.md +++ b/docs/_spec/12-the-scala-standard-library.md @@ -11,6 +11,7 @@ Some of these classes are described in the following. ![Class hierarchy of Scala](public/images/classhierarchy.png) + ## Root Classes The root of this hierarchy is formed by class `Any`. @@ -288,6 +289,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 +340,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` @@ -601,7 +622,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) { diff --git a/docs/_spec/A1-deprecated.md b/docs/_spec/A1-deprecated.md new file mode 100644 index 000000000000..e2ebc8af1d35 --- /dev/null +++ b/docs/_spec/A1-deprecated.md @@ -0,0 +1,21 @@ + +### Symbol Literals + +Symbol literals are no longer supported. + +The [`scala.Symbol`](https://scala-lang.org/api/3.x/scala/Symbol.html) class still exists, so a literal translation of the symbol literal `'xyz` is `Symbol("xyz")`. However, it is recommended to use a plain string literal `"xyz"` instead. (The `Symbol` class will be deprecated and removed in the future). Example: + + +``` +scalac Test.scala +-- Error: Test.scala:1:25 ------------------------------------------------------------------------------------------------ + +1 |@main def test = println('abc) + | ^ + | symbol literal 'abc is no longer supported, + | use a string literal "abc" or an application Symbol("abc") instead, + | or enclose in braces '{abc} if you want a quoted expression. + | For now, you can also `import language.deprecated.symbolLiterals` to accept + | the idiom, but this possibility might no longer be available in the future. +1 error found +``` \ No newline at end of file diff --git a/docs/_spec/A2-scala-2-compatibility.md b/docs/_spec/A2-scala-2-compatibility.md new file mode 100644 index 000000000000..3621887581a6 --- /dev/null +++ b/docs/_spec/A2-scala-2-compatibility.md @@ -0,0 +1,35 @@ + +### 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. + +### 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/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/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 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 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 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 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 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 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 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 diff --git a/docs/_spec/TODOreference/dropped-features/symlits.md b/docs/_spec/APPLIEDreference/dropped-features/symlits.md similarity index 100% rename from docs/_spec/TODOreference/dropped-features/symlits.md rename to docs/_spec/APPLIEDreference/dropped-features/symlits.md 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 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"]