These kinda-sorta fall under borrow checking or regions, just without any annotations. Then again, Ada/Spark's strategy also technically falls under Tofte-Talpin regions:
What’s the difference? Is the language stricter, disallowing some constructs that are valid, but hard to prove or is the error not always triggered for buggy code?
The reverse is arguably the one trait Rust is missing that is holding it back from mass adoption. You can write high-level C# code and seamlessly introduce low-level concepts into it as you see fit. However, although you can write low-level Rust code easily, introducing high-level concepts is very painful and, in many cases, impossible.
As of now - F# needs more work w.r.t. support for [<Struct; IsByRefLike>] types and byref<'T>s. There's a reason ref lifetime analysis in Roslyn is quite a sophisticated part of its implementation even if most developers aren't aware of it.
F# has other cool features like `inline` bindings and [<IlineIfLambda>] function attributes but I found it more difficult to work with for systems programming when attempting to stay within safe constructs.
With that said - F# is an incredible language, but for systems programming you are likely to get better results in C#. I hope eventually someone contributes subsequent spec and compiler work to change this (and if you think you have time and could try it - please do! it's a nice small community).
https://em-tg.github.io/csborrow/
These kinda-sorta fall under borrow checking or regions, just without any annotations. Then again, Ada/Spark's strategy also technically falls under Tofte-Talpin regions:
https://www.cs.cornell.edu/people/fluet/research/substruct-r...