Skip to content

Commit

Permalink
SI-5189 detect unsoundness when inferring type of match
Browse files Browse the repository at this point in the history
GADT skolems encode type slack that results from pattern matching on variant type constructors
I thought they would not longer be relevant after cases have been typed,
and since they caused weird issues with the old pattern matcher, I deskolemized in typedCase

however, when we don't have an expected type for the match, we need to keep the skolems around
until the skolemized type makes it out of the match and it becomes the result of type inference for that match
when you do have an expected type, it will propagate to the case-level and the confrontation will thus
already take place when typing individual cases
  • Loading branch information
adriaanm committed Jan 9, 2013
1 parent 1381cda commit 8fb19b1
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 6 deletions.
11 changes: 5 additions & 6 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2523,11 +2523,7 @@ trait Typers extends Modes with Adaptations with Tags {
}

// body1 = checkNoEscaping.locals(context.scope, pt, body1)
val treeWithSkolems = treeCopy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe

new TypeMapTreeSubstituter(deskolemizeGADTSkolems).traverse(treeWithSkolems)

treeWithSkolems // now without skolems, actually
treeCopy.CaseDef(cdef, pat1, guard1, body1) setType body1.tpe
}

// undo adaptConstrPattern's evil deeds, as they confuse the old pattern matcher
Expand Down Expand Up @@ -2562,7 +2558,10 @@ trait Typers extends Modes with Adaptations with Tags {

val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, resTp))

treeCopy.Match(tree, selector1, casesAdapted) setType resTp
val matchTyped = treeCopy.Match(tree, selector1, casesAdapted) setType resTp
if (!newPatternMatching) // TODO: remove this in 2.11 -- only needed for old pattern matcher
new TypeMapTreeSubstituter(deskolemizeGADTSkolems).traverse(matchTyped)
matchTyped
}

// match has been typed -- virtualize it if we're feeling experimental
Expand Down
6 changes: 6 additions & 0 deletions test/files/neg/t5189_inferred.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
t5189_inferred.scala:7: error: type mismatch;
found : scala.collection.immutable.Nil.type
required: ?A1 where type ?A1
f(Invariant(arr): Covariant[Any])(0) = Nil
^
one error found
8 changes: 8 additions & 0 deletions test/files/neg/t5189_inferred.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
trait Covariant[+A]
case class Invariant[A](xs: Array[A]) extends Covariant[A]

class Test {
val arr = Array("abc")
def f[A](v: Covariant[A]) /*inferred!*/ = v match { case Invariant(xs) => xs }
f(Invariant(arr): Covariant[Any])(0) = Nil
}

0 comments on commit 8fb19b1

Please sign in to comment.