Skip to content

Commit 944b6b3

Browse files
authored
Merge pull request #6417 from dotty-staging/try-contextual-delegate
Fixes to repr and implicit trials
2 parents 1e471fa + 9a038f9 commit 944b6b3

17 files changed

+40
-39
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The precise steps for synthesizing an argument for a by-name parameter of type `
4040
```
4141
where `lv` is an arbitrary fresh name.
4242

43-
1. This implicit 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 implicit argument to a by-name parameter.
43+
1. This implicit is not immediately available as a 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 implicit argument to a by-name parameter.
4444

4545
1. If this search succeeds with expression `E`, and `E` contains references to the implicit `lv`, replace `E` by
4646

docs/docs/reference/contextual-implicit/inferable-params.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ max(List(1, 2, 3), Nil)
3030

3131
## Anonymous Implicit Parameters
3232

33-
In many situations, the name of an implicit parameter of a method need not be mentioned explicitly at all, since it is only used as synthesized implicit for other constraints. In that case one can avoid defining a parameter name and just provide its type. Example:
33+
In many situations, the name of an implicit parameter of a method need not be mentioned explicitly at all, since it is only used as a synthesized argument for other implicit parameters. In that case one can avoid defining a parameter name and just provide its type. Example:
3434
```scala
3535
def maximum[T](xs: List[T]) given Ord[T]: T =
3636
xs.reduceLeft(max)

docs/docs/reference/contextual-implicit/instance-defs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ The name of an implicit instance can be left out. So the implicit instance defin
4141
of the last section can also be expressed like this:
4242
```scala
4343
implicit for Ord[Int] { ... }
44-
implicit [T] or Ord[List[T]] given (ord: Ord[T]) { ... }
44+
implicit [T] for Ord[List[T]] given (ord: Ord[T]) { ... }
4545
```
4646
If the name of an implicit is missing, the compiler will synthesize a name from
4747
the type(s) in the `for` clause.
4848

4949
## Alias Implicits
5050

51-
An alias implicit defines an implicit value that is equal to some expression. E.g.:
51+
An alias can be used to define an implicit value that is equal to some expression. E.g.:
5252
```scala
5353
implicit global for ExecutionContext = new ForkJoinPool()
5454
```

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ that derives `Eql`, e.g.
3131
```scala
3232
class T derives Eql
3333
```
34-
Alternatively, one can also provide an `Eql` implicit directly, like this:
34+
Alternatively, one can also define an `Eql` implicit directly, like this:
3535
```scala
3636
implicit for Eql[T, T] = Eql.derived
3737
```
@@ -141,7 +141,7 @@ The `Eql` object defines implicits for comparing
141141
- `java.lang.Number`, `java.lang.Boolean`, and `java.lang.Character`,
142142
- `scala.collection.Seq`, and `scala.collection.Set`.
143143

144-
Implicits are defined so that every one of these types is has a reflexive `Eql` implicit, and the following holds:
144+
Implicits are defined so that every one of these types has a reflexive `Eql` implicit, and the following holds:
145145

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

docs/docs/reference/contextual-implicit/query-types-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ Gist](https://gist.github.com/OlivierBlanvillain/234d3927fe9e9c6fba074b53a7bd9
7676

7777
### Type Checking
7878

79-
After desugaring no additional typing rules are required for context query types.
79+
After desugaring no additional typing rules are required for implicit function types.

docs/docs/reference/contextual-implicit/relationship-implicits.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ one can write
140140

141141
### Implicit Classes
142142

143-
Implicit classes in Scala 2 are often used to define extension methods, which are directly supported in Dotty. Other uses of implicit classes can be simulated by a pair of a regular class and a conversion delegate.
143+
Implicit classes in Scala 2 are often used to define extension methods, which are directly supported in Dotty. Other uses of implicit classes can be simulated by a pair of a regular class and a conversion instance.
144144

145145
### Abstract Implicits
146146

147-
An abstract implicit `val` or `def` in Scala 2 can be expressed in Dotty using a regular abstract definition and an implicit alias. E.g., Scala 2's
147+
An abstract implicit `val` or `def` in Scala 2 can be expressed in Dotty using a regular abstract definition and an alias implicit. E.g., Scala 2's
148148
```scala
149149
implicit def symDeco: SymDeco
150150
```

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ enum Tree[T] derives Eql, Ordering, Pickling {
1010
case Leaf(elem: T)
1111
}
1212
```
13-
The `derives` clause generates repr representatives of the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
13+
The `derives` clause generates representatives of the `Eql`, `Ordering`, and `Pickling` traits in the companion object `Tree`:
1414
```scala
1515
repr [T: Eql] of Eql[Tree[T]] = Eql.derived
1616
repr [T: Ordering] of Ordering[Tree[T]] = Ordering.derived
@@ -19,7 +19,7 @@ repr [T: Pickling] of Pickling[Tree[T]] = Pickling.derived
1919

2020
### Deriving Types
2121

22-
Besides for `enums`, typeclasses can also be derived for other sets of classes and objects that form an algebraic data type. These are:
22+
Besides for enums, typeclasses can also be derived for other sets of classes and objects that form an algebraic data type. These are:
2323

2424
- individual case classes or case objects
2525
- sealed classes or traits that have only case classes and case objects as children.
@@ -93,8 +93,7 @@ is represented as `T *: Unit` since there is no direct syntax for such tuples: `
9393

9494
### The Generic Typeclass
9595

96-
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` an representative of `Generic[C[T_1,...,T_n]]` that follows
97-
the outline below:
96+
For every class `C[T_1,...,T_n]` with a `derives` clause, the compiler generates in the companion object of `C` a representative of `Generic[C[T_1,...,T_n]]` that follows the outline below:
9897
```scala
9998
repr [T_1, ..., T_n] of Generic[C[T_1,...,T_n]] {
10099
type Shape = ...
@@ -215,7 +214,7 @@ trait Eql[T] {
215214
}
216215
```
217216
We need to implement a method `Eql.derived` that produces a representative of `Eql[T]` provided
218-
there exists evidence of type `Generic[T]`. Here's a possible solution:
217+
there exists a representative of type `Generic[T]`. Here's a possible solution:
219218
```scala
220219
inline def derived[T] given (ev: Generic[T]): Eql[T] = new Eql[T] {
221220
def eql(x: T, y: T): Boolean = {
@@ -234,7 +233,7 @@ there exists evidence of type `Generic[T]`. Here's a possible solution:
234233
The implementation of the inline method `derived` creates a representative 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
235234
`(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.
236235

237-
1. Map the compared values `x` and `y` to their mirrors using the `reflect` method of the implicitly passed `Generic` evidence `(1)`, `(2)`.
236+
1. Map the compared values `x` and `y` to their mirrors using the `reflect` method of the implicitly passed `Generic` `(1)`, `(2)`.
238237
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.
239238
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]`.
240239
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]`.
@@ -302,7 +301,7 @@ The last, and in a sense most interesting part of the derivation is the comparis
302301
case ev: Eql[T] =>
303302
ev.eql(x, y) // (15)
304303
case _ =>
305-
error("No `Eql` representative was found for $T")
304+
error("No `Eql` instance was found for $T")
306305
}
307306
```
308307
`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 `implicit match` that tries to find a representative of `Eql[T]`. If a representative `ev` is found, it proceeds by comparing the arguments using `ev.eql`. On the other hand, if no representative is found

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Then
5656
```scala
5757
List("here", "is", "a", "list").longestStrings
5858
```
59-
is legal everywhere `ops1` is available as a representative. 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 eligible. 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
@@ -80,7 +80,7 @@ So `circle.circumference` translates to `CircleOps.circumference(circle)`, provi
8080

8181
### Representatives for Extension Methods
8282

83-
Representatives that define extension methods can also be defined without a `for` clause. E.g.,
83+
Representatives that define extension methods can also be defined without an `of` clause. E.g.,
8484

8585
```scala
8686
repr StringOps {
@@ -94,12 +94,12 @@ repr {
9494
def (xs: List[T]) second[T] = xs.tail.head
9595
}
9696
```
97-
If such representatives are anonymous (as in the second clause), their name is synthesized from the name
97+
If such a representative is anonymous (as in the second clause), its name is synthesized from the name
9898
of the first defined extension method.
9999

100100
### Operators
101101

102-
The extension method syntax also applies to the definitions of operators.
102+
The extension method syntax also applies to the definition of operators.
103103
In each case the definition syntax mirrors the way the operator is applied.
104104
Examples:
105105
```scala

docs/docs/reference/contextual-repr/import-implied.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object B {
1818
In the code above, the `import A._` clause of object `B` will import all members
1919
of `A` _except_ the representative `tc`. Conversely, the second import `import repr A._` will import _only_ that representative.
2020

21-
Generally, a normal import clause brings all definitions except representatives into scope whereas an `import repr` clause brings only representatives into scope.
21+
Generally, a normal import clause brings all members except representatives into scope whereas an `import repr` clause brings only representatives into scope.
2222

2323
There are two main benefits arising from these rules:
2424

@@ -29,7 +29,7 @@ There are two main benefits arising from these rules:
2929
can be anonymous, so the usual recourse of using named imports is not
3030
practical.
3131

32-
### Relationship with Old-Style Implicits
32+
### Migration
3333

3434
The rules of representatives above have the consequence that a library
3535
would have to migrate in lockstep with all its users from old style implicits and
@@ -49,4 +49,4 @@ The following modifications avoid this hurdle to migration.
4949

5050
These rules mean that library users can use `import repr` to access old-style implicits in Scala 3.0,
5151
and will be gently nudged and then forced to do so in later versions. Libraries can then switch to
52-
representation clauses once their user base has migrated.
52+
`repr` clauses once their user base has migrated.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The precise steps for synthesizing an argument for a by-name parameter of type `
4040
```
4141
where `lv` is an arbitrary fresh name.
4242

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

4545
1. If this search succeeds with expression `E`, and `E` contains references to the representative `lv`, replace `E` by
4646

docs/docs/reference/contextual-repr/inferable-params.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The `max` method can be applied as follows:
2020
```scala
2121
max(2, 3).given(IntOrd)
2222
```
23-
The `.given(IntOrd)` part provides the `IntOrd` representative as an argument for the `ord` parameter. But the point of
23+
The `.given(IntOrd)` part passes `IntOrd` as an argument for the `ord` parameter. But the point of
2424
implicit parameters is that this argument can also be left out (and it usually is). So the following
2525
applications are equally valid:
2626
```scala

docs/docs/reference/contextual-repr/instance-defs.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ An alias can be used to define a representative that is equal to some expression
5252
```scala
5353
repr ctx of ExecutionContext = new ForkJoinPool()
5454
```
55-
This creates a representative `ctx` of type `ExecutionContext` that resolves to the right hand side `new ForkJoinPool()`. The first time a representative of `ExecutionContext` is demanded, a new `ForkJoinPool` is created, which is then returned for this and all subsequent accesses to `ctx`.
55+
This creates a repreentative `global` of type `ExecutionContext` that resolves to the right hand side `new ForkJoinPool()`.
56+
The first time `global` is accessed, a new `ForkJoinPool` is created, which is then
57+
returned for this and all subsequent accesses to `global`.
5658

5759
Alias representatives can be anonymous, e.g.
5860
```scala
@@ -62,7 +64,7 @@ An alias representative can have type and context parameters just like any other
6264

6365
## Representative Creation
6466

65-
A representative without type parameters or given clause is created on-demand, the first time it is accessed. No attempt is made to ensure safe publication, which means that different threads might create different representatives for the same `repr` clause. If a `repr` clause has type parameters or a given clause, a fresh representative is created for each reference.
67+
A representative without type parameters or given clause is created on-demand, the first time it is accessed. It is not required to ensure safe publication, which means that different threads might create different representatives for the same `repr` clause. If a `repr` clause has type parameters or a given clause, a fresh representative is created for each reference.
6668

6769
## Syntax
6870

docs/docs/reference/contextual-repr/motivation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ The following pages introduce a redesign of contextual abstractions in Scala. Th
5151

5252
2. [Given Clauses](./inferable-params.html) are a new syntax for implicit _parameters_ and their _arguments_. Both are introduced with the same keyword, `given`. This unambiguously aligns parameters and arguments, solving a number of language warts. It also allows us to have several implicit parameter sections, and to have implicit parameters followed by normal ones.
5353

54-
3. [Imports of Representatives](./import-implied.html) are new form of import that specifically imports representatives and nothing else. Representatives _must be_ imported with `import repr`, a plain import will no longer bring them into scope.
54+
3. [Import Repr](./import-implied.html) is new form of import that specifically imports representatives and nothing else. Representatives _must be_ imported with `import repr`, a plain import will no longer bring them into scope.
5555

5656
4. [Implicit Conversions](./conversions.html) are now expressed as representatives of a standard `Conversion` class. All other forms of implicit conversions will be phased out.
5757

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ that derives `Eql`, e.g.
3131
```scala
3232
class T derives Eql
3333
```
34-
Alternatively, one can also provide an `Eql` representative directly, like this:
34+
Alternatively, one can also define an `Eql` representative directly, like this:
3535
```scala
3636
repr for Eql[T, T] = Eql.derived
3737
```
@@ -75,7 +75,7 @@ defined as follows:
7575
def eqlAny[L, R]: Eql[L, R] = Eql.derived
7676
```
7777

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

144-
Representative are defined so that every one of these types is has a reflexive `Eql` representative, and the following holds:
144+
Representative are defined so that every one of these types has a reflexive `Eql` representative, and the following holds:
145145

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed
2828
before the expression `E` is typechecked, which means that `x_1`, ..., `x_n`
2929
are available as representatives in `E`.
3030

31-
Like their types, implicit function iterals are written with a `given` prefix. They differ from normal function literals in two ways:
31+
Like their types, implicit function literals are written with a `given` prefix. They differ from normal function literals in two ways:
3232

3333
1. Their parameters are implicit.
3434
2. Their types are implicit function types.

docs/docs/reference/contextual-repr/relationship-implicits.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ Representative clauses can be mapped to combinations of implicit objects, classe
2828
class ListOrd[T](implicit ord: Ord[T]) extends Ord[List[T]] { ... }
2929
final implicit def ListOrd[T](implicit ord: Ord[T]): ListOrd[T] = new ListOrd[T]
3030
```
31-
3. Alias representatives map to implicit methods. If the representatives has neither type parameters nor a given clause, the result of creating an instance is cached in a variable. If in addition the right hand side is pure and cheap to compute, a simple `val` can be used instead. E.g.,
31+
3. Alias representatives map to implicit methods. If the representative has neither type parameters nor a given clause, the result of creating an instance is cached in a variable. If in addition the right hand side is pure and cheap to compute, a simple `val` can be used instead. E.g.,
3232
```scala
33-
repr ec of ExecutionContext = new ForkJoinContext()
33+
repr global of ExecutionContext = new ForkJoinContext()
3434
repr config of Config = default.config
3535
```
3636
map to
3737
```scala
38-
private[this] var ec$cache: ExecutionContext | Null = null
39-
final implicit def ec: ExecutionContext = {
40-
if (ec$cache == null) ec$cache = new ForkJoinContext()
41-
ec$cache
38+
private[this] var global$cache: ExecutionContext | Null = null
39+
final implicit def global: ExecutionContext = {
40+
if (global$cache == null) global$cache = new ForkJoinContext()
41+
global$cache
4242
}
4343

4444
final implicit val config: Config = default.config

docs/docs/reference/contextual-repr/typeclasses.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ layout: doc-page
33
title: "Implementing Typeclasses"
44
---
55

6-
Traits, representatives, extension methods and context bounds
6+
Representatives, extension methods and context bounds
77
allow a concise and natural expression of _typeclasses_. Typeclasses are just traits
88
with canonical implementations defined by representatives. Here are some examples of standard typeclasses:
99

0 commit comments

Comments
 (0)