Skip to content

Commit

Permalink
Deeply look into type structure to find free type variables.
Browse files Browse the repository at this point in the history
  • Loading branch information
tarao committed Nov 28, 2023
1 parent 8008f4e commit 3338bee
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
30 changes: 24 additions & 6 deletions modules/core/src/main/scala/com/github/tarao/record4s/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,31 @@ object Macros {
import quotes.reflect.*
import internal.*

if (TypeRepr.of[T].dealias.typeSymbol.isTypeParam)
errorAndAbort(
Seq(
s"A concrete type expected but type variable ${Type.show[T]} is given.",
"Did you forget to make the method inline?",
).mkString("\n"),
type Acc = List[Type[?]]
def freeTypeVariables[T: Type]: Acc =
traverse[T, Acc](
List.empty,
(acc: Acc, tpe: Type[?]) => {
tpe match {
case '[t] if TypeRepr.of[t].typeSymbol.isTypeParam =>
tpe :: acc
case _ =>
acc
}
},
)

val vs = freeTypeVariables[T]
if (vs.nonEmpty)
vs.head match {
case '[tpe] =>
errorAndAbort(
Seq(
s"A concrete type expected but type variable ${Type.show[tpe]} is given.",
"Did you forget to make the method inline?",
).mkString("\n"),
)
}
else
'{
Concrete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ class TypeErrorSpec extends helper.UnitSpec {
typing.Record.Concat.Aux[R1, R2, RR],
): RR = r1 ++ r2
"""))

trait A

checkErrors(typeCheckErrors("""
def concat[R1 <: %, R2 <: %, RR <: %](r1: R1, r2: R2 & Tag[A])(using
typing.Record.Concat.Aux[R1, R2 & Tag[A], RR],
): RR = r1 ++ r2
"""))
}
}

Expand Down

0 comments on commit 3338bee

Please sign in to comment.