Let's deprecate user changes to standard library operator precedence

Did it occur to you that you can change the precedence of existing standard library operators? I did not, until the possibility was raised in another thread—and I don't think intentionally. Literally, you can just...change how math works:

precedencegroup TestPrecedence {
  associativity: left
  higherThan: MultiplicationPrecedence
}
infix operator - : TestPrecedence

print(7 - 3 * 2) // 8 (Yup.)

Now, I get that this flows naturally from our basic design principles. The standard library is just another library, and your own code should be allowed to shadow standard library code. I even agree with that in principle.

Someone might inadvertently change the precedence of a standard library operator because they think they're only doing it for their custom implementation of that operator, not everything else also. Or, they might do it for a bit of fun (or malice) to vex their coworkers. But to truly need to change the precedence of a standard library operator?

If Swift is to live up to being an "opinionated language," we can surely render an opinion that that's unwise. Without necessarily making existing code stop compiling, I think a warning is in order, no? This feels like a footgun that's custom made for feet.

11 Likes

Rather, we should prohibit operator redeclaration if it's already in scope (and - most definitely is), and fail to compile if multiple (ambiguous) declarations exist at the use site.

4 Likes

This has been discussed before: There is no harm to redeclare an operator in the exact same way it's been declared elsewhere, and due to shortcomings currently with library imports and how operators come into scope, identical redeclarations can happen with custom operators. There is no reason to prohibit what's not causing harm at the present time, and I don't think we need to revisit that discussion as part of this one.

Or, if we don't want to disallow redeclaration, would it be possible to fix a given implementation of an operator to the operator declaration that is most visible at the point of declaration of the implementation?

I.e., the standard library operator implementations would use the standard library operator declarations, but you could still redeclare an operator and any implementations that you provided would use the redeclaration?

Do you have a link? Might have missed that one.

I think you'd want to be able to justify a use case for a more elaborate scheme such as this--not that it's necessarily less good if we were to design operators out of whole cloth.

But without widening the scope of this project, the harm that I've illustrated above seems adequately addressed by a simple warning and no source breaking changes at all.

I'm more interested if there are any opinions against such a change because someone is making use of this...somehow.

2 Likes

Believe it or not, I don't have a database of links for every topic ;)
I'd have to dig with the search function the same way as you, and it's not coming up very easily. I'll certainly share it if I stumble across it.


Functionally, what I'm proposing is similar to banning operator redeclarations, just scoped specifically to standard library operators and only as a warning, and only when the precedence is changed. I would be very happy with that because, as I say above, it accomplishes the job with minimal (i.e., no) breakage.

1 Like

Managed to track down one, but it's not very substantial: String Comparison (was: Strings in Swift 4) - #2 by xwu

1 Like

Yea, I totally understand that. I've done it a few times. They're almost never easy to find. Just that you've been part of that discussion before, while I have no memory of it, so you might have better luck or know a few more keywords than I do.

If we really can't find it, I think we can't help but to rehash them.

1 Like

Indeed.

One can also write things like these:

enum Int {}
let String = Void.self
var print = ""
let FloatLiteralType = 4

Of course these are all ridiculously silly things to do, but I see no benefit from banning them, and the same applies to changing operator precedences.

4 Likes

It's plausible (i.e., in the linked thread, it happened) that someone might unwittingly attempt to repurpose an existing operator for different types, not realizing that some of our more esoteric operators already exist. Intrigue ensues. For these folks, a warning is nice, and we can provide one here to help them out.

As to the bigger picture about your other ridiculously silly examples, there is no need to ban them unless they're causing harm, but I would be in support of providing some helpful diagnostics where the ridiculously silly intersect with the unwittingly plausible.

1 Like

How would one disable them, though?

Implied here is that disabling the warning would require making your own operator. The point of this thread is to figure out if anyone genuinely needs this feature; if not, then no other way of disabling the warning is necessary.

1 Like