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:

Review images

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

  1. With Switch Swift takes precedence over pattern matching
  2. It’s not implemented in Swift, right and leftString~ =
  3. Because of what we useLiteral representationWhen using the Switch,StringThe literal of “, “can also beHasPrefixThe literal value of.
  4. Finally, pattern matching is performed

To verify this guess, I try to overload the ~= values of both the left and right strings.

Review images

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 useif(Ps: It feels safer to do so)

Welcome to discuss, criticize and point out mistakes.