Skip to content

Generic number literals miss overloaded method #11482

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
rjolly opened this issue Feb 20, 2021 · 2 comments
Closed

Generic number literals miss overloaded method #11482

rjolly opened this issue Feb 20, 2021 · 2 comments

Comments

@rjolly
Copy link
Contributor

rjolly commented Feb 20, 2021

Compiler version

3.0.0-RC1

Minimized code and output

import scala.language.experimental.genericNumberLiterals
type BigInteger = java.math.BigInteger
given BigInteger: scala.util.FromDigits[BigInteger] with {
  def fromDigits(digits: String) = new BigInteger(digits)
  def apply(x: BigInteger) = x
  def apply(x: String) = fromDigits(x)
}
println(BigInteger(1))
        ^^^^^^^^^^
None of the overloaded alternatives of method apply in object BigInteger with types
 (x: String): BigInteger
 (x: BigInteger): BigInteger
match arguments ((1 : Int))

Expectation

Should work as when there's no overload:

given BigInteger: scala.util.FromDigits[BigInteger] with {
  def fromDigits(digits: String) = new BigInteger(digits)
  def apply(x: BigInteger) = x
}
println(BigInteger(1))
// 1
@odersky
Copy link
Contributor

odersky commented Feb 23, 2021

This can be expressed without givens or generic number literals:

import java.math.BigInteger
class B
object B {
  def apply(x: BigInteger): B = ???
  def apply(x: String): B = ???
}
object Test {
  val x = B(1)
}
-- [E134] Type Mismatch Error: test.scala:8:10 ---------------------------------
8 |  val x = B(1) 
  |          ^
  |None of the overloaded alternatives of method apply in object B with types
  | (x: String): B
  | (x: java.math.BigInteger): B
  |match arguments ((1 : Int))
1 error found

scalac gives the same result. The problem is that there is no conversion from Int to BigInteger. It's BigInt instead.

@rjolly
Copy link
Contributor Author

rjolly commented Feb 23, 2021

Yes, with BigInt it works:

class B
object B {
  def apply(x: BigInt): B = ???
  def apply(x: String): B = ???
}
object Test {
  val x = B(1)
}

So your initial comment that the problem is that implicit conversions are not applied when doing overloading resolution, seems wrong. In addition, generic number literal is a different problem (though it could be seen as a subcase of implicit conversion, as I argued in #7468, but let's put it aside for the moment). Note that I use Java's BigInteger instead of BigInt on purpose, to remove a level of indirection (I think it would be a good idea to generalize this to other types like Option|al but it's yet another subject).

So I think the initial problem with generic number literals is not solved (and would be interesting to solve). The fact that the BigInt version does work is not telling, as it succeeds thanks to implicit conversion, not generic number literals. To convince yourself of it, you can just try it with a big number:

import scala.language.experimental.genericNumberLiterals
class B
object B {
  def apply(x: BigInt): B = ???
  def apply(x: String): B = ???
}
object Test {
  val x = B(18446744073709551616)
//          ^^^^^^^^^^^^^^^^^^^^
//          number too large
}

Remove apply(String) -> it works. I have opened a new issue, this time with BigInt for clarity.

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