Question

The following code fails for me:

object Message {
    def parse[T](bsonDoc: BSONDocument): Try[T] = {
        implicit val bsonHandler = Macros.handler[T]
        bsonDoc.seeAsTry[T]
    }
}

Message.parse[messages.ClientHello](data)

The error is:

No apply function found for T
    implicit val bsonHandler = Macros.handler[T]
                                             ^

However, if I hardcode a type (one of my case classes), it's fine:

object Message {
    def parse(bsonDoc: BSONDocument): Try[ClientHello] = {
        implicit val bsonHandler = Macros.handler[ClientHello]
        bsonDoc.seeAsTry[ClientHello]
    }
}

Message.parse(data)

So I presume this is a problem using generics. Incidentally, I have to import messages.ClientHello. If I just use messages.ClientHello I get:

not found: value ClientHello
    implicit val bsonHandler = Macros.handler[messages.ClientHello]
                                             ^

How can I achieve what I'm trying to do, which is to have a single method that will take a BSON document and return an instance of the appropriate case class?

Was it helpful?

Solution

1) Macro applications get expanded immediately when encountered (well, modulo some fine details of type inference that are irrelevant here). This means that when you write handler[T], handler will try to expand with T as a type parameter. This won't lead to anything good, hence the error. To make this work, you need to turn Message.parse into a macro itself.

2) This happens because ReactiveMongo macros are unhygienic. Specifically, https://github.com/ReactiveMongo/ReactiveMongo/blob/v0.10.0/macros/src/main/scala/macros.scala#L142 isn't going to work correctly in situations like yours, because it uses simple name of the class, not a fully qualified name. I think the best way to make the macro work correctly would be using Ident(companion), not Ident(companion.name) - that would ensure that this identifier binds to the companion, not to something in scope having the same name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top