]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #35882 - petrochenkov:patch-2, r=eddyb
authorJonathan Turner <jonathandturner@users.noreply.github.com>
Mon, 22 Aug 2016 22:34:22 +0000 (15:34 -0700)
committerGitHub <noreply@github.com>
Mon, 22 Aug 2016 22:34:22 +0000 (15:34 -0700)
rustc: Fix outdated comment

cc https://github.com/rust-lang/rust/issues/35870#issuecomment-241282692

r? @eddyb

71 files changed:
src/liballoc/rc.rs
src/libcollections/string.rs
src/libcore/ops.rs
src/libcore/ptr.rs
src/librustc/hir/lowering.rs
src/librustc/ty/relate.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_metadata/diagnostics.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/linker.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/libstd/ffi/c_str.rs
src/libstd/sys/unix/rwlock.rs
src/test/compile-fail/E0017.rs
src/test/compile-fail/E0033.rs
src/test/compile-fail/E0423.rs
src/test/compile-fail/E0424.rs
src/test/compile-fail/E0426.rs
src/test/compile-fail/E0435.rs
src/test/compile-fail/E0437.rs
src/test/compile-fail/E0438.rs
src/test/compile-fail/E0441.rs [new file with mode: 0644]
src/test/compile-fail/E0442.rs [new file with mode: 0644]
src/test/compile-fail/E0443.rs [new file with mode: 0644]
src/test/compile-fail/E0444.rs [new file with mode: 0644]
src/test/compile-fail/E0445.rs [new file with mode: 0644]
src/test/compile-fail/E0446.rs [new file with mode: 0644]
src/test/compile-fail/E0449.rs [new file with mode: 0644]
src/test/compile-fail/E0450.rs [new file with mode: 0644]
src/test/compile-fail/E0451.rs [new file with mode: 0644]
src/test/compile-fail/E0452.rs [new file with mode: 0644]
src/test/compile-fail/E0453.rs [new file with mode: 0644]
src/test/compile-fail/E0454.rs [new file with mode: 0644]
src/test/compile-fail/E0458.rs [new file with mode: 0644]
src/test/compile-fail/E0459.rs [new file with mode: 0644]
src/test/compile-fail/E0463.rs [new file with mode: 0644]
src/test/compile-fail/borrowck/borrowck-box-insensitivity.rs
src/test/compile-fail/cast-rfc0401.rs
src/test/compile-fail/import-from-missing.rs
src/test/compile-fail/import.rs
src/test/compile-fail/import2.rs
src/test/compile-fail/issue-12612.rs
src/test/compile-fail/issue-13404.rs
src/test/compile-fail/issue-1697.rs
src/test/compile-fail/issue-18252.rs
src/test/compile-fail/issue-19452.rs
src/test/compile-fail/issue-2356.rs
src/test/compile-fail/issue-25793.rs
src/test/compile-fail/issue-2937.rs
src/test/compile-fail/issue-30560.rs
src/test/compile-fail/issue-32833.rs
src/test/compile-fail/issue-5035.rs
src/test/compile-fail/issue-8208.rs
src/test/compile-fail/privacy2.rs
src/test/compile-fail/privacy3.rs
src/test/compile-fail/question-mark-type-infer.rs [new file with mode: 0644]
src/test/compile-fail/regions-escape-loop-via-vec.rs
src/test/compile-fail/resolve_self_super_hint.rs
src/test/compile-fail/super-at-top-level.rs
src/test/compile-fail/task-rng-isnt-sendable.rs
src/test/compile-fail/unresolved-import.rs
src/test/compile-fail/use-from-trait-xc.rs
src/test/compile-fail/use-from-trait.rs
src/test/compile-fail/use-keyword.rs
src/test/compile-fail/use-mod-2.rs
src/test/run-pass/try-operator-custom.rs [new file with mode: 0644]
src/tools/tidy/src/bins.rs

index 2beb652aa017a6d2c16e959afe05d592a203224d..3a158240c3a2671404336cad0d4f857cc6f1b0ad 100644 (file)
@@ -263,6 +263,23 @@ pub fn try_unwrap(this: Self) -> Result<T, Self> {
     }
 
     /// Checks if `Rc::try_unwrap` would return `Ok`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(rc_would_unwrap)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let x = Rc::new(3);
+    /// assert!(Rc::would_unwrap(&x));
+    /// assert_eq!(Rc::try_unwrap(x), Ok(3));
+    ///
+    /// let x = Rc::new(4);
+    /// let _y = x.clone();
+    /// assert!(!Rc::would_unwrap(&x));
+    /// assert_eq!(Rc::try_unwrap(x), Err(Rc::new(4)));
+    /// ```
     #[unstable(feature = "rc_would_unwrap",
                reason = "just added for niche usecase",
                issue = "28356")]
index 788c838cd3fc8ddaf70ec34a6d862bdac2d2a591..a7dc2875320b718e99a4e19fc5d443744251d28e 100644 (file)
 /// [`OsString`]: ../../std/ffi/struct.OsString.html
 ///
 /// Indexing is intended to be a constant-time operation, but UTF-8 encoding
-/// does not allow us to do this. Furtheremore, it's not clear what sort of
+/// does not allow us to do this. Furthermore, it's not clear what sort of
 /// thing the index should return: a byte, a codepoint, or a grapheme cluster.
 /// The [`as_bytes()`] and [`chars()`] methods return iterators over the first
 /// two, respectively.
index 5a1993e741c60821627d99a73eec28ace4ae4a15..282f281047e4702c9470ccd704b7b08f24dd428c 100644 (file)
@@ -74,6 +74,7 @@
 use cmp::PartialOrd;
 use fmt;
 use marker::{Sized, Unsize};
+use result::Result::{self, Ok, Err};
 
 /// The `Drop` trait is used to run some code when a value goes out of scope.
 /// This is sometimes called a 'destructor'.
@@ -298,26 +299,63 @@ fn sub(self, other: $t) -> $t { self - other }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `Mul`. When `Foo * Foo` happens, it ends up
-/// calling `mul`, and therefore, `main` prints `Multiplying!`.
+/// Implementing a `Mul`tipliable rational number struct:
 ///
 /// ```
 /// use std::ops::Mul;
 ///
-/// struct Foo;
+/// // The uniqueness of rational numbers in lowest terms is a consequence of
+/// // the fundamental theorem of arithmetic.
+/// #[derive(Eq)]
+/// #[derive(PartialEq, Debug)]
+/// struct Rational {
+///     nominator: usize,
+///     denominator: usize,
+/// }
 ///
-/// impl Mul for Foo {
-///     type Output = Foo;
+/// impl Rational {
+///     fn new(nominator: usize, denominator: usize) -> Self {
+///         if denominator == 0 {
+///             panic!("Zero is an invalid denominator!");
+///         }
 ///
-///     fn mul(self, _rhs: Foo) -> Foo {
-///         println!("Multiplying!");
-///         self
+///         // Reduce to lowest terms by dividing by the greatest common
+///         // divisor.
+///         let gcd = gcd(nominator, denominator);
+///         Rational {
+///             nominator: nominator / gcd,
+///             denominator: denominator / gcd,
+///         }
 ///     }
 /// }
 ///
-/// fn main() {
-///     Foo * Foo;
+/// impl Mul for Rational {
+///     // The multiplication of rational numbers is a closed operation.
+///     type Output = Self;
+///
+///     fn mul(self, rhs: Self) -> Self {
+///         let nominator = self.nominator * rhs.nominator;
+///         let denominator = self.denominator * rhs.denominator;
+///         Rational::new(nominator, denominator)
+///     }
 /// }
+///
+/// // Euclid's two-thousand-year-old algorithm for finding the greatest common
+/// // divisor.
+/// fn gcd(x: usize, y: usize) -> usize {
+///     let mut x = x;
+///     let mut y = y;
+///     while y != 0 {
+///         let t = y;
+///         y = x % y;
+///         x = t;
+///     }
+///     x
+/// }
+///
+/// assert_eq!(Rational::new(1, 2), Rational::new(2, 4));
+/// assert_eq!(Rational::new(2, 3) * Rational::new(3, 4),
+///            Rational::new(1, 2));
 /// ```
 ///
 /// Note that `RHS = Self` by default, but this is not mandatory. Here is an
@@ -485,26 +523,34 @@ fn div(self, other: $t) -> $t { self / other }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `Rem`. When `Foo % Foo` happens, it ends up
-/// calling `rem`, and therefore, `main` prints `Remainder-ing!`.
+/// This example implements `Rem` on a `SplitSlice` object. After `Rem` is
+/// implemented, one can use the `%` operator to find out what the remaining
+/// elements of the slice would be after splitting it into equal slices of a
+/// given length.
 ///
 /// ```
 /// use std::ops::Rem;
 ///
-/// struct Foo;
+/// #[derive(PartialEq, Debug)]
+/// struct SplitSlice<'a, T: 'a> {
+///     slice: &'a [T],
+/// }
 ///
-/// impl Rem for Foo {
-///     type Output = Foo;
+/// impl<'a, T> Rem<usize> for SplitSlice<'a, T> {
+///     type Output = SplitSlice<'a, T>;
 ///
-///     fn rem(self, _rhs: Foo) -> Foo {
-///         println!("Remainder-ing!");
-///         self
+///     fn rem(self, modulus: usize) -> Self {
+///         let len = self.slice.len();
+///         let rem = len % modulus;
+///         let start = len - rem;
+///         SplitSlice {slice: &self.slice[start..]}
 ///     }
 /// }
 ///
-/// fn main() {
-///     Foo % Foo;
-/// }
+/// // If we were to divide &[0, 1, 2, 3, 4, 5, 6, 7] into slices of size 3,
+/// // the remainder would be &[6, 7]
+/// assert_eq!(SplitSlice { slice: &[0, 1, 2, 3, 4, 5, 6, 7] } % 3,
+///            SplitSlice { slice: &[6, 7] });
 /// ```
 #[lang = "rem"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -693,26 +739,41 @@ fn not(self) -> $t { !self }
 ///
 /// # Examples
 ///
-/// A trivial implementation of `BitAnd`. When `Foo & Foo` happens, it ends up
-/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
+/// In this example, the `BitAnd` trait is implemented for a `BooleanVector`
+/// struct.
 ///
 /// ```
 /// use std::ops::BitAnd;
 ///
-/// struct Foo;
-///
-/// impl BitAnd for Foo {
-///     type Output = Foo;
-///
-///     fn bitand(self, _rhs: Foo) -> Foo {
-///         println!("Bitwise And-ing!");
-///         self
+/// #[derive(Debug)]
+/// struct BooleanVector {
+///     value: Vec<bool>,
+/// };
+///
+/// impl BitAnd for BooleanVector {
+///     type Output = Self;
+///
+///     fn bitand(self, rhs: Self) -> Self {
+///         BooleanVector {
+///             value: self.value
+///                 .iter()
+///                 .zip(rhs.value.iter())
+///                 .map(|(x, y)| *x && *y)
+///                 .collect(),
+///         }
 ///     }
 /// }
 ///
-/// fn main() {
-///     Foo & Foo;
+/// impl PartialEq for BooleanVector {
+///     fn eq(&self, other: &Self) -> bool {
+///         self.value == other.value
+///     }
 /// }
+///
+/// let bv1 = BooleanVector { value: vec![true, true, false, false] };
+/// let bv2 = BooleanVector { value: vec![true, false, true, false] };
+/// let expected = BooleanVector { value: vec![true, false, false, false] };
+/// assert_eq!(bv1 & bv2, expected);
 /// ```
 #[lang = "bitand"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1489,28 +1550,44 @@ macro_rules! shr_assign_impl_all {
 ///
 /// # Examples
 ///
-/// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up
-/// calling `index`, and therefore, `main` prints `Indexing!`.
+/// This example implements `Index` on a read-only `NucleotideCount` container,
+/// enabling individual counts to be retrieved with index syntax.
 ///
 /// ```
 /// use std::ops::Index;
 ///
-/// #[derive(Copy, Clone)]
-/// struct Foo;
-/// struct Bar;
+/// enum Nucleotide {
+///     A,
+///     C,
+///     G,
+///     T,
+/// }
 ///
-/// impl Index<Bar> for Foo {
-///     type Output = Foo;
+/// struct NucleotideCount {
+///     a: usize,
+///     c: usize,
+///     g: usize,
+///     t: usize,
+/// }
 ///
-///     fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
-///         println!("Indexing!");
-///         self
+/// impl Index<Nucleotide> for NucleotideCount {
+///     type Output = usize;
+///
+///     fn index(&self, nucleotide: Nucleotide) -> &usize {
+///         match nucleotide {
+///             Nucleotide::A => &self.a,
+///             Nucleotide::C => &self.c,
+///             Nucleotide::G => &self.g,
+///             Nucleotide::T => &self.t,
+///         }
 ///     }
 /// }
 ///
-/// fn main() {
-///     Foo[Bar];
-/// }
+/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12};
+/// assert_eq!(nucleotide_count[Nucleotide::A], 14);
+/// assert_eq!(nucleotide_count[Nucleotide::C], 9);
+/// assert_eq!(nucleotide_count[Nucleotide::G], 10);
+/// assert_eq!(nucleotide_count[Nucleotide::T], 12);
 /// ```
 #[lang = "index"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
@@ -2271,3 +2348,74 @@ pub trait BoxPlace<Data: ?Sized> : Place<Data> {
     /// Creates a globally fresh place.
     fn make_place() -> Self;
 }
+
+/// A trait for types which have success and error states and are meant to work
+/// with the question mark operator.
+/// When the `?` operator is used with a value, whether the value is in the
+/// success or error state is determined by calling `translate`.
+///
+/// This trait is **very** experimental, it will probably be iterated on heavily
+/// before it is stabilised. Implementors should expect change. Users of `?`
+/// should not rely on any implementations of `Carrier` other than `Result`,
+/// i.e., you should not expect `?` to continue to work with `Option`, etc.
+#[unstable(feature = "question_mark_carrier", issue = "31436")]
+pub trait Carrier {
+    /// The type of the value when computation succeeds.
+    type Success;
+    /// The type of the value when computation errors out.
+    type Error;
+
+    /// Create a `Carrier` from a success value.
+    fn from_success(Self::Success) -> Self;
+
+    /// Create a `Carrier` from an error value.
+    fn from_error(Self::Error) -> Self;
+
+    /// Translate this `Carrier` to another implementation of `Carrier` with the
+    /// same associated types.
+    fn translate<T>(self) -> T where T: Carrier<Success=Self::Success, Error=Self::Error>;
+}
+
+#[unstable(feature = "question_mark_carrier", issue = "31436")]
+impl<U, V> Carrier for Result<U, V> {
+    type Success = U;
+    type Error = V;
+
+    fn from_success(u: U) -> Result<U, V> {
+        Ok(u)
+    }
+
+    fn from_error(e: V) -> Result<U, V> {
+        Err(e)
+    }
+
+    fn translate<T>(self) -> T
+        where T: Carrier<Success=U, Error=V>
+    {
+        match self {
+            Ok(u) => T::from_success(u),
+            Err(e) => T::from_error(e),
+        }
+    }
+}
+
+struct _DummyErrorType;
+
+impl Carrier for _DummyErrorType {
+    type Success = ();
+    type Error = ();
+
+    fn from_success(_: ()) -> _DummyErrorType {
+        _DummyErrorType
+    }
+
+    fn from_error(_: ()) -> _DummyErrorType {
+        _DummyErrorType
+    }
+
+    fn translate<T>(self) -> T
+        where T: Carrier<Success=(), Error=()>
+    {
+        T::from_success(())
+    }
+}
index 925cdfec900dbd6da769a2f4a24eeee6be972ee0..8cb485872b3f3fe08de08b75b7987aa9d5a6e68a 100644 (file)
@@ -128,7 +128,9 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
 /// let x = 12;
 /// let y = &x as *const i32;
 ///
-/// unsafe { println!("{}", std::ptr::read(y)); }
+/// unsafe {
+///     assert_eq!(std::ptr::read(y), 12);
+/// }
 /// ```
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -178,7 +180,7 @@ pub unsafe fn read_and_drop<T>(dest: *mut T) -> T {
 ///
 /// unsafe {
 ///     std::ptr::write(y, z);
-///     println!("{}", std::ptr::read(y));
+///     assert_eq!(std::ptr::read(y), 12);
 /// }
 /// ```
 #[inline]
@@ -220,7 +222,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 /// let x = 12;
 /// let y = &x as *const i32;
 ///
-/// unsafe { println!("{}", std::ptr::read_volatile(y)); }
+/// unsafe {
+///     assert_eq!(std::ptr::read_volatile(y), 12);
+/// }
 /// ```
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
@@ -266,7 +270,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// unsafe {
 ///     std::ptr::write_volatile(y, z);
-///     println!("{}", std::ptr::read_volatile(y));
+///     assert_eq!(std::ptr::read_volatile(y), 12);
 /// }
 /// ```
 #[inline]
index c2b211238b2f1d1262ac1c812fa8a3667b6eac83..b45610c3fe820150bccc4f68a437991fc7887d7f 100644 (file)
@@ -966,7 +966,7 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                     let inplace_finalize = ["ops", "InPlace", "finalize"];
 
                     let make_call = |this: &mut LoweringContext, p, args| {
-                        let path = this.core_path(e.span, p);
+                        let path = this.std_path(e.span, p);
                         let path = this.expr_path(path, ThinVec::new());
                         this.expr_call(e.span, path, args)
                     };
@@ -1159,15 +1159,13 @@ fn make_struct(this: &mut LoweringContext,
                                    ast_expr: &Expr,
                                    path: &[&str],
                                    fields: &[(&str, &P<Expr>)]) -> P<hir::Expr> {
-                        let strs = this.std_path(&iter::once(&"ops")
-                                                        .chain(path)
-                                                        .map(|s| *s)
-                                                        .collect::<Vec<_>>());
-
-                        let structpath = this.path_global(ast_expr.span, strs);
+                        let struct_path = this.std_path(ast_expr.span,
+                                                        &iter::once(&"ops").chain(path)
+                                                                           .map(|s| *s)
+                                                                           .collect::<Vec<_>>());
 
                         let hir_expr = if fields.len() == 0 {
-                            this.expr_path(structpath, ast_expr.attrs.clone())
+                            this.expr_path(struct_path, ast_expr.attrs.clone())
                         } else {
                             let fields = fields.into_iter().map(|&(s, e)| {
                                 let expr = this.lower_expr(&e);
@@ -1180,7 +1178,7 @@ fn make_struct(this: &mut LoweringContext,
                             }).collect();
                             let attrs = ast_expr.attrs.clone();
 
-                            this.expr_struct(ast_expr.span, structpath, fields, None, attrs)
+                            this.expr_struct(ast_expr.span, struct_path, fields, None, attrs)
                         };
 
                         this.signal_block_expr(hir_vec![],
@@ -1463,11 +1461,7 @@ fn make_struct(this: &mut LoweringContext,
 
                     // `match ::std::iter::Iterator::next(&mut iter) { ... }`
                     let match_expr = {
-                        let next_path = {
-                            let strs = self.std_path(&["iter", "Iterator", "next"]);
-
-                            self.path_global(e.span, strs)
-                        };
+                        let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
                         let iter = self.expr_ident(e.span, iter, iter_pat.id);
                         let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
                         let next_path = self.expr_path(next_path, ThinVec::new());
@@ -1494,11 +1488,8 @@ fn make_struct(this: &mut LoweringContext,
 
                     // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
                     let into_iter_expr = {
-                        let into_iter_path = {
-                            let strs = self.std_path(&["iter", "IntoIterator", "into_iter"]);
-
-                            self.path_global(e.span, strs)
-                        };
+                        let into_iter_path = self.std_path(e.span,
+                                                           &["iter", "IntoIterator", "into_iter"]);
 
                         let into_iter = self.expr_path(into_iter_path, ThinVec::new());
                         self.expr_call(e.span, into_iter, hir_vec![head])
@@ -1527,16 +1518,32 @@ fn make_struct(this: &mut LoweringContext,
                     // to:
                     //
                     // {
-                    //     match <expr> {
+                    //     match { Carrier::translate( { <expr> } ) } {
                     //         Ok(val) => val,
-                    //         Err(err) => {
-                    //             return Err(From::from(err))
-                    //         }
+                    //         Err(err) => { return Carrier::from_error(From::from(err)); }
                     //     }
                     // }
 
-                    // expand <expr>
-                    let sub_expr = self.lower_expr(sub_expr);
+                    // { Carrier::translate( { <expr> } ) }
+                    let discr = {
+                        // expand <expr>
+                        let sub_expr = self.lower_expr(sub_expr);
+                        let sub_expr = self.signal_block_expr(hir_vec![],
+                                                              sub_expr,
+                                                              e.span,
+                                                              hir::PopUnstableBlock,
+                                                              ThinVec::new());
+
+                        let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
+                        let path = self.expr_path(path, ThinVec::new());
+                        let call = self.expr_call(e.span, path, hir_vec![sub_expr]);
+
+                        self.signal_block_expr(hir_vec![],
+                                               call,
+                                               e.span,
+                                               hir::PushUnstableBlock,
+                                               ThinVec::new())
+                    };
 
                     // Ok(val) => val
                     let ok_arm = {
@@ -1548,32 +1555,35 @@ fn make_struct(this: &mut LoweringContext,
                         self.arm(hir_vec![ok_pat], val_expr)
                     };
 
-                    // Err(err) => return Err(From::from(err))
+                    // Err(err) => { return Carrier::from_error(From::from(err)); }
                     let err_arm = {
                         let err_ident = self.str_to_ident("err");
                         let err_local = self.pat_ident(e.span, err_ident);
                         let from_expr = {
-                            let path = self.std_path(&["convert", "From", "from"]);
-                            let path = self.path_global(e.span, path);
+                            let path = self.std_path(e.span, &["convert", "From", "from"]);
                             let from = self.expr_path(path, ThinVec::new());
                             let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
 
                             self.expr_call(e.span, from, hir_vec![err_expr])
                         };
-                        let err_expr = {
-                            let path = self.std_path(&["result", "Result", "Err"]);
-                            let path = self.path_global(e.span, path);
-                            let err_ctor = self.expr_path(path, ThinVec::new());
-                            self.expr_call(e.span, err_ctor, hir_vec![from_expr])
+                        let from_err_expr = {
+                            let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
+                            let from_err = self.expr_path(path, ThinVec::new());
+                            self.expr_call(e.span, from_err, hir_vec![from_expr])
                         };
-                        let err_pat = self.pat_err(e.span, err_local);
+
                         let ret_expr = self.expr(e.span,
-                                                 hir::Expr_::ExprRet(Some(err_expr)),
-                                                 ThinVec::new());
-                        self.arm(hir_vec![err_pat], ret_expr)
+                                                 hir::Expr_::ExprRet(Some(from_err_expr)),
+                                                                     ThinVec::new());
+                        let ret_stmt = self.stmt_expr(ret_expr);
+                        let block = self.signal_block_stmt(ret_stmt, e.span,
+                                                           hir::PushUnstableBlock, ThinVec::new());
+
+                        let err_pat = self.pat_err(e.span, err_local);
+                        self.arm(hir_vec![err_pat], block)
                     };
 
-                    return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm],
+                    return self.expr_match(e.span, discr, hir_vec![err_arm, ok_arm],
                                            hir::MatchSource::TryDesugar);
                 }
 
@@ -1787,6 +1797,15 @@ fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
         (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
     }
 
+    // Turns `<expr>` into `<expr>;`, note that this produces a StmtSemi, not a
+    // StmtExpr.
+    fn stmt_expr(&self, expr: P<hir::Expr>) -> hir::Stmt {
+        hir::Stmt {
+            span: expr.span,
+            node: hir::StmtSemi(expr, self.next_id()),
+        }
+    }
+
     fn block_expr(&mut self, expr: P<hir::Expr>) -> P<hir::Block> {
         self.block_all(expr.span, hir::HirVec::new(), Some(expr))
     }
@@ -1803,26 +1822,22 @@ fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<
     }
 
     fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
-        let ok = self.std_path(&["result", "Result", "Ok"]);
-        let path = self.path_global(span, ok);
+        let path = self.std_path(span, &["result", "Result", "Ok"]);
         self.pat_enum(span, path, hir_vec![pat])
     }
 
     fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
-        let err = self.std_path(&["result", "Result", "Err"]);
-        let path = self.path_global(span, err);
+        let path = self.std_path(span, &["result", "Result", "Err"]);
         self.pat_enum(span, path, hir_vec![pat])
     }
 
     fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
-        let some = self.std_path(&["option", "Option", "Some"]);
-        let path = self.path_global(span, some);
+        let path = self.std_path(span, &["option", "Option", "Some"]);
         self.pat_enum(span, path, hir_vec![pat])
     }
 
     fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
-        let none = self.std_path(&["option", "Option", "None"]);
-        let path = self.path_global(span, none);
+        let path = self.std_path(span, &["option", "Option", "None"]);
         self.pat_enum(span, path, hir_vec![])
     }
 
@@ -1920,7 +1935,7 @@ fn path_all(&mut self,
         }
     }
 
-    fn std_path(&mut self, components: &[&str]) -> Vec<Name> {
+    fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
         let mut v = Vec::new();
         if let Some(s) = self.crate_root {
             v.push(token::intern(s));
@@ -1931,8 +1946,8 @@ fn std_path(&mut self, components: &[&str]) -> Vec<Name> {
 
     // Given suffix ["b","c","d"], returns path `::std::b::c::d` when
     // `fld.cx.use_std`, and `::core::b::c::d` otherwise.
-    fn core_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
-        let idents = self.std_path(components);
+    fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
+        let idents = self.std_path_components(components);
         self.path_global(span, idents)
     }
 
@@ -1953,4 +1968,21 @@ fn signal_block_expr(&mut self,
         });
         self.expr_block(block, attrs)
     }
+
+    fn signal_block_stmt(&mut self,
+                         stmt: hir::Stmt,
+                         span: Span,
+                         rule: hir::BlockCheckMode,
+                         attrs: ThinVec<Attribute>)
+                         -> P<hir::Expr> {
+        let id = self.next_id();
+        let block = P(hir::Block {
+            rules: rule,
+            span: span,
+            id: id,
+            stmts: hir_vec![stmt],
+            expr: None,
+        });
+        self.expr_block(block, attrs)
+    }
 }
index abf863f953664258de01fbcbf4f0ba40b8603922..8975a799be14328bd2ab057dbf7eafe5cf90e4e2 100644 (file)
@@ -151,13 +151,13 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R,
         let b_ty = &b_subst.types[i];
         let variance = variances.map_or(ty::Invariant, |v| v.types[i]);
         relation.relate_with_variance(variance, a_ty, b_ty)
-    }).collect()?;
+    }).collect::<Result<_, _>>()?;
 
     let regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| {
         let b_r = &b_subst.regions[i];
         let variance = variances.map_or(ty::Invariant, |v| v.regions[i]);
         relation.relate_with_variance(variance, a_r, b_r)
-    }).collect()?;
+    }).collect::<Result<_, _>>()?;
 
     Ok(Substs::new(tcx, types, regions))
 }
index 9cae270984f0047cce5f873e6004b5c47fe6722b..c1f162e5772bf41d81cffac9fa3a52bff9481341 100644 (file)
@@ -647,10 +647,13 @@ fn check_for_copy_of_frozen_path(&self,
                 struct_span_err!(self.bccx, span, E0503,
                                  "cannot use `{}` because it was mutably borrowed",
                                  &self.bccx.loan_path_to_string(copy_path))
-                    .span_note(loan_span,
+                    .span_label(loan_span,
                                &format!("borrow of `{}` occurs here",
                                        &self.bccx.loan_path_to_string(&loan_path))
                                )
+                    .span_label(span,
+                               &format!("use of borrowed `{}`",
+                                        &self.bccx.loan_path_to_string(&loan_path)))
                     .emit();
             }
         }
index fd5db97b5d8bc48ed3da920df32333b1caa638cb..225895adefa4ba7621826f71c07a611b72352e74 100644 (file)
@@ -914,9 +914,11 @@ pub fn report_aliasability_violation(&self,
             }
             mc::AliasableStatic |
             mc::AliasableStaticMut => {
-                struct_span_err!(
+                let mut err = struct_span_err!(
                     self.tcx.sess, span, E0388,
-                    "{} in a static location", prefix)
+                    "{} in a static location", prefix);
+                err.span_label(span, &format!("cannot write data in a static definition"));
+                err
             }
             mc::AliasableBorrowed => {
                 struct_span_err!(
index ae9f500c5de59113ba5165bffa00c42feca1663a..099ec62b38de715180340825420473e9ebf47288 100644 (file)
@@ -14,7 +14,7 @@
 E0454: r##"
 A link name was given with an empty name. Erroneous code example:
 
-```
+```compile_fail,E0454
 #[link(name = "")] extern {} // error: #[link(name = "")] given with empty name
 ```
 
@@ -32,7 +32,7 @@
 
 Erroneous code example:
 
-```compile_fail"
+```compile_fail,E0455
 #[link(name = "FooCoreServices",  kind = "framework")] extern {}
 // OS used to compile is Linux for example
 ```
@@ -50,7 +50,7 @@
 E0458: r##"
 An unknown "kind" was specified for a link attribute. Erroneous code example:
 
-```
+```compile_fail,E0458
 #[link(kind = "wonderful_unicorn")] extern {}
 // error: unknown kind: `wonderful_unicorn`
 ```
@@ -64,7 +64,7 @@
 E0459: r##"
 A link was used without a name parameter. Erroneous code example:
 
-```
+```compile_fail,E0459
 #[link(kind = "dylib")] extern {}
 // error: #[link(...)] specified without `name = "foo"`
 ```
@@ -80,7 +80,7 @@
 E0463: r##"
 A plugin/crate was declared but cannot be found. Erroneous code example:
 
-```
+```compile_fail,E0463
 #![feature(plugin)]
 #![plugin(cookie_monster)] // error: can't find crate for `cookie_monster`
 extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
index 116c1b7a6d06f811eb29829e316cfedfe093d1e6..579853446525e61d2fa6f9f982cf5fad48dfac0a 100644 (file)
@@ -56,12 +56,7 @@ impl<'b> Resolver<'b> {
     pub fn build_reduced_graph(&mut self, krate: &Crate) {
         let no_implicit_prelude = attr::contains_name(&krate.attrs, "no_implicit_prelude");
         self.graph_root.no_implicit_prelude.set(no_implicit_prelude);
-
-        let mut visitor = BuildReducedGraphVisitor {
-            parent: self.graph_root,
-            resolver: self,
-        };
-        visit::walk_crate(&mut visitor, krate);
+        visit::walk_crate(&mut BuildReducedGraphVisitor { resolver: self }, krate);
     }
 
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
@@ -84,11 +79,11 @@ fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
     }
 
     /// Constructs the reduced graph for one item.
-    fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
-        let parent = *parent_ref;
+    fn build_reduced_graph_for_item(&mut self, item: &Item) {
+        let parent = self.current_module;
+        let parent_vis = self.current_vis;
         let name = item.ident.name;
         let sp = item.span;
-        self.current_module = parent;
         let vis = self.resolve_visibility(&item.vis);
 
         match item.node {
@@ -130,8 +125,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
 
                         let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
                         let span = view_path.span;
-                        parent.add_import_directive(module_path, subclass, span, item.id, vis);
-                        self.unresolved_imports += 1;
+                        self.add_import_directive(module_path, subclass, span, item.id, vis);
                     }
                     ViewPathList(_, ref source_items) => {
                         // Make sure there's at most one `mod` import in the list.
@@ -176,15 +170,13 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
                             };
                             let subclass = ImportDirectiveSubclass::single(rename, name);
                             let (span, id) = (source_item.span, source_item.node.id());
-                            parent.add_import_directive(module_path, subclass, span, id, vis);
-                            self.unresolved_imports += 1;
+                            self.add_import_directive(module_path, subclass, span, id, vis);
                         }
                     }
                     ViewPathGlob(_) => {
                         let subclass = GlobImport { is_prelude: is_prelude };
                         let span = view_path.span;
-                        parent.add_import_directive(module_path, subclass, span, item.id, vis);
-                        self.unresolved_imports += 1;
+                        self.add_import_directive(module_path, subclass, span, item.id, vis);
                     }
                 }
             }
@@ -216,7 +208,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
                 });
                 self.define(parent, name, TypeNS, (module, sp, vis));
                 self.module_map.insert(item.id, module);
-                *parent_ref = module;
+
+                // Descend into the module.
+                self.current_module = module;
+                self.current_vis = ty::Visibility::Restricted(item.id);
             }
 
             ItemKind::ForeignMod(..) => {}
@@ -309,6 +304,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<
             }
             ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
         }
+
+        visit::walk_item(&mut BuildReducedGraphVisitor { resolver: self }, item);
+        self.current_module = parent;
+        self.current_vis = parent_vis;
     }
 
     // Constructs the reduced graph for one variant. Variants exist in the
@@ -333,9 +332,8 @@ fn build_reduced_graph_for_variant(&mut self,
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item(&mut self,
-                                            foreign_item: &ForeignItem,
-                                            parent: Module<'b>) {
+    fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem) {
+        let parent = self.current_module;
         let name = foreign_item.ident.name;
 
         let def = match foreign_item.node {
@@ -346,12 +344,12 @@ fn build_reduced_graph_for_foreign_item(&mut self,
                 Def::Static(self.definitions.local_def_id(foreign_item.id), m)
             }
         };
-        self.current_module = parent;
         let vis = self.resolve_visibility(&foreign_item.vis);
         self.define(parent, name, ValueNS, (def, foreign_item.span, vis));
     }
 
-    fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
+    fn build_reduced_graph_for_block(&mut self, block: &Block) {
+        let parent = self.current_module;
         if self.block_needs_anonymous_module(block) {
             let block_id = block.id;
 
@@ -362,8 +360,11 @@ fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'
             let parent_link = BlockParentLink(parent, block_id);
             let new_module = self.new_module(parent_link, None, false);
             self.module_map.insert(block_id, new_module);
-            *parent = new_module;
+            self.current_module = new_module; // Descend into the block.
         }
+
+        visit::walk_block(&mut BuildReducedGraphVisitor { resolver: self }, block);
+        self.current_module = parent;
     }
 
     /// Builds the reduced graph for a single item in an external crate.
@@ -487,25 +488,18 @@ pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
 
 struct BuildReducedGraphVisitor<'a, 'b: 'a> {
     resolver: &'a mut Resolver<'b>,
-    parent: Module<'b>,
 }
 
 impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_item(&mut self, item: &Item) {
-        let old_parent = self.parent;
-        self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
-        visit::walk_item(self, item);
-        self.parent = old_parent;
+        self.resolver.build_reduced_graph_for_item(item);
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        self.resolver.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
+        self.resolver.build_reduced_graph_for_foreign_item(foreign_item);
     }
 
     fn visit_block(&mut self, block: &Block) {
-        let old_parent = self.parent;
-        self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
-        visit::walk_block(self, block);
-        self.parent = old_parent;
+        self.resolver.build_reduced_graph_for_block(block);
     }
 }
index af39f8a415c6797e4327622cb02650e773cacf95..5641a50ccaccf53c00d71bb1b2aebe548277347f 100644 (file)
@@ -251,20 +251,24 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err
         }
         ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0437,
                              "type `{}` is not a member of trait `{}`",
                              type_,
-                             trait_)
+                             trait_);
+            err.span_label(span, &format!("not a member of trait `Foo`"));
+            err
         }
         ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0438,
                              "const `{}` is not a member of trait `{}`",
                              const_,
-                             trait_)
+                             trait_);
+            err.span_label(span, &format!("not a member of trait `Foo`"));
+            err
         }
         ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
             struct_span_err!(resolver.session,
@@ -336,19 +340,23 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err
         }
         ResolutionError::StructVariantUsedAsFunction(path_name) => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0423,
                              "`{}` is the name of a struct or struct variant, but this expression \
                              uses it like a function name",
-                             path_name)
+                             path_name);
+            err.span_label(span, &format!("struct called like a function"));
+            err
         }
         ResolutionError::SelfNotAvailableInStaticMethod => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0424,
-                             "`self` is not available in a static method. Maybe a `self` \
-                             argument is missing?")
+                             "`self` is not available in a static method");
+            err.span_label(span, &format!("not available in static method"));
+            err.note(&format!("maybe a `self` argument is missing?"));
+            err
         }
         ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
                                           is_field, def } => {
@@ -390,11 +398,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             err
         }
         ResolutionError::UndeclaredLabel(name) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0426,
-                             "use of undeclared label `{}`",
-                             name)
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0426,
+                                           "use of undeclared label `{}`",
+                                           name);
+            err.span_label(span, &format!("undeclared label `{}`",&name));
+            err
         }
         ResolutionError::SelfImportsOnlyAllowedWithin => {
             struct_span_err!(resolver.session,
@@ -418,10 +428,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
         }
         ResolutionError::UnresolvedImport(name) => {
             let msg = match name {
-                Some((n, p)) => format!("unresolved import `{}`{}", n, p),
+                Some((n, _)) => format!("unresolved import `{}`", n),
                 None => "unresolved import".to_owned(),
             };
-            struct_span_err!(resolver.session, span, E0432, "{}", msg)
+            let mut err = struct_span_err!(resolver.session, span, E0432, "{}", msg);
+            if let Some((_, p)) = name {
+                err.span_label(span, &p);
+            }
+            err
         }
         ResolutionError::FailedToResolve(msg) => {
             let mut err = struct_span_err!(resolver.session, span, E0433,
@@ -438,10 +452,12 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
                               closure form instead")
         }
         ResolutionError::AttemptToUseNonConstantValueInConstant => {
-            struct_span_err!(resolver.session,
+            let mut err = struct_span_err!(resolver.session,
                              span,
                              E0435,
-                             "attempt to use a non-constant value in a constant")
+                             "attempt to use a non-constant value in a constant");
+            err.span_label(span, &format!("non-constant used with constant"));
+            err
         }
         ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
             let shadows_what = PathResolution::new(binding.def().unwrap()).kind_name();
@@ -758,11 +774,10 @@ pub struct ModuleS<'a> {
     extern_crate_id: Option<NodeId>,
 
     resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
-    unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>,
 
     no_implicit_prelude: Cell<bool>,
 
-    glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>,
+    glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>,
     globs: RefCell<Vec<&'a ImportDirective<'a>>>,
 
     // Used to memoize the traits in this module for faster searches through all traits in scope.
@@ -772,29 +787,22 @@ pub struct ModuleS<'a> {
     // access the children must be preceded with a
     // `populate_module_if_necessary` call.
     populated: Cell<bool>,
-
-    arenas: &'a ResolverArenas<'a>,
 }
 
 pub type Module<'a> = &'a ModuleS<'a>;
 
 impl<'a> ModuleS<'a> {
-    fn new(parent_link: ParentLink<'a>,
-           def: Option<Def>,
-           external: bool,
-           arenas: &'a ResolverArenas<'a>) -> Self {
+    fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool) -> Self {
         ModuleS {
             parent_link: parent_link,
             def: def,
             extern_crate_id: None,
             resolutions: RefCell::new(HashMap::new()),
-            unresolved_imports: RefCell::new(Vec::new()),
             no_implicit_prelude: Cell::new(false),
             glob_importers: RefCell::new(Vec::new()),
             globs: RefCell::new((Vec::new())),
             traits: RefCell::new(None),
             populated: Cell::new(!external),
-            arenas: arenas
         }
     }
 
@@ -971,12 +979,19 @@ pub struct Resolver<'a> {
 
     structs: FnvHashMap<DefId, Vec<Name>>,
 
-    // The number of imports that are currently unresolved.
-    unresolved_imports: usize,
+    // All imports known to succeed or fail.
+    determined_imports: Vec<&'a ImportDirective<'a>>,
+
+    // All non-determined imports.
+    indeterminate_imports: Vec<&'a ImportDirective<'a>>,
 
     // The module that represents the current item scope.
     current_module: Module<'a>,
 
+    // The visibility of `pub(self)` items in the current scope.
+    // Equivalently, the visibility required for an item to be accessible from the current scope.
+    current_vis: ty::Visibility,
+
     // The current set of local scopes, for values.
     // FIXME #4948: Reuse ribs to avoid allocation.
     value_ribs: Vec<Rib<'a>>,
@@ -1140,7 +1155,7 @@ pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a Resolve
                -> Resolver<'a> {
         let root_def_id = DefId::local(CRATE_DEF_INDEX);
         let graph_root =
-            ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas);
+            ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false);
         let graph_root = arenas.alloc_module(graph_root);
         let mut module_map = NodeMap();
         module_map.insert(CRATE_NODE_ID, graph_root);
@@ -1159,9 +1174,11 @@ pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a Resolve
             trait_item_map: FnvHashMap(),
             structs: FnvHashMap(),
 
-            unresolved_imports: 0,
+            determined_imports: Vec::new(),
+            indeterminate_imports: Vec::new(),
 
             current_module: graph_root,
+            current_vis: ty::Visibility::Restricted(ast::CRATE_NODE_ID),
             value_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
             type_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
             label_ribs: Vec::new(),
@@ -1205,6 +1222,7 @@ pub fn arenas() -> ResolverArenas<'a> {
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
         self.current_module = self.graph_root;
+        self.current_vis = ty::Visibility::Restricted(ast::CRATE_NODE_ID);
         visit::walk_crate(self, krate);
 
         check_unused::check_crate(self, krate);
@@ -1213,12 +1231,12 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
 
     fn new_module(&self, parent_link: ParentLink<'a>, def: Option<Def>, external: bool)
                   -> Module<'a> {
-        self.arenas.alloc_module(ModuleS::new(parent_link, def, external, self.arenas))
+        self.arenas.alloc_module(ModuleS::new(parent_link, def, external))
     }
 
     fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def, local_node_id: NodeId)
                                -> Module<'a> {
-        let mut module = ModuleS::new(parent_link, Some(def), false, self.arenas);
+        let mut module = ModuleS::new(parent_link, Some(def), false);
         module.extern_crate_id = Some(local_node_id);
         self.arenas.modules.alloc(module)
     }
@@ -1250,14 +1268,15 @@ fn resolve_module_path_from_root(&mut self,
                                      mut search_module: Module<'a>,
                                      module_path: &[Name],
                                      index: usize,
-                                     span: Span)
+                                     span: Option<Span>)
                                      -> ResolveResult<Module<'a>> {
-        fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
-            match module.resolve_name(needle, TypeNS, false) {
+        fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
+                                       -> Option<Module<'a>> {
+            match this.resolve_name_in_module(module, needle, TypeNS, false, None) {
                 Success(binding) if binding.is_extern_crate() => Some(module),
                 _ => match module.parent_link {
                     ModuleParentLink(ref parent, _) => {
-                        search_parent_externals(needle, parent)
+                        search_parent_externals(this, needle, parent)
                     }
                     _ => None,
                 },
@@ -1272,16 +1291,17 @@ fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index];
-            match self.resolve_name_in_module(search_module, name, TypeNS, false, true) {
+            match self.resolve_name_in_module(search_module, name, TypeNS, false, span) {
                 Failed(None) => {
                     let segment_name = name.as_str();
                     let module_name = module_to_string(search_module);
                     let msg = if "???" == &module_name {
-                        match search_parent_externals(name, &self.current_module) {
+                        let current_module = self.current_module;
+                        match search_parent_externals(self, name, current_module) {
                             Some(module) => {
                                 let path_str = names_to_string(module_path);
                                 let target_mod_str = module_to_string(&module);
-                                let current_mod_str = module_to_string(&self.current_module);
+                                let current_mod_str = module_to_string(current_module);
 
                                 let prefix = if target_mod_str == current_mod_str {
                                     "self::".to_string()
@@ -1297,7 +1317,7 @@ fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
                         format!("Could not find `{}` in `{}`", segment_name, module_name)
                     };
 
-                    return Failed(Some((span, msg)));
+                    return Failed(span.map(|span| (span, msg)));
                 }
                 Failed(err) => return Failed(err),
                 Indeterminate => {
@@ -1310,11 +1330,10 @@ fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
                     // Check to see whether there are type bindings, and, if
                     // so, whether there is a module within.
                     if let Some(module_def) = binding.module() {
-                        self.check_privacy(name, binding, span);
                         search_module = module_def;
                     } else {
                         let msg = format!("Not a module `{}`", name);
-                        return Failed(Some((span, msg)));
+                        return Failed(span.map(|span| (span, msg)));
                     }
                 }
             }
@@ -1330,7 +1349,7 @@ fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
     fn resolve_module_path(&mut self,
                            module_path: &[Name],
                            use_lexical_scope: UseLexicalScopeFlag,
-                           span: Span)
+                           span: Option<Span>)
                            -> ResolveResult<Module<'a>> {
         if module_path.len() == 0 {
             return Success(self.graph_root) // Use the crate root
@@ -1367,7 +1386,7 @@ fn resolve_module_path(&mut self,
                         // first component of the path in the current lexical
                         // scope and then proceed to resolve below that.
                         let ident = ast::Ident::with_empty_ctxt(module_path[0]);
-                        match self.resolve_ident_in_lexical_scope(ident, TypeNS, true)
+                        match self.resolve_ident_in_lexical_scope(ident, TypeNS, span)
                                   .and_then(LexicalScopeBinding::module) {
                             None => return Failed(None),
                             Some(containing_module) => {
@@ -1384,10 +1403,7 @@ fn resolve_module_path(&mut self,
             }
         }
 
-        self.resolve_module_path_from_root(search_module,
-                                           module_path,
-                                           start_index,
-                                           span)
+        self.resolve_module_path_from_root(search_module, module_path, start_index, span)
     }
 
     /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
@@ -1410,7 +1426,7 @@ fn resolve_module_path(&mut self,
     fn resolve_ident_in_lexical_scope(&mut self,
                                       mut ident: ast::Ident,
                                       ns: Namespace,
-                                      record_used: bool)
+                                      record_used: Option<Span>)
                                       -> Option<LexicalScopeBinding<'a>> {
         if ns == TypeNS {
             ident = ast::Ident::with_empty_ctxt(ident.name);
@@ -1438,8 +1454,8 @@ fn resolve_ident_in_lexical_scope(&mut self,
                 if module.def.is_some() {
                     return match self.prelude {
                         Some(prelude) if !module.no_implicit_prelude.get() => {
-                            prelude.resolve_name(name, ns, false).success()
-                                   .map(LexicalScopeBinding::Item)
+                            self.resolve_name_in_module(prelude, name, ns, false, None).success()
+                                .map(LexicalScopeBinding::Item)
                         }
                         _ => None,
                     };
@@ -1491,7 +1507,7 @@ fn get_nearest_normal_module_parent_or_self(&self, module: Module<'a>) -> Module
     /// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
     /// (b) some chain of `super::`.
     /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
-    fn resolve_module_prefix(&mut self, module_path: &[Name], span: Span)
+    fn resolve_module_prefix(&mut self, module_path: &[Name], span: Option<Span>)
                              -> ResolveResult<ModulePrefixResult<'a>> {
         // Start at the current module if we see `self` or `super`, or at the
         // top of the crate otherwise.
@@ -1510,7 +1526,7 @@ fn resolve_module_prefix(&mut self, module_path: &[Name], span: Span)
             match self.get_nearest_normal_module_parent(containing_module) {
                 None => {
                     let msg = "There are too many initial `super`s.".into();
-                    return Failed(Some((span, msg)));
+                    return Failed(span.map(|span| (span, msg)));
                 }
                 Some(new_module) => {
                     containing_module = new_module;
@@ -1525,27 +1541,6 @@ fn resolve_module_prefix(&mut self, module_path: &[Name], span: Span)
         return Success(PrefixFound(containing_module, i));
     }
 
-    /// Attempts to resolve the supplied name in the given module for the
-    /// given namespace. If successful, returns the binding corresponding to
-    /// the name.
-    fn resolve_name_in_module(&mut self,
-                              module: Module<'a>,
-                              name: Name,
-                              namespace: Namespace,
-                              use_lexical_scope: bool,
-                              record_used: bool)
-                              -> ResolveResult<&'a NameBinding<'a>> {
-        debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
-
-        self.populate_module_if_necessary(module);
-        module.resolve_name(name, namespace, use_lexical_scope).and_then(|binding| {
-            if record_used {
-                self.record_use(name, namespace, binding);
-            }
-            Success(binding)
-        })
-    }
-
     // AST resolution
     //
     // We maintain a list of value ribs and type ribs.
@@ -1570,13 +1565,15 @@ fn with_scope<F>(&mut self, id: NodeId, f: F)
         let module = self.module_map.get(&id).cloned(); // clones a reference
         if let Some(module) = module {
             // Move down in the graph.
-            let orig_module = ::std::mem::replace(&mut self.current_module, module);
+            let orig_module = replace(&mut self.current_module, module);
+            let orig_vis = replace(&mut self.current_vis, ty::Visibility::Restricted(id));
             self.value_ribs.push(Rib::new(ModuleRibKind(module)));
             self.type_ribs.push(Rib::new(ModuleRibKind(module)));
 
             f(self);
 
             self.current_module = orig_module;
+            self.current_vis = orig_vis;
             self.value_ribs.pop();
             self.type_ribs.pop();
         } else {
@@ -2314,7 +2311,7 @@ fn resolve_pattern(&mut self,
                 PatKind::Ident(bmode, ref ident, ref opt_pat) => {
                     // First try to resolve the identifier as some existing
                     // entity, then fall back to a fresh binding.
-                    let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, false)
+                    let binding = self.resolve_ident_in_lexical_scope(ident.node, ValueNS, None)
                                       .and_then(LexicalScopeBinding::item);
                     let resolution = binding.and_then(NameBinding::def).and_then(|def| {
                         let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
@@ -2481,11 +2478,11 @@ fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace
             //
             // Such behavior is required for backward compatibility.
             // The same fallback is used when `a` resolves to nothing.
-            let def = resolve_identifier_with_fallback(self, true).ok_or(false);
+            let def = resolve_identifier_with_fallback(self, Some(span)).ok_or(false);
             return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res);
         }
 
-        let unqualified_def = resolve_identifier_with_fallback(self, false);
+        let unqualified_def = resolve_identifier_with_fallback(self, None);
         let qualified_binding = self.resolve_module_relative_path(span, segments, namespace);
         match (qualified_binding, unqualified_def) {
             (Ok(binding), Some(ref ud)) if binding.def().unwrap() == ud.def => {
@@ -2505,7 +2502,7 @@ fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace
     fn resolve_identifier(&mut self,
                           identifier: ast::Ident,
                           namespace: Namespace,
-                          record_used: bool)
+                          record_used: Option<Span>)
                           -> Option<LocalDef> {
         if identifier.name == keywords::Invalid.name() {
             return None;
@@ -2619,7 +2616,7 @@ fn resolve_module_relative_path(&mut self,
                                   .collect::<Vec<_>>();
 
         let containing_module;
-        match self.resolve_module_path(&module_path, UseLexicalScope, span) {
+        match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
             Failed(err) => {
                 let (span, msg) = match err {
                     Some((span, msg)) => (span, msg),
@@ -2640,11 +2637,9 @@ fn resolve_module_relative_path(&mut self,
         }
 
         let name = segments.last().unwrap().identifier.name;
-        let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
-        result.success().map(|binding| {
-            self.check_privacy(name, binding, span);
-            binding
-        }).ok_or(false)
+        let result =
+            self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+        result.success().ok_or(false)
     }
 
     /// Invariant: This must be called only during main resolution, not during
@@ -2658,10 +2653,7 @@ fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespa
         let root_module = self.graph_root;
 
         let containing_module;
-        match self.resolve_module_path_from_root(root_module,
-                                                 &module_path,
-                                                 0,
-                                                 span) {
+        match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) {
             Failed(err) => {
                 let (span, msg) = match err {
                     Some((span, msg)) => (span, msg),
@@ -2684,11 +2676,9 @@ fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespa
         }
 
         let name = segments.last().unwrap().name();
-        let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
-        result.success().map(|binding| {
-            self.check_privacy(name, binding, span);
-            binding
-        }).ok_or(false)
+        let result =
+            self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+        result.success().ok_or(false)
     }
 
     fn with_no_errors<T, F>(&mut self, f: F) -> T
@@ -2716,7 +2706,6 @@ pub fn with_module_lexical_scope<T, F>(&mut self, module: Module<'a>, f: F) -> T
     fn with_empty_ribs<T, F>(&mut self, f: F) -> T
         where F: FnOnce(&mut Resolver<'a>) -> T,
     {
-        use ::std::mem::replace;
         let value_ribs = replace(&mut self.value_ribs, Vec::new());
         let type_ribs = replace(&mut self.type_ribs, Vec::new());
         let label_ribs = replace(&mut self.label_ribs, Vec::new());
@@ -2941,7 +2930,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
 
                                     match self.resolve_module_path(&name_path[..],
                                                                    UseLexicalScope,
-                                                                   expr.span) {
+                                                                   Some(expr.span)) {
                                         Success(e) => {
                                             if let Some(def_type) = e.def {
                                                 def = def_type;
@@ -3274,18 +3263,12 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
             ast::Visibility::Public => return ty::Visibility::Public,
             ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
             ast::Visibility::Restricted { ref path, id } => (path, id),
-            ast::Visibility::Inherited => {
-                let current_module =
-                    self.get_nearest_normal_module_parent_or_self(self.current_module);
-                let id =
-                    self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
-                return ty::Visibility::Restricted(id);
-            }
+            ast::Visibility::Inherited => return self.current_vis,
         };
 
         let segments: Vec<_> = path.segments.iter().map(|seg| seg.identifier.name).collect();
         let mut path_resolution = err_path_resolution();
-        let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, path.span) {
+        let vis = match self.resolve_module_path(&segments, DontUseLexicalScope, Some(path.span)) {
             Success(module) => {
                 let def = module.def.unwrap();
                 path_resolution = PathResolution::new(def);
@@ -3309,15 +3292,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
     }
 
     fn is_accessible(&self, vis: ty::Visibility) -> bool {
-        let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module);
-        let node_id = self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap();
-        vis.is_accessible_from(node_id, self)
-    }
-
-    fn check_privacy(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Span) {
-        if !self.is_accessible(binding.vis) {
-            self.privacy_errors.push(PrivacyError(span, name, binding));
-        }
+        vis.is_at_least(self.current_vis, self)
     }
 
     fn report_privacy_errors(&self) {
index e08a30e40d354fb0db482f545fbc0dce56c95834..8c6d89c29bde14f68b4d42c1e8d08d2b5b93de54 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use self::Determinacy::*;
 use self::ImportDirectiveSubclass::*;
 
 use Module;
@@ -36,25 +37,31 @@ pub fn resolve_imports(&mut self) {
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum Determinacy {
+    Determined,
+    Undetermined,
+}
+
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
-pub enum ImportDirectiveSubclass {
+pub enum ImportDirectiveSubclass<'a> {
     SingleImport {
         target: Name,
         source: Name,
-        type_determined: Cell<bool>,
-        value_determined: Cell<bool>,
+        value_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
+        type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
     },
     GlobImport { is_prelude: bool },
 }
 
-impl ImportDirectiveSubclass {
+impl<'a> ImportDirectiveSubclass<'a> {
     pub fn single(target: Name, source: Name) -> Self {
         SingleImport {
             target: target,
             source: source,
-            type_determined: Cell::new(false),
-            value_determined: Cell::new(false),
+            type_result: Cell::new(Err(Undetermined)),
+            value_result: Cell::new(Err(Undetermined)),
         }
     }
 }
@@ -63,11 +70,12 @@ pub fn single(target: Name, source: Name) -> Self {
 #[derive(Debug,Clone)]
 pub struct ImportDirective<'a> {
     pub id: NodeId,
+    parent: Module<'a>,
     module_path: Vec<Name>,
-    target_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
-    subclass: ImportDirectiveSubclass,
+    imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
+    subclass: ImportDirectiveSubclass<'a>,
     span: Span,
-    vis: ty::Visibility, // see note in ImportResolutionPerNamespace about how to use this
+    vis: Cell<ty::Visibility>,
 }
 
 impl<'a> ImportDirective<'a> {
@@ -132,119 +140,145 @@ fn binding(&self) -> Option<&'a NameBinding<'a>> {
             _ => None, // The binding could be shadowed by a single import, so it is not known.
         })
     }
+}
+
+impl<'a> Resolver<'a> {
+    fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace)
+                  -> &'a RefCell<NameResolution<'a>> {
+        *module.resolutions.borrow_mut().entry((name, ns))
+               .or_insert_with(|| self.arenas.alloc_name_resolution())
+    }
+
+    /// Attempts to resolve the supplied name in the given module for the given namespace.
+    /// If successful, returns the binding corresponding to the name.
+    /// Invariant: if `record_used` is `Some`, import resolution must be complete.
+    pub fn resolve_name_in_module(&mut self,
+                                  module: Module<'a>,
+                                  name: Name,
+                                  ns: Namespace,
+                                  allow_private_imports: bool,
+                                  record_used: Option<Span>)
+                                  -> ResolveResult<&'a NameBinding<'a>> {
+        self.populate_module_if_necessary(module);
+
+        let resolution = self.resolution(module, name, ns);
+        let resolution = match resolution.borrow_state() {
+            ::std::cell::BorrowState::Unused => resolution.borrow_mut(),
+            _ => return Failed(None), // This happens when there is a cycle of imports
+        };
+
+        let is_disallowed_private_import = |binding: &NameBinding| {
+            !allow_private_imports && !binding.is_pseudo_public() && binding.is_import()
+        };
+
+        if let Some(span) = record_used {
+            if let Some(binding) = resolution.binding {
+                if is_disallowed_private_import(binding) {
+                    return Failed(None);
+                }
+                self.record_use(name, ns, binding);
+                if !self.is_accessible(binding.vis) {
+                    self.privacy_errors.push(PrivacyError(span, name, binding));
+                }
+            }
+
+            return resolution.binding.map(Success).unwrap_or(Failed(None));
+        }
+
+        // If the resolution doesn't depend on glob definability, check privacy and return.
+        if let Some(result) = self.try_result(&resolution, ns) {
+            return result.and_then(|binding| {
+                if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) {
+                    Success(binding)
+                } else {
+                    Failed(None)
+                }
+            });
+        }
+
+        // Check if the globs are determined
+        for directive in module.globs.borrow().iter() {
+            if self.is_accessible(directive.vis.get()) {
+                if let Some(module) = directive.imported_module.get() {
+                    let result = self.resolve_name_in_module(module, name, ns, true, None);
+                    if let Indeterminate = result {
+                        return Indeterminate;
+                    }
+                } else {
+                    return Indeterminate;
+                }
+            }
+        }
+
+        Failed(None)
+    }
 
     // Returns Some(the resolution of the name), or None if the resolution depends
     // on whether more globs can define the name.
-    fn try_result(&self, ns: Namespace, allow_private_imports: bool)
+    fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace)
                   -> Option<ResolveResult<&'a NameBinding<'a>>> {
-        match self.binding {
+        match resolution.binding {
             Some(binding) if !binding.is_glob_import() =>
-                return Some(Success(binding)),
-            _ => {} // Items and single imports are not shadowable
+                return Some(Success(binding)), // Items and single imports are not shadowable.
+            _ => {}
         };
 
         // Check if a single import can still define the name.
-        match self.single_imports {
-            SingleImports::None => {},
+        match resolution.single_imports {
             SingleImports::AtLeastOne => return Some(Indeterminate),
-            SingleImports::MaybeOne(directive) => {
-                // If (1) we don't allow private imports, (2) no public single import can define
-                // the name, and (3) no public glob has defined the name, the resolution depends
-                // on whether more globs can define the name.
-                if !allow_private_imports && directive.vis != ty::Visibility::Public &&
-                   !self.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
-                    return None;
-                }
-
-                let target_module = match directive.target_module.get() {
-                    Some(target_module) => target_module,
+            SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
+                let module = match directive.imported_module.get() {
+                    Some(module) => module,
                     None => return Some(Indeterminate),
                 };
                 let name = match directive.subclass {
                     SingleImport { source, .. } => source,
                     GlobImport { .. } => unreachable!(),
                 };
-                match target_module.resolve_name(name, ns, false) {
+                match self.resolve_name_in_module(module, name, ns, true, None) {
                     Failed(_) => {}
                     _ => return Some(Indeterminate),
                 }
             }
+            SingleImports::MaybeOne(_) | SingleImports::None => {},
         }
 
-        self.binding.map(Success)
-    }
-}
-
-impl<'a> ::ModuleS<'a> {
-    fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
-        *self.resolutions.borrow_mut().entry((name, ns))
-             .or_insert_with(|| self.arenas.alloc_name_resolution())
+        resolution.binding.map(Success)
     }
 
-    pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
-                        -> ResolveResult<&'a NameBinding<'a>> {
-        let resolution = self.resolution(name, ns);
-        let resolution = match resolution.borrow_state() {
-            ::std::cell::BorrowState::Unused => resolution.borrow_mut(),
-            _ => return Failed(None), // This happens when there is a cycle of imports
-        };
-
-        if let Some(result) = resolution.try_result(ns, allow_private_imports) {
-            // If the resolution doesn't depend on glob definability, check privacy and return.
-            return result.and_then(|binding| {
-                let allowed = allow_private_imports || !binding.is_import() ||
-                                                       binding.is_pseudo_public();
-                if allowed { Success(binding) } else { Failed(None) }
-            });
-        }
-
-        // Check if the globs are determined
-        for directive in self.globs.borrow().iter() {
-            if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
-            match directive.target_module.get() {
-                None => return Indeterminate,
-                Some(target_module) => match target_module.resolve_name(name, ns, false) {
-                    Indeterminate => return Indeterminate,
-                    _ => {}
-                }
-            }
-        }
-
-        Failed(None)
-    }
-
-    pub fn add_import_directive(&self,
+    // Add an import directive to the current module.
+    pub fn add_import_directive(&mut self,
                                 module_path: Vec<Name>,
-                                subclass: ImportDirectiveSubclass,
+                                subclass: ImportDirectiveSubclass<'a>,
                                 span: Span,
                                 id: NodeId,
                                 vis: ty::Visibility) {
+        let current_module = self.current_module;
         let directive = self.arenas.alloc_import_directive(ImportDirective {
+            parent: current_module,
             module_path: module_path,
-            target_module: Cell::new(None),
+            imported_module: Cell::new(None),
             subclass: subclass,
             span: span,
             id: id,
-            vis: vis,
+            vis: Cell::new(vis),
         });
 
-        self.unresolved_imports.borrow_mut().push(directive);
+        self.indeterminate_imports.push(directive);
         match directive.subclass {
             SingleImport { target, .. } => {
                 for &ns in &[ValueNS, TypeNS] {
-                    self.resolution(target, ns).borrow_mut().single_imports
-                                                            .add_directive(directive);
+                    let mut resolution = self.resolution(current_module, target, ns).borrow_mut();
+                    resolution.single_imports.add_directive(directive);
                 }
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
             // which are not relevant to import resolution.
             GlobImport { is_prelude: true } => {}
-            GlobImport { .. } => self.globs.borrow_mut().push(directive),
+            GlobImport { .. } => self.current_module.globs.borrow_mut().push(directive),
         }
     }
-}
 
-impl<'a> Resolver<'a> {
     // Given a binding and an import directive that resolves to it,
     // return the corresponding binding defined by the import directive.
     fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
@@ -255,7 +289,7 @@ fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirectiv
                 directive: directive,
             },
             span: directive.span,
-            vis: directive.vis,
+            vis: directive.vis.get(),
         }
     }
 
@@ -291,7 +325,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
         // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
         // during which the resolution might end up getting re-defined via a glob cycle.
         let (new_binding, t) = {
-            let mut resolution = &mut *module.resolution(name, ns).borrow_mut();
+            let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
             let was_known = resolution.binding().is_some();
 
             let t = f(self, resolution);
@@ -305,9 +339,9 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
 
         // Define `new_binding` in `module`s glob importers.
         if new_binding.is_importable() && new_binding.is_pseudo_public() {
-            for &(importer, directive) in module.glob_importers.borrow_mut().iter() {
+            for directive in module.glob_importers.borrow_mut().iter() {
                 let imported_binding = self.import(new_binding, directive);
-                let _ = self.try_define(importer, name, ns, imported_binding);
+                let _ = self.try_define(directive.parent, name, ns, imported_binding);
             }
         }
 
@@ -315,14 +349,6 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
     }
 }
 
-struct ImportResolvingError<'a> {
-    /// Module where the error happened
-    source_module: Module<'a>,
-    import_directive: &'a ImportDirective<'a>,
-    span: Span,
-    help: String,
-}
-
 struct ImportResolver<'a, 'b: 'a> {
     resolver: &'a mut Resolver<'b>,
 }
@@ -355,55 +381,74 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
     // remain or unsuccessfully when no forward progress in resolving imports
     // is made.
 
+    fn set_current_module(&mut self, module: Module<'b>) {
+        self.current_module = module;
+        self.current_vis = ty::Visibility::Restricted({
+            let normal_module = self.get_nearest_normal_module_parent_or_self(module);
+            self.definitions.as_local_node_id(normal_module.def_id().unwrap()).unwrap()
+        });
+    }
+
     /// Resolves all imports for the crate. This method performs the fixed-
     /// point iteration.
     fn resolve_imports(&mut self) {
         let mut i = 0;
-        let mut prev_unresolved_imports = 0;
-        let mut errors = Vec::new();
+        let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
 
-        loop {
-            debug!("(resolving imports) iteration {}, {} imports left", i, self.unresolved_imports);
+        while self.indeterminate_imports.len() < prev_num_indeterminates {
+            prev_num_indeterminates = self.indeterminate_imports.len();
+            debug!("(resolving imports) iteration {}, {} imports left", i, prev_num_indeterminates);
 
-            // Attempt to resolve imports in all local modules.
-            for module in self.arenas.local_modules().iter() {
-                self.current_module = module;
-                self.resolve_imports_in_current_module(&mut errors);
-            }
+            let mut imports = Vec::new();
+            ::std::mem::swap(&mut imports, &mut self.indeterminate_imports);
 
-            if self.unresolved_imports == 0 {
-                debug!("(resolving imports) success");
-                for module in self.arenas.local_modules().iter() {
-                    self.finalize_resolutions_in(module, false);
+            for import in imports {
+                match self.resolve_import(&import) {
+                    Failed(_) => self.determined_imports.push(import),
+                    Indeterminate => self.indeterminate_imports.push(import),
+                    Success(()) => self.determined_imports.push(import),
                 }
-                break;
             }
 
-            if self.unresolved_imports == prev_unresolved_imports {
-                // resolving failed
-                // Report unresolved imports only if no hard error was already reported
-                // to avoid generating multiple errors on the same import.
-                // Imports that are still indeterminate at this point are actually blocked
-                // by errored imports, so there is no point reporting them.
-                for module in self.arenas.local_modules().iter() {
-                    self.finalize_resolutions_in(module, errors.len() == 0);
-                }
-                for e in errors {
-                    self.import_resolving_error(e)
-                }
-                break;
+            i += 1;
+        }
+
+        for module in self.arenas.local_modules().iter() {
+            self.finalize_resolutions_in(module);
+        }
+
+        let mut errors = false;
+        for i in 0 .. self.determined_imports.len() {
+            let import = self.determined_imports[i];
+            if let Failed(err) = self.finalize_import(import) {
+                errors = true;
+                let (span, help) = match err {
+                    Some((span, msg)) => (span, msg),
+                    None => (import.span, String::new()),
+                };
+
+                // If the error is a single failed import then create a "fake" import
+                // resolution for it so that later resolve stages won't complain.
+                self.import_dummy_binding(import);
+                let path = import_path_to_string(&import.module_path, &import.subclass);
+                let error = ResolutionError::UnresolvedImport(Some((&path, &help)));
+                resolve_error(self.resolver, span, error);
             }
+        }
 
-            i += 1;
-            prev_unresolved_imports = self.unresolved_imports;
+        // Report unresolved imports only if no hard error was already reported
+        // to avoid generating multiple errors on the same import.
+        if !errors {
+            if let Some(import) = self.indeterminate_imports.iter().next() {
+                let error = ResolutionError::UnresolvedImport(None);
+                resolve_error(self.resolver, import.span, error);
+            }
         }
     }
 
     // Define a "dummy" resolution containing a Def::Err as a placeholder for a
     // failed resolution
-    fn import_dummy_binding(&mut self,
-                            source_module: Module<'b>,
-                            directive: &'b ImportDirective<'b>) {
+    fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) {
         if let SingleImport { target, .. } = directive.subclass {
             let dummy_binding = self.arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Def(Def::Err),
@@ -412,51 +457,8 @@ fn import_dummy_binding(&mut self,
             });
             let dummy_binding = self.import(dummy_binding, directive);
 
-            let _ = self.try_define(source_module, target, ValueNS, dummy_binding.clone());
-            let _ = self.try_define(source_module, target, TypeNS, dummy_binding);
-        }
-    }
-
-    /// Resolves an `ImportResolvingError` into the correct enum discriminant
-    /// and passes that on to `resolve_error`.
-    fn import_resolving_error(&mut self, e: ImportResolvingError<'b>) {
-        // If the error is a single failed import then create a "fake" import
-        // resolution for it so that later resolve stages won't complain.
-        self.import_dummy_binding(e.source_module, e.import_directive);
-        let path = import_path_to_string(&e.import_directive.module_path,
-                                         &e.import_directive.subclass);
-        resolve_error(self.resolver,
-                      e.span,
-                      ResolutionError::UnresolvedImport(Some((&path, &e.help))));
-    }
-
-    /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_in_current_module(&mut self, errors: &mut Vec<ImportResolvingError<'b>>) {
-        let mut imports = Vec::new();
-        let mut unresolved_imports = self.current_module.unresolved_imports.borrow_mut();
-        ::std::mem::swap(&mut imports, &mut unresolved_imports);
-
-        for import_directive in imports {
-            match self.resolve_import(&import_directive) {
-                Failed(err) => {
-                    let (span, help) = match err {
-                        Some((span, msg)) => (span, format!(". {}", msg)),
-                        None => (import_directive.span, String::new()),
-                    };
-                    errors.push(ImportResolvingError {
-                        source_module: self.current_module,
-                        import_directive: import_directive,
-                        span: span,
-                        help: help,
-                    });
-                }
-                Indeterminate => unresolved_imports.push(import_directive),
-                Success(()) => {
-                    // Decrement the count of unresolved imports.
-                    assert!(self.unresolved_imports >= 1);
-                    self.unresolved_imports -= 1;
-                }
-            }
+            let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone());
+            let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding);
         }
     }
 
@@ -470,126 +472,164 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
                names_to_string(&directive.module_path),
                module_to_string(self.current_module));
 
-        let target_module = match directive.target_module.get() {
-            Some(module) => module,
-            _ => match self.resolve_module_path(&directive.module_path,
-                                                DontUseLexicalScope,
-                                                directive.span) {
+        self.set_current_module(directive.parent);
+
+        let module = if let Some(module) = directive.imported_module.get() {
+            module
+        } else {
+            let vis = directive.vis.get();
+            // For better failure detection, pretend that the import will not define any names
+            // while resolving its module path.
+            directive.vis.set(ty::Visibility::PrivateExternal);
+            let result =
+                self.resolve_module_path(&directive.module_path, DontUseLexicalScope, None);
+            directive.vis.set(vis);
+
+            match result {
                 Success(module) => module,
                 Indeterminate => return Indeterminate,
                 Failed(err) => return Failed(err),
-            },
+            }
         };
 
-        directive.target_module.set(Some(target_module));
-        let (source, target, value_determined, type_determined) = match directive.subclass {
-            SingleImport { source, target, ref value_determined, ref type_determined } =>
-                (source, target, value_determined, type_determined),
-            GlobImport { .. } => return self.resolve_glob_import(target_module, directive),
+        directive.imported_module.set(Some(module));
+        let (source, target, value_result, type_result) = match directive.subclass {
+            SingleImport { source, target, ref value_result, ref type_result } =>
+                (source, target, value_result, type_result),
+            GlobImport { .. } => {
+                self.resolve_glob_import(directive);
+                return Success(());
+            }
         };
 
-        // We need to resolve both namespaces for this to succeed.
-        let value_result = self.resolve_name_in_module(target_module, source, ValueNS, false, true);
-        let type_result = self.resolve_name_in_module(target_module, source, TypeNS, false, true);
-
-        let module = self.current_module;
-        let mut privacy_error = true;
-        for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined),
-                                           (TypeNS, &type_result, type_determined)] {
-            match *result {
-                Failed(..) if !determined.get() => {
-                    determined.set(true);
-                    self.update_resolution(module, target, ns, |_, resolution| {
+        let mut indeterminate = false;
+        for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
+            if let Err(Undetermined) = result.get() {
+                result.set({
+                    match self.resolve_name_in_module(module, source, ns, false, None) {
+                        Success(binding) => Ok(binding),
+                        Indeterminate => Err(Undetermined),
+                        Failed(_) => Err(Determined),
+                    }
+                });
+            } else {
+                continue
+            };
+
+            match result.get() {
+                Err(Undetermined) => indeterminate = true,
+                Err(Determined) => {
+                    self.update_resolution(directive.parent, target, ns, |_, resolution| {
                         resolution.single_imports.directive_failed()
                     });
                 }
-                Success(binding) if !binding.is_importable() => {
+                Ok(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
                     struct_span_err!(self.session, directive.span, E0253, "{}", &msg)
                         .span_label(directive.span, &format!("cannot be imported directly"))
                         .emit();
                     // Do not import this illegal binding. Import a dummy binding and pretend
                     // everything is fine
-                    self.import_dummy_binding(module, directive);
+                    self.import_dummy_binding(directive);
                     return Success(());
                 }
-                Success(binding) if !self.is_accessible(binding.vis) => {}
-                Success(binding) if !determined.get() => {
-                    determined.set(true);
+                Ok(binding) => {
                     let imported_binding = self.import(binding, directive);
-                    let conflict = self.try_define(module, target, ns, imported_binding);
+                    let conflict = self.try_define(directive.parent, target, ns, imported_binding);
                     if let Err(old_binding) = conflict {
                         let binding = &self.import(binding, directive);
-                        self.report_conflict(module, target, ns, binding, old_binding);
+                        self.report_conflict(directive.parent, target, ns, binding, old_binding);
                     }
-                    privacy_error = false;
                 }
-                Success(_) => privacy_error = false,
-                _ => {}
             }
         }
 
-        match (&value_result, &type_result) {
-            (&Indeterminate, _) | (_, &Indeterminate) => return Indeterminate,
-            (&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
+        if indeterminate { Indeterminate } else { Success(()) }
+    }
+
+    fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
+        self.set_current_module(directive.parent);
+
+        let ImportDirective { ref module_path, span, .. } = *directive;
+        let module_result = self.resolve_module_path(&module_path, DontUseLexicalScope, Some(span));
+        let module = match module_result {
+            Success(module) => module,
+            Indeterminate => return Indeterminate,
+            Failed(err) => return Failed(err),
+        };
+
+        let (name, value_result, type_result) = match directive.subclass {
+            SingleImport { source, ref value_result, ref type_result, .. } =>
+                (source, value_result.get(), type_result.get()),
+            GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
+                // Importing a module into itself is not allowed.
+                let msg = "Cannot glob-import a module into itself.".into();
+                return Failed(Some((directive.span, msg)));
+            }
+            GlobImport { .. } => return Success(()),
+        };
+
+        for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
+            if let Ok(binding) = result {
+                self.record_use(name, ns, binding);
+            }
+        }
+
+        if value_result.is_err() && type_result.is_err() {
+            let (value_result, type_result);
+            value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span));
+            type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span));
+
+            return if let (Failed(_), Failed(_)) = (value_result, type_result) {
+                let resolutions = module.resolutions.borrow();
+                let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
+                    if *n == name { return None; } // Never suggest the same name
                     match *resolution.borrow() {
-                        NameResolution { binding: Some(_), .. } => Some(name),
+                        NameResolution { binding: Some(_), .. } => Some(n),
                         NameResolution { single_imports: SingleImports::None, .. } => None,
-                        _ => Some(name),
+                        _ => Some(n),
                     }
                 });
-                let lev_suggestion = match find_best_match_for_name(names, &source.as_str(), None) {
+                let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) {
                     Some(name) => format!(". Did you mean to use `{}`?", name),
                     None => "".to_owned(),
                 };
-                let module_str = module_to_string(target_module);
+                let module_str = module_to_string(module);
                 let msg = if &module_str == "???" {
-                    format!("There is no `{}` in the crate root{}", source, lev_suggestion)
+                    format!("no `{}` in the root{}", name, lev_suggestion)
                 } else {
-                    format!("There is no `{}` in `{}`{}", source, module_str, lev_suggestion)
+                    format!("no `{}` in `{}`{}", name, module_str, lev_suggestion)
                 };
-                return Failed(Some((directive.span, msg)));
-            }
-            _ => (),
-        }
-
-        if privacy_error {
-            for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] {
-                let binding = match *result { Success(binding) => binding, _ => continue };
-                self.privacy_errors.push(PrivacyError(directive.span, source, binding));
-                let imported_binding = self.import(binding, directive);
-                let _ = self.try_define(module, target, ns, imported_binding);
+                Failed(Some((directive.span, msg)))
+            } else {
+                // `resolve_name_in_module` reported a privacy error.
+                self.import_dummy_binding(directive);
+                Success(())
             }
         }
 
-        match (&value_result, &type_result) {
-            (&Success(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, self) &&
-                                      self.is_accessible(binding.vis) => {
-                let msg = format!("`{}` is private, and cannot be reexported", source);
-                let note_msg = format!("consider marking `{}` as `pub` in the imported module",
-                                        source);
+        match (value_result, type_result) {
+            (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
+                let msg = format!("`{}` is private, and cannot be reexported", name);
+                let note_msg =
+                    format!("consider marking `{}` as `pub` in the imported module", name);
                 struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
                     .span_note(directive.span, &note_msg)
                     .emit();
             }
 
-            (_, &Success(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, self) &&
-                                      self.is_accessible(binding.vis) => {
+            (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
                 if binding.is_extern_crate() {
                     let msg = format!("extern crate `{}` is private, and cannot be reexported \
                                        (error E0364), consider declaring with `pub`",
-                                       source);
+                                       name);
                     self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
                 } else {
-                    let mut err = struct_span_err!(self.session, directive.span, E0365,
-                                                     "`{}` is private, and cannot be reexported",
-                                                     source);
-                    err.span_label(directive.span, &format!("reexport of private `{}`", source));
-                    err.note(&format!("consider declaring type or module `{}` with `pub`", source));
-                    err.emit();
+                    struct_span_err!(self.session, directive.span, E0365,
+                                     "`{}` is private, and cannot be reexported", name)
+                        .span_label(directive.span, &format!("reexport of private `{}`", name))
+                        .note(&format!("consider declaring type or module `{}` with `pub`", name))
+                        .emit();
                 }
             }
 
@@ -599,9 +639,9 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
         // Record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let def = match type_result.success().and_then(NameBinding::def) {
+        let def = match type_result.ok().and_then(NameBinding::def) {
             Some(def) => def,
-            None => value_result.success().and_then(NameBinding::def).unwrap(),
+            None => value_result.ok().and_then(NameBinding::def).unwrap(),
         };
         let path_resolution = PathResolution::new(def);
         self.def_map.insert(directive.id, path_resolution);
@@ -610,57 +650,46 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
         return Success(());
     }
 
-    // Resolves a glob import. Note that this function cannot fail; it either
-    // succeeds or bails out (as importing * from an empty module or a module
-    // that exports nothing is valid). target_module is the module we are
-    // actually importing, i.e., `foo` in `use foo::*`.
-    fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>)
-                           -> ResolveResult<()> {
-        if let Some(Def::Trait(_)) = target_module.def {
-            self.session.span_err(directive.span, "items in traits are not importable.");
-        }
+    fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
+        let module = directive.imported_module.get().unwrap();
+        self.populate_module_if_necessary(module);
 
-        let module = self.current_module;
-        if module.def_id() == target_module.def_id() {
-            // This means we are trying to glob import a module into itself, and it is a no-go
-            let msg = "Cannot glob-import a module into itself.".into();
-            return Failed(Some((directive.span, msg)));
+        if let Some(Def::Trait(_)) = module.def {
+            self.session.span_err(directive.span, "items in traits are not importable.");
         }
-        self.populate_module_if_necessary(target_module);
 
-        if let GlobImport { is_prelude: true } = directive.subclass {
-            self.prelude = Some(target_module);
-            return Success(());
+        if module.def_id() == directive.parent.def_id()  {
+            return;
+        } else if let GlobImport { is_prelude: true } = directive.subclass {
+            self.prelude = Some(module);
+            return;
         }
 
-        // Add to target_module's glob_importers
-        target_module.glob_importers.borrow_mut().push((module, directive));
+        // Add to module's glob_importers
+        module.glob_importers.borrow_mut().push(directive);
 
         // Ensure that `resolutions` isn't borrowed during `try_define`,
         // since it might get updated via a glob cycle.
-        let bindings = target_module.resolutions.borrow().iter().filter_map(|(name, resolution)| {
+        let bindings = module.resolutions.borrow().iter().filter_map(|(name, resolution)| {
             resolution.borrow().binding().map(|binding| (*name, binding))
         }).collect::<Vec<_>>();
         for ((name, ns), binding) in bindings {
             if binding.is_importable() && binding.is_pseudo_public() {
                 let imported_binding = self.import(binding, directive);
-                let _ = self.try_define(module, name, ns, imported_binding);
+                let _ = self.try_define(directive.parent, name, ns, imported_binding);
             }
         }
 
         // Record the destination of this import
-        if let Some(did) = target_module.def_id() {
+        if let Some(did) = module.def_id() {
             let resolution = PathResolution::new(Def::Mod(did));
             self.def_map.insert(directive.id, resolution);
         }
-
-        debug!("(resolving glob import) successfully resolved import");
-        return Success(());
     }
 
     // Miscellaneous post-processing, including recording reexports, reporting conflicts,
     // reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
-    fn finalize_resolutions_in(&mut self, module: Module<'b>, report_unresolved_imports: bool) {
+    fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         // Since import resolution is finished, globs will not define any more names.
         *module.globs.borrow_mut() = Vec::new();
 
@@ -708,13 +737,6 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>, report_unresolved_impo
                 self.export_map.insert(node_id, reexports);
             }
         }
-
-        if report_unresolved_imports {
-            for import in module.unresolved_imports.borrow().iter() {
-                resolve_error(self.resolver, import.span, ResolutionError::UnresolvedImport(None));
-                break;
-            }
-        }
     }
 }
 
index cb990ead8e81e94ae0de9f5982d8817517e2e9d6..f2d5b128d270533ed9ebea7ccf17788d29e367a0 100644 (file)
@@ -247,29 +247,49 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
             return
         }
 
+        let mut arg = OsString::new();
         let path = tmpdir.join("list");
-        let prefix = if self.sess.target.target.options.is_like_osx {
-            "_"
-        } else {
-            ""
-        };
-        let res = (|| -> io::Result<()> {
-            let mut f = BufWriter::new(File::create(&path)?);
-            for sym in &self.info.cdylib_exports {
-                writeln!(f, "{}{}", prefix, sym)?;
+
+        if self.sess.target.target.options.is_like_solaris {
+            let res = (|| -> io::Result<()> {
+                let mut f = BufWriter::new(File::create(&path)?);
+                writeln!(f, "{{\n  global:")?;
+                for sym in &self.info.cdylib_exports {
+                    writeln!(f, "    {};", sym)?;
+                }
+                writeln!(f, "\n  local:\n    *;\n}};")?;
+                Ok(())
+            })();
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write version script: {}", e));
             }
-            Ok(())
-        })();
-        if let Err(e) = res {
-            self.sess.fatal(&format!("failed to write lib.def file: {}", e));
-        }
-        let mut arg = OsString::new();
-        if self.sess.target.target.options.is_like_osx {
-            arg.push("-Wl,-exported_symbols_list,");
+
+            arg.push("-Wl,-M,");
+            arg.push(&path);
         } else {
-            arg.push("-Wl,--retain-symbols-file=");
+            let prefix = if self.sess.target.target.options.is_like_osx {
+                "_"
+            } else {
+                ""
+            };
+            let res = (|| -> io::Result<()> {
+                let mut f = BufWriter::new(File::create(&path)?);
+                for sym in &self.info.cdylib_exports {
+                    writeln!(f, "{}{}", prefix, sym)?;
+                }
+                Ok(())
+            })();
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to write lib.def file: {}", e));
+            }
+            if self.sess.target.target.options.is_like_osx {
+                arg.push("-Wl,-exported_symbols_list,");
+            } else {
+                arg.push("-Wl,--retain-symbols-file=");
+            }
+            arg.push(&path);
         }
-        arg.push(&path);
+
         self.cmd.arg(arg);
     }
 }
index af24a7b51176ccca97c67e3f167da966e33a44a4..52073359c0fd99ea331c08566d1a281303151598 100644 (file)
@@ -347,9 +347,11 @@ pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::
                 if let ty::TyTrait(..) = mt.ty.sty {
                     // This is "x = SomeTrait" being reduced from
                     // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
-                    span_err!(self.tcx.sess, span, E0033,
-                              "type `{}` cannot be dereferenced",
-                              self.ty_to_string(expected));
+                    let type_str = self.ty_to_string(expected);
+                    struct_span_err!(self.tcx.sess, span, E0033,
+                              "type `{}` cannot be dereferenced", type_str)
+                        .span_label(span, &format!("type `{}` cannot be dereferenced", type_str))
+                        .emit();
                     return false
                 }
             }
index fb78d3a37ca236404c5706916566637f1d3be83c..54e63497e6202debd71f51d8392dda6c2e4613d6 100644 (file)
@@ -161,6 +161,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
+                    .span_label(self.span, &format!("unsupported cast"))
                     .help("compare with zero instead")
                     .emit();
             }
index 18a7c7c8457043de80004199a7f45f90322b6573..5dae1a09bf410f7330a3786c8270b32fbc1b90ff 100644 (file)
@@ -224,6 +224,7 @@ fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+        v.reserve_exact(1);
         v.push(0);
         CString { inner: v.into_boxed_slice() }
     }
index 08aeb5fb8ccdeae96abf30a8569e9824dfc34856..c754d5b8359a9cc5b80beae763013b0443653fdd 100644 (file)
@@ -45,10 +45,10 @@ pub unsafe fn read(&self) {
         // We roughly maintain the deadlocking behavior by panicking to ensure
         // that this lock acquisition does not succeed.
         //
-        // We also check whether there this lock is already write locked. This
+        // We also check whether this lock is already write locked. This
         // is only possible if it was write locked by the current thread and
         // the implementation allows recursive locking. The POSIX standard
-        // doesn't require recursivly locking a rwlock to deadlock, but we can't
+        // doesn't require recursively locking a rwlock to deadlock, but we can't
         // allow that because it could lead to aliasing issues.
         if r == libc::EAGAIN {
             panic!("rwlock maximum reader count exceeded");
index 1223a01cbcb6f29fc0d14d04215597b02c5cd58b..44d2f158d20bbeadad7b5c28d289963c044e7258 100644 (file)
@@ -20,6 +20,7 @@
                                               //~| ERROR E0017
                                               //~| NOTE statics require immutable values
                                               //~| ERROR E0388
+                                              //~| NOTE cannot write data in a static definition
 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
                                              //~| NOTE statics require immutable values
                                              //~| ERROR E0017
index 946600013f33dbf536a9faebf9d1f199d5a3f339..d320bcd4d0f5536924c86f666d02a18426e07a77 100644 (file)
@@ -13,7 +13,13 @@ trait SomeTrait {
 }
 
 fn main() {
-    let trait_obj: &SomeTrait = SomeTrait; //~ ERROR E0425
-                                           //~^ ERROR E0038
-    let &invalid = trait_obj; //~ ERROR E0033
+    let trait_obj: &SomeTrait = SomeTrait;
+    //~^ ERROR E0425
+    //~| ERROR E0038
+    //~| method `foo` has no receiver
+    //~| NOTE the trait `SomeTrait` cannot be made into an object
+
+    let &invalid = trait_obj;
+    //~^ ERROR E0033
+    //~| NOTE type `&SomeTrait` cannot be dereferenced
 }
index f5fea77cf9639a001500ece7b31521280b88a88e..98b700984a707c5729a9fdeb6cb45266551a2426 100644 (file)
@@ -12,4 +12,5 @@ fn main () {
     struct Foo { a: bool };
 
     let f = Foo(); //~ ERROR E0423
+                   //~^ struct called like a function
 }
index 445d0c5f3edc0db383c7925cdc243d22b23eab57..911007113d3d64804a3c8ab51eb1fd4293ed4280 100644 (file)
@@ -14,7 +14,10 @@ impl Foo {
     fn bar(self) {}
 
     fn foo() {
-        self.bar(); //~ ERROR E0424
+        self.bar();
+        //~^ ERROR `self` is not available in a static method [E0424]
+        //~| NOTE not available in static method
+        //~| NOTE maybe a `self` argument is missing?
     }
 }
 
index 2eb4c2d3b5e044c44322fc4c66d858e618dfc8df..be21421cb0781a74eff288ce81f406e242a3b0b4 100644 (file)
@@ -10,6 +10,8 @@
 
 fn main () {
     loop {
-        break 'a; //~ ERROR E0426
+        break 'a;
+        //~^ ERROR E0426
+        //~| NOTE undeclared label `'a`
     }
 }
index f6cba15a0bff8db93981fe0ab791e9ef0a59a2c7..f687633d34d86c4cb59af93ee989fae152616a6f 100644 (file)
@@ -11,4 +11,5 @@
 fn main () {
     let foo = 42u32;
     const FOO : u32 = foo; //~ ERROR E0435
+    //~| NOTE non-constant used with constant
 }
index 7440a82773e7af4675c6cd91096b8dc38054e1e3..62ee8dc3464928fa3248504b3f0a5a7ce6cebe28 100644 (file)
@@ -12,6 +12,7 @@ trait Foo {}
 
 impl Foo for i32 {
     type Bar = bool; //~ ERROR E0437
+    //~| NOTE not a member of trait `Foo`
 }
 
 fn main () {
index b3d453072049e9db7f9ccb2a3a1942e3609d4b6c..f549d62aebfea1a98d496bf065d23a74cb322e69 100644 (file)
@@ -14,6 +14,7 @@ trait Foo {}
 
 impl Foo for i32 {
     const BAR: bool = true; //~ ERROR E0438
+        //~| NOTE not a member of trait `Foo`
 }
 
 fn main () {
diff --git a/src/test/compile-fail/E0441.rs b/src/test/compile-fail/E0441.rs
new file mode 100644 (file)
index 0000000..967ff64
--- /dev/null
@@ -0,0 +1,21 @@
+// 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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+extern "platform-intrinsic" {
+    fn x86_mm_adds_ep16(x: i16x8, y: i16x8) -> i16x8; //~ ERROR E0441
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0442.rs b/src/test/compile-fail/E0442.rs
new file mode 100644 (file)
index 0000000..ddd9270
--- /dev/null
@@ -0,0 +1,29 @@
+// 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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
+             i8, i8, i8, i8, i8, i8, i8, i8);
+#[repr(simd)]
+struct i32x4(i32, i32, i32, i32);
+#[repr(simd)]
+struct i64x2(i64, i64);
+
+extern "platform-intrinsic" {
+    fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2;
+    //~^ ERROR E0442
+    //~| ERROR E0442
+    //~| ERROR E0442
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0443.rs b/src/test/compile-fail/E0443.rs
new file mode 100644 (file)
index 0000000..24d1ee0
--- /dev/null
@@ -0,0 +1,23 @@
+// 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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+#[repr(simd)]
+struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64);
+
+extern "platform-intrinsic" {
+    fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i64x8; //~ ERROR E0443
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0444.rs b/src/test/compile-fail/E0444.rs
new file mode 100644 (file)
index 0000000..a424a3c
--- /dev/null
@@ -0,0 +1,21 @@
+// 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(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+struct f64x2(f64, f64);
+
+extern "platform-intrinsic" {
+    fn x86_mm_movemask_pd(x: f64x2, y: f64x2, z: f64x2) -> i32; //~ ERROR E0444
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0445.rs b/src/test/compile-fail/E0445.rs
new file mode 100644 (file)
index 0000000..6b360c6
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+trait Foo {
+    fn dummy(&self) { }
+}
+
+pub trait Bar : Foo {} //~ ERROR E0445
+pub struct Bar2<T: Foo>(pub T); //~ ERROR E0445
+pub fn foo<T: Foo> (t: T) {} //~ ERROR E0445
+
+fn main() {}
diff --git a/src/test/compile-fail/E0446.rs b/src/test/compile-fail/E0446.rs
new file mode 100644 (file)
index 0000000..c576661
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+mod Foo {
+    struct Bar(u32);
+
+    pub fn bar() -> Bar { //~ ERROR E0446
+        Bar(0)
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0449.rs b/src/test/compile-fail/E0449.rs
new file mode 100644 (file)
index 0000000..ac365db
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+struct Bar;
+
+trait Foo {
+    fn foo();
+}
+
+pub impl Bar {} //~ ERROR E0449
+
+pub impl Foo for Bar { //~ ERROR E0449
+    pub fn foo() {} //~ ERROR E0449
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0450.rs b/src/test/compile-fail/E0450.rs
new file mode 100644 (file)
index 0000000..3d76cb9
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+mod Bar {
+    pub struct Foo(isize);
+}
+
+fn main() {
+    let f = Bar::Foo(0); //~ ERROR E0450
+}
diff --git a/src/test/compile-fail/E0451.rs b/src/test/compile-fail/E0451.rs
new file mode 100644 (file)
index 0000000..9e4a871
--- /dev/null
@@ -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.
+
+mod Bar {
+    pub struct Foo {
+        pub a: isize,
+        b: isize,
+    }
+}
+
+fn main() {
+    let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451
+}
diff --git a/src/test/compile-fail/E0452.rs b/src/test/compile-fail/E0452.rs
new file mode 100644 (file)
index 0000000..1665bbd
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#![allow(foo = "")] //~ ERROR E0452
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0453.rs b/src/test/compile-fail/E0453.rs
new file mode 100644 (file)
index 0000000..629b373
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+#![forbid(non_snake_case)]
+
+#[allow(non_snake_case)] //~ ERROR E0453
+fn main() {
+}
diff --git a/src/test/compile-fail/E0454.rs b/src/test/compile-fail/E0454.rs
new file mode 100644 (file)
index 0000000..1439c31
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#[link(name = "")] extern {} //~ ERROR E0454
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0458.rs b/src/test/compile-fail/E0458.rs
new file mode 100644 (file)
index 0000000..21bedc6
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+#[link(kind = "wonderful_unicorn")] extern {} //~ ERROR E0458
+                                              //~^ ERROR E0459
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0459.rs b/src/test/compile-fail/E0459.rs
new file mode 100644 (file)
index 0000000..dc7ac71
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#[link(kind = "dylib")] extern {} //~ ERROR E0459
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0463.rs b/src/test/compile-fail/E0463.rs
new file mode 100644 (file)
index 0000000..3eff107
--- /dev/null
@@ -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.
+
+#![feature(plugin)]
+#![plugin(cookie_monster)] //~ ERROR E0463
+extern crate cake_is_a_lie;
+
+fn main() {
+}
index 3fd71f715647dc83379b51e0839aefff1f951b4d..530822f6c5bafb1c387cae483b780d8536be33e8 100644 (file)
@@ -71,6 +71,7 @@ fn copy_after_mut_borrow() {
     let _x = &mut a.x;
     //~^ NOTE borrow of `a.x` occurs here
     let _y = a.y; //~ ERROR cannot use
+    //~^ NOTE use of borrowed `a.x`
 }
 
 fn move_after_mut_borrow() {
@@ -141,6 +142,7 @@ fn copy_after_mut_borrow_nested() {
     let _x = &mut a.x.x;
     //~^ NOTE borrow of `a.x.x` occurs here
     let _y = a.y; //~ ERROR cannot use
+    //~^ NOTE use of borrowed `a.x.x`
 }
 
 fn move_after_mut_borrow_nested() {
index 05c531e91f128e66e025da7150d503a8cc06f297..7839fb45d1c34ebfb7adce6e6f1e71cbc7345808 100644 (file)
@@ -59,10 +59,12 @@ fn main()
     //~^ ERROR casting
     //~^^ HELP through a usize first
     let _ = 3_i32 as bool;
-    //~^ ERROR cannot cast as `bool`
+    //~^ ERROR cannot cast as `bool` [E0054]
+    //~| unsupported cast
     //~| HELP compare with zero
     let _ = E::A as bool;
-    //~^ ERROR cannot cast as `bool`
+    //~^ ERROR cannot cast as `bool` [E0054]
+    //~| unsupported cast
     //~| HELP compare with zero
     let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
 
index bcd2cd816ed4560817dd23a21d682fc710f0567d..220b255bde419e9371f58c092c2f31e63cd15ed3 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use spam::{ham, eggs};
-//~^ ERROR unresolved import `spam::eggs`. There is no `eggs` in `spam`
+use spam::{ham, eggs}; //~ ERROR unresolved import `spam::eggs` [E0432]
+                       //~^ no `eggs` in `spam`
 
 mod spam {
     pub fn ham() { }
index ff93cd0f0662436c00efd1e4e9946102c46eb0df..1ca1c060410adb1b44fecc132103d2fc78680000 100644 (file)
@@ -9,13 +9,14 @@
 // except according to those terms.
 
 use zed::bar;
-use zed::baz;
-//~^ ERROR unresolved import `zed::baz`. There is no `baz` in `zed`
+use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
+              //~^ no `baz` in `zed`. Did you mean to use `bar`?
 
 
 mod zed {
     pub fn bar() { println!("bar"); }
-    use foo; //~ ERROR unresolved import
+    use foo; //~ ERROR unresolved import `foo` [E0432]
+             //~^ no `foo` in the root
 }
 
 fn main() {
index 1f25bce209314e6fe5fb4b2ce31d6daa700c8cd9..f5b03f9b2e97158ec104827b6d7ed94ef9687cf4 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use baz::zed::bar;
-//~^ ERROR unresolved import `baz::zed::bar`. Could not find `zed` in `baz`
+use baz::zed::bar; //~ ERROR unresolved import `baz::zed::bar` [E0432]
+                   //~^ Could not find `zed` in `baz`
 
 mod baz {}
 mod zed {
index f76d12d93fdf68cf9227aa2c3a5e97bb792861d9..20943bd0ea0773f8737ad45f264f81af41f89756 100644 (file)
@@ -15,8 +15,8 @@
 use foo::bar;
 
 mod test {
-    use bar::foo;
-    //~^ ERROR unresolved import `bar::foo`. Maybe a missing `extern crate bar`?
+    use bar::foo; //~ ERROR unresolved import `bar::foo` [E0432]
+                  //~^ Maybe a missing `extern crate bar`?
 }
 
 fn main() {}
index 355be1562df2bdb555c5acaff7d0ee4d76ce5283..0059e92e07f07a8aa29ae13cfb8ff78e6395509e 100644 (file)
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 use a::f;
-use b::f;
-//~^ ERROR: unresolved import `b::f`. There is no `f` in `b`
+use b::f; //~ ERROR: unresolved import `b::f` [E0432]
+          //~^ no `f` in `b`
 
 mod a { pub fn f() {} }
 mod b { }
index f2d858391cea2ae5b10f0d298ec7318e5ef92ba1..dc09af0ada66f0cb03285baf96f3d8e2eeabbc61 100644 (file)
@@ -10,6 +10,7 @@
 
 // Testing that we don't fail abnormally after hitting the errors
 
-use unresolved::*; //~ ERROR unresolved import `unresolved::*`. Maybe a missing `extern crate unres
+use unresolved::*; //~ ERROR unresolved import `unresolved::*` [E0432]
+                   //~^ Maybe a missing `extern crate unresolved`?
 
 fn main() {}
index e3e56c7f97ad5ba400b76d5c622f5c694873b6db..8e3faca02b7d1cef64a9a6a1f959859f915f29c6 100644 (file)
@@ -13,5 +13,7 @@ enum Foo {
 }
 
 fn main() {
-    let f = Foo::Variant(42); //~ ERROR uses it like a function
+    let f = Foo::Variant(42);
+    //~^ ERROR uses it like a function
+    //~| struct called like a function
 }
index 2270ba594ad2bfc5439f1be512f89054bcad6648..15d5d2b80c31d0053eeb75ae2915cefecbce8a19 100644 (file)
@@ -13,5 +13,7 @@ enum Homura {
 }
 
 fn main() {
-    let homura = Homura::Madoka; //~ ERROR uses it like a function
+    let homura = Homura::Madoka;
+    //~^ ERROR uses it like a function
+    //~| struct called like a function
 }
index d7ec1ed67397fe939d1585dc32b60f535a8958f2..da92161967dbdc98921c9684174cbc913b757b45 100644 (file)
@@ -59,7 +59,9 @@ fn purr_louder() {
 impl cat {
   fn meow() {
     if self.whiskers > 3 {
-        //~^ ERROR: `self` is not available in a static method. Maybe a `self` argument is missing?
+        //~^ ERROR `self` is not available in a static method [E0424]
+        //~| NOTE not available in static method
+        //~| NOTE maybe a `self` argument is missing?
         println!("MEOW");
     }
   }
index 44b3ada97fea8c0de34029616bcd4a7101bfa23e..ceefd583a5ca6f1b22de8dd9c8403e625297ec08 100644 (file)
@@ -12,6 +12,7 @@ macro_rules! width(
     ($this:expr) => {
         $this.width.unwrap()
         //~^ ERROR cannot use `self.width` because it was mutably borrowed
+        //~| NOTE use of borrowed `*self`
     }
 );
 
index e4fae73b18991293ee9c9a7a1ada252ca7e276c5..0d684ec5ae19b4593f2a5b379857e62a989a09e1 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use m::f as x; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
+use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
+               //~^ no `f` in `m`
 
 mod m {}
 
index 71c7e6009655b7e514eb7d0241e9b7ed182fdb90..b0cfd8714fc028969d84f8515ac3372c587f8f7b 100644 (file)
@@ -9,8 +9,12 @@
 // except according to those terms.
 
 type Alias = ();
-use Alias::*; //~ ERROR Not a module
-use std::io::Result::*; //~ ERROR Not a module
+use Alias::*;
+//~^ ERROR unresolved import `Alias::*` [E0432]
+//~| Not a module `Alias`
+use std::io::Result::*;
+//~^ ERROR unresolved import `std::io::Result::*` [E0432]
+//~| Not a module `Result`
 
 trait T {}
 use T::*; //~ ERROR items in traits are not importable
index 22261d98a128c98260eaaffaae6ab491ce2638d7..d610e8b483798af81cf2c1df4a57f5054a925b72 100644 (file)
@@ -8,9 +8,11 @@
 // 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]
+use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
+              //~^ no `Foo` in `bar`
 mod bar {
-    use Foo; //~ ERROR There is no `Foo` in the crate root [E0432]
+    use Foo; //~ ERROR unresolved import `Foo` [E0432]
+             //~^ no `Foo` in the root
 }
 
 fn main() {}
index c2154e8a6c0b605ce78e135875aa19a2e414ecf9..7a36012925eed415f3c836f067946553e1bd9f33 100644 (file)
@@ -14,7 +14,8 @@ impl K for isize {} //~ ERROR: `K` is not a trait
                     //~| NOTE: not a trait
                     //~| NOTE: aliases cannot be used for traits
 
-use ImportError; //~ ERROR unresolved
+use ImportError; //~ ERROR unresolved import `ImportError` [E0432]
+                 //~^ no `ImportError` in the root
 impl ImportError for () {} // check that this is not an additional error (c.f. #35142)
 
 fn main() {}
index 318089b3030f613d227c84f4b4957a4194c7dc28..670b6bd46e7d82a88455b82ce017c47d8b7f590c 100644 (file)
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use self::*; //~ ERROR: unresolved import `self::*`. Cannot glob-import a module into itself.
+use self::*; //~ ERROR: unresolved import `self::*` [E0432]
+             //~^ Cannot glob-import a module into itself.
 
 mod foo {
-    use foo::*; //~ ERROR: unresolved import `foo::*`. Cannot glob-import a module into itself.
+    use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
+                //~^ Cannot glob-import a module into itself.
 
     mod bar {
         use super::bar::*;
-        //~^ ERROR: unresolved import `super::bar::*`. Cannot glob-import a module into itself.
+        //~^ ERROR: unresolved import `super::bar::*` [E0432]
+        //~| Cannot glob-import a module into itself.
     }
 
 }
index abf702204d16baef221f412b22dd0e3ecc0b8004..376e95312b8fbf6b1cc7df7034e1bf42cbae3edc 100644 (file)
@@ -25,12 +25,14 @@ pub fn foo() {}
 
 fn test1() {
     use bar::foo;
-    //~^ ERROR unresolved import `bar::foo`. There is no `foo` in `bar`
+    //~^ ERROR unresolved import `bar::foo` [E0432]
+    //~| no `foo` in `bar`
 }
 
 fn test2() {
     use bar::glob::foo;
-    //~^ ERROR unresolved import `bar::glob::foo`. There is no `foo` in `bar::glob`
+    //~^ ERROR unresolved import `bar::glob::foo` [E0432]
+    //~| no `foo` in `bar::glob`
 }
 
 #[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
index 89f38fa14344580d230d84e46deade7c27e52e32..b841717bd11d8c24675b93ae3d93d521e0228e20 100644 (file)
@@ -26,7 +26,8 @@ pub fn foo() {}
 
 fn test1() {
     use bar::gpriv;
-    //~^ ERROR unresolved import `bar::gpriv`. There is no `gpriv` in `bar`
+    //~^ ERROR unresolved import `bar::gpriv` [E0432]
+    //~| no `gpriv` in `bar`
 
     // This should pass because the compiler will insert a fake name binding
     // for `gpriv`
diff --git a/src/test/compile-fail/question-mark-type-infer.rs b/src/test/compile-fail/question-mark-type-infer.rs
new file mode 100644 (file)
index 0000000..e15c9af
--- /dev/null
@@ -0,0 +1,27 @@
+// 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(question_mark, question_mark_carrier)]
+
+// Test that type inference fails where there are multiple possible return types
+// for the `?` operator.
+
+fn f(x: &i32) -> Result<i32, ()> {
+    Ok(*x)
+}
+
+fn g() -> Result<Vec<i32>, ()> {
+    let l = [1, 2, 3, 4];
+    l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve
+}
+
+fn main() {
+    g();
+}
index 89350f16167603f3b9ae01c8409623e2f405feea..8c026df7d9754ea846ad63bd58e88db69de29964 100644 (file)
 fn broken() {
     let mut x = 3;
     let mut _y = vec!(&mut x);
+    //~^ NOTE borrow of `x` occurs here
+    //~| NOTE borrow of `x` occurs here
+    //~| NOTE borrow of `x` occurs here
     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
+        //~^ NOTE use of borrowed `x`
         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
+        //~^ NOTE use of borrowed `x`
         _y.push(&mut z); //~ ERROR `z` does not live long enough
+        //~^ NOTE does not live long enough
         x += 1; //~ ERROR cannot assign
+        //~^ NOTE assignment to borrowed `x` occurs here
     }
+    //~^ NOTE borrowed value only valid until here
 }
+//~^ NOTE borrowed value must be valid until here
 
 fn main() { }
index ed143fdff687f1098c884bcd077446c1d591938a..a23ac80fca62071490dc4cd51f015a08b94cffdb 100644 (file)
 mod a {
     extern crate collections;
     use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `self::collections`?
+    //~^ ERROR unresolved import `collections::HashMap` [E0432]
+    //~| Did you mean `self::collections`?
     mod b {
         use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+        //~^ ERROR unresolved import `collections::HashMap` [E0432]
+        //~| Did you mean `a::collections`?
         mod c {
             use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+            //~^ ERROR unresolved import `collections::HashMap` [E0432]
+            //~| Did you mean `a::collections`?
             mod d {
                 use collections::HashMap;
-//~^ ERROR unresolved import `collections::HashMap`. Did you mean `a::collections`?
+                //~^ ERROR unresolved import `collections::HashMap` [E0432]
+                //~| Did you mean `a::collections`?
             }
         }
     }
index f59caef4631361f546e077efd37784b1362605d9..7d11ff6c9b54dae32081a2b2dbce8192af15b75c 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::f; //~ ERROR unresolved import `super::f`. There are too many initial `super`s.
+use super::f; //~ ERROR unresolved import `super::f` [E0432]
+              //~^ There are too many initial `super`s.
 
 fn main() {
 }
index a11df776e06d3ba1e2dc6f0add3390d80a92da6b..9c0a2267d7cf89f758d492c7ad50fdda9938fd5b 100644 (file)
@@ -16,5 +16,4 @@ fn test_send<S: Send>() {}
 
 pub fn main() {
     test_send::<rand::ThreadRng>();
-    //~^ ERROR : std::marker::Send` is not satisfied
 }
index b60d19fcab4aac6152f28133e3d10ed40bded478..d1254f3f5241b98c134cb9136cfcaf37702c329c 100644 (file)
 
 // ignore-tidy-linelength
 
-use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern crate foo`?
+use foo::bar; //~ ERROR unresolved import `foo::bar` [E0432]
+              //~^ Maybe a missing `extern crate foo`?
 
-use bar::Baz as x; //~ ERROR unresolved import `bar::Baz`. There is no `Baz` in `bar`. Did you mean to use `Bar`?
+use bar::Baz as x; //~ ERROR unresolved import `bar::Baz` [E0432]
+                   //~^ no `Baz` in `bar`. Did you mean to use `Bar`?
 
-use food::baz; //~ ERROR unresolved import `food::baz`. There is no `baz` in `food`. Did you mean to use `bag`?
+use food::baz; //~ ERROR unresolved import `food::baz`
+               //~^ no `baz` in `food`. Did you mean to use `bag`?
 
-use food::{beens as Foo}; //~ ERROR unresolved import `food::beens`. There is no `beens` in `food`. Did you mean to use `beans`?
+use food::{beens as Foo}; //~ ERROR unresolved import `food::beens` [E0432]
+                          //~^ no `beens` in `food`. Did you mean to use `beans`?
 
 mod bar {
     pub struct Bar;
index 687cdba1542bdce4c9be2889ac2bd453bb5f7da9..a40fa2337214ee8f135294ad88c3c8672f463496 100644 (file)
 use use_from_trait_xc::Trait::CONST;
 //~^ ERROR `CONST` is not directly importable
 
-use use_from_trait_xc::Foo::new;
+use use_from_trait_xc::Foo::new; //~ ERROR struct `Foo` is private
 //~^ ERROR unresolved import `use_from_trait_xc::Foo::new`
 
-use use_from_trait_xc::Foo::C;
+use use_from_trait_xc::Foo::C; //~ ERROR struct `Foo` is private
 //~^ ERROR unresolved import `use_from_trait_xc::Foo::C`
 
 use use_from_trait_xc::Bar::new as bnew;
index 28e933bc7aa0a2d180e874f4e25c173214acfeff..58e37bbfa3ea7c7729d56545777f2aff02527e81 100644 (file)
 //~^ ERROR `C` is not directly importable
 
 use Foo::new;
-//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
+//~^ ERROR unresolved import `Foo::new` [E0432]
+//~| Not a module `Foo`
 
 use Foo::C2;
-//~^ ERROR unresolved import `Foo::C2`. Not a module `Foo`
+//~^ ERROR unresolved import `Foo::C2` [E0432]
+//~| Not a module `Foo`
 
 pub trait Trait {
     fn foo();
index 040db0255678d23e53830588314c9d3c861bb926..6df20d414a788f919f0744ecc45d00a67de60791 100644 (file)
 mod a {
     mod b {
         use self as A; //~ ERROR `self` imports are only allowed within a { } list
-        //~^ ERROR unresolved import `self`. There is no `self` in the crate root
-        use super as B; //~ ERROR unresolved import `super`. There is no `super` in the crate root
-        use super::{self as C}; //~ERROR unresolved import `super`. There is no `super` in the crate
+        //~^ ERROR unresolved import `self` [E0432]
+        //~| no `self` in the root
+        use super as B;
+        //~^ ERROR unresolved import `super` [E0432]
+        //~| no `super` in the root
+        use super::{self as C};
+        //~^ ERROR unresolved import `super` [E0432]
+        //~| no `super` in the root
     }
 }
 
index f2384912cdba31c924d5723f55a25a1a82d031dd..5f8842a521abd80d940d04e31a350abed4d6dcb5 100644 (file)
 
 mod foo {
     use self::{self};
-    //~^ ERROR unresolved import `self`. There is no `self` in the crate root
+    //~^ ERROR unresolved import `self` [E0432]
+    //~| no `self` in the root
 
     use super::{self};
-    //~^ ERROR unresolved import `super`. There is no `super` in the crate root
+    //~^ ERROR unresolved import `super` [E0432]
+    //~| no `super` in the root
 }
 
 fn main() {}
diff --git a/src/test/run-pass/try-operator-custom.rs b/src/test/run-pass/try-operator-custom.rs
new file mode 100644 (file)
index 0000000..577d19a
--- /dev/null
@@ -0,0 +1,73 @@
+// 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(question_mark, question_mark_carrier)]
+
+use std::ops::Carrier;
+
+enum MyResult<T, U> {
+    Awesome(T),
+    Terrible(U)
+}
+
+impl<U, V> Carrier for MyResult<U, V> {
+    type Success = U;
+    type Error = V;
+
+    fn from_success(u: U) -> MyResult<U, V> {
+        MyResult::Awesome(u)
+    }
+
+    fn from_error(e: V) -> MyResult<U, V> {
+        MyResult::Terrible(e)
+    }
+
+    fn translate<T>(self) -> T
+        where T: Carrier<Success=U, Error=V>
+    {
+        match self {
+            MyResult::Awesome(u) => T::from_success(u),
+            MyResult::Terrible(e) => T::from_error(e),
+        }
+    }
+}
+
+fn f(x: i32) -> Result<i32, String> {
+    if x == 0 {
+        Ok(42)
+    } else {
+        let y = g(x)?;
+        Ok(y)
+    }
+}
+
+fn g(x: i32) -> MyResult<i32, String> {
+    let _y = f(x - 1)?;
+    MyResult::Terrible("Hello".to_owned())
+}
+
+fn h() -> MyResult<i32, String> {
+    let a: Result<i32, &'static str> = Err("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn i() -> MyResult<i32, String> {
+    let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn main() {
+    assert!(f(0) == Ok(42));
+    assert!(f(10) == Err("Hello".to_owned()));
+    let _ = h();
+    let _ = i();
+}
index e91b8fb0967a82375043ae927362500b428f7cfe..876ae404bbaed54f6094d118017ae9b22cb11232 100644 (file)
@@ -24,6 +24,7 @@ pub fn check(_path: &Path, _bad: &mut bool) {}
 #[cfg(unix)]
 pub fn check(path: &Path, bad: &mut bool) {
     use std::fs;
+    use std::process::{Command, Stdio};
     use std::os::unix::prelude::*;
 
     super::walk(path,
@@ -37,8 +38,22 @@ pub fn check(path: &Path, bad: &mut bool) {
 
         let metadata = t!(fs::symlink_metadata(&file), &file);
         if metadata.mode() & 0o111 != 0 {
-            println!("binary checked into source: {}", file.display());
-            *bad = true;
+            let rel_path = file.strip_prefix(path).unwrap();
+            let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
+            let ret_code = Command::new("git")
+                                        .arg("ls-files")
+                                        .arg(&git_friendly_path)
+                                        .current_dir(path)
+                                        .stdout(Stdio::null())
+                                        .stderr(Stdio::null())
+                                        .status()
+                                        .unwrap_or_else(|e| {
+                                            panic!("could not run git ls-files: {}", e);
+                                        });
+            if ret_code.success() {
+                println!("binary checked into source: {}", file.display());
+                *bad = true;
+            }
         }
     })
 }