Skip to content

Commit a9464d3

Browse files
committed
Split doc about Implicit Conversions
1 parent e30781d commit a9464d3

File tree

2 files changed

+154
-95
lines changed

2 files changed

+154
-95
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
layout: doc-page
3+
title: "Implicit Conversions - More Details"
4+
---
5+
6+
## Implementation
7+
8+
An implicit conversion, or _view_, from type `S` to type `T` is
9+
defined by either:
10+
11+
- An `implicit def` which has type `S => T` or `(=> S) => T`
12+
- An implicit value which has type `ImplicitConverter[S, T]`
13+
14+
The standard library defines an abstract class `ImplicitConverter`:
15+
16+
```scala
17+
abstract class ImplicitConverter[-T, +U] extends Function1[T, U]
18+
```
19+
20+
Function literals are automatically converted to `ImplicitConverter`
21+
values.
22+
23+
Views are applied in three situations:
24+
25+
1. If an expression `e` is of type `T`, and `T` does not conform to
26+
the expression's expected type `pt`. In this case, an implicit `v`
27+
which is applicable to `e` and whose result type conforms to `pt`
28+
is searched. The search proceeds as in the case of implicit
29+
parameters, where the implicit scope is the one of `T => pt`. If
30+
such a view is found, the expression `e` is converted to `v(e)`.
31+
1. In a selection `e.m` with `e` of type `T`, if the selector `m` does
32+
not denote an accessible member of `T`. In this case, a view `v`
33+
which is applicable to `e` and whose result contains an accessible
34+
member named `m` is searched. The search proceeds as in the case of
35+
implicit parameters, where the implicit scope is the one of `T`. If
36+
such a view is found, the selection `e.m` is converted to `v(e).m`.
37+
1. In an application `e.m(args)` with `e` of type `T`, if the selector
38+
`m` denotes some accessible member(s) of `T`, but none of these
39+
members is applicable to the arguments `args`. In this case, a view
40+
`v` which is applicable to `e` and whose result contains a method
41+
`m` which is applicable to `args` is searched. The search proceeds
42+
as in the case of implicit parameters, where the implicit scope is
43+
the one of `T`. If such a view is found, the application
44+
`e.m(args)` is converted to `v(e).m(args)`.
45+
46+
# Differences with Scala 2 implicit conversions
47+
48+
In Scala 2, views whose parameters are passed by-value take precedence
49+
over views whose parameters are passed by-name. This is no longer the
50+
case in Scala 3. A type error reporting the ambiguous conversions will
51+
be emitted in cases where this rule would be applied in Scala 2.
52+
53+
In Scala 2, implicit values of a function type would be considered as
54+
potential views. In Scala 3, these implicit value need to have type
55+
`ImplicitConverter`:
56+
57+
```scala
58+
// Scala 2:
59+
def foo(x: Int)(implicit conv: Int => String): String = x
60+
61+
// Becomes with Scala 3:
62+
def foo(x: Int)(implicit conv: ImplicitConverter[Int, String]): String = x
63+
64+
// Call site is unchanged:
65+
foo(4)(_.toString)
66+
67+
// Scala 2:
68+
implicit val myConverter: Int => String = _.toString
69+
70+
// Becomes with Scala 3:
71+
implicit val myConverter: ImplicitConverter[Int, String] = _.toString
72+
```
73+
74+
Note that implicit conversions are also affected by the [changes to
75+
implicit resolution](implicit-resolution.html) between Scala 2 and
76+
Scala 3.
77+
78+
## Motivation for the changes
79+
80+
The introduction of `ImplicitConverter` in Scala 3 and the decision to
81+
restrict implicit values of this type to be considered as potential
82+
views comes from the desire to remove surprising behavior from the
83+
language:
84+
85+
```scala
86+
implicit val m: Map[Int, String] = Map(1 -> "abc")
87+
88+
val x: String = 1 // scalac: assigns "abc" to x
89+
// Dotty: type error
90+
```
91+
92+
This snippet contains a type error. The right hand side of `val x`
93+
does not conform to type `String`. In Scala 2, the compiler will use
94+
`m` as an implicit conversion from `Int` to `String`, whereas Scala 3
95+
will report a type error, because Map isn't an instance of
96+
`ImplicitConverter`.
97+
98+
## Migration path
99+
100+
Implicit values that are used as views should see their type changed
101+
to `ImplicitConverter`.
102+
103+
For the migration of implicit conversions that are affected by the
104+
changes to implicit resolution, refer to the [Changes in Implicit
105+
Resolution](implicit-resolution.html) for more information.
106+
107+
## Reference
108+
109+
For more information about implicit resolution, see [Changes in
110+
Implicit Resolution](implicit-resolution.html).
111+
Other details are available in
112+
[PR #2065](https://github.com/lampepfl/dotty/pull/2065)
113+
Lines changed: 41 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,59 @@
11
---
22
layout: doc-page
3-
title: "Implicit Conversions - More Details"
3+
title: "Implicit Conversions"
44
---
55

6-
## Implementation
6+
An _implicit conversion_, also called _view_, is a conversion that
7+
is applied by the compiler in several situations:
78

8-
An implicit conversion, or _view_, from type `S` to type `T` is
9-
defined by either:
9+
1. When an expression `e` of type `T` is encountered, but the compiler
10+
needs an expression of type `S`.
11+
1. When an expression `e.m` where `e` has type `T` but `T` defines no
12+
member `m` is encountered.
1013

11-
- An `implicit def` which has type `S => T` or `(=> S) => T`
12-
- An implicit value which has type `ImplicitConverter[S, T]`
14+
In those cases, the compiler looks in the implicit scope for a
15+
conversion that can convert an expression of type `T` to an expression
16+
of type `S` (or to a type that defines a member `m` in the second
17+
case).
1318

14-
The standard library defines an abstract class `ImplicitConverter`:
19+
This conversion can be either:
1520

16-
```scala
17-
abstract class ImplicitConverter[-T, +U] extends Function1[T, U]
18-
```
19-
20-
Function literals are automatically converted to `ImplicitConverter`
21-
values.
22-
23-
Views are applied in three situations:
24-
25-
1. If an expression `e` is of type `T`, and `T` does not conform to
26-
the expression's expected type `pt`. In this case, an implicit `v`
27-
which is applicable to `e` and whose result type conforms to `pt`
28-
is searched. The search proceeds as in the case of implicit
29-
parameters, where the implicit scope is the one of `T => pt`. If
30-
such a view is found, the expression `e` is converted to `v(e)`.
31-
1. In a selection `e.m` with `e` of type `T`, if the selector `m` does
32-
not denote an accessible member of `T`. In this case, a view `v`
33-
which is applicable to `e` and whose result contains an accessible
34-
member named `m` is searched. The search proceeds as in the case of
35-
implicit parameters, where the implicit scope is the one of `T`. If
36-
such a view is found, the selection `e.m` is converted to `v(e).m`.
37-
1. In an application `e.m(args)` with `e` of type `T`, if the selector
38-
`m` denotes some accessible member(s) of `T`, but none of these
39-
members is applicable to the arguments `args`. In this case, a view
40-
`v` which is applicable to `e` and whose result contains a method
41-
`m` which is applicable to `args` is searched. The search proceeds
42-
as in the case of implicit parameters, where the implicit scope is
43-
the one of `T`. If such a view is found, the application
44-
`e.m(args)` is converted to `v(e).m(args)`.
21+
1. An `implicit def` of type `T => S` or `(=> T) => S`
22+
1. An implicit value of type `ImplicitConverter[T, S]`
4523

46-
# Differences with Scala 2 implicit conversions
24+
## Examples
4725

48-
In Scala 2, views whose parameters are passed by-value take precedence
49-
over views whose parameters are passed by-name. This is no longer the
50-
case in Scala 3. A type error reporting the ambiguous conversions will
51-
be emitted in cases where this rule would be applied in Scala 2.
52-
53-
In Scala 2, implicit values of a function type would be considered as
54-
potential views. In Scala 3, these implicit value need to have type
55-
`ImplicitConverter`:
26+
The first example is taken from `scala.Predef`. Thanks to this
27+
implicit conversion, it is possible to pass a `scala.Int` to a Java
28+
method that expects a `java.lang.Integer`
5629

5730
```scala
58-
// Scala 2:
59-
def foo(x: Int)(implicit conv: Int => String): String = x
60-
61-
// Becomes with Scala 3:
62-
def foo(x: Int)(implicit conv: ImplicitConverter[Int, String]): String = x
63-
64-
// Call site is unchanged:
65-
foo(4)(_.toString)
66-
67-
// Scala 2:
68-
implicit val myConverter: Int => String = _.toString
69-
70-
// Becomes with Scala 3:
71-
implicit val myConverter: ImplicitConverter[Int, String] = _.toString
31+
import scala.language.implicitConversions
32+
implicit def int2Integer(x: Int): java.lang.Integer =
33+
x.asInstanceOf[java.lang.Integer]
7234
```
7335

74-
Note that implicit conversions are also affected by the [changes to
75-
implicit resolution](implicit-resolution.html) between Scala 2 and
76-
Scala 3.
77-
78-
## Motivation for the changes
79-
80-
The introduction of `ImplicitConverter` in Scala 3 and the decision to
81-
restrict implicit values of this type to be considered as potential
82-
views comes from the desire to remove surprising behavior from the
83-
language:
36+
The second example shows how to use `ImplicitConverter` to define an
37+
`Ordering` for an arbitrary type, given existing `Ordering`s for other
38+
types:
8439

8540
```scala
86-
implicit val m: Map[Int, String] = Map(1 -> "abc")
87-
88-
val x: String = 1 // scalac: assigns "abc" to x
89-
// Dotty: type error
41+
implicit def ordT[T, S](
42+
implicit conv: ImplicitConverter[T, S],
43+
ordS: Ordering[S]
44+
): Ordering[T] = {
45+
// `ordS` compares values of type `S`, but we can convert from `T` to `S`
46+
(x: T, y: T) => ordS.compare(x, y)
47+
}
48+
49+
class A(val x: Int) // The type for which we want an `Ordering`
50+
51+
// Convert `A` to a type for which an `Ordering` is available:
52+
implicit val AToInt: ImplicitConverter[A, Int] = _.x
53+
54+
implicitly[Ordering[Int]] // Ok, exists in the standard library
55+
implicitly[Ordering[A]] // Ok, will use the implicit conversion from
56+
// `A` to `Int` and the `Ordering` for `Int`.
9057
```
9158

92-
This snippet contains a type error. The right hand side of `val x`
93-
does not conform to type `String`. In Scala 2, the compiler will use
94-
`m` as an implicit conversion from `Int` to `String`, whereas Scala 3
95-
will report a type error, because Map isn't an instance of
96-
`ImplicitConverter`.
97-
98-
## Migration path
99-
100-
Implicit values that are used as views should see their type changed
101-
to `ImplicitConverter`.
102-
103-
For the migration of implicit conversions that are affected by the
104-
changes to implicit resolution, refer to the [Changes in Implicit
105-
Resolution](implicit-resolution.html) for more information.
106-
107-
## Reference
108-
109-
For more information about implicit resolution, see [Changes in
110-
Implicit Resolution](implicit-resolution.html).
111-
Other details are available in
112-
[PR #2065](https://github.com/lampepfl/dotty/pull/2065)
113-
59+
[More details](implicit-conversions-spec.html)

0 commit comments

Comments
 (0)