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

Quoted matching on imported method causes tuple class-cast exception #8745

Closed
deusaquilus opened this issue Apr 19, 2020 · 4 comments
Closed

Comments

@deusaquilus
Copy link
Contributor

Minimized code

Let's say I have a trait with a method extended by a companion:

object Companion extends Trait
trait Trait {
  def fun(first: String): String = "anything"
}

Then I try to match this code in a macro:

tree.unseal.underlyingArgument.seal match {
    case vv @ '{ ($s: Trait).fun($arg) } => arg
}

When invoking the macro with the Companion as an import:

import Companion._
mac(fun("blah"))

The following compiler error occurs:

Exception occurred while executing macro expansion.
java.lang.ClassCastException: scala.Tuple1 cannot be cast to scala.Tuple2
    at companionbug.Macro$.macImpl(Macro.scala:16)

Expectation

The code should compile and the match should work.

Code Sample

Full code sample can be found here:
https://github.com/deusaquilus/companion_bug

@deusaquilus
Copy link
Contributor Author

I would like to add that this issue is very relevant to Quill because for things like query schemas, the following pattern is typically used:

import QuotationContext._
quote {
  querySchema[Table]("tableName", /*... */)
}

In this case, querySchema is actually QuotationContext.querySchema. Every single method in the Quotation DSL uses this pattern.

@deusaquilus
Copy link
Contributor Author

It is interesting to note that this problem only occurs when importing from a companion. Instantiating the trait directly and then importing the methods, it will work:

val inst = new Trait {}
import inst._
mac(fun("blah")) // Matching works!

Also, there seems to be a curious workaround. If you write the companion object into a val and then import from the val, this problem does not occur:

val comp = Companion
import comp._
mac(fun("blah"))

This is very odd but will at least let me make progress for now. Definitely won't suffice for Quill users though.

@nicolasstucki @liufengyun FYI, this is the only blocking issue I have at the moment, I've got a decent workaround for everything else.

nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Apr 22, 2020
@deusaquilus
Copy link
Contributor Author

I was curious to see what happens if you use Companion.type directly. So this:

object Companion {
  def fun(first: String): String = "anything"
}

Matching against this:

case vv @ '{ ($s: Companion.type).fun($arg) } => 

using this:

import Companion._
mac(fun("blah"))

This also causes the same:

java.lang.ClassCastException: scala.Tuple1 cannot be cast to scala.Tuple2

@nicolasstucki
Copy link
Contributor

nicolasstucki commented Apr 22, 2020

We were ignoring the thee prefix when the scrutinee did not mention it explicitly in the tree. I will add a regression test for that one.

@nicolasstucki nicolasstucki added this to the 0.24.0-RC1 milestone Apr 22, 2020
nicolasstucki added a commit that referenced this issue Apr 23, 2020
Fix #8745: Match Ident prefixes to find potential holes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants