If I as a programmer make a mistake and instead of marking a_slice with 'b I've marked it with 'a but reality is that it should be b, will the borrow checker let this code pass but the program will panic?
It's impossible to use a reference when its target doesn't exist anymore. The only time you'd need to make sure not to mess up your lifetimes for your program not to violate memory safety is when you are using unsafe code blocks. In your example you don't use unsafe, thus if you get the lifetimes wrong the code won't compile anymore.
I need to clarify my last statement a bit as it sounds like “wrong” lifetimes are always compiler errors and the Rust compiler always knows which lifetime annotations you need to write. To the point that people are wondering why you need to annotate lifetimes at all and why the compiler is annoyingly hesitating in telling you the correct lifetimes even if it ought to already know them.
The compiler doesn’t already know the correct lifetimes for every function in advance and it is still possible to get lifetime annotations wrong (in unsafe-free code), but never in a way that compromises memory safety. They can be wrong in the sense that they are not general enough, the consequence would be that your API becomes hard or impossible to use. It is not any memory-corrupting runtime-errors you need to worry about when writing lifetime annotations but the compile-time errors that users of your code might get. When you are your own user, this means that the compiler could complain about the code near the use site of a function while the real (and actually fixable) error was made in the lifetime annotations of the definition of that function.
In your example code, you could just try to mess up the lifetimes yourself and see when you’ll get a compile error. No need to ask anybody about what the compiler will tell you when you can ask the compiler yourself.
Lifetimes have no effect whatsoever on the (runtime) behavior of your code. They are a contract, a promise you make when you're writing a function to uphold certain relationships. The borrow checker just determines whether you're holding up your end of the deal or not. There are basically three ways to get lifetimes "wrong":
You promised too much and failed to deliver. You get a compile error inside some. (This is what happens if you change a_slice to type &'b str in your example)
You promised too little. You delivered on it, but the contract was useless because the caller needs to rely on something you didn't specify. You get a compile error at the call site of some. This mistake can be harder to fix because it can cause errors in multiple other places, and it's not always obvious that the problem is actually in some.
You promised too little, but (in this case) it didn't matter because the caller wasn't relying on the actual behavior of some, so the weak promise was sufficient. Everything compiles and works. Next week you write another function that tries to use some, but wants to rely on the promise you meant to make, and you get a compile error in that function instead. Fortunately, because you underpromised in some, you can fix this without breaking existing code.
#1 is the easiest to deal with. #2 and #3 are hazards you can fall into when you follow the compiler guidelines too literally, which is why you need to understand the lifetimes in your code and not just always take the compiler's advice.