summaryrefslogtreecommitdiff
path: root/test/files/neg/exhausting.scala
Commit message (Collapse)AuthorAgeFilesLines
* Cull extraneous whitespace.Paul Phillips2013-09-181-1/+1
| | | | | | | | | | | | | | | | | | | | | One last flurry with the broom before I leave you slobs to code in your own filth. Eliminated all the trailing whitespace I could manage, with special prejudice reserved for the test cases which depended on the preservation of trailing whitespace. Was reminded I cannot figure out how to eliminate the trailing space on the "scala> " prompt in repl transcripts. At least reduced the number of such empty prompts by trimming transcript code on the way in. Routed ConsoleReporter's "printMessage" through a trailing whitespace stripping method which might help futureproof against the future of whitespace diseases. Deleted the up-to-40 lines of trailing whitespace found in various library files. It seems like only yesterday we performed whitespace surgery on the whole repo. Clearly it doesn't stick very well. I suggest it would work better to enforce a few requirements on the way in.
* SI-7669 Fix exhaustivity warnings for recursive ADTs.Jason Zaugg2013-07-171-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The pattern matcher's analysis was correctly finding models under which the match in the enclosed test could fail. But, when trying to render that model as a counter example, it ran into an internal inconsistency and gave up. That inconsistency arose from VariableAssignment, which: > turn the variable assignments into a tree > the root is the scrutinee (x1), edges are labelled > by the fields that are assigned a node is a variable > example (which is later turned into a counter example) In the process, it notes the unreachable case `V2 = NotHandled`, which can only arise if `V1 = Op`, ie the scrutinee is `Op(NotHandled())`. V2 is assosicated with the path `x1.arg`. The code then looked for any variable assosicated with the prefix `x1` and registered that its field `arg` was assosicated with this variable assignment. However, the assignment for `V1 = NotHandled` (another missing case) is also associated with the path `x1`. Registering this field makes no sense here; we should only do that for `Op`. This commit conditionally registers the fields based on the class of `VariableAssignment#cls`. We no longer hit the inconsistency in `VariableAssignment#allFieldAssignmentsLegal`. This favourably changes the results of two existing tests. I had to tweak the counter example pruning to avoid relying on CounterExample.==, which is flaky in the light of Nil and List(). It is possible to have: A, B where A != B && A.coveredBy(B) && B.coveredBy(A) Luckily it is straightforward to implement pruning entirely with coveredBy.
* Exhaustivity: TreeMakers as boolean propositionsAdriaan Moors2012-05-221-5/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We check exhaustivity by representing a match as a formula in finite-domain propositional logic (FDPL) that is false when the match may fail. The variables in the formula represent tested trees in the match (type tests/value equality tests). The approximation uses the same framework as the CSE analysis. A matrix of tree makers is turned into a DAG, where sharing represents the same value/type being tested. We reduce FDPL to Boolean PL as follows. For all assignments, V_i = c_i_j, we introduce a proposition P_i_j that is true iff V_i is equal to the constant c_i_j, for a given i, and all j, P_i_j are mutually exclusive (a variable cannot have multiple values). If the variable's domain is closed, we assert that one of P_i_j must be true for each i and some j. The conjunction of these propositions constitutes the equality axioms. After going through negational normal form to conjunctive normal form, we use a small SAT solver (the DPLL algorithm) to find a model under which the equational axioms hold but the match fails. The formula: EqAxioms /\ -MatchSucceeds. Note that match failure expresses nicely in CNF: the negation of each case (which yields a disjunction) is anded. We then turn this model into variable assignments (what's the variable (not) equal to, along with recursive assignments for its fields). Valid assignments (no ill-typed field assignments) are then presented to the user as counter examples. A counter example is a value, a type test, a constructor call or a wildcard. We prune the example set and only report the most general examples. (Finally, we sort the output to yield stable, i.e. testable, warning messages.) A match is only checked for exhaustivity when the type of the selector is "checkable" (has a sealed type or is a tuple with at least one component of sealed type). We consider statically known guard outcomes, but generally back off (don't check exhaustivity) when a match has guards or user-defined extractor calls. (Sometimes constant folding lets us statically decide a guard.) We ignore possibly failing null checks (which are performed before calling extractors, for example), though this could be done easily in the current framework. The problem is false positives. People don't usually put nulls in tuples or lists. To improve the exhaustivity checks, we rewrite `List()` to Nil. TODO: more general rewrite of List(a, b, ..., z) to `a :: b :: ... :: z`. When presenting counter examples, we represent lists in the user-friendly List(a,...,z) format. (Similarly for tuples.) There are no exhaustivity checks for a match-defined PartialFunction. misc notes: - fix pure case of dpll solver impure set (symbol that occurs both as a positive and negative literal) was always empty since I was looking for literals (which are not equal if positivity is not equal) but should have been looking for symbols - FDPL -> BoolPL translation collects all syms in props since propForEqualsTo generates an Or, must traverse the prop rather than assuming only top-level Syms are relevant... also, propForEqualsTo will not assume Or'ing a whole domain is equivalent to True (which it isn't, since the type test may fail in general) - improve counter example description - treat as constructor call when we either have definite type information about a real class, or we have no equality information at all, but the variable's type is a class and we gathered constraints about its fields (typically when selector is a tuple) - flatten a :: b :: ... :: Nil to List(a, b, ...) - don't print tuple constructor names, so instead of "Tuple2(a, b)", say "(a, b)" - filter out more statically impossible subtypes the static types convey more information than is actually checkable at run time this is good, as it allows us to narrow down the subtypes of a sealed type, however, when modeling the corresponding run-time checks we need to "erase" the uncheckable parts (using existentials so that the types are still well-kinded), so that we can use static subtyping as a sound model for dynamic type checks - experimental java enum handling seals enum class before, we created a refinement class as the placeholder for the sealed children it seems more direct to use the enum class for that this way, the new pattern matcher's exhaustiveness checker just works for java enums
* Begone t1737...Hubert Plociniczak2011-11-021-4/+4
|
* Improves exhaustiveness analysis to not warn ab...Paul Phillips2010-10-051-1/+6
| | | | | | | | Improves exhaustiveness analysis to not warn about types which cannot match due to nonconformant type parameters. Also, look at the different warnings emitted in the test case based on the presence of a constraint. Nifty! Closes #3683, no review.
* Massively simplified the exhaustiveness checker...Paul Phillips2010-10-051-0/+40
Massively simplified the exhaustiveness checker with no measurable loss of fidelity. I might be the only one who can be unsurprised by such a bloody diff: anyone else would rightly say "how on earth..." No review.