Because returning a name of an object with automatic storage duration is treated as returning an rvalue of the object. Note this works only if the expression in the return statement is a (possibly parenthesized, not including braces) name, like return u; or return (u);, so return {u}; works as usual, i.e. the copy constructor is invoked.
Related part in the standard [class.copy.elision]/3:
In the following copy-initialization contexts, a move operation might be used instead of a copy operation:
- If the expression in a return statement ([stmt.return]) is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, or
- …
overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.