Uploaded image for project: '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.

        Attachments

          Issue Links

            Activity

            Hide
            nikov 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
            nikov 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
            soc 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
            soc 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
            harrah Mark Harrah added a comment -

            To the original example, add:

            `val z: Int = p.y`

            This will throw a !ClassCastException.

            Show
            harrah Mark Harrah added a comment - To the original example, add: `val z: Int = p.y` This will throw a !ClassCastException.
            Hide
            heathermiller 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
            heathermiller 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
            moors 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
            moors 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
            grek Grzegorz Kossakowski added a comment -

            Unassigning and rescheduling to M7 as previous deadline was missed.

            Show
            grek Grzegorz Kossakowski added a comment - Unassigning and rescheduling to M7 as previous deadline was missed.
            Hide
            retronym 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
            retronym 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
            retronym Jason Zaugg added a comment - https://github.com/scala/scala/pull/3184

              People

              • Assignee:
                retronym Jason Zaugg
                Reporter:
                nikov 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: