Skip to content

Rollup of 7 pull requests #37419

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

Merged
merged 12 commits into from
Oct 27, 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
2 changes: 1 addition & 1 deletion src/doc/book/references-and-borrowing.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ fn main() {

In other words, the mutable borrow is held through the rest of our example. What
we want is for the mutable borrow by `y` to end so that the resource can be
returned to the owner, `x`. `x` can then provide a immutable borrow to `println!`.
returned to the owner, `x`. `x` can then provide an immutable borrow to `println!`.
In Rust, borrowing is tied to the scope that the borrow is valid for. And our
scopes look like this:

Expand Down
44 changes: 22 additions & 22 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ use super::range::RangeArgument;
/// # Slicing
///
/// A `Vec` can be mutable. Slices, on the other hand, are read-only objects.
/// To get a slice, use "&". Example:
/// To get a slice, use `&`. Example:
///
/// ```
/// fn read_slice(slice: &[usize]) {
Expand Down Expand Up @@ -203,33 +203,33 @@ use super::range::RangeArgument;
///
/// # Guarantees
///
/// Due to its incredibly fundamental nature, Vec makes a lot of guarantees
/// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees
/// about its design. This ensures that it's as low-overhead as possible in
/// the general case, and can be correctly manipulated in primitive ways
/// by unsafe code. Note that these guarantees refer to an unqualified `Vec<T>`.
/// If additional type parameters are added (e.g. to support custom allocators),
/// overriding their defaults may change the behavior.
///
/// Most fundamentally, Vec is and always will be a (pointer, capacity, length)
/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length)
/// triplet. No more, no less. The order of these fields is completely
/// unspecified, and you should use the appropriate methods to modify these.
/// The pointer will never be null, so this type is null-pointer-optimized.
///
/// However, the pointer may not actually point to allocated memory. In particular,
/// if you construct a Vec with capacity 0 via [`Vec::new()`], [`vec![]`][`vec!`],
/// if you construct a `Vec` with capacity 0 via [`Vec::new()`], [`vec![]`][`vec!`],
/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit()`]
/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized
/// types inside a `Vec`, it will not allocate space for them. *Note that in this case
/// the `Vec` may not report a [`capacity()`] of 0*. Vec will allocate if and only
/// the `Vec` may not report a [`capacity()`] of 0*. `Vec` will allocate if and only
/// if [`mem::size_of::<T>()`]` * capacity() > 0`. In general, `Vec`'s allocation
/// details are subtle enough that it is strongly recommended that you only
/// free memory allocated by a Vec by creating a new Vec and dropping it.
/// free memory allocated by a `Vec` by creating a new `Vec` and dropping it.
///
/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap
/// (as defined by the allocator Rust is configured to use by default), and its
/// pointer points to [`len()`] initialized elements in order (what you would see
/// if you coerced it to a slice), followed by `[capacity()][`capacity()`] -
/// [len()][`len()`]` logically uninitialized elements.
/// if you coerced it to a slice), followed by [`capacity()`]` - `[`len()`]
/// logically uninitialized elements.
///
/// `Vec` will never perform a "small optimization" where elements are actually
/// stored on the stack for two reasons:
Expand All @@ -249,8 +249,8 @@ use super::range::RangeArgument;
/// [`shrink_to_fit`][`shrink_to_fit()`].
///
/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is
/// sufficient. [`push`] and [`insert`] *will* (re)allocate if `[len()][`len()`]
/// == [capacity()][`capacity()`]`. That is, the reported capacity is completely
/// sufficient. [`push`] and [`insert`] *will* (re)allocate if
/// [`len()`]` == `[`capacity()`]. That is, the reported capacity is completely
/// accurate, and can be relied on. It can even be used to manually free the memory
/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even
/// when not necessary.
Expand All @@ -261,11 +261,10 @@ use super::range::RangeArgument;
/// strategy is used will of course guarantee `O(1)` amortized [`push`].
///
/// `vec![x; n]`, `vec![a, b, c, d]`, and
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all
/// produce a `Vec` with exactly the requested capacity. If `[len()][`len()`] ==
/// [capacity()][`capacity()`]`, (as is the case for the [`vec!`] macro), then a
/// `Vec<T>` can be converted to and from a [`Box<[T]>`] without reallocating or
/// moving the elements.
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
/// with exactly the requested capacity. If [`len()`]` == `[`capacity()`],
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
///
/// `Vec` will not specifically overwrite any data that is removed from it,
/// but also won't specifically preserve it. Its uninitialized memory is
Expand All @@ -292,7 +291,7 @@ use super::range::RangeArgument;
/// [`push`]: ../../std/vec/struct.Vec.html#method.push
/// [`insert`]: ../../std/vec/struct.Vec.html#method.insert
/// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve
/// [`Box<[T]>`]: ../../std/boxed/struct.Box.html
/// [owned slice]: ../../std/boxed/struct.Box.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Vec<T> {
buf: RawVec<T>,
Expand Down Expand Up @@ -329,9 +328,10 @@ impl<T> Vec<T> {
/// reallocating. If `capacity` is 0, the vector will not allocate.
///
/// It is important to note that this function does not specify the *length*
/// of the returned vector, but only the *capacity*. (For an explanation of
/// the difference between length and capacity, see the main `Vec<T>` docs
/// above, 'Capacity and reallocation'.)
/// of the returned vector, but only the *capacity*. For an explanation of
/// the difference between length and capacity, see *[Capacity and reallocation]*.
///
/// [Capacity and reallocation]: #capacity-and-reallocation
///
/// # Examples
///
Expand Down Expand Up @@ -497,13 +497,13 @@ impl<T> Vec<T> {
self.buf.shrink_to_fit(self.len);
}

/// Converts the vector into [`Box<[T]>`].
/// Converts the vector into [`Box<[T]>`][owned slice].
///
/// Note that this will drop any excess capacity. Calling this and
/// converting back to a vector with [`into_vec()`] is equivalent to calling
/// [`shrink_to_fit()`].
///
/// [`Box<[T]>`]: ../../std/boxed/struct.Box.html
/// [owned slice]: ../../std/boxed/struct.Box.html
/// [`into_vec()`]: ../../std/primitive.slice.html#method.into_vec
/// [`shrink_to_fit()`]: #method.shrink_to_fit
///
Expand Down Expand Up @@ -779,7 +779,7 @@ impl<T> Vec<T> {

/// Retains only the elements specified by the predicate.
///
/// In other words, remove all elements `e` such that `f(&e)` returns false.
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
/// This method operates in place and preserves the order of the retained
/// elements.
///
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_resolve/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
// Check later.
return;
}
self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
id,
span,
"unused import".to_string());
let msg = if let Ok(snippet) = self.session.codemap().span_to_snippet(span) {
format!("unused import: `{}`", snippet)
} else {
"unused import".to_string()
};
self.session.add_lint(lint::builtin::UNUSED_IMPORTS, id, span, msg);
} else {
// This trait import is definitely used, in a way other than
// method resolution.
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,9 +854,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
let path_data = match path_data {
Some(pd) => pd,
None => {
span_bug!(path.span,
"Unexpected def kind while looking up path in `{}`",
self.span.snippet(path.span))
return;
}
};

Expand Down
28 changes: 23 additions & 5 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1261,18 +1261,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}

if bounds.len() > 1 {
let spans = bounds.iter().map(|b| {
self.tcx().impl_or_trait_items(b.def_id()).iter()
.find(|&&def_id| {
match self.tcx().impl_or_trait_item(def_id) {
ty::TypeTraitItem(ref item) => item.name.as_str() == assoc_name,
_ => false
}
})
.and_then(|&def_id| self.tcx().map.as_local_node_id(def_id))
.and_then(|node_id| self.tcx().map.opt_span(node_id))
});

let mut err = struct_span_err!(
self.tcx().sess, span, E0221,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
ty_param_name);
err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));

for bound in &bounds {
span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
bound);
for span_and_bound in spans.zip(&bounds) {
if let Some(span) = span_and_bound.0 {
err.span_label(span, &format!("ambiguous `{}` from `{}`",
assoc_name,
span_and_bound.1));
} else {
span_note!(&mut err, span,
"associated type `{}` could derive from `{}`",
ty_param_name,
span_and_bound.1);
}
}
err.emit();
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc_typeck/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
if self.tcx.used_trait_imports.borrow().contains(&id) {
return;
}
self.tcx.sess.add_lint(lint::builtin::UNUSED_IMPORTS,
id,
span,
"unused import".to_string());

let msg = if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
format!("unused import: `{}`", snippet)
} else {
"unused import".to_string()
};
self.tcx.sess.add_lint(lint::builtin::UNUSED_IMPORTS, id, span, msg);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1317,7 +1317,7 @@ pub enum UnstableFeatures {
/// Hard errors for unstable features are active, as on
/// beta/stable channels.
Disallow,
/// Allow features to me activated, as on nightly.
/// Allow features to be activated, as on nightly.
Allow,
/// Errors are bypassed for bootstrapping. This is required any time
/// during the build that feature-related lints are set to warn or above
Expand Down
18 changes: 14 additions & 4 deletions src/test/compile-fail/E0221.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,27 @@ trait T1 {}
trait T2 {}

trait Foo {
type A: T1;
type A: T1; //~ NOTE: ambiguous `A` from `Foo`
}

trait Bar : Foo {
type A: T2;
type A: T2; //~ NOTE: ambiguous `A` from `Bar`
fn do_something() {
let _: Self::A;
//~^ ERROR E0221
//~| NOTE ambiguous associated type `A`
//~| NOTE associated type `Self` could derive from `Foo`
//~| NOTE associated type `Self` could derive from `Bar`
}
}

trait T3 {}

trait My : std::str::FromStr {
type Err: T3; //~ NOTE: ambiguous `Err` from `My`
fn test() {
let _: Self::Err;
//~^ ERROR E0221
//~| NOTE ambiguous associated type `Err`
//~| NOTE associated type `Self` could derive from `std::str::FromStr`
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@

pub trait Vehicle {
type Color;
//~^ NOTE ambiguous `Color` from `Vehicle`
//~| NOTE ambiguous `Color` from `Vehicle`
//~| NOTE ambiguous `Color` from `Vehicle`

fn go(&self) { }
}

pub trait Box {
type Color;

//~^ NOTE ambiguous `Color` from `Box`
//~| NOTE ambiguous `Color` from `Box`
//~| NOTE ambiguous `Color` from `Box`
//
fn mail(&self) { }
}

Expand All @@ -29,24 +35,18 @@ pub trait BoxCar : Box + Vehicle {
fn dent<C:BoxCar>(c: C, color: C::Color) {
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
//~| NOTE ambiguous associated type `Color`
//~| NOTE could derive from `Vehicle`
//~| NOTE could derive from `Box`
}

fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
//~^ ERROR ambiguous associated type
//~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified
//~| NOTE ambiguous associated type `Color`
//~| NOTE could derive from `Vehicle`
//~| NOTE could derive from `Box`
//~| NOTE missing associated type `Color` value
}

fn paint<C:BoxCar>(c: C, d: C::Color) {
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
//~| NOTE ambiguous associated type `Color`
//~| NOTE could derive from `Vehicle`
//~| NOTE could derive from `Box`
}

pub fn main() { }
16 changes: 8 additions & 8 deletions src/test/compile-fail/lint-unused-imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ use std::mem::*; // shouldn't get errors for not using
// everything imported

// Should get errors for both 'Some' and 'None'
use std::option::Option::{Some, None}; //~ ERROR unused import
//~^ ERROR unused import
use std::option::Option::{Some, None}; //~ ERROR unused import: `Some`
//~^ ERROR unused import: `None`

use test::A; //~ ERROR unused import
use test::A; //~ ERROR unused import: `test::A`
// Be sure that if we just bring some methods into scope that they're also
// counted as being used.
use test::B;
// But only when actually used: do not get confused by the method with the same name.
use test::B2; //~ ERROR unused import
use test::B2; //~ ERROR unused import: `test::B2`

// Make sure this import is warned about when at least one of its imported names
// is unused
use test2::{foo, bar}; //~ ERROR unused import
use test2::{foo, bar}; //~ ERROR unused import: `bar`

mod test2 {
pub fn foo() {}
Expand Down Expand Up @@ -57,7 +57,7 @@ mod bar {

pub mod c {
use foo::Point;
use foo::Square; //~ ERROR unused import
use foo::Square; //~ ERROR unused import: `foo::Square`
pub fn cc(_p: Point) -> super::Square {
fn f() -> super::Square {
super::Square
Expand All @@ -73,7 +73,7 @@ mod bar {
}

fn g() {
use self::g; //~ ERROR unused import
use self::g; //~ ERROR unused import: `self::g`
fn f() {
self::g();
}
Expand All @@ -82,7 +82,7 @@ fn g() {
// c.f. issue #35135
#[allow(unused_variables)]
fn h() {
use test2::foo; //~ ERROR unused import
use test2::foo; //~ ERROR unused import: `test2::foo`
let foo = 0;
}

Expand Down