From 772e3652bb5c2b1c53577db701db7b7c8a6cbf31 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sat, 28 Sep 2019 22:34:34 +0200 Subject: [PATCH 1/9] [doc] wording, parameter inline modifier Maybe this is only of a personal taste. When I first read "can be marked `inline`" then I thought about an annotation. Since there is `@inline` it could be overlooked. Thus I suggest we rephrase it to "can have an `inline` modifier". --- docs/docs/reference/metaprogramming/inline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 251ee13c116c..3e56c8b7f46f 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -58,7 +58,7 @@ def factorial(n: BigInt): BigInt = { } ``` -If `Config.logging == false`, this will be rewritten (simplified) to +If `Config.logging == false`, this will be rewritten (simplified) to: ```scala def factorial(n: BigInt): BigInt = { @@ -120,7 +120,7 @@ inline def power(x: Double, n: Int): Double = { } ``` -Parameters of inline methods can be marked `inline`. This means +Parameters of inline methods can have an `inline` modifier as well. This means that actual arguments to these parameters must be constant expressions. For example: From 57270d2fbc10aff621ac7aff069fe516b08284e4 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sat, 28 Sep 2019 23:02:48 +0200 Subject: [PATCH 2/9] improve inline conditionals --- docs/docs/reference/metaprogramming/inline.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 3e56c8b7f46f..6d45bd176108 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -221,9 +221,9 @@ final val one: 1 = zero() + 1 ## Inline Conditionals -If the condition of an if-then-else expressions is a constant, the expression simplifies to -the selected branch. Prefixing an if-then-else expression with `inline` forces -the condition to be a constant, and thus guarantees that the conditional will always +If the condition of an if-then-else expressions is a constant expression then it simplifies to +the selected branch. Prefixing an if-then-else expression with `inline` enforces that +the condition has to be a constant expression, and thus guarantees that the conditional will always simplify. Example: From 7bf53e339c954dd28f7c97eaecb108bba28bd78a Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sat, 28 Sep 2019 23:32:37 +0200 Subject: [PATCH 3/9] improve erasedValue section --- docs/docs/reference/metaprogramming/inline.md | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 6d45bd176108..b4e6503991c0 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -33,8 +33,8 @@ object Logger { The `Config` object contains a definition of the **inline value** `logging`. This means that `logging` is treated as a _constant value_, equivalent to its right-hand side `false`. The right-hand side of such an `inline val` must itself -be a [constant expression](https://scala-lang.org/files/archive/spec/2.12/06-expressions.html#constant-expressions). Used in this -way, `inline` is equivalent to Java and Scala 2's `final`. Note that `final`, meaning +be a [constant expression](https://scala-lang.org/files/archive/spec/2.12/06-expressions.html#constant-expressions). +Used in this way, `inline` is equivalent to Java and Scala 2's `final`. Note that `final`, meaning _inlined constant_, is still supported in Dotty, but will be phased out. The `Logger` object contains a definition of the **inline method** `log`. This @@ -272,8 +272,8 @@ The scrutinee `x` is examined statically and the inline match is reduced accordingly returning the corresponding value (with the type specialized due to the `<:` in the return type). This example performs a simple type test over the scrutinee. The type can have a richer structure like the simple ADT below. -`toInt` matches the structure of a number in Church-encoding and _computes_ the -corresponding integer. +`toInt` matches the structure of a number in [Church-encoding](https://en.wikipedia.org/wiki/Church_encoding) +and _computes_ the corresponding integer. ```scala trait Nat @@ -319,11 +319,11 @@ the singleton type `2`. #### `erasedValue` -We have seen so far inline methods that take terms (tuples and integers) as +So far we have seen inline methods that take terms (tuples and integers) as parameters. What if we want to base case distinctions on types instead? For instance, one would like to be able to write a function `defaultValue`, that, -given a type `T` returns optionally the default value of `T`, if it exists. In -fact, we can already express this using rewrite match expressions and a simple +given a type `T`, returns optionally the default value of `T`, if it exists. +We can already express this using rewrite match expressions and a simple helper function, `scala.compiletime.erasedValue`, which is defined as follows: ```scala @@ -333,7 +333,7 @@ erased def erasedValue[T]: T = ??? The `erasedValue` function _pretends_ to return a value of its type argument `T`. In fact, it would always raise a `NotImplementedError` exception when called. But the function can in fact never be called, since it is declared -`erased`, so can be only used at compile-time during type checking. +`erased`, so can only be used at compile-time during type checking. Using `erasedValue`, we can then define `defaultValue` as follows: @@ -360,10 +360,11 @@ Then: val dAny: None.type = defaultValue[Any] ``` -As another example, consider the type-level version of `toNat` above the we call -`toIntT`: given a _type_ representing a Peano number, return the integer _value_ -corresponding to it. Consider the definitions of numbers as in the _Inline -Match_ section aboce. Here's how `toIntT` can be defined: +As another example, consider the type-level version of `toInt` below: +given a _type_ representing a [Peano number](https://wiki.haskell.org/Peano_numbers), +return the integer _value_ corresponding to it. +Consider the definitions of numbers as in the _Inline +Match_ section above. Here is how `toIntT` can be defined: ```scala inline def toIntT[N <: Nat] <: Int = inline scala.compiletime.erasedValue[N] match { From 03410c62a2d8b885904265a5b005e1bae6c0a5c3 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sat, 28 Sep 2019 23:57:39 +0200 Subject: [PATCH 4/9] typo identity and remove final val --- docs/docs/reference/metaprogramming/inline.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index b4e6503991c0..e434b158faa5 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -216,7 +216,7 @@ type `1`. ```scala inline def zero() <: Int = 0 -final val one: 1 = zero() + 1 +val one: 1 = zero() + 1 ``` ## Inline Conditionals @@ -285,7 +285,7 @@ inline def toInt(n: Nat) <: Int = inline n match { case Succ(n1) => toInt(n1) + 1 } -final val natTwo = toInt(Succ(Succ(Zero))) +val natTwo = toInt(Succ(Succ(Zero))) val intTwo: 2 = natTwo ``` @@ -309,7 +309,7 @@ inline def toIntC[N] <: Int = case _: S[n1] => 1 + toIntC[n1] } -final val ctwo = toIntC[2] +val ctwo = toIntC[2] ``` `constValueOpt` is the same as `constValue`, however returning an `Option[T]` @@ -338,6 +338,8 @@ called. But the function can in fact never be called, since it is declared Using `erasedValue`, we can then define `defaultValue` as follows: ```scala +import scala.compiletime.erasedValue + inline def defaultValue[T] = inline erasedValue[T] match { case _: Byte => Some(0: Byte) case _: Char => Some(0: Char) @@ -372,7 +374,7 @@ inline def toIntT[N <: Nat] <: Int = inline scala.compiletime.erasedValue[N] mat case _: Succ[n] => toIntT[n] + 1 } -final val two = toIntT[Succ[Succ[Zero.type]]] +val two = toIntT[Succ[Succ[Zero.type]]] ``` `erasedValue` is an `erased` method so it cannot be used and has no runtime @@ -392,6 +394,8 @@ If an inline expansion results in a call `error(msgStr)` the compiler produces an error message containing the given `msgStr`. ```scala +import scala.compiletime.error + inline def fail() = { error("failed for a reason") } @@ -404,7 +408,7 @@ or inline def fail(p1: => Any) = { error(code"failed on: $p1") } -fail(indentity("foo")) // error: failed on: indentity("foo") +fail(identity("foo")) // error: failed on: identity("foo") ``` ## Summoning Implicits Selectively From 3d8206d0cf004fe25faa5e66e5aa8dd76d660824 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sun, 29 Sep 2019 21:42:09 +0200 Subject: [PATCH 5/9] Update docs/docs/reference/metaprogramming/inline.md Co-Authored-By: Nicolas Stucki --- docs/docs/reference/metaprogramming/inline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index e434b158faa5..4a55e1f78adf 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -394,7 +394,7 @@ If an inline expansion results in a call `error(msgStr)` the compiler produces an error message containing the given `msgStr`. ```scala -import scala.compiletime.error +import scala.compiletime.{error, code} inline def fail() = { error("failed for a reason") From 75ee04c6ba49fc87e6e00d23c240dee7eb311d57 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sun, 29 Sep 2019 22:32:27 +0200 Subject: [PATCH 6/9] Update docs/docs/reference/metaprogramming/inline.md Co-Authored-By: Nicolas Stucki --- docs/docs/reference/metaprogramming/inline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 4a55e1f78adf..fb8874839025 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -363,7 +363,7 @@ Then: ``` As another example, consider the type-level version of `toInt` below: -given a _type_ representing a [Peano number](https://wiki.haskell.org/Peano_numbers), +given a _type_ representing a Peano number, return the integer _value_ corresponding to it. Consider the definitions of numbers as in the _Inline Match_ section above. Here is how `toIntT` can be defined: From 7dc581a94bc65dc79495be24a329607ef4c4795b Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sun, 29 Sep 2019 22:32:33 +0200 Subject: [PATCH 7/9] Update docs/docs/reference/metaprogramming/inline.md Co-Authored-By: Nicolas Stucki --- docs/docs/reference/metaprogramming/inline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index fb8874839025..7978377082f7 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -309,7 +309,7 @@ inline def toIntC[N] <: Int = case _: S[n1] => 1 + toIntC[n1] } -val ctwo = toIntC[2] +final val ctwo = toIntC[2] ``` `constValueOpt` is the same as `constValue`, however returning an `Option[T]` From 8f6c2bf49535d22f8d9cd553d29654d0e164ae2a Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sun, 29 Sep 2019 22:32:38 +0200 Subject: [PATCH 8/9] Update docs/docs/reference/metaprogramming/inline.md Co-Authored-By: Nicolas Stucki --- docs/docs/reference/metaprogramming/inline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 7978377082f7..6965abd8e458 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -285,7 +285,7 @@ inline def toInt(n: Nat) <: Int = inline n match { case Succ(n1) => toInt(n1) + 1 } -val natTwo = toInt(Succ(Succ(Zero))) +final val natTwo = toInt(Succ(Succ(Zero))) val intTwo: 2 = natTwo ``` From b7022d0485efe9ba71b988106597db50c59e8026 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Sun, 29 Sep 2019 22:32:44 +0200 Subject: [PATCH 9/9] Update docs/docs/reference/metaprogramming/inline.md Co-Authored-By: Nicolas Stucki --- docs/docs/reference/metaprogramming/inline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index 6965abd8e458..3514dd626363 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -374,7 +374,7 @@ inline def toIntT[N <: Nat] <: Int = inline scala.compiletime.erasedValue[N] mat case _: Succ[n] => toIntT[n] + 1 } -val two = toIntT[Succ[Succ[Zero.type]]] +final val two = toIntT[Succ[Succ[Zero.type]]] ``` `erasedValue` is an `erased` method so it cannot be used and has no runtime