diff --git a/docs/docs/reference/contextual/givens.md b/docs/docs/reference/contextual/givens.md index 072f3cb4a800..909b6e925ec8 100644 --- a/docs/docs/reference/contextual/givens.md +++ b/docs/docs/reference/contextual/givens.md @@ -34,8 +34,8 @@ a given for the type `Ord[Int]` whereas `listOrd[T]` defines givens for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]` themselves. The `using` clause in `listOrd` defines a condition: There must be a given of type `Ord[T]` for a given of type `List[Ord[T]]` to exist. -Such conditions are expanded by the compiler to context -parameters, which are explained in the [next section](./using-clauses.html). +Such conditions are expanded by the compiler to [context +parameters](./using-clauses.html). ## Anonymous Givens @@ -57,14 +57,15 @@ given global as ExecutionContext = new ForkJoinPool() This creates a given `global` of type `ExecutionContext` that resolves to the right hand side `new ForkJoinPool()`. The first time `global` is accessed, a new `ForkJoinPool` is created, which is then -returned for this and all subsequent accesses to `global`. +returned for this and all subsequent accesses to `global`. This operation is thread-safe. -Alias givens can be anonymous, e.g. +Alias givens can be anonymous as well, e.g. ```scala given Position = enclosingTree.position -given (using outer: Context) as Context = outer.withOwner(currentOwner) +given (using config: Config) as Factory = MemoizingFactory(config) ``` -An alias given can have type parameters and implicit parameters just like any other given, + +An alias given can have type parameters and context parameters just like any other given, but it can only implement a single type. ## Given Whitebox Macro Instances diff --git a/docs/docs/reference/enums/adts.md b/docs/docs/reference/enums/adts.md index 4400b03f2255..8e05280384b4 100644 --- a/docs/docs/reference/enums/adts.md +++ b/docs/docs/reference/enums/adts.md @@ -3,8 +3,8 @@ layout: doc-page title: "Algebraic Data Types" --- -The `enum` concept is general enough to also support algebraic data -types (ADTs) and their generalized version (GADTs). Here's an example +The [`enum` concept](./enums.html) is general enough to also support algebraic data +types (ADTs) and their generalized version (GADTs). Here is an example how an `Option` type can be represented as an ADT: ```scala @@ -34,7 +34,7 @@ Note that the parent type of the `None` value is inferred as `Option[Nothing]`. Generally, all covariant type parameters of the enum class are minimized in a compiler-generated extends clause whereas all contravariant type parameters are maximized. If `Option` was non-variant, -you'd need to give the extends clause of `None` explicitly. +you would need to give the extends clause of `None` explicitly. As for normal enum values, the cases of an `enum` are all defined in the `enum`s companion object. So it's `Option.Some` and `Option.None` diff --git a/docs/docs/reference/enums/enums.md b/docs/docs/reference/enums/enums.md index b390efcb01ba..c56f733ab5b9 100644 --- a/docs/docs/reference/enums/enums.md +++ b/docs/docs/reference/enums/enums.md @@ -95,9 +95,10 @@ If you want to use the Scala-defined enums as Java enums, you can do so by exten enum Color extends java.lang.Enum[Color] { case Red, Green, Blue } ``` -The type parameter comes from the Java enum [definition](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Enum.html) and should be the same as the type of the enum. There is no need to provide constructor arguments (as defined in the API docs) to `java.lang.Enum` when extending it – the compiler will generate them automatically. +The type parameter comes from the Java enum [definition](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Enum.html) and should be the same as the type of the enum. +There is no need to provide constructor arguments (as defined in the Java API docs) to `java.lang.Enum` when extending it – the compiler will generate them automatically. -After defining `Color` like that, you can use like you would a Java enum: +After defining `Color` like that, you can use it like you would a Java enum: ```scala scala> Color.Red.compareTo(Color.Green) diff --git a/docs/docs/reference/new-types/dependent-function-types-spec.md b/docs/docs/reference/new-types/dependent-function-types-spec.md index 555244539599..7b07b8631a97 100644 --- a/docs/docs/reference/new-types/dependent-function-types-spec.md +++ b/docs/docs/reference/new-types/dependent-function-types-spec.md @@ -31,7 +31,7 @@ FunctionN[K1, ..., Kn, R'] { ``` where the result type parameter `R'` is the least upper approximation of the -precise result type `R` without any referance to value parameters `x1, ..., xN`. +precise result type `R` without any reference to value parameters `x1, ..., xN`. The syntax and sementics of anonymous dependent functions is identical to the one of regular functions. Eta expansion is naturally generalized to produce diff --git a/docs/docs/reference/new-types/match-types.md b/docs/docs/reference/new-types/match-types.md index 980b85b58205..d22c373d8d2f 100644 --- a/docs/docs/reference/new-types/match-types.md +++ b/docs/docs/reference/new-types/match-types.md @@ -54,7 +54,7 @@ S match { P1 => T1 ... Pn => Tn } ``` is `Match(S, C1, ..., Cn) <: B` where each case `Ci` is of the form ``` -[Xs] => P => T +[Xs] =>> P => T ``` Here, `[Xs]` is a type parameter clause of the variables bound in pattern `Pi`. If there are no bound type variables in a case, the type parameter clause is omitted and only the function type `P => T` is kept. So each case is either a unary function type or a type lambda over a unary function type. @@ -68,7 +68,7 @@ We define match type reduction in terms of an auxiliary relation, `can-reduce`: ``` Match(S, C1, ..., Cn) can-reduce i, T' ``` -if `Ci = [Xs] => P => T` and there are minimal instantiations `Is` of the type variables `Xs` such that +if `Ci = [Xs] =>> P => T` and there are minimal instantiations `Is` of the type variables `Xs` such that ``` S <: [Xs := Is] P T' = [Xs := Is] T diff --git a/docs/docs/reference/new-types/type-lambdas-spec.md b/docs/docs/reference/new-types/type-lambdas-spec.md index 78ce94ee6356..58f57568e738 100644 --- a/docs/docs/reference/new-types/type-lambdas-spec.md +++ b/docs/docs/reference/new-types/type-lambdas-spec.md @@ -14,9 +14,9 @@ TypeBounds ::= [‘>:’ Type] [‘<:’ Type] ### Type Checking -A type lambda such as `[X] =>> F[X]` defines a function from types to types. The parameter(s) may carry bounds and variance annotations. -If a parameter is bounded, as in `[X >: L <: H] =>> F[X]` it is checked that arguments to the parameters conform to the bounds `L` and `H`. -Only the upper bound `H` can be F-bounded, i.e. `X` can appear in it. +A type lambda such as `[X] =>> F[X]` defines a function from types to types. The parameter(s) may carry bounds. +If a parameter is bounded, as in `[X >: L <: U] =>> F[X]` it is checked that arguments to the parameters conform to the bounds `L` and `U`. +Only the upper bound `U` can be F-bounded, i.e. `X` can appear in it. ## Subtyping Rules @@ -31,7 +31,7 @@ Then `TL1 <: TL2`, if `L1 <: L2` and `U2 <: U1`), - `R1 <: R2` -Here we have relied on alpha renaming to bring match the two bound types `X`. +Here we have relied on alpha renaming to match the two bound types `X`. A partially applied type constructor such as `List` is assumed to be equivalent to its eta expansion. I.e, `List = [X] =>> List[X]`. This allows type constructors to be compared with type lambdas. @@ -46,7 +46,7 @@ is regarded as a shorthand for an unparameterized definition with a type lambda ```scala type T = [X] =>> R ``` -If the a type definition carries `+` or `-` variance annotations, +If the type definition carries `+` or `-` variance annotations, it is checked that the variance annotations are satisfied by the type lambda. For instance, ```scala diff --git a/docs/docs/reference/new-types/type-lambdas.md b/docs/docs/reference/new-types/type-lambdas.md index 9881f4c71e80..a10510287beb 100644 --- a/docs/docs/reference/new-types/type-lambdas.md +++ b/docs/docs/reference/new-types/type-lambdas.md @@ -10,9 +10,7 @@ a type definition. [X, Y] =>> Map[Y, X] ``` -For instance, the type above defines a binary type constructor, which -constructor maps arguments `X` and `Y` to `Map[Y, X]`. Type parameters -of type lambdas can have bounds but they cannot carry `+` or `-` variance -annotations. +For instance, the type above defines a binary type constructor, which maps arguments `X` and `Y` to `Map[Y, X]`. +Type parameters of type lambdas can have bounds but they cannot carry `+` or `-` variance annotations. [More details](./type-lambdas-spec.md) diff --git a/docs/docs/reference/other-new-features/opaques-details.md b/docs/docs/reference/other-new-features/opaques-details.md index 9fab5c81b04f..2b0d9707e84a 100644 --- a/docs/docs/reference/other-new-features/opaques-details.md +++ b/docs/docs/reference/other-new-features/opaques-details.md @@ -25,7 +25,7 @@ where the lower bound `L` and the upper bound `U` may be missing, in which case Inside the scope of the alias definition, the alias is transparent: `T` is treated as a normal alias of `R`. Outside its scope, the alias is treated as the abstract type ```scala -type T >: L <: U` +type T >: L <: U ``` A special case arises if the opaque type is defined in an object. Example: ``` diff --git a/docs/docs/reference/other-new-features/opaques.md b/docs/docs/reference/other-new-features/opaques.md index 7451e95b3a1e..69ab27ca367f 100644 --- a/docs/docs/reference/other-new-features/opaques.md +++ b/docs/docs/reference/other-new-features/opaques.md @@ -12,7 +12,8 @@ object Logarithms { object Logarithm { - // These are the ways to lift to the logarithm type + // These are the two ways to lift to the Logarithm type + def apply(d: Double): Logarithm = math.log(d) def safe(d: Double): Option[Logarithm] = @@ -28,19 +29,19 @@ object Logarithms { } ``` -This introduces `Logarithm` as a new type, which is implemented as `Double` but is different from it. The fact that `Logarithm` is the same as `Double` is only known in the scope where -`Logarithm` is defined which in this case is object `Logarithms`. - -The public API of `Logarithm` consists of the `apply` and `safe` methods that convert from doubles to `Logarithm` values, an extension method `toDouble` that converts the other way, -and operations `+` and `*` on logarithm values. The implementations of these functions -type-check because within object `Logarithms`, the type `Logarithm` is just an alias of `Double`. +This introduces `Logarithm` as a new abstract type, which is implemented as `Double`. +The fact that `Logarithm` is the same as `Double` is only known in the scope where +`Logarithm` is defined which in the above example corresponds to the object `Logarithms`. +Or in other words, within the scope it is treated as type alias, but this is opaque to the outside world +where in consequence `Logarithm` is seen as an abstract type and has nothing to do with `Double`. -Outside its scope, `Logarithm` is treated as a new abstract type. So the -following operations would be valid because they use functionality implemented in the `Logarithm` object. +The public API of `Logarithm` consists of the `apply` and `safe` methods defined in the companion object. +They convert from `Double`s to `Logarithm` values. Moreover, a collective extension `logarithmOps` provides the extension methods `toDouble` that converts the other way, +and operations `+` and `*` on `Logarithm` values. +The following operations would be valid because they use functionality implemented in the `Logarithms` object. ```scala -import Logarithms._ -import Predef.{any2stringadd => _, _} +import Logarithms.Logarithm val l = Logarithm(1.0) val l2 = Logarithm(2.0) @@ -54,11 +55,9 @@ But the following operations would lead to type errors: val d: Double = l // error: found: Logarithm, required: Double val l2: Logarithm = 1.0 // error: found: Double, required: Logarithm l * 2 // error: found: Int(2), required: Logarithm -l / l2 // error: `/` is not a member fo Logarithm +l / l2 // error: `/` is not a member of Logarithm ``` -Aside: the `any2stringadd => _` import suppression is necessary since otherwise the universal `+` operation in `Predef` would take precedence over the `+` extension method in `logarithmOps`. We plan to resolve this wart by eliminating `any2stringadd`. - ### Bounds For Opaque Type Aliases Opaque type aliases can also come with bounds. Example: @@ -81,7 +80,7 @@ object Access { val ReadOrWrite: PermissionChoice = Read | Write } ``` -The `Access` object defines three opaque types: +The `Access` object defines three opaque type aliases: - `Permission`, representing a single permission, - `Permissions`, representing a set of permissions with the meaning "all of these permissions granted", @@ -98,7 +97,7 @@ Because of that, the `|` extension method in `Access` does not cause infinite re Also, the definition of `ReadWrite` must use `|`, even though an equivalent definition outside `Access` would use `&`. -All three opaque types have the same underlying representation type `Int`. The +All three opaque type aliases have the same underlying representation type `Int`. The `Permission` type has an upper bound `Permissions & PermissionChoice`. This makes it known outside the `Access` object that `Permission` is a subtype of the other two types. Hence, the following usage scenario type-checks.