Lifetime annotations look alien the first time: &'a str, fn foo<'a>(...). Let's decode the syntax so it stops being scary.
Reading 'a
An apostrophe followed by a name is a lifetime parameter: 'a reads 'lifetime a.' It's a generic parameter, just like T is for types — it stands for 'some region of code,' and the compiler fills in the concrete region at each call. &'a str means 'a reference to a str, valid for the region 'a.'
Declaring before using
Just like type generics, you declare a lifetime in angle brackets before you use it: fn foo<'a>(x: &'a str). The angle-bracket part introduces the name; the &'a str uses it. This is exactly parallel to fn foo<T>(x: T) — lifetimes are generics over regions instead of over types.
'a, 'b, 'life — the letters mean nothing on their own. What matters is which references share the same lifetime name, because that's what ties their validity together.What an annotation promises
When you write two parameters with the same 'a, you're telling the compiler: 'treat these as sharing one region — the output is valid only as long as both inputs are.' You're not extending or shortening any life; you're stating a constraint the compiler will then enforce at every call site.