Skip to content

Discarding part of .unsealed Expr inside .seal breaks TreeUnpickler #6679

Closed
@fhackett

Description

@fhackett
import quoted._
import tasty._

def makeMatch[A,T](a : Type[A], b : Type[T], head : Expr[_], parts : List[(Expr[_],Expr[_])])(implicit reflection : Reflection) : Expr[T] = {
  implicit val e1 = a
  implicit val e2 = b
  import reflection._
  Match(
    head.asInstanceOf[Expr[A]].unseal,
    parts.map({
      case (l,r) => {
        val sacrifice = '{
          ${ head.asInstanceOf[Expr[A]] } match {
            case x if x == ${ l.asInstanceOf[Expr[A]] } => ${ r.asInstanceOf[Expr[T]] }
          }
        }
        sacrifice.unseal match {
          case IsInlined(inl) => inl.body match {
            case IsMatch(m) => m.cases.head
          }
        }
      }
    })).seal.cast[T]
}

def mm(implicit reflection : Reflection) =
  makeMatch[Int,Boolean]('[Int],'[Boolean],'{42},List('{1}->'{true},'{2}->'{false},'{42}->'{true}))

inline def f = ${ mm }

Trying to call f will crash with a ClassCastException, suggesting that this code is causing some kind of misalignment wrt. holes in the tasty. It seems something is assuming some overly strong invariants about where the parts of a .unsealed expression can end up.

Removing the call to .unseal will remove the error, no matter how the result of that call is (or isn't) used.

scala> f
1 |f
  |^
  |An exception occurred while executing macro expansion
  |class scala.internal.quoted.TaggedType cannot be cast to class scala.quoted.Expr

Advice?

The root of the issue is that I can't generate match expressions with a variable number of cases using quotes, so I had to resort to tasty.Reflection. tasty.Reflection on the other hand doesn't seem to be able to generate the appropriate name bindings/patterns, so I have to "steal" the appropriate AST fragments from a quoted Expr.

Is there a better way to do this? Any workaround suggestions?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions