uintptr_t x = opaque((uintptr_t)p);
free((void *)x);
free(p);
How will you find such violations if opaque comes from so or some ffi, so compiler can't see through?
you can't. It's heuristics. Sound type system is much stronger
I mean you can annotate it if you want. Just tell the analyzer in a separate file, get the variable at this line on this file has these guarantees.
You could even annotate dependencies that didn't use your static analyzer. You could track custom invariants that your language designer didn't put in the type system.
Which is why every library that wraps C APIs provides safe wrappers that express the implicit expectations within Rust's type system. Yes the low-level calls are unsafe, of course they are, but then we expose them with a safe interface that consumers actually use.
How will you find such violations if opaque comes from so or some ffi, so compiler can't see through? you can't. It's heuristics. Sound type system is much stronger