Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of PRs in the queue; Thursday #23298

Merged
merged 33 commits into from
Mar 12, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1275c11
fix rustdoc performance problems
mahkoh Feb 24, 2015
660b48f
Add support for target-cpu=native
mahkoh Mar 10, 2015
fcae449
Purge `isize` from `core::iter`
tbu- Mar 10, 2015
fbc10c3
configure: have --enable-debug set -C debug-assertions=on so `debug!(…
codyps Mar 9, 2015
0ad8741
std: Stabilize slice::from_raw_parts
alexcrichton Mar 10, 2015
d6492e2
Fix markdown bullet points in function docs
frewsxcv Mar 11, 2015
8e082f7
disabling jemalloc on bitrig
Mar 10, 2015
33751ff
adding latest bitrig snapshot manually
Mar 10, 2015
61004f8
Improve -Z unstable-options diagnostics and avoid an ICE
rprichard Mar 11, 2015
8934c9b
Add note about local documentation installation
steveklabnik Mar 11, 2015
100e1a9
mk/tests: filter more possible debug-assertions
codyps Mar 11, 2015
47f1d67
First-class struct and tuple constants
aochagavia Mar 8, 2015
a83db81
Update tests
aochagavia Mar 11, 2015
3ac89d3
Rewrite the dynamic dispatch section to focus on usage rather than im…
Ms2ger Mar 9, 2015
de67c3a
Fix LLVM assertion when out-of-bounds indexing in a constant
dotdash Mar 11, 2015
ac6cd90
Explain why immediately dropping a JoinGuard is not what you want to do
shepmaster Mar 12, 2015
64ab111
Example -> Examples
steveklabnik Mar 12, 2015
2c251fa
Rollup merge of #23294 - dotdash:coob, r=alexcrichton
Manishearth Mar 12, 2015
0a74387
Rollup merge of #23297 - steveklabnik:examples, r=huonw
Manishearth Mar 12, 2015
21b024a
Rollup merge of #22769 - :rustdocfix, r=brson
Manishearth Mar 12, 2015
497f6b7
Rollup merge of #23234 - Ms2ger:doc-dynamic-dispatch, r=steveklabnik
Manishearth Mar 12, 2015
9e2cf11
Rollup merge of #23238 - mahkoh:nativecpu, r=dotdash
Manishearth Mar 12, 2015
7a9ef60
Rollup merge of #23247 - tbu-:pr_core_iter_rm_isize, r=huonw
Manishearth Mar 12, 2015
e4010d1
Rollup merge of #23255 - dhuseby:master, r=alexcrichton
Manishearth Mar 12, 2015
34d87b2
Rollup merge of #23257 - jmesmon:fix-debug, r=alexcrichton
Manishearth Mar 12, 2015
6290a34
Rollup merge of #23263 - alexcrichton:stabilize-from-raw-parts, r=brson
Manishearth Mar 12, 2015
99dc60d
Rollup merge of #23270 - frewsxcv:patch-5, r=alexcrichton
Manishearth Mar 12, 2015
e4e5640
Rollup merge of #23274 - rprichard:fix-21715, r=pnkfelix
Manishearth Mar 12, 2015
cc6ef80
Rollup merge of #23275 - aochagavia:constants, r=eddyb
Manishearth Mar 12, 2015
85d836a
Rollup merge of #23279 - steveklabnik:gh23244, r=alexcrichton
Manishearth Mar 12, 2015
3d70c70
Rollup merge of #23295 - johnz133:patch-1, r=steveklabnik
Manishearth Mar 12, 2015
7f7a3cc
Rollup merge of #23296 - shepmaster:explain-why-joinguard-is-must-use…
Manishearth Mar 12, 2015
419c0ff
Rm unused feature
Manishearth Mar 11, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,9 @@ fi
# Force bitrig to build with clang; gcc doesn't like us there
if [ $CFG_OSTYPE = unknown-bitrig ]
then
step_msg "on Bitrig, forcing use of clang"
step_msg "on Bitrig, forcing use of clang, disabling jemalloc"
CFG_ENABLE_CLANG=1
CFG_ENABLE_JEMALLOC=0
fi

if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
Expand Down
2 changes: 1 addition & 1 deletion mk/main.mk
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ ifdef CFG_DISABLE_DEBUG
CFG_RUSTC_FLAGS += --cfg ndebug
else
$(info cfg: enabling more debugging (CFG_ENABLE_DEBUG))
CFG_RUSTC_FLAGS += --cfg debug
CFG_RUSTC_FLAGS += --cfg debug -C debug-assertions=on
endif

ifdef SAVE_TEMPS
Expand Down
2 changes: 1 addition & 1 deletion mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \

# The tests select when to use debug configuration on their own;
# remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898).
CTEST_RUSTC_FLAGS := $$(subst -C debug-assertions,,$$(CFG_RUSTC_FLAGS))
CTEST_RUSTC_FLAGS := $$(subst -C debug-assertions,,$$(subst -C debug-assertions=on,,$$(CFG_RUSTC_FLAGS)))

# The tests cannot be optimized while the rest of the compiler is optimized, so
# filter out the optimization (if any) from rustc and then figure out if we need
Expand Down
2 changes: 1 addition & 1 deletion src/doc/trpl/comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The other kind of comment is a doc comment. Doc comments use `///` instead of
///
/// * `name` - The name of the person you'd like to greet.
///
/// # Example
/// # Examples
///
/// ```rust
/// let name = "Steve";
Expand Down
5 changes: 5 additions & 0 deletions src/doc/trpl/installing-rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06)

If you did, Rust has been installed successfully! Congrats!

This installer also installs a copy of the documentation locally, so you can
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
to.

If not, there are a number of places where you can get help. The easiest is
[the #rust IRC channel on irc.mozilla.org](irc://irc.mozilla.org/#rust), which
you can access through
Expand Down
117 changes: 68 additions & 49 deletions src/doc/trpl/static-and-dynamic-dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,49 +102,88 @@ reason.
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
*any* type that implements the given trait, where the precise type can only be
known at runtime. The methods of the trait can be called on a trait object via
a special record of function pointers (created and managed by the compiler).
known at runtime.

A function that takes a trait object is not specialized to each of the types
that implements `Foo`: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimisations from occurring.
A trait object can be obtained from a pointer to a concrete type that
implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
(e.g. using `&x` as an argument to a function that takes `&Foo`).

Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.
These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
and casts are identical.

### Obtaining a trait object
This operation can be seen as "erasing" the compiler's knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as "type erasure".

There's two similar ways to get a trait object value: casts and coercions. If
`T` is a type that implements a trait `Foo` (e.g. `u8` for the `Foo` above),
then the two ways to get a `Foo` trait object out of a pointer to `T` look
like:
Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting:

```{rust,ignore}
let ref_to_t: &T = ...;
```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }

// `as` keyword for casting
let cast = ref_to_t as &Foo;
fn do_something(x: &Foo) {
x.method();
}

// using a `&T` in a place that has a known type of `&Foo` will implicitly coerce:
let coerce: &Foo = ref_to_t;
fn main() {
let x = 5u8;
do_something(&x as &Foo);
}
```

fn also_coerce(_unused: &Foo) {}
also_coerce(ref_to_t);
or by coercing:

```rust
# trait Foo { fn method(&self) -> String; }
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }

fn do_something(x: &Foo) {
x.method();
}

fn main() {
let x = "Hello".to_string();
do_something(&x);
}
```

These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
and casts are identical.
A function that takes a trait object is not specialized to each of the types
that implements `Foo`: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimisations from occurring.

This operation can be seen as "erasing" the compiler's knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as "type erasure".
### Why pointers?

Rust does not put things behind a pointer by default, unlike many managed
languages, so types can have different sizes. Knowing the size of the value at
compile time is important for things like passing it as an argument to a
function, moving it about on the stack and allocating (and deallocating) space
on the heap to store it.

For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). There's no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.

Putting the value behind a pointer means the size of the value is not relevant
when we are tossing a trait object around, only the size of the pointer itself.

### Representation

The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a 'vtable' (created and managed by
the compiler).

Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.

Let's start simple, with the runtime representation of a trait object. The
`std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]:
Expand Down Expand Up @@ -265,23 +304,3 @@ let y = TraitObject {
If `b` or `y` were owning trait objects (`Box<Foo>`), there would be a
`(b.vtable.destructor)(b.data)` (respectively `y`) call when they went out of
scope.

### Why pointers?

The use of language like "fat pointer" implies that a trait object is
always a pointer of some form, but why?

Rust does not put things behind a pointer by default, unlike many managed
languages, so types can have different sizes. Knowing the size of the value at
compile time is important for things like passing it as an argument to a
function, moving it about on the stack and allocating (and deallocating) space
on the heap to store it.

For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). There's no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.

Putting the value behind a pointer means the size of the value is not relevant
when we are tossing a trait object around, only the size of the pointer itself.
2 changes: 1 addition & 1 deletion src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ use heap::deallocate;

/// An atomically reference counted wrapper for shared state.
///
/// # Example
/// # Examples
///
/// In this example, a large vector of floats is shared between several tasks.
/// With simple pipes, without `Arc`, a copy would have to be made for each
Expand Down
2 changes: 1 addition & 1 deletion src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl<T : ?Sized> Box<T> {
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Example
/// # Examples
/// ```
/// use std::boxed;
///
Expand Down
4 changes: 2 additions & 2 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub fn is_unique<T>(rc: &Rc<T>) -> bool {
///
/// If the `Rc<T>` is not unique, an `Err` is returned with the same `Rc<T>`.
///
/// # Example
/// # Examples
///
/// ```
/// use std::rc::{self, Rc};
Expand Down Expand Up @@ -298,7 +298,7 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
///
/// Returns `None` if the `Rc<T>` is not unique.
///
/// # Example
/// # Examples
///
/// ```
/// use std::rc::{self, Rc};
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ impl<T> ToOwned for T where T: Clone {
/// is desired, `to_mut` will obtain a mutable references to an owned
/// value, cloning if necessary.
///
/// # Example
/// # Examples
///
/// ```rust
/// use std::borrow::Cow;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
impl<K, V> BTreeMap<K, V> {
/// Gets an iterator over the entries of the map.
///
/// # Example
/// # Examples
///
/// ```
/// use std::collections::BTreeMap;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ use string;
///
/// * args - a structure of arguments generated via the `format_args!` macro.
///
/// # Example
/// # Examples
///
/// ```rust
/// use std::fmt;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ macro_rules! vec {
/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
/// # Example
/// # Examples
///
/// ```
/// format!("test");
Expand Down
24 changes: 12 additions & 12 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ pub trait SliceExt {
///
/// Panics if `size` is 0.
///
/// # Example
/// # Examples
///
/// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`,
/// `[3,4]`):
Expand All @@ -300,7 +300,7 @@ pub trait SliceExt {
///
/// Panics if `size` is 0.
///
/// # Example
/// # Examples
///
/// Print the slice two elements at a time (i.e. `[1,2]`,
/// `[3,4]`, `[5]`):
Expand Down Expand Up @@ -390,7 +390,7 @@ pub trait SliceExt {
/// `Err` is returned, containing the index where a matching
/// element could be inserted while maintaining sorted order.
///
/// # Example
/// # Examples
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
Expand All @@ -416,7 +416,7 @@ pub trait SliceExt {

/// Return the number of elements in the slice
///
/// # Example
/// # Examples
///
/// ```
/// let a = [1, 2, 3];
Expand All @@ -427,7 +427,7 @@ pub trait SliceExt {

/// Returns true if the slice has a length of 0
///
/// # Example
/// # Examples
///
/// ```
/// let a = [1, 2, 3];
Expand Down Expand Up @@ -529,7 +529,7 @@ pub trait SliceExt {
///
/// Panics if `a` or `b` are out of bounds.
///
/// # Example
/// # Examples
///
/// ```rust
/// let mut v = ["a", "b", "c", "d"];
Expand All @@ -549,7 +549,7 @@ pub trait SliceExt {
///
/// Panics if `mid > len`.
///
/// # Example
/// # Examples
///
/// ```rust
/// let mut v = [1, 2, 3, 4, 5, 6];
Expand Down Expand Up @@ -578,7 +578,7 @@ pub trait SliceExt {

/// Reverse the order of elements in a slice, in place.
///
/// # Example
/// # Examples
///
/// ```rust
/// let mut v = [1, 2, 3];
Expand Down Expand Up @@ -638,7 +638,7 @@ pub trait SliceExt {
/// shorter of `self.len()` and `src.len()`). Returns the number
/// of elements copied.
///
/// # Example
/// # Examples
///
/// ```rust
/// let mut dst = [0, 0, 0];
Expand Down Expand Up @@ -676,7 +676,7 @@ pub trait SliceExt {
/// `Err` is returned, containing the index where a matching
/// element could be inserted while maintaining sorted order.
///
/// # Example
/// # Examples
///
/// Looks up a series of four elements. The first is found, with a
/// uniquely determined position; the second and third are not
Expand Down Expand Up @@ -707,7 +707,7 @@ pub trait SliceExt {
/// Returns `true` if successful and `false` if the slice is at the
/// last-ordered permutation.
///
/// # Example
/// # Examples
///
/// ```rust
/// let v: &mut [_] = &mut [0, 1, 2];
Expand All @@ -727,7 +727,7 @@ pub trait SliceExt {
/// Returns `true` if successful and `false` if the slice is at the
/// first-ordered permutation.
///
/// # Example
/// # Examples
///
/// ```rust
/// let v: &mut [_] = &mut [1, 0, 2];
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
///
/// Will return `Err` if it's not possible to parse `self` into the type.
///
/// # Example
/// # Examples
///
/// ```
/// assert_eq!("4".parse::<u32>(), Ok(4));
Expand Down
1 change: 1 addition & 0 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ impl String {
/// Creates a new `String` from a length, capacity, and pointer.
///
/// This is unsafe because:
///
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
/// * We assume that the `Vec` contains valid UTF-8.
#[inline]
Expand Down
Loading