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

Regression involving existential types and pattern matching

    Details

      Description

      The following code compiles without errors in 2.9.1, but fails in 2.10.0-SNAPSHOT (2.10.0.rdev-4232-2012-01-23-g9a20086). This looks related to Martin's fix on Jan. 21:
      https://github.com/scala/scala/commit/2e092d4822d044312317c502badd8ad5c2674b58

      
      class Foo {
        trait Init[T]
        class ScopedKey[T] extends Init[T]
      
        trait Setting[T] {
          val key: ScopedKey[T]
        }
      
        case class ScopedKey1[T](val foo: Init[T]) extends ScopedKey[T]
      
        val scalaHome: Setting[Option[String]] = null
        val scalaVersion: Setting[String] = null
      
        def testPatternMatch(s: Setting[_]) {
          s.key match {
            case ScopedKey1(scalaHome.key | scalaVersion.key) => ()
          }
        }
      }
      

      Errors when compiled with trunk:

      
      existential.scala:34: error: type mismatch;
       found   : Foo.this.ScopedKey[Option[String]]
       required: Foo.this.Init[Any]
      Note: Option[String] <: Any, but trait Init is invariant in type T.
      You may wish to define T as +T instead. (SLS 4.5)
            case ScopedKey1(scalaHome.key | scalaVersion.key) => ()
                                      ^
      existential.scala:34: error: type mismatch;
       found   : Foo.this.ScopedKey[String]
       required: Foo.this.Init[Any]
      Note: String <: Any, but trait Init is invariant in type T.
      You may wish to define T as +T instead. (SLS 4.5)
            case ScopedKey1(scalaHome.key | scalaVersion.key) => ()
                                                         ^
      two errors found
      

        Issue Links

          Activity

          Hide
          Martin Odersky added a comment -

          In fact, my suspicion is that it's the virtual pattern matcher. Not sure whether the pattern matcher is right to refuse or not. Assigning to Adriaan.

          Show
          Martin Odersky added a comment - In fact, my suspicion is that it's the virtual pattern matcher. Not sure whether the pattern matcher is right to refuse or not. Assigning to Adriaan.
          Hide
          Iulian Dragos added a comment -

          I'm not sure either.

          For the record, I opened related ticket SI-5400. It might be a duplicate as it involves the same actors, but the error is different.

          Show
          Iulian Dragos added a comment - I'm not sure either. For the record, I opened related ticket SI-5400 . It might be a duplicate as it involves the same actors, but the error is different.
          Hide
          Grzegorz Kossakowski added a comment -

          AFAIK, virtual pattern matcher kicks in only -Yvirtpatmat is supplied. It's off by default.

          Show
          Grzegorz Kossakowski added a comment - AFAIK, virtual pattern matcher kicks in only -Yvirtpatmat is supplied. It's off by default.
          Hide
          Paul Phillips added a comment -

          This also regressed with r25935 aka https://github.com/scala/scala/commit/22d125f1e3

          Show
          Paul Phillips added a comment - This also regressed with r25935 aka https://github.com/scala/scala/commit/22d125f1e3
          Hide
          Paul Phillips added a comment -

          Closed #5400 as a duplicate since it regressed in the same commit. Here's the source for an additional test case.

          class Test {
            type AnyCyclic = Execute[Task]#CyclicException[_]
          
            trait Task[T]
          
            trait Execute[A[_] <: AnyRef] {
              class CyclicException[T](val caller: A[T], val target: A[T])
            }
          
            def convertCyclic(c: AnyCyclic): String =
              (c.caller, c.target) match {
                case (caller: Task[_], target: Task[_]) => "bazinga!"
              }
          }
          
          Show
          Paul Phillips added a comment - Closed #5400 as a duplicate since it regressed in the same commit. Here's the source for an additional test case. class Test { type AnyCyclic = Execute[Task]#CyclicException[_] trait Task[T] trait Execute[A[_] <: AnyRef] { class CyclicException[T](val caller: A[T], val target: A[T]) } def convertCyclic(c: AnyCyclic): String = (c.caller, c.target) match { case (caller: Task[_], target: Task[_]) => "bazinga!" } }
          Hide
          Paul Phillips added a comment -

          Another test case for when this is fixed.

            trait TFn1B {
              type In
              type Out
              type Apply[T <: In] <: Out
            }
          
            trait TFn1[I, O] extends TFn1B {
              type In = I
              type Out = O
            }
          
            trait >>[F1 <: TFn1[_, _], F2 <: TFn1[_, _]] extends TFn1[F1#In, F2#Out] {
              type Apply[T] = F2#Apply[F1#Apply[T]]
            }
          
          Show
          Paul Phillips added a comment - Another test case for when this is fixed. trait TFn1B { type In type Out type Apply[T <: In] <: Out } trait TFn1[I, O] extends TFn1B { type In = I type Out = O } trait >>[F1 <: TFn1[_, _], F2 <: TFn1[_, _]] extends TFn1[F1#In, F2#Out] { type Apply[T] = F2#Apply[F1#Apply[T]] }
          Hide
          Adriaan Moors added a comment -

          minimal version of the AnyCyclic test case:

          class Test {
            class A[T]
            class B[T](val a: A[T])
          
            case class CaseClass[T](x: T)
          
            def break(existB: B[_]) =
              CaseClass(existB.a) match { case CaseClass(_) => }
          }
          
          Show
          Adriaan Moors added a comment - minimal version of the AnyCyclic test case: class Test { class A[T] class B[T](val a: A[T]) case class CaseClass[T](x: T) def break(existB: B[_]) = CaseClass(existB.a) match { case CaseClass(_) => } }
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/commit/fc24db4c

            People

            • Assignee:
              Martin Odersky
              Reporter:
              Iulian Dragos
            • Votes:
              0 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development