1
# SOME DESCRIPTIVE TITLE
2
# Copyright (C) YEAR The Rust Project Developers
3
# This file is distributed under the same license as the Rust package.
4
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
9
"Project-Id-Version: Rust 0.13.0\n"
10
"POT-Creation-Date: 2014-11-10 20:48+0800\n"
11
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
"Language-Team: LANGUAGE <LL@li.org>\n"
16
"Content-Type: text/plain; charset=UTF-8\n"
17
"Content-Transfer-Encoding: 8bit\n"
20
#: src/doc/guide-crates.md:69 src/doc/intro.md:49
21
msgid "1 directory, 2 files ```"
25
#: src/doc/guide.md:1443 src/doc/intro.md:308 src/doc/intro.md:362
28
" println!(\"{}\", x);\n"
34
#: src/doc/guide.md:1828 src/doc/intro.md:70
39
" println!(\"Hello, world!\")\n"
45
#: src/doc/guide.md:3476 src/doc/intro.md:430
46
msgid "It gives us this error:"
50
#: src/doc/index.md:69 src/doc/intro.md:24
56
msgid "% A 30-minute Introduction to Rust"
62
"Rust is a modern systems programming language focusing on safety and speed. "
63
"It accomplishes these goals by being memory safe without using garbage "
68
#: src/doc/intro.md:12
70
"This introduction will give you a rough idea of what Rust is like, eliding "
71
"many details. It does not require prior experience with systems programming, "
72
"but you may find the syntax easier if you've used a 'curly brace' "
73
"programming language before, like C or JavaScript. The concepts are more "
74
"important than the syntax, so don't worry if you don't get every last "
75
"detail: you can read [the Guide](guide.html) to get a more complete "
80
#: src/doc/intro.md:16
82
"Because this is about high-level concepts, you don't need to actually "
83
"install Rust to follow along. If you'd like to anyway, check out [the "
84
"homepage](http://rust-lang.org) for explanation."
88
#: src/doc/intro.md:22
90
"To show off Rust, let's talk about how easy it is to get started with Rust. "
91
"Then, we'll talk about Rust's most interesting feature, **ownership**, and "
92
"then discuss how it makes concurrency easier to reason about. Finally, we'll "
93
"talk about how Rust breaks down the perceived dichotomy between speed and "
98
#: src/doc/intro.md:27
100
"Getting started on a new Rust project is incredibly easy, thanks to Rust's "
101
"package manager, [Cargo](http://crates.io)."
105
#: src/doc/intro.md:29
106
msgid "To start a new project with Cargo, use `cargo new`:"
110
#: src/doc/intro.md:33
111
msgid "```{bash} $ cargo new hello_world --bin ```"
115
#: src/doc/intro.md:36
117
"We're passing `--bin` because we're making a binary program: if we were "
118
"making a library, we'd leave it off."
122
#: src/doc/intro.md:38
123
msgid "Let's check out what Cargo has generated for us:"
127
#: src/doc/intro.md:46
140
#: src/doc/intro.md:51
142
"This is all we need to get started. First, let's check out `Cargo.toml`:"
146
#: src/doc/intro.md:54 src/doc/intro.md:86
147
msgid "```{toml} [package]"
151
#: src/doc/intro.md:59
153
"name = \"hello_world\" version = \"0.0.1\" authors = [\"Your Name "
154
"<you@example.com>\"] ```"
158
#: src/doc/intro.md:62
160
"This is called a **manifest**, and it contains all of the metadata that "
161
"Cargo needs to compile your project."
165
#: src/doc/intro.md:64
166
msgid "Here's what's in `src/main.rs`:"
170
#: src/doc/intro.md:73
172
"Cargo generated a 'hello world' for us. We'll talk more about the syntax "
173
"here later, but that's what Rust code looks like! Let's compile and run it:"
177
#: src/doc/intro.md:80
182
" Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)\n"
183
" Running `target/hello_world`\n"
189
#: src/doc/intro.md:83
191
"Using an external dependency in Rust is incredibly easy. You add a line to "
196
#: src/doc/intro.md:90
198
"name = \"hello_world\" version = \"0.0.1\" authors = [\"Your Name "
199
"<someone@example.com>\"]"
203
#: src/doc/intro.md:92
204
msgid "[dependencies.semver]"
208
#: src/doc/intro.md:95
209
msgid "git = \"https://github.com/rust-lang/semver.git\" ```"
213
#: src/doc/intro.md:98
215
"You added the `semver` library, which parses version numbers and compares "
216
"them according to the [SemVer specification](http://semver.org/)."
220
#: src/doc/intro.md:101
221
msgid "Now, you can pull in that library using `extern crate` in `main.rs`."
225
#: src/doc/intro.md:104
226
msgid "```{rust,ignore} extern crate semver;"
230
#: src/doc/intro.md:106
231
msgid "use semver::Version;"
235
#: src/doc/intro.md:115
239
" assert!(Version::parse(\"1.2.3\") == Ok(Version {\n"
249
#: src/doc/intro.md:119
252
" println!(\"Versions compared successfully!\");\n"
258
#: src/doc/intro.md:122
260
"Again, we'll discuss the exact details of all of this syntax soon. For now, "
261
"let's compile and run it:"
265
#: src/doc/intro.md:131
270
" Updating git repository `https://github.com/rust-lang/semver.git`\n"
271
" Compiling semver v0.0.1 (https://github.com/rust-lang/semver.git#bf739419)\n"
272
" Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)\n"
273
" Running `target/hello_world`\n"
274
"Versions compared successfully!\n"
279
#: src/doc/intro.md:137
281
"Because we only specified a repository without a version, if someone else "
282
"were to try out our project at a later date, when `semver` was updated, they "
283
"would get a different, possibly incompatible version. To solve this problem, "
284
"Cargo produces a file, `Cargo.lock`, which records the versions of any "
285
"dependencies. This gives us repeatable builds."
289
#: src/doc/intro.md:144
291
"There is a lot more here, and this is a whirlwind tour, but you should feel "
292
"right at home if you've used tools like [Bundler](http://bundler.io/), [npm]"
293
"(https://www.npmjs.org/), or [pip](https://pip.pypa.io/en/latest/). There's "
294
"no `Makefile`s or endless `autotools` output here. (Rust's tooling does "
295
"[play nice with external libraries written in those tools](http://crates.io/"
296
"native-build.html), if you need to.)"
300
#: src/doc/intro.md:146
301
msgid "Enough about tools, let's talk code!"
305
#: src/doc/intro.md:148
310
#: src/doc/intro.md:156
312
"Rust's defining feature is 'memory safety without garbage collection.' Let's "
313
"take a moment to talk about what that means. **Memory safety** means that "
314
"the programming language eliminates certain kinds of bugs, such as [buffer "
315
"overflows](http://en.wikipedia.org/wiki/Buffer_overflow) and [dangling "
316
"pointers](http://en.wikipedia.org/wiki/Dangling_pointer). These problems "
317
"occur when you have unrestricted access to memory. As an example, here's "
322
#: src/doc/intro.md:159
323
msgid "```{ruby} v = [];"
327
#: src/doc/intro.md:161
328
msgid "v.push(\"Hello\");"
332
#: src/doc/intro.md:163
337
#: src/doc/intro.md:165
338
msgid "v.push(\"world\");"
342
#: src/doc/intro.md:168
347
#: src/doc/intro.md:171
349
"We make an array, `v`, and then call `push` on it. `push` is a method which "
350
"adds an element to the end of an array."
354
#: src/doc/intro.md:174
356
"Next, we make a new variable, `x`, that's equal to the first element of the "
357
"array. Simple, but this is where the 'bug' will appear."
361
#: src/doc/intro.md:177
363
"Let's keep going. We then call `push` again, pushing \"world\" onto the end "
364
"of the array. `v` now is `[\"Hello\", \"world\"]`."
368
#: src/doc/intro.md:179
369
msgid "Finally, we print `x` with the `puts` method. This prints \"Hello.\""
373
#: src/doc/intro.md:181
375
"All good? Let's go over a similar, but subtly different example, in C++:"
379
#: src/doc/intro.md:186
380
msgid "```{cpp} #include<iostream> #include<vector> #include<string>"
384
#: src/doc/intro.md:189
388
" std::vector<std::string> v;\n"
392
#: src/doc/intro.md:191
394
msgid " v.push_back(\"Hello\");\n"
398
#: src/doc/intro.md:193
400
msgid " std::string& x = v[0];\n"
404
#: src/doc/intro.md:195
406
msgid " v.push_back(\"world\");\n"
410
#: src/doc/intro.md:199
419
#: src/doc/intro.md:204
421
"It's a little more verbose due to the static typing, but it's almost the "
422
"same thing. We make a `std::vector` of `std::string`s, we call `push_back` "
423
"(same as `push`) on it, take a reference to the first element of the vector, "
424
"call `push_back` again, and then print out the reference."
428
#: src/doc/intro.md:207
430
"There's two big differences here: one, they're not _exactly_ the same thing, "
435
#: src/doc/intro.md:213
437
"```{bash} $ g++ hello.cpp -Wall -Werror $ ./a.out Segmentation fault (core "
442
#: src/doc/intro.md:219
444
"A crash! (Note that this is actually system-dependent. Because referring to "
445
"an invalid reference is undefined behavior, the compiler can do anything, "
446
"including the right thing!) Even though we compiled with flags to give us as "
447
"many warnings as possible, and to treat those warnings as errors, we got no "
448
"errors. When we ran the program, it crashed."
452
#: src/doc/intro.md:224
454
"Why does this happen? When we append to an array, its length changes. Since "
455
"its length changes, we may need to allocate more memory. In Ruby, this "
456
"happens as well, we just don't think about it very often. So why does the C+"
457
"+ version segfault when we allocate more memory?"
461
#: src/doc/intro.md:231
463
"The answer is that in the C++ version, `x` is a **reference** to the memory "
464
"location where the first element of the array is stored. But in Ruby, `x` is "
465
"a standalone value, not connected to the underyling array at all. Let's dig "
466
"into the details for a moment. Your program has access to memory, provided "
467
"to it by the operating system. Each location in memory has an address. So "
468
"when we make our vector, `v`, it's stored in a memory location somewhere:"
472
#: src/doc/intro.md:235
475
"| location | name | value |\n"
476
"|----------|------|-------|\n"
481
#: src/doc/intro.md:239
483
"(Address numbers made up, and in hexadecimal. Those of you with deep C++ "
484
"knowledge, there are some simplifications going on here, like the lack of an "
485
"allocated length for the vector. This is an introduction.)"
489
#: src/doc/intro.md:242
491
"When we push our first string onto the array, we allocate some memory, and "
496
#: src/doc/intro.md:247
499
"| location | name | value |\n"
500
"|----------|------|----------|\n"
501
"| 0x30 | v | 0x18 |\n"
502
"| 0x18 | | \"Hello\" |\n"
506
#: src/doc/intro.md:251
508
"We then make a reference to that first element. A reference is a variable "
509
"that points to a memory location, so its value is the memory location of the "
510
"`\"Hello\"` string:"
514
#: src/doc/intro.md:257
517
"| location | name | value |\n"
518
"|----------|------|----------|\n"
519
"| 0x30 | v | 0x18 |\n"
520
"| 0x18 | | \"Hello\" |\n"
521
"| 0x14 | x | 0x18 |\n"
525
#: src/doc/intro.md:261
527
"When we push `\"world\"` onto the vector with `push_back`, there's no room: "
528
"we only allocated one element. So, we need to allocate two elements, copy "
529
"the `\"Hello\"` string over, and update the reference. Like this:"
533
#: src/doc/intro.md:269
536
"| location | name | value |\n"
537
"|----------|------|----------|\n"
538
"| 0x30 | v | 0x08 |\n"
539
"| 0x18 | | GARBAGE |\n"
540
"| 0x14 | x | 0x18 |\n"
541
"| 0x08 | | \"Hello\" |\n"
542
"| 0x04 | | \"world\" |\n"
546
#: src/doc/intro.md:274
548
"Note that `v` now refers to the new list, which has two elements. It's all "
549
"good. But our `x` didn't get updated! It still points at the old location, "
550
"which isn't valid anymore. In fact, [the documentation for `push_back` "
551
"mentions this](http://en.cppreference.com/w/cpp/container/vector/push_back):"
555
#: src/doc/intro.md:277
557
"> If the new `size()` is greater than `capacity()` then all iterators and > "
558
"references (including the past-the-end iterator) are invalidated."
562
#: src/doc/intro.md:282
564
"Finding where these iterators and references are is a difficult problem, and "
565
"even in this simple case, `g++` can't help us here. While the bug is obvious "
566
"in this case, in real code, it can be difficult to track down the source of "
571
#: src/doc/intro.md:291
573
"Before we talk about this solution, why didn't our Ruby code have this "
574
"problem? The semantics are a little more complicated, and explaining Ruby's "
575
"internals is out of the scope of a guide to Rust. But in a nutshell, Ruby's "
576
"garbage collector keeps track of references, and makes sure that everything "
577
"works as you might expect. This comes at an efficiency cost, and the "
578
"internals are more complex. If you'd really like to dig into the details, "
579
"[this article](http://patshaughnessy.net/2012/1/18/seeing-double-how-ruby-"
580
"shares-string-values) can give you more information."
584
#: src/doc/intro.md:294
586
"Garbage collection is a valid approach to memory safety, but Rust chooses a "
587
"different path. Let's examine what the Rust version of this looks like:"
591
#: src/doc/intro.md:298
596
" let mut v = vec![];\n"
600
#: src/doc/intro.md:300 src/doc/intro.md:354
602
msgid " v.push(\"Hello\");\n"
606
#: src/doc/intro.md:302
608
msgid " let x = &v[0];\n"
612
#: src/doc/intro.md:304 src/doc/intro.md:358
614
msgid " v.push(\"world\");\n"
618
#: src/doc/intro.md:313
620
"This looks like a bit of both: fewer type annotations, but we do create new "
621
"variables with `let`. The method name is `push`, some other stuff is "
622
"different, but it's pretty close. So what happens when we compile this code? "
623
"Does Rust print `\"Hello\"`, or does Rust crash?"
627
#: src/doc/intro.md:315
628
msgid "Neither. It refuses to compile:"
632
#: src/doc/intro.md:332
635
"```{notrust,ignore}\n"
637
" Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)\n"
638
"main.rs:8:5: 8:6 error: cannot borrow `v` as mutable because it is also borrowed as immutable\n"
639
"main.rs:8 v.push(\"world\");\n"
641
"main.rs:6:14: 6:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends\n"
642
"main.rs:6 let x = &v[0];\n"
644
"main.rs:11:2: 11:2 note: previous borrow ends here\n"
645
"main.rs:1 fn main() {\n"
649
"error: aborting due to previous error\n"
654
#: src/doc/intro.md:336
656
"When we try to mutate the array by `push`ing it the second time, Rust throws "
657
"an error. It says that we \"cannot borrow v as mutable because it is also "
658
"borrowed as immutable.\" What's up with \"borrowed\"?"
662
#: src/doc/intro.md:341
664
"In Rust, the type system encodes the notion of **ownership**. The variable "
665
"`v` is an \"owner\" of the vector. When we make a reference to `v`, we let "
666
"that variable (in this case, `x`) 'borrow' it for a while. Just like if you "
667
"own a book, and you lend it to me, I'm borrowing the book."
671
#: src/doc/intro.md:345
673
"So, when I try to modify the vector with the second call to `push`, I need "
674
"to be owning it. But `x` is borrowing it. You can't modify something that "
675
"you've lent to someone. And so Rust throws an error."
679
#: src/doc/intro.md:347
680
msgid "So how do we fix this problem? Well, we can make a copy of the element:"
684
#: src/doc/intro.md:352
689
" let mut v = vec![];\n"
693
#: src/doc/intro.md:356
695
msgid " let x = v[0].clone();\n"
699
#: src/doc/intro.md:366
701
"Note the addition of `clone()`. This creates a copy of the element, leaving "
702
"the original untouched. Now, we no longer have two references to the same "
703
"memory, and so the compiler is happy. Let's give that a try:"
707
#: src/doc/intro.md:373
712
" Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)\n"
713
" Running `target/hello_world`\n"
719
#: src/doc/intro.md:377
721
"Same result. Now, making a copy can be inefficient, so this solution may not "
722
"be acceptable. There are other ways to get around this problem, but this is "
723
"a toy example, and because we're in an introduction, we'll leave that for "
728
#: src/doc/intro.md:381
730
"The point is, the Rust compiler and its notion of ownership has saved us "
731
"from a bug that would crash the program. We've achieved safety, at compile "
732
"time, without needing to rely on a garbage collector to handle our memory."
736
#: src/doc/intro.md:383
737
msgid "# Concurrency"
741
#: src/doc/intro.md:388
743
"Rust's ownership model can help in other ways, as well. For example, take "
744
"concurrency. Concurrency is a big topic, and an important one for any modern "
745
"programming language. Let's take a look at how ownership can help you write "
746
"safe concurrent programs."
750
#: src/doc/intro.md:390
751
msgid "Here's an example of a concurrent Rust program:"
755
#: src/doc/intro.md:400
760
" for _ in range(0u, 10u) {\n"
762
" println!(\"Hello, world!\");\n"
770
#: src/doc/intro.md:405
772
"This program creates ten threads, who all print `Hello, world!`. The `spawn` "
773
"function takes one argument, a `proc`. 'proc' is short for 'procedure,' and "
774
"is a form of closure. This closure is executed in a new thread, created by "
779
#: src/doc/intro.md:414
781
"One common form of problem in concurrent programs is a 'data race.' This "
782
"occurs when two different threads attempt to access the same location in "
783
"memory in a non-synchronized way, where at least one of them is a write. If "
784
"one thread is attempting to read, and one thread is attempting to write, you "
785
"cannot be sure that your data will not be corrupted. Note the first half of "
786
"that requirement: two threads that attempt to access the same location in "
787
"memory. Rust's ownership model can track which pointers own which memory "
788
"locations, which solves this problem."
792
#: src/doc/intro.md:416
793
msgid "Let's see an example. This Rust code will not compile:"
797
#: src/doc/intro.md:420
802
" let mut numbers = vec![1i, 2i, 3i];\n"
806
#: src/doc/intro.md:428
809
" for i in range(0u, 3u) {\n"
811
" for j in range(0, 3) { numbers[j] += 1 }\n"
819
#: src/doc/intro.md:443
822
"```{notrust,ignore}\n"
823
"6:71 error: capture of moved value: `numbers`\n"
824
" for j in range(0, 3) { numbers[j] += 1 }\n"
826
"7:50 note: `numbers` moved into closure environment here because it has type `proc():Send`, which is non-copyable (perhaps you meant to use clone()?)\n"
828
" for j in range(0, 3) { numbers[j] += 1 }\n"
830
"6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing)\n"
831
" for j in range(0, 3) { numbers[j] += 1 }\n"
837
#: src/doc/intro.md:449
839
"It mentions that \"numbers moved into closure environment\". Because we "
840
"referred to `numbers` inside of our `proc`, and we create three `proc`s, we "
841
"would have three references. Rust detects this and gives us the error: we "
842
"claim that `numbers` has ownership, but our code tries to make three owners. "
843
"This may cause a safety problem, so Rust disallows it."
847
#: src/doc/intro.md:460
849
"What to do here? Rust has two types that helps us: `Arc<T>` and `Mutex<T>`. "
850
"\"Arc\" stands for \"atomically reference counted.\" In other words, an Arc "
851
"will keep track of the number of references to something, and not free the "
852
"associated resource until the count is zero. The 'atomic' portion refers to "
853
"an Arc's usage of concurrency primitives to atomically update the count, "
854
"making it safe across threads. If we use an Arc, we can have our three "
855
"references. But, an Arc does not allow mutable borrows of the data it holds, "
856
"and we want to modify what we're sharing. In this case, we can use a "
857
"`Mutex<T>` inside of our Arc. A Mutex will synchronize our accesses, so that "
858
"we can ensure that our mutation doesn't cause a data race."
862
#: src/doc/intro.md:462
863
msgid "Here's what using an Arc with a Mutex looks like:"
867
#: src/doc/intro.md:465
868
msgid "```{rust} use std::sync::{Arc,Mutex};"
872
#: src/doc/intro.md:468
876
" let numbers = Arc::new(Mutex::new(vec![1i, 2i, 3i]));\n"
880
#: src/doc/intro.md:473
883
" for i in range(0u, 3u) {\n"
884
" let number = numbers.clone();\n"
886
" let mut array = number.lock();\n"
890
#: src/doc/intro.md:475
892
msgid " (*array)[i] += 1;\n"
896
#: src/doc/intro.md:481
899
" println!(\"numbers[{}] is {}\", i, (*array)[i]);\n"
907
#: src/doc/intro.md:489
909
"We first have to `use` the appropriate library, and then we wrap our vector "
910
"in an Arc with the call to `Arc::new()`. Inside of the loop, we make a new "
911
"reference to the Arc with the `clone()` method. This will increment the "
912
"reference count. When each new `numbers` variable binding goes out of scope, "
913
"it will decrement the count. The `lock()` call will return us a reference to "
914
"the value inside the Mutex, and block any other calls to `lock()` until said "
915
"reference goes out of scope."
919
#: src/doc/intro.md:492
921
"We can compile and run this program without error, and in fact, see the non-"
922
"deterministic aspect:"
926
#: src/doc/intro.md:506
931
" Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)\n"
932
" Running `target/hello_world`\n"
937
" Running `target/hello_world`\n"
945
#: src/doc/intro.md:509
947
"Each time, we get a slightly different output, because each thread works in "
948
"a different order. You may not get the same output as this sample, even."
952
#: src/doc/intro.md:514
954
"The important part here is that the Rust compiler was able to use ownership "
955
"to give us assurance _at compile time_ that we weren't doing something "
956
"incorrect with regards to concurrency. In order to share ownership, we were "
957
"forced to be explicit and use a mechanism to ensure that it would be "
962
#: src/doc/intro.md:516
963
msgid "# Safety _and_ speed"
967
#: src/doc/intro.md:522
969
"Safety and speed are always presented as a continuum. On one hand, you have "
970
"maximum speed, but no safety. On the other, you have absolute safety, with "
971
"no speed. Rust seeks to break out of this mode by introducing safety at "
972
"compile time, ensuring that you haven't done anything wrong, while compiling "
973
"to the same low-level code you'd expect without the safety."
977
#: src/doc/intro.md:525
979
"As an example, Rust's ownership system is _entirely_ at compile time. The "
980
"safety check that makes this an error about moved values:"
984
#: src/doc/intro.md:529
989
" let vec = vec![1i, 2, 3];\n"
993
#: src/doc/intro.md:537
996
" for i in range(1u, 3) {\n"
998
" println!(\"{}\", vec[i]);\n"
1006
#: src/doc/intro.md:542
1008
"carries no runtime penalty. And while some of Rust's safety features do have "
1009
"a run-time cost, there's often a way to write your code in such a way that "
1010
"you can remove it. As an example, this is a poor way to iterate through a "
1015
#: src/doc/intro.md:545 src/doc/intro.md:557
1016
msgid "```{rust} let vec = vec![1i, 2, 3];"
1020
#: src/doc/intro.md:550
1023
"for i in range(1u, vec.len()) {\n"
1024
" println!(\"{}\", vec[i]);\n"
1030
#: src/doc/intro.md:554
1032
"The reason is that the access of `vec[i]` does bounds checking, to ensure "
1033
"that we don't try to access an invalid index. However, we can remove this "
1034
"while retaining safety. The answer is iterators:"
1038
#: src/doc/intro.md:562
1041
"for x in vec.iter() {\n"
1042
" println!(\"{}\", x);\n"
1048
#: src/doc/intro.md:566
1050
"This version uses an iterator that yields each element of the vector in "
1051
"turn. Because we have a reference to the element, rather than the whole "
1052
"vector itself, there's no array access bounds to check."
1056
#: src/doc/intro.md:568
1057
msgid "# Learning More"
1061
#: src/doc/intro.md:574
1063
"I hope that this taste of Rust has given you an idea if Rust is the right "
1064
"language for you. We talked about Rust's tooling, how encoding ownership "
1065
"into the type system helps you find bugs, how Rust can help you write "
1066
"correct concurrent code, and how you don't have to pay a speed cost for much "
1071
#: src/doc/intro.md:576
1073
"To continue your Rustic education, read [the guide](guide.html) for a more "
1074
"in-depth exploration of Rust's syntax and concepts."