virtual ~A() = default; is a user declared destructor. Because of that, A no longer has a move constructor. That means return tmp; can't move tmp and since tmp is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A no longer has a user declared destructor (Yes, C does but we only care about A) so it will still generate a move constructor in A. The important part of this is that C doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C's copy constructor is called in A's implicitly generated move constructor since C(std::move(A_obj_to_move_from)) will copy as long as it doesn't have a deleted move constructor.