= Solution
\b[A <function> accepting every `Base` can safely be used where only `Derived` inputs will be supplied. The reverse direction is unsafe.] A `Derived` argument is already a valid `Base` argument; restricting the possible callers introduces no new obligation for the <function>. This is the contravariant input rule of <function> <subtyping>.
The printed <trait> has <generic type invariance>, so <Scala> does not directly permit either parameter-changing assignment. The safe behavior can be exposed using an explicit adapter without changing that <trait>:
``
def restrictInput(f: Fun[Base, Base]): Fun[Derived, Base] =
new Fun[Derived, Base] {
def apply(x: Derived): Base = f(x)
}
``
For the unsafe direction, take illustrative classes in which a derived <software object> has an extra operation:
``
class Base
class Derived extends Base { def special(): Int = 1 }
val narrow = new Fun[Derived, Base] {
def apply(x: Derived): Base = { x.special(); x }
}
def broadClient(f: Fun[Base, Base]): Base = f(new Base)
// broadClient(narrow) must be rejected.
``
If that substitution were accepted, the client could pass an ordinary base <software object> to code that calls `special`, which that <software object> does not support. The rejected call is intentional counterexample code, not a promised compilable application. Variance annotations are needed to make sound direct conversions part of the generic <trait>'s declared <subtyping> relation.<Scala 2.13 variance annotations specification>[Variance Annotations: missing annotation is invariant; method-input positions reverse variance]{ref}
Back to article page