Skip to content

implicit object on a companion is not found in implicit scope #10411

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

Closed
fommil opened this issue Jul 16, 2017 · 5 comments
Closed

implicit object on a companion is not found in implicit scope #10411

fommil opened this issue Jul 16, 2017 · 5 comments

Comments

@fommil
Copy link

fommil commented Jul 16, 2017

for any simple typeclass

@typeclass trait UrlEncoded[T] {
  def urlEncoded(t: T): String
}

if the impl is on the companion of an ADT, everything works fine

  final case class AccessRequest(
    code: String,
    redirect_uri: Uri,
    client_id: String,
    client_secret: String,
    scope: String = "",
    grant_type: String = "authorization_code"
  )

  object AccessRequest {
    import java.net.URLDecoder
    import http.encoding._
    import UrlEncoded.ops._
    implicit val UrlEncoder: UrlEncoded[AccessRequest] =
      new UrlEncoded[AccessRequest] {
        def urlEncoded(a: AccessRequest): String =
          Seq(
            "code"          -> a.code.urlEncoded,
            "redirect_uri"  -> a.redirect_uri.urlEncoded,
            "client_id"     -> a.client_id.urlEncoded,
            "client_secret" -> a.client_secret.urlEncoded,
            "scope"         -> a.scope.urlEncoded,
            "grant_type"    -> a.grant_type
          ).urlEncoded
      }
  }

but if implicit val UrlEncoder is rewritten as an implicit object

    implicit object UrlEncoder extends UrlEncoded[AccessRequest] {

compilation fails when trying to implicitly[UrlEncoded[AccessRequest]]

from https://github.com/fommil/drone-dynamic-agents/blob/6f3a629a9ab7fb801cfc1dcdd9b41fa4de10056e/src/main/scala/http/oauth2.scala#L281-L330

@milessabin
Copy link

Where is implicit object UrlEncoder defined? As a member of object AccessRequest?

@fommil
Copy link
Author

fommil commented Jul 16, 2017

yes, just swapping implicit val with implicit object in the above example

@fommil
Copy link
Author

fommil commented Jul 16, 2017

I suspect this could be one of two things:

  1. object is treated separately to val
  2. the object is a type in its own right, UrlEncoder.type <: UrlEncoded[AccessRequest], as opposed to the exact type I want to derive UrlEncoded[AccessRequest].

I think the best thing for it, for now, is to just avoid implicit object. I've requested a wart to catch this wartremover/wartremover#381 and I'm rewriting implicit object uses in my current project accordingly. Too many moving parts.

@som-snytt
Copy link

There is the known limitation around explicit implicit types. It makes implicit lookup sensitive to definition order in source text. They plan to outlaw lack of explicit type. (Sorry if this has nothing to do with your use case.)

scala> trait X[A]
defined trait X

scala> :pa
// Entering paste mode (ctrl-D to finish)

object Test {
implicitly[X[C]]
case class C(c: String)
object C {
  implicit object x extends X[C]
}
}

// Exiting paste mode, now interpreting.

<pastie>:13: error: could not find implicit value for parameter e: X[Test.C]
       implicitly[X[C]]
                 ^

scala> :pa
// Entering paste mode (ctrl-D to finish)

object Test {
case class C(c: String)
object C {
  implicit object x extends X[C]
}
implicitly[X[C]]
}

// Exiting paste mode, now interpreting.

defined object Test

scala> :pa
// Entering paste mode (ctrl-D to finish)

object Test {
implicitly[X[C]]
case class C(c: String)
object C {
  implicit val x: X[C] = null
}
}

// Exiting paste mode, now interpreting.

defined object Test

@Jasper-M
Copy link

Jasper-M commented Jul 17, 2017

Yes, this is probably a duplicate of (among others) #8697.
I think it works in Dotty though.

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

5 participants