Skip to content

Support retroactive variance declarations for Java function types #184

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
retronym opened this issue Jul 14, 2016 · 6 comments
Closed

Support retroactive variance declarations for Java function types #184

retronym opened this issue Jul 14, 2016 · 6 comments
Milestone

Comments

@retronym
Copy link
Member

scala> "abc".chars.boxed.map[String](x => x.toString).collect(java.util.stream.Collectors.toList())
res15: java.util.List[String] = [97, 98, 99]

scala> "abc".chars.boxed.map(x => x.toString).collect(java.util.stream.Collectors.toList())
<console>:12: error: no type parameters for method map: (x$1: java.util.function.Function[_ >: Integer, _ <: R])java.util.stream.Stream[R] exist so that it can be applied to arguments (java.util.function.Function[Integer,String])
 --- because ---
argument expression's type is not compatible with formal parameter type;
 found   : java.util.function.Function[Integer,String]
 required: java.util.function.Function[_ >: Integer, _ <: ?R]
Note: Integer <: Any, but Java-defined trait Function is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
       "abc".chars.boxed.map(x => x.toString).collect(java.util.stream.Collectors.toList())
                         ^
<console>:12: error: type mismatch;
 found   : java.util.function.Function[Integer,String]
 required: java.util.function.Function[_ >: Integer, _ <: R]
       "abc".chars.boxed.map(x => x.toString).collect(java.util.stream.Collectors.toList())
                               ^

scala> :power
Power mode enabled. :phase is at typer.
import scala.tools.nsc._, intp.global._, definitions._
Try :help or completions for vals._ and power._

scala> val j_u_f_Function = symbolOf[java.util.function.Function[_, _]]
j_u_f_Function: $r.intp.global.TypeSymbol = trait Function

scala> val t :: r :: Nil = j_u_f_Function.typeParams
t: $r.intp.global.Symbol = type T
r: $r.intp.global.Symbol = type R

scala> t.setFlag(Flag.CONTRAVARIANT)
res17: t.type = type T

scala> r.setFlag(Flag.COVARIANT)
res18: r.type = type R

scala> "abc".chars.boxed.map(x => x.toString).collect(java.util.stream.Collectors.toList())
res19: java.util.List[String] = [97, 98, 99]

Should we just go ahead and set the variances for java.util.Function? We could follow up with an extension point for third party classes in a later release?

Precedent: we change Serializable and Comparable to look like universal traits:

    lazy val JavaSerializableClass = requiredClass[java.io.Serializable] modifyInfo fixupAsAnyTrait
    lazy val ComparableClass       = requiredClass[java.lang.Comparable[_]] modifyInfo fixupAsAnyTrait
@retronym retronym added this to the 2.12.x milestone Jul 14, 2016
@retronym
Copy link
Member Author

@adriaanm I fear that the "variance cast" solution in SI-8079 won't really be that useful in practice, it relies on people using the wrapper type aliases in the API you're working with.

@retronym
Copy link
Member Author

I've implemented this as a proof of concept compiler plugin for now.

https://github.com/retronym/variant-java

@adriaanm
Copy link
Contributor

Cool!!

@smarter
Copy link
Member

smarter commented Jun 4, 2019

FWIW, Dotty is able to type "abc".chars.boxed.map(x => x.toString).collect(java.util.stream.Collectors.toList()) without assuming anything about the variance of java.util.Function.

@smarter
Copy link
Member

smarter commented Jun 4, 2019

@retronym
Copy link
Member Author

retronym commented Jun 9, 2019

Closing this as it turns out we don't need it to make things work as desired, constraint solving just needed a bug fix.

@retronym retronym closed this as completed Jun 9, 2019
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

No branches or pull requests

3 participants