Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I locate where an implicit comes from in Scala?

Short question:

Is there a way to ask the scala compiler to tell me where a certain implicit used at a given point in a program was declared ?

If not, is there an algorithm that I can follow manually to find out myself where an implicit was declared ?

Long question:

I am following simple spray crud tutorial.

In the code snippet below (coming the this repo for the tutorial):

pathEnd {
  post {
    entity(as[Question]) { question =>
      completeWithLocationHeader(
        resourceId = questionService.createQuestion(question),
        ifDefinedStatus = 201, ifEmptyStatus = 409)
      }
    }
} ~

as takes an implicit of type FromRequestUnmarshaller[T] (full source here):

  def as[T](implicit um: FromRequestUnmarshaller[T]) = um

and when I ask IntelliJ where this implicit comes from (using CMD+SHIFT+P), I get:

enter image description here and when I follow the first hint I get this:

trait UnmarshallerLifting {

  implicit def fromRequestUnmarshaller[T](implicit um: FromMessageUnmarshaller[T]): FromRequestUnmarshaller[T] =
    new FromRequestUnmarshaller[T] {
      def apply(request: HttpRequest): Deserialized[T] = um(request)
    }
...

this does not help me to figure out where the implicit FromRequestUnmarshaller[T] comes from because I cannot figure out how the trait UnmarshallerLifting gets mixed into QuestionResource if I inspect the class hierarchy:

enter image description here

I inspect the traits that look like they might contain this implict, for example this trait,but it does not contain the implicit:

trait MarshallingDirectives {
  import BasicDirectives._
  import MiscDirectives._
  import RouteDirectives._

  /**
   * Unmarshalls the requests entity to the given type passes it to its inner Route.
   * If there is a problem with unmarshalling the request is rejected with the [[spray.routing.Rejection]]
   * produced by the unmarshaller.
   */
  def entity[T](um: FromRequestUnmarshaller[T]): Directive1[T] =
    extract(_.request.as(um)).flatMap[T :: HNil] {
      case Right(value)                            ⇒ provide(value)
      case Left(ContentExpected)                   ⇒ reject(RequestEntityExpectedRejection)
      case Left(UnsupportedContentType(supported)) ⇒ reject(UnsupportedRequestContentTypeRejection(supported))
      case Left(MalformedContent(errorMsg, cause)) ⇒ reject(MalformedRequestContentRejection(errorMsg, cause))
    } & cancelAllRejections(ofTypes(RequestEntityExpectedRejection.getClass, classOf[UnsupportedRequestContentTypeRejection]))

  /**
   * Returns the in-scope FromRequestUnmarshaller for the given type.
   */
  def as[T](implicit um: FromRequestUnmarshaller[T]) = um

  /**
   * Uses the marshaller for the given type to produce a completion function that is passed to its inner route.
   * You can use it do decouple marshaller resolution from request completion.
   */
  def produce[T](marshaller: ToResponseMarshaller[T]): Directive[(T ⇒ Unit) :: HNil] =
    extract { ctx ⇒ (value: T) ⇒ ctx.complete(value)(marshaller) } & cancelAllRejections(ofType[UnacceptedResponseContentTypeRejection])

  /**
   * Returns the in-scope Marshaller for the given type.
   */
  def instanceOf[T](implicit m: ToResponseMarshaller[T]) = m

  /**
   * Completes the request using the given function. The input to the function is produced with the in-scope
   * entity unmarshaller and the result value of the function is marshalled with the in-scope marshaller.
   */
  def handleWith[A, B](f: A ⇒ B)(implicit um: FromRequestUnmarshaller[A], m: ToResponseMarshaller[B]): Route =
    entity(um) { a ⇒ RouteDirectives.complete(f(a)) }
}

object MarshallingDirectives extends MarshallingDirectives

after looking at 20 different places I become frustrated.

Is there a way to ask the scala compiler to tell me where a certain implicit (in this example FromRequestUnmarshaller[T]) used at a given point in a program (in this example here) was declared ?

If not, is there an algorithm that I can follow manually to find out myself where an implicit was declared ?

I looked for this question on Google/SOF but the hints I found did not help. I also went through this and I still don't know where the FromRequestUnmarshaller[T] comes from.

like image 235
jhegedus Avatar asked Dec 29 '16 15:12

jhegedus


People also ask

What is implicit parameter in Scala?

Implicit parameters are the parameters that are passed to a function with implicit keyword in Scala, which means the values will be taken from the context in which they are called.

Where does Scala look for Implicits?

When an implicit value is required, the Scala compiler would first look into the current scope to find the required implicit value that can act as a function for the type conversion required. The current scope used as implicit scope include: Local scope.

How do implicit classes work Scala?

Scala 2.10 introduced a new feature called implicit classes. An implicit class is a class marked with the implicit keyword. This keyword makes the class's primary constructor available for implicit conversions when the class is in scope. Implicit classes were proposed in SIP-13.

What is implicit object in Scala?

In Scala, objects and values are treated mostly the same. An implicit object can be thought of as a value which is found in the process of looking up an implicit of its type.


2 Answers

Typically I enable -Xlog-implicits in compiler to see what's going on with implicits.

Also spray is deprecated in favor of akka-http. I recommend to switch.

like image 106
expert Avatar answered Nov 15 '22 04:11

expert


I did this (as suggested in Michael's comment):

    import scala.reflect.runtime.universe.reify
    println(reify(entity(as[Question])))

It printed:

Expr[spray.routing.Directive1[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question]](QuestionResource.entity(QuestionResource.as[Question](Deserializer.fromRequestUnmarshaller(Deserializer.fromMessageUnmarshaller(QuestionResource.json4sUnmarshaller(ManifestFactory.classType(classOf[spray_examples.plain_rest.danielasfregola.quiz.management.entities.Question])))))))

This tells directly where the implicit is coming from : Deserializer.fromRequestUnmarshaller

Also, here is an other way, by using InteliJ's search usage function:

enter image description here

like image 36
jhegedus Avatar answered Nov 15 '22 05:11

jhegedus