Chris Eidhof posted a piece of code like this on his Tweets yesterday, which he believes is a Swift bug. tweets
Review images
Recently I was watching Swifter — Swift Essential Tips (3rd Edition) by Meow God, and I happened to see literal expressions and patterns matching. So I also want to try to explain the cause of this bug.
Literal expression
What is a literal? In Swift we assign variables as follows, where 3, Hello, and true are literals.
let aNumber = 3
let aString = "Hello"
let aBool = true
Copy the code
In the code above HasPrefix the struct inherits ExpressibleByStringLiteral the agreement, it supports the literal expression. That is, HasPrefix can now be assigned as follows:
Pattern matching
I won’t explain the use of pattern matching here. Open the SwiftGG series for pattern matching:
It is worth mentioning here that Swift uses ~= to represent the pattern-matching operator. (because this is related to the bug discussed in this article) the above code overrides the ~= operator so that HasPrefix supports pattern matching.
Emergence of a problem
(Here is my own interpretation of the question, and feel free to insult me if I don’t understand it.)
From the print of the Playground above we can see that the code executes ~=. In other words, a pattern match was made.
The ~= rvalue is a HasPrefix, and the switch part of the code is two strings.
Review images
Recall what the code did with HasPrefix above? This allows us to simply assign String to HasPrefix.
guess
- With Switch Swift takes precedence over pattern matching
- It’s not implemented in Swift, right and left
String
的~ =
。 - Because of what we use
Literal representation
When using the Switch,String
The literal of “, “can also beHasPrefix
The literal value of. - Finally, pattern matching is performed
To verify this guess, I try to overload the ~= values of both the left and right strings.
This time the problem seems to go away.
Thinking 🤔
What if I want to pattern match HasPrefix?
Review images
It seems to be the only way…
Are we likely to encounter such pits in daily development?
Suppose we introduce a third-party library that implements literal representation and pattern matching for a type that it defines. It looks like we’re about to hit this hole.
The solution
- Maybe it’s something like that definition I just gave you
~ =
But I’m not sure there’s anything else I can’t think of - If you don’t want pattern matching, you use
if
(Ps: It feels safer to do so)
Welcome to discuss, criticize and point out mistakes.