I know this exists: https://www.pm.inf.ethz.ch/research/prusti.html
But I've never used it (it's not friendly to use). But lately I've used some times the WhyML language: http://why3.lri.fr/
I convert a (simple, not parallel, not concurrent) Rust function to that ML variant (and this is easy enough to do), then I (very slowly) add annotations (and sometimes I modify the code a little to make it more fit for the static analysis) to prove some of its functional proprieties. LLVM is able to remove few array bound tests, but not all of them. So I use Why3 to prove those array/slice accesses are always in-bound. This doesn't prove that the array accesses in the original Rust code is correct (because translation by hand introduces some bugs) but it's still good enough. In some cases if my brain works well enough I try to prove some other functional propriety of the code (often the limit is my skills and my patience, it's not Why3)
In Python3 they added "type hints", they do nothing: https://docs.python.org/3/library/typing.html
They give a nice syntax that extenal programs (like MyPy, Pyre, Pytype, and the PyCharm editor) use to perform static type checking. The type hints syntax helps to avoid the decorated comments usually used where there isn't a specific syntax, like {-@ ... @-} in LiquidHaskell ( https://ucsd-progsys.github.io/liquidhaskell-blog/ ) and so on, and to avoid the need to use the "compiled" (type annotations stripped) version generated like by TypeScript.
After a while it's possible to fold the external program inside the interepreter (and to run it optionally) if there's enough consensus and desire.
A disadvantage of having a built-in syntax for the external static analyzer is that it freezes the kind of static analysis you usually want to perform in your programs. If you introduce syntax for type predicates like LiquidHaskell and WhyML ones then later you probably can't use that syntax for very different things like dependent typing. 10-15 years from now if the preferred way to prove some correctness of the code will be like LiquidHaskell.
Still, refinement typing isn't controversial stuff, I think it will last some time. So what do you think about introducing in Rust some nice built-in syntax (that gets ignored as Python3 type hints) to be used to verify the code with external programs?
I am thinking about:
lemma {}
requires {}
invariant {}
ensures {}
variant {}
measure fn
predicate fn
Plus just inside the logic formulas it's also allowed:
->
<->
forall
exists
Old()
I think this amount of syntax could cover 99% of future usages of refinement typing (and all contract-based programming, see in C++: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0542r0.html it also introduces "audit" and "axiom", that I have omitted in Rust because the purpose is different).