1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
|
<!-- Automatically generated by emacsconf-publish-after-page -->
<a name="rust-mainVideo-transcript"></a>
# Transcript
[[!template new="1" text="""Rune""" start="00:00:00.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Hello, EmacsConf. My name is Troy Hinckley, and this is my""" start="00:00:00.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""talk on Rune, a Rust implementation in Emacs. We strive to be""" start="00:00:05.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""bug compatible with Emacs, so you can use the same Elisp.""" start="00:00:08.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""It's still a fairly early stage experimental project, and""" start="00:00:11.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""we have some basic things implemented.""" start="00:00:14.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""The Emacs core""" start="00:00:17.082" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Before I get started, I want to talk a bit more""" start="00:00:17.082" video="mainVideo-rust" id="subtitle"]]
[[!template text="""about what the core is.""" start="00:00:19.947" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So the Emacs core, it includes the runtime, the interpreter,""" start="00:00:21.848" video="mainVideo-rust" id="subtitle"]]
[[!template text="""garbage collector, everything used to run the code.""" start="00:00:24.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""It includes the GUI. It includes all the data structures.""" start="00:00:26.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""If you look underneath all the Elisp data structures,""" start="00:00:29.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""there's C code underneath there,""" start="00:00:31.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""as well as the auxiliary functions""" start="00:00:33.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""of which there's about 1500. In making this talk, I don't""" start="00:00:35.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""want to give the impression that I'm saying the core is""" start="00:00:39.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""outdated or that needs to be replaced or that it can't be""" start="00:00:40.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""evolved on its own, because clearly it has continued to""" start="00:00:42.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""evolve. If we look in just the last few years, we can see that""" start="00:00:45.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""we've added native compilation, we've added tree-sitter""" start="00:00:48.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""support, we've added color emoji, and there's work right""" start="00:00:50.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""now to add a new garbage collector to Emacs as well.""" start="00:00:52.760" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Why create this?""" start="00:00:57.168" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Why create this project? Emacs has a long history.""" start="00:00:57.168" video="mainVideo-rust" id="subtitle"]]
[[!template text="""It has a lot of users. It needs to support a big community.""" start="00:01:01.072" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Because of that, it has to be very conservative""" start="00:01:04.536" video="mainVideo-rust" id="subtitle"]]
[[!template text="""about what things it can allow into the project.""" start="00:01:06.838" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Forks like this create an""" start="00:01:10.322" video="mainVideo-rust" id="subtitle"]]
[[!template text="""opportunity to experiment and try new approaches.""" start="00:01:11.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""This is particularly a good use case for Rust because the C core,""" start="00:01:15.587" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it's pretty well tested. It's been around for a long time.""" start="00:01:18.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""A lot of the bugs have been ironed out, but when you're doing a""" start="00:01:20.850" video="mainVideo-rust" id="subtitle"]]
[[!template text="""new greenfield project, it's very easy to introduce new""" start="00:01:22.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""undefined behavior and memory unsafety""" start="00:01:26.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and stuff like that. Rust protects us from most of that,""" start="00:01:28.775" video="mainVideo-rust" id="subtitle"]]
[[!template text="""but it also gives us the ability to be fast""" start="00:01:32.377" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and has a strong ecosystem behind it.""" start="00:01:34.938" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Rust is also really good at multi-threading.""" start="00:01:37.884" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Their phrase in the community is fearless concurrency.""" start="00:01:40.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""They should be able to write concurrent programs without""" start="00:01:43.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""having to worry about data races. It's also really high""" start="00:01:45.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""performance. It has a really good regex engine. It's known""" start="00:01:49.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""for its non-copy I/O as well.""" start="00:01:51.840" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How does this compare to other projects?""" start="00:01:55.865" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How does this compare to other""" start="00:01:55.865" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Rust and Emacs projects, whether there's been a couple? The""" start="00:01:57.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""first is Remacs. This project was the first. It took an""" start="00:01:59.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""outside-in approach. Basically you could take a C""" start="00:02:02.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""function and replace it with a Rust function and build it""" start="00:02:05.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""together as one executable. This is pretty easy to do""" start="00:02:09.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""because they could both talk over the C ABI. You could""" start="00:02:11.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""swap out functions once at a time. They made really good""" start="00:02:14.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""progress at first, but eventually they ran into the problem""" start="00:02:16.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that as you get down to the really core parts of it, you can't""" start="00:02:20.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""just replace one function at a time anymore, because some of""" start="00:02:23.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that functionality is connected to other things. Like for""" start="00:02:25.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""example, you can't replace the garbage collector without""" start="00:02:28.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""replacing the entire garbage collection system. So the""" start="00:02:30.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""progress really kind of slowed down. Another issue with it""" start="00:02:32.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""was, is that they were doing a one-to-one rewrite, so they""" start="00:02:36.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""weren't adding any new features or functionality, just""" start="00:02:38.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""taking the same code and replacing it in Rust, which doesn't""" start="00:02:41.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""add any advantages in and of itself.""" start="00:02:43.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""This spawned Emacs-NG, which was kind of the spiritual successor to""" start="00:02:46.802" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Remacs, where they decided to add new functionality,""" start="00:02:50.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the biggest one being a JavaScript runtime,""" start="00:02:52.747" video="mainVideo-rust" id="subtitle"]]
[[!template text="""as well as some new renderers to Emacs.""" start="00:02:55.809" video="mainVideo-rust" id="subtitle"]]
[[!template text="""This is no longer actively developed though.""" start="00:02:58.231" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading""" start="00:03:01.315" video="mainVideo-rust" id="subtitle"]]
[[!template text="""In this project, one of the big focuses we have is""" start="00:03:01.315" video="mainVideo-rust" id="subtitle"]]
[[!template text="""on multi-threading. The C core itself is, everything is""" start="00:03:04.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""designed around being single-threaded, all the data""" start="00:03:07.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""structures and everything like that. Rust has a great""" start="00:03:09.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""concurrency story. In Rust, everything is intended to be""" start="00:03:13.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""multi-threaded. That doesn't mean that everything has to""" start="00:03:15.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""run on multiple threads, but you can't write something that""" start="00:03:18.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""is limited to only running in a single-threaded""" start="00:03:20.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""environment. So this makes it really easy to use all the""" start="00:03:22.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""existing packages and build something that is""" start="00:03:25.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""concurrency safe. which is what we've done here,""" start="00:03:28.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and that was relatively easy to do.""" start="00:03:30.481" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp""" start="00:03:32.441" video="mainVideo-rust" id="subtitle"]]
[[!template text="""But adding it to Elisp is the hard part,""" start="00:03:32.441" video="mainVideo-rust" id="subtitle"]]
[[!template text="""because we've got to come up with a good model""" start="00:03:34.782" video="mainVideo-rust" id="subtitle"]]
[[!template text="""for Lisp, and Elisp is just a giant ball""" start="00:03:36.503" video="mainVideo-rust" id="subtitle"]]
[[!template text="""of mutable state. We need to find some""" start="00:03:39.625" video="mainVideo-rust" id="subtitle"]]
[[!template text="""way to tame that so we can make workable concurrency""" start="00:03:41.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""out of it. There's really two ways you can do this.""" start="00:03:44.567" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""No-GIL method""" start="00:03:47.648" video="mainVideo-rust" id="subtitle"]]
[[!template text="""One is what I call the no-GIL method.""" start="00:03:47.648" video="mainVideo-rust" id="subtitle"]]
[[!template text="""This is what Python is doing, where""" start="00:03:49.269" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you take all of your data structures, you make them""" start="00:03:51.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""concurrency safe, and then you just leave it up to the""" start="00:03:53.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""programmer to decide what they're going to do with it.""" start="00:03:56.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""They've got to build safe abstractions on top of that.""" start="00:03:58.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""One of the big downsides with this is that""" start="00:04:00.468" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it comes with a pretty high cost.""" start="00:04:03.087" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The last benchmarks I've seen is that by making""" start="00:04:05.248" video="mainVideo-rust" id="subtitle"]]
[[!template text="""everything concurrency safe in Python, single-threaded""" start="00:04:07.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""code is about 20% slower in some benchmarks.""" start="00:04:10.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Since most code is single-threaded, this has a big""" start="00:04:15.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""performance impact for most code that isn't taking""" start="00:04:19.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""advantage of the multi-threading. The other thing is this""" start="00:04:21.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""introduces a lot of nasty concurrency bugs because you can""" start="00:04:23.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""have anything mutating any part of the data from any thread,""" start="00:04:26.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""even if you can't have memory unsafety per se.""" start="00:04:29.040" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Actors""" start="00:04:32.638" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other option is actors,""" start="00:04:32.638" video="mainVideo-rust" id="subtitle"]]
[[!template text="""which are a really known way to approach this,""" start="00:04:34.739" video="mainVideo-rust" id="subtitle"]]
[[!template text="""where you trade some of that flexibility that you get""" start="00:04:36.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""with fully concurrent for more control and. Code and""" start="00:04:39.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""functions are shared between all the different threads,""" start="00:04:43.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""but data has to be passed along channels between different""" start="00:04:45.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""actors.""" start="00:04:50.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (functions)""" start="00:04:51.252" video="mainVideo-rust" id="subtitle"]]
[[!template text="""We want the functions to be shared, and this""" start="00:04:51.252" video="mainVideo-rust" id="subtitle"]]
[[!template text="""should be pretty easy because we don't mutate functions""" start="00:04:52.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""like we do data, except when we do. In Lisp, functions are""" start="00:04:55.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""just lists like anything else. So you can mutate them""" start="00:05:00.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""just like lists. Even if you're not talking about""" start="00:05:03.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""interpreted code, like if you have a native compiled""" start="00:05:06.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""function, you can still mutate the constants inside the""" start="00:05:09.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""function. For example, here we have a function returns a""" start="00:05:11.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""string. We take that string out, we mutate that string, and""" start="00:05:14.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""now the function returns a different string. In Rune, we""" start="00:05:17.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""enforce that all functions, their constants are""" start="00:05:23.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""immutable. You can't mutate the insides of a function. You""" start="00:05:25.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can still swap out functions and redefine them, but you""" start="00:05:27.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can't mutate the inside of a function. This enables them""" start="00:05:29.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to be safely shared across threads.""" start="00:05:32.240" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Caveats""" start="00:05:34.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""However, there are some caveats to this.""" start="00:05:34.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""For example, some functions actually do""" start="00:05:36.401" video="mainVideo-rust" id="subtitle"]]
[[!template text="""need to mutate their own data. The example that we run into is""" start="00:05:38.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""cl-generic. It uses a method cache. So it has to be able to""" start="00:05:41.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""update that cache. In this case, we just made a special""" start="00:05:44.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""case for this particular situation, but we don't know what""" start="00:05:47.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""more of these we're gonna run into the future where this is""" start="00:05:50.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""needed behavior to be able to mutate a function.""" start="00:05:53.160" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (data)""" start="00:05:57.090" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Okay, so functions are pretty easy.""" start="00:05:57.090" video="mainVideo-rust" id="subtitle"]]
[[!template text="""They just can be shared between""" start="00:05:59.811" video="mainVideo-rust" id="subtitle"]]
[[!template text="""threads, but data can't be immutable, at least not into the""" start="00:06:00.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""model that Emacs currently has. We have two different""" start="00:06:05.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""ways to handle this. One is we require whenever you're""" start="00:06:08.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""calling some other code in a different thread, you have to""" start="00:06:12.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""send all the variables that it's going to need over to that""" start="00:06:14.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""thread. This is how you traditionally do inside actors.""" start="00:06:17.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Any data that needs to go to a different actor needs to be sent""" start="00:06:19.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""over a channel. It's relatively easy implementation, but""" start="00:06:21.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""this is difficult in the Emacs case because everything is""" start="00:06:25.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""going to be accessing different variables. That means""" start="00:06:28.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""when you call something, you have to know ahead of time, all""" start="00:06:30.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the different variables that are gonna be accessed inside""" start="00:06:33.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that other thread and put those in when you call it.""" start="00:06:34.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Copy values to other threads on demands""" start="00:06:38.249" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other option we're using is we're copying values to the""" start="00:06:38.249" video="mainVideo-rust" id="subtitle"]]
[[!template text="""other threads on demand. If you're running a thread, it""" start="00:06:40.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""tries to look up a variable. It doesn't have any value for""" start="00:06:43.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that variable. It will go back and ask the main thread and it""" start="00:06:45.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""will copy that value into that thread and it can continue""" start="00:06:48.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""execution. This is nice because you can just launch some""" start="00:06:50.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""code and it'll take care of handling all the data transfer""" start="00:06:53.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""for you.""" start="00:06:55.640" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Multi-threading elisp (buffers)""" start="00:06:57.884" video="mainVideo-rust" id="subtitle"]]
[[!template text="""But we don't want to be copying around is buffers,""" start="00:06:57.884" video="mainVideo-rust" id="subtitle"]]
[[!template text="""because they can be really large. In this case, we have a""" start="00:07:00.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""mutex. Each thread could only have one current buffer that""" start="00:07:04.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it has an exclusive lock to. This comes with some""" start="00:07:07.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""trade-offs, big one being that if the user tries to access""" start="00:07:12.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""some buffer, they want to type something, and a background""" start="00:07:16.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""thread is holding onto that buffer, what do we do in that""" start="00:07:18.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""situation? And we still need to hold an exclusive lock, even""" start="00:07:20.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""if we're only going to read a buffer. If you have multiple""" start="00:07:24.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""readers, they each still need to take turns because we can't""" start="00:07:26.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""determine if at some point a thread is going to try and mutate""" start="00:07:29.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the buffer. It has to be an exclusive lock. The other issue""" start="00:07:31.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""is buffer-locals. This is less of a implementation issue""" start="00:07:33.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""as much as it is a technical issue. Because you think about""" start="00:07:37.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""when we switch to a buffer, it has some buffer-local data and""" start="00:07:40.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""we have some thread-local data. As we go through, we're""" start="00:07:42.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""mutating everything. Those can get intertwined and""" start="00:07:45.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""pointing to each other. Then we switch away from that""" start="00:07:47.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""buffer. We need some quick way to be able to separate those""" start="00:07:49.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""out. The buffer-locals can go with the buffer-locals and""" start="00:07:51.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the thread data can stay with thread data and make copies of""" start="00:07:54.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""anything that was pointing to the other side. But we don't""" start="00:07:56.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""have a good method to determine how to separate those two,""" start="00:07:58.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""like what data belongs to this and what data belongs to this,""" start="00:08:02.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""so that we can do that quickly. We haven't found a good""" start="00:08:05.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""solution to that yet, but it's something we're still""" start="00:08:08.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""working on.""" start="00:08:09.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Would this actually be useful?""" start="00:08:11.903" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The question is, would this actually be""" start="00:08:11.903" video="mainVideo-rust" id="subtitle"]]
[[!template text="""useful for doing real work inside Emacs? I would say,""" start="00:08:13.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""yes, there's a lot of things you can do with this. You could""" start="00:08:15.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""handle process output in the background. You can do syntax""" start="00:08:17.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""highlighting. You can do buffer search in parallel. You can""" start="00:08:20.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""do LSP. You can do fetching your mail in the background. You""" start="00:08:23.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can have a window manager that doesn't block your window""" start="00:08:26.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""manager when Emacs is blocked. You could do""" start="00:08:29.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""something like a file system watcher that keeps up on files""" start="00:08:32.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""without blocking Emacs. This wouldn't be so great for""" start="00:08:34.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""building concurrent data structures or operating on""" start="00:08:37.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""shared data or building your own abstractions, because of the""" start="00:08:39.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""trade-offs that we've made here. Okay. That's talking""" start="00:08:42.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""about multi-threading.""" start="00:08:46.040" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Precise garbage collection""" start="00:08:46.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other thing we're going to talk""" start="00:08:46.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""about is precise garbage collection. In Rune, we have a""" start="00:08:47.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""safe, precise garbage collection because of the Rust type""" start="00:08:51.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""system. Let's look at what the problem is with garbage""" start="00:08:54.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""collection in the first place. Really, the tricky part""" start="00:08:58.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""about garbage collection is rooting. How do we find out what""" start="00:09:00.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the roots are? These are all the values that are on the""" start="00:09:03.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""stack or inside the registers. In this example here, we""" start="00:09:06.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""allocate an object. We call garbage_collect, that object's""" start="00:09:08.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""collected, and then we try and return it.""" start="00:09:11.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""It's no longer valid.""" start="00:09:13.537" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How Emacs used to deal with roots""" start="00:09:16.537" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Let's look at how Emacs used to deal with this""" start="00:09:16.537" video="mainVideo-rust" id="subtitle"]]
[[!template text="""problem way back in the day. There was a system called gcpro""" start="00:09:19.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""or GC Protect, which is basically designed that every time a""" start="00:09:22.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""value needed to survive past a garbage collection point,""" start="00:09:26.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you had to try and protect it. In order to do this, you had""" start="00:09:28.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to declare a struct, you had to put a macro around it to root""" start="00:09:32.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the object, and then you had to unroot it when you were done--""" start="00:09:35.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""past the garbage collection. Now the value is safe. You""" start="00:09:38.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can see down here, I pulled these eight rules out from a""" start="00:09:41.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""really old version of the Emacs manual about all the things""" start="00:09:44.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you had to keep track of when you were trying to use this""" start="00:09:46.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""system. All right, so there was a special handling for""" start="00:09:49.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""nested GC protects. You had to make sure the memory was""" start="00:09:52.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""initialized. You had to make sure that traps couldn't occur""" start="00:09:54.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""between allocating and when GC protect would happen. It""" start="00:09:58.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can be tricky because you don't always know when a function""" start="00:10:00.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that's getting called could potentially call garbage""" start="00:10:03.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""collection. So if you got something wrong, you also""" start="00:10:06.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""might not catch it for a long time because garbage""" start="00:10:10.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""collection may only get called one out of 99 times. The other""" start="00:10:12.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""99 times is just fine. That one time it happens and you""" start="00:10:15.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can't reproduce the issue. When you do get this wrong and""" start="00:10:19.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""some, something doesn't get rooted and it gets""" start="00:10:22.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""overwritten, it generally doesn't show up right where the""" start="00:10:24.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""problem is. It gets showed up way later when you actually try""" start="00:10:26.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and access the value and the value is invalid. You've got""" start="00:10:28.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to track it back to where that thing did not get properly""" start="00:10:31.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""rooted. It's a huge source of bugs and very hard to""" start="00:10:33.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""maintain.""" start="00:10:37.360" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Conservative stack scanning""" start="00:10:38.713" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Emacs decided to go with a different path,""" start="00:10:38.713" video="mainVideo-rust" id="subtitle"]]
[[!template text="""which we call conservative stack scanning. Basically,""" start="00:10:40.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the garbage collector just looks at the stack and all the""" start="00:10:42.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""registers and any data inside there that looks like it could""" start="00:10:45.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""be a pointer, it treats it as a pointer. This is nice because""" start="00:10:47.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you get really easy root tracking,""" start="00:10:52.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""but it also comes with some trade-offs,""" start="00:10:54.712" video="mainVideo-rust" id="subtitle"]]
[[!template text="""mostly that your objects are no longer movable.""" start="00:10:56.114" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Movable objects""" start="00:11:00.157" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Why would we want movable objects in Emacs?""" start="00:11:00.157" video="mainVideo-rust" id="subtitle"]]
[[!template text="""There's a couple of different reasons. One is compaction.""" start="00:11:03.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""You can take all your heap, you can pack that on down because""" start="00:11:05.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you can coalesce all your objects together. Another is that""" start="00:11:08.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it's easy to implement generational garbage collection.""" start="00:11:11.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""You can just copy everything out of your minor heap into your""" start="00:11:13.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""older heap. Really, Emacs is kind of uniquely ideal for""" start="00:11:16.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""generational collection, because the typical way we""" start="00:11:21.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""interact with Emacs is as a series of commands. You execute""" start="00:11:24.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""some command, you'd execute the next command, you execute""" start="00:11:27.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""a command. It could be happening every key press, it could be""" start="00:11:29.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""happening with M-x. However long that command is, that is""" start="00:11:33.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the ideal length for the minor collection generation, the""" start="00:11:36.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""first generation. Because once you're done with that""" start="00:11:40.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""generation, anything that's still existing is going to be""" start="00:11:43.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""around for a very long time. So that works out really well""" start="00:11:45.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""for Emacs. We want to make this a generational collector.""" start="00:11:49.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other thing is with object layout. We use a lot of lists""" start="00:11:52.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""inside Emacs Lisp. Every time you go to the cdr, you've""" start="00:11:56.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""got to be chasing a pointer around the heap and following""" start="00:12:00.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that. That can potentially result in cache misses and""" start="00:12:03.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""all sorts of other things like that. So it can take a long""" start="00:12:05.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""time. It can be quite slow. But if you have the ability to move""" start="00:12:08.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""objects, you can just relocate an entire list and lay it out""" start="00:12:12.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""in an array right next to each other inside memory.""" start="00:12:16.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So iterating over it is just as fast as iterating over an array.""" start="00:12:19.169" video="mainVideo-rust" id="subtitle"]]
[[!template text="""But you can only do that if you have movable objects.""" start="00:12:22.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""I'll point out here too, that with conservative stack scanning,""" start="00:12:25.422" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it's not that all objects are immovable. It's only ones that""" start="00:12:28.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""are pointed to from the stack or from the registers that have""" start="00:12:31.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to become immovable.""" start="00:12:35.520" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How Rust makes precise GC easy""" start="00:12:38.829" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Let's look at how Rust makes precise""" start="00:12:38.829" video="mainVideo-rust" id="subtitle"]]
[[!template text="""garbage collection easy. Here I have some Rust code to""" start="00:12:41.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""show kind of how the lifetime system works and what we call""" start="00:12:44.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""XOR mutability, where we can only have one mutable""" start="00:12:47.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""reference or multiple immutable references to the same""" start="00:12:49.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""thing. Here we declare a vector, we take a reference to the""" start="00:12:52.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""first element of the vector, and then we mutate the vector.""" start="00:12:56.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Now this could potentially resize the vector and move it to a""" start="00:12:59.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""different location in memory, so that reference is no""" start="00:13:02.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""longer valid. The nice thing is, Rust catches this for""" start="00:13:04.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""us. It says, hey, this is no longer valid. This reference""" start="00:13:07.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can't survive past when you mutated it. Okay? That's""" start="00:13:10.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""exactly what we want for a garbage collector. You can see""" start="00:13:14.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""here, we take this in a garbage collection context, we""" start="00:13:17.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""create a new context object, we add an object, we call""" start="00:13:19.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""garbage_collect, then we try and access that object. It's no""" start="00:13:23.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""longer accessible, and Rust will prevent us from trying to""" start="00:13:26.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""access that variable. So, how do we solve this? We have a""" start="00:13:29.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""root macro. We declared this root macro, it lets us take the""" start="00:13:34.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""object and let it live past garbage collection, and""" start="00:13:39.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""everything works out. The nice thing is, this root macro""" start="00:13:41.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""will get dropped when it's out of scope, so we don't have to""" start="00:13:45.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""worry about the un-gc-protect step of this. Statically,""" start="00:13:47.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Rust will verify and tell us any object that needs to be""" start="00:13:51.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""rooted. If we try and access it, it'll tell us it's invalid.""" start="00:13:55.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""We have this root macro and then we can access it. So in""" start="00:13:58.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that way, we have safe, precise garbage collection without""" start="00:14:01.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""any chance of introducing undefined behavior, which is""" start="00:14:03.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""really, really powerful. It's really easy because the""" start="00:14:07.480" video="mainVideo-rust" id="subtitle"]]
[[!template text="""type system will catch it all for us.""" start="00:14:10.000" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Other Rust niceties: proc macro""" start="00:14:13.227" video="mainVideo-rust" id="subtitle"]]
[[!template text="""There's some other Rust niceties I want to kind of""" start="00:14:13.227" video="mainVideo-rust" id="subtitle"]]
[[!template text="""talk through that are useful, but""" start="00:14:15.148" video="mainVideo-rust" id="subtitle"]]
[[!template text="""are not, you know, star features. One is proc macros. You""" start="00:14:16.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""can see up on the top, you can see how you declare a function""" start="00:14:21.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""inside the C core. All right. You have to use the macro. You""" start="00:14:23.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""have to put the list type, the function type,""" start="00:14:27.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the struct type, the different types of arguments""" start="00:14:29.142" video="mainVideo-rust" id="subtitle"]]
[[!template text="""or different number of arguments, the doc string,""" start="00:14:30.964" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and then you can put your argument listing down inside there.""" start="00:14:33.226" video="mainVideo-rust" id="subtitle"]]
[[!template text="""On the Rust side, we just write this like we would""" start="00:14:36.024" video="mainVideo-rust" id="subtitle"]]
[[!template text="""any other Rust function. And then we put""" start="00:14:37.985" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the defun proc macro on there""" start="00:14:40.045" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and it takes care of everything for us behind the scenes.""" start="00:14:41.286" video="mainVideo-rust" id="subtitle"]]
[[!template text="""A couple of cool additional things we can do with this""" start="00:14:44.187" video="mainVideo-rust" id="subtitle"]]
[[!template text="""is that we don't have to make everything just an object.""" start="00:14:46.408" video="mainVideo-rust" id="subtitle"]]
[[!template text="""We can actually make things""" start="00:14:48.728" video="mainVideo-rust" id="subtitle"]]
[[!template text="""more specific types. Here we have symbols. As well as""" start="00:14:49.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you can see subfeature, it's an optional parameter, and we""" start="00:14:54.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""just make it an option inside Rust and it automatically make""" start="00:14:56.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it an optional inside Elisp.""" start="00:15:00.920" video="mainVideo-rust" id="subtitle"]]
[[!template text="""This makes them really easy to write.""" start="00:15:03.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""I can't take credit for this is because this is""" start="00:15:05.182" video="mainVideo-rust" id="subtitle"]]
[[!template text="""something that I saw inside Remacs and I stole from them, but""" start="00:15:06.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it makes the functions really easy to call from each other""" start="00:15:09.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and really easy to write as well.""" start="00:15:11.440" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""sum types""" start="00:15:14.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Another thing that's really nice is sum types.""" start="00:15:14.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""In the C core, if I wanted to get a""" start="00:15:18.524" video="mainVideo-rust" id="subtitle"]]
[[!template text="""string out of an object, I would first need to check that it's""" start="00:15:21.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""a string and then dereference it as a string. But if it's not a""" start="00:15:23.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""string, I may introduce undefined behavior. So in""" start="00:15:28.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""complicated code, I have to make sure that I have always""" start="00:15:30.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""checked what type it is before I try and dereference that""" start="00:15:32.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""type. We don't have to worry about any of that inside Rust""" start="00:15:34.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""because we can untag a value and we can use their some types,""" start="00:15:37.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""basically create an enum and we can match on what the""" start="00:15:41.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""different values can be. Then we only get out the types""" start="00:15:44.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that are viable or are actually there. So we never""" start="00:15:47.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""accidentally get something out of an object that we didn't""" start="00:15:50.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""mean to, or dereference it as something that doesn't""" start="00:15:52.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""really exist. We can just match on it and we can get out the""" start="00:15:54.240" video="mainVideo-rust" id="subtitle"]]
[[!template text="""values that we need, which is really, really powerful.""" start="00:15:56.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Regex""" start="00:16:01.041" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So there's some other Rust niceties as well working with here.""" start="00:16:01.041" video="mainVideo-rust" id="subtitle"]]
[[!template text="""One is the regex engine inside Rust is really fast, high""" start="00:16:03.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""performance. We are using that for the Elixir regex""" start="00:16:07.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""engine to give it high performance and worst-case""" start="00:16:10.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""guarantees.""" start="00:16:14.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Parsers""" start="00:16:16.052" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is that Rust has a lot of really good""" start="00:16:16.052" video="mainVideo-rust" id="subtitle"]]
[[!template text="""parsers for things like JSON that are no copy parsers that""" start="00:16:18.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""are high performance. We can use those inside Rune as""" start="00:16:21.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""well.""" start="00:16:24.720" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Other changes: GUI first, terminal second""" start="00:16:27.210" video="mainVideo-rust" id="subtitle"]]
[[!template text="""There's a handful of other changes we're working on""" start="00:16:27.210" video="mainVideo-rust" id="subtitle"]]
[[!template text="""that are not Rust-specific, but we'd like to see. The first is""" start="00:16:29.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""being GUI first, terminal second. This means two things.""" start="00:16:33.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""First is that we have all of our key bindings. Right now""" start="00:16:36.760" video="mainVideo-rust" id="subtitle"]]
[[!template text="""inside Emacs, C-i and TAB are bound to the same key""" start="00:16:40.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""binding by default, because that's how it works inside the""" start="00:16:43.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""terminal. In the GUI, you shouldn't have that limitation.""" start="00:16:45.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The second is that the GUI should not block when Lisp is""" start="00:16:48.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""blocked. It should be independent of that. Your GUI can""" start="00:16:52.560" video="mainVideo-rust" id="subtitle"]]
[[!template text="""still continue to operate when Lisp is running.""" start="00:16:55.200" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Off-screen cursor""" start="00:16:58.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is the ability to have an off-screen cursor""" start="00:16:58.919" video="mainVideo-rust" id="subtitle"]]
[[!template text="""so that you can be typing on something,""" start="00:17:01.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you can scroll up and down and the point""" start="00:17:02.700" video="mainVideo-rust" id="subtitle"]]
[[!template text="""doesn't have to follow you where you lose your place where""" start="00:17:04.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""you were before. You don't have to intentionally set a mark.""" start="00:17:06.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""You can just scroll and then start typing and it'll go back up""" start="00:17:09.400" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to where it was before, like it works in most applications.""" start="00:17:11.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""And this can be optional.""" start="00:17:13.880" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Image flow""" start="00:17:16.305" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The other is image flow. We want it""" start="00:17:16.305" video="mainVideo-rust" id="subtitle"]]
[[!template text="""so that you can easily flow images and you can have large""" start="00:17:18.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""images and scroll past them without jumping and you can flow""" start="00:17:20.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""text around images.""" start="00:17:23.160" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Testing""" start="00:17:24.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How are we testing this project? Because there's a lot of""" start="00:17:24.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""things that you could get wrong here. One thing we're doing""" start="00:17:29.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""is we're using ERT. Emacs ships with over 7,000 built-in""" start="00:17:33.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""tests--Elisp tests. We are using this test suite to test""" start="00:17:38.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""our project as well. We can kind of use this as a dashboard""" start="00:17:42.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""of saying how close are we to getting to parity with GNU""" start="00:17:45.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""Emacs. The other thing that we have is a tool called elprop,""" start="00:17:47.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""which is an external utility that basically tests for""" start="00:17:52.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""correctness. Because really, the correctness of Rune is""" start="00:17:55.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""whatever Emacs does, because there's no official spec on""" start="00:17:58.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""how things should behave. To do this, we can go look at""" start="00:18:01.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the Rust function signature. We know what the arguments""" start="00:18:04.080" video="mainVideo-rust" id="subtitle"]]
[[!template text="""are, we know how many they are, and we know what types they""" start="00:18:07.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""should be. Given that information, we can generate a""" start="00:18:09.320" video="mainVideo-rust" id="subtitle"]]
[[!template text="""whole bunch of random functions feeding those types in. And""" start="00:18:11.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""then we send a copy over to Emacs, we send a copy over to Rune.""" start="00:18:15.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""They each evaluate it and they return the result and we make""" start="00:18:18.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""sure the results are the same. Then you do that for""" start="00:18:21.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""thousands of different implementations of the function.""" start="00:18:23.520" video="mainVideo-rust" id="subtitle"]]
[[!template text="""And it helps us find corner cases really easy without having""" start="00:18:26.200" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to handwrite a whole bunch of different cases to test things""" start="00:18:29.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and say, where are these two functions different?""" start="00:18:31.640" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Status""" start="00:18:36.345" video="mainVideo-rust" id="subtitle"]]
[[!template text="""So the current status: we already have a multi-threaded Elixir""" start="00:18:36.345" video="mainVideo-rust" id="subtitle"]]
[[!template text="""interpreter and bytecode engine inside there. There's no""" start="00:18:39.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""actual text editor in there yet, but the primitives are""" start="00:18:43.000" video="mainVideo-rust" id="subtitle"]]
[[!template text="""there. Like you can insert text, move point around,""" start="00:18:45.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""delete text, do different things like that. But we don't""" start="00:18:48.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""have a GUI hooked up to different key bindings to actually""" start="00:18:52.040" video="mainVideo-rust" id="subtitle"]]
[[!template text="""type on. There's just a REPL to operate in. We have about""" start="00:18:53.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""250 of the 1500 built-in functions already implemented""" start="00:18:58.160" video="mainVideo-rust" id="subtitle"]]
[[!template text="""inside there. There's a lot of low-hanging fruit inside this""" start="00:19:01.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""area to still be implemented.""" start="00:19:04.120" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""Next directions""" start="00:19:07.247" video="mainVideo-rust" id="subtitle"]]
[[!template text="""The next directions we're""" start="00:19:07.247" video="mainVideo-rust" id="subtitle"]]
[[!template text="""working on is we're optimizing the GC. We want to make it""" start="00:19:07.720" video="mainVideo-rust" id="subtitle"]]
[[!template text="""generational. Like I said, right now, it's just a simple""" start="00:19:11.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""semi-spaced copying GC. We want to add a proper GUI. We need""" start="00:19:13.840" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to implement text properties, overlays, process and job""" start="00:19:17.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""control, all that goodness right there.""" start="00:19:19.600" video="mainVideo-rust" id="subtitle"]]
[[!template new="1" text="""How to get involved""" start="00:19:22.739" video="mainVideo-rust" id="subtitle"]]
[[!template text="""How can you get involved? This is hosted on GitHub.""" start="00:19:22.739" video="mainVideo-rust" id="subtitle"]]
[[!template text="""You can come on over.""" start="00:19:25.379" video="mainVideo-rust" id="subtitle"]]
[[!template text="""If you have any ideas about how to implement something or""" start="00:19:26.425" video="mainVideo-rust" id="subtitle"]]
[[!template text="""something you'd like to see done, go ahead and just open an""" start="00:19:28.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""issue so we can have a discussion about it. We've had lots of""" start="00:19:30.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""interesting discussions with different people coming in""" start="00:19:32.800" video="mainVideo-rust" id="subtitle"]]
[[!template text="""to the GitHub repo. If you're interested in contributing,""" start="00:19:34.600" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the easiest way is probably to run elprop, pick some""" start="00:19:37.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""function, run elprop on it. I promise it won't take long to""" start="00:19:40.440" video="mainVideo-rust" id="subtitle"]]
[[!template text="""find some issues, some discrepancy between Emacs and Rune,""" start="00:19:43.280" video="mainVideo-rust" id="subtitle"]]
[[!template text="""and that lets you dive into the Rust code and figure out, and""" start="00:19:45.640" video="mainVideo-rust" id="subtitle"]]
[[!template text="""the C code, and figure out what the difference is between the""" start="00:19:48.960" video="mainVideo-rust" id="subtitle"]]
[[!template text="""two. or come along and help implement your favorite""" start="00:19:50.880" video="mainVideo-rust" id="subtitle"]]
[[!template text="""functionality. This has been a really interesting project""" start="00:19:53.120" video="mainVideo-rust" id="subtitle"]]
[[!template text="""so far, and we've had a handful of different contributors on""" start="00:19:55.680" video="mainVideo-rust" id="subtitle"]]
[[!template text="""it who just kind of want to learn Rust or get more into""" start="00:19:58.360" video="mainVideo-rust" id="subtitle"]]
[[!template text="""systems-level programming. Thank you.""" start="00:20:01.800" video="mainVideo-rust" id="subtitle"]]
Captioner: sachac
Questions or comments? Please e-mail [troy@troyhinckley.com](mailto:troy@troyhinckley.com?subject=Comment%20for%20EmacsConf%202023%20rust%3A%20An%20experimental%20Emacs%20core%20in%20Rust)
<!-- End of emacsconf-publish-after-page -->
|