Well, that’s exciting. I used Books to download
Develop in Swift Explorations and then, an page 11, clicked “Download student materials”. In the resulting directory I opened
Types.playground and then, on the
Type Safety page, I uncommented line 10, that is:
Code Block | //"banana" + 1 |
Like you, I’d expect this to yield an error. Moreover, when I put that line in a new playground it
does error. There’s something about the context of this playground that’s causing the problem.
To investigate this further I first deleted all the other playground pages, just to make sure there wasn’t some cross talk going on. That didn’t help.
I then went into raw mode (Editor > Hide Raw Markup) and deleted everything except the problematic line. Still no dice.
I then deleted
Sources/SimpleFileIO.swift and that fixed the problem, that is, once I deleted that file the uncommented line generated an error.
Some trial and error reveals that this is the root of the problem:
Code Block | extension Int: ExpressibleByStringLiteral { |
| public typealias StringLiteralType = String |
| public init(stringLiteral: String) { |
| var value = 0 |
| if let represented = Int(stringLiteral) { |
| value = represented |
| } |
| self.init(value) |
| } |
| } |
This extends
Int so it can be expressed by a string literal. So, here’s what’s going on:
Swift is looking for a way for "banana" + 1 to make sense.
It has two overloads on +, one that takes two Int values and one that takes two String values.
The String overload is useless but the Int overload can work if it can convert "banana" to an Int. And that’s exactly that this extension allows it to do.
So, there’s a bunch of lessons here:
This is clearly a bug in the playground and I recommend that you file a bug report about that. Please post your bug number, just for the record.
Swift lore is that you should not extend types you don’t ‘own’ (Int in this example) to conform to protocols you don’t own (ExpressibleByStringLiteral), so this was never a good design choice.
Even if you ignore that, the implementation of this extension makes no sense. When you implement one of these ExpressibleByXxx protocols, you should not fail silently (in this case returning a default value of 0) if the literal is malformed. Rather, you should crash out (with a fatalError) because a malformed literal is obviously a programming error. Changing the code to do that would’ve made this problem much easier to find.
As to how you should work around this, the obvious choice here is to remove that extension from
SimpleFileIO.swift. Unfortunately I don’t know enough about the playground to see whether that’ll have collateral damage. You should do that, and then work through the playground to see what else breaks.
If you hit a problem you can’t resolve, post the details here and I’ll take a look.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"