On Tuesday, 8 September 2015 at 20:55:35 UTC, Timon Gehr wrote:
On 09/08/2015 06:49 PM, Jonathan M Davis wrote:
Sure, it _could_ be implemented that way, but the only reason I
see to do that is if we're specifically looking to support defining overloaded operators outside of the types that they apply to. I can't
think of anything else that would be affected by it.
...

The compiler does not match the specification. I see no reason to change the specification here, but it would be easy.

I don't know where you get this idea. The spec says _nothing_ about UFCS applying to overloaded operators or that UFCS would apply to lowered code in any way shape or form.

Regardless, I honestly think that it would be a very bad technical decision to support defining overloaded operators outside of the type itself - _especially_ when you take into account operators that have defaults generated by the compiler (e.g. opEquals), since that would allow a third party to change what your code does by adding their own
overloaded operator.

Well, how? "Overloaded operators" are just specially named functions that support an additional call syntax. There are no strange issues with modularity that somehow only apply to overloaded operators. UFCS calls can never ignore methods of the type. It does not matter how they were generated. Was this your strongest point against having the compiler combine UFCS and operator call syntax in the straightforward fashion?

There would be no way to disambiguate overloaded operators if an operator were overloaded in multiple modules. foo + bar has no import paths involved in it at all. So, what would you do, write opBinary!"+"(foo, bar) instead? That's downright hideous, and it relies on you using the function call to emulate the operator correctly. For something like bar++, you'd be even more screwed, because it doesn't lower to a simple function call.

UFCS is already enough of a problem on its own. It has some benefits, but it doesn't work when conflicts come into play, forcing you to just call the function normally, and its overload rules are such that it doesn't actually prevent hijacking in all cases (e.g. your code could suddenly change behavior, because you used UFCS with a type that then had a function with the same name and parameters added to it). And overloaded operators are closely tied to what a type does, whereas functions are far more diverse. So, there's a lot more to be gained with UFCS than with declaring overloaded operators separately from a type. I really don't see any reason why it would even make sense to declare operators separately from a type. So that you can declare multiple overloads of it for when you import different modules? That would just be plain confusing and incredibly error-prone. And if the problem is that you're dealing with someone else's type, then just declare a function to do what you want and be done with it. And do you really want people to be able to overload stray operators for stuff like strings and then write code that uses + and - and / or whatever on them? That would be ludicrous. It's one thing for people to do that with their own types. It's quite another to do that to built-in types or to someone else's types. What do you want next? To be able to declare constructors for someone else's type? That kind of stuff is part of the type, and allowing 3rd parties to declare it as well just makes it that much harder to figure out what's going on. At least when using UFCS, it's the exception that the function is on the type, so the overload rules don't usually shoot you in the foot (though they can), and you know to look elsewhere for the function just like you would with a function that was called normally. It's the complete opposite with operators.

We have overloaded operators so that someone who is writing a user-defined type can make it act like a built-in type where appropriate. Allowing 3rd party code to declare overloaded operators for a type doesn't help with that at all.

There is _nothing_ in the spec which supports UFCS having anything to do with overloaded operators and nothing to support overloading operators separately from a type. And I recall Walter Bright stating that it was on purpose that you can only overload operators on a type. So, even if the spec _could_ be interpreted to mean that you should be able to declare overloaded operators separately from the type that they apply to, that's _not_ its intention, and you're going to have to convince Walter if you want anything else.

- Jonathan M Davis

Reply via email to