From bbba81f9379dbdf7c1d9eaeb45f7a4626d1fc430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Wed, 30 Dec 2020 18:19:32 +0100 Subject: [PATCH 1/3] more fixes in Markdown files --- .../changed-features/eta-expansion-spec.md | 2 +- .../implicit-conversions-spec.md | 2 +- .../changed-features/main-functions.md | 22 +++++++----- .../changed-features/match-syntax.md | 10 +++--- .../changed-features/numeric-literals.md | 9 +++-- .../reference/changed-features/operators.md | 20 ++++++++--- .../changed-features/structural-types-spec.md | 7 ++-- .../changed-features/structural-types.md | 16 ++++++++- .../changed-features/type-checking.md | 2 +- .../changed-features/type-inference.md | 5 ++- .../reference/changed-features/wildcards.md | 5 +-- .../contextual/by-name-context-parameters.md | 5 +-- .../reference/contextual/context-bounds.md | 4 +-- .../contextual/context-functions-spec.md | 21 ++++++----- .../reference/contextual/context-functions.md | 2 +- docs/docs/reference/contextual/derivation.md | 4 +-- .../reference/contextual/extension-methods.md | 2 +- docs/docs/reference/contextual/givens.md | 2 +- .../contextual/relationship-implicits.md | 8 ++--- .../docs/reference/contextual/type-classes.md | 6 ++-- .../reference/contextual/using-clauses.md | 20 +++++++++++ .../reference/dropped-features/auto-apply.md | 15 +++++++- .../dropped-features/class-shadowing.md | 7 +++- .../dropped-features/delayed-init.md | 11 +++--- .../docs/reference/dropped-features/macros.md | 2 +- .../dropped-features/nonlocal-returns.md | 13 +++++-- docs/docs/reference/enums/adts.md | 16 ++++++--- docs/docs/reference/enums/desugarEnums.md | 14 ++++---- docs/docs/reference/enums/enums.md | 8 ++--- .../docs/reference/features-classification.md | 8 ++--- .../metaprogramming/erased-terms-spec.md | 36 +++++++++---------- .../reference/metaprogramming/erased-terms.md | 6 ++-- docs/docs/reference/metaprogramming/inline.md | 2 +- docs/docs/reference/metaprogramming/macros.md | 6 ++-- .../metaprogramming/tasty-inspect.md | 2 +- .../dependent-function-types-spec.md | 6 ++-- .../new-types/dependent-function-types.md | 4 +++ .../new-types/intersection-types-spec.md | 18 +++++----- .../new-types/polymorphic-function-types.md | 6 ++-- .../reference/new-types/union-types-spec.md | 18 +++++++--- .../other-new-features/explicit-nulls.md | 5 +-- .../reference/other-new-features/export.md | 14 +++++++- .../other-new-features/indentation.md | 10 +++--- .../other-new-features/opaques-details.md | 8 ++++- .../parameter-untupling-spec.md | 8 +++-- .../other-new-features/parameter-untupling.md | 12 +++++-- .../other-new-features/trait-parameters.md | 2 +- docs/docs/reference/overview.md | 2 +- docs/docs/reference/syntax.md | 10 +++--- 49 files changed, 297 insertions(+), 146 deletions(-) diff --git a/docs/docs/reference/changed-features/eta-expansion-spec.md b/docs/docs/reference/changed-features/eta-expansion-spec.md index 28ac11eef2e8..172c7c1be0be 100644 --- a/docs/docs/reference/changed-features/eta-expansion-spec.md +++ b/docs/docs/reference/changed-features/eta-expansion-spec.md @@ -73,4 +73,4 @@ The method value syntax `m _` is deprecated. ## Reference -For more info, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). +For more information, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). diff --git a/docs/docs/reference/changed-features/implicit-conversions-spec.md b/docs/docs/reference/changed-features/implicit-conversions-spec.md index df76c0b7dbfe..5df0f5f0ac46 100644 --- a/docs/docs/reference/changed-features/implicit-conversions-spec.md +++ b/docs/docs/reference/changed-features/implicit-conversions-spec.md @@ -119,4 +119,4 @@ Resolution](implicit-resolution.md) for more information. For more information about implicit resolution, see [Changes in Implicit Resolution](implicit-resolution.md). Other details are available in -[PR #2065](https://github.com/lampepfl/dotty/pull/2065) +[PR #2065](https://github.com/lampepfl/dotty/pull/2065). diff --git a/docs/docs/reference/changed-features/main-functions.md b/docs/docs/reference/changed-features/main-functions.md index 3a063a17b412..95bab2c00c87 100644 --- a/docs/docs/reference/changed-features/main-functions.md +++ b/docs/docs/reference/changed-features/main-functions.md @@ -4,8 +4,9 @@ title: "Main Methods" --- Scala 3 offers a new way to define programs that can be invoked from the command line: -A `@main` annotation on a method turns this method into an executable program. +A `@main`{.scala} annotation on a method turns this method into an executable program. Example: + ```scala @main def happyBirthday(age: Int, name: String, others: String*) = val suffix = @@ -21,18 +22,21 @@ Example: for other <- others do bldr.append(" and ").append(other) bldr.toString ``` + This would generate a main program `happyBirthday` that could be called like this + ``` > scala happyBirthday 23 Lisa Peter Happy 23rd Birthday, Lisa and Peter! ``` -A `@main` annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main` method can have an arbitrary number of parameters. + +A `@main`{.scala} annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main`{.scala} method can have an arbitrary number of parameters. For each parameter type there must be an instance of the `scala.util.FromString` type class that is used to convert an argument string to the required parameter type. The parameter list of a main method can end in a repeated parameter that then takes all remaining arguments given on the command line. -The program implemented from a `@main` method checks that there are enough arguments on +The program implemented from a `@main`{.scala} method checks that there are enough arguments on the command line to fill in all parameters, and that argument strings are convertible to the required types. If a check fails, the program is terminated with an error message. @@ -46,15 +50,16 @@ Illegal command line after first argument: more arguments expected Illegal command line: java.lang.NumberFormatException: For input string: "sixty" ``` -The Scala compiler generates a program from a `@main` method `f` as follows: +The Scala compiler generates a program from a `@main`{.scala} method `f` as follows: - - It creates a class named `f` in the package where the `@main` method was found + - It creates a class named `f` in the package where the `@main`{.scala} method was found - The class has a static method `main` with the usual signature. It takes an `Array[String]` as argument and returns `Unit`. - The generated `main` method calls method `f` with arguments converted using - methods in the `scala.util.CommandLineParser` object. + methods in the [`scala.util.CommandLineParser` object](https://dotty.epfl.ch/api/scala/util/CommandLineParser$.html). For instance, the `happyBirthDay` method above would generate additional code equivalent to the following class: + ```scala final class happyBirthday: import scala.util.{CommandLineParser => CLP} @@ -67,10 +72,11 @@ final class happyBirthday: catch case error: CLP.ParseError => CLP.showError(error) ``` + **Note**: The `` modifier above expresses that the `main` method is generated as a static method of class `happyBirthDay`. It is not available for user programs in Scala. Regular "static" members are generated in Scala using objects instead. -`@main` methods are the recommended scheme to generate programs that can be invoked from the command line in Scala 3. They replace the previous scheme to write program as objects with a special `App` parent class. In Scala 2, `happyBirthday` could be written also like this: +`@main`{.scala} methods are the recommended scheme to generate programs that can be invoked from the command line in Scala 3. They replace the previous scheme to write program as objects with a special `App` parent class. In Scala 2, `happyBirthday` could be written also like this: ```scala object happyBirthday extends App: @@ -78,5 +84,5 @@ object happyBirthday extends App: ... ``` -The previous functionality of `App`, which relied on the "magic" `DelayedInit` trait, is no longer available. `App` still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build +The previous functionality of `App`, which relied on the "magic" [`DelayedInit`](../dropped-features/delayed-init.md) trait, is no longer available. `App` still exists in limited form for now, but it does not support command line arguments and will be deprecated in the future. If programs need to cross-build between Scala 2 and Scala 3, it is recommended to use an explicit `main` method with an `Array[String]` argument instead. diff --git a/docs/docs/reference/changed-features/match-syntax.md b/docs/docs/reference/changed-features/match-syntax.md index ed4ec87e2380..aec3111240f0 100644 --- a/docs/docs/reference/changed-features/match-syntax.md +++ b/docs/docs/reference/changed-features/match-syntax.md @@ -1,12 +1,12 @@ --- layout: doc-page -title: Match Expressions +title: "Match Expressions" --- The syntactical precedence of match expressions has been changed. -`match` is still a keyword, but it is used like an alphabetical operator. This has several consequences: +`match`{.scala} is still a keyword, but it is used like an alphabetical operator. This has several consequences: -1. `match` expressions can be chained: +1. `match`{.scala} expressions can be chained: ```scala xs match { @@ -29,7 +29,7 @@ The syntactical precedence of match expressions has been changed. case "nonempty" => 1 ``` -2. `match` may follow a period: +2. `match`{.scala} may follow a period: ```scala if xs.match @@ -41,7 +41,7 @@ The syntactical precedence of match expressions has been changed. 3. The scrutinee of a match expression must be an `InfixExpr`. Previously the scrutinee could be followed by a type ascription `: T`, but this is no longer supported. So `x : T match { ... }` - now has to be written `(x: T) match { ... }`. + now has to be written `(x: T) match { ... }`{.scala}. ## Syntax diff --git a/docs/docs/reference/changed-features/numeric-literals.md b/docs/docs/reference/changed-features/numeric-literals.md index 843c348fffa1..0a1590b27b5e 100644 --- a/docs/docs/reference/changed-features/numeric-literals.md +++ b/docs/docs/reference/changed-features/numeric-literals.md @@ -1,14 +1,16 @@ --- layout: doc-page -title: Numeric Literals +title: "Numeric Literals" --- **Note**: This feature is not yet part of the Scala 3 language definition. It can be made available by a language import: + ```scala import scala.language.experimental.genericNumberLiterals ``` -In Scala 2, numeric literals were confined to the primitive numeric types `Int`, `Long`, `Float`, and `Double`. Scala 3 allows to write numeric literals also for user defined types. Example: +In Scala 2, numeric literals were confined to the primitive numeric types `Int`, `Long`, `Float`, and `Double`. Scala 3 allows to write numeric literals also for user-defined types. Example: + ```scala val x: Long = -10_000_000_000 val y: BigInt = 0x123_abc_789_def_345_678_901 @@ -17,6 +19,7 @@ val z: BigDecimal = 110_222_799_799.99 (y: BigInt) match case 123_456_789_012_345_678_901 => ``` + The syntax of numeric literals is the same as before, except there are no pre-set limits how large they can be. @@ -63,7 +66,7 @@ gives a type error, since without an expected type `-10_000_000_000` is treated ### The FromDigits Trait -To allow numeric literals, a type simply has to define a `given` instance of the +To allow numeric literals, a type simply has to define a `given`{.scala} instance of the `scala.util.FromDigits` type class, or one of its subclasses. `FromDigits` is defined as follows: diff --git a/docs/docs/reference/changed-features/operators.md b/docs/docs/reference/changed-features/operators.md index d98da3bed317..9002a04cec2b 100644 --- a/docs/docs/reference/changed-features/operators.md +++ b/docs/docs/reference/changed-features/operators.md @@ -5,13 +5,14 @@ title: "Rules for Operators" The rules for infix operators have changed in some parts: -First, an alphanumeric method can be used as an infix operator only if its definition carries an `infix` modifier. Second, it is recommended (but not enforced) to -augment definitions of symbolic operators with `@targetName` annotations. Finally, +First, an alphanumeric method can be used as an infix operator only if its definition carries an `infix`{.scala} modifier. Second, it is recommended (but not enforced) to +augment definitions of symbolic operators with `@targetName`{.scala} annotations. Finally, a syntax change allows infix operators to be written on the left in a multi-line expression. ## The `infix` Modifier -An `infix` modifier on a method definition allows using the method as an infix operation. Example: +An `infix`{.scala} modifier on a method definition allows using the method as an infix operation. Example: + ```scala import scala.annotation.targetName @@ -40,6 +41,7 @@ s1 * s2 // OK s1 `*` s2 // also OK, but unusual s1.*(s2) // also OK, but unusual ``` + Infix operations involving alphanumeric operators are deprecated, unless one of the following conditions holds: @@ -52,8 +54,9 @@ any Unicode character `c` for which `java.lang.Character.isIdentifierPart(c)` re Infix operations involving symbolic operators are always allowed, so `infix` is redundant for methods with symbolic names. -The `infix` modifier can also be given to a type: -``` +The `infix`{.scala} modifier can also be given to a type: + +```scala infix type or[X, Y] val x: String or Int = ... ``` @@ -107,6 +110,7 @@ It is recommended that definitions of symbolic operators carry a [`@targetName` ## Syntax Change Infix operators can now appear at the start of lines in a multi-line expression. Examples: + ```scala val str = "hello" ++ " world" @@ -117,6 +121,7 @@ def condition = || xs.exists(_ > 0) || xs.isEmpty ``` + Previously, those expressions would have been rejected, since the compiler's semicolon inference would have treated the continuations `++ " world"` or `|| xs.isEmpty` as separate statements. @@ -133,19 +138,24 @@ Example: freezing | boiling ``` + This is recognized as a single infix operation. Compare with: + ```scala freezing !boiling ``` + This is seen as two statements, `freezing` and `!boiling`. The difference is that only the operator in the first example is followed by a space. Another example: + ```scala println("hello") ??? ??? match { case 0 => 1 } ``` + This code is recognized as three different statements. `???` is syntactically a symbolic identifier, but neither of its occurrences is followed by a space and a token that can start an expression. diff --git a/docs/docs/reference/changed-features/structural-types-spec.md b/docs/docs/reference/changed-features/structural-types-spec.md index 489dd795bc9d..4de11e2d5d50 100644 --- a/docs/docs/reference/changed-features/structural-types-spec.md +++ b/docs/docs/reference/changed-features/structural-types-spec.md @@ -30,9 +30,11 @@ the methods `selectDynamic` and `applyDynamic`. The methods could be members of The `selectDynamic` method takes a field name and returns the value associated with that name in the `Selectable`. It should have a signature of the form: + ```scala def selectDynamic(name: String): T ``` + Often, the return type `T` is `Any`. Unlike `scala.Dynamic`, there is no special meaning for an `updateDynamic` method. @@ -41,10 +43,12 @@ Consequently, it is recommended not to define any member called `updateDynamic` The `applyDynamic` method is used for selections that are applied to arguments. It takes a method name and possibly `Class`es representing its parameters types as well as the arguments to pass to the function. Its signature should be of one of the two following forms: + ```scala def applyDynamic(name: String)(args: Any*): T def applyDynamic(name: String, ctags: Class[?]*)(args: Any*): T ``` + Both versions are passed the actual arguments in the `args` parameter. The second version takes in addition a vararg argument of `java.lang.Class`es that identify the method's parameter classes. Such an argument is needed if `applyDynamic` is implemented using Java reflection, but it could be useful in other cases as well. `selectDynamic` and `applyDynamic` can also take additional context parameters in using clauses. These are resolved in the normal way at the callsite. @@ -94,5 +98,4 @@ conversion that can turn `v` into a `Selectable`, and the selection methods coul ## Context -For more info, see [Rethink Structural -Types](https://github.com/lampepfl/dotty/issues/1886). +For more information, see [Rethink Structural Types](https://github.com/lampepfl/dotty/issues/1886). diff --git a/docs/docs/reference/changed-features/structural-types.md b/docs/docs/reference/changed-features/structural-types.md index 0ffbd3f37f8f..a907a126a07e 100644 --- a/docs/docs/reference/changed-features/structural-types.md +++ b/docs/docs/reference/changed-features/structural-types.md @@ -32,6 +32,7 @@ configure how fields and methods should be resolved. ## Example Here's an example of a structural type `Person`: + ```scala class Record(elems: (String, Any)*) extends Selectable: private val fields = elems.toMap @@ -39,12 +40,15 @@ Here's an example of a structural type `Person`: type Person = Record { val name: String; val age: Int } ``` + The type `Person` adds a _refinement_ to its parent type `Record` that defines the two fields `name` and `age`. We say the refinement is _structural_ since `name` and `age` are not defined in the parent type. But they exist nevertheless as members of class `Person`. For instance, the following program would print "Emma is 42 years old.": + ```scala val person = Record("name" -> "Emma", "age" -> 42).asInstanceOf[Person] println(s"${person.name} is ${person.age} years old.") ``` + The parent type `Record` in this example is a generic class that can represent arbitrary records in its `elems` argument. This argument is a sequence of pairs of labels of type `String` and values of type `Any`. When we create a `Person` as a `Record` we have to assert with a typecast @@ -59,12 +63,14 @@ a method `selectDynamic`, which maps a field name to its value. Selecting a structural type member is done by calling this method. The `person.name` and `person.age` selections are translated by the Scala compiler to: + ```scala person.selectDynamic("name").asInstanceOf[String] person.selectDynamic("age").asInstanceOf[Int] ``` Besides `selectDynamic`, a `Selectable` class sometimes also defines a method `applyDynamic`. This can then be used to translate function calls of structural members. So, if `a` is an instance of `Selectable`, a structural call like `a.f(b, c)` would translate to + ```scala a.applyDynamic("f")(b, c) ``` @@ -72,6 +78,7 @@ Besides `selectDynamic`, a `Selectable` class sometimes also defines a method `a ## Using Java Reflection Structural types can also be accessed using [Java reflection](https://www.oracle.com/technical-resources/articles/java/javareflection.html). Example: + ```scala type Closeable = { def close(): Unit } @@ -81,14 +88,17 @@ Structural types can also be accessed using [Java reflection](https://www.oracle class Channel: def close(): Unit ``` + Here, we define a structural type `Closeable` that defines a `close` method. There are various classes that have `close` methods, we just list `FileInputStream` and `Channel` as two examples. It would be easiest if the two classes shared a common interface that factors out the `close` method. But such factorings are often not possible if different libraries are combined in one application. Yet, we can still have methods that work on all classes with a `close` method by using the `Closeable` type. For instance, + ```scala import scala.reflect.Selectable.reflectiveSelectable def autoClose(f: Closeable)(op: Closeable => Unit): Unit = try op(f) finally f.close() ``` + The call `f.close()` has to use Java reflection to identify and call the `close` method in the receiver `f`. This needs to be enabled by an import of `reflectiveSelectable` shown above. What happens "under the hood" is then the following: @@ -122,6 +132,7 @@ the database access example given at the beginning of this document. Local and anonymous classes that extend `Selectable` get more refined types than other classes. Here is an example: + ```scala trait Vehicle extends reflect.Selectable: val wheels: Int @@ -132,12 +143,14 @@ val i3 = new Vehicle: // i3: Vehicle { val range: Int } i3.range ``` -The type of `i3` in this example is `Vehicle { val range: Int }`. Hence, + +The type of `i3` in this example is `Vehicle { val range: Int }`{.scala}. Hence, `i3.range` is well-formed. Since the base class `Vehicle` does not define a `range` field or method, we need structural dispatch to access the `range` field of the anonymous class that initializes `id3`. Structural dispatch is implemented by the base trait `reflect.Selectable` of `Vehicle`, which defines the necessary `selectDynamic` member. `Vehicle` could also extend some other subclass of `scala.Selectable` that implements `selectDynamic` and `applyDynamic` differently. But if it does not extend a `Selectable` at all, the code would no longer typecheck: + ```scala trait Vehicle: val wheels: Int @@ -148,6 +161,7 @@ val i3 = new Vehicle: // i3: Vehicle i3.range // error: range is not a member of `Vehicle` ``` + The difference is that the type of an anonymous class that does not extend `Selectable` is just formed from the parent type(s) of the class, without adding any refinements. Hence, `i3` now has just type `Vehicle` and the selection `i3.range` gives a "member not found" error. diff --git a/docs/docs/reference/changed-features/type-checking.md b/docs/docs/reference/changed-features/type-checking.md index b167a37c44cc..4c9d1f6139b9 100644 --- a/docs/docs/reference/changed-features/type-checking.md +++ b/docs/docs/reference/changed-features/type-checking.md @@ -3,4 +3,4 @@ layout: doc-page title: "Changes in Type Checking" --- -[//]: # todo: fill in +*** **TO BE FILLED IN** *** diff --git a/docs/docs/reference/changed-features/type-inference.md b/docs/docs/reference/changed-features/type-inference.md index 226063912244..b1cd806c0999 100644 --- a/docs/docs/reference/changed-features/type-inference.md +++ b/docs/docs/reference/changed-features/type-inference.md @@ -3,4 +3,7 @@ layout: doc-page title: "Changes in Type Inference" --- -See https://www.youtube.com/watch?v=lMvOykNQ4zs, https://www.youtube.com/watch?v=VV9lPg3fNl8. +For more information, see the two presentations + +* [Scala 3, Type inference and You!](https://www.youtube.com/watch?v=lMvOykNQ4zs) by Guillaume Martres (September 2019) +* [GADTs in Dotty](https://www.youtube.com/watch?v=VV9lPg3fNl8) by Aleksander Boruch-Gruszecki (July 2019). diff --git a/docs/docs/reference/changed-features/wildcards.md b/docs/docs/reference/changed-features/wildcards.md index 38db6174ae43..a17d283bc9af 100644 --- a/docs/docs/reference/changed-features/wildcards.md +++ b/docs/docs/reference/changed-features/wildcards.md @@ -17,7 +17,8 @@ for the type lambda `[X] =>> C[X]`. This makes higher-kinded types easier to use parameter, `F[_]` means `F` is a type constructor whereas used as a type, `F[_]` means it is a wildcard (i.e. existential) type. In the future, `F[_]` will mean the same thing, no matter where it is used. -We pick `?` as a replacement syntax for wildcard types, since it aligns with Java's syntax. +We pick `?` as a replacement syntax for wildcard types, since it aligns with +[Java's syntax](https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html). ### Migration Strategy @@ -40,4 +41,4 @@ option `-Ykind-projector`: available to rewrite one to the other. 3. In Scala 3.3, `*` is removed again, and all type parameter placeholders will be expressed with `_`. -These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using option `-Ykind-projector`. +These rules make it possible to cross build between Scala 2 using the kind projector plugin and Scala 3.0 - 3.2 using the compiler option `-Ykind-projector`. diff --git a/docs/docs/reference/contextual/by-name-context-parameters.md b/docs/docs/reference/contextual/by-name-context-parameters.md index 868ab8a3f08f..549cdb4e08b7 100644 --- a/docs/docs/reference/contextual/by-name-context-parameters.md +++ b/docs/docs/reference/contextual/by-name-context-parameters.md @@ -35,6 +35,7 @@ The precise steps for synthesizing an argument for a by-name context parameter o ```scala given lv: T = ??? ``` + where `lv` is an arbitrary fresh name. 1. This given is not immediately available as candidate for argument inference (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an argument to a by-name context parameter. @@ -51,7 +52,7 @@ In the example above, the definition of `s` would be expanded as follows. ```scala val s = summon[Test.Codec[Option[Int]]]( - optionCodec[Int](using intCodec) + optionCodec[Int](using intCodec) ) ``` @@ -59,5 +60,5 @@ No local given instance was generated because the synthesized argument is not re ### Reference -For more info, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) +For more information, see [Issue #1998](https://github.com/lampepfl/dotty/issues/1998) and the associated [Scala SIP](https://docs.scala-lang.org/sips/byname-implicits.html). diff --git a/docs/docs/reference/contextual/context-bounds.md b/docs/docs/reference/contextual/context-bounds.md index 3c1e2e3b3aa7..4d86976a30ee 100644 --- a/docs/docs/reference/contextual/context-bounds.md +++ b/docs/docs/reference/contextual/context-bounds.md @@ -30,11 +30,11 @@ def g[T <: B : C](x: T): R = ... ## Migration To ease migration, context bounds in Dotty map in Scala 3.0 to old-style implicit parameters -for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. +for which arguments can be passed either with a `(using ...)`{.scala} clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. If the source version is `3.1` and the `-migration` command-line option is set, any pairing of an evidence context parameter stemming from a context bound with a normal argument will give a migration -warning. The warning indicates that a `(using ...)` clause is needed instead. The rewrite can be +warning. The warning indicates that a `(using ...)`{.scala} clause is needed instead. The rewrite can be done automatically under `-rewrite`. ## Syntax diff --git a/docs/docs/reference/contextual/context-functions-spec.md b/docs/docs/reference/contextual/context-functions-spec.md index 1f212c299d4b..d5e1eaa61ca7 100644 --- a/docs/docs/reference/contextual/context-functions-spec.md +++ b/docs/docs/reference/contextual/context-functions-spec.md @@ -5,10 +5,12 @@ title: "Context Functions - More Details" ## Syntax - Type ::= ... - | FunArgTypes ‘?=>’ Type - Expr ::= ... - | FunParams ‘?=>’ Expr +``` +Type ::= ... + | FunArgTypes ‘?=>’ Type +Expr ::= ... + | FunParams ‘?=>’ Expr +``` Context function types associate to the right, e.g. `S ?=> T ?=> U` is the same as `S ?=> (T ?=> U)`. @@ -19,11 +21,13 @@ Context function types are shorthands for class types that define `apply` methods with context parameters. Specifically, the `N`-ary function type `T1, ..., TN => R` is a shorthand for the class type `ContextFunctionN[T1 , ... , TN, R]`. Such class types are assumed to have the following definitions, for any value of `N >= 1`: + ```scala package scala trait ContextFunctionN[-T1 , ... , -TN, +R]: def apply(using x1: T1 , ... , xN: TN): R ``` + Context function types erase to normal function types, so these classes are generated on the fly for typechecking, but not realized in actual code. @@ -40,17 +44,18 @@ The type of the context function literal is `scala.ContextFunctionN[S1, ...,Sn, type of `e`. `T` must be equivalent to a type which does not refer to any of the context parameters `xi`. -The context function literal is evaluated as the instance creation -expression +The context function literal is evaluated as the instance creation expression + ```scala new scala.ContextFunctionN[T1, ..., Tn, T]: def apply(using x1: T1, ..., xn: Tn): T = e ``` + A context parameter may also be a wildcard represented by an underscore `_`. In that case, a fresh name for the parameter is chosen arbitrarily. Note: The closing paragraph of the -[Anonymous Functions section](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-functions) -of Scala 2.12 is subsumed by context function types and should be removed. +[Anonymous Functions section](https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#anonymous-functions) +of Scala 2.13 is subsumed by context function types and should be removed. Context function literals `(x1: T1, ..., xn: Tn) ?=> e` are automatically created for any expression `e` whose expected type is diff --git a/docs/docs/reference/contextual/context-functions.md b/docs/docs/reference/contextual/context-functions.md index 284f07485a98..46b7ffa539ae 100644 --- a/docs/docs/reference/contextual/context-functions.md +++ b/docs/docs/reference/contextual/context-functions.md @@ -148,7 +148,7 @@ val s = ``` ### Reference -For more info, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html), +For more information, see the [blog article](https://www.scala-lang.org/blog/2016/12/07/implicit-function-types.html), (which uses a different syntax that has been superseded). [More details](./context-functions-spec.md) diff --git a/docs/docs/reference/contextual/derivation.md b/docs/docs/reference/contextual/derivation.md index fea8c3355e57..7d542e597795 100644 --- a/docs/docs/reference/contextual/derivation.md +++ b/docs/docs/reference/contextual/derivation.md @@ -1,6 +1,6 @@ --- layout: doc-page -title: Type Class Derivation +title: "Type Class Derivation" --- Type class derivation is a way to automatically generate given instances for type classes which satisfy some simple @@ -353,7 +353,7 @@ ConstrApps ::= ConstrApp {‘with’ ConstrApp} | ConstrApp {‘,’ ConstrApp} ``` -Note: To align `extends` clauses and `derives` clauses, Scala 3 also allows multiple +Note: To align `extends`{.scala} clauses and `derives`{.scala} clauses, Scala 3 also allows multiple extended types to be separated by commas. So the following is now legal: ```scala diff --git a/docs/docs/reference/contextual/extension-methods.md b/docs/docs/reference/contextual/extension-methods.md index e7bddf6dbc21..6a0a2eac0375 100644 --- a/docs/docs/reference/contextual/extension-methods.md +++ b/docs/docs/reference/contextual/extension-methods.md @@ -186,7 +186,7 @@ object IntOpsEx extends IntOps: trait SafeDiv: import IntOpsEx._ // brings safeDiv and safeMod into scope - extension (i: Int) def divide(d: Int) : Option[(Int, Int)] = + extension (i: Int) def divide(d: Int): Option[(Int, Int)] = // extension methods imported and thus in scope (i.safeDiv(d), i.safeMod(d)) match case (Some(d), Some(r)) => Some((d, r)) diff --git a/docs/docs/reference/contextual/givens.md b/docs/docs/reference/contextual/givens.md index 738a2d3e0f29..95cb2969782d 100644 --- a/docs/docs/reference/contextual/givens.md +++ b/docs/docs/reference/contextual/givens.md @@ -66,7 +66,7 @@ use named instances. ## Alias Givens -An alias can be used to define a given instance that is equal to some expression. E.g.: +An alias can be used to define a given instance that is equal to some expression. Example: ```scala given global: ExecutionContext = ForkJoinPool() diff --git a/docs/docs/reference/contextual/relationship-implicits.md b/docs/docs/reference/contextual/relationship-implicits.md index c9a0020fbf63..f79d3204200a 100644 --- a/docs/docs/reference/contextual/relationship-implicits.md +++ b/docs/docs/reference/contextual/relationship-implicits.md @@ -143,7 +143,7 @@ Implicit by-name parameters are not supported in Scala 2, but can be emulated to ### Implicit Conversions -Implicit conversion methods in Scala 2 can be expressed as given instances of the `scala.Conversion` class in Scala 3. E.g. instead of +Implicit conversion methods in Scala 2 can be expressed as given instances of the `scala.Conversion` class in Scala 3. For instance, instead of ```scala implicit def stringToToken(str: String): Token = new Keyword(str) @@ -169,7 +169,7 @@ Implicit classes in Scala 2 are often used to define extension methods, which ar ### Implicit Values Implicit `val` definitions in Scala 2 can be expressed in Scala 3 using a regular `val` definition and an alias given. -E.g., Scala 2's +For instance, Scala 2's ```scala lazy implicit val pos: Position = tree.sourcePos @@ -184,7 +184,7 @@ given Position = pos ### Abstract Implicits -An abstract implicit `val` or `def` in Scala 2 can be expressed in Scala 3 using a regular abstract definition and an alias given. E.g., Scala 2's +An abstract implicit `val` or `def` in Scala 2 can be expressed in Scala 3 using a regular abstract definition and an alias given. For instance, Scala 2's ```scala implicit def symDecorator: SymDecorator @@ -199,7 +199,7 @@ given SymDecorator = symDecorator ## Implementation Status and Timeline -The Scala 3 implementation implements both Scala 2's implicits and the new abstractions. In fact, support for Scala 2's implicits is an essential part of the common language subset between 2.13/2.14 and Scala 3. +The Scala 3 implementation implements both Scala 2's implicits and the new abstractions. In fact, support for Scala 2's implicits is an essential part of the common language subset between 2.13 and Scala 3. Migration to the new abstractions will be supported by making automatic rewritings available. Depending on adoption patterns, old style implicits might start to be deprecated in a version following Scala 3.0. diff --git a/docs/docs/reference/contextual/type-classes.md b/docs/docs/reference/contextual/type-classes.md index e771595a28e5..d29ad1710e09 100644 --- a/docs/docs/reference/contextual/type-classes.md +++ b/docs/docs/reference/contextual/type-classes.md @@ -8,7 +8,7 @@ A _type class_ is an abstract, parameterized type that lets you add new behavior * expressing how a type you don't own (from the standard or 3rd-party library) conforms to such behavior * expressing such a behavior for multiple types without involving sub-typing relationships (one `extends` another) between those types (see: [ad hoc polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) for instance) -Therefore in Scala 3, _type classes_ are just _traits_ with one or more parameters whose implementations are not defined through the `extends` keyword, but by **given instances**. +Therefore in Scala 3, _type classes_ are just _traits_ with one or more parameters whose implementations are not defined through the `extends`{.scala} keyword, but by **given instances**. Here are some examples of common type classes: ### Semigroups and monoids @@ -272,9 +272,9 @@ end readerMonad ### Summary -The definition of a _type class_ is expressed with a parameterised type with abstract members, such as a `trait`. +The definition of a _type class_ is expressed with a parameterised type with abstract members, such as a `trait`{.scala}. The main difference between subtype polymorphism and ad-hoc polymorphism with _type classes_ is how the definition of the _type class_ is implemented, in relation to the type it acts upon. -In the case of a _type class_, its implementation for a concrete type is expressed through a `given` instance definition, which is supplied as an implicit argument alongside the value it acts upon. With subtype polymorphism, the implementation is mixed into the parents of a class, and only a single term is required to perform a polymorphic operation. The type class solution +In the case of a _type class_, its implementation for a concrete type is expressed through a `given`{.scala} instance definition, which is supplied as an implicit argument alongside the value it acts upon. With subtype polymorphism, the implementation is mixed into the parents of a class, and only a single term is required to perform a polymorphic operation. The type class solution takes more effort to set up, but is more extensible: Adding a new interface to a class requires changing the source code of that class. But contrast, instances for type classes can be defined anywhere. diff --git a/docs/docs/reference/contextual/using-clauses.md b/docs/docs/reference/contextual/using-clauses.md index f5ae506c80b1..e76ad8b71693 100644 --- a/docs/docs/reference/contextual/using-clauses.md +++ b/docs/docs/reference/contextual/using-clauses.md @@ -10,16 +10,21 @@ repetitive arguments instead of the programmer having to write them explicitly. For example, with the [given instances](./givens.md) defined previously, a `max` function that works for any arguments for which an ordering exists can be defined as follows: + ```scala def max[T](x: T, y: T)(using ord: Ord[T]): T = if ord.compare(x, y) < 0 then y else x ``` + Here, `ord` is a _context parameter_ introduced with a `using` clause. The `max` function can be applied as follows: + ```scala max(2, 3)(using intOrd) ``` + The `(using intOrd)` part passes `intOrd` as an argument for the `ord` parameter. But the point of context parameters is that this argument can also be left out (and it usually is). So the following applications are equally valid: + ```scala max(2, 3) max(List(1, 2, 3), Nil) @@ -31,10 +36,12 @@ In many situations, the name of a context parameter need not be mentioned explicitly at all, since it is used only in synthesized arguments for other context parameters. In that case one can avoid defining a parameter name and just provide its type. Example: + ```scala def maximum[T](xs: List[T])(using Ord[T]): T = xs.reduceLeft(max) ``` + `maximum` takes a context parameter of type `Ord` only to pass it on as an inferred argument to `max`. The name of the parameter is left out. @@ -43,6 +50,7 @@ Generally, context parameters may be defined either as a full parameter list `(p ## Inferring Complex Arguments Here are two other methods that have a context parameter of type `Ord[T]`: + ```scala def descending[T](using asc: Ord[T]): Ord[T] = new Ord[T]: def compare(x: T, y: T) = asc.compare(y, x) @@ -50,8 +58,10 @@ def descending[T](using asc: Ord[T]): Ord[T] = new Ord[T]: def minimum[T](xs: List[T])(using Ord[T]) = maximum(xs)(using descending) ``` + The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`. With this setup, the following calls are all well-formed, and they all normalize to the last one: + ```scala minimum(xs) maximum(xs)(using descending) @@ -62,22 +72,28 @@ maximum(xs)(using descending(using listOrd(using intOrd))) ## Multiple `using` Clauses There can be several `using` clauses in a definition and `using` clauses can be freely mixed with normal parameter clauses. Example: + ```scala def f(u: Universe)(using ctx: u.Context)(using s: ctx.Symbol, k: ctx.Kind) = ... ``` + Multiple `using` clauses are matched left-to-right in applications. Example: + ```scala object global extends Universe { type Context = ... } given ctx : global.Context with { type Symbol = ...; type Kind = ... } given sym : ctx.Symbol given kind: ctx.Kind + ``` Then the following calls are all valid (and normalize to the last one) + ```scala f(global) f(global)(using ctx) f(global)(using ctx)(using sym, kind) ``` + But `f(global)(using sym, kind)` would give a type error. @@ -85,10 +101,13 @@ But `f(global)(using sym, kind)` would give a type error. The method `summon` in `Predef` returns the given of a specific type. For example, the given instance for `Ord[List[Int]]` is produced by + ```scala summon[Ord[List[Int]]] // reduces to listOrd(using intOrd) ``` + The `summon` method is simply defined as the (non-widening) identity function over a context parameter. + ```scala def summon[T](using x: T): x.type = x ``` @@ -96,6 +115,7 @@ def summon[T](using x: T): x.type = x ## Syntax Here is the new syntax of parameters and arguments seen as a delta from the [standard context free syntax of Scala 3](../syntax.md). `using` is a soft keyword, recognized only at the start of a parameter or argument list. It can be used as a normal identifier everywhere else. + ``` ClsParamClause ::= ... | UsingClsParamClause DefParamClauses ::= ... | UsingParamClause diff --git a/docs/docs/reference/dropped-features/auto-apply.md b/docs/docs/reference/dropped-features/auto-apply.md index d7bbab69329b..9ff9aa648502 100644 --- a/docs/docs/reference/dropped-features/auto-apply.md +++ b/docs/docs/reference/dropped-features/auto-apply.md @@ -5,28 +5,36 @@ title: "Dropped: Auto-Application" Previously an empty argument list `()` was implicitly inserted when calling a nullary method without arguments. Example: + ```scala def next(): T = ... next // is expanded to next() ``` + In Scala 3, this idiom is an error. + ```scala next ^ missing arguments for method next ``` + In Scala 3, the application syntax has to follow exactly the parameter syntax. Excluded from this rule are methods that are defined in Java or that override methods defined in Java. The reason for being more lenient with such methods is that otherwise everyone would have to write + ```scala xs.toString().length() ``` + instead of + ```scala xs.toString.length ``` + The latter is idiomatic Scala because it conforms to the _uniform access principle_. This principle states that one should be able to change an object member from a field to a non-side-effecting method @@ -47,9 +55,11 @@ the correspondence between definition and call was not enforced in Scala so far, there are quite a few method definitions in Scala 2 libraries that use `()` in an inconsistent way. For instance, we find in `scala.math.Numeric` + ```scala def toInt(): Int ``` + whereas `toInt` is written without parameters everywhere else. Enforcing strict parameter correspondence for references to such methods would project the inconsistencies to client code, which @@ -61,12 +71,15 @@ Stricter conformance rules also apply to overriding of nullary methods. It is no longer allowed to override a parameterless method by a nullary method or _vice versa_. Instead, both methods must agree exactly in their parameter lists. + ```scala class A: def next(): Int + class B extends A: def next: Int // overriding error: incompatible type ``` + Methods overriding Java or Scala 2 methods are again exempted from this requirement. @@ -79,4 +92,4 @@ stricter checking. ### Reference -For more info, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). +For more information, see [Issue #2570](https://github.com/lampepfl/dotty/issues/2570) and [PR #2716](https://github.com/lampepfl/dotty/pull/2716). diff --git a/docs/docs/reference/dropped-features/class-shadowing.md b/docs/docs/reference/dropped-features/class-shadowing.md index a733273fc0ed..d1d92a47bcbc 100644 --- a/docs/docs/reference/dropped-features/class-shadowing.md +++ b/docs/docs/reference/dropped-features/class-shadowing.md @@ -4,6 +4,7 @@ title: "Dropped: Class Shadowing" --- Scala 2 so far allowed patterns like this: + ```scala class Base { class Ops { ... } @@ -13,12 +14,16 @@ class Sub extends Base { class Ops { ... } } ``` + Scala 3 rejects this with the error message: + ```scala 6 | class Ops { } | ^ - |class Ops cannot have the same name as class Ops in class Base -- class definitions cannot be overridden + |class Ops cannot have the same name as class Ops in class Base + | -- class definitions cannot be overridden ``` + The issue is that the two `Ops` classes _look_ like one overrides the other, but classes in Scala 2 cannot be overridden. To keep things clean (and its internal operations consistent) the Scala 3 compiler forces you diff --git a/docs/docs/reference/dropped-features/delayed-init.md b/docs/docs/reference/dropped-features/delayed-init.md index fd115ab08db0..ca640185252d 100644 --- a/docs/docs/reference/dropped-features/delayed-init.md +++ b/docs/docs/reference/dropped-features/delayed-init.md @@ -3,24 +3,27 @@ layout: doc-page title: "Dropped: Delayedinit" --- -The special handling of the `DelayedInit` trait is no longer -supported. +The special handling of the `DelayedInit` trait is no longer supported. One consequence is that the `App` class, which used `DelayedInit` is now partially broken. You can still use `App` as a simple way to set up a main program. Example: + ```scala object HelloWorld extends App { - println("Hello, world!") + println("Hello, world!") } ``` + However, the code is now run in the initializer of the object, which on some JVM's means that it will only be interpreted. So, better not use it for benchmarking! Also, if you want to access the command line arguments, you need to use an explicit `main` method for that. + ```scala object Hello: def main(args: Array[String]) = println(s"Hello, ${args(0)}") ``` + On the other hand, Scala 3 offers a convenient alternative to such "program" objects -with [@main methods](../changed-features/main-functions.html). +with [`@main` methods](../changed-features/main-functions.md). diff --git a/docs/docs/reference/dropped-features/macros.md b/docs/docs/reference/dropped-features/macros.md index aaf180ee7e84..ca8d2adfb345 100644 --- a/docs/docs/reference/dropped-features/macros.md +++ b/docs/docs/reference/dropped-features/macros.md @@ -12,4 +12,4 @@ Additionally, the contents of code can be inspected and created with a more comp * `inline` has been [implemented](../metaprogramming/inline.md) in Scala 3. * Quotes `'{ ... }` and splices `${ ... }` has been [implemented](../metaprogramming/macros.md) in Scala 3. - * [TASTy reflect](../metaprogramming/tasty-reflect.md) provides more complex tree based APIs to inspect or create quoted code. +* [TASTy reflect](../metaprogramming/tasty-reflect.md) provides more complex tree based APIs to inspect or create quoted code. diff --git a/docs/docs/reference/dropped-features/nonlocal-returns.md b/docs/docs/reference/dropped-features/nonlocal-returns.md index e3af0d1de2d1..9ef49c635c84 100644 --- a/docs/docs/reference/dropped-features/nonlocal-returns.md +++ b/docs/docs/reference/dropped-features/nonlocal-returns.md @@ -7,10 +7,19 @@ Returning from nested anonymous functions has been deprecated. Nonlocal returns are implemented by throwing and catching `scala.runtime.NonLocalReturnException`-s. This is rarely what is intended by the programmer. It can be problematic because of the hidden performance cost of throwing and catching exceptions. Furthermore, it is a leaky implementation: a catch-all exception handler can intercept a `NonLocalReturnException`. -A drop-in library replacement is provided in `scala.util.control.NonLocalReturns`: +A drop-in library replacement is provided in [`scala.util.control.NonLocalReturns`](http://dotty.epfl.ch/api/scala/util/control/NonLocalReturns$.html). Example: ```scala import scala.util.control.NonLocalReturns._ -returning { ... throwReturn(x) ... } +extension [T](xs: List[T]) + def has(elem: T): Boolean = returning { + for x <- xs do + if x == elem then throwReturn(true) + false + } + +@main def test = + val xs = List(1, 2, 3, 4, 5) + assert(xs.has(2) == xs.contains(2)) ``` diff --git a/docs/docs/reference/enums/adts.md b/docs/docs/reference/enums/adts.md index f12d53c97cd0..5cf6ad167bb8 100644 --- a/docs/docs/reference/enums/adts.md +++ b/docs/docs/reference/enums/adts.md @@ -19,7 +19,7 @@ parameterized with a value parameter `x`. It is a shorthand for writing a case class that extends `Option`. Since `None` is not parameterized, it is treated as a normal enum value. -The `extends` clauses that were omitted in the example above can also +The `extends`{.scala} clauses that were omitted in the example above can also be given explicitly: ```scala @@ -30,12 +30,12 @@ enum Option[+T]: 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 +class are minimized in a compiler-generated `extends`{.scala} clause whereas all contravariant type parameters are maximized. If `Option` was non-variant, 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` +As for normal enum values, the cases of an `enum`{.scala} are all defined in +the `enum`{.scala}s companion object. So it's `Option.Some` and `Option.None` unless the definitions are "pulled out" with an import: ```scala @@ -98,12 +98,15 @@ below: The following `View` enum has a contravariant type parameter `T` and a single case `Refl`, representing a function mapping a type `T` to itself: + ```scala enum View[-T]: case Refl(f: T => T) ``` + The definition of `Refl` is incorrect, as it uses contravariant type `T` in the covariant result position of a function type, leading to the following error: + ```scala -- Error: View.scala:2:12 -------- 2 | case Refl(f: T => T) @@ -111,7 +114,9 @@ function type, leading to the following error: |contravariant type T occurs in covariant position in type T => T of value f |enum case Refl requires explicit declaration of type T to resolve this issue. ``` + Because `Refl` does not declare explicit parameters, it looks to the compiler like the following: + ```scala enum View[-T]: case Refl[/*synthetic*/-T1](f: T1 => T1) extends View[T1] @@ -126,6 +131,7 @@ enum View[-T]: - case Refl(f: T => T) + case Refl[R](f: R => R) extends View[R] ``` + Above, type `R` is chosen as the parameter for `Refl` to highlight that it has a different meaning to type `T` in `View`, but any name will do. @@ -163,4 +169,4 @@ The changes are specified below as deltas with respect to the Scala syntax given ### Reference -For more info, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). +For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970). diff --git a/docs/docs/reference/enums/desugarEnums.md b/docs/docs/reference/enums/desugarEnums.md index ea8faf1774ad..064ff8f5708f 100644 --- a/docs/docs/reference/enums/desugarEnums.md +++ b/docs/docs/reference/enums/desugarEnums.md @@ -23,11 +23,11 @@ some terminology and notational conventions: Simple cases and value cases are collectively called _singleton cases_. -The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val` definitions. +The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val`{.scala} definitions. There are nine desugaring rules. Rule (1) desugars enum definitions. Rules -(2) and (3) desugar simple cases. Rules (4) to (6) define `extends` clauses for cases that -are missing them. Rules (7) to (9) define how such cases with `extends` clauses +(2) and (3) desugar simple cases. Rules (4) to (6) define `extends`{.scala} clauses for cases that +are missing them. Rules (7) to (9) define how such cases with `extends`{.scala} clauses map into `case class`es or `val`s. 1. An `enum` definition @@ -82,7 +82,7 @@ map into `case class`es or `val`s. ``` where `Bi` is `Li` if `Vi = '+'` and `Ui` if `Vi = '-'`. This result is then further rewritten with rule (8). Simple cases of enums with non-variant type - parameters are not permitted (however value cases with explicit `extends` clause are) + parameters are not permitted (however value cases with explicit `extends`{.scala} clause are) 5. A class case without an extends clause ```scala @@ -191,7 +191,7 @@ The `ordinal` method is only generated if the enum does not extend from `java.la ### Scopes for Enum Cases -A case in an `enum` is treated similarly to a secondary constructor. It can access neither the enclosing `enum` using `this`, nor its value parameters or instance members using simple +A case in an `enum`{.scala} is treated similarly to a secondary constructor. It can access neither the enclosing `enum`{.scala} using `this`, nor its value parameters or instance members using simple identifiers. Even though translated enum cases are located in the enum's companion object, referencing @@ -202,7 +202,7 @@ A Java-compatible enum is an enum that extends `java.lang.Enum`. The translation It is a compile-time error for a Java-compatible enum to have class cases. -Cases such as `case C` expand to a `@static val` as opposed to a `val`. This allows them to be generated as static fields of the enum type, thus ensuring they are represented the same way as Java enums. +Cases such as `case C`{.scala} expand to a `@static val`{.scala} as opposed to a `val`{.scala}. This allows them to be generated as static fields of the enum type, thus ensuring they are represented the same way as Java enums. ### Other Rules @@ -210,5 +210,5 @@ Cases such as `case C` expand to a `@static val` as opposed to a `val`. This all `scala.reflect.Enum`. This ensures that the only cases of an enum are the ones that are explicitly declared in it. - - If an enum case has an `extends` clause, the enum class must be one of the + - If an enum case has an `extends`{.scala} clause, the enum class must be one of the classes that's extended. diff --git a/docs/docs/reference/enums/enums.md b/docs/docs/reference/enums/enums.md index 278036272731..a08fc77a0d13 100644 --- a/docs/docs/reference/enums/enums.md +++ b/docs/docs/reference/enums/enums.md @@ -110,7 +110,7 @@ For a more in-depth example of using Scala 3 enums from Java, see [this test](ht ### Implementation -Enums are represented as `sealed` classes that extend the `scala.reflect.Enum` trait. +Enums are represented as `sealed`{.scala} classes that extend the `scala.reflect.Enum` trait. This trait defines a single public method, `ordinal`: ```scala @@ -123,7 +123,7 @@ transparent trait Enum extends Any, Product, Serializable: def ordinal: Int ``` -Enum values with `extends` clauses get expanded to anonymous class instances. +Enum values with `extends`{.scala} clauses get expanded to anonymous class instances. For instance, the `Venus` value above would be defined like this: ```scala @@ -133,7 +133,7 @@ val Venus: Planet = new Planet(4.869E24, 6051800.0): override def toString: String = "Venus" ``` -Enum values without `extends` clauses all share a single implementation +Enum values without `extends`{.scala} clauses all share a single implementation that can be instantiated using a private method that takes a tag and a name as arguments. For instance, the first definition of value `Color.Red` above would expand to: @@ -144,5 +144,5 @@ val Red: Color = $new(0, "Red") ### Reference -For more info, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and +For more information, see [Issue #1970](https://github.com/lampepfl/dotty/issues/1970) and [PR #4003](https://github.com/lampepfl/dotty/pull/4003). diff --git a/docs/docs/reference/features-classification.md b/docs/docs/reference/features-classification.md index 70fe386323ec..1b729987a980 100644 --- a/docs/docs/reference/features-classification.md +++ b/docs/docs/reference/features-classification.md @@ -34,12 +34,12 @@ Since these are additions, there's generally no migration cost for old code. An These constructs replace existing constructs with the aim of making the language safer and simpler to use, and to promote uniformity in code style. - - [Trait Parameters](other-new-features/trait-parameters.md) replace [early initializers](dropped-features/early-initializers.md) with a more generally useful construct. - - [Given Instances](contextual/givens.md) + - [Trait parameters](other-new-features/trait-parameters.md) replace [early initializers](dropped-features/early-initializers.md) with a more generally useful construct. + - [Given instances](contextual/givens.md) replace implicit objects and defs, focussing on intent over mechanism. - [Using Clauses](contextual/using-clauses.md) replace implicit parameters, avoiding their ambiguities. - - [Extension Methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. - - [Opaque Type Aliases](other-new-features/opaques.md) replace most uses + - [Extension methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. + - [Opaque type aliases](other-new-features/opaques.md) replace most uses of value classes while guaranteeing absence of boxing. - [Top-level definitions](dropped-features/package-objects.md) replace package objects, dropping syntactic boilerplate. - [Export clauses](other-new-features/export.md) diff --git a/docs/docs/reference/metaprogramming/erased-terms-spec.md b/docs/docs/reference/metaprogramming/erased-terms-spec.md index 2813ab9941d8..3b8f42b222b9 100644 --- a/docs/docs/reference/metaprogramming/erased-terms-spec.md +++ b/docs/docs/reference/metaprogramming/erased-terms-spec.md @@ -5,10 +5,10 @@ title: "Erased Terms Spec" ## Rules -1. The `erased` modifier can appear: +1. The `erased`{.scala} modifier can appear: * At the start of a parameter block of a method, function or class * In a method definition - * In a `val` definition (but not `lazy val` or `var`) + * In a `val`{.scala} definition (but not `lazy val`{.scala} or `var`{.scala}) ```scala erased val x = ... @@ -23,39 +23,39 @@ title: "Erased Terms Spec" ``` -2. A reference to an `erased` definition can only be used - * Inside the expression of argument to an `erased` parameter - * Inside the body of an `erased` `val` or `def` +2. A reference to an `erased`{.scala} definition can only be used + * Inside the expression of argument to an `erased`{.scala} parameter + * Inside the body of an `erased`{.scala} `val`{.scala} or `def`{.scala} 3. Functions - * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R` - * `(given erased x1: T1, x2: T2, ..., xN: TN) => y: (given erased T1, T2, ..., TN) => R` - * `(given erased T1) => R <:< erased T1 => R` - * `(given erased T1, T2) => R <:< (erased T1, T2) => R` + * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R`{.scala} + * `(given erased x1: T1, x2: T2, ..., xN: TN) => y: (given erased T1, T2, ..., TN) => R`{.scala} + * `(given erased T1) => R <:< erased T1 => R`{.scala} + * `(given erased T1, T2) => R <:< (erased T1, T2) => R`{.scala} * ... - Note that there is no subtype relation between `(erased T) => R` and `T => R` (or `(given erased T) => R` and `(given T) => R`) + Note that there is no subtype relation between `(erased T) => R`{.scala} and `T => R` (or `(given erased T) => R`{.scala} and `(given T) => R`{.scala}) 4. Eta expansion - if `def f(erased x: T): U` then `f: (erased T) => U`. + if `def f(erased x: T): U`{.scala} then `f: (erased T) => U`{.scala}. 5. Erasure Semantics - * All `erased` parameters are removed from the function - * All argument to `erased` parameters are not passed to the function - * All `erased` definitions are removed - * All `(erased T1, T2, ..., TN) => R` and `(given erased T1, T2, ..., TN) => R` become `() => R` + * All `erased`{.scala} parameters are removed from the function + * All argument to `erased`{.scala} parameters are not passed to the function + * All `erased`{.scala} definitions are removed + * All `(erased T1, T2, ..., TN) => R`{.scala} and `(given erased T1, T2, ..., TN) => R`{.scala} become `() => R`{.scala} 6. Overloading - Method with `erased` parameters will follow the normal overloading constraints after erasure. + Method with `erased`{.scala} parameters will follow the normal overloading constraints after erasure. 7. Overriding - * Member definitions overriding each other must both be `erased` or not be `erased` - * `def foo(x: T): U` cannot be overridden by `def foo(erased x: T): U` and vice-versa + * Member definitions overriding each other must both be `erased`{.scala} or not be `erased`{.scala} + * `def foo(x: T): U`{.scala} cannot be overridden by `def foo(erased x: T): U`{.scala} and vice-versa diff --git a/docs/docs/reference/metaprogramming/erased-terms.md b/docs/docs/reference/metaprogramming/erased-terms.md index dde296ebff83..67ea4422e725 100644 --- a/docs/docs/reference/metaprogramming/erased-terms.md +++ b/docs/docs/reference/metaprogramming/erased-terms.md @@ -65,8 +65,8 @@ def methodWithErasedInt2(erased i: Int): Int = methodWithErasedInt1(i) // OK ``` -Not only parameters can be marked as erased, `val` and `def` can also be marked -with `erased`. These will also only be usable as arguments to `erased` +Not only parameters can be marked as erased, `val`{.scala} and `def`{.scala} can also be marked +with `erased`{.scala}. These will also only be usable as arguments to `erased`{.scala} parameters. ```scala @@ -153,7 +153,7 @@ object Machine: ``` Note that in [Inline](./inline.md) we discussed `erasedValue` and inline -matches. `erasedValue` is implemented with `erased`, so the state machine above +matches. `erasedValue` is implemented with `erased`{.scala}, so the state machine above can be encoded as follows: ```scala diff --git a/docs/docs/reference/metaprogramming/inline.md b/docs/docs/reference/metaprogramming/inline.md index bb87d7792a18..ba18f55d76d8 100644 --- a/docs/docs/reference/metaprogramming/inline.md +++ b/docs/docs/reference/metaprogramming/inline.md @@ -623,5 +623,5 @@ transparent inline def summonInline[T]: T = summonFrom { ### Reference -For more info, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), +For more information, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), which explains how `summonFrom`'s predecessor (implicit matches) can be used for typelevel programming and code specialization and [PR #7201](https://github.com/lampepfl/dotty/pull/7201) which explains the new `summonFrom` syntax. diff --git a/docs/docs/reference/metaprogramming/macros.md b/docs/docs/reference/metaprogramming/macros.md index eb443338d9df..a91767fc3fe6 100644 --- a/docs/docs/reference/metaprogramming/macros.md +++ b/docs/docs/reference/metaprogramming/macros.md @@ -158,9 +158,11 @@ is legal because it is spliced, then quoted. They can be used as follows: ```scala -val f1: Expr[Int => String] = to((x: Expr[Int]) => '{ $x.toString }) // '{ (x: Int) => x.toString } +val f1: Expr[Int => String] = + to((x: Expr[Int]) => '{ $x.toString }) // '{ (x: Int) => x.toString } -val f2: Expr[Int] => Expr[String] = from('{ (x: Int) => x.toString }) // (x: Expr[Int]) => '{ ((x: Int) => x.toString)($x) } +val f2: Expr[Int] => Expr[String] = + from('{ (x: Int) => x.toString }) // (x: Expr[Int]) => '{ ((x: Int) => x.toString)($x) } f2('{2}) // '{ ((x: Int) => x.toString)(2) } ``` diff --git a/docs/docs/reference/metaprogramming/tasty-inspect.md b/docs/docs/reference/metaprogramming/tasty-inspect.md index a1657fdc6c20..a9abfd48b12f 100644 --- a/docs/docs/reference/metaprogramming/tasty-inspect.md +++ b/docs/docs/reference/metaprogramming/tasty-inspect.md @@ -4,7 +4,7 @@ title: "TASTy Inspection" --- ```scala -libraryDependencies += "ch.epfl.lamp" %% "scala3-tasty-inspector" % scalaVersion.value +libraryDependencies += "org.scala-lang" %% "scala3-tasty-inspector" % scalaVersion.value ``` TASTy files contain the full typed tree of a class including source positions 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 48f3102c8890..944fec44ff86 100644 --- a/docs/docs/reference/new-types/dependent-function-types-spec.md +++ b/docs/docs/reference/new-types/dependent-function-types-spec.md @@ -3,7 +3,7 @@ layout: doc-page title: "Dependent Function Types - More Details" --- -Initial implementation in [#3464](https://github.com/lampepfl/dotty/pull/3464) +Initial implementation in [PR #3464](https://github.com/lampepfl/dotty/pull/3464). ## Syntax @@ -37,8 +37,8 @@ one of regular functions. Eta expansion is naturally generalized to produce dependent function types for methods with dependent result types. Dependent functions can be implicit, and generalize to arity `N > 22` in the -same way that other functions do, see [the corresponding -documentation](../dropped-features/limit22.md). +same way that other functions do, see +[the corresponding documentation](../dropped-features/limit22.md). ## Examples diff --git a/docs/docs/reference/new-types/dependent-function-types.md b/docs/docs/reference/new-types/dependent-function-types.md index 8e7a79ae2b37..8374c9c41794 100644 --- a/docs/docs/reference/new-types/dependent-function-types.md +++ b/docs/docs/reference/new-types/dependent-function-types.md @@ -5,6 +5,7 @@ title: "Dependent Function Types" A dependent function type is a function type whose result depends on the function's parameters. For example: + ```scala trait Entry { type Key; val key: Key } @@ -14,6 +15,7 @@ val extractor: (e: Entry) => e.Key = extractKey // a dependent function value // ^^^^^^^^^^^^^^^^^^^ // a dependent function type ``` + Scala already has _dependent methods_, i.e. methods where the result type refers to some of the parameters of the method. Method `extractKey` is an example. Its result type, `e.Key` refers to its @@ -37,8 +39,10 @@ instance of the `Function1` trait (i.e. `Function1[A, B]`) and analogously for functions with more parameters. Dependent functions are also represented as instances of these traits, but they get an additional refinement. In fact, the dependent function type above is just syntactic sugar for + ```scala Function1[Entry, Entry#Key]: def apply(e: Entry): e.Key ``` + [More details](./dependent-function-types-spec.md) diff --git a/docs/docs/reference/new-types/intersection-types-spec.md b/docs/docs/reference/new-types/intersection-types-spec.md index e4b92388e2db..1ad0ed62601d 100644 --- a/docs/docs/reference/new-types/intersection-types-spec.md +++ b/docs/docs/reference/new-types/intersection-types-spec.md @@ -84,20 +84,20 @@ below in pseudocode: ``` |S & T| = glb(|S|, |T|) -glb(JArray(A), JArray(B)) = JArray(glb(A, B)) -glb(JArray(T), _) = JArray(T) -glb(_, JArray(T)) = JArray(T) -glb(A, B) = A if A extends B -glb(A, B) = B if B extends A -glb(A, _) = A if A is not a trait -glb(_, B) = B if B is not a trait -glb(A, _) = A // use first +glb(JArray(A), JArray(B)) = JArray(glb(A, B)) +glb(JArray(T), _) = JArray(T) +glb(_, JArray(T)) = JArray(T) +glb(A, B) = A if A extends B +glb(A, B) = B if B extends A +glb(A, _) = A if A is not a trait +glb(_, B) = B if B is not a trait +glb(A, _) = A // use first ``` In the above, `|T|` means the erased type of `T`, `JArray` refers to the type of Java Array. -See also: `TypeErasure#erasedGlb` +See also: [`TypeErasure#erasedGlb`](https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/TypeErasure.scala#L289). ## Relationship with Compound Type (`with`) diff --git a/docs/docs/reference/new-types/polymorphic-function-types.md b/docs/docs/reference/new-types/polymorphic-function-types.md index 9b6abb9b6dd5..5b7e5344a713 100644 --- a/docs/docs/reference/new-types/polymorphic-function-types.md +++ b/docs/docs/reference/new-types/polymorphic-function-types.md @@ -5,6 +5,7 @@ title: "Polymorphic Function Types" A polymorphic function type is a function type which accepts type parameters. For example: + ```scala // A polymorphic method: def foo[A](xs: List[A]): List[A] = xs.reverse @@ -15,6 +16,7 @@ val bar: [A] => List[A] => List[A] // a polymorphic function type = [A] => (xs: List[A]) => foo[A](xs) ``` + Scala already has _polymorphic methods_, i.e. methods which accepts type parameters. Method `foo` above is an example, accepting a type parameter `A`. So far, it @@ -87,5 +89,5 @@ A good way of understanding the difference is to notice that whereas polymorphic functions are applied in terms_**: One would call the function `bar` above by passing it a type argument `bar[Int]` _within a method body_. -On the other hand, given a type lambda such as `type F = [A] =>> List[A]`, -one would call `F` _within a type expression_, as in `type Bar = F[Int]`. +On the other hand, given a type lambda such as `type F = [A] =>> List[A]`{.scala}, +one would call `F` _within a type expression_, as in `type Bar = F[Int]`{.scala}. diff --git a/docs/docs/reference/new-types/union-types-spec.md b/docs/docs/reference/new-types/union-types-spec.md index ad1fe6b8f57e..92cc6e6eff94 100644 --- a/docs/docs/reference/new-types/union-types-spec.md +++ b/docs/docs/reference/new-types/union-types-spec.md @@ -15,11 +15,15 @@ lower precedence than `:` as used in typed patterns, this means that: ```scala case _: A | B => ... ``` + is still equivalent to: + ```scala case (_: A) | B => ... ``` + and not to: + ```scala case _: (A | B) => ... ``` @@ -29,18 +33,21 @@ case _: (A | B) => ... - `A` is always a subtype of `A | B` for all `A`, `B`. - If `A <: C` and `B <: C` then `A | B <: C` - Like `&`, `|` is commutative and associative: + ```scala A | B =:= B | A A | (B | C) =:= (A | B) | C ``` + - `&` is distributive over `|`: + ```scala A & (B | C) =:= A & B | A & C ``` From these rules it follows that the _least upper bound_ (LUB) of a set of types is the union of these types. This replaces the -[definition of least upper bound in the Scala 2 specification](https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#least-upper-bounds-and-greatest-lower-bounds). +[definition of least upper bound in the Scala 2 specification](https://www.scala-lang.org/files/archive/spec/2.13/03-types.html#least-upper-bounds-and-greatest-lower-bounds). ## Motivation @@ -80,7 +87,7 @@ The join of `A | B` is `C[A | B] & D` ## Type inference -When inferring the result type of a definition (`val`, `var`, or `def`) and the +When inferring the result type of a definition (`val`{.scala}, `var`{.scala}, or `def`{.scala}) and the type we are about to infer is a union type, then we replace it by its join. Similarly, when instantiating a type argument, if the corresponding type parameter is not upper-bounded by a union type and the type we are about to @@ -92,9 +99,10 @@ which are "too precise" can lead to unintuitive typechecking issues later on. Note: Since this behavior limits the usability of union types, it might be changed in the future. For example by not widening unions that have been explicitly written down by the user and not inferred, or by not widening a type -argument when the corresponding type parameter is covariant. See -[#2330](https://github.com/lampepfl/dotty/pull/2330) and -[#4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. +argument when the corresponding type parameter is covariant. + +See [PR #2330](https://github.com/lampepfl/dotty/pull/2330) and +[Issue #4867](https://github.com/lampepfl/dotty/issues/4867) for further discussions. ### Example diff --git a/docs/docs/reference/other-new-features/explicit-nulls.md b/docs/docs/reference/other-new-features/explicit-nulls.md index a651107f59d6..b05055c5c26a 100644 --- a/docs/docs/reference/other-new-features/explicit-nulls.md +++ b/docs/docs/reference/other-new-features/explicit-nulls.md @@ -11,10 +11,10 @@ This means the following code will no longer typecheck: val x: String = null // error: found `Null`, but required `String` ``` -Instead, to mark a type as nullable we use a [union type](https://dotty.epfl.ch/docs/reference/new-types/union-types.html) +Instead, to mark a type as nullable we use a [union type](../new-types/union-types.md) ```scala -val x: String|Null = null // ok +val x: String | Null = null // ok ``` Explicit nulls are enabled via a `-Yexplicit-nulls` flag. @@ -37,6 +37,7 @@ After erasure, `Null` remains a subtype of all reference types (as forced by the The new type system is unsound with respect to `null`. This means there are still instances where an expression has a non-nullable type like `String`, but its value is actually `null`. The unsoundness happens because uninitialized fields in a class start out as `null`: + ```scala class C: val f: String = foo(f) diff --git a/docs/docs/reference/other-new-features/export.md b/docs/docs/reference/other-new-features/export.md index b770cbf99c03..b5b8c71e2c2b 100644 --- a/docs/docs/reference/other-new-features/export.md +++ b/docs/docs/reference/other-new-features/export.md @@ -4,6 +4,7 @@ title: "Export Clauses" --- An export clause defines aliases for selected members of an object. Example: + ```scala class BitMap class InkJet @@ -26,22 +27,29 @@ class Copier: def status: List[String] = printUnit.status ++ scanUnit.status ``` + The two `export` clauses define the following _export aliases_ in class `Copier`: + ```scala final def scan(): BitMap = scanUnit.scan() final def print(bits: BitMap): Unit = printUnit.print(bits) final type PrinterType = printUnit.PrinterType ``` + They can be accessed inside `Copier` as well as from outside: + ```scala val copier = new Copier copier.print(copier.scan()) ``` + An export clause has the same format as an import clause. Its general form is: + ```scala export path . { sel_1, ..., sel_n } export given path . { sel_1, ..., sel_n } ``` + It consists of a qualifier expression `path`, which must be a stable identifier, followed by one or more selectors `sel_i` that identify what gets an alias. Selectors can be of one of the following forms: @@ -93,7 +101,7 @@ Export clauses can appear in classes or they can appear at the top-level. An exp It is a standard recommendation to prefer composition over inheritance. This is really an application of the principle of least power: Composition treats components as blackboxes whereas inheritance can affect the internal workings of components through overriding. Sometimes the close coupling implied by inheritance is the best solution for a problem, but where this is not necessary the looser coupling of composition is better. -So far, object oriented languages including Scala made it much easier to use inheritance than composition. Inheritance only requires an `extends` clause whereas composition required a verbose elaboration of a sequence of forwarders. So in that sense, object-oriented languages are pushing +So far, object-oriented languages including Scala made it much easier to use inheritance than composition. Inheritance only requires an `extends` clause whereas composition required a verbose elaboration of a sequence of forwarders. So in that sense, object-oriented languages are pushing programmers to a solution that is often too powerful. Export clauses redress the balance. They make composition relationships as concise and easy to express as inheritance relationships. Export clauses also offer more flexibility than extends clauses since members can be renamed or omitted. Export clauses also fill a gap opened by the shift from package objects to top-level definitions. One occasionally useful idiom that gets lost in this shift is a package object inheriting from some class. The idiom is often used in a facade like pattern, to make members @@ -114,17 +122,21 @@ Export ::= ‘export’ [‘given’] ImportExpr {‘,’ ImportExpr} Export clauses raise questions about the order of elaboration during type checking. Consider the following example: + ```scala class B { val c: Int } object a { val b = new B } export a._ export b._ ``` + Is the `export b._` clause legal? If yes, what does it export? Is it equivalent to `export a.b._`? What about if we swap the last two clauses? + ``` export b._ export a._ ``` + To avoid tricky questions like these, we fix the elaboration order of exports as follows. Export clauses are processed when the type information of the enclosing object or class is completed. Completion so far consisted of the following steps: diff --git a/docs/docs/reference/other-new-features/indentation.md b/docs/docs/reference/other-new-features/indentation.md index 6c5d6a3617f9..2ebbe817b9ea 100644 --- a/docs/docs/reference/other-new-features/indentation.md +++ b/docs/docs/reference/other-new-features/indentation.md @@ -83,9 +83,9 @@ There are two rules: - the first token on the next line is not a [leading infix operator](../changed-features/operators.md). - If an `` is inserted, the top element is popped from `IW`. - If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `` tokens - may be inserted in a row. + If an `` is inserted, the top element is popped from `IW`. + If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `` tokens + may be inserted in a row. An `` is also inserted if the next token following a statement sequence starting with an `` closes an indentation region, i.e. is one of `then`, `else`, `do`, `catch`, `finally`, `yield`, `}`, `)`, `]` or `case`. @@ -134,9 +134,11 @@ new A: package p: def a = 1 + package q: def b = 2 ``` + In each case, the `:` at the end of line can be replaced without change of meaning by a pair of braces that enclose the following indented definition(s). The syntax changes allowing this are as follows: @@ -356,7 +358,7 @@ Significant indentation is enabled by default. It can be turned off by giving an The Scala 3 compiler can rewrite source code to indented code and back. When invoked with options `-rewrite -indent` it will rewrite braces to indented regions where possible. When invoked with options `-rewrite -noindent` it will rewrite in the reverse direction, inserting braces for indentation regions. -The `-indent` option only works on [new-style syntax](./control-syntax.html). So to go from old-style syntax to new-style indented code one has to invoke the compiler twice, first with options `-rewrite -new-syntax`, then again with options +The `-indent` option only works on [new-style syntax](./control-syntax.md). So to go from old-style syntax to new-style indented code one has to invoke the compiler twice, first with options `-rewrite -new-syntax`, then again with options `-rewrite -indent`. To go in the opposite direction, from indented code to old-style syntax, it's `-rewrite -noindent`, followed by `-rewrite -old-syntax`. ### Variant: Indentation Marker `:` diff --git a/docs/docs/reference/other-new-features/opaques-details.md b/docs/docs/reference/other-new-features/opaques-details.md index 723d319e2f3e..af7483d9f799 100644 --- a/docs/docs/reference/other-new-features/opaques-details.md +++ b/docs/docs/reference/other-new-features/opaques-details.md @@ -9,6 +9,7 @@ title: "Opaque Type Aliases: More Details" Modifier ::= ... | ‘opaque’ ``` + `opaque` is a [soft modifier](../soft-modifier.md). It can still be used as a normal identifier when it is not in front of a definition keyword. Opaque type aliases must be members of classes, traits, or objects, or they are defined @@ -17,9 +18,11 @@ at the top-level. They cannot be defined in local blocks. ### Type Checking The general form of a (monomorphic) opaque type alias is + ```scala opaque type T >: L <: U = R ``` + where the lower bound `L` and the upper bound `U` may be missing, in which case they are assumed to be `scala.Nothing` and `scala.Any`, respectively. If bounds are given, it is checked that the right hand side `R` conforms to them, i.e. `L <: R` and `R <: U`. F-bounds are not supported for opaque type aliases: `T` is not allowed to appear in `L` or `U`. Inside the scope of the alias definition, the alias is transparent: `T` is treated @@ -28,15 +31,18 @@ as a normal alias of `R`. Outside its scope, the alias is treated as the abstrac type T >: L <: U ``` A special case arises if the opaque type alias is defined in an object. Example: -``` + +```scala object o: opaque type T = R ``` + In this case we have inside the object (also for non-opaque types) that `o.T` is equal to `T` or its expanded form `o.this.T`. Equality is understood here as mutual subtyping, i.e. `o.T <: o.this.T` and `o.this.T <: T`. Furthermore, we have by the rules of opaque type aliases that `o.this.T` equals `R`. The two equalities compose. That is, inside `o`, it is also known that `o.T` is equal to `R`. This means the following code type-checks: + ```scala object o: opaque type T = Int diff --git a/docs/docs/reference/other-new-features/parameter-untupling-spec.md b/docs/docs/reference/other-new-features/parameter-untupling-spec.md index 42ca89ed5361..21e1aebd6a12 100644 --- a/docs/docs/reference/other-new-features/parameter-untupling-spec.md +++ b/docs/docs/reference/other-new-features/parameter-untupling-spec.md @@ -13,6 +13,7 @@ val xs: List[(Int, Int)] and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to their sum. Previously, the best way to do this was with a pattern-matching decomposition: + ```scala xs.map { case (x, y) => x + y @@ -25,7 +26,9 @@ xs.map { (x, y) => x + y } ``` + or, equivalently: + ```scala xs.map(_ + _) ``` @@ -51,6 +54,7 @@ can in turn be adapted to the expected type with auto-tupling. #### Term adaptation If the function + ```scala (p1: T1, ..., pn: Tn) => e ``` @@ -75,9 +79,9 @@ Translation of such a tuples would use the `apply` method on the tuple to access Code like this could not be written before, hence the new notation would not be ambiguous after adoption. Though it is possible that someone has written an implicit conversion form `(T1, ..., Tn) => R` to `TupleN[T1, ..., Tn] => R` -for some `n`. This change could be detected and fixed by `Scalafix`. Furthermore, such conversion would probably +for some `n`. This change could be detected and fixed by [`Scalafix`](https://scalacenter.github.io/scalafix/). Furthermore, such conversion would probably be doing the same translation (semantically) but in a less efficient way. ### Reference -For more info see [Issue #897](https://github.com/lampepfl/dotty/issues/897). +For more information, see [Issue #897](https://github.com/lampepfl/dotty/issues/897). diff --git a/docs/docs/reference/other-new-features/parameter-untupling.md b/docs/docs/reference/other-new-features/parameter-untupling.md index 24400f178e34..5f8f322c5126 100644 --- a/docs/docs/reference/other-new-features/parameter-untupling.md +++ b/docs/docs/reference/other-new-features/parameter-untupling.md @@ -4,34 +4,42 @@ title: "Parameter Untupling" --- Say you have a list of pairs + ```scala val xs: List[(Int, Int)] ``` + and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to their sum. Previously, the best way to do this was with a pattern-matching decomposition: + ```scala xs map { case (x, y) => x + y } ``` + While correct, this is also inconvenient and confusing, since the `case` suggests that the pattern match could fail. As a shorter and clearer alternative Scala 3 now allows + ```scala xs.map { (x, y) => x + y } ``` + or, equivalently: + ```scala xs.map(_ + _) ``` + Generally, a function value with `n > 1` parameters is converted to a pattern-matching closure using `case` if the expected type is a unary function type of the form `((T_1, ..., T_n)) => U`. -### Reference +## Reference -For more info see: +For more information see: * [More details](./parameter-untupling-spec.md) * [Issue #897](https://github.com/lampepfl/dotty/issues/897). diff --git a/docs/docs/reference/other-new-features/trait-parameters.md b/docs/docs/reference/other-new-features/trait-parameters.md index c82c1e225f1c..1655e338b32c 100644 --- a/docs/docs/reference/other-new-features/trait-parameters.md +++ b/docs/docs/reference/other-new-features/trait-parameters.md @@ -54,4 +54,4 @@ class E extends Greeting("Bob"), FormalGreeting ## Reference -For more info, see [Scala SIP 25](http://docs.scala-lang.org/sips/pending/trait-parameters.html). +For more information, see [Scala SIP 25](http://docs.scala-lang.org/sips/pending/trait-parameters.html). diff --git a/docs/docs/reference/overview.md b/docs/docs/reference/overview.md index 38c27f0622d1..9add67e6b947 100644 --- a/docs/docs/reference/overview.md +++ b/docs/docs/reference/overview.md @@ -36,7 +36,7 @@ These constructs replace existing constructs with the aim of making the language - [Given instances](contextual/givens.md) replace implicit objects and defs, focussing on intent over mechanism. - [Using clauses](contextual/using-clauses.md) replace implicit parameters, avoiding their ambiguities. - - [Extension Methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. + - [Extension methods](contextual/extension-methods.md) replace implicit classes with a clearer and simpler mechanism. - [Opaque type aliases](other-new-features/opaques.md) replace most uses of value classes while guaranteeing absence of boxing. - [Top-level definitions](dropped-features/package-objects.md) replace package objects, dropping syntactic boilerplate. diff --git a/docs/docs/reference/syntax.md b/docs/docs/reference/syntax.md index 6764ed477179..b37ecf514a1c 100644 --- a/docs/docs/reference/syntax.md +++ b/docs/docs/reference/syntax.md @@ -28,9 +28,9 @@ letter ::= upper | lower “… and Unicode categories Lo, Lt, Nl” digit ::= ‘0’ | … | ‘9’ paren ::= ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’ | ‘'(’ | ‘'[’ | ‘'{’ delim ::= ‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’ -opchar ::= “printableChar not matched by (whiteSpace | upper | lower | - letter | digit | paren | delim | opchar | Unicode_Sm | - Unicode_So)” +opchar ::= “printableChar not matched by (whiteSpace | upper | + lower | letter | digit | paren | delim | opchar | + Unicode_Sm | Unicode_So)” printableChar ::= “all characters in [\u0020, \u007F] inclusive” charEscapeSeq ::= ‘\’ (‘b’ | ‘t’ | ‘n’ | ‘f’ | ‘r’ | ‘"’ | ‘'’ | ‘\’) @@ -93,8 +93,8 @@ colonEol ::= ": at end of line that can start a template body" abstract case catch class def do else enum export extends false final finally for given if implicit import lazy match new -null object package private protected override return -super sealed then throw trait true try +null object override package private protected return +sealed super then throw trait true try type val var while with yield : = <- => <: :> # @ =>> ?=> From 6bc9dd0ec132360f0a4427744c81860c42b24b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Wed, 30 Dec 2020 20:38:04 +0100 Subject: [PATCH 2/3] addressed review comment --- docs/docs/reference/overview.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/reference/overview.md b/docs/docs/reference/overview.md index 9add67e6b947..6cd62f39edcd 100644 --- a/docs/docs/reference/overview.md +++ b/docs/docs/reference/overview.md @@ -107,11 +107,11 @@ Most aspects of old-style implicit resolution are still available under `-source These are additions to the language that make it more powerful or pleasant to use. - [Enums](enums/enums.md) provide concise syntax for enumerations and [algebraic data types](enums/adts.md). - - [Parameter Untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. - - [Dependent Function Types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. - - [Polymorphic Function Types](new-types/polymorphic-function-types.md) generalize polymorphic methods to polymorphic function values and types. _Current status_: There is a proposal and a merged prototype implementation, but the implementation has not been finalized (it is notably missing type inference support). - - [Kind Polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. - - [`@targetName` Annotations](other-new-features/targetName.md) make it easier to interoperate with code written in other languages and give more flexibility for avoiding name clashes. + - [Parameter untupling](other-new-features/parameter-untupling.md) avoids having to use `case` for tupled parameter destructuring. + - [Dependent function types](new-types/dependent-function-types.md) generalize dependent methods to dependent function values and types. + - [Polymorphic function types](new-types/polymorphic-function-types.md) generalize polymorphic methods to polymorphic function values and types. _Current status_: There is a proposal and a merged prototype implementation, but the implementation has not been finalized (it is notably missing type inference support). + - [Kind polymorphism](other-new-features/kind-polymorphism.md) allows the definition of operators working equally on types and type constructors. + - [`@targetName` annotations](other-new-features/targetName.md) make it easier to interoperate with code written in other languages and give more flexibility for avoiding name clashes. ## Metaprogramming From d96b2a2a5567448e57eb3fa2e595694aac9d8af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Micheloud?= Date: Fri, 1 Jan 2021 13:35:34 +0100 Subject: [PATCH 3/3] postponed addition of attribute {.scala} --- .../changed-features/main-functions.md | 12 +++---- .../changed-features/match-syntax.md | 8 ++--- .../changed-features/numeric-literals.md | 2 +- .../reference/changed-features/operators.md | 8 ++--- .../changed-features/structural-types.md | 2 +- .../reference/contextual/context-bounds.md | 4 +-- docs/docs/reference/contextual/derivation.md | 2 +- .../docs/reference/contextual/type-classes.md | 6 ++-- docs/docs/reference/enums/adts.md | 8 ++--- docs/docs/reference/enums/desugarEnums.md | 14 ++++---- docs/docs/reference/enums/enums.md | 6 ++-- .../metaprogramming/erased-terms-spec.md | 36 +++++++++---------- .../reference/metaprogramming/erased-terms.md | 6 ++-- .../new-types/polymorphic-function-types.md | 4 +-- .../reference/new-types/union-types-spec.md | 2 +- 15 files changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/docs/reference/changed-features/main-functions.md b/docs/docs/reference/changed-features/main-functions.md index 95bab2c00c87..3fc00ce3da92 100644 --- a/docs/docs/reference/changed-features/main-functions.md +++ b/docs/docs/reference/changed-features/main-functions.md @@ -4,7 +4,7 @@ title: "Main Methods" --- Scala 3 offers a new way to define programs that can be invoked from the command line: -A `@main`{.scala} annotation on a method turns this method into an executable program. +A `@main` annotation on a method turns this method into an executable program. Example: ```scala @@ -30,13 +30,13 @@ This would generate a main program `happyBirthday` that could be called like thi Happy 23rd Birthday, Lisa and Peter! ``` -A `@main`{.scala} annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main`{.scala} method can have an arbitrary number of parameters. +A `@main` annotated method can be written either at the top-level or in a statically accessible object. The name of the program is in each case the name of the method, without any object prefixes. The `@main` method can have an arbitrary number of parameters. For each parameter type there must be an instance of the `scala.util.FromString` type class that is used to convert an argument string to the required parameter type. The parameter list of a main method can end in a repeated parameter that then takes all remaining arguments given on the command line. -The program implemented from a `@main`{.scala} method checks that there are enough arguments on +The program implemented from a `@main` method checks that there are enough arguments on the command line to fill in all parameters, and that argument strings are convertible to the required types. If a check fails, the program is terminated with an error message. @@ -50,9 +50,9 @@ Illegal command line after first argument: more arguments expected Illegal command line: java.lang.NumberFormatException: For input string: "sixty" ``` -The Scala compiler generates a program from a `@main`{.scala} method `f` as follows: +The Scala compiler generates a program from a `@main` method `f` as follows: - - It creates a class named `f` in the package where the `@main`{.scala} method was found + - It creates a class named `f` in the package where the `@main` method was found - The class has a static method `main` with the usual signature. It takes an `Array[String]` as argument and returns `Unit`. - The generated `main` method calls method `f` with arguments converted using @@ -76,7 +76,7 @@ final class happyBirthday: **Note**: The `` modifier above expresses that the `main` method is generated as a static method of class `happyBirthDay`. It is not available for user programs in Scala. Regular "static" members are generated in Scala using objects instead. -`@main`{.scala} methods are the recommended scheme to generate programs that can be invoked from the command line in Scala 3. They replace the previous scheme to write program as objects with a special `App` parent class. In Scala 2, `happyBirthday` could be written also like this: +`@main` methods are the recommended scheme to generate programs that can be invoked from the command line in Scala 3. They replace the previous scheme to write program as objects with a special `App` parent class. In Scala 2, `happyBirthday` could be written also like this: ```scala object happyBirthday extends App: diff --git a/docs/docs/reference/changed-features/match-syntax.md b/docs/docs/reference/changed-features/match-syntax.md index aec3111240f0..440925b52643 100644 --- a/docs/docs/reference/changed-features/match-syntax.md +++ b/docs/docs/reference/changed-features/match-syntax.md @@ -4,9 +4,9 @@ title: "Match Expressions" --- The syntactical precedence of match expressions has been changed. -`match`{.scala} is still a keyword, but it is used like an alphabetical operator. This has several consequences: +`match` is still a keyword, but it is used like an alphabetical operator. This has several consequences: -1. `match`{.scala} expressions can be chained: +1. `match` expressions can be chained: ```scala xs match { @@ -29,7 +29,7 @@ The syntactical precedence of match expressions has been changed. case "nonempty" => 1 ``` -2. `match`{.scala} may follow a period: +2. `match` may follow a period: ```scala if xs.match @@ -41,7 +41,7 @@ The syntactical precedence of match expressions has been changed. 3. The scrutinee of a match expression must be an `InfixExpr`. Previously the scrutinee could be followed by a type ascription `: T`, but this is no longer supported. So `x : T match { ... }` - now has to be written `(x: T) match { ... }`{.scala}. + now has to be written `(x: T) match { ... }`. ## Syntax diff --git a/docs/docs/reference/changed-features/numeric-literals.md b/docs/docs/reference/changed-features/numeric-literals.md index 0a1590b27b5e..d9c9af042b54 100644 --- a/docs/docs/reference/changed-features/numeric-literals.md +++ b/docs/docs/reference/changed-features/numeric-literals.md @@ -66,7 +66,7 @@ gives a type error, since without an expected type `-10_000_000_000` is treated ### The FromDigits Trait -To allow numeric literals, a type simply has to define a `given`{.scala} instance of the +To allow numeric literals, a type simply has to define a `given` instance of the `scala.util.FromDigits` type class, or one of its subclasses. `FromDigits` is defined as follows: diff --git a/docs/docs/reference/changed-features/operators.md b/docs/docs/reference/changed-features/operators.md index 9002a04cec2b..50801f5aef7c 100644 --- a/docs/docs/reference/changed-features/operators.md +++ b/docs/docs/reference/changed-features/operators.md @@ -5,13 +5,13 @@ title: "Rules for Operators" The rules for infix operators have changed in some parts: -First, an alphanumeric method can be used as an infix operator only if its definition carries an `infix`{.scala} modifier. Second, it is recommended (but not enforced) to -augment definitions of symbolic operators with `@targetName`{.scala} annotations. Finally, +First, an alphanumeric method can be used as an infix operator only if its definition carries an `infix` modifier. Second, it is recommended (but not enforced) to +augment definitions of symbolic operators with `@targetName` annotations. Finally, a syntax change allows infix operators to be written on the left in a multi-line expression. ## The `infix` Modifier -An `infix`{.scala} modifier on a method definition allows using the method as an infix operation. Example: +An `infix` modifier on a method definition allows using the method as an infix operation. Example: ```scala import scala.annotation.targetName @@ -54,7 +54,7 @@ any Unicode character `c` for which `java.lang.Character.isIdentifierPart(c)` re Infix operations involving symbolic operators are always allowed, so `infix` is redundant for methods with symbolic names. -The `infix`{.scala} modifier can also be given to a type: +The `infix` modifier can also be given to a type: ```scala infix type or[X, Y] diff --git a/docs/docs/reference/changed-features/structural-types.md b/docs/docs/reference/changed-features/structural-types.md index a907a126a07e..9a056fb2beee 100644 --- a/docs/docs/reference/changed-features/structural-types.md +++ b/docs/docs/reference/changed-features/structural-types.md @@ -144,7 +144,7 @@ val i3 = new Vehicle: // i3: Vehicle { val range: Int } i3.range ``` -The type of `i3` in this example is `Vehicle { val range: Int }`{.scala}. Hence, +The type of `i3` in this example is `Vehicle { val range: Int }`. Hence, `i3.range` is well-formed. Since the base class `Vehicle` does not define a `range` field or method, we need structural dispatch to access the `range` field of the anonymous class that initializes `id3`. Structural dispatch is implemented by the base trait `reflect.Selectable` of `Vehicle`, which defines the necessary `selectDynamic` member. diff --git a/docs/docs/reference/contextual/context-bounds.md b/docs/docs/reference/contextual/context-bounds.md index 4d86976a30ee..3c1e2e3b3aa7 100644 --- a/docs/docs/reference/contextual/context-bounds.md +++ b/docs/docs/reference/contextual/context-bounds.md @@ -30,11 +30,11 @@ def g[T <: B : C](x: T): R = ... ## Migration To ease migration, context bounds in Dotty map in Scala 3.0 to old-style implicit parameters -for which arguments can be passed either with a `(using ...)`{.scala} clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. +for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above. If the source version is `3.1` and the `-migration` command-line option is set, any pairing of an evidence context parameter stemming from a context bound with a normal argument will give a migration -warning. The warning indicates that a `(using ...)`{.scala} clause is needed instead. The rewrite can be +warning. The warning indicates that a `(using ...)` clause is needed instead. The rewrite can be done automatically under `-rewrite`. ## Syntax diff --git a/docs/docs/reference/contextual/derivation.md b/docs/docs/reference/contextual/derivation.md index 7d542e597795..6c8b59125333 100644 --- a/docs/docs/reference/contextual/derivation.md +++ b/docs/docs/reference/contextual/derivation.md @@ -353,7 +353,7 @@ ConstrApps ::= ConstrApp {‘with’ ConstrApp} | ConstrApp {‘,’ ConstrApp} ``` -Note: To align `extends`{.scala} clauses and `derives`{.scala} clauses, Scala 3 also allows multiple +Note: To align `extends` clauses and `derives` clauses, Scala 3 also allows multiple extended types to be separated by commas. So the following is now legal: ```scala diff --git a/docs/docs/reference/contextual/type-classes.md b/docs/docs/reference/contextual/type-classes.md index d29ad1710e09..e771595a28e5 100644 --- a/docs/docs/reference/contextual/type-classes.md +++ b/docs/docs/reference/contextual/type-classes.md @@ -8,7 +8,7 @@ A _type class_ is an abstract, parameterized type that lets you add new behavior * expressing how a type you don't own (from the standard or 3rd-party library) conforms to such behavior * expressing such a behavior for multiple types without involving sub-typing relationships (one `extends` another) between those types (see: [ad hoc polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) for instance) -Therefore in Scala 3, _type classes_ are just _traits_ with one or more parameters whose implementations are not defined through the `extends`{.scala} keyword, but by **given instances**. +Therefore in Scala 3, _type classes_ are just _traits_ with one or more parameters whose implementations are not defined through the `extends` keyword, but by **given instances**. Here are some examples of common type classes: ### Semigroups and monoids @@ -272,9 +272,9 @@ end readerMonad ### Summary -The definition of a _type class_ is expressed with a parameterised type with abstract members, such as a `trait`{.scala}. +The definition of a _type class_ is expressed with a parameterised type with abstract members, such as a `trait`. The main difference between subtype polymorphism and ad-hoc polymorphism with _type classes_ is how the definition of the _type class_ is implemented, in relation to the type it acts upon. -In the case of a _type class_, its implementation for a concrete type is expressed through a `given`{.scala} instance definition, which is supplied as an implicit argument alongside the value it acts upon. With subtype polymorphism, the implementation is mixed into the parents of a class, and only a single term is required to perform a polymorphic operation. The type class solution +In the case of a _type class_, its implementation for a concrete type is expressed through a `given` instance definition, which is supplied as an implicit argument alongside the value it acts upon. With subtype polymorphism, the implementation is mixed into the parents of a class, and only a single term is required to perform a polymorphic operation. The type class solution takes more effort to set up, but is more extensible: Adding a new interface to a class requires changing the source code of that class. But contrast, instances for type classes can be defined anywhere. diff --git a/docs/docs/reference/enums/adts.md b/docs/docs/reference/enums/adts.md index 5cf6ad167bb8..6bfb188b349d 100644 --- a/docs/docs/reference/enums/adts.md +++ b/docs/docs/reference/enums/adts.md @@ -19,7 +19,7 @@ parameterized with a value parameter `x`. It is a shorthand for writing a case class that extends `Option`. Since `None` is not parameterized, it is treated as a normal enum value. -The `extends`{.scala} clauses that were omitted in the example above can also +The `extends` clauses that were omitted in the example above can also be given explicitly: ```scala @@ -30,12 +30,12 @@ enum Option[+T]: 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`{.scala} clause whereas all +class are minimized in a compiler-generated `extends` clause whereas all contravariant type parameters are maximized. If `Option` was non-variant, you would need to give the extends clause of `None` explicitly. -As for normal enum values, the cases of an `enum`{.scala} are all defined in -the `enum`{.scala}s companion object. So it's `Option.Some` and `Option.None` +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` unless the definitions are "pulled out" with an import: ```scala diff --git a/docs/docs/reference/enums/desugarEnums.md b/docs/docs/reference/enums/desugarEnums.md index 064ff8f5708f..ea8faf1774ad 100644 --- a/docs/docs/reference/enums/desugarEnums.md +++ b/docs/docs/reference/enums/desugarEnums.md @@ -23,11 +23,11 @@ some terminology and notational conventions: Simple cases and value cases are collectively called _singleton cases_. -The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val`{.scala} definitions. +The desugaring rules imply that class cases are mapped to case classes, and singleton cases are mapped to `val` definitions. There are nine desugaring rules. Rule (1) desugars enum definitions. Rules -(2) and (3) desugar simple cases. Rules (4) to (6) define `extends`{.scala} clauses for cases that -are missing them. Rules (7) to (9) define how such cases with `extends`{.scala} clauses +(2) and (3) desugar simple cases. Rules (4) to (6) define `extends` clauses for cases that +are missing them. Rules (7) to (9) define how such cases with `extends` clauses map into `case class`es or `val`s. 1. An `enum` definition @@ -82,7 +82,7 @@ map into `case class`es or `val`s. ``` where `Bi` is `Li` if `Vi = '+'` and `Ui` if `Vi = '-'`. This result is then further rewritten with rule (8). Simple cases of enums with non-variant type - parameters are not permitted (however value cases with explicit `extends`{.scala} clause are) + parameters are not permitted (however value cases with explicit `extends` clause are) 5. A class case without an extends clause ```scala @@ -191,7 +191,7 @@ The `ordinal` method is only generated if the enum does not extend from `java.la ### Scopes for Enum Cases -A case in an `enum`{.scala} is treated similarly to a secondary constructor. It can access neither the enclosing `enum`{.scala} using `this`, nor its value parameters or instance members using simple +A case in an `enum` is treated similarly to a secondary constructor. It can access neither the enclosing `enum` using `this`, nor its value parameters or instance members using simple identifiers. Even though translated enum cases are located in the enum's companion object, referencing @@ -202,7 +202,7 @@ A Java-compatible enum is an enum that extends `java.lang.Enum`. The translation It is a compile-time error for a Java-compatible enum to have class cases. -Cases such as `case C`{.scala} expand to a `@static val`{.scala} as opposed to a `val`{.scala}. This allows them to be generated as static fields of the enum type, thus ensuring they are represented the same way as Java enums. +Cases such as `case C` expand to a `@static val` as opposed to a `val`. This allows them to be generated as static fields of the enum type, thus ensuring they are represented the same way as Java enums. ### Other Rules @@ -210,5 +210,5 @@ Cases such as `case C`{.scala} expand to a `@static val`{.scala} as opposed to a `scala.reflect.Enum`. This ensures that the only cases of an enum are the ones that are explicitly declared in it. - - If an enum case has an `extends`{.scala} clause, the enum class must be one of the + - If an enum case has an `extends` clause, the enum class must be one of the classes that's extended. diff --git a/docs/docs/reference/enums/enums.md b/docs/docs/reference/enums/enums.md index a08fc77a0d13..fff3c721f163 100644 --- a/docs/docs/reference/enums/enums.md +++ b/docs/docs/reference/enums/enums.md @@ -110,7 +110,7 @@ For a more in-depth example of using Scala 3 enums from Java, see [this test](ht ### Implementation -Enums are represented as `sealed`{.scala} classes that extend the `scala.reflect.Enum` trait. +Enums are represented as `sealed` classes that extend the `scala.reflect.Enum` trait. This trait defines a single public method, `ordinal`: ```scala @@ -123,7 +123,7 @@ transparent trait Enum extends Any, Product, Serializable: def ordinal: Int ``` -Enum values with `extends`{.scala} clauses get expanded to anonymous class instances. +Enum values with `extends` clauses get expanded to anonymous class instances. For instance, the `Venus` value above would be defined like this: ```scala @@ -133,7 +133,7 @@ val Venus: Planet = new Planet(4.869E24, 6051800.0): override def toString: String = "Venus" ``` -Enum values without `extends`{.scala} clauses all share a single implementation +Enum values without `extends` clauses all share a single implementation that can be instantiated using a private method that takes a tag and a name as arguments. For instance, the first definition of value `Color.Red` above would expand to: diff --git a/docs/docs/reference/metaprogramming/erased-terms-spec.md b/docs/docs/reference/metaprogramming/erased-terms-spec.md index 3b8f42b222b9..2813ab9941d8 100644 --- a/docs/docs/reference/metaprogramming/erased-terms-spec.md +++ b/docs/docs/reference/metaprogramming/erased-terms-spec.md @@ -5,10 +5,10 @@ title: "Erased Terms Spec" ## Rules -1. The `erased`{.scala} modifier can appear: +1. The `erased` modifier can appear: * At the start of a parameter block of a method, function or class * In a method definition - * In a `val`{.scala} definition (but not `lazy val`{.scala} or `var`{.scala}) + * In a `val` definition (but not `lazy val` or `var`) ```scala erased val x = ... @@ -23,39 +23,39 @@ title: "Erased Terms Spec" ``` -2. A reference to an `erased`{.scala} definition can only be used - * Inside the expression of argument to an `erased`{.scala} parameter - * Inside the body of an `erased`{.scala} `val`{.scala} or `def`{.scala} +2. A reference to an `erased` definition can only be used + * Inside the expression of argument to an `erased` parameter + * Inside the body of an `erased` `val` or `def` 3. Functions - * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R`{.scala} - * `(given erased x1: T1, x2: T2, ..., xN: TN) => y: (given erased T1, T2, ..., TN) => R`{.scala} - * `(given erased T1) => R <:< erased T1 => R`{.scala} - * `(given erased T1, T2) => R <:< (erased T1, T2) => R`{.scala} + * `(erased x1: T1, x2: T2, ..., xN: TN) => y : (erased T1, T2, ..., TN) => R` + * `(given erased x1: T1, x2: T2, ..., xN: TN) => y: (given erased T1, T2, ..., TN) => R` + * `(given erased T1) => R <:< erased T1 => R` + * `(given erased T1, T2) => R <:< (erased T1, T2) => R` * ... - Note that there is no subtype relation between `(erased T) => R`{.scala} and `T => R` (or `(given erased T) => R`{.scala} and `(given T) => R`{.scala}) + Note that there is no subtype relation between `(erased T) => R` and `T => R` (or `(given erased T) => R` and `(given T) => R`) 4. Eta expansion - if `def f(erased x: T): U`{.scala} then `f: (erased T) => U`{.scala}. + if `def f(erased x: T): U` then `f: (erased T) => U`. 5. Erasure Semantics - * All `erased`{.scala} parameters are removed from the function - * All argument to `erased`{.scala} parameters are not passed to the function - * All `erased`{.scala} definitions are removed - * All `(erased T1, T2, ..., TN) => R`{.scala} and `(given erased T1, T2, ..., TN) => R`{.scala} become `() => R`{.scala} + * All `erased` parameters are removed from the function + * All argument to `erased` parameters are not passed to the function + * All `erased` definitions are removed + * All `(erased T1, T2, ..., TN) => R` and `(given erased T1, T2, ..., TN) => R` become `() => R` 6. Overloading - Method with `erased`{.scala} parameters will follow the normal overloading constraints after erasure. + Method with `erased` parameters will follow the normal overloading constraints after erasure. 7. Overriding - * Member definitions overriding each other must both be `erased`{.scala} or not be `erased`{.scala} - * `def foo(x: T): U`{.scala} cannot be overridden by `def foo(erased x: T): U`{.scala} and vice-versa + * Member definitions overriding each other must both be `erased` or not be `erased` + * `def foo(x: T): U` cannot be overridden by `def foo(erased x: T): U` and vice-versa diff --git a/docs/docs/reference/metaprogramming/erased-terms.md b/docs/docs/reference/metaprogramming/erased-terms.md index 67ea4422e725..dde296ebff83 100644 --- a/docs/docs/reference/metaprogramming/erased-terms.md +++ b/docs/docs/reference/metaprogramming/erased-terms.md @@ -65,8 +65,8 @@ def methodWithErasedInt2(erased i: Int): Int = methodWithErasedInt1(i) // OK ``` -Not only parameters can be marked as erased, `val`{.scala} and `def`{.scala} can also be marked -with `erased`{.scala}. These will also only be usable as arguments to `erased`{.scala} +Not only parameters can be marked as erased, `val` and `def` can also be marked +with `erased`. These will also only be usable as arguments to `erased` parameters. ```scala @@ -153,7 +153,7 @@ object Machine: ``` Note that in [Inline](./inline.md) we discussed `erasedValue` and inline -matches. `erasedValue` is implemented with `erased`{.scala}, so the state machine above +matches. `erasedValue` is implemented with `erased`, so the state machine above can be encoded as follows: ```scala diff --git a/docs/docs/reference/new-types/polymorphic-function-types.md b/docs/docs/reference/new-types/polymorphic-function-types.md index 5b7e5344a713..1be8baca17ad 100644 --- a/docs/docs/reference/new-types/polymorphic-function-types.md +++ b/docs/docs/reference/new-types/polymorphic-function-types.md @@ -89,5 +89,5 @@ A good way of understanding the difference is to notice that whereas polymorphic functions are applied in terms_**: One would call the function `bar` above by passing it a type argument `bar[Int]` _within a method body_. -On the other hand, given a type lambda such as `type F = [A] =>> List[A]`{.scala}, -one would call `F` _within a type expression_, as in `type Bar = F[Int]`{.scala}. +On the other hand, given a type lambda such as `type F = [A] =>> List[A]`, +one would call `F` _within a type expression_, as in `type Bar = F[Int]`. diff --git a/docs/docs/reference/new-types/union-types-spec.md b/docs/docs/reference/new-types/union-types-spec.md index 92cc6e6eff94..4349c136bd60 100644 --- a/docs/docs/reference/new-types/union-types-spec.md +++ b/docs/docs/reference/new-types/union-types-spec.md @@ -87,7 +87,7 @@ The join of `A | B` is `C[A | B] & D` ## Type inference -When inferring the result type of a definition (`val`{.scala}, `var`{.scala}, or `def`{.scala}) and the +When inferring the result type of a definition (`val`, `var`, or `def`) and the type we are about to infer is a union type, then we replace it by its join. Similarly, when instantiating a type argument, if the corresponding type parameter is not upper-bounded by a union type and the type we are about to