Skip to content

Unsoundness in overriding methods with higher-order type parameters #2066

Closed

Description

@scabug

Try to compile the following code with Scala 2.7.5 final:

trait A {
 def f[T[_]](x : T[Int]) : T[Any]
}

class B extends A {
 def f[T[+_]](x : T[Int]) : T[Any] = x
}

class P[Y](var y : Y)

It is compiled without any errors. But then you can write:

val p = new P(1)
val palias = (new B():A).f[P](p)
palias.y = "hello"

Result:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

So, this way of overriding is unsound.

Activity

  1. scabug commented on Jun 17, 2009

    @scabug
    Author

    Imported From: https://issues.scala-lang.org/browse/SI-2066?orig=1
    Reporter: Vladimir Reshetnikov (nikov)
    See #5517

  2. scabug commented on Jun 19, 2009

    @scabug
    Author

    Vladimir Reshetnikov (nikov) said:
    Similar issue:

    class C[T](var y : T)
    
    object A {
    val a : AnyRef { def f[T[_]](x : T[int]) : T[Any] } = A
    def f[T[+_]](x : T[Int]) : T[Any] = x
    }

    Scala 2.8.0.r18050-b20090618020144 compiler compiles this without
    errors. But it seems unsound, as we can write:

    scala> val c = new C(1)
    c: C[Int] = C@9e7d46

    scala> val c1 = A.a.fC
    c1: C[Any] = C@9e7d46

    scala> c1.y = ""

    scala> c.y
    java.lang.ClassCastException: java.lang.String cannot be cast to
    java.lang.Integer

  3. scabug commented on Mar 4, 2011

    @scabug
    Author

    @soc said:
    Behavior has changed, both examples compile in 2.9.0.r24324-b20110222020042 and don't throw at runtime.

    Should the compiler reject those examples right at the beginning or can this considered to be fixed?

  4. scabug commented on Apr 7, 2011

    @scabug
    Author

    @harrah said:
    To the original example, add:

    val z: Int = p.y

    This will throw a !ClassCastException.

  5. scabug commented on May 7, 2012

    @scabug
    Author

    @heathermiller said:
    B.f should not be able to implement A.f because the type parameter of T is covariant in B but not in A. This seems like it shouldn't compile.

    Added a test case for this one (pull request)

  6. scabug commented on Feb 3, 2013

    @scabug
    Author

    @adriaanm said:
    fixing this will break existing code -- the rule is only to do that in major versions,
    so this will have to wait for 2.11

  7. scabug commented on Oct 15, 2013

    @scabug
    Author

    @gkossakowski said:
    Unassigning and rescheduling to M7 as previous deadline was missed.

  8. scabug commented on Nov 22, 2013

    @scabug
    Author

    @retronym said:
    Here's an patch that I'm cobbling together:

    https://github.com/retronym/scala/compare/ticket;2066?expand=1

  9. scabug commented on Nov 22, 2013

    @scabug
    Author
  10. added this to the 2.11.0-M8 milestone on Apr 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions