scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Equality in type refinement fails in some contexts #8599

Open scabug opened 10 years ago

scabug commented 10 years ago

The following code uses type refinement to prove the equality of two types. The equality sought is essentially the same in each case, but in one it succeeds and in one it fails:

object RefinementTest {
    sealed trait Grandparent[A]
    sealed trait Parent[A] extends Grandparent[A]
    case class Child[C](c: (C, C)) extends Parent[(C, C)]

    def extractParent[A](parent: Parent[A]): A = parent match {
      case child: Child[c] => child.c
    }

    // Fails
    def extractGrandparent1[A](grandparent: Grandparent[A]): A = grandparent match {
      case parent: Parent[a] =>
        parent match {
          //     Error: type mismatch;
          //     found   : (c, c)
          //     required: a
          case child: Child[c] => child.c: a
        }
    }

    // Works
    def extractGrandparent2[A](grandparent: Grandparent[A]): A = grandparent match {
      case parent: Parent[a] => extractParent(parent)
    }
  }
scabug commented 10 years ago

Imported From: https://issues.scala-lang.org/browse/SI-8599?orig=1 Reporter: Owen Healy (ellbur) Affected Versions: 2.11.0

scabug commented 10 years ago

@retronym said: The relevant players in this bug / limitation are shown in the following log output:

% qbin/scalac -Ylog:typer -Xdev -explaintypes sandbox/test.scala
[log typer] updated bounds: type A from  to:  >: (c, c) <: (c, c)
[log typer] instantiateTypeVar with nonEmpty saved type bounds {
  enclosing  Context(test.scala) {    owner       = method extractParent
      saved  List((type A,))
     tparam  AbstractTypeSymbol type c
}
[log typer] redundant bounds: discarding TypeBounds(Nothing, Any) for type c, no improvement on TypeBounds(Nothing, Any)
[log typer] Discarding inferred TypeBounds(lo=(c, c), hi=(c, c)) because type A does not appear in: (c, c)
[log typer] Adding cast to pattern because (c, c) does not conform to expected type A
[log typer] updated bounds: type a from  to:  >: A <: A
[log typer] inconsistent bounds: discarding TypeBounds(Any, A with (c, c))
[log typer] redundant bounds: discarding TypeBounds(Nothing, Any) for type c, no improvement on TypeBounds(Nothing, Any)
sandbox/test.scala:17: error: type mismatch;
 found   : (c, c)
 required: a
        case child: Child[c] => child.c: a
                                      ^
(c, c) <: a?
false
[log typer] Discarding inferred TypeBounds(lo=A, hi=A) because type a does not appear in: A
[log typer] updated bounds: type a from  to:  >: A <: A
warning: !!! Preserving inference: a=A in a (based on TypeBounds(lo=A, hi=A)) before restoring type a to saved <empty bounds>: A
one warning found
one error found
scabug commented 10 years ago

@retronym said: https://github.com/scala/scala/pull/3759