Why isn't it a compile-time error to return a nullptr as a std::string?

Yes, your assumption is right, checking std::basic_string constructors #5 will be called:

basic_string( const CharT* s,
              const Allocator& alloc = Allocator() );

Note that passing nullptr invokes undefined behavior as stated in the standard and the notes :

The behavior is undefined if [s, s + Traits::length(s)) is not a valid range (for example, if s is a null pointer).


Why shouldn't it compile? std::string has the following constructor:

string(const CharT* s, const Allocator& alloc = Allocator());

that constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The constructor is not explicit, so the implicit conversion from nullptr to std::string is indeed possible.