If the mutable set were allowed a covariant type parameter, both variables below could refer to the same mutable object:The broad view accepts any value, including a string. The narrow view still promises that deletion returns an
val s1: Set[Int] = new Set[Int](List())
val s2: Set[Any] = s1 // hypothetically permitted
s2.add("not an integer")
val n: Int = s1.delete() // cannot return an IntInt, yet the sole stored value is that string. This violates type safety:This is covariance failure for a mutable collection. The input occurrence in add(x: T) conflicts with the positive occurrence in the result of delete. Keeping a generic type invariance restriction prevents the unsafe aliasing. The example uses an initially empty set so that the problematic deletion result is forced.Hypothetical covariance would allow the following unsound alias:
val narrow: MSet[Int] = new MSet[Int](Nil)
val wide: MSet[Any] = narrow // hypothetical covariant conversion
wide.add("not an integer")
val n: Int = narrow.delete() // would return the inserted stringThe last value cannot satisfy its promised type. This is the covariance failure for a mutable collection: a broader consuming interface could insert values that violate a narrower alias's guarantee. The actual invariant
MSet[T] rejects the conversion, and declaring +T while retaining add(x: T) is itself rejected by the variance-position rule. The mutable read-and-write interface must remain invariant in T.