It sounds like you get it now. In the reference case, NLL and the fact that references have trivial destructors are what allows it to compile.
Technically b1 still goes out of scope ("drops") after b2, but the borrow checker knows that b1 can't observe a when it goes out of scope, so the borrow of a can still end before b1 goes out of scope.
The presence or absense of a non-trivial destructor, such as a Drop implementation, is key.
No it doesn't. Values aren't dropped eagerly upon their last use. NLL does consider the last use for borrow checking reasons, but dropping is never implicitly moved around. This is because dropping is very much an observable effect.
This is fundamentally why the two snippets differ in their behavior. RefCell's guard types are Drop so they can't be assumed by the compiler to be unused any earlier than the end of their scope.
Alas, library types can't be used for modeling everything that the built-in analyses of the language do, and you'll have to live with this. Insert explicit drops if you need different behavior.