Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unneeded use of a binding fixes tuple-matching macro that should work without it #15971

Closed
deusaquilus opened this issue Sep 5, 2022 · 1 comment · Fixed by #16257
Closed
Assignees
Labels
area:metaprogramming:quotes Issues related to quotes and splices itype:bug
Milestone

Comments

@deusaquilus
Copy link
Contributor

deusaquilus commented Sep 5, 2022

Compiler version

3.2.0 (also 3.1.3)

Minimized code

Let's say we write a macro that takes apart a tuple into h *: t and puts this into a specialized class HeadTail in order to make it easier to match.

trait HeadTail
object HeadTail:
  case class Pair[H, T <: Tuple](h: H, t: T) extends HeadTail
  object Nil extends HeadTail

object MatchHeadTail {
  transparent inline def apply[A <: Tuple](inline tup: A): HeadTail = ${ applyImpl('tup) }
  def applyImpl[A <: Tuple](tup: Expr[A])(using q: Quotes, tpe: Type[A]): Expr[HeadTail] = {
    import quotes.reflect._
    tpe match
      case '[EmptyTuple] =>
        '{ HeadTail.Nil }
      case '[h *: t] =>
        '{ HeadTail.Pair[h, t]($tup.productElement(0).asInstanceOf[h], $tup.drop(1).asInstanceOf[t]) }
  }
}

Then we attempt to use it like so:

object HeadTailUse {

  inline def concat[T <: Tuple](inline args: T): String =
    inline MatchHeadTail(args) match
      case HeadTail.Nil =>
        ""
      case HeadTail.Pair(head, tail): HeadTail.Pair[h, t] =>
        head.toString + concat(tail)

  def main(args: Array[String]) = {
    println(concat("Hello" *: 42 *: EmptyTuple))
  }
}

An error will occur:

[error] -- Error: /home/alexi/git/tuple-example/src/main/scala/org/deusaquilus/HeadTailUse.scala:13:18 
[error] 13 |    println(concat("Hello" *: 42 *: EmptyTuple))
[error]    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]    |cannot reduce inline match with
[error]    | scrutinee:  org.deusaquilus.HeadTail.Pair.apply[String, Int *: EmptyTuple.type](
[error]    |  {
[error]    |    val Tuple_this: EmptyTuple.type = EmptyTuple
[error]    |    {
[error]    |      val Tuple_this: (Int *: EmptyTuple.type) = 
[error]    |        (
[error]    |          runtime.Tuples.cons(42, Tuple_this).asInstanceOf[
[error]    |            *:[Int, EmptyTuple.type]
[error]    |          ]
[error]    |        :*:[Int, EmptyTuple.type])
[error]    |      (
[error]    |        runtime.Tuples.cons("Hello", Tuple_this).asInstanceOf[
[error]    |          *:[String, Int *: EmptyTuple.type]
[error]    |        ]
[error]    |      :*:[String, Int *: EmptyTuple.type])
[error]    |    }
[error]    |  }.productElement(0).asInstanceOf[String]
...
[error] one error found

However if we just add a bogus binding e.g. bogusBinding @ then the whole thing will work:

  inline def concat[T <: Tuple](inline args: T): String =
    inline MatchHeadTail(args) match
      case HeadTail.Nil =>
        ""
      case bogusBinding @ HeadTail.Pair(head, tail): HeadTail.Pair[h, t] =>
        head.toString + concat(tail)

// runMain org.deusaquilus.HeadTailUse
// Hello42

Expectation

The same thing should happen in both cases (i.e. the sample should work)

Repo

Code can be found here:
https://github.com/deusaquilus/headtail-macro-fail

@deusaquilus deusaquilus added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 5, 2022
@deusaquilus deusaquilus changed the title Bizzare use of a binding fixes tuple-matching macro Unneeded use of a binding fixes functional tuple-matching macro Sep 5, 2022
@deusaquilus deusaquilus changed the title Unneeded use of a binding fixes functional tuple-matching macro Unneeded use of a binding fixes tuple-matching macro that should work without it Sep 5, 2022
@prolativ
Copy link
Contributor

prolativ commented Sep 5, 2022

The minimization lacks import scala.quoted.* in the first file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:metaprogramming:quotes Issues related to quotes and splices itype:bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants