It's still too confusing. Try drawing actual pictures to illustrate the scope/lifetime issues. Talking about addresses on the stack is an implementation
detail.

Things to cover:

Basic lifetime concepts in Rust:

1. Scopes are nested.
2. Variable lifetimes are tied to scopes.
3. Unlike other languages, variables can be created
tied to a scope outer to the one where they are
created. The user can control this by indicating
that the lifetime of a variable is the same as that
of some variable from an outer scope. This is Rust's
big innovation.
4. A function can create a new object and return it by
reference if the function explicitly says that the
new object has the same lifetime as some parameter.

Basic ownership concepts in Rust:

1. There are three kinds of ownership - single ownership,
reference count multiple ownership, and thread-safe reference
count ownership.
2. The reference count ones work like you'd expect.
3. Single ownership interacts with the lifetime system in
to make it possible to create data structures such as
trees, with all components single ownership and having the
same lifetime.
4. The "=" operator usually means "move", and when it does,
the right hand side of the "=" becomes inaccessable.
(This is type-dependent; some types copy when "=" is used.)
This preserves single ownership.

Basic data structure concepts in Rust:

1. Rust has enums, which, unlike enums in other languages, can
have data objects associated with them. They're really variant
records.
2. You can declare an enum with a data object as a field in a
structure. This creates a structure that contains (really links
to) another data object.
3. This can be done recursively, so you can create trees of
structures.
4. You can't violate the rules of single-ownership. Trees are OK;
directed acyclic graphs or backpointers are not allowed using
single ownership.
5. There's no "Null". Instead you create enums which have one value
with an associated data item and one without.
6. Everything has to be initialized to a valid value for its type.

Basic borrowing concepts in Rust:

1. You can create temporary references to something with an equal
or longer lifetime, because the temporary "borrowed" reference
cannot outlive the thing it is referencing. That's safe.
2. You can have one writer (a mutable reference) or N readers
(immutable references) at a time.

Basic type concepts in Rust:

1. It's complicated.
2. There's automatic type inference. Not just for "let", either.
3. Function parameters have to be declared, not inferred,
except for the special syntax for closures that lets you write
concise lambda expressions. This limits how hard the
type inference system has to work.
4. I don't fully understand Rust's type system yet.

Basic safety concepts in Rust:

1. All of the above is enforced at compile time.
2. The result is memory safety.

Misc. notes:

- Lifetimes are novel, but not that complex.
- The type system really is complex.
- There are generics and you'll need them more often than in C++.
- The compiler first checks syntax, then types, then borrowing. It does not report
borrow errors until everything else is correct.
- There are no exceptions, and proper error handling requires rather verbose code.
- Have a plan for your variable lifetimes before you start coding, or you end up
fighting with the borrow checker and losing.
- If you think you need "unsafe" in pure Rust code, you're doing it wrong.