In C++11, value parameters (and other values) enjoy implicit move when returned:
A func(A a) {
return a; // uses A::A(A&&) if it exists
}
This was fixed for C++20 by P0527 and P1825. The only way to have a function parameter bind to an rvalue reference is for the source to either be a temporary or for the caller to explicitly cast a non-temporary to an rvalue (for instance, with std::move). Therefore, this "mandatory optimization" was deemed safe.