Skip to content

Commit 90cc830

Browse files
committed
Auto merge of #24703 - Manishearth:rollup, r=Manishearth
r? @Manishearth
2 parents 5c96369 + b0319e9 commit 90cc830

File tree

6 files changed

+293
-6
lines changed

6 files changed

+293
-6
lines changed

src/doc/trpl/SUMMARY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* [The Stack and the Heap](the-stack-and-the-heap.md)
1010
* [Debug and Display](debug-and-display.md)
1111
* [Testing](testing.md)
12+
* [Conditional Compilation](conditional-compilation.md)
1213
* [Documentation](documentation.md)
1314
* [Iterators](iterators.md)
1415
* [Concurrency](concurrency.md)
@@ -46,7 +47,6 @@
4647
* [`const` and `static`](const-and-static.md)
4748
* [Tuple Structs](tuple-structs.md)
4849
* [Attributes](attributes.md)
49-
* [Conditional Compilation](conditional-compilation.md)
5050
* [`type` aliases](type-aliases.md)
5151
* [Casting between types](casting-between-types.md)
5252
* [Associated Types](associated-types.md)

src/doc/trpl/attributes.md

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,70 @@
11
% Attributes
22

3-
Coming Soon!
3+
Declarations can be annotated with ‘attributes’ in Rust. They look like this:
4+
5+
```rust
6+
#[test]
7+
# fn foo() {}
8+
```
9+
10+
or like this:
11+
12+
```rust
13+
# mod foo {
14+
#![test]
15+
# }
16+
```
17+
18+
The difference between the two is the `!`, which changes what the attribute
19+
applies to:
20+
21+
```rust,ignore
22+
#[foo]
23+
struct Foo;
24+
25+
mod bar {
26+
#![bar]
27+
}
28+
```
29+
30+
The `#[foo]` attribute applies to the next item, which is the `struct`
31+
declaration. The `#![bar]` attribute applies to the item enclosing it, which is
32+
the `mod` declaration. Otherwise, they’re the same. Both change the meaning of
33+
the item they’re attached to somehow.
34+
35+
For example, consider a function like this:
36+
37+
```rust
38+
#[test]
39+
fn check() {
40+
assert_eq!(2, 1 + 1);
41+
}
42+
```
43+
44+
It is marked with `#[test]`. This means it’s special: when you run
45+
[tests][tests], this function will execute. When you compile as usual, it won’t
46+
even be included. This function is now a test function.
47+
48+
[tests]: testing.html
49+
50+
Attributes may also have additional data:
51+
52+
```rust
53+
#[inline(always)]
54+
fn super_fast_fn() {
55+
# }
56+
```
57+
58+
Or even keys and values:
59+
60+
```rust
61+
#[cfg(target_os = "macos")]
62+
mod macos_only {
63+
# }
64+
```
65+
66+
Rust attributes are used for a number of different things. There is a full list
67+
of attributes [in the reference][reference]. Currently, you are not allowed to
68+
create your own attributes, the Rust compiler defines them.
69+
70+
[reference]: reference.html#attributes
+91-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,93 @@
11
% Conditional Compilation
22

3-
Coming Soon!
3+
Rust has a special attribute, `#[cfg]`, which allows you to compile code
4+
based on a flag passed to the compiler. It has two forms:
5+
6+
```rust
7+
#[cfg(foo)]
8+
# fn foo() {}
9+
10+
#[cfg(bar = "baz")]
11+
# fn bar() {}
12+
```
13+
14+
They also have some helpers:
15+
16+
```rust
17+
#[cfg(any(unix, windows))]
18+
# fn foo() {}
19+
20+
#[cfg(all(unix, target_pointer_width = "32"))]
21+
# fn bar() {}
22+
23+
#[cfg(not(foo))]
24+
# fn not_foo() {}
25+
```
26+
27+
These can nest arbitrarily:
28+
29+
```rust
30+
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
31+
# fn foo() {}
32+
```
33+
34+
As for how to enable or disable these switches, if you’re using Cargo,
35+
they get set in the [`[features]` section][features] of your `Cargo.toml`:
36+
37+
[features]: http://doc.crates.io/manifest.html#the-[features]-section
38+
39+
```toml
40+
[features]
41+
# no features by default
42+
default = []
43+
44+
# The “secure-password” feature depends on the bcrypt package.
45+
secure-password = ["bcrypt"]
46+
```
47+
48+
When you do this, Cargo passes along a flag to `rustc`:
49+
50+
```text
51+
--cfg feature="${feature_name}"
52+
```
53+
54+
The sum of these `cfg` flags will determine which ones get activated, and
55+
therefore, which code gets compiled. Let’s take this code:
56+
57+
```rust
58+
#[cfg(feature = "foo")]
59+
mod foo {
60+
}
61+
```
62+
63+
If we compile it with `cargo build --features "foo"`, it will send the `--cfg
64+
feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
65+
If we compile it with a regular `cargo build`, no extra flags get passed on,
66+
and so, no `foo` module will exist.
67+
68+
# cfg_attr
69+
70+
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
71+
72+
```rust
73+
#[cfg_attr(a, b)]
74+
# fn foo() {}
75+
```
76+
77+
Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.
78+
79+
# cfg!
80+
81+
The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags
82+
elsewhere in your code, too:
83+
84+
```rust
85+
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
86+
println!("Think Different!");
87+
}
88+
```
89+
90+
[compilerplugins]: compiler-plugins.html
91+
92+
These will be replaced by a `true` or `false` at compile-time, depending on the
93+
configuration settings.

src/doc/trpl/type-aliases.md

+74-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,76 @@
11
% `type` Aliases
22

3-
Coming soon
3+
The `type` keyword lets you declare an alias of another type:
4+
5+
```rust
6+
type Name = String;
7+
```
8+
9+
You can then use this type as if it were a real type:
10+
11+
```rust
12+
type Name = String;
13+
14+
let x: Name = "Hello".to_string();
15+
```
16+
17+
Note, however, that this is an _alias_, not a new type entirely. In other
18+
words, because Rust is strongly typed, you’d expect a comparison between two
19+
different types to fail:
20+
21+
```rust,ignore
22+
let x: i32 = 5;
23+
let y: i64 = 5;
24+
25+
if x == y {
26+
// ...
27+
}
28+
```
29+
30+
this gives
31+
32+
```text
33+
error: mismatched types:
34+
expected `i32`,
35+
found `i64`
36+
(expected i32,
37+
found i64) [E0308]
38+
if x == y {
39+
^
40+
```
41+
42+
But, if we had an alias:
43+
44+
```rust
45+
type Num = i32;
46+
47+
let x: i32 = 5;
48+
let y: Num = 5;
49+
50+
if x == y {
51+
// ...
52+
}
53+
```
54+
55+
This compiles without error. Values of a `Num` type are the same as a value of
56+
type `i32`, in every way.
57+
58+
You can also use type aliases with generics:
59+
60+
```rust
61+
use std::result;
62+
63+
enum ConcreteError {
64+
Foo,
65+
Bar,
66+
}
67+
68+
type Result<T> = result::Result<T, ConcreteError>;
69+
```
70+
71+
This creates a specialized version of the `Result` type, which always has a
72+
`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used
73+
in the standard library to create custom errors for each subsection. For
74+
example, [io::Result][ioresult].
75+
76+
[ioresult]: ../std/io/type.Result.html

src/doc/trpl/unsized-types.md

+56-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,58 @@
11
% Unsized Types
22

3-
Coming Soon!
3+
Most types have a particular size, in bytes, that is knowable at compile time.
4+
For example, an `i32` is thirty-two bits big, or four bytes. However, there are
5+
some types which are useful to express, but do not have a defined size. These are
6+
called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type
7+
represents a certain number of `T` in sequence. But we don’t know how many
8+
there are, so the size is not known.
9+
10+
Rust understands a few of these types, but they have some restrictions. There
11+
are three:
12+
13+
1. We can only manipulate an instance of an unsized type via a pointer. An
14+
`&[T]` works just fine, but a `[T]` does not.
15+
2. Variables and arguments cannot have dynamically sized types.
16+
3. Only the last field in a `struct` may have a dynamically sized type; the
17+
other fields must not. Enum variants must not have dynamically sized types as
18+
data.
19+
20+
So why bother? Well, because `[T]` can only be used behind a pointer, if we
21+
didn’t have language support for unsized types, it would be impossible to write
22+
this:
23+
24+
```rust,ignore
25+
impl Foo for str {
26+
```
27+
28+
or
29+
30+
```rust,ignore
31+
impl<T> Foo for [T] {
32+
```
33+
34+
Instead, you would have to write:
35+
36+
```rust,ignore
37+
impl Foo for &str {
38+
```
39+
40+
Meaning, this implementation would only work for [references][ref], and not
41+
other types of pointers. With this `impl`, all pointers, including (at some
42+
point, there are some bugs to fix first) user-defined custom smart pointers,
43+
can use this `impl`.
44+
45+
# ?Sized
46+
47+
If you want to write a function that accepts a dynamically sized type, you
48+
can use the special bound, `?Sized`:
49+
50+
```rust
51+
struct Foo<T: ?Sized> {
52+
f: T,
53+
}
54+
```
55+
56+
This `?`, read as “T may be `Sized`”, means that this bound is special: it
57+
lets us match more kinds, not less. It’s almost like every `T` implicitly has
58+
`T: Sized`, and the `?` undoes this default.

src/test/run-pass/ifmt.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,11 @@ fn test_write() {
195195
write!(w, "{}", "hello");
196196
writeln!(w, "{}", "line");
197197
writeln!(w, "{foo}", foo="bar");
198+
w.write_char('☃');
199+
w.write_str("str");
198200
}
199201

200-
t!(buf, "34helloline\nbar\n");
202+
t!(buf, "34helloline\nbar\n☃str");
201203
}
202204

203205
// Just make sure that the macros are defined, there's not really a lot that we

0 commit comments

Comments
 (0)