-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #24703 - Manishearth:rollup, r=Manishearth
r? @Manishearth
- Loading branch information
Showing
6 changed files
with
293 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,70 @@ | ||
% Attributes | ||
|
||
Coming Soon! | ||
Declarations can be annotated with ‘attributes’ in Rust. They look like this: | ||
|
||
```rust | ||
#[test] | ||
# fn foo() {} | ||
``` | ||
|
||
or like this: | ||
|
||
```rust | ||
# mod foo { | ||
#![test] | ||
# } | ||
``` | ||
|
||
The difference between the two is the `!`, which changes what the attribute | ||
applies to: | ||
|
||
```rust,ignore | ||
#[foo] | ||
struct Foo; | ||
mod bar { | ||
#![bar] | ||
} | ||
``` | ||
|
||
The `#[foo]` attribute applies to the next item, which is the `struct` | ||
declaration. The `#![bar]` attribute applies to the item enclosing it, which is | ||
the `mod` declaration. Otherwise, they’re the same. Both change the meaning of | ||
the item they’re attached to somehow. | ||
|
||
For example, consider a function like this: | ||
|
||
```rust | ||
#[test] | ||
fn check() { | ||
assert_eq!(2, 1 + 1); | ||
} | ||
``` | ||
|
||
It is marked with `#[test]`. This means it’s special: when you run | ||
[tests][tests], this function will execute. When you compile as usual, it won’t | ||
even be included. This function is now a test function. | ||
|
||
[tests]: testing.html | ||
|
||
Attributes may also have additional data: | ||
|
||
```rust | ||
#[inline(always)] | ||
fn super_fast_fn() { | ||
# } | ||
``` | ||
|
||
Or even keys and values: | ||
|
||
```rust | ||
#[cfg(target_os = "macos")] | ||
mod macos_only { | ||
# } | ||
``` | ||
|
||
Rust attributes are used for a number of different things. There is a full list | ||
of attributes [in the reference][reference]. Currently, you are not allowed to | ||
create your own attributes, the Rust compiler defines them. | ||
|
||
[reference]: reference.html#attributes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,93 @@ | ||
% Conditional Compilation | ||
|
||
Coming Soon! | ||
Rust has a special attribute, `#[cfg]`, which allows you to compile code | ||
based on a flag passed to the compiler. It has two forms: | ||
|
||
```rust | ||
#[cfg(foo)] | ||
# fn foo() {} | ||
|
||
#[cfg(bar = "baz")] | ||
# fn bar() {} | ||
``` | ||
|
||
They also have some helpers: | ||
|
||
```rust | ||
#[cfg(any(unix, windows))] | ||
# fn foo() {} | ||
|
||
#[cfg(all(unix, target_pointer_width = "32"))] | ||
# fn bar() {} | ||
|
||
#[cfg(not(foo))] | ||
# fn not_foo() {} | ||
``` | ||
|
||
These can nest arbitrarily: | ||
|
||
```rust | ||
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))] | ||
# fn foo() {} | ||
``` | ||
|
||
As for how to enable or disable these switches, if you’re using Cargo, | ||
they get set in the [`[features]` section][features] of your `Cargo.toml`: | ||
|
||
[features]: http://doc.crates.io/manifest.html#the-[features]-section | ||
|
||
```toml | ||
[features] | ||
# no features by default | ||
default = [] | ||
|
||
# The “secure-password” feature depends on the bcrypt package. | ||
secure-password = ["bcrypt"] | ||
``` | ||
|
||
When you do this, Cargo passes along a flag to `rustc`: | ||
|
||
```text | ||
--cfg feature="${feature_name}" | ||
``` | ||
|
||
The sum of these `cfg` flags will determine which ones get activated, and | ||
therefore, which code gets compiled. Let’s take this code: | ||
|
||
```rust | ||
#[cfg(feature = "foo")] | ||
mod foo { | ||
} | ||
``` | ||
|
||
If we compile it with `cargo build --features "foo"`, it will send the `--cfg | ||
feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it. | ||
If we compile it with a regular `cargo build`, no extra flags get passed on, | ||
and so, no `foo` module will exist. | ||
|
||
# cfg_attr | ||
|
||
You can also set another attribute based on a `cfg` variable with `cfg_attr`: | ||
|
||
```rust | ||
#[cfg_attr(a, b)] | ||
# fn foo() {} | ||
``` | ||
|
||
Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise. | ||
|
||
# cfg! | ||
|
||
The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags | ||
elsewhere in your code, too: | ||
|
||
```rust | ||
if cfg!(target_os = "macos") || cfg!(target_os = "ios") { | ||
println!("Think Different!"); | ||
} | ||
``` | ||
|
||
[compilerplugins]: compiler-plugins.html | ||
|
||
These will be replaced by a `true` or `false` at compile-time, depending on the | ||
configuration settings. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,76 @@ | ||
% `type` Aliases | ||
|
||
Coming soon | ||
The `type` keyword lets you declare an alias of another type: | ||
|
||
```rust | ||
type Name = String; | ||
``` | ||
|
||
You can then use this type as if it were a real type: | ||
|
||
```rust | ||
type Name = String; | ||
|
||
let x: Name = "Hello".to_string(); | ||
``` | ||
|
||
Note, however, that this is an _alias_, not a new type entirely. In other | ||
words, because Rust is strongly typed, you’d expect a comparison between two | ||
different types to fail: | ||
|
||
```rust,ignore | ||
let x: i32 = 5; | ||
let y: i64 = 5; | ||
if x == y { | ||
// ... | ||
} | ||
``` | ||
|
||
this gives | ||
|
||
```text | ||
error: mismatched types: | ||
expected `i32`, | ||
found `i64` | ||
(expected i32, | ||
found i64) [E0308] | ||
if x == y { | ||
^ | ||
``` | ||
|
||
But, if we had an alias: | ||
|
||
```rust | ||
type Num = i32; | ||
|
||
let x: i32 = 5; | ||
let y: Num = 5; | ||
|
||
if x == y { | ||
// ... | ||
} | ||
``` | ||
|
||
This compiles without error. Values of a `Num` type are the same as a value of | ||
type `i32`, in every way. | ||
|
||
You can also use type aliases with generics: | ||
|
||
```rust | ||
use std::result; | ||
|
||
enum ConcreteError { | ||
Foo, | ||
Bar, | ||
} | ||
|
||
type Result<T> = result::Result<T, ConcreteError>; | ||
``` | ||
|
||
This creates a specialized version of the `Result` type, which always has a | ||
`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used | ||
in the standard library to create custom errors for each subsection. For | ||
example, [io::Result][ioresult]. | ||
|
||
[ioresult]: ../std/io/type.Result.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,58 @@ | ||
% Unsized Types | ||
|
||
Coming Soon! | ||
Most types have a particular size, in bytes, that is knowable at compile time. | ||
For example, an `i32` is thirty-two bits big, or four bytes. However, there are | ||
some types which are useful to express, but do not have a defined size. These are | ||
called ‘unsized’ or ‘dynamically sized’ types. One example is `[T]`. This type | ||
represents a certain number of `T` in sequence. But we don’t know how many | ||
there are, so the size is not known. | ||
|
||
Rust understands a few of these types, but they have some restrictions. There | ||
are three: | ||
|
||
1. We can only manipulate an instance of an unsized type via a pointer. An | ||
`&[T]` works just fine, but a `[T]` does not. | ||
2. Variables and arguments cannot have dynamically sized types. | ||
3. Only the last field in a `struct` may have a dynamically sized type; the | ||
other fields must not. Enum variants must not have dynamically sized types as | ||
data. | ||
|
||
So why bother? Well, because `[T]` can only be used behind a pointer, if we | ||
didn’t have language support for unsized types, it would be impossible to write | ||
this: | ||
|
||
```rust,ignore | ||
impl Foo for str { | ||
``` | ||
|
||
or | ||
|
||
```rust,ignore | ||
impl<T> Foo for [T] { | ||
``` | ||
|
||
Instead, you would have to write: | ||
|
||
```rust,ignore | ||
impl Foo for &str { | ||
``` | ||
|
||
Meaning, this implementation would only work for [references][ref], and not | ||
other types of pointers. With this `impl`, all pointers, including (at some | ||
point, there are some bugs to fix first) user-defined custom smart pointers, | ||
can use this `impl`. | ||
|
||
# ?Sized | ||
|
||
If you want to write a function that accepts a dynamically sized type, you | ||
can use the special bound, `?Sized`: | ||
|
||
```rust | ||
struct Foo<T: ?Sized> { | ||
f: T, | ||
} | ||
``` | ||
|
||
This `?`, read as “T may be `Sized`”, means that this bound is special: it | ||
lets us match more kinds, not less. It’s almost like every `T` implicitly has | ||
`T: Sized`, and the `?` undoes this default. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters