Skip to content
This repository was archived by the owner on Feb 27, 2021. It is now read-only.

Commit 8ab307f

Browse files
committed
Fixed Either/OptionCapture (they just never worked at all) (fixes #25)
1 parent 16889af commit 8ab307f

File tree

6 files changed

+155
-35
lines changed

6 files changed

+155
-35
lines changed

core/src/main/scala/shims/util/capture.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import scala.language.experimental.macros
2121
import scala.annotation.implicitNotFound
2222
import scala.util.Either
2323

24-
@implicitNotFound("unable to find an implicit value of type ${A}")
24+
@implicitNotFound("could not find an implicit value of type ${A}")
2525
final case class Capture[A](value: A) extends AnyVal
2626

2727
object Capture {
@@ -30,7 +30,7 @@ object Capture {
3030
macro CaptureMacros.materializeCapture[A]
3131
}
3232

33-
@implicitNotFound("unable to find an implicit value of type ${A} or ${B}")
33+
@implicitNotFound("could not find an implicit value of type ${A} or ${B}")
3434
final case class EitherCapture[A, B](value: Either[A, B]) extends AnyVal
3535

3636
object EitherCapture {

core/src/main/scala/shims/util/macros.scala

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,43 +27,42 @@ class CaptureMacros(val c: whitebox.Context) extends OpenImplicitMacros {
2727

2828
def materializeCapture[A: WeakTypeTag]: Tree = {
2929
val A = openImplicitTpeParam.getOrElse(weakTypeOf[A])
30-
3130
q"""_root_.shims.util.Capture[$A](${reconstructImplicit(A)})"""
3231
}
3332

3433
def materializeEitherCapture[A: WeakTypeTag, B: WeakTypeTag]: Tree = {
35-
val A = openImplicitTpeParam.getOrElse(weakTypeOf[A])
36-
val B = openImplicitTpeParam.getOrElse(weakTypeOf[B])
37-
3834
val treeAM = try {
39-
Right(q"_root_.scala.util.Left(${reconstructImplicit(A)})")
35+
val A = leftImplicitTpeParam.getOrElse(weakTypeOf[A])
36+
val B = weakTypeOf[B]
37+
Right(q"""_root_.shims.util.EitherCapture[$A, $B](_root_.scala.util.Left[$A, $B](${reconstructImplicit(A)}))""")
4038
} catch {
41-
case e: Exception => Left(e)
39+
// ok it's actually an Error, not an Exception 🤦‍♀️
40+
case t: Throwable => Left(t)
4241
}
4342

4443
val treeBM = try {
45-
Right(q"_root_.scala.util.Right(${reconstructImplicit(B)})")
44+
val A = weakTypeOf[A]
45+
val B = rightImplicitTpeParam.getOrElse(weakTypeOf[B])
46+
Right(q"""_root_.shims.util.EitherCapture[$A, $B](_root_.scala.util.Right[$A, $B](${reconstructImplicit(B)}))""")
4647
} catch {
47-
case e: Exception => Left(e)
48+
// ok it's actually an Error, not an Exception 🤦‍♀️
49+
case t: Throwable => Left(t)
4850
}
4951

50-
val result = treeAM.right.map(Right(_)).right.getOrElse(treeBM).fold(
52+
treeAM.fold(_ => treeBM, Right(_)).fold(
5153
throw _, // it's so great how scalac uses exceptions...
5254
identity)
53-
54-
q"""_root_.shims.util.EitherCapture[$A, $B]($result)"""
5555
}
5656

5757
def materializeOptionCapture[A: WeakTypeTag]: Tree = {
58-
val A = openImplicitTpeParam.getOrElse(weakTypeOf[A])
59-
60-
val result = try {
61-
q"_root_.scala.Some(${reconstructImplicit(A)})"
58+
try {
59+
val A = openImplicitTpeParam.getOrElse(weakTypeOf[A])
60+
q"""_root_.shims.util.OptionCapture[$A](_root_.scala.Some(${reconstructImplicit(A)}))"""
6261
} catch {
63-
case e: Exception => q"_root_.scala.None"
62+
// ok it's actually an Error, not an Exception 🤦‍♀️
63+
case t: Throwable =>
64+
q"""_root_.shims.util.OptionCapture[${weakTypeOf[A]}](_root_.scala.None)"""
6465
}
65-
66-
q"""_root_.shims.util.OptionCapture[$A]($result)"""
6766
}
6867

6968
private def reconstructImplicit(A: Type): Tree = {
@@ -73,16 +72,16 @@ class CaptureMacros(val c: whitebox.Context) extends OpenImplicitMacros {
7372
try {
7473
c.inferImplicitValue(A)
7574
} catch {
76-
case e: Exception => c.abort(c.enclosingPosition, s"Implicit $A not found")
75+
case t: Throwable => c.abort(c.enclosingPosition, s"implicit $A not found")
7776
}
7877
}
7978

8079
if (tree0 == EmptyTree) {
81-
c.abort(c.enclosingPosition, s"Implicit $A not found")
80+
c.abort(c.enclosingPosition, s"implicit $A not found")
8281
}
8382

8483
if (tree0.tpe <:< Synthetic) {
85-
c.abort(c.enclosingPosition, s"Cannot capture subtype of Synthetic")
84+
c.abort(c.enclosingPosition, s"cannot capture subtype of Synthetic")
8685
}
8786

8887
tree0
@@ -109,7 +108,7 @@ private[util] object CaptureMacros {
109108

110109
// simple divergence check
111110
if (vs.exists(tpe <:< _.asInstanceOf[c.universe.Type])) {
112-
c.abort(c.enclosingPosition, s"Implicit $tpe not found")
111+
c.abort(c.enclosingPosition, s"implicit $tpe not found")
113112
} else {
114113
val vs2 = tpe :: vs
115114

@@ -133,17 +132,29 @@ private[shims] trait OpenImplicitMacros {
133132
c.openImplicits.headOption.map(_.pt)
134133

135134
def openImplicitTpeParam: Option[Type] =
136-
openImplicitTpe.map {
135+
openImplicitTpe map {
137136
case TypeRef(_, _, List(tpe)) =>
138137
tpe.map(_.dealias)
138+
139+
case other =>
140+
c.abort(c.enclosingPosition, s"bad materialization: $other")
141+
}
142+
143+
def leftImplicitTpeParam: Option[Type] =
144+
openImplicitTpe map {
145+
case TypeRef(_, _, List(tpe, _)) =>
146+
tpe.map(_.dealias)
147+
139148
case other =>
140-
c.abort(c.enclosingPosition, s"Bad materialization: $other")
149+
c.abort(c.enclosingPosition, s"bad materialization (left): $other")
141150
}
142151

143-
def secondOpenImplicitTpe: Option[Type] =
144-
c.openImplicits match {
145-
case (List(_, second, _ @ _*)) =>
146-
Some(second.pt)
147-
case _ => None
152+
def rightImplicitTpeParam: Option[Type] =
153+
openImplicitTpe map {
154+
case TypeRef(_, _, List(_, tpe)) =>
155+
tpe.map(_.dealias)
156+
157+
case other =>
158+
c.abort(c.enclosingPosition, s"bad materialization (right): $other")
148159
}
149160
}

core/src/test/scala/shims/MonadConversionSpecs.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ object MonadConversionSpecs extends Specification with Discipline {
191191

192192
checkAll("Option", MonadTests[Option].monad[Int, Int, Int])
193193
}
194+
195+
"F[_]" >> {
196+
def foo[F[_]](implicit F: scalaz.Monad[F]) = {
197+
cats.Applicative[F]
198+
cats.Monad[F]
199+
}
200+
201+
ok
202+
}
194203
}
195204
}
196205

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2018 Daniel Spiewak
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package shims.util
18+
19+
import org.specs2.mutable._
20+
21+
object CaptureSpecs extends Specification {
22+
23+
"capture" should {
24+
trait Foo
25+
implicit case object Foo extends Foo
26+
27+
"find implicits" in {
28+
implicitly[Capture[Foo]].value mustEqual implicitly[Foo]
29+
}
30+
}
31+
32+
"either capture" should {
33+
"find left" in {
34+
trait Foo
35+
implicit case object Foo extends Foo
36+
trait Bar
37+
38+
implicitly[EitherCapture[Foo, Bar]].value must beLeft(implicitly[Foo])
39+
}
40+
41+
"find right" in {
42+
trait Foo
43+
trait Bar
44+
implicit case object Bar extends Bar
45+
46+
implicitly[EitherCapture[Foo, Bar]].value must beRight(implicitly[Bar])
47+
}
48+
}
49+
50+
"option capture" should {
51+
"find some" in {
52+
trait Foo
53+
implicit case object Foo extends Foo
54+
55+
implicitly[OptionCapture[Foo]].value must beSome(implicitly[Foo])
56+
}
57+
58+
"find none" in {
59+
trait Foo
60+
61+
implicitly[OptionCapture[Foo]].value must beNone
62+
}
63+
}
64+
}

scratch/src/main/scala/shims/playground.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2018 Daniel Spiewak
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
import shims._
218

319
object ScalazExamples {
Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1+
/*
2+
* Copyright 2018 Daniel Spiewak
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package shims
218

3-
object Test /*{
4-
implicit val capList: cats.Applicative[List] = null
19+
import shims.util.EitherCapture
20+
21+
object Test {
22+
trait Foo
23+
implicit case object Foo extends Foo
24+
trait Bar
525

6-
scalaz.Applicative[List]
7-
}*/
26+
implicitly[EitherCapture[Foo, Bar]]
27+
}

0 commit comments

Comments
 (0)