Skip to content

Commit

Permalink
Fix ImperativeCleanup cleaning too much
Browse files Browse the repository at this point in the history
  • Loading branch information
mario-bucev committed Feb 15, 2024
1 parent ab7c793 commit 6f83505
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,25 @@ class ImperativeCleanup(override val s: Trees, override val t: oo.Trees)
object ReconstructTuple {
def unapply(e: s.Expr): Option[s.Expr] = e match {
case s.Let(vd, tuple, Lets(lets, s.Tuple(es))) =>
val letsMap = lets.map { case (vd, e) => (vd.id, e) }.toMap
if (
vd.getType.isInstanceOf[s.TupleType] &&
es.length == vd.getType.asInstanceOf[s.TupleType].bases.length &&
es.zipWithIndex.forall {
case (e0 : s.Variable, i) =>
letsMap.contains(e0.id) &&
letsMap(e0.id) == s.TupleSelect(vd.toVariable, i + 1)
case (e0, i) =>
e0 == s.TupleSelect(vd.toVariable, i + 1)
}
)
Some(tuple)
else
None
vd.getType match {
case s.TupleType(bases) =>
val letsMap = lets.map { case (vd, e) => (vd.id, e) }.toMap
// All let-bindings are used in the "returned" value `es`
lazy val returnedLets = letsMap.keySet.filter(id => es.exists { case v: s.Variable => v.id == id })
// All values in `es` are reconstruction of selections of `vd`
lazy val esIsTupleSel = es.zipWithIndex.forall {
case (e0: s.Variable, i) =>
letsMap.contains(e0.id) &&
letsMap(e0.id) == s.TupleSelect(vd.toVariable, i + 1)
case (e0, i) =>
e0 == s.TupleSelect(vd.toVariable, i + 1)
}
if (es.length == bases.length && returnedLets.size == letsMap.size && esIsTupleSel)
Some(tuple)
else None
case _ =>
None
}

case s.Let(vd, e, Lets(Seq(), v)) if v == vd.toVariable =>
Some(e)
Expand Down
21 changes: 21 additions & 0 deletions frontends/benchmarks/verification/invalid/TupleCleanup.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import stainless.lang._
import stainless.collection._

object TupleCleanup {
def test1(x: BigInt, y: BigInt): (BigInt, BigInt) = {
val (xx, yy) = (x, y)
val boom = Nil[BigInt]().head
(xx, yy)
}

def test2(xs: List[BigInt]): (List[BigInt], List[BigInt]) = {
decreases(xs)
xs match {
case Nil() => (Nil(), Nil())
case Cons(i, t) =>
val (s2, g2) = test2(t)
val boom = Nil[BigInt]().head
(s2, g2)
}
}
}

0 comments on commit 6f83505

Please sign in to comment.