Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
5541207
Add lifetime elision information to the ownership guide.
steveklabnik Dec 11, 2014
9f244dc
Minor fix for the Rust language FAQ
barosl Dec 13, 2014
739f74b
Make the line numbers of the source code clickable
barosl Dec 19, 2014
9554794
Add unstable_options method
sanxiyn Dec 27, 2014
d4da758
Use -Z unstable-options for span debugger
sanxiyn Dec 27, 2014
20fa7cb
Add header to optimizations section
steveklabnik Dec 15, 2014
cd85f0a
restore paragraph
steveklabnik Dec 15, 2014
98aeac2
Extend span debugger
sanxiyn Dec 27, 2014
5cf72ff
Parse arbitrary operators after expr-like macro invocations in statem…
ftxqxd Dec 21, 2014
5b0bebf
Return passed value from black_box
amaranth Jan 3, 2015
3995797
Minor documentation edit.
SeanTAllen Jan 3, 2015
0536986
Minor documentation edit.
SeanTAllen Jan 3, 2015
149833d
Update rust-installer. Fixes #20479
brson Jan 3, 2015
8cebb1f
Rename `raw_pointer_deriving` lint to `raw_pointer_derive`
csouth3 Jan 4, 2015
56f3f83
Fix the parsing of where-clauses for structs
jroesch Jan 2, 2015
e723fe0
Do not use entropy during gen_weighted_bool(1)
nagisa Jan 4, 2015
9b820d0
Correct the subtyping relations created by the pattern typechecking
nikomatsakis Jan 4, 2015
a17a7c9
Miscellaneous reformatting and commenting.
nikomatsakis Jan 4, 2015
dbfa054
Cleanup type-checking of constants, but do not try to fix #20489.
nikomatsakis Jan 4, 2015
cc18053
bench: do not quit rt-messaging-ping-pong.rs early
tshepang Jan 5, 2015
fb1871d
Refactor struct parsing and add tests
jroesch Jan 4, 2015
540bec1
sed -i -s 's/ for Sized?//g' **/*.rs
Jan 5, 2015
0995c60
remove unused `Sized` imports
Jan 5, 2015
04b006a
undo one `for Sized?` removal that was in a comment
Jan 5, 2015
8abcbf9
update comment to reflect new `Sized` semantics
Jan 5, 2015
bf6c007
Change `&` pat to only work with &T, and `&mut` with &mut T.
huonw Dec 5, 2014
5deef52
std: Redesign c_str and c_vec
alexcrichton Nov 25, 2014
0cb7a40
serialize: Use assoc types + less old_orphan_check
alexcrichton Jan 4, 2015
0be4630
rollup merge of #19736: steveklabnik/gh19662
alexcrichton Jan 5, 2015
4893114
rollup merge of #19888: steveklabnik/gh19861
alexcrichton Jan 5, 2015
f6438cf
rollup merge of #20092: barosl/rustdoc-line-number-clickable
alexcrichton Jan 5, 2015
2383a9c
rollup merge of #20099: P1start/parse-more-macro-ops
alexcrichton Jan 5, 2015
ed9a10a
rollup merge of #20258: sanxiyn/show-span-2
alexcrichton Jan 5, 2015
1663b48
rollup merge of #20424: jroesch/tuple-struct-where-clause-fix
alexcrichton Jan 5, 2015
51269f0
rollup merge of #20451: brson/installer
alexcrichton Jan 5, 2015
124eb28
rollup merge of #20463: amaranth/black_box_output
alexcrichton Jan 5, 2015
80e4cce
rollup merge of #20478: SeanTAllen/master
alexcrichton Jan 5, 2015
1140588
rollup merge of #20507: alexcrichton/issue-20444
alexcrichton Jan 5, 2015
3e1ea44
rollup merge of #20511: csouth3/derive-lint
alexcrichton Jan 5, 2015
0787e7d
rollup merge of #20514: alexcrichton/serialize-associated-type
alexcrichton Jan 5, 2015
cb8f6e2
rollup merge of #20517: nikomatsakis/safety-issue-19997
alexcrichton Jan 5, 2015
2a514a0
rollup merge of #20518: nagisa/weighted-bool
alexcrichton Jan 5, 2015
8a6325c
rollup merge of #20548: tshepang/fix-ping-pong-benchmark
alexcrichton Jan 5, 2015
c397f49
rollup merge of #20554: huonw/mut-pattern
alexcrichton Jan 5, 2015
3fa3557
rollup merge of #20556: japaric/no-for-sized
alexcrichton Jan 5, 2015
acef292
Test fixes and rebase conflicts
alexcrichton Jan 5, 2015
085e4e4
Merge remote-tracking branch 'origin/master' into rollup
alexcrichton Jan 5, 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
2 changes: 1 addition & 1 deletion src/doc/complement-lang-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Some examples that demonstrate different aspects of the language:
* [sprocketnes], an NES emulator with no GC, using modern Rust conventions
* The language's general-purpose [hash] function, SipHash-2-4. Bit twiddling, OO, macros
* The standard library's [HashMap], a sendable hash map in an OO style
* The extra library's [json] module. Enums and pattern matching
* The standard library's [json] module. Enums and pattern matching

[sprocketnes]: https://github.com/pcwalton/sprocketnes
[hash]: https://github.com/rust-lang/rust/blob/master/src/libstd/hash/mod.rs
Expand Down
50 changes: 27 additions & 23 deletions src/doc/guide-ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ them.
~~~no_run
extern crate libc;

use std::c_str::ToCStr;
use std::ffi::CString;
use std::ptr;

#[link(name = "readline")]
Expand All @@ -460,11 +460,10 @@ extern {
}

fn main() {
"[my-awesome-shell] $".with_c_str(|buf| {
unsafe { rl_prompt = buf; }
// get a line, process it
unsafe { rl_prompt = ptr::null(); }
});
let prompt = CString::from_slice(b"[my-awesome-shell] $");
unsafe { rl_prompt = prompt.as_ptr(); }
// get a line, process it
unsafe { rl_prompt = ptr::null(); }
}
~~~

Expand Down Expand Up @@ -509,23 +508,28 @@ to define a block for all windows systems, not just x86 ones.

# Interoperability with foreign code

Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out
struct members without padding. `#[repr(C)]` can also be applied to an enum.

Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
object. However, they should not be manually created because they are managed by internal
allocators. References can safely be assumed to be non-nullable pointers directly to the type.
However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
them.

Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.

The standard library includes type aliases and function definitions for the C standard library in
the `libc` module, and Rust links against `libc` and `libm` by default.
Rust guarantees that the layout of a `struct` is compatible with the platform's
representation in C only if the `#[repr(C)]` attribute is applied to it.
`#[repr(C, packed)]` can be used to lay out struct members without padding.
`#[repr(C)]` can also be applied to an enum.

Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
to the contained object. However, they should not be manually created because
they are managed by internal allocators. References can safely be assumed to be
non-nullable pointers directly to the type. However, breaking the borrow
checking or mutability rules is not guaranteed to be safe, so prefer using raw
pointers (`*`) if that's needed because the compiler can't make as many
assumptions about them.

Vectors and strings share the same basic memory layout, and utilities are
available in the `vec` and `str` modules for working with C APIs. However,
strings are not terminated with `\0`. If you need a NUL-terminated string for
interoperability with C, you should use the `CString` type in the `std::ffi`
module.

The standard library includes type aliases and function definitions for the C
standard library in the `libc` module, and Rust links against `libc` and `libm`
by default.

# The "nullable pointer optimization"

Expand Down
80 changes: 78 additions & 2 deletions src/doc/guide-ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@ fn add_one(num: &int) -> int {
```

Rust has a feature called 'lifetime elision,' which allows you to not write
lifetime annotations in certain circumstances. This is one of them. Without
eliding the lifetimes, `add_one` looks like this:
lifetime annotations in certain circumstances. This is one of them. We will
cover the others later. Without eliding the lifetimes, `add_one` looks like
this:

```rust
fn add_one<'a>(num: &'a int) -> int {
Expand Down Expand Up @@ -449,6 +450,81 @@ This is the simplest kind of multiple ownership possible. For example, there's
also `Arc<T>`, which uses more expensive atomic instructions to be the
thread-safe counterpart of `Rc<T>`.

## Lifetime Elision

Earlier, we mentioned 'lifetime elision,' a feature of Rust which allows you to
not write lifetime annotations in certain circumstances. All references have a
lifetime, and so if you elide a lifetime (like `&T` instead of `&'a T`), Rust
will do three things to determine what those lifetimes should be.

When talking about lifetime elision, we use the term 'input lifetime' and
'output lifetime'. An 'input liftime' is a lifetime associated with a parameter
of a function, and an 'output lifetime' is a lifetime associated with the return
value of a function. For example, this function has an input lifetime:

```{rust,ignore}
fn foo<'a>(bar: &'a str)
```

This one has an output lifetime:

```{rust,ignore}
fn foo<'a>() -> &'a str
```

This one has both:

```{rust,ignore}
fn foo<'a>(bar: &'a str) -> &'a str
```

Here are the three rules:

* Each elided lifetime in a function's arguments becomes a distinct lifetime
parameter.

* If there is exactly one input lifetime, elided or not, that lifetime is
assigned to all elided lifetimes in the return values of that function..

* If there are multiple input lifetimes, but one of them is `&self` or `&mut
self`, the lifetime of `self` is assigned to all elided output lifetimes.

Otherwise, it is an error to elide an output lifetime.

### Examples

Here are some examples of functions with elided lifetimes, and the version of
what the elided lifetimes are expand to:

```{rust,ignore}
fn print(s: &str); // elided
fn print<'a>(s: &'a str); // expanded

fn debug(lvl: uint, s: &str); // elided
fn debug<'a>(lvl: uint, s: &'a str); // expanded

// In the preceeding example, `lvl` doesn't need a lifetime because it's not a
// reference (`&`). Only things relating to references (such as a `struct`
// which contains a reference) need lifetimes.

fn substr(s: &str, until: uint) -> &str; // elided
fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded

fn get_str() -> &str; // ILLEGAL, no inputs

fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs

fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded

fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded

fn new(buf: &mut [u8]) -> BufWriter; // elided
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded

```

# Related Resources

Coming Soon.
13 changes: 11 additions & 2 deletions src/doc/guide-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ Advice on writing benchmarks:
* Make the code in the `iter` loop do something simple, to assist in pinpointing
performance improvements (or regressions)

## Gotcha: optimizations

There's another tricky part to writing benchmarks: benchmarks compiled with
optimizations activated can be dramatically changed by the optimizer so that
the benchmark is no longer benchmarking what one expects. For example, the
Expand Down Expand Up @@ -554,8 +556,12 @@ extern crate test;
# fn main() {
# struct X; impl X { fn iter<T>(&self, _: || -> T) {} } let b = X;
b.iter(|| {
test::black_box(range(0u, 1000).fold(0, |old, new| old ^ new));
});
let mut n = 1000_u32;

test::black_box(&mut n); // pretend to modify `n`

range(0, n).fold(0, |a, b| a ^ b)
})
# }
```

Expand All @@ -571,3 +577,6 @@ test bench_xor_1000_ints ... bench: 1 ns/iter (+/- 0)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
```

However, the optimizer can still modify a testcase in an undesirable manner
even when using either of the above.
4 changes: 2 additions & 2 deletions src/doc/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ Hello, world!
Bam! We build our project with `cargo build`, and run it with
`./target/hello_world`. This hasn't bought us a whole lot over our simple use
of `rustc`, but think about the future: when our project has more than one
file, we would need to call `rustc` twice, and pass it a bunch of options to
file, we would need to call `rustc` more than once, and pass it a bunch of options to
tell it to build everything together. With Cargo, as our project grows, we can
just `cargo build` and it'll work the right way.

Expand Down Expand Up @@ -977,7 +977,7 @@ fn main() {
```

Even though Rust functions can only return one value, a tuple _is_ one value,
that happens to be made up of two. You can also see in this example how you
that happens to be made up of more than one value. You can also see in this example how you
can destructure a pattern returned by a function, as well.

Tuples are a very simple data structure, and so are not often what you want.
Expand Down
5 changes: 3 additions & 2 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -3484,8 +3484,9 @@ fn main() {

```

Patterns can also dereference pointers by using the `&`, `box` symbols,
as appropriate. For example, these two matches on `x: &int` are equivalent:
Patterns can also dereference pointers by using the `&`, `&mut` and `box`
symbols, as appropriate. For example, these two matches on `x: &int` are
equivalent:

```
# let x = &3i;
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2541,7 +2541,7 @@ mod bitv_bench {
for _ in range(0u, 100) {
bitv |= 1 << ((r.next_u32() as uint) % u32::BITS);
}
black_box(&bitv)
black_box(&bitv);
});
}

Expand All @@ -2553,7 +2553,7 @@ mod bitv_bench {
for _ in range(0u, 100) {
bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
}
black_box(&bitv)
black_box(&bitv);
});
}

Expand Down
1 change: 1 addition & 0 deletions src/libcollections/dlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,7 @@ mod tests {
}

#[allow(deprecated)]
#[test]
fn test_append() {
{
let mut m = DList::new();
Expand Down
4 changes: 2 additions & 2 deletions src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub use core::slice::{from_raw_buf, from_raw_mut_buf};

/// Allocating extension methods for slices.
#[unstable = "needs associated types, may merge with other traits"]
pub trait SliceExt for Sized? {
pub trait SliceExt {
type Item;

/// Sorts the slice, in place, using `compare` to compare
Expand Down Expand Up @@ -989,7 +989,7 @@ impl<T> SliceExt for [T] {
////////////////////////////////////////////////////////////////////////////////
#[unstable = "U should be an associated type"]
/// An extension trait for concatenating slices
pub trait SliceConcatExt<Sized? T, U> for Sized? {
pub trait SliceConcatExt<Sized? T, U> {
/// Flattens a slice of `T` into a single value `U`.
#[stable]
fn concat(&self) -> U;
Expand Down
7 changes: 3 additions & 4 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ use core::char::CharExt;
use core::clone::Clone;
use core::iter::AdditiveIterator;
use core::iter::{range, Iterator, IteratorExt};
use core::kinds::Sized;
use core::ops;
use core::option::Option::{self, Some, None};
use core::slice::AsSlice;
Expand Down Expand Up @@ -401,7 +400,7 @@ Section: Trait implementations
*/

/// Any string that can be represented as a slice.
pub trait StrExt for Sized?: ops::Slice<uint, str> {
pub trait StrExt: ops::Slice<uint, str> {
/// Escapes each char in `s` with `char::escape_default`.
#[unstable = "return type may change to be an iterator"]
fn escape_default(&self) -> String {
Expand Down Expand Up @@ -2829,7 +2828,7 @@ mod bench {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";

b.iter(|| {
for ch in s.chars() { black_box(ch) }
for ch in s.chars() { black_box(ch); }
});
}

Expand Down Expand Up @@ -2857,7 +2856,7 @@ mod bench {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";

b.iter(|| {
for ch in s.chars().rev() { black_box(ch) }
for ch in s.chars().rev() { black_box(ch); }
});
}

Expand Down
42 changes: 0 additions & 42 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,30 +320,6 @@ impl String {
}
}

/// Creates a `String` from a null-terminated `*const u8` buffer.
///
/// This function is unsafe because we dereference memory until we find the
/// NUL character, which is not guaranteed to be present. Additionally, the
/// slice is not checked to see whether it contains valid UTF-8
#[unstable = "just renamed from `mod raw`"]
pub unsafe fn from_raw_buf(buf: *const u8) -> String {
String::from_str(str::from_c_str(buf as *const i8))
}

/// Creates a `String` from a `*const u8` buffer of the given length.
///
/// This function is unsafe because it blindly assumes the validity of the
/// pointer `buf` for `len` bytes of memory. This function will copy the
/// memory from `buf` into a new allocation (owned by the returned
/// `String`).
///
/// This function is also unsafe because it does not validate that the
/// buffer is valid UTF-8 encoded data.
#[unstable = "just renamed from `mod raw`"]
pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
}

/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
Expand Down Expand Up @@ -1126,24 +1102,6 @@ mod tests {
String::from_str("\u{FFFD}𐒋\u{FFFD}"));
}

#[test]
fn test_from_buf_len() {
unsafe {
let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
}
}

#[test]
fn test_from_buf() {
unsafe {
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = String::from_raw_buf(b);
assert_eq!(c, String::from_str("AAAAAAA"));
}
}

#[test]
fn test_push_bytes() {
let mut s = String::from_str("ABC");
Expand Down
6 changes: 3 additions & 3 deletions src/libcore/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ use option::Option;
use self::Cow::*;

/// A trait for borrowing data.
pub trait BorrowFrom<Sized? Owned> for Sized? {
pub trait BorrowFrom<Sized? Owned> {
/// Immutably borrow from an owned value.
fn borrow_from(owned: &Owned) -> &Self;
}

/// A trait for mutably borrowing data.
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
pub trait BorrowFromMut<Sized? Owned> : BorrowFrom<Owned> {
/// Mutably borrow from an owned value.
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
}
Expand Down Expand Up @@ -103,7 +103,7 @@ impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
}

/// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
pub trait ToOwned<Owned>: BorrowFrom<Owned> {
/// Create owned data from borrowed data, usually by copying.
fn to_owned(&self) -> Owned;
}
Expand Down
Loading