22layout : blog-detail
33post-type : blog
44by : Oliver Bračevac, EPFL
5- title : " Changes to Givens Prioritization in Scala 3.5"
5+ title : " Changes to Givens in Scala 3.5"
66---
77
8- ## Motivation
8+ ## New Prioritization of Givens
99
1010Starting with Scala 3.5, the prioritization of givens has been
1111improved to better handle inheritance triangles, resulting in enhanced
1212typeclass support.
1313
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:
1516``` scala
1617trait Functor [F [_]]:
1718 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
4041
4142In Scala 3.5, the compiler now selects the instance with the _ most
4243general_ 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] ` .
4445
4546Inheritance triangles like this are common in practice, and the
4647prioritization change in Scala 3.5 makes working with them more
4748intuitive and straightforward.
4849
49- ## Tips for Migrating to 3.5
50+ ### Community Impact
5051
5152Based on our evaluation using the [ open community
5253build] ( https://github.com/VirtusLab/community-build3 ) , the impact of
5354this change on existing Scala 3 projects has been minimal. However,
5455there 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+
5662
5763In some cases, the new prioritization might silently select the wrong
5864` given ` . For example, consider a library that provides a default
@@ -82,12 +88,9 @@ given userComponent: UserComponent = UserComponent()
8288// Scala 3.5: prints "library-defined"
8389```
8490
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+
9194``` scala
9295-- Warning : client.scala: 11 : 30 ------------------------------------------
939611 |@ main def run = printComponent
@@ -101,7 +104,20 @@ This will issue warnings when the choice of `given` has changed:
101104 | New choice from Scala 3.6 : the second alternative
102105```
103106
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
105121
106122If the pre-3.5 behavior is preferred, you can explicitly pass the
107123desired given:
@@ -126,3 +142,51 @@ This will output all parameters explicitly:
126142
127143We are considering adding ` -rewrite ` rules that automatically insert
128144explicit 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