Scala Programming Language
  1. Scala Programming Language
  2. SI-2066

Unsoundness in overriding methods with higher-order type parameters

    Details

      Description

      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.

        Issue Links

          Activity

          Hide
          Vladimir Reshetnikov added a comment -

          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.f[C](c)
          c1: C[Any] = C@9e7d46

          scala> c1.y = ""

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

          Show
          Vladimir Reshetnikov added a comment - 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.f [C] (c) c1: C [Any] = C@9e7d46 scala> c1.y = "" scala> c.y java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
          Hide
          Simon Ochsenreither added a comment -

          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?

          Show
          Simon Ochsenreither added a comment - 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?
          Hide
          Mark Harrah added a comment -

          To the original example, add:

          `val z: Int = p.y`

          This will throw a !ClassCastException.

          Show
          Mark Harrah added a comment - To the original example, add: `val z: Int = p.y` This will throw a !ClassCastException.
          Hide
          Heather Miller added a comment -

          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)

          Show
          Heather Miller added a comment - 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 )
          Hide
          Adriaan Moors added a comment -

          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

          Show
          Adriaan Moors added a comment - 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
          Hide
          Grzegorz Kossakowski added a comment -

          Unassigning and rescheduling to M7 as previous deadline was missed.

          Show
          Grzegorz Kossakowski added a comment - Unassigning and rescheduling to M7 as previous deadline was missed.
          Hide
          Jason Zaugg added a comment -

          Here's an patch that I'm cobbling together:

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

          Show
          Jason Zaugg added a comment - Here's an patch that I'm cobbling together: https://github.com/retronym/scala/compare/ticket;2066?expand=1
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/pull/3184

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Vladimir Reshetnikov
              TracCC:
              Ismael Juma, Mark Harrah, Simon Ochsenreither
            • Votes:
              2 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development