You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -7,116 +7,129 @@ Implicit resolution uses a new algorithm which caches implicit results
7
7
more aggressively for performance. There are also some changes that
8
8
affect implicits on the language level.
9
9
10
-
1. Types of implicit values and result types of implicit methods
11
-
must be explicitly declared. Excepted are only values in local blocks
12
-
where the type may still be inferred:
13
-
```scala
14
-
classC {
15
-
16
-
valctx:Context= ... // ok
17
-
18
-
/*!*/implicitvalx= ... // error: type must be given explicitly
19
-
20
-
/*!*/implicitdefy= ... // error: type must be given explicitly
21
-
22
-
valy= {
23
-
implicitvalctx=this.ctx // ok
24
-
...
25
-
}
26
-
```
27
-
2. Nesting is now taken into account for selecting an implicit.
28
-
Considerfor instance the following scenario:
29
-
```scala
30
-
deff(impliciti: C) = {
31
-
defg(implicitj: C) = {
32
-
implicitly[C]
33
-
}
10
+
**1.** Types of implicit values and result types of implicit methods
11
+
must be explicitly declared. Excepted are only values in local blocks
12
+
where the type may still be inferred:
13
+
```scala
14
+
classC {
15
+
16
+
valctx:Context= ... // ok
17
+
18
+
/*!*/implicitvalx= ... // error: type must be given explicitly
19
+
20
+
/*!*/implicitdefy= ... // error: type must be given explicitly
21
+
22
+
valy= {
23
+
implicitvalctx=this.ctx // ok
24
+
...
25
+
}
26
+
```
27
+
**2.**Nesting is now taken into account for selecting an implicit.Considerfor instance the following scenario:
28
+
```scala
29
+
deff(impliciti: C) = {
30
+
defg(implicitj: C) = {
31
+
implicitly[C]
34
32
}
35
-
```
36
-
This will now resolve the `implicitly` call to `j`, because `j` is nested
37
-
more deeply than `i`. Previously, this would have resulted in an
38
-
ambiguity error. The previous possibility of an implicit search failure
39
-
due to _shadowing_ (where an implicit is hidden by a nested definition)
40
-
no longer applies.
41
-
42
-
3. Package prefixes no longer contribute to the implicit search scope of a type.
43
-
Example:
44
-
```scala
45
-
packagep
46
-
givena as A
47
-
48
-
objecto {
49
-
givenb as B
50
-
typeC
51
-
}
52
-
```
53
-
Both `a` and `b` are visible asimplicits at the point of the definition
54
-
of `type C`. However, a reference to `p.o.C` outside of package`p`will
55
-
have only `b` in its implicit search scope but not `a`.
56
-
57
-
4. The treatment of ambiguity errors has changed. If an ambiguity is encountered
58
-
in some recursive step of an implicit search, the ambiguity is propagated to the caller.
59
-
Example:Say you have the following definitions:
60
-
```scala
61
-
classA
62
-
classBextendsC
63
-
classC
64
-
implicitdefa1:A
65
-
implicitdefa2:A
66
-
implicitdefb(implicita: A):B
67
-
implicitdefc:C
68
-
```
69
-
and the query `implicitly[C]`.
70
-
71
-
This query would now be classified asambiguous. This makes sense, after all
72
-
there are two possible solutions, `b(a1)` and `b(a2)`, neither of which is better
73
-
than the other and both of which are better than the third solution, `c`.
74
-
By contrast, Scala2 would have rejected the search for `A` as
75
-
ambiguous, and subsequently have classified the query `b(implicitly[A])` asa normal fail,
76
-
which means that the alternative `c` would be chosen assolution!
77
-
78
-
Scala2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement
79
-
the analogue of a "negated" search in implicit resolution, where a query `Q1` fails if some
80
-
other query `Q2` succeeds and `Q1` succeeds if `Q2` fails. With the new cleaned up behavior
81
-
these techniques no longer work. But there is now a new special type`scala.implicits.Not`
82
-
which implements negation directly. For any query type`Q`: `Not[Q]` succeeds if and only if
83
-
the implicit search for `Q` fails.
84
-
85
-
5. The treatment of divergence errors has also changed. A divergent implicit is
86
-
treated asa normal failure, after which alternatives are still tried. This also makes
87
-
sense: Encountering a divergent implicit means that we assume that no finite
88
-
solution can be found on the corresponding path, but another path can still be tried. By contrast
89
-
most (but not all) divergence errors in Scala2 would terminate the implicit
90
-
search asa whole.
91
-
92
-
6. Scala-2 gives a lower level of priority to implicit conversions with call-by-name
93
-
parameters relative to implicit conversions with call-by-value parameters. Dotty
94
-
drops this distinction. So the following code snippet would be ambiguous in Dotty:
95
-
```scala
96
-
implicitdefconv1(x: Int):A=newA(x)
97
-
implicitdefconv2(x: =>Int):A=newA(x)
98
-
defbuzz(y: A) =???
99
-
buzz(1) // error: ambiguous
100
-
```
101
-
7. The rule for picking a _most specific_ alternative among a set of overloaded or implicit
102
-
alternatives is refined to take context parameters into account. Allelse
103
-
being equal, an alternative that takes some context parameters is taken to be less specific
104
-
than an alternative that takes none. If both alternatives take context parameters, we try
105
-
to choose between them asif they were methods with regular parameters.
106
-
The following paragraph in the SLS is affected by thischange:
107
-
108
-
_Original version:_
109
-
110
-
>An alternative A is _more specific_ than an alternative Bif the relative weight of A over B is greater than the relative weight of B over A.
111
-
112
-
_Modified version:_
113
-
114
-
An alternative A is _more specific_ than an alternative Bif
115
-
116
-
- the relative weight of A over B is greater than the relative weight of B over A, or
117
-
- the relative weights are the same, and A takes no implicit parameters but B does, or
118
-
- the relative weights are the same, both A and B take implicit parameters, and
119
-
A is more specific than Bif all implicit parameters in either alternative are
120
-
replaced by regular parameters.
33
+
}
34
+
```
35
+
This will now resolve the `implicitly` call to `j`, because `j` is nested
36
+
more deeply than `i`. Previously, this would have resulted in an
37
+
ambiguity error. The previous possibility of an implicit search failure
38
+
due to _shadowing_ (where an implicit is hidden by a nested definition)
39
+
no longer applies.
40
+
41
+
**3.**Package prefixes no longer contribute to the implicit search scope of a type. Example:
42
+
```scala
43
+
packagep
44
+
givena as A
45
+
46
+
objecto {
47
+
givenb as B
48
+
typeC
49
+
}
50
+
```
51
+
Both `a` and `b` are visible asimplicits at the point of the definition
52
+
of `type C`. However, a reference to `p.o.C` outside of package`p`will
53
+
have only `b` in its implicit search scope but not `a`.
54
+
55
+
**4.**The treatment of ambiguity errors has changed. If an ambiguity is encountered in some recursive step of an implicit search, the ambiguity is propagated to the caller.
56
+
57
+
Example:Say you have the following definitions:
58
+
```scala
59
+
classA
60
+
classBextendsC
61
+
classC
62
+
implicitdefa1:A
63
+
implicitdefa2:A
64
+
implicitdefb(implicita: A):B
65
+
implicitdefc:C
66
+
```
67
+
and the query `implicitly[C]`.
68
+
69
+
This query would now be classified asambiguous. This makes sense, after all
70
+
there are two possible solutions, `b(a1)` and `b(a2)`, neither of which is better
71
+
than the other and both of which are better than the third solution, `c`.
72
+
By contrast, Scala2 would have rejected the search for `A` as
73
+
ambiguous, and subsequently have classified the query `b(implicitly[A])` asa normal fail,
74
+
which means that the alternative `c` would be chosen assolution!
75
+
76
+
Scala2's somewhat puzzling behavior with respect to ambiguity has been exploited to implement
77
+
the analogue of a "negated" search in implicit resolution, where a query `Q1` fails if some
78
+
other query `Q2` succeeds and `Q1` succeeds if `Q2` fails. With the new cleaned up behavior
79
+
these techniques no longer work. But there is now a new special type`scala.implicits.Not`
80
+
which implements negation directly. For any query type`Q`: `Not[Q]` succeeds if and only if
81
+
the implicit search for `Q` fails.
82
+
83
+
**5.**The treatment of divergence errors has also changed. A divergent implicit is treated asa normal failure, after which alternatives are still tried. This also makes sense: Encountering a divergent implicit means that we assume that no finite solution can be found on the corresponding path, but another path can still be tried. By contrast,
84
+
most (but not all) divergence errors in Scala2 would terminate the implicit search asa whole.
85
+
86
+
**6.**Scala-2 gives a lower level of priority to implicit conversions with call-by-name parameters relative to implicit conversions with call-by-value parameters. Dotty drops this distinction. So the following code snippet would be ambiguous in Dotty:
87
+
88
+
```scala
89
+
implicitdefconv1(x: Int):A=newA(x)
90
+
implicitdefconv2(x: =>Int):A=newA(x)
91
+
defbuzz(y: A) =???
92
+
buzz(1) // error: ambiguous
93
+
```
94
+
**7.**The rule for picking a _most specific_ alternative among a set of overloaded or implicit alternatives is refined to take context parameters into account. Allelse being equal, an alternative that takes some context parameters is taken to be less specific than an alternative that takes none. If both alternatives take context parameters, we try to choose between them asif they were methods with regular parameters. The following paragraph in the SLS is affected by thischange:
95
+
96
+
_Original version:_
97
+
98
+
>An alternative A is _more specific_ than an alternative Bif the relative weight of A over B is greater than the relative weight of B over A.
99
+
100
+
_Modified version:_
101
+
102
+
An alternative A is _more specific_ than an alternative Bif
103
+
104
+
- the relative weight of A over B is greater than the relative weight of B over A, or
105
+
- the relative weights are the same, and A takes no implicit parameters but B does, or
106
+
- the relative weights are the same, both A and B take implicit parameters, and A is more specific than Bif all implicit parameters in either alternative are replaced by regular parameters.
107
+
108
+
**8.**The previous disambiguation of implicits based on inheritance depth is refined to make it transitive. Transitivity is important to guarantee that search outcomes are compilation-order independent. Here's a scenario where the previous rules violated transitivity:
109
+
```scala
110
+
classAextendsB
111
+
objectA { givena ... }
112
+
classB
113
+
objectBextendsC { givenb ... }
114
+
classC { givenc }
115
+
```
116
+
Here `a` is more specific than `b` since the companion class`A` is a subclass of the companion class`B`. Also, `b` is more specific than `c`
117
+
since `object B` extendsclass`C`. But `a` is not more specific than `c`. This means if `a, b, c` are all applicable implicits, it makes
118
+
a difference in what order they are compared. If we compare `b` and `c`
119
+
first, we keep `b` and drop `c`. Then, comparing `a` with`b` we keep `a`. Butif we compare `a` with`c` first, we fail with an ambiguity error.
120
+
121
+
Thenew rules are asfollows:Animplicit `a` defined in `A` is more specific than an implicit `b` defined in `B` if
122
+
123
+
- `A` extends`B`, or
124
+
- `A` is an objectand the companion classof `A` extends`B`, or
125
+
- `A` and `B` are objects,
126
+
`B` does not inherit any implicit members from base classes (*),
127
+
and the companion classof `A` extends the companion classof `B`.
128
+
129
+
Condition (*) is new. It is necessary to ensure that the defined relation is transitive.
0 commit comments