Skip to content

Commit

Permalink
Do not use eval for some Validate instances
Browse files Browse the repository at this point in the history
This avoids to call `eval` for a few `Validate` instances in
`RefinedMacro.impl`. This is similar in spirit to #332.

For the `autoRefineV_PosInt` benchmark we get a decrease in compilation
time of ~56% (or ~67% prior to #332):
```
[info] Result "eu.timepit.refined.benchmark.RefineMacroBenchmark.autoRefineV_PosInt":
[info]   0.181 ±(99.9%) 0.001 s/op [Average]
[info]   (min, avg, max) = (0.173, 0.181, 0.234), stdev = 0.006
[info]   CI (99.9%): [0.180, 0.182] (assumes normal distribution)
[info] # Run complete. Total time: 00:08:03
[info] Benchmark                                Mode  Cnt  Score   Error Units
[info] RefineMacroBenchmark.autoRefineV_PosInt  avgt  200  0.181 ± 0.001 s/op
```
  • Loading branch information
fthomas committed Sep 29, 2017
1 parent 3049967 commit fce2027
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ class InferMacro(val c: blackbox.Context) extends MacroUtils {
abort(Resources.invalidInference(weakTypeOf[A].toString, weakTypeOf[B].toString))
}

refTypeObj(rt).unsafeRewrapM(c)(ta)
refTypeInstance(rt).unsafeRewrapM(c)(ta)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ trait MacroUtils {
def tryN[T](n: Int, t: => T): T =
Stream.fill(n)(Try(t)).collectFirst { case Success(r) => r }.getOrElse(t)

protected def refTypeObj[F[_, _]](rt: c.Expr[RefType[F]]): RefType[F] =
protected def refTypeInstance[F[_, _]](rt: c.Expr[RefType[F]]): RefType[F] =
if (rt.tree.tpe =:= weakTypeOf[RefType[Refined]])
RefType[Refined].asInstanceOf[RefType[F]]
else if (rt.tree.tpe =:= weakTypeOf[RefType[@@]])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package eu.timepit.refined
package macros

import eu.timepit.refined.api.{RefType, Validate}
import eu.timepit.refined.char.{Digit, Letter, LowerCase, UpperCase, Whitespace}
import eu.timepit.refined.collection.NonEmpty
import eu.timepit.refined.internal.Resources
import eu.timepit.refined.numeric.{Negative, NonNegative, NonPositive, Positive}
import macrocompat.bundle
import scala.reflect.macros.blackbox

Expand All @@ -20,13 +23,13 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils {
case _ => abort(Resources.refineNonCompileTimeConstant)
}

val validate = eval(v)
val validate = validateInstance(v)
val res = validate.validate(tValue)
if (res.isFailed) {
abort(validate.showResult(tValue, res))
}

refTypeObj(rt).unsafeWrapM(c)(t)
refTypeInstance(rt).unsafeWrapM(c)(t)
}

def implApplyRef[FTP, F[_, _], T, P](t: c.Expr[T])(
Expand All @@ -35,4 +38,56 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils {
v: c.Expr[Validate[T, P]]
): c.Expr[FTP] =
c.Expr(impl(t)(rt, v).tree)

private def validateInstance[T, P](v: c.Expr[Validate[T, P]])(
implicit
T: c.WeakTypeTag[T],
P: c.WeakTypeTag[P]
): Validate[T, P] =
validateInstances
.collectFirst {
case (tpeT, list) if tpeT =:= T.tpe =>
list.collectFirst {
case (tpeP, validate) if tpeP =:= P.tpe =>
validate.asInstanceOf[Validate[T, P]]
}
}
.flatten
.getOrElse(eval(v))

private val validateInstances: List[(Type, List[(Type, Any)])] = {
def instance[T, P](implicit P: c.WeakTypeTag[P], v: Validate[T, P]): (Type, Validate[T, P]) =
P.tpe -> v

List(
weakTypeOf[Int] -> List(
instance[Int, Positive],
instance[Int, NonPositive],
instance[Int, Negative],
instance[Int, NonNegative]
),
weakTypeOf[Long] -> List(
instance[Long, Positive],
instance[Long, NonPositive],
instance[Long, Negative],
instance[Long, NonNegative]
),
weakTypeOf[Double] -> List(
instance[Double, Positive],
instance[Double, NonPositive],
instance[Double, Negative],
instance[Double, NonNegative]
),
weakTypeOf[String] -> List(
instance[String, NonEmpty]
),
weakTypeOf[Char] -> List(
instance[Char, Digit],
instance[Char, Letter],
instance[Char, LowerCase],
instance[Char, UpperCase],
instance[Char, Whitespace]
)
)
}
}

0 comments on commit fce2027

Please sign in to comment.