Skip to content

Support retroactive variance declarations for Java function types #184

Closed
@retronym

Description

@retronym
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions