forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Higher-kinded type variable unification.
Can cause ambiguous implicits, so is under a compiler flag -Yhk-typevar-unification. Fixes scala/bug#10197 Fixes scala/bug#10213 Fixes scala/bug#10238 Fixes scala/bug#10372 Presents an alternative fix to scala/bug#6895.
- Loading branch information
1 parent
e1e8d05
commit d163afb
Showing
23 changed files
with
340 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
hk-typevar-unification.scala:16: error: inferred kinds of the type arguments ([_]Foo[_]) do not conform to the expected kinds of the type parameters (type F). | ||
[_]Foo[_]'s type parameters do not match type F's expected parameters: | ||
type _ (in class Foo) is invariant, but type _ is declared covariant | ||
g(tcFoo) | ||
^ | ||
hk-typevar-unification.scala:16: error: type mismatch; | ||
found : TC[Foo] | ||
required: TC[F] | ||
g(tcFoo) | ||
^ | ||
two errors found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
trait TC[F[_]] | ||
class A | ||
class Foo[_] | ||
|
||
object Test { | ||
|
||
def f[F[_ <: A]](tc: TC[F]): Unit = () | ||
def g[F[+_]] (tc: TC[F]): Unit = () | ||
|
||
val tcFoo: TC[Foo] = new TC[Foo] {} | ||
|
||
// incompatible bounds | ||
f(tcFoo) | ||
|
||
// incompatible variance | ||
g(tcFoo) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import scala.language.higherKinds | ||
|
||
final case class Getter[S, A](get: S => A) | ||
|
||
final case class Wrap[F[_], A](value: F[A]) | ||
|
||
object Wrap { | ||
// Helper to defer specifying second argument to Wrap. | ||
// Basically a type lambda specialized for Wrap. | ||
// Wr[F]#ap[A] =:= Wrap[F, A] | ||
type Wr[F[_]] = { type ap[A] = Wrap[F, A] } | ||
|
||
implicit def unwrapper[F[_], A]: Getter[Wrap[F, A], F[A]] = | ||
Getter(w => w.value) | ||
} | ||
|
||
object Test { | ||
import Wrap._ | ||
|
||
type Foo[A] = List[A] | ||
type Bar[A] = String | ||
|
||
type WrapFoo1[A] = Wrap[Foo, A] | ||
type WrapBar1[A] = Wrap[Bar, A] | ||
|
||
implicitly[Getter[WrapFoo1[Int], Foo[Int]]] | ||
implicitly[Getter[WrapBar1[Int], Bar[Int]]] | ||
|
||
type WrapFoo2[A] = Wr[Foo]#ap[A] | ||
type WrapBar2[A] = Wr[Bar]#ap[A] | ||
|
||
// here's evidence that the new types are the same as the old ones | ||
implicitly[WrapFoo2[Int] =:= WrapFoo1[Int]] | ||
implicitly[WrapBar2[Int] =:= WrapBar1[Int]] | ||
|
||
implicitly[Getter[WrapFoo2[Int], Foo[Int]]] | ||
implicitly[Getter[WrapBar2[Int], Bar[Int]]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import scala.language.higherKinds | ||
|
||
final case class Coproduct[F[_], G[_], A](run: Either[F[A], G[A]]) | ||
|
||
object Coproduct { | ||
|
||
sealed trait Builder { | ||
type Out[_] | ||
} | ||
|
||
sealed trait :++:[F[_], G[_]] extends Builder { | ||
type Out[A] = Coproduct[F, G, A] | ||
} | ||
|
||
sealed trait :+:[F[_], B <: Builder] extends Builder { | ||
type Out[A] = Coproduct[F, B#Out, A] | ||
} | ||
} | ||
|
||
trait Inject[F[_], H[_]] { | ||
def inj[A](fa: F[A]): H[A] | ||
} | ||
|
||
object Inject { | ||
import Coproduct._ | ||
|
||
implicit def reflexiveInject[F[_]]: Inject[F, F] = | ||
new Inject[F, F] { | ||
def inj[A](fa: F[A]): F[A] = fa | ||
} | ||
|
||
implicit def injectLeft[F[_], G[_]]: Inject[F, (F :++: G)#Out] = | ||
new Inject[F, (F :++: G)#Out] { | ||
def inj[A](fa: F[A]): Coproduct[F, G, A] = Coproduct(Left(fa)) | ||
} | ||
|
||
implicit def injectRight[F[_], G[_], H[_]](implicit I: Inject[F, H]): Inject[F, (G :++: H)#Out] = | ||
new Inject[F, (G :++: H)#Out] { | ||
def inj[A](fa: F[A]): Coproduct[G, H , A] = Coproduct(Right(I.inj(fa))) | ||
} | ||
} | ||
|
||
object Test1 { | ||
import Coproduct.{:++:, :+:} | ||
|
||
class Foo[A] | ||
class Bar[A] | ||
class Baz[A] | ||
|
||
implicitly[Inject[Baz, (Foo :+: Bar :++: Baz)#Out]] | ||
|
||
implicitly[Inject[Baz, ({ type Out[A] = Coproduct[Foo, ({ type Out1[a] = Coproduct[Bar, Baz, a] })#Out1, A] })#Out]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
object Test { | ||
|
||
// Data types | ||
|
||
type Id[A] = A | ||
|
||
class MaybeT[F[_], A] | ||
|
||
type Maybe[A] = MaybeT[Id, A] | ||
|
||
type MaybeMaybe[A] = MaybeT[Maybe, A] | ||
|
||
|
||
// Typeclass | ||
|
||
trait Monad[F[_]] | ||
|
||
|
||
// Instances | ||
|
||
implicit val monadId: Monad[Id] = ??? | ||
|
||
implicit def monadMaybeT[F[_]: Monad]: Monad[({ type λ[A] = MaybeT[F, A] })#λ] = ??? | ||
|
||
implicit val monadOption: Monad[Option] = ??? | ||
|
||
|
||
// Implicit search tests | ||
|
||
implicitly[Monad[Id]] | ||
implicitly[Monad[({ type λ[A] = A })#λ]] | ||
implicitly[Monad[Maybe]] | ||
implicitly[Monad[({ type λ[A] = MaybeT[Id, A] })#λ]] | ||
implicitly[Monad[MaybeMaybe]] | ||
implicitly[Monad[({ type λ[A] = MaybeT[Maybe, A] })#λ]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import scala.language.higherKinds | ||
import scala.language.implicitConversions | ||
|
||
object Test { | ||
class Expected[T, Func[_]] | ||
implicit def conv[T, Func[_]](i : Int) : Expected[T, Func] = ??? | ||
type FuncId[T] = T | ||
|
||
object DoesNotCompile { | ||
class Bla { | ||
type Alias[T] = Expected[T, FuncId] | ||
def bla[T](expected : Alias[T]) : Unit = {} | ||
} | ||
(new Bla).bla(2) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-Yhk-typevar-unification | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
trait Foo[F[_]] | ||
trait Bar[F[_], A] | ||
|
||
trait Or[A, B] | ||
|
||
class Test { | ||
implicit def orFoo[A]: Foo[({type L[X] = Or[A, X]})#L] = ??? | ||
implicit def barFoo[F[_]](implicit f: Foo[F]): Foo[({type L[X] = Bar[F, X]})#L] = ??? | ||
|
||
// Now we can define a couple of type aliases: | ||
type StringOr[X] = Or[String, X] | ||
type BarStringOr[X] = Bar[StringOr, X] | ||
|
||
// ok | ||
implicitly[Foo[BarStringOr]] | ||
barFoo[StringOr](null) : Foo[BarStringOr] | ||
barFoo(null) : Foo[BarStringOr] | ||
|
||
// nok | ||
implicitly[Foo[({type L[X] = Bar[StringOr, X]})#L]] | ||
// Let's write the application explicitly, and then | ||
// compile with just this line enabled and -explaintypes. | ||
barFoo(null) : Foo[({type L[X] = Bar[StringOr, X]})#L] | ||
|
||
// Foo[[X]Bar[F,X]] <: Foo[[X]Bar[[X]Or[String,X],X]]? | ||
// Bar[[X]Or[String,X],X] <: Bar[F,X]? | ||
// F[_] <: Or[String,_]? | ||
// false | ||
// false | ||
// false | ||
|
||
// Note that the type annotation above is typechecked as | ||
// Foo[[X]Bar[[X]Or[String,X],X]], ie the type alias `L` | ||
// is eta expanded. | ||
// | ||
// This is done so that it does not escape its defining scope. | ||
// However, one this is done, higher kinded inference | ||
// no longer is able to unify F with `StringOr` (scala/bug#2712) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Some(1) | ||
Some(1) | ||
Some((hi,5)) | ||
Some((hi,5)) | ||
Some(X) | ||
Some(X) | ||
Some(X) | ||
Some(X) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
-Yhk-typevar-unification |
Oops, something went wrong.