> struct Base { };
> void f(Base~ x) { }
> struct Derived : Base { };
> void g() {
>   Derived d;
>   f(reloc d);
> }
> Who is responsible for the destruction of the parts added in Derived
> when it is relocated to a Base?

This code would not compile. reloc returns the newly built instance directly, not a relocation reference. As such f(reloc d) is equivalent to f(Derived{const_cast<Derived~>(d)}), and this cannot be cast into the relocation reference parameter for f.
The reason things are designed this way is that it simplifies many things:
- it avoids object slicing.
- if we can make relocation to avoid the destructor call, then we will have a hard time tracking whether relocation references would make their way into a relocation constructor, so we can avoid the destructor call.
- we deter users from storing relocation references (or doing other insane stuff), since those references are never exposed by reloc.

Stating that reloc returns the new instance simplifies several things. We can rely on mechanisms such as copy elision or other language rules to make sure that the temporary object returned by reloc is almost always optimized out.

Best regards,