2
2
layout : blog-detail
3
3
post-type : blog
4
4
by : Oliver Bračevac, EPFL
5
- title : " Changes to Givens Prioritization in Scala 3.5"
5
+ title : " Changes to Givens in Scala 3.5"
6
6
---
7
7
8
- ## Motivation
8
+ ## New Prioritization of Givens
9
9
10
10
Starting with Scala 3.5, the prioritization of givens has been
11
11
improved to better handle inheritance triangles, resulting in enhanced
12
12
typeclass support.
13
13
14
- Consider a scenario with the following inheritance triangle of type classes:
14
+ Consider a scenario with the following inheritance triangle of type
15
+ classes:
15
16
``` scala
16
17
trait Functor [F [_]]:
17
18
extension [A , B ](x : F [A ]) def map (f : A => B ): F [B ]
@@ -40,19 +41,24 @@ than the other. However, all we really need is the functionality of
40
41
41
42
In Scala 3.5, the compiler now selects the instance with the _ most
42
43
general_ subtype that satisfies the context bound of ` fmap ` . In this
43
- case, it chooses ` a:Functor[List] ` .
44
+ case, it chooses the desired ` a:Functor[List] ` .
44
45
45
46
Inheritance triangles like this are common in practice, and the
46
47
prioritization change in Scala 3.5 makes working with them more
47
48
intuitive and straightforward.
48
49
49
- ## Tips for Migrating to 3.5
50
+ ### Community Impact
50
51
51
52
Based on our evaluation using the [ open community
52
53
build] ( https://github.com/VirtusLab/community-build3 ) , the impact of
53
54
this change on existing Scala 3 projects has been minimal. However,
54
55
there may still be cases where the behavior of existing programs
55
- changes due to the new prioritization of givens.
56
+ changes due to the new prioritization of givens. Cf. below for
57
+ tips to migrate to Scala 3.5.
58
+
59
+
60
+ ## Tips for Migrating to the New Prioritization
61
+
56
62
57
63
In some cases, the new prioritization might silently select the wrong
58
64
` given ` . For example, consider a library that provides a default
@@ -82,12 +88,9 @@ given userComponent: UserComponent = UserComponent()
82
88
// Scala 3.5: prints "library-defined"
83
89
```
84
90
85
- To detect such "silent" changes, we recommend compiling under Scala
86
- 3.5 with the ` -source:3.6-migration ` flag:
87
- ``` bash
88
- scalac client.scala -source:3.6-migration
89
- ```
90
- This will issue warnings when the choice of ` given ` has changed:
91
+ Scala 3.5 will automatically issue
92
+ warnings when the choice of ` given ` has changed:
93
+
91
94
``` scala
92
95
-- Warning : client.scala: 11 : 30 ------------------------------------------
93
96
11 |@ main def run = printComponent
@@ -101,7 +104,20 @@ This will issue warnings when the choice of `given` has changed:
101
104
| New choice from Scala 3.6 : the second alternative
102
105
```
103
106
104
- ### Explicit Parameters
107
+
108
+ ### Useful Compiler Options
109
+
110
+ In future releases (Scala 3.6+), automatic warnings related to changes
111
+ in the selection of givens, as described above, will no longer be
112
+ issued by default. However, these warnings can be reactivated using
113
+ the ` -source:3.5 ` option with ` scalac ` .
114
+
115
+ Additionally, combining Scala 3.5 with the ` -source:3.6 ` option can be
116
+ useful to verify that implicit search results will not be ambiguous in
117
+ future versions or to test your application at runtime with the new
118
+ rules in effect.
119
+
120
+ ### Resorting to Explicit Parameters
105
121
106
122
If the pre-3.5 behavior is preferred, you can explicitly pass the
107
123
desired given:
@@ -126,3 +142,51 @@ This will output all parameters explicitly:
126
142
127
143
We are considering adding ` -rewrite ` rules that automatically insert
128
144
explicit parameters when a change in choice is detected.
145
+
146
+
147
+ ## Towards Context Bounds as Givens
148
+
149
+ We are gradually phasing out remaining uses of Scala 2 style
150
+ ` implicit ` s in favor of the ` given ` /` using ` syntax. Scala 3.5 marks
151
+ the first step in transitioning context bounds on type parameters to
152
+ givens, with this transition expected to be completed in the upcoming
153
+ Scala 3.6 release.
154
+
155
+ Currently, context bounds on type parameters still desugar into
156
+ ` implicit ` parameters:
157
+
158
+ ``` scala
159
+ def f [Element : Eq : Ordering ] = summon[Eq [Element ]].toOrdering
160
+ // expands to:
161
+ def f [Element >: Nothing <: Any ](implicit evidence$1 : Eq [Element ],
162
+ implicit evidence$2 : Order [Element ]): Ordering [Element ] =
163
+ evidence$2 .toOrdering
164
+ ```
165
+
166
+ Prior to Scala 3.5, it was possible to pass ` implicit ` arguments
167
+ explicitly for context bounds as if they were regular arguments. In
168
+ Scala 3.5, however, these parameters must be qualified with ` using ` :
169
+
170
+ ``` scala
171
+ val eq : Eq [Int ] = ???
172
+ val ord : Order [Int ] = ???
173
+ f(eq, ord) // ok in Scala < 3.5, error in 3.5
174
+ f(using eq, ord) // ok in Scala 3.5
175
+ ```
176
+
177
+ At this stage, the change does not affect the expansion of functions
178
+ like ` f ` above, which still rely on ` implicit ` parameters. However,
179
+ this is a crucial step towards facilitating the eventual transition to
180
+ ` given ` s for context bounds in Scala 3.6.
181
+
182
+ To assist with the migration to explicit ` using ` clauses, Scala 3.5
183
+ provides an error message and offers automatic rewrites:
184
+
185
+ ``` scala
186
+ -- Error : bounds.scala: 10 : 2 ----------------------------------------------
187
+ 10 | f(eq, ord) // error
188
+ | ^
189
+ | Context bounds will map to context parameters.
190
+ | A `using` clause is needed to pass explicit arguments to them.
191
+ | This code can be rewritten automatically under - rewrite - source 3.4 - migration.
192
+ ```
0 commit comments