Q:

Using Macro to Make Case Class

Given the following macro (thanks @TravisBrown for this help ):
JetDim.scala
case class JetDim(dimension: Int) {
  require(dimension > 0)
}

object JetDim {
  def validate(dimension: Int): Int = macro JetDimMacro.apply
  def build(dimension: Int): JetDim = JetDim(validate(dimension))
}

JetDimMacro.scala
import reflect.macros. Context

object JetDimMacro {

    sealed trait PosIntCheckResult
    case class LteqZero(x: Int) extends PosIntCheckResult
    case object NotConstant extends PosIntCheckResult

    def apply(c: Context)(dimension: c.Expr[Int]): c.Expr[Int] = {

        import c.universe._ 

        getInt(c)(dimension) match {
            case Right(_)          => reify { dimension.splice }
            case Left(LteqZero(x)) => c.abort(c.enclosingPosition, s"$x must be > 0.") 
            case Left(NotConstant) => reify { dimension.splice }
        }
    }

    def getInt(c: Context)(dimension: c.Expr[Int]): Either[PosIntCheckResult, Int] = {

        import c.universe._ 

        dimension.tree match {
            case Literal(Constant(x: Int)) => if (x > 0) Right(x) else Left(LteqZero(x))
            case _                         => Left(NotConstant)
        }
    }
}

It works from the REPL:
scala> import spire.math. JetDim
import spire.math. JetDim

scala> JetDim.validate(-55)
<console>:9: error: -55 must be > 0. 
              JetDim.validate(-55)
                             ^

scala> JetDim.validate(100)
res1: Int = 100

But, I'd like to build this compile-time check (via the JetDimMacro) into the case class's apply method. 
Attempt 1
case class JetDim(dimension: Int) {
  require(dimension > 0)
}

object JetDim {
  private def validate(dimension: Int): Int = macro JetDimMacro.apply
  def build(dimension: Int): JetDim = JetDim(validate(dimension))
}

But that failed:
scala> import spire.math. JetDim
import spire.math. JetDim

scala> JetDim.build(-55)
java.lang. IllegalArgumentException: requirement failed
  at scala. Predef$.require(Predef.scala:207)
  at spire.math. JetDim.<init>(Jet.scala:21)
  at spire.math. JetDim$.build(Jet.scala:26)
  ... 43 elided

Attempt 2
class JetDim(dim: Int) {
  require(dim > 0)

  def dimension: Int = dim
}

object JetDim {
  private def validate(dimension: Int): Int = macro JetDimMacro.apply
  def apply(dimension: Int): JetDim = {
    validate(dimension)
    new JetDim(dimension)
  }
}

Yet that failed too:
scala> import spire.math. JetDim
import spire.math. JetDim

scala> JetDim(555)
res0: spire.math. JetDim = spire.math. JetDim@4b56f205

scala> JetDim(-555)
java.lang. IllegalArgumentException: requirement failed
  at scala. Predef$.require(Predef.scala:207)
  at spire.math. JetDim.<init>(Jet.scala:21)
  at spire.math. JetDim$.apply(Jet.scala:30)
  ... 43 elided

I thought to modify JetDimMacro#apply to return a JetDim rather than an Int.  However, JetDim lives in the core project, which, from what I see, depends on the macros project (where JetDimMacro lives). 
How can I use this validate method from JetDim's companion object to check for positive int's at compile-time? 

A:

The problem is that by the time we call validate in apply we are no longer dealing with a constant (singleton type).  So, validate gets a non-constant Int. 
As an alternative, you could try using an implicit witness for positive ints, which JetDim then takes as a constructor.  For instance, something like:
package com.example

case class JetDim(n: PositiveInt)

case class PositiveInt(value: Int) {
  require(value > 0)
}

Then, we add an implicit (macro) conversion from Int => PositiveInt that does your check. 
import scala.language.experimental.macros

import scala.reflect.macros.blackbox. Context

object PositiveInt {
  implicit def wrapConstantInt(n: Int): PositiveInt = macro verifyPositiveInt

  def verifyPositiveInt(c: Context)(n: c.Expr[Int]): c.Expr[PositiveInt] = {
    import c.universe._ 

    val tree = n.tree match {
      case Literal(Constant(x: Int)) if x > 0 =>
        q"_root_.com.example. PositiveInt($n)"
      case Literal(Constant(x: Int)) =>
        c.abort(c.enclosingPosition, s"$x <= 0")
      case x =>
        c.abort(c.enclosingPosition, s"cannot verify $x > 0")
    }
    c.Expr(tree)
  }
}

You can then use JetDim(12), which will pass, or JetDim(-12), which will fail (the macro expands the Int to a PositiveInt).