diff --git a/docs/docs/reference/changed-features/implicit-conversions-spec.md b/docs/docs/reference/changed-features/implicit-conversions-spec.md index 47cfd941bf02..b4ab97355036 100644 --- a/docs/docs/reference/changed-features/implicit-conversions-spec.md +++ b/docs/docs/reference/changed-features/implicit-conversions-spec.md @@ -12,7 +12,7 @@ defined by either: - An `implicit def` which has type `S => T` or `(=> S) => T` - An implicit value which has type `Conversion[S, T]` -The standard library defines an abstract class `Conversion`: +The standard library defines an abstract class [`Conversion`](https://scala-lang.org/api/3.x/scala/Conversion.html): ```scala package scala @@ -86,7 +86,7 @@ Note that implicit conversions are also affected by the [changes to implicit res ## Motivation for the changes -The introduction of [`scala.Conversion`](https://github.com/lampepfl/dotty/blob/master/library/src/scala/Conversion.scala) +The introduction of [`scala.Conversion`](https://scala-lang.org/api/3.x/scala/Conversion.html) in Scala 3 and the decision to restrict implicit values of this type to be considered as potential views comes from the desire to remove surprising behavior from the language: @@ -102,7 +102,7 @@ This snippet contains a type error. The right-hand side of `val x` does not conform to type `String`. In Scala 2, the compiler will use `m` as an implicit conversion from `Int` to `String`, whereas Scala 3 will report a type error, because `Map` isn't an instance of -`Conversion`. +[`Conversion`](https://scala-lang.org/api/3.x/scala/Conversion.html). ## Migration path diff --git a/docs/docs/reference/changed-features/implicit-conversions.md b/docs/docs/reference/changed-features/implicit-conversions.md index 2ee2583d3cd8..69737d5b6bf9 100644 --- a/docs/docs/reference/changed-features/implicit-conversions.md +++ b/docs/docs/reference/changed-features/implicit-conversions.md @@ -28,9 +28,10 @@ Defining an implicit conversion will emit a warning unless the import ## Examples -The first example is taken from `scala.Predef`. Thanks to this -implicit conversion, it is possible to pass a `scala.Int` to a Java -method that expects a `java.lang.Integer` +The first example is taken from [`scala.Predef`](https://scala-lang.org/api/3.x/scala/Predef$.html). +Thanks to this implicit conversion, it is possible to pass a +[`scala.Int`](https://scala-lang.org/api/3.x/scala/Int.html) +to a Java method that expects a `java.lang.Integer` ```scala import scala.language.implicitConversions diff --git a/docs/docs/reference/changed-features/implicit-resolution.md b/docs/docs/reference/changed-features/implicit-resolution.md index 435104a12024..cf8af361b787 100644 --- a/docs/docs/reference/changed-features/implicit-resolution.md +++ b/docs/docs/reference/changed-features/implicit-resolution.md @@ -110,7 +110,7 @@ which means that the alternative `c` would be chosen as solution! Scala 2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement the analogue of a "negated" search in implicit resolution, where a query `Q1` fails if some other query `Q2` succeeds and `Q1` succeeds if `Q2` fails. With the new cleaned up behavior -these techniques no longer work. But there is now a new special type `scala.util.NotGiven` +these techniques no longer work. But there is now a new special type [`scala.util.NotGiven`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) which implements negation directly. For any query type `Q`, `NotGiven[Q]` succeeds if and only if the implicit search for `Q` fails. diff --git a/docs/docs/reference/changed-features/interpolation-escapes.md b/docs/docs/reference/changed-features/interpolation-escapes.md index d5b3a82d94cc..6c9afa9d85cb 100644 --- a/docs/docs/reference/changed-features/interpolation-escapes.md +++ b/docs/docs/reference/changed-features/interpolation-escapes.md @@ -4,7 +4,7 @@ title: "Escapes in interpolations" movedTo: https://docs.scala-lang.org/scala3/reference/changed-features/interpolation-escapes.html --- -In Scala 2 there is no straightforward way to represent a single quote character `"` in a single quoted interpolation. A `\` character can't be used for that because interpolators themselves decide how to handle escaping, so the parser doesn't know whether the `"` should be escaped or used as a terminator. +In Scala 2 there is no straightforward way to represent a single quote character `"` in a single quoted interpolation. A `\` character can't be used for that because interpolators themselves decide how to handle escaping, so the parser doesn't know whether the `"` character should be escaped or used as a terminator. In Scala 3, we can use the `$` meta character of interpolations to escape a `"` character. Example: diff --git a/docs/docs/reference/changed-features/main-functions.md b/docs/docs/reference/changed-features/main-functions.md index f6f6067204a3..7485dc942d99 100644 --- a/docs/docs/reference/changed-features/main-functions.md +++ b/docs/docs/reference/changed-features/main-functions.md @@ -5,7 +5,7 @@ movedTo: https://docs.scala-lang.org/scala3/reference/changed-features/main-func --- 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`](https://scala-lang.org/api/3.x/scala/main.html) annotation on a method turns this method into an executable program. Example: ```scala @@ -31,13 +31,11 @@ This would generate a main program `happyBirthday` that could be called like thi 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. -For each parameter type there must be an instance of the `scala.util.CommandLineParser.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. +A [`@main`](https://scala-lang.org/api/3.x/scala/main.html) 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`](https://scala-lang.org/api/3.x/scala/main.html) method can have an arbitrary number of parameters. +For each parameter type there must be an instance of the [`scala.util.CommandLineParser.FromString[T]`](https://scala-lang.org/api/3.x/scala/util/CommandLineParser$$FromString.html) type class that is used to convert an argument string to the required parameter type `T`. +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`](https://scala-lang.org/api/3.x/scala/main.html) 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. @@ -51,11 +49,11 @@ 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`](https://scala-lang.org/api/3.x/scala/main.html) 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`](https://scala-lang.org/api/3.x/scala/main.html) method was found - The class has a static method `main` with the usual signature. It takes an `Array[String]` - as argument and returns `Unit`. + as argument and returns [`Unit`](https://scala-lang.org/api/3.x/scala/Unit.html). - The generated `main` method calls method `f` with arguments converted using methods in the [`scala.util.CommandLineParser`](https://scala-lang.org/api/3.x/scala/util/CommandLineParser$.html) object. @@ -77,7 +75,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` 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`](https://scala-lang.org/api/3.x/scala/main.html) 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: @@ -85,5 +83,5 @@ object happyBirthday extends App: ... ``` -The previous functionality of `App`, which relied on the "magic" [`DelayedInit`](../dropped-features/delayed-init.md) trait, is no longer available. [`App`](https://scala-lang.org/api/3.x/scala/App.md) 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`](https://www.scala-lang.org/api/3.x/scala/App.html), which relied on the "magic" [`DelayedInit`](../dropped-features/delayed-init.md) trait, is no longer available. [`App`](https://scala-lang.org/api/3.x/scala/App.html) 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/pattern-bindings.md b/docs/docs/reference/changed-features/pattern-bindings.md index 978bff2d7d7e..2c8d1c10ceae 100644 --- a/docs/docs/reference/changed-features/pattern-bindings.md +++ b/docs/docs/reference/changed-features/pattern-bindings.md @@ -21,12 +21,11 @@ This code gives a compile-time warning in Scala 3.1 (and also in Scala 3.0 under val pair = (1, true) val (x, y) = pair ``` -Sometimes one wants to decompose data anyway, even though the pattern is refutable. For instance, if at some point one knows that a list `elems` is non-empty one might -want to decompose it like this: +Sometimes one wants to decompose data anyway, even though the pattern is refutable. For instance, if at some point one knows that a list `elems` is non-empty one might want to decompose it like this: ```scala val first :: rest = elems // error ``` -This works in Scala 2. In fact it is a typical use case for Scala 2's rules. But in Scala 3.1 it will give a warning. One can avoid the warning by marking the right-hand side with an `@unchecked` annotation: +This works in Scala 2. In fact it is a typical use case for Scala 2's rules. But in Scala 3.1 it will give a warning. One can avoid the warning by marking the right-hand side with an [`@unchecked`](https://scala-lang.org/api/3.x/scala/unchecked.html) annotation: ```scala val first :: rest = elems: @unchecked // OK ``` diff --git a/docs/docs/reference/changed-features/structural-types.md b/docs/docs/reference/changed-features/structural-types.md index 904525a4655d..cc07487feb4d 100644 --- a/docs/docs/reference/changed-features/structural-types.md +++ b/docs/docs/reference/changed-features/structural-types.md @@ -59,7 +59,7 @@ help from the user. In practice, the connection between a structural type and its underlying generic representation would most likely be done by a database layer, and therefore would not be a concern of the end user. -`Record` extends the marker trait `scala.Selectable` and defines +`Record` extends the marker trait [`scala.Selectable`](https://scala-lang.org/api/3.x/scala/Selectable.html) and defines 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 @@ -90,7 +90,7 @@ Structural types can also be accessed using [Java reflection](https://www.oracle 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 +Here, we define a structural type `Closeable` that defines a `close` method. There are various classes that have `close` methods, we just list [`FileInputStream`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/FileInputStream.html#%3Cinit%3E(java.io.File)) and [`Channel`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/channels/Channel.html) 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 @@ -147,10 +147,9 @@ i3.range 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. +is implemented by the base trait [`reflect.Selectable`](https://scala-lang.org/api/3.x/scala/reflect/Selectable.html) 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: +`Vehicle` could also extend some other subclass of [`scala.Selectable`](https://scala-lang.org/api/3.x/scala/Selectable.html) 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: @@ -168,11 +167,11 @@ adding any refinements. Hence, `i3` now has just type `Vehicle` and the selectio Note that in Scala 2 all local and anonymous classes could produce values with refined types. But members defined by such refinements could be selected only with the language import -`reflectiveCalls`. +[`reflectiveCalls`](https://scala-lang.org/api/3.x/scala/languageFeature$$reflectiveCalls$.html). ## Relation with `scala.Dynamic` -There are clearly some connections with `scala.Dynamic` here, since +There are clearly some connections with [`scala.Dynamic`](https://scala-lang.org/api/3.x/scala/Dynamic.html) here, since both select members programmatically. But there are also some differences. @@ -180,13 +179,13 @@ differences. is, as long as the correspondence of the structural type with the underlying value is as stated. -- `Dynamic` is just a marker trait, which gives more leeway where and +- [`Dynamic`](https://scala-lang.org/api/3.x/scala/Dynamic.html) is just a marker trait, which gives more leeway where and how to define reflective access operations. By contrast `Selectable` is a trait which declares the access operations. - Two access operations, `selectDynamic` and `applyDynamic` are shared between both approaches. In `Selectable`, `applyDynamic` also may also take - `java.lang.Class` arguments indicating the method's formal parameter types. - `Dynamic` comes with `updateDynamic`. + [`java.lang.Class`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html) arguments indicating the method's formal parameter types. + [`Dynamic`](https://scala-lang.org/api/3.x/scala/Dynamic.html) comes with `updateDynamic`. [More details](structural-types-spec.md) diff --git a/docs/docs/reference/contextual/context-functions-spec.md b/docs/docs/reference/contextual/context-functions-spec.md index 9e358ecede41..3c61e0e0c6ca 100644 --- a/docs/docs/reference/contextual/context-functions-spec.md +++ b/docs/docs/reference/contextual/context-functions-spec.md @@ -1,7 +1,6 @@ --- layout: doc-page title: "Context Functions - More Details" - movedTo: https://docs.scala-lang.org/scala3/reference/contextual/context-functions-spec.html --- @@ -64,7 +63,7 @@ Context function literals `(x1: T1, ..., xn: Tn) ?=> e` are automatically created for any expression `e` whose expected type is `scala.ContextFunctionN[T1, ..., Tn, R]`, unless `e` is itself a context function literal. This is analogous to the automatic -insertion of `scala.Function0` around expressions in by-name argument position. +insertion of [`scala.Function0`](https://scala-lang.org/api/3.x/scala/Function0.html) around expressions in by-name argument position. Context function types generalize to `N > 22` in the same way that function types do, see [the corresponding documentation](../dropped-features/limit22.md). diff --git a/docs/docs/reference/contextual/givens.md b/docs/docs/reference/contextual/givens.md index caaa1990282b..9b90040c01c3 100644 --- a/docs/docs/reference/contextual/givens.md +++ b/docs/docs/reference/contextual/givens.md @@ -120,9 +120,9 @@ In each case, a pattern-bound given instance consists of `given` and a type `T`. Scala 2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement the analogue of a "negated" search in implicit resolution, where a query Q1 fails if some other query Q2 succeeds and Q1 succeeds if Q2 fails. With the new cleaned up behavior these techniques no longer work. -But the new special type `scala.util.NotGiven` now implements negation directly. +But the new special type [`scala.util.NotGiven`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) now implements negation directly. -For any query type `Q`, `NotGiven[Q]` succeeds if and only if the implicit +For any query type `Q`, [`NotGiven[Q]`](https://scala-lang.org/api/3.x/scala/util/NotGiven.html) succeeds if and only if the implicit search for `Q` fails, for example: ```scala diff --git a/docs/docs/reference/dropped-features/delayed-init.md b/docs/docs/reference/dropped-features/delayed-init.md index 875ccec5132e..ab48de388569 100644 --- a/docs/docs/reference/dropped-features/delayed-init.md +++ b/docs/docs/reference/dropped-features/delayed-init.md @@ -4,9 +4,11 @@ title: "Dropped: DelayedInit" movedTo: https://docs.scala-lang.org/scala3/reference/dropped-features/delayed-init.html --- -The special handling of the `DelayedInit` trait is no longer supported. +The special handling of the [`DelayedInit`](https://scala-lang.org/api/3.x/scala/DelayedInit.html) +trait is no longer supported. -One consequence is that the `App` class, which used `DelayedInit` is +One consequence is that the [`App`](https://scala-lang.org/api/3.x/scala/App.html) class, +which used [`DelayedInit`](https://scala-lang.org/api/3.x/scala/DelayedInit.html) is now partially broken. You can still use `App` as a simple way to set up a main program. Example: ```scala diff --git a/docs/docs/reference/dropped-features/package-objects.md b/docs/docs/reference/dropped-features/package-objects.md index e98c6c787a89..5e58b5479fd8 100644 --- a/docs/docs/reference/dropped-features/package-objects.md +++ b/docs/docs/reference/dropped-features/package-objects.md @@ -11,7 +11,7 @@ package object p { def b = ... } ``` -will be dropped. They are still available in Scala 3.0, but will be deprecated and removed afterwards. +will be dropped. They are still available in Scala 3.0 and 3.1, but will be deprecated and removed afterwards. Package objects are no longer needed since all kinds of definitions can now be written at the top-level. Example: ```scala diff --git a/docs/docs/reference/dropped-features/symlits.md b/docs/docs/reference/dropped-features/symlits.md index 33c3e6ee0c39..cec98030a831 100644 --- a/docs/docs/reference/dropped-features/symlits.md +++ b/docs/docs/reference/dropped-features/symlits.md @@ -6,5 +6,19 @@ movedTo: https://docs.scala-lang.org/scala3/reference/dropped-features/symlits.h Symbol literals are no longer supported. -The `scala.Symbol` class still exists, so a -literal translation of the symbol literal `'xyz` is `Symbol("xyz")`. However, it is recommended to use a plain string literal `"xyz"` instead. (The `Symbol` class will be deprecated and removed in the future). +The [`scala.Symbol`](https://scala-lang.org/api/3.x/scala/Symbol.html) class still exists, so a literal translation of the symbol literal `'xyz` is `Symbol("xyz")`. However, it is recommended to use a plain string literal `"xyz"` instead. (The `Symbol` class will be deprecated and removed in the future). Example: + + +``` +scalac Test.scala +-- Error: Test.scala:1:25 ------------------------------------------------------------------------------------------------ + +1 |@main def test = println('abc) + | ^ + | symbol literal 'abc is no longer supported, + | use a string literal "abc" or an application Symbol("abc") instead, + | or enclose in braces '{abc} if you want a quoted expression. + | For now, you can also `import language.deprecated.symbolLiterals` to accept + | the idiom, but this possibility might no longer be available in the future. +1 error found +``` diff --git a/docs/docs/reference/experimental/canthrow.md b/docs/docs/reference/experimental/canthrow.md index 58a9db62b763..b46cd8cc4876 100644 --- a/docs/docs/reference/experimental/canthrow.md +++ b/docs/docs/reference/experimental/canthrow.md @@ -20,7 +20,7 @@ However, exceptions in current Scala and many other languages are not reflected ## The Problem With Java's Checked Exceptions -The main problem with Java's checked exception model is its inflexibility, which is due to lack of polymorphism. Consider for instance the `map` function which is declared on `List[A]` like this: +The main problem with [Java's checked exception model](https://docs.oracle.com/javase/specs/jls/se8/html/jls-11.html#jls-11.2) is its inflexibility, which is due to lack of polymorphism. Consider for instance the `map` function which is declared on `List[A]` like this: ```scala def map[B](f: A => B): List[B] ``` @@ -28,7 +28,7 @@ In the Java model, function `f` is not allowed to throw a checked exception. So ```scala xs.map(x => if x < limit then x * x else throw LimitExceeded()) ``` -The only way around this would be to wrap the checked exception `LimitExceeded` in an unchecked `RuntimeException` that is caught at the callsite and unwrapped again. Something like this: +The only way around this would be to wrap the checked exception `LimitExceeded` in an unchecked [`java.lang.RuntimeException`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/RuntimeException.html) that is caught at the callsite and unwrapped again. Something like this: ```scala try xs.map(x => if x < limit then x * x else throw Wrapper(LimitExceeded())) @@ -38,7 +38,7 @@ Ugh! No wonder checked exceptions in Java are not very popular. ## Monadic Effects -So the dilemma is that exceptions are easy to use only as long as we forgo static type checking. This has caused many people working with Scala to abandon exceptions altogether and to use an error monad like `Either` instead. This can work in many situations but is not without its downsides either. It makes code a lot more complicated and harder to refactor. It means one is quickly confronted with the problem how to work with several monads. In general, dealing with one monad at a time in Scala is straightforward but dealing with several monads together is much less pleasant since monads don't compose. A great number of techniques have been proposed, implemented, and promoted to deal with this, from monad transformers, to free monads, to tagless final. But none of these techniques is universally liked; each introduces a complicated DSL that's hard to understand for non-experts, introduces runtime overheads, and makes debugging difficult. In the end, quite a few developers prefer to work instead with a single "super-monad" like ZIO that has error propagation built in alongside other aspects. This one-size fits all approach can work very nicely, even though (or is it because?) it represents an all-encompassing framework. +So the dilemma is that exceptions are easy to use only as long as we forget static type checking. This has caused many people working with Scala to abandon exceptions altogether and to use an error monad like [`Either`](https://scala-lang.org/api/3.x/scala/util/Either.html) instead. This can work in many situations but is not without its downsides either. It makes code a lot more complicated and harder to refactor. It means one is quickly confronted with the problem how to work with several monads. In general, dealing with one monad at a time in Scala is straightforward but dealing with several monads together is much less pleasant since monads don't compose. A great number of techniques have been proposed, implemented, and promoted to deal with this, from monad transformers, to free monads, to tagless final. But none of these techniques is universally liked; each introduces a complicated DSL that's hard to understand for non-experts, introduces runtime overheads, and makes debugging difficult. In the end, quite a few developers prefer to work instead with a single "super-monad" like [`ZIO`](https://zio.dev/version-1.x/datatypes/core/zio) that has error propagation built in alongside other aspects. This one-size fits all approach can work very nicely, even though (or is it because?) it represents an all-encompassing framework. However, a programming language is not a framework; it has to cater also for those applications that do not fit the framework's use cases. So there's still a strong motivation for getting exception checking right. @@ -53,10 +53,10 @@ This assumes a type `A throws E` to indicate computations of type `A` that can t But there is a way to avoid the ceremony. Instead of concentrating on possible _effects_ such as "this code might throw an exception", concentrate on _capabilities_ such as "this code needs the capability to throw an exception". From a standpoint of expressiveness this is quite similar. But capabilities can be expressed as parameters whereas traditionally effects are expressed as some addition to result values. It turns out that this can make a big difference! -## The CanThrow Capability +## The `CanThrow` Capability In the _effects as capabilities_ model, an effect is expressed as an (implicit) parameter of a certain type. For exceptions we would expect parameters of type -`CanThrow[E]` where `E` stands for the exception that can be thrown. Here is the definition of `CanThrow`: +[`CanThrow[E]`](https://scala-lang.org/api/3.x/scala/CanThrow.html) where `E` stands for the exception that can be thrown. Here is the definition of `CanThrow`: ```scala erased class CanThrow[-E <: Exception] ``` @@ -66,14 +66,14 @@ Now, if the compiler sees a `throw Exc()` construct where `Exc` is a checked exc How can the capability be produced? There are several possibilities: -Most often, the capability is produced by having a using clause `(using CanThrow[Exc])` in some enclosing scope. This roughly corresponds to a `throws` clause -in Java. The analogy is even stronger since alongside `CanThrow` there is also the following type alias defined in the `scala` package: +Most often, the capability is produced by having a using clause `(using CanThrow[Exc])` in some enclosing scope. This roughly corresponds to a [`throws`](https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.6) clause in Java. The analogy is even stronger since alongside [`CanThrow`](https://scala-lang.org/api/3.x/scala/CanThrow.html) there is also the following type alias defined in the [`scala`](https://scala-lang.org/api/3.x/scala.html) package: +```scala +infix type A = Int +``` ```scala infix type $throws[R, +E <: Exception] = CanThrow[E] ?=> R ``` -That is, `R $throws E` is a context function type that takes an implicit `CanThrow[E]` parameter and that returns a value of type `R`. What's more, the compiler -will translate an infix types with `throws` as the operator to `$throws` applications -according to the rules +That is, [`R $throws E`](https://scala-lang.org/api/3.x/scala/runtime.html#$throws-0) is a context function type that takes an implicit `CanThrow[E]` parameter and that returns a value of type `R`. What's more, the compiler will translate an infix types with `throws` as the operator to `$throws` applications according to the rules ``` A throws E --> A $throws E A throws E₁ | ... | Eᵢ --> A $throws E₁ ... $throws Eᵢ @@ -127,7 +127,7 @@ catch ... Note that the right-hand side of the synthesized given is `???` (undefined). This is OK since this given is erased; it will not be executed at runtime. -**Note 1:** The `saferExceptions` feature is designed to work only with checked exceptions. An exception type is _checked_ if it is a subtype of +**Note 1:** The [`saferExceptions`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$experimental$$saferExceptions$.html) feature is designed to work only with checked exceptions. An exception type is _checked_ if it is a subtype of `Exception` but not of `RuntimeException`. The signature of `CanThrow` still admits `RuntimeException`s since `RuntimeException` is a proper subtype of its bound, `Exception`. But no capabilities will be generated for `RuntimeException`s. Furthermore, `throws` clauses also may not refer to `RuntimeException`s. @@ -141,7 +141,7 @@ checked exception type. Constructor patterns such as `Ex(...)` or patterns with are not allowed. The compiler will issue an error if one of these is used to catch a checked exception and `saferExceptions` is enabled. -## An Example +## Example That's it. Let's see it in action in an example. First, add an import ```scala @@ -160,13 +160,15 @@ You'll get this error message: if x < limit then x * x else throw LimitExceeded() ^^^^^^^^^^^^^^^^^^^^^ The capability to throw exception LimitExceeded is missing. +``` The capability can be provided by one of the following: + - Adding a using clause `(using CanThrow[LimitExceeded])` to the definition of the enclosing method - Adding `throws LimitExceeded` clause after the result type of the enclosing method - - Wrapping this piece of code with a `try` block that catches LimitExceeded + - Wrapping this piece of code with a `try` block that catches `LimitExceeded` The following import might fix the problem: - +```scala import unsafeExceptions.canThrowAny ``` As the error message implies, you have to declare that `f` needs the capability to throw a `LimitExceeded` exception. The most concise way to do so is to add a `throws` clause: @@ -205,13 +207,13 @@ So the takeaway is that the effects as capabilities model naturally provides for ## Gradual Typing Via Imports -Another advantage is that the model allows a gradual migration from current unchecked exceptions to safer exceptions. Imagine for a moment that `experimental.saferExceptions` is turned on everywhere. There would be lots of code that breaks since functions have not yet been properly annotated with `throws`. But it's easy to create an escape hatch that lets us ignore the breakages for a while: simply add the import +Another advantage is that the model allows a gradual migration from current unchecked exceptions to safer exceptions. Imagine for a moment that [`experimental.saferExceptions`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$experimental$$saferExceptions$.html) is turned on everywhere. There would be lots of code that breaks since functions have not yet been properly annotated with `throws`. But it's easy to create an escape hatch that lets us ignore the breakages for a while: simply add the import ```scala import scala.unsafeExceptions.canThrowAny ``` -This will provide the `CanThrow` capability for any exception, and thereby allow +This will provide the [`CanThrow`](https://scala-lang.org/api/3.x/scala/CanThrow.html) capability for any exception, and thereby allow all throws and all other calls, no matter what the current state of `throws` declarations is. Here's the -definition of `canThrowAny`: +definition of [`canThrowAny`](https://scala-lang.org/api/3.x/scala/unsafeExceptions$.html#canThrowAny-0): ```scala package scala object unsafeExceptions: @@ -224,7 +226,7 @@ enable more fluid explorations of code without regard for complete exception saf To summarize, the extension for safer exception checking consists of the following elements: - - It adds to the standard library the class `scala.CanThrow`, the type `scala.$throws`, and the `scala.unsafeExceptions` object, as they were described above. + - It adds to the standard library the class `scala.CanThrow`, the type `scala.$throws`, and the [`scala.unsafeExceptions`](https://scala-lang.org/api/3.x/scala/unsafeExceptions$.html) object, as they were described above. - It adds some desugaring rules ro rewrite `throws` types to cascaded `$throws` types. - It augments the type checking of `throw` by _demanding_ a `CanThrow` capability or the thrown exception. - It augments the type checking of `try` by _providing_ `CanThrow` capabilities for every caught exception. @@ -240,7 +242,7 @@ we cannot enforce that since the function argument to `pureMap` can capture arbi capabilities in its free variables without them showing up in its type. One possible way to address this would be to introduce a pure function type (maybe written `A -> B`). Pure functions are not allowed to close over capabilities. Then `pureMap` could be written like this: -``` +```scala def pureMap(f: A -> B): List[B] ``` Another area where the lack of purity requirements shows up is when capabilities escape from bounded scopes. Consider the following function @@ -266,16 +268,14 @@ g() the result will be a `LimitExceeded` exception thrown at the second line where `g` is called. What's missing is that `try` should enforce that the capabilities it generates do not escape as free variables in the result of its body. It makes sense to describe such scoped effects as _ephemeral capabilities_ - they have lifetimes that cannot be extended to delayed code in a lambda. -# Outlook +## Outlook -We are working on a new class of type system that supports ephemeral capabilities by tracking the free variables of values. Once that research matures, it will hopefully be possible to augment the language so that we can enforce the missing properties. +We are working on a new class of type system that supports ephemeral capabilities by tracking the free variables of values. Once that research matures, it will hopefully be possible to augment the Scala language so that we can enforce the missing properties. -And it would have many other applications besides: Exceptions are a special case of _algebraic effects_, which has been a very active research area over the last 20 years and is finding its way into programming languages (e.g. Koka, Eff, Multicore OCaml, Unison). In fact, algebraic effects have been characterized as being equivalent to exceptions with an additional _resume_ operation. The techniques developed here for exceptions can probably be generalized to other classes of algebraic effects. +And it would have many other applications besides: Exceptions are a special case of _algebraic effects_, which has been a very active research area over the last 20 years and is finding its way into programming languages (e.g. [Koka](https://koka-lang.github.io/koka/doc/book.html#why-handlers), [Eff](https://www.eff-lang.org/learn/), [Multicore OCaml](https://discuss.ocaml.org/t/multicore-ocaml-september-2021-effect-handlers-will-be-in-ocaml-5-0/8554), [Unison](https://www.unisonweb.org/docs/language-reference/#abilities-and-ability-handlers)). In fact, algebraic effects have been characterized as being equivalent to exceptions with an additional _resume_ operation. The techniques developed here for exceptions can probably be generalized to other classes of algebraic effects. But even without these additional mechanisms, exception checking is already useful as it is. It gives a clear path forward to make code that uses exceptions safer, better documented, and easier to refactor. The only loophole arises for scoped capabilities - here we have to verify manually that these capabilities do not escape. Specifically, a `try` always has to be placed in the same computation stage as the throws that it enables. Put another way: If the status quo is 0% static checking since 100% is too painful, then an alternative that gives you 95% static checking with great ergonomics looks like a win. And we might still get to 100% in the future. -For more info, see also our [paper at the ACM Scala Symposium 2021](resources/safer-exceptions.pdf). - - +For more info, see also our [paper at the ACM Scala Symposium 2021](https://infoscience.epfl.ch/record/290885). diff --git a/docs/docs/reference/experimental/erased-defs-spec.md b/docs/docs/reference/experimental/erased-defs-spec.md index dc7922ddb10f..7ca815878b55 100644 --- a/docs/docs/reference/experimental/erased-defs-spec.md +++ b/docs/docs/reference/experimental/erased-defs-spec.md @@ -1,7 +1,6 @@ --- layout: doc-page -title: "Erased Definitions: More Details" - +title: "Erased Definitions - More Details" movedTo: https://docs.scala-lang.org/scala3/reference/experimental/erased-defs-spec.html --- diff --git a/docs/docs/reference/experimental/erased-defs.md b/docs/docs/reference/experimental/erased-defs.md index 4eb02b7b1de1..d8562d20b420 100644 --- a/docs/docs/reference/experimental/erased-defs.md +++ b/docs/docs/reference/experimental/erased-defs.md @@ -5,12 +5,12 @@ movedTo: https://docs.scala-lang.org/scala3/reference/experimental/erased-defs.h --- `erased` is a modifier that expresses that some definition or expression is erased by the compiler instead of being represented in the compiled output. It is not yet part of the Scala language standard. To enable `erased`, turn on the language feature -`experimental.erasedDefinitions`. This can be done with a language import +[`experimental.erasedDefinitions`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$experimental$$erasedDefinitions$.html). This can be done with a language import ```scala import scala.language.experimental.erasedDefinitions ``` or by setting the command line option `-language:experimental.erasedDefinitions`. -Erased definitions must be in an experimental scope (see [../other-new-features/experimental-defs.md]). +Erased definitions must be in an experimental scope (see [Experimental definitions](../other-new-features/experimental-defs.md)). ## Why erased terms? diff --git a/docs/docs/reference/experimental/named-typeargs-spec.md b/docs/docs/reference/experimental/named-typeargs-spec.md index e12743fe4656..7bf5c2f43ccf 100644 --- a/docs/docs/reference/experimental/named-typeargs-spec.md +++ b/docs/docs/reference/experimental/named-typeargs-spec.md @@ -4,6 +4,8 @@ title: "Named Type Arguments - More Details" movedTo: https://docs.scala-lang.org/scala3/reference/experimental/named-typeargs-spec.html --- +In this section we give more details about the [named type arguments](named-typeargs.md) (*experimental*). + ## Syntax The addition to the grammar is: diff --git a/docs/docs/reference/experimental/numeric-literals.md b/docs/docs/reference/experimental/numeric-literals.md index 40383787a2d0..56684d2722d5 100644 --- a/docs/docs/reference/experimental/numeric-literals.md +++ b/docs/docs/reference/experimental/numeric-literals.md @@ -24,7 +24,7 @@ val z: BigDecimal = 110_222_799_799.99 The syntax of numeric literals is the same as before, except there are no pre-set limits how large they can be. -### Meaning of Numeric Literals +## Meaning of Numeric Literals The meaning of a numeric literal is determined as follows: @@ -37,7 +37,7 @@ In each of these cases the conversion to a number is exactly as in Scala 2 or in 1. If the expected type is `Int`, `Long`, `Float`, or `Double`, the literal is treated as a standard literal of that type. 2. If the expected type is a fully defined type `T` that has a given instance of type - `scala.util.FromDigits[T]`, the literal is converted to a value of type `T` by passing it as an argument to + [`scala.util.FromDigits[T]`](https://scala-lang.org/api/3.x/scala/util/FromDigits.html), the literal is converted to a value of type `T` by passing it as an argument to the `fromDigits` method of that instance (more details below). 3. Otherwise, the literal is treated as a `Double` literal (if it has a decimal point or an exponent), or as an `Int` literal (if not). (This last possibility is again as in Scala 2 or Java.) @@ -55,9 +55,7 @@ val y: BigInt = 0x123_abc_789_def_345_678_901 val z: BigDecimal = 111222333444.55 ``` -are legal by rule (2), since both `BigInt` and `BigDecimal` have `FromDigits` instances -(which implement the `FromDigits` subclasses `FromDigits.WithRadix` and `FromDigits.Decimal`, respectively). -On the other hand, +are legal by rule (2), since both `BigInt` and `BigDecimal` have [`FromDigits`](https://scala-lang.org/api/3.x/scala/util/FromDigits.html) instances (which implement the `FromDigits` subclasses [`FromDigits.WithRadix`](https://scala-lang.org/api/3.x/scala/util/FromDigits$$WithRadix.html) and [`FromDigits.Decimal`](https://scala-lang.org/api/3.x/scala/util/FromDigits$$Decimal.html), respectively). On the other hand, ```scala val x = -10_000_000_000 @@ -65,11 +63,10 @@ val x = -10_000_000_000 gives a type error, since without an expected type `-10_000_000_000` is treated by rule (3) as an `Int` literal, but it is too large for that type. -### The FromDigits Trait +## The `FromDigits` Trait 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: +[`scala.util.FromDigits`](https://scala-lang.org/api/3.x/scala/util/FromDigits.html) type class, or one of its subclasses. `FromDigits` is defined as follows: ```scala trait FromDigits[T]: @@ -82,9 +79,7 @@ The `digits` string consists of digits between `0` and `9`, possibly preceded by sign ("+" or "-"). Number separator characters `_` are filtered out before the string is passed to `fromDigits`. -The companion object `FromDigits` also defines subclasses of `FromDigits` for -whole numbers with a given radix, for numbers with a decimal point, and for -numbers that can have both a decimal point and an exponent: +The companion object [`FromDigits`](https://scala-lang.org/api/3.x/scala/util/FromDigits$.html) also defines subclasses of `FromDigits` for whole numbers with a given radix, for numbers with a decimal point, and for numbers that can have both a decimal point and an exponent: ```scala object FromDigits: @@ -112,10 +107,10 @@ A user-defined number type can implement one of those, which signals to the comp that hexadecimal numbers, decimal points, or exponents are also accepted in literals for this type. -### Error Handling +## Error Handling `FromDigits` implementations can signal errors by throwing exceptions of some subtype -of `FromDigitsException`. `FromDigitsException` is defined with three subclasses in the +of [`FromDigitsException`](https://scala-lang.org/api/3.x/scala/util/FromDigits$$FromDigitsException.html). `FromDigitsException` is defined with three subclasses in the `FromDigits` object as follows: ```scala @@ -126,7 +121,7 @@ class NumberTooSmall (msg: String = "number too small") extends FromDigi class MalformedNumber(msg: String = "malformed number literal") extends FromDigitsException(msg) ``` -### Example +## Example As a fully worked out example, here is an implementation of a new numeric class, `BigFloat`, that accepts numeric literals. `BigFloat` is defined in terms of a `BigInt` mantissa and an `Int` exponent: @@ -183,7 +178,7 @@ assumed that only valid arguments are passed. For calls coming from the compiler that assumption is valid, since the compiler will first check whether a numeric literal has the correct format before it gets passed on to a conversion method. -### Compile-Time Errors +## Compile-Time Errors With the setup of the previous section, a literal like @@ -197,7 +192,7 @@ would be expanded by the compiler to BigFloat.FromDigits.fromDigits("1e100000000000") ``` -Evaluating this expression throws a `NumberTooLarge` exception at run time. We would like it to +Evaluating this expression throws a [`NumberTooLarge`](https://scala-lang.org/api/3.x/scala/util/FromDigits$$NumberTooLarge.html) exception at run time. We would like it to produce a compile-time error instead. We can achieve this by tweaking the `BigFloat` class with a small dose of metaprogramming. The idea is to turn the `fromDigits` method into a macro, i.e. make it an inline method with a splice as right-hand side. diff --git a/docs/docs/reference/language-versions.md b/docs/docs/reference/language-versions.md index 67659d1fe109..ef31ccc28707 100644 --- a/docs/docs/reference/language-versions.md +++ b/docs/docs/reference/language-versions.md @@ -4,25 +4,25 @@ title: "Language Versions" movedTo: https://docs.scala-lang.org/scala3/reference/language-versions.html --- -The default Scala language version currently supported by the Dotty compiler is `3.0`. There are also other language versions that can be specified instead: +The default Scala language version currently supported by the Dotty compiler is [`3.0`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$3/0$.html). There are also other language versions that can be specified instead: -- `3.0-migration`: Same as `3.0` but with a Scala 2 compatibility mode that helps moving Scala 2.13 sources over to Scala 3. In particular, it +- [`3.0-migration`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$3/0-migration$.html): Same as `3.0` but with a Scala 2 compatibility mode that helps moving Scala 2.13 sources over to Scala 3. In particular, it - flags some Scala 2 constructs that are disallowed in Scala 3 as migration warnings instead of hard errors, - changes some rules to be more lenient and backwards compatible with Scala 2.13 - gives some additional warnings where the semantics has changed between Scala 2.13 and 3.0 - in conjunction with `-rewrite`, offer code rewrites from Scala 2.13 to 3.0. -- `future`: A preview of changes introduced in the next versions after 3.0. In the doc pages here we refer to the language version with these changes as `3.1`, but it might be that some of these changes will be rolled out in later `3.x` versions. +- [`future`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$future$.html): A preview of changes introduced in the next versions after 3.0. In the doc pages here we refer to the language version with these changes as `3.1`, but it might be that some of these changes will be rolled out in later `3.x` versions. -Some Scala-2 specific idioms will be dropped in this version. The feature set supported by this version will be refined over time as we approach its release. +Some Scala 2 specific idioms will be dropped in this version. The feature set supported by this version will be refined over time as we approach its release. -- `future-migration`: Same as `future` but with additional helpers to migrate from `3.0`. Similarly to the helpers available under `3.0-migration`, these include migration warnings and optional rewrites. +- [`future-migration`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$future-migration$.html): Same as `future` but with additional helpers to migrate from `3.0`. Similarly to the helpers available under `3.0-migration`, these include migration warnings and optional rewrites. -There are two ways to specify a language version. +There are two ways to specify a language version : -- With a `-source` command line setting, e.g. `-source 3.0-migration`. -- With a `scala.language` import at the top of a source file, e.g: +- with a `-source` command line setting, e.g. `-source 3.0-migration`. +- with a `scala.language` import at the top of a source file, e.g: ```scala package p @@ -32,3 +32,5 @@ class C { ... } ``` Language imports supersede command-line settings in the source files where they are specified. Only one language import specifying a source version is allowed in a source file, and it must come before any definitions in that file. + +**Note**: The [Scala 3 Migration Guide](https://docs.scala-lang.org/scala3/guides/migration/compatibility-intro.html) gives further information to help the Scala programmer moving from Scala 2.13 to Scala 3. diff --git a/docs/docs/reference/new-types/intersection-types.md b/docs/docs/reference/new-types/intersection-types.md index 1854ce847896..d498e664d150 100644 --- a/docs/docs/reference/new-types/intersection-types.md +++ b/docs/docs/reference/new-types/intersection-types.md @@ -1,6 +1,6 @@ --- layout: doc-page -title: Intersection Types +title: "Intersection Types" movedTo: https://docs.scala-lang.org/scala3/reference/new-types/intersection-types.html --- diff --git a/docs/docs/reference/new-types/type-lambdas-spec.md b/docs/docs/reference/new-types/type-lambdas-spec.md index 09fb9c76d6cf..5c791ba40272 100644 --- a/docs/docs/reference/new-types/type-lambdas-spec.md +++ b/docs/docs/reference/new-types/type-lambdas-spec.md @@ -114,4 +114,3 @@ The body of a type lambda can again be a type lambda. Example: type TL = [X] =>> [Y] =>> (X, Y) ``` Currently, no special provision is made to infer type arguments to such curried type lambdas. This is left for future work. - diff --git a/docs/docs/reference/other-new-features/experimental-defs.md b/docs/docs/reference/other-new-features/experimental-defs.md index a5c0bff378cd..ef9eca1ea7f5 100644 --- a/docs/docs/reference/other-new-features/experimental-defs.md +++ b/docs/docs/reference/other-new-features/experimental-defs.md @@ -1,273 +1,281 @@ --- layout: doc-page -title: "Experimental definitions" +title: "Experimental Definitions" movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/experimental-defs.html --- - -## Experimental definitions - -The `@experimental` annotation allows the definition of an API that is not guaranteed backward binary or source compatibility. +The [`@experimental`](https://scala-lang.org/api/3.x/scala/annotation/experimental.html) annotation allows the definition of an API that is not guaranteed backward binary or source compatibility. This annotation can be placed on term or type definitions. -### References to experimental definitions - -Experimental definitions can only be referenced in an experimental scope. Experimental scopes are defined as follows. - -(1) The RHS of an experimental `def`, `val`, `var`, `given` or `type` is an experimental scope. - -
-Examples - -```scala -import scala.annotation.experimental - -@experimental -def x = () - -def d1 = x // error: value x is marked @experimental and therefore ... -@experimental def d2 = x - -val v1 = x // error: value x is marked @experimental and therefore ... -@experimental val v2 = x - -var vr1 = x // error: value x is marked @experimental and therefore ... -@experimental var vr2 = x +## References to experimental definitions + +Experimental definitions can only be referenced in an experimental scope. Experimental scopes are defined as follows: + +1. The RHS of an experimental `def`, `val`, `var`, `given` or `type` is an experimental scope. Examples: + +
+ Example 1 + + ```scala + import scala.annotation.experimental + + @experimental + def x = () + + def d1 = x // error: value x is marked @experimental and therefore ... + @experimental def d2 = x + + val v1 = x // error: value x is marked @experimental and therefore ... + @experimental val v2 = x + + var vr1 = x // error: value x is marked @experimental and therefore ... + @experimental var vr2 = x + + lazy val lv1 = x // error: value x is marked @experimental and therefore ... + @experimental lazy val lv2 = x + ``` +
+ +
+ Example 2 + + ```scala + import scala.annotation.experimental + + @experimental + val x = () + + @experimental + def f() = () + + @experimental + object X: + def fx() = 1 + + def test1: Unit = + f() // error: def f is marked @experimental and therefore ... + x // error: value x is marked @experimental and therefore ... + X.fx() // error: object X is marked @experimental and therefore ... + import X.fx + fx() // error: object X is marked @experimental and therefore ... + + @experimental + def test2: Unit = + // references to f, x and X are ok because `test2` is experimental + f() + x + X.fx() + import X.fx + fx() + ``` +
+ +
+ Example 3 + + ```scala + import scala.annotation.experimental + + @experimental type E + + type A = E // error type E is marked @experimental and therefore ... + @experimental type B = E + ``` +
+ +
+ Example 4 + + ```scala + import scala.annotation.experimental + + @experimental class A + @experimental type X + @experimental type Y = Int + @experimental opaque type Z = Int + + def test: Unit = + new A // error: class A is marked @experimental and therefore ... + val i0: A = ??? // error: class A is marked @experimental and therefore ... + val i1: X = ??? // error: type X is marked @experimental and therefore ... + val i2: Y = ??? // error: type Y is marked @experimental and therefore ... + val i2: Z = ??? // error: type Y is marked @experimental and therefore ... + () + ``` +
+ +
+ Example 5 + + ```scala + @experimental + trait ExpSAM { + def foo(x: Int): Int + } + def bar(f: ExpSAM): Unit = {} // error: error form rule 2 + + def test: Unit = + bar(x => x) // error: reference to experimental SAM + () + ``` +
+ +2. The signatures of an experimental `def`, `val`, `var`, `given` and `type`, or constructors of `class` and `trait` are experimental scopes. Examples: + +
+ Example 1 + + ```scala + import scala.annotation.experimental + + @experimental def x = 2 + @experimental class A + @experimental type X + @experimental type Y = Int + @experimental opaque type Z = Int + + def test1( + p1: A, // error: class A is marked @experimental and therefore ... + p2: List[A], // error: class A is marked @experimental and therefore ... + p3: X, // error: type X is marked @experimental and therefore ... + p4: Y, // error: type Y is marked @experimental and therefore ... + p5: Z, // error: type Z is marked @experimental and therefore ... + p6: Any = x // error: def x is marked @experimental and therefore ... + ): A = ??? // error: class A is marked @experimental and therefore ... + + @experimental def test2( + p1: A, + p2: List[A], + p3: X, + p4: Y, + p5: Z, + p6: Any = x + ): A = ??? + + class Test1( + p1: A, // error + p2: List[A], // error + p3: X, // error + p4: Y, // error + p5: Z, // error + p6: Any = x // error + ) {} + + @experimental class Test2( + p1: A, + p2: List[A], + p3: X, + p4: Y, + p5: Z, + p6: Any = x + ) {} + + trait Test1( + p1: A, // error + p2: List[A], // error + p3: X, // error + p4: Y, // error + p5: Z, // error + p6: Any = x // error + ) {} + + @experimental trait Test2( + p1: A, + p2: List[A], + p3: X, + p4: Y, + p5: Z, + p6: Any = x + ) {} + ``` +
+ +3. The `extends` clause of an experimental `class`, `trait` or `object` is an experimental scope. Examples: + +
+ Example 1 + + ```scala + import scala.annotation.experimental + + @experimental def x = 2 + + @experimental class A1(x: Any) + class A2(x: Any) + + + @experimental class B1 extends A1(1) + class B2 extends A1(1) // error: class A1 is marked @experimental and therefore marked @experimental and therefore ... + + @experimental class C1 extends A2(x) + class C2 extends A2(x) // error def x is marked @experimental and therefore + ``` +
+ +4. The body of an experimental `class`, `trait` or `object` is an experimental scope. Examples: + +
+ Example 1 + ```scala + import scala.annotation.experimental + + @experimental def x = 2 + + @experimental class A { + def f = x // ok because A is experimental + } + + @experimental class B { + def f = x // ok because A is experimental + } + + @experimental object C { + def f = x // ok because A is experimental + } + + @experimental class D { + def f = { + object B { + x // ok because A is experimental + } + } + } + ``` +
+ +5. Annotations of an experimental definition are in experimental scopes. Examples: + +
+ Example 1 + + ```scala + import scala.annotation.experimental + + @experimental class myExperimentalAnnot extends scala.annotation.Annotation + + @myExperimentalAnnot // error + def test: Unit = () + + @experimental + @myExperimentalAnnot + def test: Unit = () + ``` -lazy val lv1 = x // error: value x is marked @experimental and therefore ... -@experimental lazy val lv2 = x -``` - -```scala -import scala.annotation.experimental - -@experimental -val x = () - -@experimental -def f() = () - -@experimental -object X: - def fx() = 1 - -def test1: Unit = - f() // error: def f is marked @experimental and therefore ... - x // error: value x is marked @experimental and therefore ... - X.fx() // error: object X is marked @experimental and therefore ... - import X.fx - fx() // error: object X is marked @experimental and therefore ... - -@experimental -def test2: Unit = - // references to f, x and X are ok because `test2` is experimental - f() - x - X.fx() - import X.fx - fx() -``` - -```scala -import scala.annotation.experimental - -@experimental type E - -type A = E // error type E is marked @experimental and therefore ... -@experimental type B = E -``` - -```scala -import scala.annotation.experimental - -@experimental class A -@experimental type X -@experimental type Y = Int -@experimental opaque type Z = Int - -def test: Unit = - new A // error: class A is marked @experimental and therefore ... - val i0: A = ??? // error: class A is marked @experimental and therefore ... - val i1: X = ??? // error: type X is marked @experimental and therefore ... - val i2: Y = ??? // error: type Y is marked @experimental and therefore ... - val i2: Z = ??? // error: type Y is marked @experimental and therefore ... - () -``` - -```scala -@experimental -trait ExpSAM { - def foo(x: Int): Int -} -def bar(f: ExpSAM): Unit = {} // error: error form rule 2 - -def test: Unit = - bar(x => x) // error: reference to experimental SAM - () -``` - -
- -(2.) The signatures of an experimental `def`, `val`, `var`, `given` and `type`, or constructors of `class` and `trait` are experimental scopes. - -
-Examples - -```scala -import scala.annotation.experimental - -@experimental def x = 2 -@experimental class A -@experimental type X -@experimental type Y = Int -@experimental opaque type Z = Int - -def test1( - p1: A, // error: class A is marked @experimental and therefore ... - p2: List[A], // error: class A is marked @experimental and therefore ... - p3: X, // error: type X is marked @experimental and therefore ... - p4: Y, // error: type Y is marked @experimental and therefore ... - p5: Z, // error: type Z is marked @experimental and therefore ... - p6: Any = x // error: def x is marked @experimental and therefore ... -): A = ??? // error: class A is marked @experimental and therefore ... - -@experimental def test2( - p1: A, - p2: List[A], - p3: X, - p4: Y, - p5: Z, - p6: Any = x -): A = ??? - -class Test1( - p1: A, // error - p2: List[A], // error - p3: X, // error - p4: Y, // error - p5: Z, // error - p6: Any = x // error -) {} - -@experimental class Test2( - p1: A, - p2: List[A], - p3: X, - p4: Y, - p5: Z, - p6: Any = x -) {} - -trait Test1( - p1: A, // error - p2: List[A], // error - p3: X, // error - p4: Y, // error - p5: Z, // error - p6: Any = x // error -) {} - -@experimental trait Test2( - p1: A, - p2: List[A], - p3: X, - p4: Y, - p5: Z, - p6: Any = x -) {} -``` - -
- -(3.) The `extends` clause of an experimental `class`, `trait` or `object` is an experimental scope. - -
-Examples - -```scala -import scala.annotation.experimental - -@experimental def x = 2 - -@experimental class A1(x: Any) -class A2(x: Any) - - -@experimental class B1 extends A1(1) -class B2 extends A1(1) // error: class A1 is marked @experimental and therefore marked @experimental and therefore ... - -@experimental class C1 extends A2(x) -class C2 extends A2(x) // error def x is marked @experimental and therefore -``` - -
- -(4.) The body of an experimental `class`, `trait` or `object` is an experimental scope. - -
-Examples - -```scala -import scala.annotation.experimental - -@experimental def x = 2 - -@experimental class A { - def f = x // ok because A is experimental -} - -@experimental class B { - def f = x // ok because A is experimental -} - -@experimental object C { - def f = x // ok because A is experimental -} - -@experimental class D { - def f = { - object B { - x // ok because A is experimental - } - } -} -``` - -
- -(5.) Annotations of an experimental definition are in experimental scopes. - -
-Examples - -```scala -import scala.annotation.experimental - -@experimental class myExperimentalAnnot extends scala.annotation.Annotation - -@myExperimentalAnnot // error -def test: Unit = () - -@experimental -@myExperimentalAnnot -def test: Unit = () -``` - -
+
-(6.) Any code compiled using a _Nightly_ or _Snapshot_ version of the compiler is considered to be in an experimental scope. +6. Any code compiled using a [_Nightly_](https://search.maven.org/artifact/org.scala-lang/scala3-compiler_3) or _Snapshot_ version of the compiler is considered to be in an experimental scope. Can use the `-Yno-experimental` compiler flag to disable it and run as a proper release. In any other situation, a reference to an experimental definition will cause a compilation error. -### Experimental inheritance +## Experimental inheritance -All subclasses of an experimental `class` or `trait` must be marked as `@experimental` even if they are in an experimental scope. +All subclasses of an experimental `class` or `trait` must be marked as [`@experimental`](https://scala-lang.org/api/3.x/scala/annotation/experimental.html) even if they are in an experimental scope. Anonymous classes and SAMs of experimental classes are considered experimental. We require explicit annotations to make sure we do not have completion or cycles issues with nested classes. This restriction could be relaxed in the future. -### Experimental overriding +## Experimental overriding For an overriding member `M` and overridden member `O`, if `O` is non-experimental then `M` must be non-experimental. @@ -279,12 +287,12 @@ class B extends A: - @experimental def f: Int = 2 ``` -### Test frameworks +## Test frameworks -Tests can be defined as experimental. Tests frameworks can execute tests using reflection even if they are in an experimental class, object or method. +Tests can be defined as experimental. Tests frameworks can execute tests using reflection even if they are in an experimental class, object or method. Examples:
-Examples +Example 1 Test that touch experimental APIs can be written as follows diff --git a/docs/docs/reference/other-new-features/explicit-nulls.md b/docs/docs/reference/other-new-features/explicit-nulls.md index c1afe6a4e067..1ee404a44cec 100644 --- a/docs/docs/reference/other-new-features/explicit-nulls.md +++ b/docs/docs/reference/other-new-features/explicit-nulls.md @@ -5,7 +5,7 @@ movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/explici --- Explicit nulls is an opt-in feature that modifies the Scala type system, which makes reference types -(anything that extends `AnyRef`) _non-nullable_. +(anything that extends [`AnyRef`](https://scala-lang.org/api/3.x/scala/AnyRef.html)) _non-nullable_. This means the following code will no longer typecheck: @@ -59,7 +59,7 @@ So far, we have found the following useful: Don't use `.nn` on mutable variables directly, because it may introduce an unknown type into the type of the variable. -- An `unsafeNulls` language feature. +- An [`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html) language feature. When imported, `T | Null` can be used as `T`, similar to regular Scala (without explicit nulls). @@ -277,7 +277,7 @@ We illustrate the rules with following examples: ### Override check -When we check overriding between Scala classes and Java classes, the rules are relaxed for `Null` type with this feature, in order to help users to working with Java libraries. +When we check overriding between Scala classes and Java classes, the rules are relaxed for [`Null`](https://scala-lang.org/api/3.x/scala/Null.html) type with this feature, in order to help users to working with Java libraries. Suppose we have Java method `String f(String x)`, we can override this method in Scala in any of the following forms: @@ -448,10 +448,10 @@ We don't support: ### UnsafeNulls -It is difficult to work with many nullable values, we introduce a language feature `unsafeNulls`. +It is difficult to work with many nullable values, we introduce a language feature [`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html). Inside this "unsafe" scope, all `T | Null` values can be used as `T`. -Users can import `scala.language.unsafeNulls` to create such scopes, or use `-language:unsafeNulls` to enable this feature globally (for migration purpose only). +Users can import [`scala.language.unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html) to create such scopes, or use `-language:unsafeNulls` to enable this feature globally (for migration purpose only). Assume `T` is a reference type (a subtype of `AnyRef`), the following unsafe operation rules are applied in this unsafe-nulls scope: @@ -470,7 +470,7 @@ can be used as `T2` if `T1` is a subtype of `T2` using regular subtyping rules Addtionally, `null` can be used as `AnyRef` (`Object`), which means you can select `.eq` or `.toString` on it. -The program in `unsafeNulls` will have a **similar** semantic as regular Scala, but not **equivalent**. +The program in [`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html) will have a **similar** semantic as regular Scala, but not **equivalent**. For example, the following code cannot be compiled even using unsafe nulls. Because of the Java interoperation, the type of the get method becomes `T | Null`. @@ -483,7 +483,7 @@ Since the compiler doesn’t know whether `T` is a reference type, it is unable to `T`. A `.nn` need to be inserted after `xs.get(0)` by user manually to fix the error, which strips the `Null` from its type. -The intention of this `unsafeNulls` is to give users a better migration path for explicit nulls. +The intention of this [`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html) is to give users a better migration path for explicit nulls. Projects for Scala 2 or regular Scala 3 can try this by adding `-Yexplicit-nulls -language:unsafeNulls` to the compile options. A small number of manual modifications are expected. To migrate to the full explicit nulls feature in the future, `-language:unsafeNulls` can be dropped and add @@ -514,9 +514,9 @@ class C[T >: Null <: String] // define a type bound with unsafe conflict bound val n = nullOf[String] // apply a type bound unsafely ``` -Without the `unsafeNulls`, all these unsafe operations will not be type-checked. +Without the [`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html), all these unsafe operations will not be type-checked. -`unsafeNulls` also works for extension methods and implicit search. +[`unsafeNulls`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$unsafeNulls$.html) also works for extension methods and implicit search. ```scala import scala.language.unsafeNulls diff --git a/docs/docs/reference/other-new-features/export.md b/docs/docs/reference/other-new-features/export.md index d21f6ed6d4cb..ce1d536a1432 100644 --- a/docs/docs/reference/other-new-features/export.md +++ b/docs/docs/reference/other-new-features/export.md @@ -44,7 +44,7 @@ val copier = new Copier copier.print(copier.scan()) ``` -An export clause has the same format as an import clause. Its general form is: +An `export` clause has the same format as an import clause. Its general form is: ```scala export path . { sel_1, ..., sel_n } diff --git a/docs/docs/reference/other-new-features/kind-polymorphism.md b/docs/docs/reference/other-new-features/kind-polymorphism.md index 7dbcf3e96927..057e9de9d55d 100644 --- a/docs/docs/reference/other-new-features/kind-polymorphism.md +++ b/docs/docs/reference/other-new-features/kind-polymorphism.md @@ -14,7 +14,7 @@ _must_ be applied to a type argument, unless they are passed to type parameters Sometimes we would like to have type parameters that can have more than one kind, for instance to define an implicit value that works for parameters of any kind. This is now possible through a form of (_subtype_) kind polymorphism. -Kind polymorphism relies on the special type `scala.AnyKind` that can be used as an upper bound of a type. +Kind polymorphism relies on the special type [`scala.AnyKind`](https://scala-lang.org/api/3.x/scala/AnyKind.html) that can be used as an upper bound of a type. ```scala def f[T <: AnyKind] = ... @@ -38,7 +38,7 @@ through advanced uses of implicits. (todo: insert good concise example) -Some technical details: `AnyKind` is a synthesized class just like `Any`, but without any members. It extends no other class. +Some technical details: [`AnyKind`](https://scala-lang.org/api/3.x/scala/AnyKind.html) is a synthesized class just like `Any`, but without any members. It extends no other class. It is declared `abstract` and `final`, so it can be neither instantiated nor extended. `AnyKind` plays a special role in Scala's subtype system: It is a supertype of all other types no matter what their kind is. It is also assumed to be kind-compatible with all other types. Furthermore, `AnyKind` is treated as a higher-kinded type (so it cannot be used as a type of values), but at the same time it has no type parameters (so it cannot be instantiated). diff --git a/docs/docs/reference/other-new-features/matchable.md b/docs/docs/reference/other-new-features/matchable.md index fdce97dab8f0..b1bb16697d62 100644 --- a/docs/docs/reference/other-new-features/matchable.md +++ b/docs/docs/reference/other-new-features/matchable.md @@ -4,11 +4,11 @@ title: "The Matchable Trait" movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/matchable.html --- -A new trait `Matchable` controls the ability to pattern match. +A new trait [`Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) controls the ability to pattern match. ### The Problem -The Scala 3 standard library has a type `IArray` for immutable +The Scala 3 standard library has a type [`IArray`](https://scala-lang.org/api/3.x/scala.html#IArray-0) for immutable arrays that is defined like this: ```scala @@ -25,7 +25,7 @@ imm match case a: Array[Int] => a(0) = 1 ``` -The test will succeed at runtime since `IArray`s _are_ represented as +The test will succeed at runtime since [`IArray`](https://scala-lang.org/api/3.x/scala.html#IArray-0)s _are_ represented as `Array`s at runtime. But if we allowed it, it would break the fundamental abstraction of immutable arrays. __Aside:__ One could also achieve the same by casting: @@ -36,7 +36,7 @@ imm.asInstanceOf[Array[Int]](0) = 1 But that is not as much of a problem since in Scala `asInstanceOf` is understood to be low-level and unsafe. By contrast, a pattern match that compiles without warning or error should not break abstractions. -Note also that the problem is not tied to opaque types as match selectors. The following slight variant with a value of parametric +Note also that the problem is not tied to [opaque types](opaques.md) as match selectors. The following slight variant with a value of parametric type `T` as match selector leads to the same problem: ```scala @@ -45,11 +45,11 @@ def f[T](x: T) = x match f(imm) ``` -Finally, note that the problem is not linked to just opaque types. No unbounded type parameter or abstract type should be decomposable with a pattern match. +Finally, note that the problem is not linked to just [opaque types](opaques.md). No unbounded type parameter or abstract type should be decomposable with a pattern match. ### The Solution -There is a new type `scala.Matchable` that controls pattern matching. When typing a pattern match of a constructor pattern `C(...)` or +There is a new type [`scala.Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) that controls pattern matching. When typing a pattern match of a constructor pattern `C(...)` or a type pattern `_: C` it is required that the selector type conforms to `Matchable`. If that's not the case a warning is issued. For instance when compiling the example at the start of this section we get: @@ -65,8 +65,7 @@ to `Matchable`. If that's not the case a warning is issued. For instance when co To allow migration from Scala 2 and cross-compiling between Scala 2 and 3 the warning is turned on only for `-source future-migration` or higher. -`Matchable` is a universal trait with `Any` as its parent class. It is -extended by both `AnyVal` and `AnyRef`. Since `Matchable` is a supertype of every concrete value or reference class it means that instances of such classes can be matched as before. However, match selectors of the following types will produce a warning: +[`Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) is a universal trait with `Any` as its parent class. It is extended by both [`AnyVal`](https://scala-lang.org/api/3.x/scala/AnyVal.html) and [`AnyRef`](https://scala-lang.org/api/3.x/scala/AnyRef.html). Since `Matchable` is a supertype of every concrete value or reference class it means that instances of such classes can be matched as before. However, match selectors of the following types will produce a warning: - Type `Any`: if pattern matching is required one should use `Matchable` instead. - Unbounded type parameters and abstract types: If pattern matching is required they should have an upper bound `Matchable`. @@ -93,7 +92,7 @@ class AnyVal extends Any, Matchable class Object extends Any, Matchable ``` -`Matchable` is currently a marker trait without any methods. Over time +[`Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) is currently a marker trait without any methods. Over time we might migrate methods `getClass` and `isInstanceOf` to it, since these are closely related to pattern-matching. ### `Matchable` and Universal Equality @@ -111,9 +110,9 @@ class C(val x: String): case _ => false ``` -The cast of `that` to `Matchable` serves as an indication that universal equality +The cast of `that` to [`Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) serves as an indication that universal equality is unsafe in the presence of abstract types and opaque types since it cannot properly distinguish the meaning of a type from its representation. The cast -is guaranteed to succeed at run-time since `Any` and `Matchable` both erase to +is guaranteed to succeed at run-time since `Any` and [`Matchable`](https://scala-lang.org/api/3.x/scala/Matchable.html) both erase to `Object`. For instance, consider the definitions diff --git a/docs/docs/reference/other-new-features/opaques-details.md b/docs/docs/reference/other-new-features/opaques-details.md index ecfb78db48b7..0a992ff5f6be 100644 --- a/docs/docs/reference/other-new-features/opaques-details.md +++ b/docs/docs/reference/other-new-features/opaques-details.md @@ -4,7 +4,7 @@ title: "Opaque Type Aliases: More Details" movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/opaques-details.html --- -### Syntax +## Syntax ``` Modifier ::= ... @@ -16,7 +16,7 @@ Modifier ::= ... Opaque type aliases must be members of classes, traits, or objects, or they are defined at the top-level. They cannot be defined in local blocks. -### Type Checking +## Type Checking The general form of a (monomorphic) opaque type alias is @@ -24,7 +24,7 @@ The general form of a (monomorphic) opaque type alias is 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`. +where the lower bound `L` and the upper bound `U` may be missing, in which case they are assumed to be [`scala.Nothing`](https://scala-lang.org/api/3.x/scala/Nothing.html) and [`scala.Any`](https://scala-lang.org/api/3.x/scala/Any.html), 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 as a normal alias of `R`. Outside its scope, the alias is treated as the abstract type @@ -51,7 +51,7 @@ object o: def id(x: o.T): o.T = x ``` -### Type Parameters of Opaque Types +## Type Parameters of Opaque Types Opaque type aliases can have a single type parameter list. The following aliases are well-formed @@ -65,7 +65,7 @@ opaque type BadF[T] = [U] =>> (T, U) opaque type BadG = [T] =>> [U] => (T, U) ``` -### Translation of Equality +## Translation of Equality Comparing two values of opaque type with `==` or `!=` normally uses universal equality, unless another overloaded `==` or `!=` operator is defined for the type. To avoid @@ -80,7 +80,7 @@ defined on the underlying type. For instance, x == y // uses Int equality for the comparison. ``` -### Top-level Opaque Types +## Top-level Opaque Types An opaque type alias on the top-level is transparent in all other top-level definitions in the sourcefile where it appears, but is opaque in nested objects and classes and in all other source files. Example: @@ -107,7 +107,7 @@ object obj: The opaque type alias `A` is transparent in its scope, which includes the definition of `x`, but not the definitions of `obj` and `y`. -### Relationship to SIP 35 +## Relationship to SIP 35 Opaque types in Scala 3 are an evolution from what is described in [Scala SIP 35](https://docs.scala-lang.org/sips/opaque-types.html). diff --git a/docs/docs/reference/other-new-features/open-classes.md b/docs/docs/reference/other-new-features/open-classes.md index f1ddcf8c190f..6762b0eac14b 100644 --- a/docs/docs/reference/other-new-features/open-classes.md +++ b/docs/docs/reference/other-new-features/open-classes.md @@ -31,7 +31,7 @@ Classes that are not open can still be extended, but only if at least one of two - The extending class is in the same source file as the extended class. In this case, the extension is usually an internal implementation matter. - - The language feature `adhocExtensions` is enabled for the extending class. This is typically enabled by an import clause in the source file of the extension: + - The language feature [`adhocExtensions`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$adhocExtensions$.html) is enabled for the extending class. This is typically enabled by an import clause in the source file of the extension: ```scala import scala.language.adhocExtensions ``` @@ -47,7 +47,7 @@ Classes that are not open can still be extended, but only if at least one of two |or by setting the compiler option -language:adhocExtensions. ``` -### Motivation +## Motivation When writing a class, there are three possible expectations of extensibility: @@ -64,17 +64,17 @@ It is good practice to avoid _ad-hoc_ extensions in a code base, since they tend are still some situations where these extensions are useful: for instance, to mock classes in tests, or to apply temporary patches that add features or fix bugs in library classes. That's why _ad-hoc_ extensions are permitted, but only if there is an explicit opt-in via a language feature import. -### Details +## Details - `open` is a soft modifier. It is treated as a normal identifier unless it is in modifier position. - An `open` class cannot be `final` or `sealed`. - Traits or `abstract` classes are always `open`, so `open` is redundant for them. -### Relationship with `sealed` +## Relationship with `sealed` -A class that is neither `abstract` nor `open` is similar to a `sealed` class: it can still be extended, but only in the same source file. The difference is what happens if an extension of the class is attempted in another source file. For a `sealed` class, this is an error, whereas for a simple non-open class, this is still permitted provided the `adhocExtensions` feature is enabled, and it gives a warning otherwise. +A class that is neither `abstract` nor `open` is similar to a `sealed` class: it can still be extended, but only in the same source file. The difference is what happens if an extension of the class is attempted in another source file. For a `sealed` class, this is an error, whereas for a simple non-open class, this is still permitted provided the [`adhocExtensions`](https://scala-lang.org/api/3.x/scala/runtime/stdLibPatches/language$$adhocExtensions$.html) feature is enabled, and it gives a warning otherwise. -### Migration +## Migration `open` is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under `-source future`. It will be produced by default from Scala 3.1 on. diff --git a/docs/docs/reference/other-new-features/targetName.md b/docs/docs/reference/other-new-features/targetName.md index a83c4247c1ef..d2a654697d15 100644 --- a/docs/docs/reference/other-new-features/targetName.md +++ b/docs/docs/reference/other-new-features/targetName.md @@ -4,7 +4,7 @@ title: "The @targetName annotation" movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/targetName.html --- -A `@targetName` annotation on a definition defines an alternate name for the implementation of that definition. Example: +A [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation on a definition defines an alternate name for the implementation of that definition. Example: ```scala import scala.annotation.targetName @@ -21,7 +21,7 @@ Here, the `++=` operation is implemented (in Byte code or native code) under the VecOps.append(vec1, vec2) ``` -The `@targetName` annotation has no bearing on Scala usages. Any application of that method in Scala has to use `++=`, not `append`. +The [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation has no bearing on Scala usages. Any application of that method in Scala has to use `++=`, not `append`. ### Details @@ -31,22 +31,21 @@ The `@targetName` annotation has no bearing on Scala usages. Any application of 2. A `@targetName` annotation can be given for all kinds of definitions. - 3. The name given in a `@targetName` annotation must be a legal name + 3. The name given in a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation must be a legal name for the defined entities on the host platform. - 4. It is recommended that definitions with symbolic names have a `@targetName` annotation. This will establish an alternate name that is easier to search for and + 4. It is recommended that definitions with symbolic names have a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation. This will establish an alternate name that is easier to search for and will avoid cryptic encodings in runtime diagnostics. 5. Definitions with names in backticks that are not legal host platform names - should also have a `@targetName` annotation. + should also have a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation. ### Relationship with Overriding -`@targetName` annotations are significant for matching two method definitions to decide whether they conflict or override each other. Two method definitions match if they have the same name, signature, and erased name. Here, +[`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotations are significant for matching two method definitions to decide whether they conflict or override each other. Two method definitions match if they have the same name, signature, and erased name. Here, - The _signature_ of a definition consists of the names of the erased types of all (value-) parameters and the method's result type. -- The _erased name_ of a method definition is its target name if a `@targetName` - annotation is given and its defined name otherwise. +- The _erased name_ of a method definition is its target name if a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation is given and its defined name otherwise. This means that `@targetName` annotations can be used to disambiguate two method definitions that would otherwise clash. For instance. @@ -55,8 +54,7 @@ def f(x: => String): Int = x.length def f(x: => Int): Int = x + 1 // error: double definition ``` -The two definitions above clash since their erased parameter types are both `Function0`, which is the type of the translation of a by-name-parameter. Hence -they have the same names and signatures. But we can avoid the clash by adding a `@targetName` annotation to either method or to both of them. Example: +The two definitions above clash since their erased parameter types are both [`Function0`](https://scala-lang.org/api/3.x/scala/Function0.html), which is the type of the translation of a by-name-parameter. Hence they have the same names and signatures. But we can avoid the clash by adding a [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotation to either method or to both of them. Example: ```scala @targetName("f_string") @@ -66,7 +64,7 @@ def f(x: => Int): Int = x + 1 // OK This will produce methods `f_string` and `f` in the generated code. -However, `@targetName` annotations are not allowed to break overriding relationships +However, [`@targetName`](https://scala-lang.org/api/3.x/scala/annotation/targetName.html) annotations are not allowed to break overriding relationships between two definitions that have otherwise the same names and types. So the following would be in error: ```scala diff --git a/docs/docs/reference/other-new-features/threadUnsafe-annotation.md b/docs/docs/reference/other-new-features/threadUnsafe-annotation.md index 99a16413f310..cd0d45e2246a 100644 --- a/docs/docs/reference/other-new-features/threadUnsafe-annotation.md +++ b/docs/docs/reference/other-new-features/threadUnsafe-annotation.md @@ -4,9 +4,9 @@ title: "The @threadUnsafe annotation" movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/threadUnsafe-annotation.html --- -A new annotation `@threadUnsafe` can be used on a field which defines +A new annotation [`@threadUnsafe`](https://scala-lang.org/api/3.x/scala/annotation/threadUnsafe.html) can be used on a field which defines a `lazy val`. When this annotation is used, the initialization of the -`lazy val` will use a faster mechanism which is not thread-safe. +[`lazy val`](../changed-features/lazy-vals-init.md) will use a faster mechanism which is not thread-safe. ### Example diff --git a/docs/docs/reference/other-new-features/transparent-traits.md b/docs/docs/reference/other-new-features/transparent-traits.md index 8f37f24174e1..3236bf71252d 100644 --- a/docs/docs/reference/other-new-features/transparent-traits.md +++ b/docs/docs/reference/other-new-features/transparent-traits.md @@ -9,7 +9,7 @@ Traits are used in two roles: 1. As mixins for other classes and traits 2. As types of vals, defs, or parameters -Some traits are used primarily in the first role, and we usually do not want to see them in inferred types. An example is the `Product` trait that the compiler adds as a mixin trait to every case class or case object. In Scala 2, this parent trait sometimes makes inferred types more complicated than they should be. Example: +Some traits are used primarily in the first role, and we usually do not want to see them in inferred types. An example is the [`Product`](https://scala-lang.org/api/3.x/scala/Product.html) trait that the compiler adds as a mixin trait to every case class or case object. In Scala 2, this parent trait sometimes makes inferred types more complicated than they should be. Example: ```scala trait Kind @@ -40,15 +40,15 @@ appear in the inferred type. ## Transparent Traits -The traits `scala.Product`, `java.lang.Serializable` and `java.lang.Comparable` +The traits [`scala.Product`](https://scala-lang.org/api/3.x/scala/Product.html), [`java.io.Serializable`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/Serializable.html) and [`java.lang.Comparable`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Comparable.html) are treated automatically as transparent. Other traits are turned into transparent traits using the modifier `transparent`. Scala 2 traits can also be made transparent -by adding a [`@transparentTrait` annotation](https://scala-lang.org/api/3.x/scala/annotation/transparentTrait.html). This annotation is defined in `scala.annotation`. It will be deprecated and phased out once Scala 2/3 interopability is no longer needed. +by adding a [`@transparentTrait`](https://scala-lang.org/api/3.x/scala/annotation/transparentTrait.html) annotation. This annotation is defined in [`scala.annotation`](https://scala-lang.org/api/3.x/scala/annotation.html). It will be deprecated and phased out once Scala 2/3 interopability is no longer needed. Typically, transparent traits are traits that influence the implementation of inheriting classes and traits that are not usually used as types by themselves. Two examples from the standard collection library are: -- `IterableOps`, which provides method implementations for an `Iterable`. -- `StrictOptimizedSeqOps`, which optimises some of these implementations for sequences with efficient indexing. +- [`IterableOps`](https://scala-lang.org/api/3.x/scala/collection/IterableOps.html), which provides method implementations for an [`Iterable`](https://scala-lang.org/api/3.x/scala/collection/Iterable.html). +- [`StrictOptimizedSeqOps`](https://scala-lang.org/api/3.x/scala/collection/StrictOptimizedSeqOps.html), which optimises some of these implementations for sequences with efficient indexing. Generally, any trait that is extended recursively is a good candidate to be declared transparent. @@ -67,4 +67,4 @@ The precise rules are as follows: the resulting type is still a subtype of the bound `B`. - However, do not perform this widening if all transparent traits `Ti` can get replaced in that way. -The last clause ensures that a single transparent trait instance such as `Product` is not widened to `Any`. Transparent trait instances are only dropped when they appear in conjunction with some other type. +The last clause ensures that a single transparent trait instance such as [`Product`](https://scala-lang.org/api/3.x/scala/Product.html) is not widened to [`Any`](https://scala-lang.org/api/3.x/scala/Any.html). Transparent trait instances are only dropped when they appear in conjunction with some other type. diff --git a/docs/docs/reference/other-new-features/type-test.md b/docs/docs/reference/other-new-features/type-test.md index da9fa6a1c2b3..ee4e612e9a37 100644 --- a/docs/docs/reference/other-new-features/type-test.md +++ b/docs/docs/reference/other-new-features/type-test.md @@ -27,7 +27,7 @@ object Y: In both cases, a class test will be performed at runtime. But when the type test is on an abstract type (type parameter or type member), the test cannot be performed because the type is erased at runtime. -A `TypeTest` can be provided to make this test possible. +A [`TypeTest`](https://scala-lang.org/api/3.x/scala/reflect/TypeTest.html) can be provided to make this test possible. ```scala package scala.reflect @@ -80,7 +80,7 @@ new TypeTest[A, B]: If the type tests cannot be done there will be an unchecked warning that will be raised on the `case s: B =>` test. -The most common `TypeTest` instances are the ones that take any parameters (i.e. `TypeTest[Any, T]`). +The most common [`TypeTest`](https://scala-lang.org/api/3.x/scala/reflect/TypeTest.html) instances are the ones that take any parameters (i.e. `TypeTest[Any, T]`). To make it possible to use such instances directly in context bounds we provide the alias ```scala @@ -103,10 +103,10 @@ f[Int] // false ## TypeTest and ClassTag -`TypeTest` is a replacement for functionality provided previously by `ClassTag.unapply`. -Using `ClassTag` instances was unsound since classtags can check only the class component of a type. -`TypeTest` fixes that unsoundness. -`ClassTag` type tests are still supported but a warning will be emitted after 3.0. +[`TypeTest`](https://scala-lang.org/api/3.x/scala/reflect/TypeTest.html) is a replacement for functionality provided previously by `ClassTag.unapply`. +Using [`ClassTag`](https://scala-lang.org/api/3.x/scala/reflect/ClassTag.html) instances was unsound since classtags can check only the class component of a type. +[`TypeTest`](https://scala-lang.org/api/3.x/scala/reflect/TypeTest.html) fixes that unsoundness. +[`ClassTag`](https://scala-lang.org/api/3.x/scala/reflect/ClassTag.html) type tests are still supported but a warning will be emitted after 3.0. ## Example diff --git a/docs/docs/reference/soft-modifier.md b/docs/docs/reference/soft-modifier.md index 9706e18e3e5b..6421c38f00dd 100644 --- a/docs/docs/reference/soft-modifier.md +++ b/docs/docs/reference/soft-modifier.md @@ -4,9 +4,9 @@ title: "Soft Keywords" movedTo: https://docs.scala-lang.org/scala3/reference/soft-modifier.html --- -A soft modifier is one of the identifiers `opaque`, `inline`, `open`, `transparent`, and `infix`. +A soft modifier is one of the identifiers `infix`, `inline`, `opaque`, `open` and `transparent`. -A soft keyword is a soft modifier, or one of `derives`, `end`, `extension`, `throws`, `using`, `|`, `+`, `-`, `*` +A soft keyword is a soft modifier, or one of `as`, `derives`, `end`, `extension`, `throws`, `using`, `|`, `+`, `-`, `*` A soft modifier is treated as potential modifier of a definition if it is followed by a hard modifier or a keyword combination starting a definition (`def`, `val`, `var`, `type`, `given`, `class`, `trait`, `object`, `enum`, `case class`, `case object`). Between the two words there may be a sequence of newline tokens and soft modifiers. diff --git a/docs/docs/reference/syntax.md b/docs/docs/reference/syntax.md index 0bf2ed86a164..c2f990b0a953 100644 --- a/docs/docs/reference/syntax.md +++ b/docs/docs/reference/syntax.md @@ -122,7 +122,8 @@ type val var while with yield ### Soft keywords ``` -as derives end extension infix inline opaque open transparent using | * + - +as derives end extension infix inline opaque open throws +transparent using | * + - ``` See the [separate section on soft keywords](./soft-modifier.md) for additional