Skip to content

Macro matching with anonymous variable fails #9570

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

Closed
hmf opened this issue Aug 16, 2020 · 3 comments · Fixed by #9585
Closed

Macro matching with anonymous variable fails #9570

hmf opened this issue Aug 16, 2020 · 3 comments · Fixed by #9585
Assignees

Comments

@hmf
Copy link

hmf commented Aug 16, 2020

Minimized code

In a Macros.scala file we have

import scala.quoted._

object Macros {

  object HList {
    sealed trait HList
    case class HCons[+HD, TL <: HList](hd: HD, tl: TL) extends HList
    case object HNil extends HList

    private def sizeImpl(e: Expr[HList], n:Int)(using qctx:QuoteContext): Expr[Int] = {
      import qctx.tasty._
      e match {
        case '{HCons(_,$t)} =>
        //case '{HCons($a,$t)} =>
        //case '{HCons(($a,$b),$t)} =>
          sizeImpl(t,n+1)
        case '{HNil} => Expr(n)
      }
    }

    inline def size(inline expr: HList ): Int = {
      ${sizeImpl('expr,0)}
    }

  }
}

In a Main.scala file we have

object Main {

  def main(args: Array[String]): Unit = {
    import HList._

    val hl0n = size( HCons(("1",1), HCons(("2",2), HCons(("3",3),HNil))) )
    println(s"size(?) = $hl0n")
  }
}

Output

[error] -- Error: /IdeaProjects/snol/tutorial/src/ad/Main.scala:130:19 --------
[error] 130 |    val hl0n = size( HCons(("1",2), HCons(("2",2), HCons(("3",3),HNil))) )
[error]     |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error]     |      Exception occurred while executing macro expansion.
[error]     |      scala.MatchError: '{ ... } (of class scala.internal.quoted.Expr)
[error]     |
[error]     | This location contains code that was inlined from Main.scala:130
[error] one error found

Expectation

I expected a correct match. If we use:

        case '{HCons($a,$t)} =>

or

        case '{HCons(($a,$b),$t)} =>

matching works correctly.

Tested on 0.26.0-RC1

@nicolasstucki
Copy link
Contributor

Awkwardly the behavior is correct. The pattern case '{HCons(_,$t)} will never match because _ is never a valid term.
The correct way to write this wildcard pattern is

case '{HCons($_,$t)} =>
// or
case '{HCons(${_},$t)} =>

where _ is a pattern equivalent to a in $a where we do not name the a.

We should reject the _ in pattern '{HCons(_,$t)} as it is neve useful. We can also suggest the user to write $_ instead.

@nicolasstucki
Copy link
Contributor

Actually case '{HCons(_,$t)} is equivalent to case '{x => HCons(x,$t)}. Therefore it could match such a lambda. We can warn and expect the users to write the explicit lambda or the $_ instead.

nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Aug 19, 2020
@nicolasstucki nicolasstucki linked a pull request Aug 19, 2020 that will close this issue
@liufengyun
Copy link
Contributor

@nicolasstucki : Great diagnosis 👍 It's easy to have the wrong intuition when working with quoted patterns.

liufengyun added a commit that referenced this issue Aug 19, 2020
Fix #9570: Warn on use of `_` in quoted pattern
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants