WEBVTT

00:00.000 --> 00:18.960
So, our next speaker is Doug Cracker. He has deep expertise in programming languages and

00:18.960 --> 00:24.340
compilers. He is currently working on the Swift programming languages and has in the

00:24.340 --> 00:31.860
past, also contributed to Clang, LLVM and ICC++ standard. He works at Apple and today

00:31.860 --> 00:39.260
he will be sharing his deep understanding of programming languages and how memory safety

00:39.260 --> 00:49.340
can be made easier by incorporating and blending Swift with CNC++. Please welcome Doug.

00:49.580 --> 01:01.020
Thank you. All right, I'm here to talk about Swift. We're about 10 years after the introduction

01:01.020 --> 01:07.580
of Swift and we've been rolling it out into an established software ecosystem trying to bring

01:07.580 --> 01:15.260
memory safety to a predominantly CNC++ world. We've learned a lot in these last 10 years.

01:15.260 --> 01:21.180
So, I want to share some of how we've done this. We've learned along the way and some ideas

01:21.180 --> 01:29.020
for helping the open source software ecosystem move toward more memory safety. Now, I'm not

01:29.020 --> 01:33.580
going to try to sell you on the benefits of memory safety. A lot has been said and written on

01:33.580 --> 01:39.740
that topic. So, this is one particular report, co-signed by a whole bunch of government

01:39.740 --> 01:47.180
cybersecurity agencies and it makes the point that we as a software discipline need to move

01:47.180 --> 01:53.340
from the memory unsafe languages that we have today like CNC++ toward memory safe languages.

01:55.340 --> 01:59.180
The goal here is of course to improve software security, but there are a lot of other benefits

01:59.180 --> 02:07.260
of memory safe languages. But the hard part here is the how, how do we actually get there?

02:08.060 --> 02:16.220
Because where we are today is we have CNC++ everywhere. Our entire software universe is built

02:16.220 --> 02:21.180
on top of these languages that do not provide memory safety. And there's no magic bullet that's

02:21.180 --> 02:27.500
going to make the memory safe. Now, on the other hand, you have a lot of options for memory

02:27.500 --> 02:32.940
safe programming languages. So, I took this list directly from the report. I'm very sorry if

02:33.260 --> 02:38.860
you're programming language of choice isn't on here. But the idea is there are a bunch of good

02:38.860 --> 02:43.340
options. And if you were starting from nothing, you're going to build your own software ecosystem

02:43.340 --> 02:48.540
from the bottom up, you could do so in one of these memory safe programming languages and have memory

02:48.540 --> 02:53.740
safety. In a sense, that's not even the hard part. The hard part is how do we get from where we are

02:53.740 --> 02:58.540
today, over to this world, where we have better memory safety, throughout the whole open source

02:58.540 --> 03:07.340
ecosystem. We don't know the answer, but we're looking for a roadmap. Swift itself, the language

03:07.340 --> 03:14.940
that we rolled it out, was actually designed specifically for this transition. Swift launched into

03:14.940 --> 03:20.540
an ecosystem that was already well established and built on top of the C family of languages,

03:20.540 --> 03:29.100
C, C++, and Objective C. So, in this Apple ecosystem, this is the apps that run on the

03:29.100 --> 03:34.220
iPhone, run on the Mac, and so on, we had this large software development kit,

03:35.340 --> 03:40.860
comprised of many libraries written in, and C, and Objective C, and many, many developers that

03:40.860 --> 03:47.020
knew how to write code for this environment. Objective C is not familiar to you. It's fine,

03:47.100 --> 03:50.860
just think of it as C, with like small talk, wedged on top, to give it Objective

03:50.860 --> 03:55.100
oriented programming, but it still retains all of the memory safety aspects of, let's see.

03:56.140 --> 04:01.580
Now, in this ecosystem, we had a couple of other things to be concerned about. We needed binary

04:01.580 --> 04:07.500
stability. So, if you're building an app for something like a phone, and you run it on today's OS,

04:07.500 --> 04:13.100
well, it needs to work on next year's OS and in the future. And so, we had to embrace the ecosystem

04:13.180 --> 04:19.180
we had, but move it from this C family of languages toward a memory safe future based on Swift.

04:21.900 --> 04:27.500
The approach we took is pretty different from how programming languages are often introduced.

04:27.500 --> 04:31.900
So, often a programming language comes with its whole big stack of, you know, libraries and

04:31.900 --> 04:35.740
platform libraries. Everything that you need to build stuff in that programming language.

04:36.780 --> 04:42.460
We didn't do that. When we launched Swift, it had basically one library, it standard library,

04:42.540 --> 04:46.860
with arrays and strings and these little-level components in it, but nothing else.

04:48.220 --> 04:55.820
Instead, we took interoperability with the C family of languages as a first-class language feature.

04:56.860 --> 05:02.460
And the idea here is we had launched into the existing ecosystem. We had all of the libraries

05:02.460 --> 05:06.220
that were already there, all of the code that was already there for C and Objective C,

05:06.220 --> 05:09.900
just integrate naturally into Swift with no ceremony whatsoever.

05:10.220 --> 05:15.820
It's interesting because here what you're doing essentially is you're only changing one variable.

05:16.380 --> 05:21.260
We're changing the programming language, but everything that developers already knew from this ecosystem.

05:21.820 --> 05:26.700
All the libraries they learned, all the tricks they learned to build great apps, all of that

05:26.700 --> 05:31.740
that transferred, but now they could do it with Swift and get the benefits of memory safety and

05:31.740 --> 05:39.820
a more ergonomic programming language. We also made sure to make it very, very easy to get started using

05:39.820 --> 05:45.980
Swift in the code that people had. So if you had an existing project, tons of Objective C,

05:45.980 --> 05:50.540
it doesn't matter how complicated it was, you could go add a single Swift source file to that.

05:51.660 --> 05:56.380
And start using all of the APIs there, including using all of your own code.

05:57.500 --> 06:02.940
This produced a really nice onboarding path where it didn't cost you more than a couple of minutes

06:02.940 --> 06:07.900
to try out Swift. You know, write just one class in it, implement one feature in your app,

06:07.980 --> 06:13.660
see how you like it. Very low risk. And so people could go ahead and invest time in using this new

06:13.660 --> 06:20.540
language instead of what they already knew when it was appropriate for them. So this has worked very

06:20.540 --> 06:27.900
well for us in the Apple platforms. So the existing C and Objective C ecosystem is moving towards Swift.

06:27.900 --> 06:33.020
And we've seen this movement everywhere. I've talked about apps that sort of the highest level

06:33.100 --> 06:37.660
and which we operate, but we've also been able to move lower level components. Things like

06:37.660 --> 06:45.180
rewriting, you know, decades old C components with Swift as drop in binary compatible replacements.

06:45.180 --> 06:50.860
So we can move memory safety forward, sort of anywhere in the system when it's time to make that

06:50.860 --> 06:57.500
particular investment. We've learned a ton and we think that these lessons actually apply to other

06:57.500 --> 07:02.540
ecosystems, and especially to the open source software ecosystem. And so that's what I want to

07:02.860 --> 07:07.180
talk about today. And we've got four parts to this talk. First, I'm going to teach you a

07:07.180 --> 07:11.660
little bit of Swift. Mostly to talk about how Swift tackles the memory safety problem because

07:11.660 --> 07:15.900
it's a bit different than some of the other languages you might know. Then I want to go into

07:15.900 --> 07:21.020
interoperability and what it means, how we tackled interoperability with the C family of languages

07:21.020 --> 07:26.780
to make it possible to have this incremental approach to adopting memory safety. And I'm going

07:26.780 --> 07:31.740
to talk about build systems. It turns out they're really important. Even when your language does

07:31.820 --> 07:37.020
well interoperability to get build level interoperability. And finally, I'll bring it back to

07:37.020 --> 07:41.660
memory safety because now we're talking about a memory safe language interoperating with

07:41.660 --> 07:46.780
memory safe code as the way forward, but we have to talk about what it means to have memory

07:46.780 --> 07:54.620
safety and that kind of hybrid environment. All right, let's talk some Swift. What is Swift? I

07:54.620 --> 07:59.420
haven't actually said. So it is a general purpose programming language that's a joy to write.

07:59.500 --> 08:04.380
So the goal here is to produce an approachable language. So whatever you're background in programming,

08:04.380 --> 08:09.900
you can come to Swift, learn a couple things, see some familiar aspects, and get productive

08:09.900 --> 08:15.980
immediately. And the language will grow to you. It has the power tools needed for experts as well,

08:15.980 --> 08:20.460
but we have this principle of its progressive disclosure so that that comes along later in your

08:20.460 --> 08:26.060
journey of learning Swift. The language itself is native compiled. It's great for performance.

08:26.700 --> 08:31.500
And it's been open source since 2015. So if you want to go check us out and get hub with a Swift

08:31.500 --> 08:35.420
language organization, there we've got all its compilers, tools, lots of libraries and so on.

08:36.700 --> 08:43.340
And now I started my story with Apple, but Swift has grown beyond just the Apple platforms

08:43.340 --> 08:47.020
to support all the major platforms and it's portable to other platforms as well.

08:49.580 --> 08:53.420
So let's talk about the memory safety aspects of Swift. That's why we're here.

08:54.380 --> 09:00.780
So memory safety in discussions, it can be a little confusing sort of what it is. And sometimes

09:00.780 --> 09:05.740
when you listen to a memory safety talk, it sort of sounds like memory safety solves all program

09:05.740 --> 09:11.580
programmer errors. It doesn't. That's not what it's about. I wish we could solve all program

09:11.580 --> 09:17.580
errors. What memory safety is about is acknowledging that programmer errors will happen for sure,

09:17.580 --> 09:21.100
but they need to not escalate into problems that can cause security issues.

09:21.740 --> 09:27.580
Now there are aspects of language design that can eliminate classes of program errors. Those

09:27.580 --> 09:33.340
are wonderful, right? And they can help with memory safety, but they're not the whole story. My favorite

09:33.340 --> 09:40.140
example here is actually no pointers. So you have many options as a program language for what to do

09:40.140 --> 09:46.460
about no pointers. In Swift our approach is, well they don't really exist. If you have a reference

09:46.460 --> 09:51.180
to something, it's not null. If you want to represent that something may or may not be there,

09:51.180 --> 09:55.820
you use an optional type. And so we have defined a way this problem, which is great,

09:55.820 --> 10:02.700
but really that is static checking, right? Static checking that there's no places where you

10:02.700 --> 10:09.500
dereference a null pointer in your program. Good that is a perfectly valid approach to memory safety

10:09.500 --> 10:15.820
for null pointers. Java takes a different but equally valid approach. Java objects, they can all be

10:16.540 --> 10:22.540
however, the Java system, the virtual machine, makes sure that it always checks for a null

10:22.540 --> 10:26.620
pointer before you dereference it. And then throws a null pointer exception you can deal with later

10:27.900 --> 10:33.500
to address that. This is also memory safety. It's dynamically checked, but it's just a safe.

10:36.140 --> 10:42.620
Now what C does is the unsafe ground, right? There's no checking. So anything can be null

10:42.700 --> 10:47.260
and there's no checking at runtime. And so if you dereference a null pointer and you do the right

10:47.260 --> 10:52.860
things, you've created a security gadget that you can use to attack the program because it's

10:52.860 --> 10:58.620
undefined behavior. The program can do anything. I call this a violation of the abstract model.

10:58.620 --> 11:03.580
We can no longer reason about what the program is supposed to do by looking at the source code,

11:03.580 --> 11:09.660
when there is a break of the abstract model, when there is undefined behavior. As a language,

11:09.740 --> 11:14.140
you need to look at all the ways in which memory safety could compromise the abstract model

11:14.140 --> 11:19.820
and lock them down either by refusing to compile the program or putting in a dynamic check

11:19.820 --> 11:26.540
that will halt the program at runtime instead of limping on in some compromise state that can be a

11:26.540 --> 11:34.220
security problem. When I think of memory safety in programming languages, I think of it

11:34.220 --> 11:39.500
along about five different axes. And so there's lifetime safety. Are you accessing something

11:39.500 --> 11:44.620
during its defined lifetime? A violation here is something like a use after free. You've freed

11:44.620 --> 11:49.420
up some memory ending its lifetime, but then you access it later. Anything can happen. You have

11:49.420 --> 11:55.100
no idea what's there. Bound safety is when you have a memory allocation, making sure that you're

11:55.100 --> 12:02.140
accessing within the size of that memory allocation and no further out. Type safety is when you're

12:02.140 --> 12:08.140
accessing a value, you need to use the same type as that memory was initialized with or some

12:08.140 --> 12:13.820
other compatible type. So failures here are called type confusions, something like you wrote an

12:13.820 --> 12:19.340
integer into one field of a C union and then you read a pointer out later. Well, now you've

12:19.340 --> 12:26.540
got undefined behavior. Initialization safety is another easy one. Make sure that you've initialized

12:26.540 --> 12:29.740
the memory before you actually read from it. Otherwise there could be garbage there that makes

12:29.740 --> 12:35.740
your program do weird things. And then the hard one is thread safety. When your program is

12:35.740 --> 12:41.180
concurrently executing, you need to make sure that whatever mitigations you have in place for the

12:41.180 --> 12:47.180
other for, they still work in the presence of data races in that program. And there's a lot of

12:48.460 --> 12:53.100
different ways you can tackle these various problems. Lifetime is perhaps the one that's most

12:53.180 --> 13:00.300
talked about in the programming language world. So Swiss approach to lifetimes is essentially

13:00.300 --> 13:07.020
goes in two directions. One is to build up from primitive types. So every programming language has

13:07.020 --> 13:12.460
primitive types like integers, floating point numbers. We don't ever talk about the lifetime

13:12.460 --> 13:17.420
safety of these things. It's an integer, right? The compiler handles it for you. It copies around

13:17.420 --> 13:21.820
when you need. You can return them and there's no extra heap allocations to deal with. They're

13:21.900 --> 13:28.780
very, very simple and there's safety there. So Swift builds up from this model with value types.

13:28.780 --> 13:34.140
So all the primitive types are value types, but also things like arrays, strings, dictionaries.

13:34.780 --> 13:41.340
Very large data models can be value types in the Swift world and Swift makes sure to copy them around

13:41.340 --> 13:46.060
as needed. And it gives you this nice local reasoning property where, you know, when you make a copy

13:46.060 --> 13:52.620
of a value, changing the original doesn't have any impact on the copy. It's very nice separation

13:52.620 --> 13:57.820
of concerns you get. Swift makes that true for all the value types everywhere. And when you're talking

13:57.820 --> 14:02.780
about something like a string and array, well the copying sounds like it could be expensive. Under

14:02.780 --> 14:07.420
the hoods, Swift uses copy on right, so they can give this semantic behavior while still having

14:07.420 --> 14:14.460
cheap copies. And you can build things that are essentially arbitrarily complicated with value types

14:14.460 --> 14:20.220
and higher data models. Structs can be used to aggregate value types into more value types.

14:20.220 --> 14:25.180
This is pretty common most programming languages, Swift also has e-dums, and so these are type

14:25.180 --> 14:31.980
safe unions. Use this to express a choice among, you know, one of several alternatives,

14:31.980 --> 14:41.660
all of which can have data with them, if you'd like. Now generally speaking, we pass value types

14:41.820 --> 14:46.460
reference. Again, they're copies. There's no lifetime issues when you do that. However, we can

14:46.460 --> 14:51.340
pass them by value with these in-out parameters. This is where things start to get interesting.

14:51.340 --> 14:56.220
At the call site, we acknowledge the fact that you're essentially passing down the address of a variable.

14:58.060 --> 15:03.580
Now of course, that variable has to be mutable. It's a let in in the Swift world. That means

15:03.580 --> 15:08.220
it's immutable. You can't change it neither can anyone else so you can't pass it down by reference.

15:08.300 --> 15:12.140
But when it's a variable, you're effectively passing down the address of mutable state.

15:12.780 --> 15:16.460
As soon as you do that, you've introduced the possibility of lifetime issues.

15:17.820 --> 15:24.540
And so Swift has this property that in-out parameters never alias any other reference to that value.

15:24.540 --> 15:30.300
So when you have an in-out parameter, and it's referring to an argument, you are the only person

15:30.300 --> 15:35.900
that can touch that memory. This exclusive access is critical for maintaining these lifetime properties.

15:36.460 --> 15:43.100
Now this is a mix of static and dynamic analysis in the Swift language. So here's a little swap function,

15:43.100 --> 15:49.740
just to swap two values. Now if you go ahead and swap two different local variables, it's fine.

15:49.740 --> 15:54.860
We know that they're separate and the compiler will accept it. If you're to do something silly,

15:54.860 --> 16:00.780
like swap A and A, well this would create an aliasing between those two arguments. So the compiler will

16:00.860 --> 16:04.700
reject it and tell you, you have overlapping accesses here. These are not permitted.

16:05.740 --> 16:10.300
Now if one of these is some sort of global variable, where we can't reason about everyone that's

16:10.300 --> 16:14.700
potentially touching that memory, it'll roll over to a dynamic analysis. And we'll do a runtime

16:14.700 --> 16:20.540
check to make sure that you don't have aliasing going into these in-out functions. This allows us to

16:20.540 --> 16:27.500
have this lifetime safety model for this extension of primitive types. These value types that are

16:27.500 --> 16:34.220
very easy to work with. Now Swift also supports object oriented programming. So if you're coming

16:34.220 --> 16:38.860
from an OO language, this will be very familiar to you. We've got classes with single inheritance,

16:38.860 --> 16:44.300
you can override methods. There's initializers that create those objects, DNitializers that

16:44.300 --> 16:50.700
tear them down at the end, and classes have reference semantics. So you can have multiple variables

16:50.700 --> 16:57.500
all pointing to that same object of class type on the heap. It was great for building all sorts

16:57.500 --> 17:04.700
of data structures, of course. But it means you have to deal with lifetimes of these heap data

17:04.700 --> 17:10.940
structures. With Swift we chose to use automatic reference counting. This is kind of in the

17:10.940 --> 17:17.740
Goldilocks zone of sort of automatic memory management schemes, because it lets you have

17:17.900 --> 17:22.780
lifetimes safety with very little ceremony. The programmer doesn't think about how you're doing this

17:22.780 --> 17:27.900
behind the scenes. It just works to keep objects alive until they're no longer needed and then they're

17:27.900 --> 17:33.900
destroyed. Now when compared against a traditional garbage collector, there's actually some really

17:33.900 --> 17:39.980
nice engineering benefits to using automatic reference counting. It behaves deterministically. So

17:39.980 --> 17:44.780
when the last reference to an object goes away, that object is destroyed. You don't wait until

17:44.940 --> 17:50.700
some time later. And this can help you reason about your program. It permits local optimization.

17:50.700 --> 17:54.860
Compiler can understand where we're doing reference counting and eliminate various reference counts.

17:56.060 --> 18:00.780
And you can implement this with a really tiny runtime. You basically need a retain and a release

18:00.780 --> 18:06.060
function to increment and decrement to the count and then call it a DNitializer when the thing goes away.

18:07.740 --> 18:12.540
On our reference reference counting is also common in CNC++ libraries because it is a great

18:12.620 --> 18:19.660
mechanism for dealing with lifetime. And so in C, it'll be manual. You have to call these,

18:19.660 --> 18:23.340
you know, retain and release operations, but it's still the same underlying model.

18:25.100 --> 18:30.700
Now, you do have to think about memory management a little bit with reference counting. Because

18:30.700 --> 18:36.860
if you write a reference cycle, then unless you break that cycle, one object is keeping the other

18:36.860 --> 18:42.460
alive. Some languages that use automatic reference counting have cycle collectors. It'll come by

18:42.460 --> 18:48.300
identify these cycles and then destroy them. Swift does not and will not provide a cycle collector.

18:48.300 --> 18:53.260
Because doing so basically undermines all of the engineering advantages that just talked about

18:53.260 --> 18:57.820
with automatic reference counting. Now you have non-determinism when it happens. Now you have to have

18:57.820 --> 19:01.820
a lot of metadata and a heavy runtime to support it so you can't run an all environments.

19:02.780 --> 19:07.580
Instead of having a cycle collector, you know, we build into the language model the notion of

19:07.580 --> 19:12.060
weak references. And so you can break a cycle by making one of the references weak.

19:12.780 --> 19:18.300
And we support this in the type system. So when you have a weak variable, it must have optional

19:18.300 --> 19:23.580
type. That's what this question mark is here. Optional is either the object is still alive and I have

19:23.580 --> 19:29.020
a reference to it or the object died because no one was keeping it alive and now I have a meal here.

19:29.740 --> 19:35.820
I can check this with this if let pattern where I go and try to get the objects. If it's there,

19:35.820 --> 19:41.180
I have a strong reference to it so I'm keeping alive within the body that if. If the object is gone,

19:41.180 --> 19:44.460
well the body of the if doesn't run and maybe I have some code in the else to deal with it.

19:45.420 --> 19:50.060
But by building into the model, it makes it very easy to deal with reference cycles and model your

19:50.060 --> 19:57.340
data in a way that works well with the system. That's it for lifetime safety. Down safety is really

19:57.980 --> 20:02.460
easy. So if it has a raise, it bounds checks, it's a raise. There's not a whole lot more to say. As

20:02.460 --> 20:06.460
long as you have the data there, bound checking is easy as a dynamic check that's often optimized

20:06.460 --> 20:12.620
away by the compiler. Lift also checks for overflow and arithmetic operations and traps on

20:12.620 --> 20:21.980
overflow as an additional security mitigation. Type safety again built into the design of the language.

20:21.980 --> 20:25.260
If you have some instance of a super class and you want to check whether it's a particular

20:25.260 --> 20:29.660
subclass, you can use the as question mark operator and that returns an optional. Either it has

20:29.660 --> 20:35.420
the subclass instance or it wasn't there and it's no. That's safe. If you're dealing with the enums,

20:35.420 --> 20:39.500
which are essentially type safe unions, you can just switch on them and check the various cases.

20:39.500 --> 20:45.660
Again, just type safety built into the language. Initialization safety, very similar.

20:46.700 --> 20:50.940
Before you get to use a value, it needs to be initialized along all paths, otherwise compile

20:50.940 --> 20:59.660
either rejects the program. Fred safety is where things get pretty interesting. So where

20:59.660 --> 21:04.540
Fred's, what are the threat safety problems? The fundamentally shared mutable state is the

21:04.540 --> 21:09.180
root of all problems here in concurrent programs. Because when you have shared mutable state,

21:09.180 --> 21:14.060
you can have a data race where someone is writing and someone else is either reading or writing

21:14.060 --> 21:19.020
and you might not have data in a consistent state. Very easy to let this break your model.

21:19.980 --> 21:25.100
Fortunately, this tells us what the strategies are for avoiding data races in programming language

21:25.100 --> 21:29.820
design. You can make things immutable, right? If there's no one changing it, then it's fine.

21:29.820 --> 21:34.860
You can read it from as many threads as you want. You can choose not to share. If you're not

21:34.860 --> 21:39.820
sharing it across threads, then you can't have any data races because everything is in one thread.

21:40.700 --> 21:47.260
And finally, you can make sure that if it is shared, that all access goes through some kind of synchronization

21:47.260 --> 21:51.660
mechanism so that there's only one thread at a time that's touching that data.

21:54.700 --> 22:00.540
Per Swift, the different lifetime mechanisms fit in with this. So value types are especially

22:00.540 --> 22:06.940
good for concurrency because you don't have sharing. Whenever you make a copy of a value type,

22:06.940 --> 22:11.740
you have a completely independent copy so you can't have data races on it. Even if both of those

22:11.740 --> 22:23.660
happen to be mutable. Additionally, the value types can be passed around fairly safely,

22:23.660 --> 22:29.660
right? Where if you have this notion of deep immutability. So if you have a let of a value type,

22:29.660 --> 22:34.700
that thing is truly immutable. No one can change it out from under you. And so those let variables

22:34.700 --> 22:40.860
can be accessed from any place at the same time. We know that no one is mutating. So the combination

22:40.860 --> 22:46.860
of copying is liberally and having a deep immutability makes value types wonderful for writing

22:46.860 --> 22:53.580
concurrent programs. References are a little bit trickier. The whole point of using reference

22:53.580 --> 22:59.340
types in a system is that you have this shared mutable state. So Swift actually was inspired

22:59.340 --> 23:05.180
by a length and other actor models and has actors as a first class language feature. So with

23:05.180 --> 23:11.340
the Swift actor and actor owns and protects its state. Actors themselves can be used from many places,

23:11.340 --> 23:17.340
but wherever you use them, you have to go through the actor's synchronization mechanism. So here

23:17.340 --> 23:21.020
you see we're trying to withdraw something from this particular bank account. We have an

23:21.020 --> 23:26.380
await here because you may have to wait until the actor is free to service your request to go

23:26.380 --> 23:31.500
and actually do that operation. That's what guarantees mutual exclusion and the language and the

23:31.500 --> 23:36.860
runtime work together to make that a safe concurrent model. It doesn't have any thread safety.

23:38.540 --> 23:45.020
So I've just taught you Swift how wonderfully memory safe it is. Now you should all just go

23:45.020 --> 23:52.860
and rewrite your code. No? Okay, I'm not going to tell you to do that. Maybe for some tiny

23:52.860 --> 23:58.220
library utility? Yes, you can go ahead and just rewrite it. But rewrites are really, really,

23:58.220 --> 24:04.460
really treacherous. Right? If you're going after trying to rewrite a library that's in use,

24:04.460 --> 24:09.340
well, it's going to be a lot of work. And there's a lot of technical hurdles to actually

24:09.340 --> 24:14.540
getting it right. The first one is sort of ourselves, right? The second system effect, where

24:14.540 --> 24:18.860
it's a successful system, we build a new system and we're going to get everything right this time.

24:18.860 --> 24:23.900
We're going to hit all the use cases, fix all the bugs, add new features, and this massive

24:23.900 --> 24:27.900
architecture is possibly going to fall over it on itself. Even when we're doing this

24:27.900 --> 24:33.660
noblely, like I'm going to rewrite to match the spec. Oh, the spec and the reality of the existing

24:33.660 --> 24:39.180
library are probably not in alignment and you're going to run into trouble. And so rewrites

24:39.180 --> 24:45.580
they're difficult and they take time and you probably can't just abandon the existing sea library

24:45.580 --> 24:49.020
while you're doing this rewrite. You have to ship updates. You have to add features. You have to

24:49.020 --> 24:53.740
respond to security issues. You can't just say, well, it'll be ready in five years. So you have

24:53.740 --> 25:02.220
to keep shipping yield version. This brings up the social hurdles to just rewrite what's going on.

25:02.940 --> 25:08.700
Because as soon as you've done this, you've basically split your world into the maintenance

25:08.700 --> 25:14.540
of the old thing that everyone depends on and then the shiny new thing that we're off building

25:14.540 --> 25:21.900
that people are having a lot of fun and giving conference talks about. And this can really

25:21.900 --> 25:27.500
cause problems within a community when you've created this competition between the things

25:27.500 --> 25:33.100
that's being used and this new rewrite. And it can leave people out. It can leave to some frustrations.

25:34.140 --> 25:41.180
And it's not good for sort of anyone, but as a proponent of a memory safe language,

25:41.180 --> 25:45.020
I always worry about how this reflects on the language itself, right? Because if these rewrites

25:45.020 --> 25:50.700
go poorly, then it's going to set back to your goal of moving toward memory safe languages by

25:50.700 --> 25:59.900
potentially years with anyone who was affected by this. My main bit of advice here is avoid creating

25:59.900 --> 26:05.500
silos. It's silos is when you have something and it's separated from the outside world that

26:05.500 --> 26:10.620
it doesn't work well with. And as we work toward introducing memory safety into our existing

26:10.620 --> 26:16.860
ecosystems, be mindful that we're not creating this big silo with big walls from the outside world.

26:17.580 --> 26:23.420
Instead, what I suggest is that we take an incremental approach, take the existing projects

26:23.420 --> 26:28.620
that are there, right? The whole world is running on. You know, they're written in C and C++.

26:29.260 --> 26:34.540
And yet that first line of memory safe code in there, so they can start on the path,

26:35.900 --> 26:40.700
better memory safety. So when you do this, you've got to build system wired up. You

26:40.700 --> 26:44.380
got to see, what does it take to actually write that first line of code and what is the experience

26:44.380 --> 26:49.980
like? And then you move toward, well, try to write all of your new code in the memory safe language

26:49.980 --> 26:53.980
in that existing code base. You will improve memory safety, right? You're bending the arc

26:53.980 --> 26:58.860
toward memory safety over time, but you're not leaving anyone behind, you're not leaving any

26:58.940 --> 27:06.140
code behind. You're evolving the existing code base. At this incremental approach, provides improvements

27:06.140 --> 27:12.540
over time that everyone can make. Now, if you want to rewrite something in the project,

27:12.540 --> 27:17.500
that's okay. You can do a targeted rewrite. That's fine. But have a reason that isn't just

27:17.500 --> 27:21.900
I want to play with the new language. Make that reason be, well, this component needed to rewrite

27:21.900 --> 27:25.900
because it doesn't meet these functional requirements. And you know what, we're going to do it in

27:25.900 --> 27:29.420
the new language because that's what we're doing going forward. You've already established that.

27:32.540 --> 27:37.500
All right. Let's say you've gotten that first line of memory safe code into your existing

27:37.500 --> 27:41.660
C project, it has to talk to the rest of the code in the project. This is where language

27:41.660 --> 27:49.100
inner operability comes in. So Swift went all in on inner operability with C and C++. Actually

27:49.100 --> 27:55.740
embeds a full C and C++ compiler into the Swift compiler. So we use all of the M and Swift,

27:55.820 --> 28:01.020
and we embed the client compiler. So the client can parse C headers and then Swift will translate

28:01.020 --> 28:06.220
those into APIs that you can call directly from the Swift language. Very little ceremony,

28:06.220 --> 28:11.580
just to get access to everything that's already out there in C. You can also mark things in Swift

28:11.580 --> 28:16.220
as being compatible with C and those will be exported through a header that can then be used

28:16.220 --> 28:21.500
from the C part of your code base. So this is inner operability in both directions. So we can

28:21.580 --> 28:26.380
leverage what is already there and reinforce it, work with it, incrementally move forward.

28:28.220 --> 28:33.100
Let's give some examples of code. So your OS headers probably are written in C.

28:33.740 --> 28:38.380
And so you access all of your OS services with C. Maybe it's POSX, maybe it's something else,

28:38.380 --> 28:44.220
but at the end of the day, it's going to be C. We can take this in very literally translate

28:44.220 --> 28:50.140
into Swift. So if you import a POSX header into Swift, you're going to get those definitions,

28:50.460 --> 28:55.900
you know, directly translated just in syntax. The compiler understands an implementation level

28:55.900 --> 28:59.820
that these are C. So it will use the C calling conventions and type layouts and so on.

29:01.580 --> 29:05.020
But you don't actually care. This is a Swift program where you just know that the APIs that

29:05.020 --> 29:11.900
you were using in your C code are there now in your Swift code. These are not beautiful Swift APIs.

29:11.900 --> 29:15.900
First thing you'll probably do in Swift is go, ugh, and write a nice abstraction barrier.

29:15.900 --> 29:19.100
That's fine. The important part is that you can get to it from the first place with no

29:19.180 --> 29:25.980
Zaremonie whatsoever. However, we can actually do better when we're translating C into the Swift world.

29:26.700 --> 29:31.420
So this is the part of the core graphics library. It happens to be on Apple platforms,

29:31.420 --> 29:36.780
but this is indicative of a lot of C libraries out there. And that, you know, it defines things

29:36.780 --> 29:43.500
in a way that is standard to see conventions. So we have this CG color space ref pointer. And this type

29:43.580 --> 29:48.940
is always passed around as no cake objects. We have retained in release functions because they're

29:48.940 --> 29:53.500
using reference counting and C to handle object lifetimes. Completely reasonable thing to do.

29:54.060 --> 29:58.780
We've got a lot of functions that all start with CG color space. They take these CG ref parameters.

29:58.780 --> 30:03.580
There's a ton of structure here. A lot of convention that's been built up around C.

30:04.300 --> 30:10.620
And if we use that, we can provide a much nicer Swift interface more or less automatically. Without

30:10.700 --> 30:17.820
writing wrappers, we just tell Swift what the conventions are. And so this CG color space type

30:17.820 --> 30:24.620
actually comes in as a Swift class. Now Swift is automatically doing reference counting for you.

30:24.620 --> 30:29.980
It's calling those retained in release functions that you would have manually done in C automatically.

30:30.540 --> 30:35.660
So not only did we get like nicer, nicer, more ergonomic interface here. We've got initializers

30:35.660 --> 30:40.220
and properties and methods. It feels like great Swift. We got more safety out of this.

30:40.860 --> 30:45.740
Because Swift is following the conventions that were established by the C library.

30:45.740 --> 30:48.620
But safer to use the C library from Swift than it was from C.

30:52.380 --> 30:59.980
In recent years, we've been taking this to C++. C++ is a much larger language with a whole lot more

30:59.980 --> 31:06.780
idioms to think about. But we've been working through those a lot of them fit well with the way

31:06.860 --> 31:11.660
Swift works. So a C++ container like a stood vector. Well, that can be treated as a Swift collection.

31:12.300 --> 31:17.580
C++ has moved only types. Well, we can map that into the world of non-copyable types in Swift.

31:18.220 --> 31:23.580
And what this does is it opens up more interoperability. It means that more existing libraries,

31:23.580 --> 31:29.820
those written in C++, can be used in Swift and work well with Swift to allow us to write

31:29.820 --> 31:39.020
more code in memory safe languages incrementally. Language of the operability is really important.

31:39.740 --> 31:46.380
But for this to actually work, you need to get them building together. And this is not always easy.

31:47.340 --> 31:51.580
This is sort of interesting where, you know, back when Swift started, we were launching into

31:51.580 --> 31:55.820
one ecosystem. And we had this massive advantage. We didn't even realize.

31:55.900 --> 32:00.220
Which is, there was really one build system that dominated there. And we were able to modify it.

32:01.100 --> 32:07.820
Simple thing. And so what we did was we went and extended the build system so that you could mix

32:07.820 --> 32:13.820
Swift into existing projects. Effectively, with zero configuration, you could take whatever existing

32:13.820 --> 32:19.020
project, however messy, add some Swift code in there. And the build system would handle compiling

32:19.020 --> 32:23.420
them separately and linking them together and help you, you know, talk across the boundaries

32:23.420 --> 32:28.940
by leveraging that language of an interoperability. As we started looking at, you know,

32:28.940 --> 32:34.620
going cross platform, like, ah, we need a way to make sure we can build Swift on every platform.

32:35.500 --> 32:41.500
Let's build a package manager. Language specific package managers are awesome. You go clone some

32:41.500 --> 32:46.460
repo and then you do just build or run or whatever. It's one command. It's amazing.

32:48.060 --> 32:52.380
You know, we went further because we wanted to make sure, well, language level interoperability.

32:52.460 --> 32:56.940
This is important. Let's make sure it ties into the system nicely. So we can use PKG config to

32:56.940 --> 33:02.460
go find the headers for a C library and make them all available in Swift. And also the Swift

33:02.460 --> 33:06.940
package manager, let's see build C and C++ sources along with your Swift. Great. We've solved

33:06.940 --> 33:14.460
the interoperability problem. Except that we haven't, because a language specific package manager

33:14.460 --> 33:21.660
is a silo. And if your goal is to move forward incrementally to allow C and C++ projects to go

33:21.660 --> 33:26.380
and adopt a memory safe language, well, you don't want to tell them that the first thing they

33:26.380 --> 33:30.860
have to do is rewrite their entire build system. Trust me, nobody wants to rewrite their entire

33:30.860 --> 33:36.220
build system before they try your memory safe language. So you've created this massive barrier

33:37.100 --> 33:41.580
and we sort of hadn't realized that that was the issue. And so when we did realize that this

33:41.580 --> 33:48.940
barrier was there, we decided, okay, we're going to embrace C make. So C make well-known cross

33:48.940 --> 33:53.820
platform build environment, it's open source and it supports a whole bunch of different languages.

33:53.820 --> 33:58.860
There was already some basic support there for Swift. And so we work with the open source community

33:58.860 --> 34:04.620
to go ahead and make that support real. So you can add Swift as a language to your C make project

34:04.620 --> 34:10.300
and you can create Swift only targets, you can create mixed targets to have C or C++ and Swift.

34:10.300 --> 34:16.540
And if you're using C make, which so many people are, it becomes a much lower investment to get

34:16.620 --> 34:21.420
that first line of Swift code into your project. So you can start incrementally moving forward.

34:22.140 --> 34:26.940
We have a GitHub repo up here of examples that show you how to do that if you're interested.

34:27.500 --> 34:34.060
But the meta point here is build systems can be a huge barrier to entry and we need to deal with

34:34.060 --> 34:38.700
that if we want to be able to move the ecosystem forward to memory safety. Language specific

34:38.700 --> 34:42.700
package managers are awesome but they just they don't help with this particular problem.

34:43.660 --> 34:51.340
All right. So, I've been talking a lot about interoperability. We've got C and C++. We're going to

34:51.340 --> 34:56.940
make a talk to our memory safe language. But our goal was memory safety. So how is it that this hybrid

34:56.940 --> 35:04.220
environment actually is or can be memory safe? First thing to do is step back. It's proponents of

35:04.220 --> 35:10.380
a memory safe language. Remember that we can't just treat all of the C and C++ code on which the

35:10.460 --> 35:17.980
universe depends as something fundamentally irredemally unsafe. This is really not the right attitude

35:17.980 --> 35:24.220
to take. I can show an example of this. It actually comes from the Java ecosystem. This is a recent

35:24.220 --> 35:30.460
Java enhancement proposal. And what it says is basically, well, we're building for the world where

35:30.460 --> 35:37.100
we're going to treat all native code as memory unsafe. The problem here is what we know that

35:37.180 --> 35:41.500
there's native code that's memory safe. I've just been talking about one of several native

35:42.300 --> 35:49.740
memory safe languages. Right? And this proposal is basically creating a silo around the Java

35:49.740 --> 35:54.140
Merciful Machine and putting every native language, including those outside of the silo.

35:56.540 --> 36:03.420
The thing is, we can build safe interoperability between languages. So my colleague Conrad,

36:03.580 --> 36:08.220
we'll be having a talk later in the Java room on the Swift Java interoperability and how we deal

36:08.220 --> 36:14.460
with memory safety across the boundary there. But this is a general principle. If you know the

36:14.460 --> 36:19.580
conventions of the other language that you're talking to, you can figure out how to interact with

36:19.580 --> 36:27.820
it safely. And so my proposal here is we should evolve C and C++ to take those conventions that already

36:27.820 --> 36:34.300
exist and codify them. In a way that can help improve interoperability and make it more memory safe.

36:35.900 --> 36:42.060
I'm going to show some examples of this. So let's think about bound safety in C. So fundamentally,

36:42.060 --> 36:47.980
bound safety in C is hard because when you have a pointer in C, there's no bounds information.

36:47.980 --> 36:52.940
It could point to one element. It could point to 1.000 elements. That information is not there

36:52.940 --> 37:01.500
in that pointer and you can't just add it to the pointer. So if you're bringing that into a

37:01.500 --> 37:06.780
memory safe language, you're stuck using unsafe features. So in Swift it'll come in as unsafe

37:06.780 --> 37:11.580
pointer. It's screaming unsafe at you for a reason. We have no idea what the bounds in that pointer

37:11.580 --> 37:18.140
are. We have no idea what the life time of that pointer is. The thing is, if you look at this

37:18.140 --> 37:25.180
CAPI, this was designed to provide that information. The count of the number of elements that

37:25.180 --> 37:30.460
numbers points to is right there in the function signature and the documentation is going to say

37:30.460 --> 37:36.700
or at least imply that that's the count for the function. So what if we actually just said that?

37:37.980 --> 37:44.700
So this counted by attribute here is saying that the memory pointed to by numbers has count

37:44.700 --> 37:50.140
elements in it. Those are the bounds. Simple annotation moving documentation into code.

37:51.020 --> 37:58.460
Now, on the C side, if we have this, we can improve the C code by doing bounds checking on

37:58.460 --> 38:03.020
that pointer based on the count that we're given, incrementally improving the memory safety of

38:03.020 --> 38:07.500
C itself. So this is the feature that's implemented experimentally in Clang. You can go check

38:07.500 --> 38:13.900
out this URL if you're interested. It's the bounds safety flag and it helps incrementally improve

38:13.980 --> 38:19.580
safety of C, but also communicates critical information about the conventions here that are

38:19.580 --> 38:26.860
needed that you have to follow to make this API safe. And so one of the things that let's us do is

38:26.860 --> 38:33.580
if we honor that convention from the swift side, well, now we can fuse these numbers and count values

38:33.580 --> 38:38.940
that like separately together describe the information you need to be bound safe into a single

38:38.940 --> 38:43.340
parameter on the swift side of an unsafe buffer pointer. It's still unsafe because we know nothing

38:43.340 --> 38:48.940
about lifetime at this point, but we at least know the bounds and they're there with the

38:48.940 --> 38:53.180
pointer together. So we've created that information that wasn't there before or wasn't there

38:53.180 --> 39:02.220
in a mechanically verifiable way. Again, leverage safety by describing this convention, we can

39:02.220 --> 39:09.020
improve safety on both sides. Let's talk again about automatic reference counting. I showed you

39:09.020 --> 39:14.700
a little example before of taking this convention of automatic reference counting forward. Let's

39:14.700 --> 39:20.140
dig into another example here. So this is from the Knome G lib library, so one of the lower level

39:20.140 --> 39:24.380
libraries with the Knome Toolkit. And there's this G variant type that uses reference counting,

39:24.380 --> 39:29.580
like so many things in these Knome libraries. And, you know, it's this G variant type, there's a

39:29.580 --> 39:34.700
ref in an unref, there's some couple of other operations. We could bring this into swift just with

39:34.780 --> 39:39.740
a whole bunch of unsafe pointers, but we would rather state what the convention is. And so we can

39:39.740 --> 39:44.940
state with this macro here, the swift shared reference macro, that in fact G variant is meant to be

39:44.940 --> 39:51.340
used as a ref counted type. Variant ref's in variant unrest or the retain and the release operations

39:51.340 --> 39:56.620
respectively. And by doing this, we've stated what the convention is. So in swift, we can bring

39:56.620 --> 40:01.420
this in as a class. Now, there's other things we may have to annotate, so this G variant new double.

40:01.500 --> 40:05.420
What does that return? Like, did it return something where you're responsible for

40:05.420 --> 40:10.780
incrementing the reference count before you destroy it or not? We don't know. And so this is again

40:10.780 --> 40:15.420
another annotation to say, well, it returns a retained reference. So it's returning at plus one,

40:15.420 --> 40:21.500
or it's already retained at for you, you need to go and do the release yourself when you're done

40:21.500 --> 40:27.180
with it. By establishing the convention, right, which should be in the documentation anyway to be clear,

40:27.260 --> 40:31.260
but by putting in the signature here, we can actually have swift fall that convention and

40:31.260 --> 40:36.060
provide safe access to this type. Now, I've done one more thing here. I'd notice I've marked the

40:36.060 --> 40:42.940
the return pointer as non-null, right? As I said before, swift doesn't have null pointers. And so

40:42.940 --> 40:47.820
if we have a pointer coming in from C, we have to assume it could be null, so we treat it as an optional

40:47.820 --> 40:53.020
type. By marking this as non-null, we're stating that no, this will never be a null pointer

40:53.020 --> 41:02.460
when coming out of C, and so we can use a non-optional type. So these two macros essentially

41:02.460 --> 41:08.540
let us state in C the convention's on reference counting so that we can make the swift code

41:08.540 --> 41:15.740
use these APIs directly. Now, extra translation layer and get memory safe behavior out of it.

41:15.740 --> 41:20.060
Biler will automatically put in the retains and releases based on those C functions you provided,

41:21.020 --> 41:26.460
giving you memory safe access to this underlying C. If we want to go a little further,

41:26.460 --> 41:31.500
we can add some annotations and say, hey, actually be really nice if, you know, that new

41:31.500 --> 41:36.700
double function was treated like an initializer to create the class the way you would probably want to

41:36.700 --> 41:42.380
in swift code. And then you can turn, you know, the various functions into methods or properties,

41:42.380 --> 41:48.940
just to give a nice swift interface to make it easier to use. So you get safety and you get nice

41:49.020 --> 41:54.300
ergonomics just from this, you know, adding annotations into the C header, describing the

41:54.300 --> 42:03.340
conventions that we're already there. There's other lifetime safety attributes in Clang to

42:03.340 --> 42:09.820
color of other situations, right? Reference counting isn't everything. There's this no escape

42:09.820 --> 42:15.420
attribute, which basically says, if you have a parameter that's no escape, then that pointer will

42:15.500 --> 42:19.980
only be used within the body of that function. It's not going to be saved somewhere in access later.

42:19.980 --> 42:24.380
This is really important information because it says, it's okay to pass down a pointer to some

42:24.380 --> 42:29.580
temporary, it's on the stack, for example, whether you're going to remove afterward. There's also

42:29.580 --> 42:34.460
the much more complicated lifetime bound attribute that's newer, that describes the relationship

42:34.460 --> 42:39.500
between sort of the lifetime of a pointer parameter that comes in and says that the result of the

42:39.500 --> 42:44.380
function points somewhere into the data structure that came from that pointer, right? So it establishes

42:44.380 --> 42:51.260
this important link. Now, the important thing about these attributes being there is we can

42:51.260 --> 42:56.140
use them on the swift side, but they can also be used to improve C and C++. Because if you've added

42:56.140 --> 43:02.380
these annotations, some static analysis tool for C and C++ can go and make sure that those actually

43:02.380 --> 43:06.460
do hold. Make sure that you don't escape the pointer that you said was no escape or that you're

43:06.460 --> 43:14.220
following these lifetime rules. Adding these to a header, therefore improves the world for

43:15.180 --> 43:20.620
C and improves the world for swift. And so if we go and add this no escape attribute to numbers,

43:20.620 --> 43:25.820
which is documenting the behavior we already expected there, well, we can bring this into swift

43:25.820 --> 43:30.780
in an even better form. No one's safe here anymore because we get to bring this parameter in as a

43:30.780 --> 43:36.940
span. Span is like a reference to some kind of contiguous memory where we have the count,

43:36.940 --> 43:41.260
we know the bounds information and we know the lifetime of it, right? And so we can make sure that

43:41.260 --> 43:48.300
it doesn't, isn't used past the lifetime of that particular entity. So the CPI is now far safer

43:48.860 --> 43:58.860
to be more verified from the C side and it's safe to use from the swift side. Now, I just talked

43:58.860 --> 44:04.300
about a whole lot of modifications to genome headers. You can't usually do that with your system

44:04.300 --> 44:09.100
headers. You can't just go and rewrite them. And so one of the things we found here is if you can't

44:09.100 --> 44:12.460
modify the headers, you don't own them, can't get the maintainer, take your patch, don't want to

44:12.460 --> 44:18.140
wait for the updates to roll out. We have this separate mechanism. We call API notes. And so this is

44:18.140 --> 44:24.060
actually a YAML file that you can sit on the side and it can come with your own project to layer

44:24.060 --> 44:30.380
this convention information on top of a C library that you use. And so I didn't actually touch

44:30.380 --> 44:36.060
my canone headers when I was playing with this demo project. I just wrote API notes directly

44:36.060 --> 44:41.740
to go and layer conventions on top of my existing system headers for genome to get this nice

44:41.740 --> 44:50.300
safe access to the existing C library. Now, this is not a solution that will work forever. The

44:50.300 --> 44:54.940
right answer is to get those annotations into the headers at some point. But let's do incrementally

44:54.940 --> 45:00.140
move forward by translating the documentation of conventions into code that everyone can use.

45:00.140 --> 45:10.140
So this kind of safe interoperability. We're talking across the language boundary to

45:10.140 --> 45:16.140
provide safety. This is going to require coordination. And so our general software community

45:16.140 --> 45:19.820
is going to have to actually work on this together and it's going to require work like real

45:19.820 --> 45:25.740
work from a lot of different places. So some of that work is going to have to be in the C

45:25.740 --> 45:32.220
++ communities and their committees that evolve the language to find a standard way to

45:32.220 --> 45:39.660
codify these conventions so they can be rolled out throughout C libraries. And we shouldn't be codifying

45:39.660 --> 45:43.980
them with swift shared reference because this isn't just about swift. This is about documenting

45:43.980 --> 45:49.180
the memory safety conventions that exist. And so things like nullability, these lifetime

45:49.180 --> 45:55.100
annotations, these bound annotations. We should standardize those in C and C++ and start adopting

45:55.100 --> 46:00.380
them throughout our system libraries. Now we need to do this in a way that benefits C and C++.

46:01.260 --> 46:07.100
So these should come with optional runtime checking for things like bounds when you add bounds

46:07.100 --> 46:13.740
annotations or static analysis tools that can verify these so that when you go and say okay I'm

46:13.740 --> 46:18.700
going to add these annotations to my library to make it better it makes the C code based incrementally

46:18.700 --> 46:25.580
better. So we improve what we have and we build a bridge to the memory safe future where we can

46:25.580 --> 46:32.220
use those annotations to provide better safer interfaces in the memory safe language. So I think on

46:32.220 --> 46:37.180
the memory safe language side we need to prioritize thinking about interoperability with the

46:37.180 --> 46:42.300
C family of languages, making sure that's safe and easy to do both at a language level and at

46:42.300 --> 46:48.380
the build system level. And when these changes come along to C and C++ to add this convention

46:48.380 --> 46:54.620
interoperation we need to go and honor that on the on the side of the memory safe language.

46:54.620 --> 47:01.340
So now that we have this convention information we can reason about what it takes to use this

47:01.340 --> 47:08.620
safely. And then say okay this whole program right where we've documented all the conventions

47:08.620 --> 47:13.820
and we have checking we can reason about its memory safety properties. This is an incremental step forward.

47:14.940 --> 47:20.380
When we do this we can get a faster rollout of memory safe languages because we've compartmentalized the

47:20.380 --> 47:30.700
problem. So a couple of parting thoughts here. The goal here is to incrementally move memory safety

47:30.700 --> 47:36.700
forward and we want to be able to take sort of any part of the system and when we put in some work

47:36.780 --> 47:40.380
to the memory safety whether it's you know bringing up support for memory safe language,

47:40.380 --> 47:46.060
rewriting a piece or showing up the secret that's there by documenting conventions. That moves

47:46.060 --> 47:52.380
memory safety forward for that ecosystem. As we do this be mindful to avoid creating silos.

47:53.420 --> 47:57.020
Don't don't build up a memory safe silo over here and say well we can't work with the rest of this

47:57.020 --> 48:02.860
world. It's not memory safe. Try to keep it moving together so because this is going to take

48:02.940 --> 48:08.860
everyone in the industry to move forward. And we have to work across these language barriers to improve

48:08.860 --> 48:14.540
safety throughout. There's no way we can build up any one silo that's big enough to cover an

48:14.540 --> 48:19.900
entire ecosystem. So we have to keep working across languages maintaining safety across these boundaries

48:19.900 --> 48:29.420
to make progress. I've talked a lot about Swift. If you're interested you can check out Swift.org

48:29.420 --> 48:34.460
for some resources and learning it. There's a Swift room here at Fossom. So it's up on the fourth floor

48:34.460 --> 48:38.700
in this building. I think we start three o'clock this afternoon. We've got some great talks and demos

48:38.700 --> 48:44.380
on embedded Swift, Swift on server, all sorts of other interesting Swift talks. In the Java

48:44.380 --> 48:49.660
in the free Java room there will be a Conrad's talk on Swift and Java interoperability and how to

48:49.660 --> 48:57.260
get safety along the funders. All right well thank you very much. If you have any questions please come

48:57.260 --> 48:59.420
talk to me after.

