Transcript
[ Music ]
[ Applause ]
>> Good morning and welcome to
What's New in Swift.
This has been an exciting year
for Swift and the Swift
Community.
And over the next 40 minutes
Slava and I are thrilled to give
you an update on the major
developments there.
The session is roughly broken in
to two parts.
First I'm going to give an
update on the Swift open source
project and the community around
it.
And then we'll dive into Swift
4.2, which is available as a
preview today in the Xcode 10
beta.
Since late 2015, Swift has been
an open source project on
GitHub.
With a vibrant community of
users who discuss, propose, and
review all changes to the
language and standard library.
In that time over 600
individuals have contributed
code to GitHub as Swift open
source project.
And together they have merged
over 18,000 pull requests.
Since Swift.org was launched
Swift has been available for
download on Swift.org both for
downloadable tool chains for
Xcode, as well as various
version of Ubuntu.
These are both development
snapshots and official releases.
Now we want Swift to be
supported on all platforms so
everyone can use it.
And a critical part of that is
extending the testing support
provided to the community.
Various folks in the open source
project are working on bringing
Swift support to other
platforms.
And we'd like to support those
efforts.
About a month ago we extended
the public continuous
integration systems to support
community hosted CI notes.
So if you are a member of the
community interested in bringing
Swift to another platform or
effort, you can now seamlessly
plug in your own hardware
support to bring testing there.
This is a nice prerequisite for
supporting Swift in other
places.
We've also invested tremendously
in the community around the
Swift open source project.
This is the community that
discusses all changes to the
language.
About six months ago we moved
from using mailing lists, which
were very high traffic to
forums.
This was at the behest of the
community.
Various people were concerned
that they wanted to be able to
engage in the project at a level
that worked well for them but
found it difficult to do so.
With the forums you can now
engage the level that works well
for you.
The forums have also worked so
well that we wanted to extend
their utility out to supporting
the general open source project.
If you maintain a Swift open
source project such as a popular
Swift library, you can now use
the forums for use to discuss
things on that project such as
discussions with your users or
development.
We've also looked at ways to
continue to extend Swift.org to
be of general use the community.
This week we've moved to hosting
the Swift programming language
book to swift.org.
Located at docs.swift.org, this
will be a natural place for us
to extend more documentation for
use by the community.
Now the really exciting thing
about Swift is that people are
really thrilled about using it.
And they're talking about it in
a variety of places.
At Podcasts, Meetups,
conferences.
And we, Apple, thought it was
very important for us to engage
in those places because that's
where a lot of the discussion is
happening.
Over the last year we have made
a very conscious effort to
engage in those conferences and
present technical presentations
on things that we're doing with
Swift, or how does Swift work,
or how you can get involved in
the open source project.
And this is something we're very
committed to continuing going
forward.
One of these efforts I'd like to
talk about is a event co-located
next to WWDC on Friday and that
is the try!
Swift San Jose Conference.
There there will be a workshop
with members from the community
to help on board people who are
interested in contributing to
the Swift open source project.
And there will be members from
Apple's compiler team there to
also facilitate those
conversations.
So that's all about the
community update.
Let's talk about Swift 4.2.
I think the natural place to
start is well, what is this
release about and how does it
fit into the bigger picture?
Swift updates occur -- some
major updates occur about twice
a year.
And Swift 4.2 is a major update
over Swift 4.1 and 4.0.
Now there are in broad strokes
two themes to this release.
One is a huge focus on developer
productivity.
You can see this in a variety of
ways.
The faster builds for projects.
But also just through and
through massive improvement to
the core tooling experience from
the Debugger through the Editor.
And the community has also
focused on language improvements
that aim to improve common
developer workflows, remove
boilerplate.
And Apple has continued invested
improvements to the SDK so that
the Objective-C APIs better
reflect into Swift making better
use of the language and
improving your use of our APIs.
And the other side there's been
a massive effort on under the
hood improvements and changes to
the runtime towards this binary
compatibility goal, which
culminates in Swift 5, which
will be released in early 2019.
So what is binary compatibility?
Binary compatibility means that
you can build your Swift code
with the Swift 5 compiler and
layer.
And at the binary level it will
be able to interoperate with
other code built with that
compiler or any other compiler
layer.
This is a very important
milestone for the maturity of
the language.
And what this will enable is
Apple to shift the Swift runtime
in the operating system, which
means apps can directly use it,
meaning that they no longer need
it included in the application
bundle.
So this is a code size win but
it's also important that it
impacts things like startup
time, memory usage, it's an
overall huge win for the
community.
If you're -- we've been very
transparent on the progress
towards ABI stability or binary
compatibility.
You can follow along on the ABI
stability dashboard on
Swift.org.
Today's focus is on Swift 4.2,
which is an important waypoint
toward Swift 5.
Let's talk about source
compatibility.
So just like in Xcode 9, Xcode
10 shifts with one Swift
compiler.
So if you're using Xcode 10, you
are using Swift 4.2.
However, just like in Xcode 9,
the compiler also supports
multiple language compatibility
modes.
Now in all the modes you can use
all the new APIs.
You can use all the new language
features.
What these gate are
source-impacting changes.
The first two are ones that
existed previously in Xcode 9.
They're there to provide an out
of the box experience that you
can build your Swift 3 and Swift
4 code without modifications.
The Swift 4.2 mode is almost
identical to the 4 mode except
it gates those SDK improvements
that are talked about.
That's it.
Just some previous versions of
Xcode, there's Migrator Support
that you can find in the edit
menu to mechanize most of your
changes.
I want to give an important
disclaimer about the Swift 4.2
SDK changes.
Later Xcode 10 betas will likely
have further SDK improvements.
This is to provide opportunities
to incorporate you feedback from
the betas of how these APIs
should be improved and how they
reflect into Swift.
This means if you migrate to 4.2
early, you should expect there
are going to be some changes
later.
Or you can hold off and migrate
later.
It's completely up to you.
Now with Swift 4.2 we think we
are rapidly converging on what
Swift code is going to look like
going forward.
This is an important phase in
the maturation of the language.
And thus we really think it's
important for everyone to move
off of Swift 3 and embrace using
Swift 4.2.
There are important code size
improvements there and just
overall improvements to the
language.
And this is Xcode 10 is going to
be the last release to support
that Swift 3 compatibility mode.
So let's talk about some
improvements to the tooling.
In the State of the Union we
mentioned that there are some
significant improvements to
build improvement for Swift
projects over Xcode 9.
And so these numbers are run on
a 4-Core MacBook Pro i7.
Let's look a little bit closer
at one of them.
This project is a mix and match
of Objective-C in Swift.
It started out as an Objective-C
project and started
incorporating Swift.
This is a very common scenario.
Now what this Build time
improvement doesn't really
underscore is how much faster
building this Swift Code
actually became.
So if we just focus on how much
faster the Swift code built, it
actually builds three times
faster than it did before.
And so that's why the project
has that more modest 1.6x
speedup.
And what you will see is that
the overall build improvements
will depend on the nature of
your project, how much Swift
code it's using, the number of
cores on your machine, but we've
in practice have seen from many
projects it's a 2x speedup.
And the win comes from observing
that because within a Swift
target you have cross-file
visibility, right, that's one of
the great features of Swift
where you don't need header
files.
There was a lot of redundant
work being done by the compiler.
And what we've done is we've
retooled the compilation
pipeline to reduce a lot of this
redundant work and make better
use of the cores on your
machine.
And that's where these speedups
come from.
If you're interested in more
details there's these two great
talks later this week that dive
into how the build process works
under the book including more
details about where this
performance win comes from.
Now this big win comes from
debug builds.
I want to focus on how this is
surfacing in the Xcode build
settings.
Recently we separated out
compilation mode from
optimization level.
Compilation mode is how your
project builds.
So for release builds the
default is whole module
compilation that means all the
files within your target are
always built together.
This is to enable maximum
opportunities for optimization.
It's not the amount of
optimization done but the
opportunities for optimization.
And for Debug builds the default
is incremental.
That means not all the files are
all built, re-built always all
together.
So this is a tradeoff in
performance for build times.
Optimization level for Debug
builds continues to be no
optimization by default.
This is for faster builds and
better Debug information and the
release builds are optimized for
speed.
We'll get back to the
optimization level in a few
minutes.
All right so this separation of
compilation mode and
optimization level nicely
highlights and interesting
stopgap measure that various
folds discovered that when they
combined whole module
compilation with no optimization
that they sometimes would get
faster Debug builds.
And this is because that
combination reduces a lot of
that redundant work that I
talked about before that we have
no made great efforts to
eliminate or significantly
reduce.
The problem with this
combination is, is it impedes
incremental builds.
So anytime you touch a file
within a target the whole target
gets rebuilt.
Now with the improvements in
Xcode 10 to Debug builds, we
feel you no longer need to use
the stopgap measure and we have
observed that the default
incremental builds are at least
as good as this combination or
better.
Especially since they support
incremental builds.
Let's talk about some important
under the hood runtime
optimizations and this is all
part of that march towards
binary compatibility.
Swift uses automatic memory
management and it uses reference
counting just like Objective-C
for managing object instances.
On this slide I've illustrated
in comments where the compiler
inserts, retains, and releases.
This is how it behaved in Swift
4.1.
When an object is created
there's a +1 reference account
associated with it.
What the convention was if the
object is passed off as an
argument to another function,
it's the obligation of that
function call to release the
object.
So it's basically you're passing
off the responsibility to the
call to release it.
This provided some performance
opportunities to shrink the
lifetime of some objects to like
their smallest range of use.
However, code often looks more
like this where you're passing
the object off several times to
different APIs.
And because you have this
calling convention, you still
have this dance where the
initial reference count is
balanced out with the final
call.
But the intermediate calls are
expected to have these extra
retains and releases because
that's what a convention is.
This is really wasteful because
the object is really just going
to be alive during the entire
duration of this function.
So in Swift 4.2 we changed the
calling convention so that it
was no longer the callee's
obligation to release the
object.
This means all these retains and
releases go away, which is a
significant reduction in
retained release traffic.
This has two implications.
It's both a code size win
because those calls are gone and
it has a runtime improvement.
Another important optimization
we did was to string.
And Swift 4.2 string is now 16
bytes big where it as previously
24.
We feel this is a good tradeoff
between memory usage and
performance.
It's also, however, still large
enough to do an important small
string optimization.
If the string fits within 15
bytes then the actual string is
represented directly in the
string type without going to the
heap to allocate a separate
buffer to represent the string.
This is obviously also a memory
win and a performance win.
This is as similar to an
optimization that exists within
a string.
We can actually represent larger
strings.
Finally before I hand it off to
Slava we'll talk about the
language improvements.
I want to talk a little bit more
about the efforts to reduce code
size.
I talked a little bit about that
calling convention change, which
reduces code size.
But we've also introduced a new
optimization level, Optimize for
Size.
This can be useful for
applications that care very much
about app size limits such as
from cellular over the air
download limits.
Swift is a very powerful
language with static knowledge
about what your program does.
And so compiler has many
opportunities to do performance
optimizations such as function
call inlining, speculative
devirtualization, which trade
off a little bit of code size
for more performance, but
sometimes that more performance
isn't really needed in practice.
This is the result of applying
Osize to the Swift Source
Compatibility Suite, which
contains an assortment of
projects from GitHub, frameworks
and applications.
And what you'll see is a wide
range depending on what language
features are used about 10% to
30% reduction in code size.
Now this, when I talk about code
size I'm talking about the
machine code that is generated
as a result of compiling your
Swift code, not the overall app
size.
The overall app size depends on
assets and all sorts of other
stuff.
In practice we observe that
runtime performance is usually
about 5% slower.
So you're trading off for a
little bit of performance.
For many applications this is
totally fine.
So it really depends on your use
case.
But if this is something you're
interested in we encourage you
to give it a try.
With that I'd like to hand it
off to Slava who will talk about
all the great language and
improvements with Swift 4.2
[ Applause ]
>> Hey everybody, I'm Slava
Pestov.
I work on the Swift Compiler and
today I'm going to talk about
how the new language features in
Swift 4.2 allow you to write
simpler and more maintainable
code.
So before we start talking about
the new language changes, let's
review the process for making
improvements to the language.
So as Ted mentioned, Swift is an
open source project, but it also
has an open design.
This means that if you have an
idea for improving the language,
you can go and pitch it on the
forums and if the idea gains
enough traction and crystalizes
into draft proposal, you can
submit it together with
implementation to the core team
for review.
At this point a formal review
period allows members of the
community to give additional
feedback and then the core team
makes a decision as to whether
to accept the proposal.
If you go to the Swift Evolution
website, you can see a list of
all the proposals that were
accepted and implemented in
Swift 4.2.
And if you look at this list of
proposals there's a lot here.
There's more than I can cover
today.
But one thing I really wanted to
emphasize was the large number
of proposals that were both
designed and implemented by the
community.
What this means is that these
proposals address common
pinpoints in the language that
came up in the real world and
you came up with the idea for
fixing these pinpoints and you
contributed these improvements
back to Swift so that everybody
benefits.
Thank you.
[ Applause ]
So for the first improvement
we're going to see how to
eliminate a common source of
boilerplate when working with
enum's.
So let's say I have to find an
enum.
And I want to print every
possible value that this data
type can have.
So in Swift 4, I had to define a
property perhaps with a list of
all the possible cases.
And if I add a new case then I
have to remember to update that
property, otherwise I just get
incorrect behavior or runtime.
And this is just not very good
because you're repeating
yourself to the compiler.
So in Swift 4.2 we've added a
new CaseIterable protocol and if
you state a conformance to this
protocol, the compiler will
synthesize an all cases property
for you.
OK, that was short and sweet.
[ Applause ]
For the next improvement we're
going to see how to eliminate
another source of boilerplate.
This time it's when you're
unable to make your code
sufficiently generic.
So in Swift 4 we have this
contains method on sequence.
And this requires that the
element type of the sequence is
Equatable so that it can find
the element that it's looking
for.
And of course I could call this
within an array of strings
because string is Equatable.
But what if I call it within an
array of arrays.
Well array of Int, the element
type here is not equitable,
which meant that I would just
get a compile time error.
And you might ask, well why
doesn't the standard library
make all arrays Equatable.
But that doesn't make sense
either because if the element
type of the array is not
Equatable, like a function
perhaps, then you can't really
make the array Equatable either.
But certainly if the element
type of the array is Equatable
then I can define an equality
operation on arrays that just
compares the elements pair wise.
And this is what conditional
conformance allows a standard
library to do.
So now array gets an
implementation of Equatable for
the case where the element type
is equitable.
And in Swift 4.2 this example we
saw earlier now works.
And in addition to arrays being
Equatable the standard library
defines a number of other
conditional conformance.
For example, optional and
dictionaries are now Equatable
when their element type is
Equatable and the same works for
Hashable, Encodable, and
Decodable conformances.
[ Applause ]
And this allows you to compose
collections in ways that were
not possible before.
So here I have a set of arrays
of optional integers and
everything just works.
If you want to learn more
there's a session later this
week where you can learn about
conditional conformance and some
other generics improvements in
Swift 4.2 that I won't be
covering today.
So what about defining your own
Equatable and Hashable
conformances.
Well, a common pattern in Swift
is that I have a struct with a
bunch of stored properties and
all those stored properties are
themselves Equatable.
And then I want to make the
struct Equatable just by
comparing those properties of
the two values.
In Swift 4 previously you had to
write this out by hand.
And this is just boilerplate.
If I add a new stored property
to my struct, I have to remember
to update this implementation of
Equatable and it's easy to make
a copy and paste error or some
other mistake.
So in Swift 4.1 we introduce
this ability to synthesize the
implementation of equality.
If you emit the implementation
than the compiler will fill it
in for you as long as all those
stored properties are themselves
Equatable.
This also works for Hashable.
Now what about generic types?
So here I have a data type whose
values are either instances of
the left type or instances of
the right type.
And I might now want to make
left and right constrained to
Equatable because again, I want
to be able to use this either
type with functions, errors, and
other non Equatable types.
But certainly I can define a
conditional conformance so that
if left and right are both
Equatable then either is
Equatable.
But I can do even better than
this.
Notice how the implementation of
equality here there's only
really one obviously correct way
to do it.
You have to check that both
values have the same case and if
they do you check their payloads
for equality.
So you might guess, well the
compiler should be able to
synthesize this for you and it
can in Swift 4.2.
And this also works for
Hashable.
So now I can have a set of
either Int's or strings as one
example.
OK.
[ Applause ]
Now, there are cases where you
really do have to implement
equality and Hashing by hand.
So let's look at one example of
that.
Let's say I have a data type
that represents a city and it's
got a name, it's got the state
that it's located in, and it has
the population.
And let's say that for the
purposes of this example I only
have to compare the name and the
state for equality and if I know
those are equal I don't have to
check the population.
So if I let the compiler
synthesize the implementation of
equality here it's going to do
unnecessary work because it's
going to be comparing that
population field.
But I certainly write it out by
hand and maybe in this case it's
not too bad.
But what about Hashable?
So if I want to calculate the
Hash code of the city object,
then I'm going to calculate the
Hash code of the name and the
Hash code of the state and I
have to combine them somehow.
But how do I do that?
Well, I can use an exclusive or
operation or I could use some
random math formula that I found
on the Internet or just came up
with myself.
But neither one of these is very
satisfying and it feels like
these Hash combining functions
have a lot of magic to them.
And the cost of getting it wrong
is pretty high because the
performance properties that you
expect to get from a dictionary
or a set really rely on having a
good high-quality Hash function.
There's also a security angle
here.
So if an attacker is able to
craft inputs that all Hash to
the same value and send them to
your app over the Internet
somehow, then it might slow your
app down to the point where it
becomes unusable creating a
denial of service attack.
So in Swift 4.2 we've added a
better API for this.
Now recall the Hashable protocol
in Swift 4 and 4.1.
It has a single Hash value
requirement that produces a
single integer value.
In Swift 4.2 we've redesigned
the Hashable protocol so now
there's a different Hash into
requirement.
And instead of producing a
single Hash code value, Hash
into takes a Hasher instance and
then you can feed multiple
values into the Hasher, which
will combine them into one Hash
code.
So going back to our example of
the city data type, all we have
to do is implement Hash into by
recursively calling Hash into on
the name and the state passing
in the Hasher object instance
that we were given.
And the Hash combining algorithm
in the Hasher, it does a good
job of balancing the quality of
the Hash code with performance
and as an added layer of
protection against denial of
service attacks, it uses a
random preprocess seed, which is
generated when your app starts.
And we think that it should be
pretty easy to migrate your code
to using the new Hashable
protocol and we encourage you to
do so.
The one caveat to watch out for
is you might have some code
where you're expecting that Hash
values remain constant from
different runs of your app or
that if you iterate over a
dictionary or a set you're going
to get the elements in the same
order.
And this is no longer the case
because of that random
preprocess seed.
So you will need to fix your
code.
And to make this easier we've
added a build setting, the Swift
Deterministic Hashing
Environment Variable, which you
can enable in the scheme editor
to temporarily disable that
preprocess random seed.
OK, so let's talk about
generating random numbers.
So how do you generate random
numbers in Swift today?
Well, you have to use imported C
APIs.
And this is really not ideal
because they are different
between platforms and they have
different names, different
behavior, so you have to use
build configuration checks.
But also they're quite low level
and these common operations that
are not quite so obvious to
implement.
For example, if I want to get a
random number between 1 and 6,
then I might think to just call
this Darwin arc4random function
and then calculate the remainder
of dividing by 6.
But that actually gives you a
result that is not uniformly
distributed between 1 and 6.
So in Swift 4.2 we've added a
new set of APIs to make this
kind of thing easier.
First of all, all the numeric
types now define a random method
that takes a range and returns a
number uniformly distributed in
that range.
This uses the correct algorithm
and it even works for floats.
[ Applause ]
For higher level code we've
added a random element method to
the collection protocol.
And just like min and max this
returns an optional so that if
you pass in an empty collection
you get back no.
And finally there's a shuffled
method on collection where this
gives you an array with a random
permutation of the elements of
that collection.
And we think the default Random
Number Generator is a good
choice for most apps.
But you can also implement your
own.
So there's a random number
generator protocol and once you
write a type that conforms to
this protocol you can pass it to
all these APIs that I talked
about which have an additional
overload with a using parameter
that takes a random number
generator.
OK, so we saw these build
configuration checks earlier.
Let's talk some more about them.
Well, this is a pretty common
pattern in Swift.
You have a little piece of Swift
code that is shared between iOS
and macOS and on iOS you want to
do something with UIKit.
On macOS you want to do
something similar in AppKit.
So if you want to do this today
you're going to write a #if
compile time condition check and
then you have to list out those
operating systems where UIKit is
available.
So but what you really care
about is not that you're running
on this particular operating
system, but that you can import
UIKit.
So on Swift 4.2 we've added a
has import Build Configuration
Directive so you can better
express your intent.
[ Applause ]
And with the new features of
Swift 4.2, I can actually
improve this code further.
So let's say that I'm also going
to explicitly check for AppKit
and then if neither UIKit nor
AppKit is available, for example
if I'm building on Linux, I'm
going to use the new #error
build directive to produce a
friendly compile time error
message.
OK, now here's another similar
source of boilerplate.
So if I want to compile
something conditionally when I'm
in the simulator environment,
then today in Swift 4 I have to
copy and paste this ugly thing
everywhere I want to perform
that check.
In Swift 4.2 you can use the new
hasTargetEnvironment condition,
to again better state your
intent and just explicitly ask
the compiler, am I compiling for
the simulator or not?
And while we're at it, let's
replace that FIXME with a
#warning build directive to
produce a message or compile
time so that I don't forget to
fix my FIXME.
OK, so that about wraps up all
the features that I'm going to
discuss today, but I have a
couple more things to talk
about.
Let's unwrap, Implicitly
Unwrapped Optionals.
That's a horrible pun.
OK, so Implicitly Unwrapped
Optionals can be a little bit
confusing and let's first review
the mental model for Implicitly
Unwrapped Optionals.
How do I think about them?
Well, so since Swift 3 they're
not the type of an expression.
Don't think of it as a type.
Instead, think of Implicitly
Unwrapped Optionals as an
attribute of a declaration.
And what the compiler does when
you reference such a declaration
is it will first try to type
check it as a plain optional and
then if that doesn't make sense
in the context where it's used,
it goes ahead and unwraps it and
then type checks it as the
underlined type.
So let's look at an example of
the first case.
So here I have two functions,
the first of which produces and
implicitly unwrapped optional
integer and the second of which
takes a value of any type.
And I'm going to call the second
function with the result of the
first function.
Now in this case I can store an
optional Int inside of an Any
and so no forced unwrapping is
performed.
The value simply becomes a plain
optional.
Let's look at an example of the
second case now.
Here, the first function now
produces -- sorry, the second
function now takes an integer.
So when I call the second
function with the result of the
first function then I cannot
pass an optional Int where an
Int was expected.
So the compiler has to insert a
force unwrap and then it all
works because now I have an Int
and an Int And this mental model
makes Implicitly Unwrapped
Optionals very easy to reason
about.
But until recently the compiler
had some edge cases where it did
not always follow this model.
So recall that you cannot have
an implicitly unwrapped optional
that is part of another type.
And this is still the case in
Swift 4.2.
I cannot have an array of
implicitly unwrapped Int's.
However, in Swift 4 previously,
there is some edge cases like
this.
I could define a type alias
where the underlying type was
implicitly unwrapped Int and
then I could make an array of
this type alias and I would get
very confusing behavior from the
compiler that made code hard to
understand.
So in Swift 4.2 we've
re-implemented Implicitly
Unwrapped Optional so that it
exactly matches the mental model
I outlined earlier and this
confusing code example now
generates a compile time warning
and the compiler parses that as
if it was just a plain array of
integers, of optional integers.
Now, most code will not be
affected by this change to
Implicitly Unwrapped Optional,
but if you were accidentally
relying on these edge cases I
encourage you to check out this
blog post on Swift.org that goes
into a lot of detail and has a
lot of examples about what
changed and how.
OK, now there's only one more
thing here today.
Let's talk about memory
exclusivity checking.
So if you recall, in Swift 4 we
introduced something called
Memory Exclusivity Checking,
which was a combination of
compile time and runtime checks
that restricted certain
operations from being performed.
In particular we banned
overlapping access to the same
memory location.
What does this mean?
Well, let's look at an example.
So here's a piece of code that
implements a data type for
operating system paths.
And this is represented as an
array of path components.
And there's a withAppended
method.
This method adds an element to
the array, then in calls a
closure that you pass in and
then it removes that element
from the array.
And this code is totally fine,
it's a valid Swift 4 code.
But let's look at this usage of
our path data type.
So here I have a path that's
stored and a local variable and
then I call withAppended on it
and inside the closure I access
that local variable again
printing it.
So what the problem here?
Well, it turns out this code is
actually ambiguous because when
I access that local variable
inside the closure, it's already
being modified by this
withAppended method, which is a
mutating method.
So the ambiguity is that do I
mean the original value of path
as it was before I called
withAppended or do I mean the
current value that is being
modified whatever that means.
Well, in Swift 4 this was a
compile time error because it
was an exclusivity violation.
And one way to address this is
to resolve the ambiguity by
telling the complier, hey I
really want the new value so I'm
going to just pass it in as a
parameter to the closure instead
of capturing it.
OK, but now look at this
example.
So this is almost the same
function except that it's
generic, it's prioritized by the
return type of the closure.
And in this case we can have the
same kind of ambiguity by
accessing the path value from
inside the closure.
But previously Swift 4 did not
catch this error at compile
time.
In Swift 4.2 we've improved the
static exclusivity checking to
catch ambiguities like this in
more cases.
And in addition to improving --
OK, and you can also fix the
ambiguity in the same way by
passing it as a parameter to the
closure.
In addition to improving the
static checks, we've also added
the ability to use the runtime
exclusivity checks and release
builds.
And this has some overhead but
if your app is not performance
critical, we encourage you to
try this out and leave it on all
the time.
In the future, we will get the
overhead of these dynamic checks
down to the point where we can
leave this enabled all the time
and it will give you an extra
level of protection just like
array bounce checking or integer
overflow checking today.
And there's a lot more in Swift
4.2 that I didn't talk about
today.
And we encourage you to try it
out on your existing apps.
We also want you to try out the
new features and if you have any
questions please come to the
labs and ask us.
Thank you.
[ Applause ]