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 9 pull requests #38214

Merged
merged 16 commits into from
Dec 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 14 additions & 9 deletions src/doc/book/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,26 +662,31 @@ attribute turns off Rust's name mangling, so that it is easier to link to.

It’s important to be mindful of `panic!`s when working with FFI. A `panic!`
across an FFI boundary is undefined behavior. If you’re writing code that may
panic, you should run it in another thread, so that the panic doesn’t bubble up
to C:
panic, you should run it in a closure with [`catch_unwind()`]:

```rust
use std::thread;
use std::panic::catch_unwind;

#[no_mangle]
pub extern fn oh_no() -> i32 {
let h = thread::spawn(|| {
let result = catch_unwind(|| {
panic!("Oops!");
});

match h.join() {
Ok(_) => 1,
Err(_) => 0,
match result {
Ok(_) => 0,
Err(_) => 1,
}
}
# fn main() {}

fn main() {}
```

Please note that [`catch_unwind()`] will only catch unwinding panics, not
those who abort the process. See the documentation of [`catch_unwind()`]
for more information.

[`catch_unwind()`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

# Representing opaque structs

Sometimes, a C library wants to provide a pointer to something, but not let you
Expand Down
3 changes: 2 additions & 1 deletion src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,8 @@ syntax named by _designator_. Valid designators are:
* `ty`: a [type](#types)
* `ident`: an [identifier](#identifiers)
* `path`: a [path](#paths)
* `tt`: either side of the `=>` in macro rules
* `tt`: a token tree (a single [token](#tokens) or a sequence of token trees surrounded
by matching `()`, `[]`, or `{}`)
* `meta`: the contents of an [attribute](#attributes)

In the transcriber, the
Expand Down
88 changes: 45 additions & 43 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,35 @@

//! Single-threaded reference-counting pointers.
//!
//! The type [`Rc<T>`][rc] provides shared ownership of a value of type `T`,
//! allocated in the heap. Invoking [`clone`][clone] on `Rc` produces a new
//! pointer to the same value in the heap. When the last `Rc` pointer to a
//! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`,
//! allocated in the heap. Invoking [`clone()`][clone] on [`Rc`] produces a new
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a
//! given value is destroyed, the pointed-to value is also destroyed.
//!
//! Shared references in Rust disallow mutation by default, and `Rc` is no
//! exception. If you need to mutate through an `Rc`, use [`Cell`][cell] or
//! [`RefCell`][refcell].
//! exception. If you need to mutate through an [`Rc`], use [`Cell`] or
//! [`RefCell`].
//!
//! `Rc` uses non-atomic reference counting. This means that overhead is very
//! low, but an `Rc` cannot be sent between threads, and consequently `Rc`
//! [`Rc`] uses non-atomic reference counting. This means that overhead is very
//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
//! does not implement [`Send`][send]. As a result, the Rust compiler
//! will check *at compile time* that you are not sending `Rc`s between
//! will check *at compile time* that you are not sending [`Rc`]s between
//! threads. If you need multi-threaded, atomic reference counting, use
//! [`sync::Arc`][arc].
//!
//! The [`downgrade`][downgrade] method can be used to create a non-owning
//! [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
//! to an `Rc`, but this will return [`None`][option] if the value has
//! The [`downgrade()`][downgrade] method can be used to create a non-owning
//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
//! to an [`Rc`], but this will return [`None`] if the value has
//! already been dropped.
//!
//! A cycle between `Rc` pointers will never be deallocated. For this reason,
//! `Weak` is used to break cycles. For example, a tree could have strong
//! `Rc` pointers from parent nodes to children, and `Weak` pointers from
//! A cycle between [`Rc`] pointers will never be deallocated. For this reason,
//! [`Weak`] is used to break cycles. For example, a tree could have strong
//! [`Rc`] pointers from parent nodes to children, and [`Weak`] pointers from
//! children back to their parents.
//!
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
//! so you can call `T`'s methods on a value of type `Rc<T>`. To avoid name
//! clashes with `T`'s methods, the methods of `Rc<T>` itself are [associated
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
//! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are [associated
//! functions][assoc], called using function-like syntax:
//!
//! ```
Expand All @@ -50,28 +50,15 @@
//! Rc::downgrade(&my_rc);
//! ```
//!
//! `Weak<T>` does not auto-dereference to `T`, because the value may have
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the value may have
//! already been destroyed.
//!
//! [rc]: struct.Rc.html
//! [weak]: struct.Weak.html
//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
//! [cell]: ../../std/cell/struct.Cell.html
//! [refcell]: ../../std/cell/struct.RefCell.html
//! [send]: ../../std/marker/trait.Send.html
//! [arc]: ../../std/sync/struct.Arc.html
//! [deref]: ../../std/ops/trait.Deref.html
//! [downgrade]: struct.Rc.html#method.downgrade
//! [upgrade]: struct.Weak.html#method.upgrade
//! [option]: ../../std/option/enum.Option.html
//! [assoc]: ../../book/method-syntax.html#associated-functions
//!
//! # Examples
//!
//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.
//! We want to have our `Gadget`s point to their `Owner`. We can't do this with
//! unique ownership, because more than one gadget may belong to the same
//! `Owner`. `Rc` allows us to share an `Owner` between multiple `Gadget`s,
//! `Owner`. [`Rc`] allows us to share an `Owner` between multiple `Gadget`s,
//! and have the `Owner` remain allocated as long as any `Gadget` points at it.
//!
//! ```
Expand Down Expand Up @@ -127,20 +114,20 @@
//! ```
//!
//! If our requirements change, and we also need to be able to traverse from
//! `Owner` to `Gadget`, we will run into problems. An `Rc` pointer from `Owner`
//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner`
//! to `Gadget` introduces a cycle between the values. This means that their
//! reference counts can never reach 0, and the values will remain allocated
//! forever: a memory leak. In order to get around this, we can use `Weak`
//! forever: a memory leak. In order to get around this, we can use [`Weak`]
//! pointers.
//!
//! Rust actually makes it somewhat difficult to produce this loop in the first
//! place. In order to end up with two values that point at each other, one of
//! them needs to be mutable. This is difficult because `Rc` enforces
//! them needs to be mutable. This is difficult because [`Rc`] enforces
//! memory safety by only giving out shared references to the value it wraps,
//! and these don't allow direct mutation. We need to wrap the part of the
//! value we wish to mutate in a [`RefCell`][refcell], which provides *interior
//! value we wish to mutate in a [`RefCell`], which provides *interior
//! mutability*: a method to achieve mutability through a shared reference.
//! `RefCell` enforces Rust's borrowing rules at runtime.
//! [`RefCell`] enforces Rust's borrowing rules at runtime.
//!
//! ```
//! use std::rc::Rc;
Expand Down Expand Up @@ -214,6 +201,19 @@
//! // Gadget Man, so he gets destroyed as well.
//! }
//! ```
//!
//! [`Rc`]: struct.Rc.html
//! [`Weak`]: struct.Weak.html
//! [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
//! [`Cell`]: ../../std/cell/struct.Cell.html
//! [`RefCell`]: ../../std/cell/struct.RefCell.html
//! [send]: ../../std/marker/trait.Send.html
//! [arc]: ../../std/sync/struct.Arc.html
//! [`Deref`]: ../../std/ops/trait.Deref.html
//! [downgrade]: struct.Rc.html#method.downgrade
//! [upgrade]: struct.Weak.html#method.upgrade
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [assoc]: ../../book/method-syntax.html#associated-functions

#![stable(feature = "rust1", since = "1.0.0")]

Expand Down Expand Up @@ -251,9 +251,11 @@ struct RcBox<T: ?Sized> {
/// See the [module-level documentation](./index.html) for more details.
///
/// The inherent methods of `Rc` are all associated functions, which means
/// that you have to call them as e.g. `Rc::get_mut(&value)` instead of
/// `value.get_mut()`. This avoids conflicts with methods of the inner
/// that you have to call them as e.g. [`Rc::get_mut(&value)`][get_mut] instead of
/// `value.get_mut()`. This avoids conflicts with methods of the inner
/// type `T`.
///
/// [get_mut]: #method.get_mut
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rc<T: ?Sized> {
ptr: Shared<RcBox<T>>,
Expand Down Expand Up @@ -337,10 +339,10 @@ impl<T> Rc<T> {
}

/// Checks whether [`Rc::try_unwrap`][try_unwrap] would return
/// [`Ok`][result].
/// [`Ok`].
///
/// [try_unwrap]: struct.Rc.html#method.try_unwrap
/// [result]: ../../std/result/enum.Result.html
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
///
/// # Examples
///
Expand Down Expand Up @@ -543,14 +545,14 @@ impl<T: ?Sized> Rc<T> {
/// Returns a mutable reference to the inner value, if there are
/// no other `Rc` or [`Weak`][weak] pointers to the same value.
///
/// Returns [`None`][option] otherwise, because it is not safe to
/// Returns [`None`] otherwise, because it is not safe to
/// mutate a shared value.
///
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
/// the inner value when it's shared.
///
/// [weak]: struct.Weak.html
/// [option]: ../../std/option/enum.Option.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [make_mut]: struct.Rc.html#method.make_mut
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
///
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_resolve/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ impl<'a, 'b> Visitor for UnusedImportCheckVisitor<'a, 'b> {
}

ViewPathList(_, ref list) => {
if list.len() == 0 {
self.unused_imports
.entry(item.id)
.or_insert_with(NodeMap)
.insert(item.id, item.span);
}
for i in list {
self.check_import(item.id, i.node.id, i.span);
}
Expand Down
4 changes: 4 additions & 0 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,10 @@ impl DefaultHasher {

#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
impl Default for DefaultHasher {
/// Creates a new `DefaultHasher` using [`DefaultHasher::new`]. See
/// [`DefaultHasher::new`] documentation for more information.
///
/// [`DefaultHasher::new`]: #method.new
fn default() -> DefaultHasher {
DefaultHasher::new()
}
Expand Down
106 changes: 104 additions & 2 deletions src/libstd/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,23 @@ pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
}

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook()`]
/// function.
///
/// [`set_hook()`]: ../../std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// println!("panic occured: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct PanicInfo<'a> {
payload: &'a (Any + Send),
Expand All @@ -168,7 +185,21 @@ pub struct PanicInfo<'a> {
impl<'a> PanicInfo<'a> {
/// Returns the payload associated with the panic.
///
/// This will commonly, but not always, be a `&'static str` or `String`.
/// This will commonly, but not always, be a `&'static str` or [`String`].
///
/// [`String`]: ../../std/string/struct.String.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// println!("panic occured: {:?}", panic_info.payload().downcast_ref::<&str>().unwrap());
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn payload(&self) -> &(Any + Send) {
self.payload
Expand All @@ -177,15 +208,54 @@ impl<'a> PanicInfo<'a> {
/// Returns information about the location from which the panic originated,
/// if available.
///
/// This method will currently always return `Some`, but this may change
/// This method will currently always return [`Some`], but this may change
/// in future versions.
///
/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// if let Some(location) = panic_info.location() {
/// println!("panic occured in file '{}' at line {}", location.file(), location.line());
/// } else {
/// println!("panic occured but can't get location information...");
/// }
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn location(&self) -> Option<&Location> {
Some(&self.location)
}
}

/// A struct containing information about the location of a panic.
///
/// This structure is created by the [`location()`] method of [`PanicInfo`].
///
/// [`location()`]: ../../std/panic/struct.PanicInfo.html#method.location
/// [`PanicInfo`]: ../../std/panic/struct.PanicInfo.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// if let Some(location) = panic_info.location() {
/// println!("panic occured in file '{}' at line {}", location.file(), location.line());
/// } else {
/// println!("panic occured but can't get location information...");
/// }
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
file: &'a str,
Expand All @@ -194,12 +264,44 @@ pub struct Location<'a> {

impl<'a> Location<'a> {
/// Returns the name of the source file from which the panic originated.
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// if let Some(location) = panic_info.location() {
/// println!("panic occured in file '{}'", location.file());
/// } else {
/// println!("panic occured but can't get location information...");
/// }
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn file(&self) -> &str {
self.file
}

/// Returns the line number from which the panic originated.
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
/// if let Some(location) = panic_info.location() {
/// println!("panic occured at line {}", location.line());
/// } else {
/// println!("panic occured but can't get location information...");
/// }
/// }));
///
/// panic!("Normal panic");
/// ```
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn line(&self) -> u32 {
self.line
Expand Down
Loading