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 10 pull requests #32860

Closed
wants to merge 18 commits into from
Closed
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
21 changes: 8 additions & 13 deletions src/doc/book/concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ The same [ownership system](ownership.html) that helps prevent using pointers
incorrectly also helps rule out data races, one of the worst kinds of
concurrency bugs.

As an example, here is a Rust program that could have a data race in many
As an example, here is a Rust program that would have a data race in many
languages. It will not compile:

```ignore
Expand All @@ -174,7 +174,7 @@ fn main() {

for i in 0..3 {
thread::spawn(move || {
data[i] += 1;
data[0] += i;
});
}

Expand All @@ -186,7 +186,7 @@ This gives us an error:

```text
8:17 error: capture of moved value: `data`
data[i] += 1;
data[0] += i;
^~~~
```

Expand All @@ -195,11 +195,6 @@ thread, and the thread takes ownership of the reference, we'd have three owners!
`data` gets moved out of `main` in the first call to `spawn()`, so subsequent
calls in the loop cannot use this variable.

Note that this specific example will not cause a data race since different array
indices are being accessed. But this can't be determined at compile time, and in
a similar situation where `i` is a constant or is random, you would have a data
race.

So, we need some type that lets us have more than one owning reference to a
value. Usually, we'd use `Rc<T>` for this, which is a reference counted type
that provides shared ownership. It has some runtime bookkeeping that keeps track
Expand All @@ -223,7 +218,7 @@ fn main() {

// use it in a thread
thread::spawn(move || {
data_ref[i] += 1;
data_ref[0] += i;
});
}

Expand Down Expand Up @@ -266,7 +261,7 @@ fn main() {
for i in 0..3 {
let data = data.clone();
thread::spawn(move || {
data[i] += 1;
data[0] += i;
});
}

Expand All @@ -281,7 +276,7 @@ And... still gives us an error.

```text
<anon>:11:24 error: cannot borrow immutable borrowed content as mutable
<anon>:11 data[i] += 1;
<anon>:11 data[0] += i;
^~~~
```

Expand Down Expand Up @@ -317,7 +312,7 @@ fn main() {
let data = data.clone();
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
data[0] += i;
});
}

Expand Down Expand Up @@ -360,7 +355,7 @@ Let's examine the body of the thread more closely:
# let data = data.clone();
thread::spawn(move || {
let mut data = data.lock().unwrap();
data[i] += 1;
data[0] += i;
});
# }
# thread::sleep(Duration::from_millis(50));
Expand Down
81 changes: 81 additions & 0 deletions src/libcore/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,20 @@ macro_rules! make_mut_slice {
}

/// Immutable slice iterator
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // First, we declare a type which has `iter` method to get the `Iter` struct (&[usize here]):
/// let slice = &[1, 2, 3];
///
/// // Then, we iterate over it:
/// for element in slice.iter() {
/// println!("{}", element);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
ptr: *const T,
Expand All @@ -897,6 +911,26 @@ impl<'a, T> Iter<'a, T> {
///
/// This has the same lifetime as the original slice, and so the
/// iterator can continue to be used while this exists.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // First, we declare a type which has the `iter` method to get the `Iter`
/// // struct (&[usize here]):
/// let slice = &[1, 2, 3];
///
/// // Then, we get the iterator:
/// let mut iter = slice.iter();
/// // So if we print what `as_slice` method returns here, we have "[1, 2, 3]":
/// println!("{:?}", iter.as_slice());
///
/// // Next, we move to the second element of the slice:
/// iter.next();
/// // Now `as_slice` returns "[2, 3]":
/// println!("{:?}", iter.as_slice());
/// ```
#[stable(feature = "iter_to_slice", since = "1.4.0")]
pub fn as_slice(&self) -> &'a [T] {
make_slice!(self.ptr, self.end)
Expand Down Expand Up @@ -928,6 +962,24 @@ impl<'a, T> Clone for Iter<'a, T> {
}

/// Mutable slice iterator.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // First, we declare a type which has `iter_mut` method to get the `IterMut`
/// // struct (&[usize here]):
/// let mut slice = &mut [1, 2, 3];
///
/// // Then, we iterate over it and increment each element value:
/// for element in slice.iter_mut() {
/// *element += 1;
/// }
///
/// // We now have "[2, 3, 4]":
/// println!("{:?}", slice);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
ptr: *mut T,
Expand Down Expand Up @@ -956,6 +1008,35 @@ impl<'a, T> IterMut<'a, T> {
/// to consume the iterator. Consider using the `Slice` and
/// `SliceMut` implementations for obtaining slices with more
/// restricted lifetimes that do not consume the iterator.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// // First, we declare a type which has `iter_mut` method to get the `IterMut`
/// // struct (&[usize here]):
/// let mut slice = &mut [1, 2, 3];
///
/// {
/// // Then, we get the iterator:
/// let mut iter = slice.iter_mut();
/// // We move to next element:
/// iter.next();
/// // So if we print what `into_slice` method returns here, we have "[2, 3]":
/// println!("{:?}", iter.into_slice());
/// }
///
/// // Now let's modify a value of the slice:
/// {
/// // First we get back the iterator:
/// let mut iter = slice.iter_mut();
/// // We change the value of the first element of the slice returned by the `next` method:
/// *iter.next().unwrap() += 1;
/// }
/// // Now slice is "[2, 2, 3]":
/// println!("{:?}", slice);
/// ```
#[stable(feature = "iter_to_slice", since = "1.4.0")]
pub fn into_slice(self) -> &'a mut [T] {
make_mut_slice!(self.ptr, self.end)
Expand Down
10 changes: 7 additions & 3 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
(&Failed(_), &Failed(_)) => {
let resolutions = target_module.resolutions.borrow();
let names = resolutions.iter().filter_map(|(&(ref name, _), resolution)| {
if *name == source { return None; } // Never suggest the same name
match *resolution.borrow() {
NameResolution { binding: Some(_), .. } => Some(name),
NameResolution { single_imports: SingleImports::None, .. } => None,
Expand All @@ -549,9 +550,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
Some(name) => format!(". Did you mean to use `{}`?", name),
None => "".to_owned(),
};
let msg = format!("There is no `{}` in `{}`{}",
source,
module_to_string(target_module), lev_suggestion);
let module_str = module_to_string(target_module);
let msg = if &module_str == "???" {
format!("There is no `{}` in the crate root{}", source, lev_suggestion)
} else {
format!("There is no `{}` in `{}`{}", source, module_str, lev_suggestion)
};
return Failed(Some((directive.span, msg)));
}
_ => (),
Expand Down
21 changes: 15 additions & 6 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2578,24 +2578,33 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
ty::TyFloat(ast::FloatTy::F32) => {
fcx.type_error_message(arg.span,
|t| {
format!("can't pass an {} to variadic \
function, cast to c_double", t)
format!("can't pass an `{}` to variadic \
function, cast to `c_double`", t)
}, arg_ty, None);
}
ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
fcx.type_error_message(arg.span, |t| {
format!("can't pass {} to variadic \
function, cast to c_int",
format!("can't pass `{}` to variadic \
function, cast to `c_int`",
t)
}, arg_ty, None);
}
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
fcx.type_error_message(arg.span, |t| {
format!("can't pass {} to variadic \
function, cast to c_uint",
format!("can't pass `{}` to variadic \
function, cast to `c_uint`",
t)
}, arg_ty, None);
}
ty::TyFnDef(_, _, f) => {
let ptr_ty = fcx.tcx().mk_ty(ty::TyFnPtr(f));
let ptr_ty = fcx.infcx().resolve_type_vars_if_possible(&ptr_ty);
fcx.type_error_message(arg.span,
|t| {
format!("can't pass `{}` to variadic \
function, cast to `{}`", t, ptr_ty)
}, arg_ty, None);
}
_ => {}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,11 @@ impl<T: Read> Read for Take<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: BufRead> BufRead for Take<T> {
fn fill_buf(&mut self) -> Result<&[u8]> {
// Don't call into inner reader at all at EOF because it may still block
if self.limit == 0 {
return Ok(&[]);
}

let buf = self.inner.fill_buf()?;
let cap = cmp::min(buf.len() as u64, self.limit) as usize;
Ok(&buf[..cap])
Expand Down Expand Up @@ -1860,9 +1865,16 @@ mod tests {
Err(io::Error::new(io::ErrorKind::Other, ""))
}
}
impl BufRead for R {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Err(io::Error::new(io::ErrorKind::Other, ""))
}
fn consume(&mut self, _amt: usize) { }
}

let mut buf = [0; 1];
assert_eq!(0, R.take(0).read(&mut buf).unwrap());
assert_eq!(b"", R.take(0).fill_buf().unwrap());
}

fn cmp_bufread<Br1: BufRead, Br2: BufRead>(mut br1: Br1, mut br2: Br2, exp: &[u8]) {
Expand Down
9 changes: 9 additions & 0 deletions src/test/compile-fail/extern-crate-visibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,14 @@ fn f() {
mod core {} // Check that private crates are not glob imported
}

mod bar {
pub extern crate core;
}

mod baz {
pub use bar::*;
use self::core::cell; // Check that public extern crates are glob imported
}

#[rustc_error]
fn main() {} //~ ERROR compilation successful
28 changes: 28 additions & 0 deletions src/test/compile-fail/issue-24883.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

mod a {
pub mod b { pub struct Foo; }

pub mod c {
use super::b;
pub struct Bar(pub b::Foo);
}

pub use self::c::*;
}

#[rustc_error]
fn main() { //~ ERROR compilation successful
let _ = a::c::Bar(a::b::Foo);
let _ = a::Bar(a::b::Foo);
}
20 changes: 20 additions & 0 deletions src/test/compile-fail/issue-26930.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]
#![allow(unused)]

extern crate core;
use core as core_export;
use self::x::*;
mod x {}

#[rustc_error]
fn main() {} //~ ERROR compilation successful
22 changes: 22 additions & 0 deletions src/test/compile-fail/issue-32201.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern {
fn foo(a: i32, ...);
}

fn bar(_: *const u8) {}

fn main() {
unsafe {
foo(0, bar);
//~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function, cast to `fn(*const u8)`
}
}
16 changes: 16 additions & 0 deletions src/test/compile-fail/issue-32833.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2016 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use bar::Foo; //~ ERROR There is no `Foo` in `bar` [E0432]
mod bar {
use Foo; //~ ERROR There is no `Foo` in the crate root [E0432]
}

fn main() {}
Loading