Skip to content

Commit 4dfdc69

Browse files
committed
auto merge of #16331 : steveklabnik/rust/guide_macros_and_unsafe, r=brson
The last two sections of the guide, and a small conclusion. I suck at conclusions. I also realized I never covered strings, so I'm going to put that section up before we're actually 'done.'
2 parents 33037fd + 1395166 commit 4dfdc69

File tree

1 file changed

+177
-4
lines changed

1 file changed

+177
-4
lines changed

src/doc/guide.md

+177-4
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ arguments we pass to functions and macros, if you're passing more than one.
535535
When you just use the curly braces, Rust will attempt to display the
536536
value in a meaningful way by checking out its type. If you want to specify the
537537
format in a more detailed manner, there are a [wide number of options
538-
available](/std/fmt/index.html). For now, we'll just stick to the default:
538+
available](std/fmt/index.html). For now, we'll just stick to the default:
539539
integers aren't very complicated to print.
540540

541541
So, we've cleared up all of the confusion around bindings, with one exception:
@@ -3520,15 +3520,15 @@ out.
35203520
In systems programming, pointers are an incredibly important topic. Rust has a
35213521
very rich set of pointers, and they operate differently than in many other
35223522
languages. They are important enough that we have a specific [Pointer
3523-
Guide](/guide-pointers.html) that goes into pointers in much detail. In fact,
3523+
Guide](guide-pointers.html) that goes into pointers in much detail. In fact,
35243524
while you're currently reading this guide, which covers the language in broad
35253525
overview, there are a number of other guides that put a specific topic under a
35263526
microscope. You can find the list of guides on the [documentation index
3527-
page](/index.html#guides).
3527+
page](index.html#guides).
35283528

35293529
In this section, we'll assume that you're familiar with pointers as a general
35303530
concept. If you aren't, please read the [introduction to
3531-
pointers](/guide-pointers.html#an-introduction) section of the Pointer Guide,
3531+
pointers](guide-pointers.html#an-introduction) section of the Pointer Guide,
35323532
and then come back here. We'll wait.
35333533

35343534
Got the gist? Great. Let's talk about pointers in Rust.
@@ -5211,4 +5211,177 @@ fail.
52115211

52125212
# Macros
52135213

5214+
One of Rust's most advanced features is its system of **macro**s. While
5215+
functions allow you to provide abstractions over values and operations, macros
5216+
allow you to provide abstractions over syntax. Do you wish Rust had the ability
5217+
to do something that it can't currently do? You may be able to write a macro
5218+
to extend Rust's capabilities.
5219+
5220+
You've already used one macro extensively: `println!`. When we invoke
5221+
a Rust macro, we need to use the exclamation mark (`!`). There's two reasons
5222+
that this is true: the first is that it makes it clear when you're using a
5223+
macro. The second is that macros allow for flexible syntax, and so Rust must
5224+
be able to tell where a macro starts and ends. The `!(...)` helps with this.
5225+
5226+
Let's talk some more about `println!`. We could have implemented `println!` as
5227+
a function, but it would be worse. Why? Well, what macros allow you to do
5228+
is write code that generates more code. So when we call `println!` like this:
5229+
5230+
```{rust}
5231+
let x = 5i;
5232+
println!("x is: {}", x);
5233+
```
5234+
5235+
The `println!` macro does a few things:
5236+
5237+
1. It parses the string to find any `{}`s
5238+
2. It checks that the number of `{}`s matches the number of other arguments.
5239+
3. It generates a bunch of Rust code, taking this in mind.
5240+
5241+
What this means is that you get type checking at compile time, because
5242+
Rust will generate code that takes all of the types into account. If
5243+
`println!` was a function, it could still do this type checking, but it
5244+
would happen at run time rather than compile time.
5245+
5246+
We can check this out using a special flag to `rustc`. This code, in a file
5247+
`print.rs`:
5248+
5249+
```{rust}
5250+
fn main() {
5251+
let x = "Hello";
5252+
println!("x is: {:s}", x);
5253+
}
5254+
```
5255+
5256+
Can have its macros expanded like this: `rustc print.rs --pretty=expanded`, will
5257+
give us this huge result:
5258+
5259+
```{rust,ignore}
5260+
#![feature(phase)]
5261+
#![no_std]
5262+
#![feature(globs)]
5263+
#[phase(plugin, link)]
5264+
extern crate std = "std";
5265+
extern crate rt = "native";
5266+
use std::prelude::*;
5267+
fn main() {
5268+
let x = "Hello";
5269+
match (&x,) {
5270+
(__arg0,) => {
5271+
#[inline]
5272+
#[allow(dead_code)]
5273+
static __STATIC_FMTSTR: [::std::fmt::rt::Piece<'static>, ..2u] =
5274+
[::std::fmt::rt::String("x is: "),
5275+
::std::fmt::rt::Argument(::std::fmt::rt::Argument{position:
5276+
::std::fmt::rt::ArgumentNext,
5277+
format:
5278+
::std::fmt::rt::FormatSpec{fill:
5279+
' ',
5280+
align:
5281+
::std::fmt::rt::AlignUnknown,
5282+
flags:
5283+
0u,
5284+
precision:
5285+
::std::fmt::rt::CountImplied,
5286+
width:
5287+
::std::fmt::rt::CountImplied,},})];
5288+
let __args_vec =
5289+
&[::std::fmt::argument(::std::fmt::secret_string, __arg0)];
5290+
let __args =
5291+
unsafe {
5292+
::std::fmt::Arguments::new(__STATIC_FMTSTR, __args_vec)
5293+
};
5294+
::std::io::stdio::println_args(&__args)
5295+
}
5296+
};
5297+
}
5298+
```
5299+
5300+
Intense. Here's a trimmed down version that's a bit easier to read:
5301+
5302+
```{rust,ignore}
5303+
fn main() {
5304+
let x = 5i;
5305+
match (&x,) {
5306+
(__arg0,) => {
5307+
static __STATIC_FMTSTR: =
5308+
[String("x is: "),
5309+
Argument(Argument {
5310+
position: ArgumentNext,
5311+
format: FormatSpec {
5312+
fill: ' ',
5313+
align: AlignUnknown,
5314+
flags: 0u,
5315+
precision: CountImplied,
5316+
width: CountImplied,
5317+
},
5318+
},
5319+
];
5320+
let __args_vec = &[argument(secret_string, __arg0)];
5321+
let __args = unsafe { Arguments::new(__STATIC_FMTSTR, __args_vec) };
5322+
5323+
println_args(&__args)
5324+
}
5325+
};
5326+
}
5327+
```
5328+
5329+
Whew! This isn't too terrible. You can see that we still `let x = 5i`,
5330+
but then things get a little bit hairy. Three more bindings get set: a
5331+
static format string, an argument vector, and the aruments. We then
5332+
invoke the `println_args` function with the generated arguments.
5333+
5334+
This is the code (well, the full version) that Rust actually compiles. You can
5335+
see all of the extra information that's here. We get all of the type safety and
5336+
options that it provides, but at compile time, and without needing to type all
5337+
of this out. This is how macros are powerful. Without them, you would need to
5338+
type all of this by hand to get a type checked `println`.
5339+
5340+
For more on macros, please consult [the Macros Guide](guide-macros.html).
5341+
Macros are a very advanced and still slightly experimental feature, but don't
5342+
require a deep understanding to call, since they look just like functions. The
5343+
Guide can help you if you want to write your own.
5344+
52145345
# Unsafe
5346+
5347+
Finally, there's one more concept that you should be aware in Rust: `unsafe`.
5348+
There are two circumstances where Rust's safety provisions don't work well.
5349+
The first is when interfacing with C code, and the second is when building
5350+
certain kinds of abstractions.
5351+
5352+
Rust has support for FFI, (which you can read about in the [FFI
5353+
Guide](guide-ffi.html)) but Rust can't guarantee that the C code will be safe,
5354+
like Rust's will. Therefore, Rust marks such functions with the `unsafe`
5355+
keyword, which indicates that the function may not behave properly.
5356+
5357+
Second, if you'd like to create some sort of shared-memory data structure, Rust
5358+
won't allow it, because memory must be owned by a single owner. However, if
5359+
you're planning on making access to that shared memory safe, such as with a
5360+
mutex, _you_ know that it's safe, but Rust can't know. Writing an `unsafe`
5361+
block allows you to ask the compiler to trust you. In this case, the _internal_
5362+
implementation of the mutex is considered unsafe, but the _external_ interface
5363+
we present is safe. This allows it to be effectively used in normal Rust, while
5364+
being able to implement functionality that the compiler can't double check for
5365+
us.
5366+
5367+
Doesn't an escape hatch undermine the safety of the entire system? Well, if
5368+
Rust code segfaults, it _must_ be because of unsafe code somewhere. By
5369+
annotating exactly where that is, you have a significantly smaller area to
5370+
search.
5371+
5372+
We haven't even talked about any examples here, and that's because I want to
5373+
emphasize that you should not be writing unsafe code unless you know exactly
5374+
what you're doing. The vast majority of Rust developers will only interact with
5375+
it when doing FFI, and advanced library authors may use it to build certain
5376+
kinds of abstraction.
5377+
5378+
# Conclusion
5379+
5380+
We covered a lot of ground here. When you've mastered everything in this Guide,
5381+
you will have a firm grasp of basic Rust development. There's a whole lot more
5382+
out there, we've just covered the surface. There's tons of topics that you can
5383+
dig deeper into, and we've built specialized guides for many of them. To learn
5384+
more, dig into the [full documentation
5385+
index](http://doc.rust-lang.org/index.html).
5386+
5387+
Happy hacking!

0 commit comments

Comments
 (0)