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
in any code that uses them as implicit conversions (code that calls conversions explicitly is not affected). If the import is missing, a feature warning is currently issued, and this will become an error in future versions of Scala 3. The motivation for this restriction is two-fold:
19
19
20
20
- Code with hidden implicit conversions is hard to understand and might have correctness or performance issues that go undetected.
21
-
- If we require explicit user-opt in for implicit conversions, we can significantly improve type inference by propagating expected type information more widely in those parts of the program where there is no opt-in.
21
+
- If we require explicit user opt-in for implicit conversions, we can significantly improve type inference by propagating expected type information more widely in those parts of the program where there is no opt-in.
22
22
23
23
There is one broad use case, however, where implicit conversions are very hard to replace. This is the case where an implicit conversion is used to adapt a method argument to its formal parameter type. An example from the standard library:
24
24
```scala
@@ -132,5 +132,52 @@ type Modifier = into[ModifierClass]
132
132
```
133
133
The into-erasure for function parameters also works in aliased types. So a function defining parameters of `Modifier` type can use them internally as if they were from the underlying `ModifierClass`.
134
134
135
-
## Alternatives
135
+
## Details: Conversion target types
136
136
137
+
The description so far said that conversions are allowed if the target type
138
+
139
+
A conversion target type is one of the following:
140
+
141
+
- a type of the form `into[T]`,
142
+
- a reference `p.C` to a class or trait `C` that is declared with an `into` modifier,
143
+
which can also be followed by type arguments,
144
+
- a type alias of a conversion target type,
145
+
- a match type that reduces to a conversion target type,
146
+
- an annotated type `T @ann` where `T` is a conversion target type,
147
+
- a refined type `T {...}` where `T` is a conversion target type,
148
+
- a union `T | U` if two conversion target types `T` and `U`,
149
+
- an intersection `T & U` if two conversion target types `T` and `U`,
150
+
- an instance of a type parameter that is explicitly instantiated to a conversion target type.
151
+
152
+
153
+
Inferred type parameters do not count as conversion target types. For instance, consider:
154
+
155
+
```scala
156
+
traitToken
157
+
classKeyword(str: String)
158
+
givenConversion[String, Keyword] =KeyWord(_)
159
+
160
+
List[into[Keyword]]("if", "then", "else")
161
+
```
162
+
This type-checks since the target type of the list elements is the type parameter of the `List.apply` method which is explicitly instantiated to `into[Keyword]`. On the other hand, if we continue the example as follows we get an error:
163
+
```scala
164
+
valifKW: into[Keyword] ="if"
165
+
List(ifKW, "then", "else") // error
166
+
```
167
+
Here, the type variable of `List.apply` is not explicitly instantiated, but is inferred to have type `into[Keyword]`. This is not enough to allow
168
+
implicit conversions on the second and third arguments.
169
+
170
+
Subclasses of `into` classes or traits do not count as conversion target types. For instance, consider:
171
+
172
+
```scala
173
+
into traitT
174
+
classC(x: Int) extendsT
175
+
givenConversion[Int, C] =C(_)
176
+
177
+
deff(x: T) = ()
178
+
defg(x: C) = ()
179
+
f("abc") // ok
180
+
g("abc") // error
181
+
```
182
+
The call `f("abc")` type-checks since `f`'s parameter type `T` is `into`.
183
+
But the call `g("abc")` does not type-check since `g`'s parameter type `C` is not `into`. It does not matter that `C` extends a trait `T` that is `into`.
0 commit comments