It is because returning a value is considered an implicit conversion.
Quoting from the C++11 standard:
6.6.3 The return statement
2 [...]
A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function. The value of the expression is implicitly converted to the return type of the function in which it appears. A return statement can involve the construction and copy or move of a temporary object (12.2). [...]
The conversion from the return expression to the temporary object to hold the return value is implicit. So just as this would result in an error
Foo f = Foo(); // Copy initialization, which means implicit conversion
having code as your example would also trigger a similar one.
Question 1: Why does the compiler need the copy-ctor of Foo? I expected the return value of bar to be constructed from the rvalue Foo() with move-ctor.
It is because Foo(Foo&&)
is not a viable overload, because of the reasons above. The rules state that whenever the move constructor cannot be used, it is when the compiler shall then consider the copy constructor, which, in your case, is implicitly deleted due to the presence of a user-defined move constructor.
Question 2: Why the compiler does not need copy-ctor any more when I redeclare the move-ctor as implicit?
It is because your move constructor can be used now. Thus, the compiler can immediately use it without even considering the presence of the copy constructor.
Question 3: What does explicit keyword mean in the context of copy and move ctors as it definitely means something different from from the context of regular ctors.
IMHO, it doesn't make sense, and it only leads to problems, just as in your case.