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

Cannot summon Type[T] from Quotes #21696

Open
tribbloid opened this issue Oct 2, 2024 · 3 comments
Open

Cannot summon Type[T] from Quotes #21696

tribbloid opened this issue Oct 2, 2024 · 3 comments
Labels
area:metaprogramming:quotes Issues related to quotes and splices better-errors Issues concerned with improving confusing/unhelpful diagnostic messages itype:enhancement

Comments

@tribbloid
Copy link

tribbloid commented Oct 2, 2024

Compiler version

3.5.1

Minimized code

import scala.quoted.{Expr, Quotes, Type}

case class Thing[T](vs: List[String])

class BugDemo {

  object TASTyLowering {

    override protected def deserialize[T](expr: Expr[List[String]])(
        using
        qt: Quotes
    ): Expr[Thing[T]] = {

      val tt = Type.of[T](
        using
        qt
      )

      '{ Thing[T]($expr) }
    }
  }
}

Output

/home/peng/git/dottyspike/src/main/scala/com/tribbloids/spike/dotty/quoted/autolift/spike/BugDemo.scala:16:24
Reference to T within quotes requires a given scala.quoted.Type[T] in scope.


      val tt = Type.of[T](

/home/peng/git/dottyspike/src/main/scala/com/tribbloids/spike/dotty/quoted/autolift/spike/BugDemo.scala:21:16
Reference to T within quotes requires a given scala.quoted.Type[T] in scope.


      '{ Thing[T]($expr) }

the signature of Type.of[T] is:

  /** Return a quoted.Type with the given type */
  @compileTimeOnly("Reference to `scala.quoted.Type.of` was not handled by PickleQuotes")
  given of[T <: AnyKind](using Quotes): Type[T] = ???

so clearly something is wrong here

Expectation

both summoning should succeed

@tribbloid tribbloid added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 2, 2024
@hamzaremmal
Copy link
Member

Hi @tribbloid,

This is actually the correct behavior. Since Scala is subject to the erasure of type parameters, we don't have enough information at runtime to be able to execute val tt = Type.of[T](using qt) or compute anything related to T. To be able to use any information on the type parameter at runtime, you should include a witness (using Type[T]) (or using the following syntax [T: Type]) that describe the type parameter T.

To fix the provided snippet, here is the change to do:

import scala.quoted.{Expr, Quotes, Type}

case class Thing[T](vs: List[String])

def deserialize[T: Type](expr: Expr[List[String]])(using Quotes): Expr[Thing[T]] = {
      '{ Thing[T]($expr) }
}

@hamzaremmal hamzaremmal added area:metaprogramming:quotes Issues related to quotes and splices and removed itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label labels Oct 3, 2024
@hamzaremmal
Copy link
Member

I'm keeping the ticket open to see if we might benefit from a better error reporting

@hamzaremmal hamzaremmal added itype:enhancement better-errors Issues concerned with improving confusing/unhelpful diagnostic messages labels Oct 3, 2024
@tribbloid
Copy link
Author

@hamzaremmal I doubt if it could be that simple, everything defined in the example is indeed compile-time only.

But you are right it is not revealing enough, may I suggest a better example?

comparing the following 2 cases:

(error)

object Demo1 {

  object TASTyLowering {

    def deserialize[T](expr: Expr[List[String]])(
        using
        qt: Quotes,
        tt: Type[T]
    ): Expr[Thing[T]] = {

      '{ Thing[T]($expr) }
    }
  }

  def deserialize[T](expr: Expr[List[String]])(
      using
      Quotes
  ): Expr[Thing[T]] = {

    TASTyLowering.deserialize(expr)
  }
}

(success)

object Demo2 {

  object TASTyLowering {

    def deserialize[T](expr: Expr[List[String]])(
        using
        qt: Quotes,
        tt: Type[T]
    ): Expr[T] = {

      '{ ($expr).asInstanceOf[T] }
    }
  }

  def deserialize[T](expr: Expr[List[String]])(
      using
      Quotes
  ): Expr[T] = {

    TASTyLowering.deserialize(expr)
  }
}

The successful case only differs in return type of the Expr, yet Type can be summoned from Quotes using given Type.of, how did this happen?

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 better-errors Issues concerned with improving confusing/unhelpful diagnostic messages itype:enhancement
Projects
None yet
Development

No branches or pull requests

2 participants