diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md index e09922fd390a9..d531a22d0e0dd 100644 --- a/src/doc/trpl/compound-data-types.md +++ b/src/doc/trpl/compound-data-types.md @@ -47,7 +47,7 @@ This pattern is very powerful, and we'll see it repeated more later. There are also a few things you can do with a tuple as a whole, without destructuring. You can assign one tuple into another, if they have the same -contained types and arity. Tuples have the same arity when they have the same +contained types and [arity]. Tuples have the same arity when they have the same length. ```rust @@ -196,8 +196,9 @@ Now, we have actual names, rather than positions. Good names are important, and with a struct, we have actual names. There _is_ one case when a tuple struct is very useful, though, and that's a -tuple struct with only one element. We call this a *newtype*, because it lets -you create a new type that's similar to another one: +tuple struct with only one element. We call this the *newtype* pattern, because +it allows you to create a new type, distinct from that of its contained value +and expressing its own semantic meaning: ```{rust} struct Inches(i32); @@ -216,7 +217,7 @@ destructuring `let`, as we discussed previously in 'tuples.' In this case, the Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful feature of Rust, and are used throughout the standard library. An `enum` is -a type which ties a set of alternates to a specific name. For example, below +a type which relates a set of alternates to a specific name. For example, below we define `Character` to be either a `Digit` or something else. These can be used via their fully scoped names: `Character::Other` (more about `::` below). @@ -228,8 +229,8 @@ enum Character { } ``` -An `enum` variant can be defined as most normal types. Below are some example -types which also would be allowed in an `enum`. +Most normal types are allowed as the variant components of an `enum`. Here are +some examples: ```rust struct Empty; @@ -239,15 +240,15 @@ struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 } struct HeightDatabase(Vec); ``` -So you see that depending on the sub-datastructure, the `enum` variant, same as -a struct, may or may not hold data. That is, in `Character`, `Digit` is a name -tied to an `i32` where `Other` is just a name. However, the fact that they are -distinct makes this very useful. +You see that, depending on its type, an `enum` variant may or may not hold data. +In `Character`, for instance, `Digit` gives a meaningful name for an `i32` +value, where `Other` is only a name. However, the fact that they represent +distinct categories of `Character` is a very useful property. -As with structures, enums don't by default have access to operators such as -compare ( `==` and `!=`), binary operations (`*` and `+`), and order -(`<` and `>=`). As such, using the previous `Character` type, the -following code is invalid: +As with structures, the variants of an enum by default are not comparable with +equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not +support other binary operations such as `*` and `+`. As such, the following code +is invalid for the example `Character` type: ```{rust,ignore} // These assignments both succeed @@ -265,9 +266,10 @@ let four_equals_ten = four == ten; ``` This may seem rather limiting, but it's a limitation which we can overcome. -There are two ways: by implementing equality ourselves, or by using the -[`match`][match] keyword. We don't know enough about Rust to implement equality -yet, but we can use the `Ordering` enum from the standard library, which does: +There are two ways: by implementing equality ourselves, or by pattern matching +variants with [`match`][match] expressions, which you'll learn in the next +chapter. We don't know enough about Rust to implement equality yet, but we can +use the `Ordering` enum from the standard library, which does: ``` enum Ordering { @@ -277,9 +279,8 @@ enum Ordering { } ``` -Because we did not define `Ordering`, we must import it (from the std -library) with the `use` keyword. Here's an example of how `Ordering` is -used: +Because `Ordering` has already been defined for us, we will import it with the +`use` keyword. Here's an example of how it is used: ```{rust} use std::cmp::Ordering; @@ -313,17 +314,17 @@ the standard library if you need them. Okay, let's talk about the actual code in the example. `cmp` is a function that compares two things, and returns an `Ordering`. We return either -`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if -the two values are less, greater, or equal. Note that each variant of the -`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not -`Greater`. +`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on +whether the first value is less than, greater than, or equal to the second. Note +that each variant of the `enum` is namespaced under the `enum` itself: it's +`Ordering::Greater`, not `Greater`. The `ordering` variable has the type `Ordering`, and so contains one of the three values. We then do a bunch of `if`/`else` comparisons to check which one it is. -This `Ordering::Greater` notation is too long. Let's use `use` to import the -`enum` variants instead. This will avoid full scoping: +This `Ordering::Greater` notation is too long. Let's use another form of `use` +to import the `enum` variants instead. This will avoid full scoping: ```{rust} use std::cmp::Ordering::{self, Equal, Less, Greater}; @@ -347,16 +348,18 @@ fn main() { ``` Importing variants is convenient and compact, but can also cause name conflicts, -so do this with caution. It's considered good style to rarely import variants -for this reason. +so do this with caution. For this reason, it's normally considered better style +to `use` an enum rather than its variants directly. -As you can see, `enum`s are quite a powerful tool for data representation, and are -even more useful when they're [generic][generics] across types. Before we -get to generics, though, let's talk about how to use them with pattern matching, a -tool that will let us deconstruct this sum type (the type theory term for enums) -in a very elegant way and avoid all these messy `if`/`else`s. +As you can see, `enum`s are quite a powerful tool for data representation, and +are even more useful when they're [generic][generics] across types. Before we +get to generics, though, let's talk about how to use enums with pattern +matching, a tool that will let us deconstruct sum types (the type theory term +for enums) like `Ordering` in a very elegant way that avoids all these messy +and brittle `if`/`else`s. +[arity]: ./glossary.html#arity [match]: ./match.html [game]: ./guessing-game.html#comparing-guesses [generics]: ./generics.html diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 4a16db63950dd..5d301cc0aef6e 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -40,14 +40,14 @@ us enforce that it can't leave the current thread. ### `Sync` -The second of these two trait is called [`Sync`](../std/marker/trait.Sync.html). +The second of these traits is called [`Sync`](../std/marker/trait.Sync.html). When a type `T` implements `Sync`, it indicates to the compiler that something of this type has no possibility of introducing memory unsafety when used from multiple threads concurrently. For example, sharing immutable data with an atomic reference count is threadsafe. Rust provides a type like this, `Arc`, and it implements `Sync`, -so that it could be safely shared between threads. +so it is safe to share between threads. These two traits allow you to use the type system to make strong guarantees about the properties of your code under concurrency. Before we demonstrate @@ -69,7 +69,7 @@ fn main() { } ``` -The `Thread::scoped()` method accepts a closure, which is executed in a new +The `thread::scoped()` method accepts a closure, which is executed in a new thread. It's called `scoped` because this thread returns a join guard: ``` @@ -208,10 +208,10 @@ Here's the error: ```text :11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec>` [E0277] -:11 Thread::spawn(move || { +:11 thread::spawn(move || { ^~~~~~~~~~~~~ :11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec>` cannot be sent between threads safely -:11 Thread::spawn(move || { +:11 thread::spawn(move || { ^~~~~~~~~~~~~ ``` @@ -322,7 +322,6 @@ While this channel is just sending a generic signal, we can send any data that is `Send` over the channel! ``` -use std::sync::{Arc, Mutex}; use std::thread; use std::sync::mpsc; diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 65ff42ffdcef4..37785c030e6e5 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -430,7 +430,7 @@ fn main() { } ``` -But it is not idiomatic. This is significantly more likely to introducing a +But it is not idiomatic. This is significantly more likely to introduce a naming conflict. In our short program, it's not a big deal, but as it grows, it becomes a problem. If we have conflicting names, Rust will give a compilation error. For example, if we made the `japanese` functions public, and tried to do diff --git a/src/doc/trpl/documentation.md b/src/doc/trpl/documentation.md index 8e5b3b6a7f0af..7300753cc66d0 100644 --- a/src/doc/trpl/documentation.md +++ b/src/doc/trpl/documentation.md @@ -333,6 +333,41 @@ By repeating all parts of the example, you can ensure that your example still compiles, while only showing the parts that are relevant to that part of your explanation. +### Documenting macros + +Here’s an example of documenting a macro: + +``` +/// Panic with a given message unless an expression evaluates to true. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(1 + 1 == 2, “Math is broken.”); +/// # } +/// ``` +/// +/// ```should_fail +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(true == false, “I’m broken.”); +/// # } +/// ``` +#[macro_export] +macro_rules! panic_unless { + ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); +} +``` + +You’ll note three things: we need to add our own `extern crate` line, so that +we can add the `#[macro_use]` attribute. Second, we’ll need to add our own +`main()` as well. Finally, a judicious use of `#` to comment out those two +things, so they don’t show up in the output. + +### Running documentation tests + To run the tests, either ```bash diff --git a/src/doc/trpl/more-strings.md b/src/doc/trpl/more-strings.md index 6567cd448f998..0f19b9249f549 100644 --- a/src/doc/trpl/more-strings.md +++ b/src/doc/trpl/more-strings.md @@ -12,7 +12,7 @@ Additionally, strings are not null-terminated and can contain null bytes. Rust has two main types of strings: `&str` and `String`. -# &str +# `&str` The first kind is a `&str`. This is pronounced a 'string slice'. String literals are of the type `&str`: @@ -36,7 +36,36 @@ Like vector slices, string slices are simply a pointer plus a length. This means that they're a 'view' into an already-allocated string, such as a string literal or a `String`. -# String +## `str` + +You may occasionally see references to a `str` type, without the `&`. While +this type does exist, it’s not something you want to use yourself. Sometimes, +people confuse `str` for `String`, and write this: + +```rust +struct S { + s: str, +} +``` + +This leads to ugly errors: + +```text +error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277] +note: `str` does not have a constant size known at compile-time +``` + +Instead, this `struct` should be + +```rust +struct S { + s: String, +} +``` + +So let’s talk about `String`s. + +# `String` A `String` is a heap-allocated string. This string is growable, and is also guaranteed to be UTF-8. `String`s are commonly created by diff --git a/src/doc/trpl/standard-input.md b/src/doc/trpl/standard-input.md index 794b1df7563de..228891f9f052b 100644 --- a/src/doc/trpl/standard-input.md +++ b/src/doc/trpl/standard-input.md @@ -115,8 +115,9 @@ doesn't work, so we're okay with that. In most cases, we would want to handle the error case explicitly. `expect()` allows us to give an error message if this crash happens. -We will cover the exact details of how all of this works later in the Guide. -For now, this gives you enough of a basic understanding to work with. +We will cover the exact details of how all of this works later in the Guide in +[Error Handling]. For now, this gives you enough of a basic understanding to +work with. Back to the code we were working on! Here's a refresher: @@ -157,3 +158,6 @@ here. That's all you need to get basic input from the standard input! It's not too complicated, but there are a number of small parts. + + +[Error Handling]: ./error-handling.html diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index aaf6e76237ca5..3733350412e49 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -26,6 +26,9 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { /// /// On failure, return a null pointer and leave the original allocation intact. /// +/// If the allocation was relocated, the memory at the passed-in pointer is +/// undefined after the call. +/// /// Behavior is undefined if the requested size is 0 or the alignment is not a /// power of 2. The alignment must be no larger than the largest supported page /// size on the platform. diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index a9e1ce8d7ce50..0baf9ea046654 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -124,26 +124,26 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { } /// A view into a single entry in a map, which may either be vacant or occupied. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K:'a, V:'a> { /// A vacant Entry + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, K, V>), + /// An occupied Entry + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, K, V>), } /// A vacant Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, K:'a, V:'a> { key: K, stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>, } /// An occupied Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, K:'a, V:'a> { stack: stack::SearchStack<'a, K, V, node::handle::KV, node::handle::LeafOrInternal>, } @@ -1115,9 +1115,9 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } impl<'a, K: Ord, V> Entry<'a, K, V> { - #[unstable(feature = "collections", - reason = "matches collection reform v2 specification, waiting for dust to settle")] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant + #[unstable(feature = "std_misc", + reason = "will soon be replaced by or_insert")] pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 6e67d8763273d..056be4acaeb80 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -67,26 +67,28 @@ pub struct VecMap { } /// A view into a single entry in a map, which may either be vacant or occupied. -#[unstable(feature = "collections", - reason = "precise API still under development")] + +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, V:'a> { /// A vacant Entry + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, V>), + /// An occupied Entry + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, V>), } /// A vacant Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] + +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, V:'a> { map: &'a mut VecMap, index: usize, } /// An occupied Entry. -#[unstable(feature = "collections", - reason = "precise API still under development")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, V:'a> { map: &'a mut VecMap, index: usize, @@ -651,7 +653,7 @@ impl VecMap { impl<'a, V> Entry<'a, V> { #[unstable(feature = "collections", - reason = "matches collection reform v2 specification, waiting for dust to settle")] + reason = "will soon be replaced by or_insert")] /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, V>> { match self { diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index c5abff3b96360..4f365beed213f 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -119,6 +119,24 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool { contains_bindings } +/// Checks if the pattern contains any `ref` or `ref mut` bindings. +pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> bool { + let mut result = false; + pat_bindings(dm, pat, |mode, _, _, _| { + match mode { + ast::BindingMode::BindByRef(_) => { result = true; } + ast::BindingMode::BindByValue(_) => { } + } + }); + result +} + +/// Checks if the patterns for this arm contain any `ref` or `ref mut` +/// bindings. +pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> bool { + arm.pats.iter().any(|pat| pat_contains_ref_binding(dm, pat)) +} + /// Checks if the pattern contains any patterns that bind something to /// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`, pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 99c35c6e54258..b490de335c5a0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -52,6 +52,7 @@ use middle::mem_categorization as mc; use middle::region; use middle::resolve_lifetime; use middle::infer; +use middle::pat_util; use middle::stability; use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace}; use middle::traits; @@ -2684,6 +2685,14 @@ impl<'tcx> ctxt<'tcx> { { self.ty_param_defs.borrow()[node_id].clone() } + + pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> bool { + pat_util::pat_contains_ref_binding(&self.def_map, pat) + } + + pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> bool { + pat_util::arm_contains_ref_binding(&self.def_map, arm) + } } // Interns a type/name combination, stores the resulting box in cx.interner, diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 8e2f4dcefa022..a66c0f351bf49 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -287,10 +287,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // (nmatsakis) an hour or two debugging to remember, so I thought // I'd write them down this time. // - // 1. Most importantly, there is no loss of expressiveness - // here. What we are saying is that the type of `x` - // becomes *exactly* what is expected. This might seem - // like it will cause errors in a case like this: + // 1. There is no loss of expressiveness here, though it does + // cause some inconvenience. What we are saying is that the type + // of `x` becomes *exactly* what is expected. This can cause unnecessary + // errors in some cases, such as this one: + // it will cause errors in a case like this: // // ``` // fn foo<'x>(x: &'x int) { @@ -361,8 +362,21 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, match_src: ast::MatchSource) { let tcx = fcx.ccx.tcx; - let discrim_ty = fcx.infcx().next_ty_var(); - check_expr_has_type(fcx, discrim, discrim_ty); + // Not entirely obvious: if matches may create ref bindings, we + // want to use the *precise* type of the discriminant, *not* some + // supertype, as the "discriminant type" (issue #23116). + let contains_ref_bindings = arms.iter().any(|a| tcx.arm_contains_ref_binding(a)); + let discrim_ty; + if contains_ref_bindings { + check_expr(fcx, discrim); + discrim_ty = fcx.expr_ty(discrim); + } else { + // ...but otherwise we want to use any supertype of the + // discriminant. This is sort of a workaround, see note (*) in + // `check_pat` for some details. + discrim_ty = fcx.infcx().next_ty_var(); + check_expr_has_type(fcx, discrim, discrim_ty); + }; // Typecheck the patterns first, so that we get types for all the // bindings. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 45d4a1edc6b24..09309c7bbeb88 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4242,11 +4242,27 @@ impl<'tcx> Repr<'tcx> for Expectation<'tcx> { } pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, - nid: ast::NodeId, + local: &'tcx ast::Local, init: &'tcx ast::Expr) { - let local_ty = fcx.local_ty(init.span, nid); - check_expr_coercable_to_type(fcx, init, local_ty) + let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat); + + let local_ty = fcx.local_ty(init.span, local.id); + if !ref_bindings { + check_expr_coercable_to_type(fcx, init, local_ty) + } else { + // Somewhat subtle: if we have a `ref` binding in the pattern, + // we want to avoid introducing coercions for the RHS. This is + // both because it helps preserve sanity and, in the case of + // ref mut, for soundness (issue #23116). In particular, in + // the latter case, we need to be clear that the type of the + // referent for the reference that results is *equal to* the + // type of the lvalue it is referencing, and not some + // supertype thereof. + check_expr(fcx, init); + let init_ty = fcx.expr_ty(init); + demand::eqtype(fcx, init.span, init_ty, local_ty); + }; } pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) { @@ -4256,7 +4272,7 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local) fcx.write_ty(local.id, t); if let Some(ref init) = local.init { - check_decl_initializer(fcx, local.id, &**init); + check_decl_initializer(fcx, local, &**init); let init_ty = fcx.expr_ty(&**init); if ty::type_is_error(init_ty) { fcx.write_ty(local.id, init_ty); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 9139e182ce479..330891273e755 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1323,15 +1323,13 @@ pub struct Drain<'a, K: 'a, V: 'a> { } /// A view into a single occupied location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry<'a, K: 'a, V: 'a> { elem: FullBucket>, } /// A view into a single empty location in a HashMap. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry<'a, K: 'a, V: 'a> { hash: SafeHash, key: K, @@ -1339,12 +1337,14 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> { } /// A view into a single location in a map, which may be vacant or occupied. -#[unstable(feature = "std_misc", - reason = "precise API still being fleshed out")] +#[stable(feature = "rust1", since = "1.0.0")] pub enum Entry<'a, K: 'a, V: 'a> { /// An occupied Entry. + #[stable(feature = "rust1", since = "1.0.0")] Occupied(OccupiedEntry<'a, K, V>), + /// A vacant Entry. + #[stable(feature = "rust1", since = "1.0.0")] Vacant(VacantEntry<'a, K, V>), } @@ -1465,10 +1465,10 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() } } -#[unstable(feature = "std_misc", - reason = "matches collection reform v2 specification, waiting for dust to settle")] impl<'a, K, V> Entry<'a, K, V> { /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant. + #[unstable(feature = "std_misc", + reason = "will soon be replaced by or_insert")] pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> { match self { Occupied(entry) => Ok(entry.into_mut()), diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 87e5a2a448855..79f0af670b446 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -17,20 +17,18 @@ use iter::repeat; use num::Int; use slice; -/// A `Cursor` is a type which wraps another I/O object to provide a `Seek` +/// A `Cursor` is a type which wraps a non-I/O object to provide a `Seek` /// implementation. /// -/// Cursors are currently typically used with memory buffer objects in order to -/// allow `Seek` plus `Read` and `Write` implementations. For example, common -/// cursor types include: +/// Cursors are typically used with memory buffer objects in order to allow +/// `Seek`, `Read`, and `Write` implementations. For example, common cursor types +/// include `Cursor>` and `Cursor<&[u8]>`. /// -/// * `Cursor>` -/// * `Cursor<&[u8]>` -/// -/// Implementations of the I/O traits for `Cursor` are not currently generic +/// Implementations of the I/O traits for `Cursor` are currently not generic /// over `T` itself. Instead, specific implementations are provided for various /// in-memory buffer types like `Vec` and `&[u8]`. #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone, Debug)] pub struct Cursor { inner: T, pos: u64, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 237435d6dfbfa..39c718c96b38a 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -558,6 +558,12 @@ pub trait BufRead: Read { /// This function does not perform any I/O, it simply informs this object /// that some amount of its buffer, returned from `fill_buf`, has been /// consumed and should no longer be returned. + /// + /// This function is used to tell the buffer how many bytes you've consumed + /// from the return value of `fill_buf`, and so may do odd things if + /// `fill_buf` isn't called before calling this. + /// + /// The `amt` must be `<=` the number of bytes in the buffer returned by `fill_buf`. #[stable(feature = "rust1", since = "1.0.0")] fn consume(&mut self, amt: usize); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index b055796ba547f..6833b6a0a21b8 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -40,11 +40,11 @@ //! //! ## Vectors, slices and strings //! -//! The common container type, `Vec`, a growable vector backed by an -//! array, lives in the [`vec`](vec/index.html) module. References to -//! arrays, `&[T]`, more commonly called "slices", are built-in types -//! for which the [`slice`](slice/index.html) module defines many -//! methods. +//! The common container type, `Vec`, a growable vector backed by an array, +//! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions +//! of memory, `[T]`, commonly called "slices", and their borrowed versions, +//! `&[T]`, commonly called "borrowed slices", are built-in types for which the +//! for which the [`slice`](slice/index.html) module defines many methods. //! //! `&str`, a UTF-8 string, is a built-in type, and the standard library //! defines methods for it on a variety of traits in the diff --git a/src/test/compile-fail/match-ref-mut-invariance.rs b/src/test/compile-fail/match-ref-mut-invariance.rs new file mode 100644 index 0000000000000..c2b54a972bdc0 --- /dev/null +++ b/src/test/compile-fail/match-ref-mut-invariance.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `match`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + match self.0 { ref mut x => x } //~ ERROR mismatched types + } +} + +fn main() {} diff --git a/src/test/compile-fail/match-ref-mut-let-invariance.rs b/src/test/compile-fail/match-ref-mut-let-invariance.rs new file mode 100644 index 0000000000000..ea16c61dfd4d1 --- /dev/null +++ b/src/test/compile-fail/match-ref-mut-let-invariance.rs @@ -0,0 +1,25 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that when making a ref mut binding with type `&mut T`, the +// type `T` must match precisely the type `U` of the value being +// matched, and in particular cannot be some supertype of `U`. Issue +// #23116. This test focuses on a `let`. + +#![allow(dead_code)] +struct S<'b>(&'b i32); +impl<'b> S<'b> { + fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { + let ref mut x = self.0; + x //~ ERROR mismatched types + } +} + +fn main() {}