diff --git a/src/doc/nomicon/vec-alloc.md b/src/doc/nomicon/vec-alloc.md index c2ae1a4eb6d26..bc60a577bd35c 100644 --- a/src/doc/nomicon/vec-alloc.md +++ b/src/doc/nomicon/vec-alloc.md @@ -150,7 +150,7 @@ LLVM needs to work with different languages' semantics and custom allocators, it can't really intimately understand allocation. Instead, the main idea behind allocation is "doesn't overlap with other stuff". That is, heap allocations, stack allocations, and globals don't randomly overlap. Yep, it's about alias -analysis. As such, Rust can technically play a bit fast an loose with the notion of +analysis. As such, Rust can technically play a bit fast and loose with the notion of an allocation as long as it's *consistent*. Getting back to the empty allocation case, there are a couple of places where diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index c407cef25e74c..8b3168b29aa4f 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -147,6 +147,7 @@ impl RawVec { /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. + #[inline(always)] pub fn cap(&self) -> usize { if mem::size_of::() == 0 { !0 diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index d58c26a72136b..ce1d6ec5a6478 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -521,12 +521,24 @@ use string; /// /// # Examples /// +/// Basic usage: +/// /// ``` /// use std::fmt; /// /// let s = fmt::format(format_args!("Hello, {}!", "world")); /// assert_eq!(s, "Hello, world!".to_string()); /// ``` +/// +/// Please note that using [`format!`][format!] might be preferrable. +/// Example: +/// +/// ``` +/// let s = format!("Hello, {}!", "world"); +/// assert_eq!(s, "Hello, world!".to_string()); +/// ``` +/// +/// [format!]: ../macro.format!.html #[stable(feature = "rust1", since = "1.0.0")] pub fn format(args: Arguments) -> string::String { let mut output = string::String::new(); diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0c824b5a8e69a..dde4d03dad8ac 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -776,6 +776,32 @@ pub trait UpperExp { /// /// * output - the buffer to write output to /// * args - the precompiled arguments generated by `format_args!` +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::fmt; +/// +/// let mut output = String::new(); +/// fmt::write(&mut output, format_args!("Hello {}!", "world")) +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// Please note that using [`write!`][write_macro] might be preferrable. Example: +/// +/// ``` +/// use std::fmt::Write; +/// +/// let mut output = String::new(); +/// write!(&mut output, "Hello {}!", "world") +/// .expect("Error occurred while trying to write in String"); +/// assert_eq!(output, "Hello world!"); +/// ``` +/// +/// [write_macro]: ../../std/macro.write!.html #[stable(feature = "rust1", since = "1.0.0")] pub fn write(output: &mut Write, args: Arguments) -> Result { let mut formatter = Formatter { diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index b889d0a9daab6..9d2d52015e394 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -1240,9 +1240,6 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> { orig_node_idx, node_idx); - // figure out the direction from which this node takes its - // values, and search for concrete regions etc in that direction - let dir = graph::INCOMING; process_edges(self, &mut state, graph, node_idx, dir); } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 23eb5a56c8439..5c06231631010 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -193,7 +193,12 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { }) } FnKind::Closure(_) => { - self.add_scope_and_walk_fn(fk, fd, b, s, fn_id) + // Closures have their own set of labels, save labels just + // like for foreign items above. + let saved = replace(&mut self.labels_in_fn, vec![]); + let result = self.add_scope_and_walk_fn(fk, fd, b, s, fn_id); + replace(&mut self.labels_in_fn, saved); + result } } } diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index 8d9b88e899be2..0687faa112f5e 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -454,6 +454,110 @@ fn foo(a: &mut i32) { ``` "##, +E0504: r##" +This error occurs when an attempt is made to move a borrowed variable into a +closure. + +Example of erroneous code: + +```compile_fail +struct FancyNum { + num: u8 +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + println!("child function: {}", fancy_num.num); + // error: cannot move `fancy_num` into closure because it is borrowed + }; + + x(); + println!("main function: {}", fancy_ref.num); +} +``` + +Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into +the closure `x`. There is no way to move a value into a closure while it is +borrowed, as that would invalidate the borrow. + +If the closure can't outlive the value being moved, try using a reference +rather than moving: + +``` +struct FancyNum { + num: u8 +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + // fancy_ref is usable here because it doesn't move `fancy_num` + println!("child function: {}", fancy_ref.num); + }; + + x(); + + println!("main function: {}", fancy_num.num); +} +``` + +If the value has to be borrowed and then moved, try limiting the lifetime of +the borrow using a scoped block: + +``` +struct FancyNum { + num: u8 +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + + { + let fancy_ref = &fancy_num; + println!("main function: {}", fancy_ref.num); + // `fancy_ref` goes out of scope here + } + + let x = move || { + // `fancy_num` can be moved now (no more references exist) + println!("child function: {}", fancy_num.num); + }; + + x(); +} +``` + +If the lifetime of a reference isn't enough, such as in the case of threading, +consider using an `Arc` to create a reference-counted value: + +``` +use std::sync::Arc; +use std::thread; + +struct FancyNum { + num: u8 +} + +fn main() { + let fancy_ref1 = Arc::new(FancyNum { num: 5 }); + let fancy_ref2 = fancy_ref1.clone(); + + let x = thread::spawn(move || { + // `fancy_ref1` can be moved and has a `'static` lifetime + println!("child thread: {}", fancy_ref1.num); + }); + + x.join().expect("child thread should finish"); + println!("main thread: {}", fancy_ref2.num); +} +``` +"##, + E0506: r##" This error occurs when an attempt is made to assign to a borrowed value. @@ -756,7 +860,6 @@ register_diagnostics! { E0500, // closure requires unique access to `..` but .. is already borrowed E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... E0503, // cannot use `..` because it was mutably borrowed - E0504, // cannot move `..` into closure because it is borrowed E0505, // cannot move out of `..` because it is borrowed E0508, // cannot move out of type `..`, a non-copy fixed-size array E0524, // two closures require unique access to `..` at the same time diff --git a/src/librustc_const_eval/diagnostics.rs b/src/librustc_const_eval/diagnostics.rs index 4f5176f6b0be5..c86c22b1e0f3b 100644 --- a/src/librustc_const_eval/diagnostics.rs +++ b/src/librustc_const_eval/diagnostics.rs @@ -215,22 +215,63 @@ match Some("hi".to_string()) { The variable `s` has type `String`, and its use in the guard is as a variable of type `String`. The guard code effectively executes in a separate scope to the body of the arm, so the value would be moved into this anonymous scope and -therefore become unavailable in the body of the arm. Although this example seems -innocuous, the problem is most clear when considering functions that take their -argument by value. +therefore becomes unavailable in the body of the arm. -```compile_fail +The problem above can be solved by using the `ref` keyword. + +``` match Some("hi".to_string()) { - Some(s) if { drop(s); false } => (), - Some(s) => {}, // use s. + Some(ref s) if s.len() == 0 => {}, _ => {}, } ``` -The value would be dropped in the guard then become unavailable not only in the -body of that arm but also in all subsequent arms! The solution is to bind by -reference when using guards or refactor the entire expression, perhaps by -putting the condition inside the body of the arm. +Though this example seems innocuous and easy to solve, the problem becomes clear +when it encounters functions which consume the value: + +```compile_fail +struct A{} + +impl A { + fn consume(self) -> usize { + 0 + } +} + +fn main() { + let a = Some(A{}); + match a { + Some(y) if y.consume() > 0 => {} + _ => {} + } +} +``` + +In this situation, even the `ref` keyword cannot solve it, since borrowed +content cannot be moved. This problem cannot be solved generally. If the value +can be cloned, here is a not-so-specific solution: + +``` +#[derive(Clone)] +struct A{} + +impl A { + fn consume(self) -> usize { + 0 + } +} + +fn main() { + let a = Some(A{}); + match a{ + Some(ref y) if y.clone().consume() > 0 => {} + _ => {} + } +} +``` + +If the value will be consumed in the pattern guard, using its clone will not +move its ownership, so the code works. "##, E0009: r##" diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index ad91bc9399fef..05e4c79a7e8d5 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -742,7 +742,7 @@ fn f(a: u16, b: &str) {} Must always be called with exactly two arguments, e.g. `f(2, "test")`. -Note, that Rust does not have a notion of optional function arguments or +Note that Rust does not have a notion of optional function arguments or variadic functions (except for its C-FFI). "##, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 6a2a0a37c1c05..da0520ebcb84a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1537,7 +1537,6 @@ impl<'a> Item<'a> { } } - impl<'a> fmt::Display for Item<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { debug_assert!(!self.item.is_stripped()); @@ -1575,6 +1574,9 @@ impl<'a> fmt::Display for Item<'a> { write!(fmt, "")?; // in-band write!(fmt, "")?; + if let Some(version) = self.item.stable_since() { + write!(fmt, "{}", version)?; + } write!(fmt, r##" @@ -1922,7 +1924,6 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, generics = f.generics, where_clause = WhereClause(&f.generics), decl = f.decl)?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } @@ -2236,7 +2237,6 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, "", true)?; write!(w, "")?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it)?; let mut fields = s.fields.iter().filter(|f| { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4d65b91ed421c..d256e939afcfc 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -634,6 +634,12 @@ a.test-arrow { padding-left: 10px; } +span.since { + position: initial; + font-size: 20px; + margin-right: 5px; +} + /* Media Queries */ @media (max-width: 700px) { diff --git a/src/test/compile-fail/region-invariant-static-error-reporting.rs b/src/test/compile-fail/region-invariant-static-error-reporting.rs new file mode 100644 index 0000000000000..ac0167e08bdd6 --- /dev/null +++ b/src/test/compile-fail/region-invariant-static-error-reporting.rs @@ -0,0 +1,36 @@ +// Copyright 2012 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. + +// This test checks that the error messages you get for this example +// at least mention `'a` and `'static`. The precise messages can drift +// over time, but this test used to exhibit some pretty bogus messages +// that were not remotely helpful. + +// error-pattern:cannot infer +// error-pattern:cannot outlive the lifetime 'a +// error-pattern:must be valid for the static lifetime +// error-pattern:cannot infer +// error-pattern:cannot outlive the lifetime 'a +// error-pattern:must be valid for the static lifetime + +struct Invariant<'a>(Option<&'a mut &'a mut ()>); + +fn mk_static() -> Invariant<'static> { Invariant(None) } + +fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { + let bad = if x.is_some() { + x.unwrap() + } else { + mk_static() + }; + f(bad); +} + +fn main() {} diff --git a/src/test/run-pass/issue-25343.rs b/src/test/run-pass/issue-25343.rs index 9e01d577276b8..64e7350fb8244 100644 --- a/src/test/run-pass/issue-25343.rs +++ b/src/test/run-pass/issue-25343.rs @@ -8,9 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(unused)] fn main() { || { 'label: loop { } }; + + // More cases added from issue 31754 + + 'label2: loop { + break; + } + + let closure = || { + 'label2: loop {} + }; + + fn inner_fn() { + 'label2: loop {} + } }