Apparently, the System Preferences window on my computer running OS X El Capitan was considerably wider than 668 (or even 595) pixels. Some research later it turned out that the width of the System Preferences window depends on the system language: The window will be 668 pixels wide when English is the primary language, but will have a different width for other languages. For example, with German set as primary language, as it is on my computer, the window is 762 pixels wide.
While Apple’s preference panes that come with OS X dynamically adjust their width to the actual width of the System Preferences window, this is not true for any custom preference pane, that will instead be displayed centered with more or less wide blank margins.
Notice how this URL does not contain a hash (at the end). If you visit this URL, a hash will be added to the URL after the page loads. The hash value is some jumbled combination of letters and digits. What’s the purpose of this hash?
The idea is that when you share that page you will share it with the hash at the end. The visitors of the link you share will have their own hash generated to track their referrals. Medium will be able to see who visited the link that you shared, and build a tree of referrals (who the users you referred shared it with, who they shared it with etc). It’s a great metric to use in analytics when looking at user acquisition through social channels.
I hate this, I can’t tell you how many times I get a duplicate bookmark because I thought I didn’t have the article already in my bookmarks.
But the line doesn’t get past the Swift type checker. Instead, it emits an error that the expression is too complex to solve. It doesn’t look complex, does it? It’s 5 integer literals, 4 addition operators, two negation operators and a binding to a
How can an expression containing just 12 entities be “too complex”?
If you don’t typically combine these features in your code, then you’re unlikely to see the “expression was too complex” error. However, if you are using these features, it isn’t always straightforward to suddenly stop. Mathematics code, large “function”-style expressions and declarative code are easier to write with these features and often require a complete rethink to avoid them.
A note about this approach though: unlike other languages,
Double(x)is not equivalent to
x as Doublein Swift. The constructor works more like another function and since it has multiple overloads on its parameter, it actually introduces another overloaded function into the search space (albeit at a different location in the expression).
Posts like this: “[swift-dev] A type-checking performance case study”, indicate that the Swift developers believe resolving function overloads in the type checker is inherently exponential. Rather than redesigning the type checker to eliminate exponential complexity, they are redesigning the standard library to try and skirt around the issue.
Changing stdlib interfaces is done with an eye toward fixes like SE-0091 that mitigate inherently exponential work.
Most of the proposals around function labels and types are trying to kill type checker tech debt too.
“Rewrite the type checker” is up there on list of things we want to do.
I’m going to attempt to start by giving an overview of how types work in Swift, from the parser down to the lower layers of code generation in the frontend. Swift is a strong, statically-typed language with an advanced type system more reminisicent of functional languages such as OCaml and Haskell than something like C, so this seems like as good a place to start as any.
Types in Swift form a mini-language in of themselves, with a grammar consisting of nominal types as leaves, and structural types such as function types as interior nodes. Types are formed from TypeLocs and TypeReprs early on in semantic analysis. Further down in the compiler, sugar is removed and types are canonicalized, simplifying structural walks and equality comparisons. Substitution is a fundamental operation frequently used in the implementation of generics, and it is important to think about the role of types and declarations when performing substitutions for member access. Various higher-order operations simplify tedious boilerplate when manipulating types throughout the compiler.
Now, let’s peel back a layer and dive into the type system of SIL, the Swift Intermediate Language. SIL adds a layer of detail missing from formal types, drawing a distinction between values and addresses, and making function types more explicit by introducing explicit annotations for argument and return value conventions.
At this point, we still cannot compile our code, but at least we can detect a type mismatch at the level of SILFunctionTypes, instead of just mis-compiling incorrect code. A situation where the formal types of the expressions match, but the lowered types do not is called an “abstraction difference”. Abstraction differences are handled by SILGen wrapping the substituted function value inside a re-abstraction thunk.
The re-abstraction thunk forwards arguments, calls the function, and forwards the result, taking care to handle any abstraction differences in the arguments and results. If the substituted argument is trivial but the original argument is passed indirectly, the thunk will load the value from its address and pass it to the substituted function. Similarly, if the substituted result is trivial but the original result is returned indirectly, the thunk takes the substituted result value, and stores it into the indirect return address given to the thunk.