diff --git a/core/src/main/scala/cats/arrow/FunctionK.scala b/core/src/main/scala/cats/arrow/FunctionK.scala index 2c59e2dbde..201d3e5b00 100644 --- a/core/src/main/scala/cats/arrow/FunctionK.scala +++ b/core/src/main/scala/cats/arrow/FunctionK.scala @@ -3,7 +3,7 @@ package arrow import cats.data.Coproduct -import reflect.macros.blackbox.Context +import cats.macros.MacroCompat trait FunctionK[F[_], G[_]] extends Serializable { self => def apply[A](fa: F[A]): G[A] @@ -37,13 +37,12 @@ object FunctionK { } -object FunctionKMacros { +object FunctionKMacros extends MacroCompat { - def lift[ - F[_]: λ[α[_] ⇒ c.WeakTypeTag[α[_]]], - G[_]: λ[α[_] ⇒ c.WeakTypeTag[α[_]]] - ](c: Context)( - f: c.Expr[F[α] ⇒ G[α]] forSome { type α } + def lift[F[_], G[_]](c: Context)( + f: c.Expr[(F[α] ⇒ G[α]) forSome { type α }] + )( + implicit evF: c.WeakTypeTag[F[_]], evG: c.WeakTypeTag[G[_]] ): c.Expr[FunctionK[F, G]] = { import c.universe._ @@ -54,7 +53,7 @@ object FunctionKMacros { def punchHole(tpe: Type): Tree = tpe match { case PolyType(undet :: Nil, underlying: TypeRef) ⇒ - val α = TypeName("α") + val α = compatNewTypeName(c, "α") def rebind(typeRef: TypeRef): Tree = if (typeRef.sym == undet) tq"$α" else { @@ -82,8 +81,8 @@ object FunctionKMacros { s"type parameter $param must not be supplied when lifting function $trans to FunctionK") } - val F = punchHole(weakTypeTag[F[_]].tpe) - val G = punchHole(weakTypeTag[G[_]].tpe) + val F = punchHole(evF.tpe) + val G = punchHole(evG.tpe) q""" new FunctionK[$F, $G] { diff --git a/macros/src/main/scala/cats/macros/compat.scala b/macros/src/main/scala/cats/macros/compat.scala new file mode 100644 index 0000000000..54f4ddd8fc --- /dev/null +++ b/macros/src/main/scala/cats/macros/compat.scala @@ -0,0 +1,15 @@ +package cats +package macros + +/** Macro compatibility. + * + * Used only to push deprecation errors in core off into + * the macros project, as warnings. + */ +private[cats] class MacroCompat { + + type Context = reflect.macros.Context + def compatNewTypeName(c: Context, name: String): c.TypeName = + c.universe.newTypeName(name) + +} diff --git a/tests/src/test/scala/cats/tests/FunctionKTests.scala b/tests/src/test/scala/cats/tests/FunctionKTests.scala index ac33338ab9..b6edee8f06 100644 --- a/tests/src/test/scala/cats/tests/FunctionKTests.scala +++ b/tests/src/test/scala/cats/tests/FunctionKTests.scala @@ -69,24 +69,24 @@ class FunctionKTests extends CatsSuite { test("lift simple unary") { def optionToList[A](option: Option[A]): List[A] = option.toList - val fOptionToList = FunctionK.lift(optionToList) + val fOptionToList = FunctionK.lift(optionToList _) forAll { (a: Option[Int]) => fOptionToList(a) should === (optionToList(a)) } - val fO2I: FunctionK[Option, Iterable] = FunctionK.lift(Option.option2Iterable) + val fO2I: FunctionK[Option, Iterable] = FunctionK.lift(Option.option2Iterable _) forAll { (a: Option[String]) => fO2I(a).toList should === (Option.option2Iterable(a).toList) } - val fNelFromListUnsafe = FunctionK.lift(NonEmptyList.fromListUnsafe) + val fNelFromListUnsafe = FunctionK.lift(NonEmptyList.fromListUnsafe _) forAll { (a: NonEmptyList[Int]) => fNelFromListUnsafe(a.toList) should === (NonEmptyList.fromListUnsafe(a.toList)) } } test("lift compound unary") { - val fNelFromList = FunctionK.lift[List, λ[α ⇒ Option[NonEmptyList[α]]]](NonEmptyList.fromList) + val fNelFromList = FunctionK.lift[List, λ[α ⇒ Option[NonEmptyList[α]]]](NonEmptyList.fromList _) forAll { (a: List[String]) => fNelFromList(a) should === (NonEmptyList.fromList(a)) }