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

Unable to invoke a varargs method with non-one number of arguments in reflect api #18784

Closed
rayrobdod opened this issue Oct 29, 2023 · 1 comment · Fixed by #18792
Closed
Assignees
Labels

Comments

@rayrobdod
Copy link

Compiler version

3.3.1, 3.4.0-RC1-bin-20231027-c0eae68-NIGHTLY

Minimized code

import scala.quoted.*

object Macro {
  def template(args:List[Expr[Int]])(using Quotes):Expr[List[Int]] = {
    import quotes.reflect.*
    val listObjectTerm = '{ List }.asTerm
    Apply(
      TypeApply(
        Select.unique(listObjectTerm, "apply"),
        List(TypeTree.of[Int])
      ),
      args.map(_.asTerm)
    ).asExprOf[List[Int]]
  }

  inline def apply_0 = ${Macro.impl_0}
  def impl_0(using quotes:Quotes):Expr[List[Int]] =
    Macro.template(List.empty)

  inline def apply_1 = ${Macro.impl_1}
  def impl_1(using quotes:Quotes):Expr[List[Int]] =
    Macro.template(List(Expr(1)))

  inline def apply_2 = ${Macro.impl_2}
  def impl_2(using quotes:Quotes):Expr[List[Int]] =
    Macro.template(List(Expr(1), Expr(2)))

  inline def repeated = ${Macro.repeatedImpl}
  def repeatedImpl(using Quotes):Expr[List[Int]] = {
    import quotes.reflect.*
    val args = List(Expr(1), Expr(2))
    val listObjectTerm = '{ List }.asTerm
    Apply(
      TypeApply(
        Select.unique(listObjectTerm, "apply"),
        List(TypeTree.of[Int])
      ),
      List(Repeated(args.map(_.asTerm), TypeTree.of[Int]))
    ).asExprOf[List[Int]]
  }
}
Macro.apply_0
Macro.apply_1
Macro.apply_2
Macro.repeated

Output

scala> Macro.apply_0
-- Error: ----------------------------------------------------------------------
1 |Macro.apply_0
  |^^^^^^^^^^^^^
  |wrong number of arguments at pickler for (elems: Int*): List[Int]: (elems: Int*): List[Int], expected: 1, found: 0
1 error found

scala> Macro.apply_1
val res0: List[Int] = List(1)

scala> Macro.apply_2
-- Error: ----------------------------------------------------------------------
1 |Macro.apply_2
  |^^^^^^^^^^^^^
  |wrong number of arguments at pickler for (elems: Int*): List[Int]: (elems: Int*): List[Int], expected: 1, found: 2
1 error found

scala> Macro.repeated
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |Macro.repeated
  |^^^^^^^^^^^^^^
  |Found:    Seq[Int]
  |Required: Int
  |
  | longer explanation available when compiling with `-explain`
1 error found

Expectation

The three apply_x calls should all succeed, producing List(), List(1) and List(1, 2) respectively

Alternatively, the three apply_x call should all be compile errors, and the repeated call should succeed, producing List(1, 2)

@rayrobdod rayrobdod added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 29, 2023
@nicolasstucki nicolasstucki added area:metaprogramming:reflection Issues related to the quotes reflection API and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 30, 2023
@nicolasstucki nicolasstucki self-assigned this Oct 30, 2023
@nicolasstucki
Copy link
Contributor

This is a bug in the user code. It is not an obvious one. We will need to add documentation to the Repeated explaining this.

The Repeated needs to have a type ascription <repeated>[T] which can be written as follows.

-  Repeated(args.map(_.asTerm), TypeTree.of[Int])
+ Typed(
+   Repeated(args.map(_.asTerm), TypeTree.of[Int]),
+   Inferred(defn.RepeatedParamClass.typeRef.appliedTo(TypeRepr.of[Int]))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants