Skip to content

Commit d8033bc

Browse files
authored
Add section about unreducible application of higher-kinded types to wildcard types
1 parent 19ed993 commit d8033bc

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

docs/cross-build.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,70 @@ implicit val locationWrites: Writes[Location] = (
5252
)(location => (location.lat, location.long)) // Compiles with both Scala 2 and Scala 3
5353
~~~
5454

55+
### Unreducible application of higher-kinded type to wildcard arguments
56+
57+
This warning happens when you apply the “wildcard” type to a higher-kinded type.
58+
59+
Consider the following example:
60+
61+
~~~ scala
62+
trait Example {
63+
64+
type Foo[A]
65+
66+
def f(foo: Foo[_]): Unit // Warning with Scala 3
67+
68+
def g(foos: Seq[Foo[_]]): Unit // Warning with Scala 3
69+
70+
}
71+
~~~
72+
73+
It compiles with Scala 2, but Scala 3 produces the following warnings:
74+
75+
~~~
76+
[warn] -- Migration Warning:
77+
[warn] 132 | def f(foo: Foo[_]): Unit
78+
[warn] | ^^^^^^
79+
[warn] |unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
80+
[warn] -- Migration Warning:
81+
[warn] 134 | def g(foos: Seq[Foo[_]]): Unit
82+
[warn] | ^^^^^^
83+
[warn] |unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
84+
[warn] two warnings found
85+
~~~
86+
87+
Two solutions can be considered for cross-compiling.
88+
89+
In the case of the function `f`, we can change its signature to take a type parameter:
90+
91+
~~~ scala
92+
def f[A](foo: Foo[A]): Unit // Compiles with both Scala 2 and Scala 3
93+
~~~
94+
95+
The second function, `g`, requires more work. We want to accept collections containing
96+
values of type `Foo[A]` with possibly different types for the parameter `A`. To achieve
97+
this, we create a wrapper type that models the type parameter as a type member instead:
98+
99+
~~~ scala
100+
// Wrapper type
101+
trait SomeFoo {
102+
type T
103+
def value: Foo[T]
104+
}
105+
106+
// Construct a value of type `SomeFoo`
107+
def SomeFoo[A](foo: Foo[A]): SomeFoo =
108+
new SomeFoo {
109+
type T = A
110+
def value = foo
111+
}
112+
113+
def g(foos: Seq[SomeFoo]): Unit // Compiles with both Scala 2 and Scala 3
114+
~~~
115+
116+
Users will have to explicitly wrap their `Foo` values into `SomeFoo` by calling the
117+
corresponding constructor.
118+
55119
### Other incompatibilities
56120

57121
[Contributors Welcome!](CONTRIBUTING.md)

0 commit comments

Comments
 (0)