Eliminate redundant computation in VC experession translation #1009
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR is in response to issue #993 which uncovers unexpected long-running execution during the translation of a large Expr into a VCExpr. My intuition suggested that the expression translation should do linear work unless the expression being translated involves deeply nested inlined function calls. Linear complexity would not exhibit the behavior being seen since the example does not have deeply nested function calls.
The root cause appears to be a piece of code that examines the current term substitution whenever the translation scope crosses a binding (let-binding or quantifier). This examination is done to collect free variables in the substituted expressions to check whether they might collide with the bound variables in the binding about to be translated. In the example, the function ConcatVec is being invoked with increasingly larger expressions for its arguments which makes the substitution mapping formals to actuals increasingly larger. There is a let binding inside ConcatVec which triggers the examination of the increasingly larger substitutions. This ultimately leads to quadratic complexity in translation.
I concluded that the collision detection is unnecessary because it will never detect any collisions in the scenarios where it is being invoked. The substitutions should never refer to the bound variables of the binding being translated. To test my understanding, I ran the Boogie tests with a Debug.Assert capturing my hypothesis. All tests passed.
This PR removes the redundant collision detection code.