# Hiding local proofs with `assert(...) by { ... }` ## Motivation Sometimes, in a long function, you need to establish a fact `F` that requires a modest-size proof `P`. Typically, you do this by `...; P; assert(F); ...`. But doing this comes with a risk: the facts `P` introduces can be used not only for proving `F` but also for proving the entire rest of the function. This gives the SMT solver much more to think about when proving things beyond `assert(F)`, which is especially problematic when these additional facts are universally quantified. This can make the solver take longer, and even time out, on the rest of the function. ## Enter `assert(...) by { ... }` Saying `assert(F) by {P}` restricts the context that `P` affects, so that it's used to establish `F` and nothing else. After the closing brace at the end of `{ P }`, all facts that it established except for `F` are removed from the proof context. ## Underlying mechanism The way this works internally is as follows. The solver is given the facts following from `P` as a premise when proving `F` but isn't given them for the rest of the proof. For instance, suppose `lemma_A` establishes fact `A` and `lemma_B` establishes fact `B`. Then ``` lemma_A(); assert(F) by { lemma_B(); }; assert(G); ``` is encoded to the solver as something like `(A && B ==> F) && (A ==> G)`. If `B` is an expansive fact to think about, like `forall|i: int| b(i)`, the solver won't be able to think about it when trying to establish `G`. ## Difference from auxiliary lemmas Another way to isolate the proof of `F` from the local context is to put the proof `P` in a separate lemma and invoke that lemma. To do this, the proof writer has to think about what parts of the context (like fact `A` in the example above) are necessary to establish `F`, and put those as `requires` clauses in the lemma. The developer may then also need to pass other variables to the lemma that are mentioned in those required facts. This can be done, but can be a lot of work. Using `assert(F) by { P }` obviates all this work. It also makes the proof more compact by removing the need to have a separate lemma with its own signature.