Skip to content

Commit 619e728

Browse files
authored
Merge pull request #6387 from dotty-staging/try-context-instance
Add missing files to contextual-instance
2 parents 2e078cb + f572f7a commit 619e728

File tree

5 files changed

+39
-38
lines changed

5 files changed

+39
-38
lines changed

docs/docs/reference/contextual-instance/derivation.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ enum Tree[T] derives Eql, Ordering, Pickling {
1010
case Leaf(elem: T)
1111
}
1212
```
13-
The `derives` clause generates evidence for the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
13+
The `derives` clause generates implicit instances of the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
1414
```scala
15-
evidence [T: Eql] for Eql[Tree[T]] = Eql.derived
16-
evidence [T: Ordering] for Ordering[Tree[T]] = Ordering.derived
17-
evidence [T: Pickling] for Pickling[Tree[T]] = Pickling.derived
15+
instance [T: Eql] of Eql[Tree[T]] = Eql.derived
16+
instance [T: Ordering] of Ordering[Tree[T]] = Ordering.derived
17+
instance [T: Pickling] of Pickling[Tree[T]] = Pickling.derived
1818
```
1919

2020
### Deriving Types
@@ -42,7 +42,7 @@ A trait or class can appear in a `derives` clause if its companion object define
4242
```scala
4343
def derived[T] given Generic[T] = ...
4444
```
45-
That is, the `derived` method takes an inferable parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. Evidence for `Generic` is generated automatically for any type that derives a typeclass with a `derived`
45+
That is, the `derived` method takes an inferable parameter of type `Generic` that determines the _shape_ of the deriving type `T` and it computes the typeclass implementation according to that shape. An implicit instance of `Generic` is generated automatically for any type that derives a typeclass with a `derived`
4646
method that refers to `Generic`. One can also derive `Generic` alone, which means a `Generic` instance is generated without any other type class instances. E.g.:
4747
```scala
4848
sealed trait ParseResult[T] derives Generic
@@ -94,9 +94,9 @@ is represented as `T *: Unit` since there is no direct syntax for such tuples: `
9494

9595
### The Generic Typeclass
9696

97-
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` evidence for `Generic[C[T_1,...,T_n]]` that follows the outline below:
97+
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an implicit instance of `Generic[C[T_1,...,T_n]]` that follows the outline below:
9898
```scala
99-
evidence [T_1, ..., T_n] for Generic[C[T_1,...,T_n]] {
99+
instance [T_1, ..., T_n] of Generic[C[T_1,...,T_n]] {
100100
type Shape = ...
101101
...
102102
}
@@ -114,7 +114,7 @@ would produce:
114114
object Result {
115115
import scala.compiletime.Shape._
116116

117-
evidence [T, E] for Generic[Result[T, E]] {
117+
instance [T, E] of Generic[Result[T, E]] {
118118
type Shape = Cases[(
119119
Case[Ok[T], T *: Unit],
120120
Case[Err[E], E *: Unit]
@@ -214,8 +214,8 @@ trait Eql[T] {
214214
def eql(x: T, y: T): Boolean
215215
}
216216
```
217-
We need to implement a method `Eql.derived` that produces an instance of `Eql[T]` provided
218-
there exists evidence of type `Generic[T]`. Here's a possible solution:
217+
We need to implement a method `Eql.derived` that produces an implicit instance of `Eql[T]` provided
218+
there exists an implicit instance of `Generic[T]`. Here's a possible solution:
219219
```scala
220220
inline def derived[T] given (ev: Generic[T]): Eql[T] = new Eql[T] {
221221
def eql(x: T, y: T): Boolean = {
@@ -234,7 +234,7 @@ there exists evidence of type `Generic[T]`. Here's a possible solution:
234234
The implementation of the inline method `derived` creates an instance of `Eql[T]` and implements its `eql` method. The right-hand side of `eql` mixes compile-time and runtime elements. In the code above, runtime elements are marked with a number in parentheses, i.e
235235
`(1)`, `(2)`, `(3)`. Compile-time calls that expand to runtime code are marked with a number in brackets, i.e. `[4]`, `[5]`. The implementation of `eql` consists of the following steps.
236236

237-
1. Map the compared values `x` and `y` to their mirrors using the `reflect` method of the implicitly passed `Generic` evidence `(1)`, `(2)`.
237+
1. Map the compared values `x` and `y` to their mirrors using the `reflect` method of the implicitly passed `Generic` instance `(1)`, `(2)`.
238238
2. Match at compile-time against the shape of the ADT given in `ev.Shape`. Dotty does not have a construct for matching types directly, but we can emulate it using an `inline` match over an `erasedValue`. Depending on the actual type `ev.Shape`, the match will reduce at compile time to one of its two alternatives.
239239
3. If `ev.Shape` is of the form `Cases[alts]` for some tuple `alts` of alternative types, the equality test consists of comparing the ordinal values of the two mirrors `(3)` and, if they are equal, comparing the elements of the case indicated by that ordinal value. That second step is performed by code that results from the compile-time expansion of the `eqlCases` call `[4]`.
240240
4. If `ev.Shape` is of the form `Case[elems]` for some tuple `elems` for element types, the elements of the case are compared by code that results from the compile-time expansion of the `eqlElems` call `[5]`.
@@ -298,14 +298,14 @@ non-empty, say of form `elem *: elems1`, the following code is produced:
298298

299299
The last, and in a sense most interesting part of the derivation is the comparison of a pair of element values in `tryEql`. Here is the definition of this method:
300300
```scala
301-
inline def tryEql[T](x: T, y: T) = implicit match {
301+
inline def tryEql[T](x: T, y: T) = instance match {
302302
case ev: Eql[T] =>
303303
ev.eql(x, y) // (15)
304304
case _ =>
305305
error("No `Eql` instance was found for $T")
306306
}
307307
```
308-
`tryEql` is an inline method that takes an element type `T` and two element values of that type as arguments. It is defined using an `evidence match` that tries to find evidence for `Eql[T]`. If an instance `ev` is found, it proceeds by comparing the arguments using `ev.eql`. On the other hand, if no instance is found
308+
`tryEql` is an inline method that takes an element type `T` and two element values of that type as arguments. It is defined using an `instance match` that tries to find an implicit instance of `Eql[T]`. If an instance `ev` is found, it proceeds by comparing the arguments using `ev.eql`. On the other hand, if no instance is found
309309
this signals a compilation error: the user tried a generic derivation of `Eql` for a class with an element type that does not support an `Eql` instance itself. The error is signaled by
310310
calling the `error` method defined in `scala.compiletime`.
311311

@@ -314,7 +314,7 @@ calling the `error` method defined in `scala.compiletime`.
314314
**Example:** Here is a slightly polished and compacted version of the code that's generated by inline expansion for the derived `Eql` instance of class `Tree`.
315315

316316
```scala
317-
evidence [T] given (elemEq: Eql[T]) for Eql[Tree[T]] {
317+
instance [T] given (elemEq: Eql[T]) of Eql[Tree[T]] {
318318
def eql(x: Tree[T], y: Tree[T]): Boolean = {
319319
val ev = the[Generic[Tree[T]]]
320320
val mx = ev.reflect(x)
@@ -333,21 +333,22 @@ evidence [T] given (elemEq: Eql[T]) for Eql[Tree[T]] {
333333
}
334334
```
335335

336-
One important difference between this approach and Scala-2 typeclass derivation frameworks such as Shapeless or Magnolia is that no automatic attempt is made to generate typeclass instances of elements recursively using the generic derivation framework. There must be an evidence value of type `Eql[T]` (which can of course be produced in turn using `Eql.derived`), or the compilation will fail. The advantage of this more restrictive approach to typeclass derivation is that it avoids uncontrolled transitive typeclass derivation by design. This keeps code sizes smaller, compile times lower, and is generally more predictable.
336+
One important difference between this approach and Scala-2 typeclass derivation frameworks such as Shapeless or Magnolia is that no automatic attempt is made to generate typeclass instances of elements recursively using the generic derivation framework. There must be an implicit instance of type `Eql[T]` (which can of course be produced in turn using `Eql.derived`), or the compilation will fail. The advantage of this more restrictive approach to typeclass derivation is that it avoids uncontrolled transitive typeclass derivation by design. This keeps code sizes smaller, compile times lower, and is generally more predictable.
337337

338338
### Derived Instances Elsewhere
339339

340340
Sometimes one would like to derive a typeclass instance for an ADT after the ADT is defined, without being able to change the code of the ADT itself.
341341
To do this, simply define an instance with the `derived` method of the typeclass as right-hand side. E.g, to implement `Ordering` for `Option`, define:
342342
```scala
343-
evidence [T: Ordering]: Ordering[Option[T]] = Ordering.derived
343+
instance [T: Ordering] of Ordering[Option[T]] = Ordering.derived
344344
```
345345
Usually, the `Ordering.derived` clause has an inferable parameter of type
346346
`Generic[Option[T]]`. Since the `Option` trait has a `derives` clause,
347-
the necessary evidence is already present in the companion object of `Option`.
348-
If the ADT in question does not have a `derives` clause, evidence for `Generic`
347+
the necessary implicit instance is already present in the companion object of `Option`.
348+
If the ADT in question does not have a `derives` clause, an implicit instance of `Generic`
349349
would still be synthesized by the compiler at the point where `derived` is called.
350-
This is similar to the situation with type tags or class tags: If no evidence is found, the compiler will synthesize it.
350+
This is similar to the situation with type tags or class tags: If no instance is found,
351+
the compiler will synthesize one.
351352

352353
### Syntax
353354

docs/docs/reference/contextual-instance/extension-methods.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ When is an extension method applicable? There are two possibilities.
3636

3737
- An extension method is applicable if it is visible under a simple name, by being defined
3838
or inherited or imported in a scope enclosing the application.
39-
- An extension method is applicable if it is a member of some evidence value at the point of the application.
39+
- An extension method is applicable if it is a member of some implicit instance at the point of the application.
4040

4141
As an example, consider an extension method `longestStrings` on `String` defined in a trait `StringSeqOps`.
4242

@@ -48,15 +48,15 @@ trait StringSeqOps {
4848
}
4949
}
5050
```
51-
We can make the extension method available by defining evidence for `StringSeqOps`, like this:
51+
We can make the extension method available by defining an implicit instance of `StringSeqOps`, like this:
5252
```scala
5353
instance ops1 of StringSeqOps
5454
```
5555
Then
5656
```scala
5757
List("here", "is", "a", "list").longestStrings
5858
```
59-
is legal everywhere `ops1` is available as evidence. Alternatively, we can define `longestStrings` as a member of a normal object. But then the method has to be brought into scope to be usable as an extension method.
59+
is legal everywhere `ops1` is available as an implicit. Alternatively, we can define `longestStrings` as a member of a normal object. But then the method has to be brought into scope to be usable as an extension method.
6060

6161
```scala
6262
object ops2 extends StringSeqOps
@@ -69,32 +69,32 @@ Assume a selection `e.m[Ts]` where `m` is not a member of `e`, where the type ar
6969
and where `T` is the expected type. The following two rewritings are tried in order:
7070

7171
1. The selection is rewritten to `m[Ts](e)`.
72-
2. If the first rewriting does not typecheck with expected type `T`, and there is evidence `i`
73-
in either the current scope or in the evidence scope of `T`, and `i` defines an extension
72+
2. If the first rewriting does not typecheck with expected type `T`, and there is an implicit `i`
73+
in either the current scope or in the implicit scope of `T`, and `i` defines an extension
7474
method named `m`, then selection is expanded to `i.m[Ts](e)`.
7575
This second rewriting is attempted at the time where the compiler also tries an implicit conversion
7676
from `T` to a type containing `m`. If there is more than one way of rewriting, an ambiguity error results.
7777

7878
So `circle.circumference` translates to `CircleOps.circumference(circle)`, provided
79-
`circle` has type `Circle` and `CircleOps` is an eligible evidence value (i.e. it is visible at the point of call or it is defined in the companion object of `Circle`).
79+
`circle` has type `Circle` and `CircleOps` is an eligible implicit (i.e. it is visible at the point of call or it is defined in the companion object of `Circle`).
8080

81-
### Evidence for Extension Methods
81+
### Implicit Instances for Extension Methods
8282

83-
Evidence that defines extension methods can also be defined without a `for` clause. E.g.,
83+
Implicits that wrap extension methods can also be defined without an `of` clause. E.g.,
8484

8585
```scala
86-
evidence StringOps {
86+
instance StringOps {
8787
def (xs: Seq[String]) longestStrings: Seq[String] = {
8888
val maxLength = xs.map(_.length).max
8989
xs.filter(_.length == maxLength)
9090
}
9191
}
9292

93-
evidence {
93+
instance {
9494
def (xs: List[T]) second[T] = xs.tail.head
9595
}
9696
```
97-
If such an evidence is anonymous (as in the second example above), its name is synthesized from the name
97+
If such an instance is anonymous (as in the second example above), its name is synthesized from the name
9898
of the first defined extension method.
9999

100100
### Operators

docs/docs/reference/contextual-instance/inferable-by-name-parameters.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: doc-page
3-
title: "Implicit By-Name Parameters"
3+
title: "Inferable By-Name Parameters"
44
---
55

66
Inferable by-name parameters can be used to avoid a divergent inferred expansion. Example:
@@ -42,7 +42,7 @@ The precise steps for constructing an inferable argument for a by-name parameter
4242

4343
1. This instance is not immediately available as candidate for argument inference (making it immediately available could result in a loop in the synthesized computation). But it becomes available in all nested contexts that look again for an inferred argument to a by-name parameter.
4444

45-
1. If this search succeeds with expression `E`, and `E` contains references to the evidence `lv`, replace `E` by
45+
1. If this search succeeds with expression `E`, and `E` contains references to `lv`, replace `E` by
4646

4747

4848
```scala

docs/docs/reference/contextual-instance/multiversal-equality.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ that derives `Eql`, e.g.
3030
```scala
3131
class T derives Eql
3232
```
33-
Alternatively, one can also provide the derived evidence directly, like this:
33+
Alternatively, one can also provide the derived instance directly, like this:
3434
```scala
3535
instance of Eql[T, T] = Eql.derived
3636
```
@@ -74,7 +74,7 @@ defined as follows:
7474
def eqlAny[L, R]: Eql[L, R] = Eql.derived
7575
```
7676

77-
Even though `eqlAny` is not declared as `evidence`, the compiler will still
77+
Even though `eqlAny` is not declared as `instance`, the compiler will still
7878
construct an `eqlAny` instance as answer to an implicit search for the
7979
type `Eql[L, R]`, unless `L` or `R` have `Eql` instances
8080
defined on them, or the language feature `strictEquality` is enabled
@@ -140,7 +140,7 @@ The `Eql` object defines implicit instances for
140140
- `java.lang.Number`, `java.lang.Boolean`, and `java.lang.Character`,
141141
- `scala.collection.Seq`, and `scala.collection.Set`.
142142

143-
Instances are defined so that everyone of these types is has a reflexive `Eql` evidence, and the following holds:
143+
Instances are defined so that everyone of these types has a reflexive `Eql` instance, and the following holds:
144144

145145
- Primitive numeric types can be compared with each other.
146146
- Primitive numeric types can be compared with subtypes of `java.lang.Number` (and _vice versa_).

docs/docs/reference/contextual-instance/query-types.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ context query literal, `E` is converted to a context query literal by rewriting
2727
```
2828
where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed
2929
before the expression `E` is typechecked, which means that `x_1`, ..., `x_n`
30-
are available as evidence in `E`.
30+
are available as implicits in `E`.
3131

3232
Like query types, query literals are written with a `given` prefix. They differ from normal function literals in two ways:
3333

@@ -139,9 +139,9 @@ object Test {
139139
```
140140
**Explanations**: We use a context query type `given WrappedResult[T] => Boolean`
141141
as the type of the condition of `ensuring`. An argument to `ensuring` such as
142-
`(result == 6)` will therefore have evidence of type `WrappedResult[T]` in
142+
`(result == 6)` will therefore have an implicit instance of type `WrappedResult[T]` in
143143
scope to pass along to the `result` method. `WrappedResult` is a fresh type, to make sure
144-
that we do not get unwanted evidence types in scope (this is good practice in all cases
144+
that we do not get unwanted implicit instances in scope (this is good practice in all cases
145145
where given clauses are involved). Since `WrappedResult` is an opaque type alias, its
146146
values need not be boxed, and since `ensuring` is added as an extension method, its argument
147147
does not need boxing either. Hence, the implementation of `ensuring` is as about as efficient

0 commit comments

Comments
 (0)