Great explanation. The system also takes care of ownership moving around. In C you have functions that take a pointer to something, but you don't know who owns it (and is responsible for cleaning it up) after the function call, unless that is made explicit in the description. In Rust if you've moved ownership you can't use it in the caller afterwards, and if you haven't moved ownership you can't use it in the callee after the function has finished (this system is called borrowing, and is why the system that deals with lifetimes is called the 'borrow checker').
Actually there is another way which you'll find commonly in well written robust libraries - make the argument a const pointer, so that the callee is obviously not responsible for clearing it up and then the callee takes a copy to keep. This also allows passing both const and non const data to the same function, and means that there is much less likely to be an ownership screq-up across a library boundary. As a pattern though it can result in a lot of unnecessary copies, which Rust's system allows you to avoid.
The checker in the compiler was being too conservative, because it was easier to write a conservative one. That means that sometimes it would complain about cases that were actually just fine. The language doesn't specify that lifetimes are tied to lexical scope, that's just what the borrow checker was using as a shortcut. The new one will be more specific.
This is sort of true, but also not: it wasn't that it was easier to write a conservative one, it's that analysis is inherently conservative, and so we chose lexical scope because, well, that's what most languages do.
The language generally does specify that they are, and that's exactly how we teach borrowing today. This new one is not more specific, but more general: it allows all programs today to stay the same, but enables more programs that don't compile today to compile in the future.
Actually there is another way which you'll find commonly in well written robust libraries - make the argument a const pointer, so that the callee is obviously not responsible for clearing it up and then the callee takes a copy to keep. This also allows passing both const and non const data to the same function, and means that there is much less likely to be an ownership screq-up across a library boundary. As a pattern though it can result in a lot of unnecessary copies, which Rust's system allows you to avoid.