Array#join actually tries three coercions on elements: #to_str, followed by
#to_ary (for nested joins), followed by #to_s.

The separator is coerced with #to_str if it is not nil and not a
String. Note that this matters only for an explicitly passed parameter, as
assignment to $, is restricted to Strings and nil. I would favor lifting
this restriction, as the current coercion logic *is* applied to $, -- it
just happens to be a no-op given the assignment restriction.