Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active May 30, 2021 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/cd2c3c61425fdbe5a821c5859d79f328 to your computer and use it in GitHub Desktop.
Save xuwei-k/cd2c3c61425fdbe5a821c5859d79f328 to your computer and use it in GitHub Desktop.
scalaVersion := "3.0.0"
package example
import scala.quoted.*
trait Close[A] {
def close(a: A): Unit
}
object Close {
implicit inline def instance[A]: Close[A] =
${ impl[A] }
def impl[A: Type](using Quotes): Expr[Close[A]] = {
import quotes.reflect.*
val method = TypeRepr.of[A].typeSymbol.declaredMethods.filter(_.name == "close") match {
case List(m) =>
m
case Nil =>
report.throwError("not found `close` method")
case values =>
report.throwError("found multiple `close` method")
}
'{
new Close[A] {
override def close(a: A): Unit = {
${Apply(Select(('a).asTerm, method), Nil).asExpr}
}
}
}
}
}
package example
import scala.compiletime.testing.typeCheckErrors
import scala.compiletime.testing.ErrorKind
object Test {
def main(args: Array[String]): Unit = {
summon[Close[A1]].close(new A1())
summon[Close[scala.io.Source]]
summon[Close[java.io.InputStream]]
val List(error1) = typeCheckErrors("summon[Close[A2]]")
assert(error1.message == "not found `close` method")
assert(error1.lineContent == "summon[Close[A2]]")
assert(error1.kind == ErrorKind.Typer)
val List(error2) = typeCheckErrors("summon[Close[A3]]")
assert(error2.message == "found multiple `close` method")
assert(error2.lineContent == "summon[Close[A3]]")
assert(error2.kind == ErrorKind.Typer)
}
}
package example
class A1 {
def close(): Unit = println("close")
}
class A2
trait A3 {
def close(): Unit
def close(a: Int): Unit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment