Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion kyo-actor/shared/src/main/scala/kyo/Actor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,6 @@ object Actor:
Scope.run, // Close used resources
Fiber.init // Start the actor's processing loop in an async context
)
_ <- Scope.ensure(mailbox.close) // Registers a finalizer in the outer scope to provide the actor hierarchy behavior
yield new Actor[E, A, B](_subject, _consumer):
def close(using Frame) = mailbox.close
end Actor
4 changes: 2 additions & 2 deletions kyo-data/shared/src/main/scala/kyo/ConcreteTag.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package kyo

import kyo.Maybe
import kyo.internal.SafeClassTagMacro
import kyo.internal.ConcreteTagMacro
import scala.quoted.*

/** An alternative to ClassTag that supports union and intersection types.
Expand Down Expand Up @@ -42,7 +42,7 @@ object ConcreteTag:
case object AnyValTag extends Element
case object NothingTag extends Element

inline given apply[A]: ConcreteTag[A] = ${ SafeClassTagMacro.derive[A] }
inline given apply[A]: ConcreteTag[A] = ${ ConcreteTagMacro.derive[A] }

extension [A](self: ConcreteTag[A])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import kyo.ConcreteTag
import kyo.ConcreteTag.*
import scala.quoted.*

private[kyo] object SafeClassTagMacro:
private[kyo] object ConcreteTagMacro:

def derive[A: Type](using Quotes): Expr[ConcreteTag[A]] =
import quotes.reflect.*
Expand Down Expand Up @@ -55,43 +55,48 @@ private[kyo] object SafeClassTagMacro:
end create

def createSingle(tpe: TypeRepr): Expr[ConcreteTag[Any]] =
checkType(tpe)
tpe match
case ConstantType(const) =>
val value =
const.value match
case x: Int => Expr(x)
case x: Long => Expr(x)
case x: Float => Expr(x)
case x: Double => Expr(x)
case x: Boolean => Expr(x)
case x: Char => Expr(x)
case x: String => Expr(x)
case x => report.errorAndAbort(s"Unsupported literal type: $x")
'{ LiteralTag($value) }
Implicits.search(TypeRepr.of[[A] =>> ConcreteTag[A]].appliedTo(tpe)) match
case result: ImplicitSearchSuccess =>
val tagExpr: Expr[Any] = result.tree.asExpr
'{ $tagExpr.asInstanceOf[ConcreteTag[Any]] }
case _ =>
tpe.asType match
case '[Nothing] => '{ NothingTag }
case '[Unit] => '{ UnitTag }
case '[Int] => '{ IntTag }
case '[Long] => '{ LongTag }
case '[Double] => '{ DoubleTag }
case '[Float] => '{ FloatTag }
case '[Byte] => '{ ByteTag }
case '[Short] => '{ ShortTag }
case '[Char] => '{ CharTag }
case '[Boolean] => '{ BooleanTag }
case _ if tpe =:= TypeRepr.of[AnyVal] => '{ AnyValTag }
case '[t] =>
val classOfSym = Symbol.requiredMethod("scala.Predef.classOf")
val classOfExpr = Select(Ref(Symbol.requiredModule("scala.Predef")), classOfSym)
.appliedToType(TypeRepr.of[t])
val expr = classOfExpr.asExprOf[Any]
'{ $expr.asInstanceOf[ConcreteTag[Any]] }
end match
checkType(tpe)
tpe match
case ConstantType(const) =>
val value =
const.value match
case x: Int => Expr(x)
case x: Long => Expr(x)
case x: Float => Expr(x)
case x: Double => Expr(x)
case x: Boolean => Expr(x)
case x: Char => Expr(x)
case x: String => Expr(x)
case x => report.errorAndAbort(s"Unsupported literal type: $x")
'{ LiteralTag($value) }
case _ =>
tpe.asType match
case '[Nothing] => '{ NothingTag }
case '[Unit] => '{ UnitTag }
case '[Int] => '{ IntTag }
case '[Long] => '{ LongTag }
case '[Double] => '{ DoubleTag }
case '[Float] => '{ FloatTag }
case '[Byte] => '{ ByteTag }
case '[Short] => '{ ShortTag }
case '[Char] => '{ CharTag }
case '[Boolean] => '{ BooleanTag }
case _ if tpe =:= TypeRepr.of[AnyVal] => '{ AnyValTag }
case '[t] =>
val classOfSym = Symbol.requiredMethod("scala.Predef.classOf")
val classOfExpr = Select(Ref(Symbol.requiredModule("scala.Predef")), classOfSym)
.appliedToType(TypeRepr.of[t])
val expr = classOfExpr.asExprOf[Any]
'{ $expr.asInstanceOf[ConcreteTag[Any]] }
end match
end createSingle

val result = create(TypeRepr.of[A].dealias)
'{ $result.asInstanceOf[ConcreteTag[A]] }
end derive
end SafeClassTagMacro
end ConcreteTagMacro
20 changes: 18 additions & 2 deletions kyo-data/shared/src/test/scala/kyo/ConcreteTagTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package kyo

case class CustomInt(value: Int) extends AnyVal

class SafeClassTagTest extends Test:
class ConcreteTagTest extends Test:

trait Animal
trait Mammal extends Animal
Expand Down Expand Up @@ -794,6 +794,22 @@ class SafeClassTagTest extends Test:
assert(complexTag.accepts("hello"))
assert(!complexTag.accepts(true))
}

"deriving" - {
"union" in {
def union[A: ConcreteTag, B: ConcreteTag]: ConcreteTag[A | B] =
summon[ConcreteTag[A | B]]

assert(union[Int, Boolean] == (ConcreteTag[Int] | ConcreteTag[Boolean]))
}

"intersection" in {
def intersection[A: ConcreteTag, B: ConcreteTag]: ConcreteTag[A & B] =
summon[ConcreteTag[A & B]]

assert(intersection[Int, Boolean] == (ConcreteTag[Int] & ConcreteTag[Boolean]))
}
}
}

end SafeClassTagTest
end ConcreteTagTest