It depends on the compiler. In this case, the standard requires that there will be at least one constructor call. Namely, the construction of t.
But the standard allows the possibility of two others: the move-construction of the value output of foo from t, and the move-construction of s from the value output of foo. Most decent compilers will forgo these constructors by constructing t directly in the memory for s. This optimization is made possible because the standard allows these constructors to not be called if the compiler chooses not to.
This is called copy/move "elision".
If so, in the function I am not even returning rvalue reference, so how could the compiler invoke the move constructor?
You seem to be laboring under the misconception that && means "move", and that if there's no && somewhere, then movement can't happen. Or that move construction requires move, which also is not true.
C++ is specified in such a way that certain kinds of expressions in certain places are considered valid to move from. This means that the value or reference will attempt to bind to a && parameter before binding to a & parameter. Temporaries, for example, will preferentially bind to a && parameter before a const& one. That's why temporaries used to construct values of that type will be moved from.
If you have a function which returns a value of some type T, and a return expression is of the form return x, where x is a named variable of type T of automatic storage duration (ie: a function parameter or stack variable), then the standard requires that this return expression move construct the returned value from x.
The return value of foo is a temporary. The rules of C++ require that temporaries bind to && parameters before const&. So you get move construction into s.