Skip to content

Ambiguous implicit arguments problem #12123

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
jczuchnowski opened this issue Apr 16, 2021 · 4 comments
Closed

Ambiguous implicit arguments problem #12123

jczuchnowski opened this issue Apr 16, 2021 · 4 comments

Comments

@jczuchnowski
Copy link

jczuchnowski commented Apr 16, 2021

Compiler version

3.0.0-RC2

Minimized code

sealed trait TypeTag[+A]

object TypeTag {
  implicit case object TDouble extends TypeTag[Double]
  implicit case object TInt extends TypeTag[Int]
}

case class Expr[+B](value: B)

case class Fun[-A, +B](name: String) { self =>
  def run[B1 >: B](param: Expr[A])(implicit typeTag: TypeTag[B1]): Expr[B1] = ???
}

object Example {

  val fun = Fun[Double, Double]("name")
  fun.run(Expr(3.0))

}

Output

[error] -- Error: Example.scala:17:20 
[error] 17 |  fun.run(Expr(3.0))
[error]    |                    ^
[error]    |ambiguous implicit arguments: both object TDouble in object TypeTag and object TInt in object TypeTag match type TypeTag[B1] of parameter typeTag of method run in class Fun
[error] one error found

Expectation

This is something we have a problem with when migrating ZIO SQL to Scala 3. It works fine in Scala 2.13 and 2.12 and it seems it shouldn't be ambiguous in Scala 3 either.

@jczuchnowski
Copy link
Author

Possibly a diplicate of #7999

@smarter
Copy link
Member

smarter commented Apr 16, 2021

Well, the compiler isn't wrong, both of these implicits could fit and neither one is more specific than the other. This wouldn't be an issue if TypeTag was invariant in its type parameter, but I assume there's a good reason you need it to be covariant?

@odersky
Copy link
Contributor

odersky commented Apr 17, 2021

If I pass TInt explicitly, I get an error in Scala 2:

test.scala:17: error: type mismatch;
 found   : TypeTag.TInt.type
 required: TypeTag[Double]
  val x1 = fun.run(Expr(3.0))(TypeTag.TInt)
                                      ^

Scala 3 compiles this line and expands it to:

val x1: Expr[AnyVal] = 
      Example.fun.run[AnyVal](Expr.apply[Double](3.0d))(TypeTag.TInt)

The Scala 3 solution is correct. Scala 2 instantiates B1 too early to Double and then runs into an error. That's why in Scala 2 only one implicit is applicable. So better type inference in Scala 3 means in this case unfortunately more ambiguities for implicits. But as @smarter wrote, the ambiguity is real, it's just that Scala 2's more limited type inference did not detect it.

I don't think there's anything we can do here, unfortunately. TypeTag should be invariant; then it works.

@odersky odersky closed this as completed Apr 17, 2021
@jczuchnowski
Copy link
Author

Thank you for helping with this. I think we can live with invariant TypeTag in that case.

jczuchnowski added a commit to zio-archive/zio-sql that referenced this issue Jun 6, 2021
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