@@ -1231,8 +1231,8 @@ object quantifiedChunkSupporter extends QuantifiedChunkSupport {
12311231 case Some (heuristics) =>
12321232 heuristics
12331233 case None =>
1234- quantifiedChunkSupporter.hintBasedChunkOrderHeuristic(
1235- quantifiedChunkSupporter.extractHints(None , arguments))
1234+ quantifiedChunkSupporter.singleReceiverChunkOrderHeuristic(arguments,
1235+ quantifiedChunkSupporter.extractHints(None , arguments), v )
12361236 }
12371237
12381238 if (s.exhaleExt) {
@@ -1737,6 +1737,38 @@ object quantifiedChunkSupporter extends QuantifiedChunkSupport {
17371737 matchingChunks ++ otherChunks
17381738 }
17391739
1740+ def singleReceiverChunkOrderHeuristic (receiver : Seq [Term ], hints : Seq [Term ], v : Verifier )
1741+ : Seq [QuantifiedBasicChunk ] => Seq [QuantifiedBasicChunk ] = {
1742+ // Heuristic that emulates greedy Silicon behavior for consuming single-receiver permissions.
1743+ // First: Find singleton chunks that have the same receiver syntactically.
1744+ // If so, consider those first, then all others.
1745+ // Second: If nothing matches syntactically, try to find a chunk that matches the receiver using the decider.
1746+ // If that's the case, consider that chunk first, then all others.
1747+ // Third: As a fallback, use the standard hint based heuristics.
1748+ val fallback = hintBasedChunkOrderHeuristic(hints)
1749+
1750+ (chunks : Seq [QuantifiedBasicChunk ]) => {
1751+ val (syntacticMatches, others) = chunks.partition(c => c.singletonArguments.contains(receiver))
1752+ if (syntacticMatches.nonEmpty) {
1753+ syntacticMatches ++ others
1754+ } else {
1755+ val greedyMatch = chunks.find(c => c.singletonArguments match {
1756+ case Some (args) if args.length == receiver.length =>
1757+ args.zip(receiver).forall(ts => v.decider.check(ts._1 === ts._2, Verifier .config.checkTimeout()))
1758+ case _ =>
1759+ false
1760+ }).toSeq
1761+ if (greedyMatch.nonEmpty) {
1762+ greedyMatch ++ chunks.diff(greedyMatch)
1763+ } else {
1764+ // It doesn't seem to be any of the singletons. Use the fallback on the non-singletons.
1765+ val (qpChunks, singletons) = chunks.partition(_.singletonArguments.isEmpty)
1766+ fallback(qpChunks) ++ singletons
1767+ }
1768+ }
1769+ }
1770+ }
1771+
17401772 def extractHints (cond : Option [Term ], arguments : Seq [Term ]): Seq [Term ] = {
17411773 var hints =
17421774 arguments.flatMap {
0 commit comments