One of the tenets of Rust is Local Reasoning, both for static analysis (compiler) and human reader.
This is why function signatures are so specific, and potentially verbose, with:
- Types for every argument, and return type, explicitly spelled out.
- Constraints explicitly spelled out (on generic code).
- Lifetimes annotations.
The latter is subject to Lifetime Elision rules, as syntactic sugar, but those rules are themselves strictly limited to the signature of the function.
The end result is that there is never a need to peek inside the function to perform semantic checks.
Note: on the other hand, with -> impl Trait
, code generation needs to peek inside the function to know the exact type; it's not about reasoning though, so it gets a pass.