Skip to content

Open code patterns have issues when substituting arguments with a generic/bound type. #15165

Closed
@rmgk

Description

@rmgk

Compiler version

3.1.2 (also tested some 3.1 and 3.2 nightly versions)

Minimized example

Consider we want to transform val bindings into function application, that is, we want to take the following snippet

  valToFun {
    val a: Int = 1
    a + 1
  }

and transform it into (x => x + 1).apply(1) using the valToFun macro below:

import scala.quoted.*

inline def valToFun[T](inline expr: T): T =
  ${ impl('expr) }

def impl[T: Type](expr: Expr[T])(using quotes: Quotes): Expr[T] =
  expr match
    case '{ { val ident = ($a: α); $rest(ident): T } } =>
      '{
        { (y: α) =>
          ${
            val bound   = '{ ${ rest }(y) }
            Expr.betaReduce(bound)
          }
        }.apply($a)
      }

Output

This outputs

undefined: ident.+ # -1: TermRef(TermRef(NoPrefix,val ident),+) at inlining [7:5]

pointing at the a of a + 1

Expectation

Should compile and work just fine, as slight variants also work fine:

It works when adding type ascription's to the use site:

  valToFun {
    val a: Int = 1
    (a: Int) + 1
  }

It also works when replacing the generic type extracted in the quote by an explicit type (i.e., replace α with Int)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions