From 8850124336ebea5cb92d4af399c7597acdb1d3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Fromentin?= <42907886+Iltotore@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:06:28 +0200 Subject: [PATCH] feat: Allow both raw and refined types in RefinedTypeOps#apply (#261) --- .../github/iltotore/iron/RefinedTypeOps.scala | 11 +++++----- .../github/iltotore/iron/macros/package.scala | 20 ++++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/main/src/io/github/iltotore/iron/RefinedTypeOps.scala b/main/src/io/github/iltotore/iron/RefinedTypeOps.scala index c34f1338..4004981d 100644 --- a/main/src/io/github/iltotore/iron/RefinedTypeOps.scala +++ b/main/src/io/github/iltotore/iron/RefinedTypeOps.scala @@ -24,12 +24,13 @@ trait RefinedTypeOps[A, C, T](using private val _rtc: RuntimeConstraint[A, C]): * Implicitly refine at compile-time the given value. * * @param value the value to refine. - * @tparam A the refined type. - * @tparam C the constraint applied to the type. - * @return the given value typed as [[IronType]] * @note This method ensures that the value satisfies the constraint. If it doesn't or isn't evaluable at compile-time, the compilation is aborted. */ - inline def apply(value: A :| C): T = value.asInstanceOf[T] + inline def apply[A1 <: A](inline value: A1)(using inline constraint: Constraint[A, C]): T = + inline if macros.isIronType[A1, C] then value.asInstanceOf[T] + else + macros.assertCondition(value, constraint.test(value), constraint.message) + value.asInstanceOf[T] /** * Refine the given value, assuming the constraint holds. @@ -176,4 +177,4 @@ object RefinedTypeOps: * //FinalType =/= IronType * }}} */ - type FinalType = T + type FinalType = T \ No newline at end of file diff --git a/main/src/io/github/iltotore/iron/macros/package.scala b/main/src/io/github/iltotore/iron/macros/package.scala index 2ef8d5ba..61a797e0 100644 --- a/main/src/io/github/iltotore/iron/macros/package.scala +++ b/main/src/io/github/iltotore/iron/macros/package.scala @@ -3,6 +3,8 @@ package io.github.iltotore.iron.macros import io.github.iltotore.iron.internal.{IronConfig, colorized} import scala.Console.{MAGENTA, RESET} import scala.quoted.* +import io.github.iltotore.iron.IronType +import io.github.iltotore.iron.Implication /** * Asserts at compile time if the given condition is true. @@ -66,4 +68,20 @@ def compileTimeError(msg: String)(using Quotes): Nothing = s"""|-- Constraint Error -------------------------------------------------------- |$msg |----------------------------------------------------------------------------""".stripMargin - ) \ No newline at end of file + ) + +inline def isIronType[T, C]: Boolean = ${isIronTypeImpl[T, C]} +def isIronTypeImpl[T : Type, C : Type](using Quotes): Expr[Boolean] = + import quotes.reflect.* + + val ironType = TypeRepr.of[IronType] + val implicationType = TypeRepr.of[Implication] + val targetConstraintType = TypeRepr.of[C] + + TypeRepr.of[T] match + case AppliedType(tpe, List(baseType, constraintType)) if tpe =:= ironType => + Implicits.search(implicationType.appliedTo(List(constraintType, targetConstraintType))) match + case _: ImplicitSearchSuccess => Expr(true) + case _: ImplicitSearchFailure => Expr(false) + + case _ => Expr(false)