Skip to content

Fix numeric implicit args #902

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

Merged
merged 3 commits into from
Nov 9, 2015

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Nov 1, 2015

Fix problems encountered when trying to compile math.BigInt and BigDecimal. Review by @smarter or @retronym

Compiling scala.math.BigDecimal and scala.math.BigInteger shows a problem.
The conversion `int2bigInt` is not applicable to a Byte because `Byte -> Int`
requires another implicit conversion.

We fix that by using a new method relaxed_<:< for implicit compatibility checks,
which always admits numeric widenings.

This leads to another problem. Now the conversions

    implicit def byteToInt(x: Byte): Int
    implicit def byteToShort(x: Byte): Short

are ambiguous when we try to convert from Byte to Int.
We fix that by adding a "tie-break" to implicit search
where if several methods match a numeric value result type
and all have numeric value types as result types, we
pick the numerically largest type that matches.
Dotty delivers an ambiguity error. The comment in the test argues why
this is OK.
and explain why it's different now.
@odersky odersky force-pushed the fix-numeric-implicit-args branch from 1e17cc2 to 3460856 Compare November 2, 2015 07:58
@smarter
Copy link
Member

smarter commented Nov 5, 2015

So, this PR allows the following code to compile:

class Foo
object Test {
  implicit def fooToShort(x: Foo): Short = 1
  val x: Int = new Foo
}

This was not allowed in Scala so this is a language change, should we write an SIP for it? It seems like a useful feature to me, but it complicates the rules for implicit resolution and the implementation (if I'm not mistaken, the numericValueTieBreak function wouldn't be needed if we didn't allow this) and it makes the numeric types even more "magic". LGTM, but it'd be great to hear from @retronym or someone else with experience dealing with numeric types.

@smarter smarter mentioned this pull request Nov 5, 2015
@odersky
Copy link
Contributor Author

odersky commented Nov 5, 2015

@smarter Interesting example. Scala 2 has the concept of "weak conformance" which handles some of the things this PR addresses. We made a decision not to go with weak conformance because it is complicated. But without this PR, the standard library does not compile (for the reasons given in the commits).

It seems to me the Dotty proposal is more local and less sweeping than weak conformance. It only applies to implicit search. In essence, it means we allow some implicit conversions (namely those between numeric types) to be composed with other conversions in implicit search. So this is an exception to the rule that generally implicit search is not transitive. And we need to clean up the fallout of possible ambiguities by a tie-break which essentially says the less distance covered by those additional numeric conversions the better.

I think that design is still a net win over weak conformance, but if people disagree or want to propose another alternative how to deal with this, I'd be interested to see some arguments.

@odersky
Copy link
Contributor Author

odersky commented Nov 9, 2015

No additional arguments, so I am merging this for now. We should revisit the issue of weak conformance in the future.

odersky added a commit that referenced this pull request Nov 9, 2015
@odersky odersky merged commit 80c2fbd into scala:master Nov 9, 2015
@propensive
Copy link
Contributor

Would a small set of implicits like this one help?

implicit def shortToInt[T](t: T)(implicit fn: T => Short): Int = fn(t)

This one permits @smarter's example to compile on Scala 2.

@odersky
Copy link
Contributor Author

odersky commented Nov 9, 2015

No because we run into the transitivity issue.

On Mon, Nov 9, 2015 at 10:07 AM, Jon Pretty notifications@github.com
wrote:

Would a small set of implicits like this one help?

implicit def shortToInt[T](t: T)(implicit fn: T => Short): Int = fn(t)

This one permits @smarter https://github.com/smarter's example to
compile on Scala 2.


Reply to this email directly or view it on GitHub
#902 (comment).

Martin Odersky
EPFL

@allanrenucci allanrenucci deleted the fix-numeric-implicit-args branch December 14, 2017 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants