]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #34739 - therealbstern:ipv4unspec, r=alexcrichton
authorbors <bors@rust-lang.org>
Wed, 13 Jul 2016 02:11:02 +0000 (19:11 -0700)
committerGitHub <noreply@github.com>
Wed, 13 Jul 2016 02:11:02 +0000 (19:11 -0700)
Mark Ipv4Addr is_unspecified as stable and provide reference.

Per [#27709 (comment)](https://github.com/rust-lang/rust/issues/27709#issuecomment-231280999), no RFC is needed here.

IPv4 "unspecified" has been defined in [Stevens], and has been part of the IPv4 stack for quite some time.  This property should become stable, since this use of 0.0.0.0 is not going anywhere.

[Stevens][_UNIX Network Programming Volume 1, Second Edition_.  Stevens, W. Richard.  Prentice-Hall, 1998.  p. 891]

Please let me know if I got the rustdoc wrong or something.  I tried to be as terse as possible while still conveying the appropriate information.

This also has a slight impact on PR #34694, but that one came first, so this shouldn't block it, IMO.

106 files changed:
configure
src/doc/book/closures.md
src/doc/reference.md
src/liballoc/boxed.rs
src/libcollections/slice.rs
src/libcore/any.rs
src/libcore/cell.rs
src/libcore/intrinsics.rs
src/libcore/iter/mod.rs
src/libcore/ops.rs
src/librustc/cfg/construct.rs
src/librustc/hir/def.rs
src/librustc/hir/fold.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/pat_util.rs
src/librustc/hir/print.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/mem_categorization.rs
src/librustc/mir/repr.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/util/common.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/pattern.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_trans/_match.rs
src/librustc_trans/base.rs
src/librustc_trans/closure.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/debuginfo/create_scope_map.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/libstd/error.rs
src/libstd/fs.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/process.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/common/backtrace.rs
src/libstd/sys/common/poison.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/fs.rs
src/libsyntax/attr.rs
src/libsyntax/diagnostic_list.rs
src/stage0.txt
src/test/compile-fail-fulldeps/issue-18986.rs
src/test/compile-fail/E0163.rs [deleted file]
src/test/compile-fail/auxiliary/lint_stability.rs
src/test/compile-fail/empty-struct-braces-pat-1.rs
src/test/compile-fail/issue-16058.rs
src/test/compile-fail/issue-17001.rs
src/test/compile-fail/issue-17405.rs
src/test/compile-fail/issue-21449.rs
src/test/compile-fail/issue-22933-1.rs [new file with mode: 0644]
src/test/compile-fail/issue-22933-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-26459.rs
src/test/compile-fail/issue-27815.rs
src/test/compile-fail/issue-27831.rs
src/test/compile-fail/issue-32004.rs
src/test/compile-fail/issue-34209.rs [new file with mode: 0644]
src/test/compile-fail/issue-4736.rs
src/test/compile-fail/lexical-scopes.rs
src/test/compile-fail/lint-stability.rs
src/test/compile-fail/method-path-in-pattern.rs
src/test/compile-fail/qualified-path-params.rs
src/test/compile-fail/struct-pat-associated-path.rs [new file with mode: 0644]
src/test/compile-fail/trait-as-struct-constructor.rs
src/test/compile-fail/variant-size-differences.rs [new file with mode: 0644]
src/test/debuginfo/constant-debug-locs.rs
src/test/run-pass/issue34569.rs [new file with mode: 0644]
src/test/run-pass/std-sync-right-kind-impls.rs
src/tools/tidy/src/errors.rs
src/tools/tidy/src/features.rs

index 6451b87673f628c230d2686f3f7dc3773506bd10..16496eb89d4ca8ef1ec581fb60fbebc0d43af1f3 100755 (executable)
--- a/configure
+++ b/configure
@@ -637,10 +637,20 @@ valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
 valopt armv7-linux-androideabi-ndk "" "armv7-linux-androideabi NDK standalone path"
 valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
 valopt nacl-cross-path  "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!"
-valopt release-channel "dev" "the name of the release channel to build"
 valopt musl-root "/usr/local" "MUSL root installation directory"
 valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag"
 
+if [ -e ${CFG_SRC_DIR}.git ]
+then
+    valopt release-channel "dev" "the name of the release channel to build"
+else
+    # If we have no git directory then we are probably a tarball distribution
+    # and should default to stable channel - Issue 28322
+    probe CFG_GIT          git
+    msg "git: no git directory. Changing default release channel to stable"
+    valopt release-channel "stable" "the name of the release channel to build"
+fi
+
 # Used on systems where "cc" and "ar" are unavailable
 valopt default-linker "cc" "the default linker"
 valopt default-ar     "ar" "the default ar"
index e8c88b7db0699d1ebe03b1827c29c4607aac3dd2..666d0946ecc80a3eac3e25a9764bb34b097bd85b 100644 (file)
@@ -336,7 +336,7 @@ could annotate it on the function declaration:
 
 ```rust,ignore
 fn call_with_ref<'a, F>(some_closure:F) -> i32
-    where F: Fn(&'a 32) -> i32 {
+    where F: Fn(&'a i32) -> i32 {
 ```
 
 However this presents a problem with in our case. When you specify the explicit
@@ -350,7 +350,7 @@ of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax:
 
 ```ignore
 fn call_with_ref<F>(some_closure:F) -> i32
-    where F: for<'a> Fn(&'a 32) -> i32 {
+    where F: for<'a> Fn(&'a i32) -> i32 {
 ```
 
 This lets the Rust compiler find the minimum lifetime to invoke our closure and
index 59dbffd6e28e7e705f679cb59bd9454015c8c339..b3073f5e526033271c855588b8fb343d40d63bb5 100644 (file)
@@ -2633,7 +2633,7 @@ comma:
 
 There are several forms of struct expressions. A _struct expression_
 consists of the [path](#paths) of a [struct item](#structs), followed by
-a brace-enclosed list of one or more comma-separated name-value pairs,
+a brace-enclosed list of zero or more comma-separated name-value pairs,
 providing the field values of a new instance of the struct. A field name
 can be any identifier, and is separated from its value expression by a colon.
 The location denoted by a struct field is mutable if and only if the
@@ -2652,10 +2652,12 @@ The following are examples of struct expressions:
 
 ```
 # struct Point { x: f64, y: f64 }
+# struct NothingInMe { }
 # struct TuplePoint(f64, f64);
 # mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } }
 # struct Cookie; fn some_fn<T>(t: T) {}
 Point {x: 10.0, y: 20.0};
+NothingInMe {};
 TuplePoint(10.0, 20.0);
 let u = game::User {name: "Joe", age: 35, score: 100_000};
 some_fn::<Cookie>(Cookie);
index 51523ca8dc601126d8dafdb2a50d52cd103b962f..7ba5ca30941f476f01f7957325b1cd361ab43e27 100644 (file)
@@ -249,6 +249,14 @@ impl<T: ?Sized> Box<T> {
     /// This function is unsafe because improper use may lead to
     /// memory problems. For example, a double-free may occur if the
     /// function is called twice on the same raw pointer.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = Box::new(5);
+    /// let ptr = Box::into_raw(x);
+    /// let x = unsafe { Box::from_raw(ptr) };
+    /// ```
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
@@ -266,9 +274,8 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
     /// # Examples
     ///
     /// ```
-    /// let seventeen = Box::new(17);
-    /// let raw = Box::into_raw(seventeen);
-    /// let boxed_again = unsafe { Box::from_raw(raw) };
+    /// let x = Box::new(5);
+    /// let ptr = Box::into_raw(x);
     /// ```
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
@@ -399,6 +406,24 @@ impl Box<Any> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Attempt to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<Any>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let my_string = "Hello World".to_string();
+    ///     print_if_string(Box::new(my_string));
+    ///     print_if_string(Box::new(0i8));
+    /// }
+    /// ```
     pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
         if self.is::<T>() {
             unsafe {
@@ -419,6 +444,24 @@ impl Box<Any + Send> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Attempt to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<Any + Send>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let my_string = "Hello World".to_string();
+    ///     print_if_string(Box::new(my_string));
+    ///     print_if_string(Box::new(0i8));
+    /// }
+    /// ```
     pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
         <Box<Any>>::downcast(self).map_err(|s| unsafe {
             // reapply the Send marker
index cef8a33703b7a61aa58b4c6f0e6e07b695cb30b6..2c54dc13c8d0b6440494bf927138dfec7a6b06fd 100644 (file)
@@ -151,7 +151,6 @@ pub fn to_vec<T>(s: &[T]) -> Vec<T>
     }
 }
 
-/// Allocating extension methods for slices.
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
@@ -200,7 +199,18 @@ pub fn first(&self) -> Option<&T> {
         core_slice::SliceExt::first(self)
     }
 
-    /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
+    /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(first) = x.first_mut() {
+    ///     *first = 5;
+    /// }
+    /// assert_eq!(x, &[5, 1, 2]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn first_mut(&mut self) -> Option<&mut T> {
@@ -208,6 +218,17 @@ pub fn first_mut(&mut self) -> Option<&mut T> {
     }
 
     /// Returns the first and all the rest of the elements of a slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first() {
+    ///     assert_eq!(first, &0);
+    ///     assert_eq!(elements, &[1, 2]);
+    /// }
+    /// ```
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first(&self) -> Option<(&T, &[T])> {
@@ -215,6 +236,19 @@ pub fn split_first(&self) -> Option<(&T, &[T])> {
     }
 
     /// Returns the first and all the rest of the elements of a slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first_mut() {
+    ///     *first = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[3, 4, 5]);
+    /// ```
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
@@ -222,6 +256,17 @@ pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
     }
 
     /// Returns the last and all the rest of the elements of a slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last() {
+    ///     assert_eq!(last, &2);
+    ///     assert_eq!(elements, &[0, 1]);
+    /// }
+    /// ```
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last(&self) -> Option<(&T, &[T])> {
@@ -230,6 +275,19 @@ pub fn split_last(&self) -> Option<(&T, &[T])> {
     }
 
     /// Returns the last and all the rest of the elements of a slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last_mut() {
+    ///     *last = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[4, 5, 3]);
+    /// ```
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
@@ -254,6 +312,17 @@ pub fn last(&self) -> Option<&T> {
     }
 
     /// Returns a mutable pointer to the last item in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(last) = x.last_mut() {
+    ///     *last = 10;
+    /// }
+    /// assert_eq!(x, &[0, 1, 10]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn last_mut(&mut self) -> Option<&mut T> {
@@ -276,7 +345,18 @@ pub fn get(&self, index: usize) -> Option<&T> {
         core_slice::SliceExt::get(self, index)
     }
 
-    /// Returns a mutable reference to the element at the given index,
+    /// Returns a mutable reference to the element at the given index.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(elem) = x.get_mut(1) {
+    ///     *elem = 42;
+    /// }
+    /// assert_eq!(x, &[0, 42, 2]);
+    /// ```
     /// or `None` if the index is out of bounds
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -285,14 +365,37 @@ pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
     }
 
     /// Returns a pointer to the element at the given index, without doing
-    /// bounds checking.
+    /// bounds checking. So use it very carefully!
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    ///
+    /// unsafe {
+    ///     assert_eq!(x.get_unchecked(1), &2);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub unsafe fn get_unchecked(&self, index: usize) -> &T {
         core_slice::SliceExt::get_unchecked(self, index)
     }
 
-    /// Returns an unsafe mutable pointer to the element in index
+    /// Returns an unsafe mutable pointer to the element in index. So use it
+    /// very carefully!
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    ///
+    /// unsafe {
+    ///     let elem = x.get_unchecked_mut(1);
+    ///     *elem = 13;
+    /// }
+    /// assert_eq!(x, &[1, 13, 4]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
@@ -306,6 +409,19 @@ pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
     ///
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let x_ptr = x.as_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn as_ptr(&self) -> *const T {
@@ -319,6 +435,20 @@ pub fn as_ptr(&self) -> *const T {
     ///
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// let x_ptr = x.as_mut_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         *x_ptr.offset(i as isize) += 2;
+    ///     }
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn as_mut_ptr(&mut self) -> *mut T {
@@ -336,7 +466,7 @@ pub fn as_mut_ptr(&mut self) -> *mut T {
     ///
     /// Panics if `a` or `b` are out of bounds.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```rust
     /// let mut v = ["a", "b", "c", "d"];
@@ -365,13 +495,39 @@ pub fn reverse(&mut self) {
     }
 
     /// Returns an iterator over the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let mut iterator = x.iter();
+    ///
+    /// assert_eq!(iterator.next(), Some(&1));
+    /// assert_eq!(iterator.next(), Some(&2));
+    /// assert_eq!(iterator.next(), Some(&4));
+    /// assert_eq!(iterator.next(), None);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn iter(&self) -> Iter<T> {
         core_slice::SliceExt::iter(self)
     }
 
-    /// Returns an iterator that allows modifying each value
+    /// Returns an iterator that allows modifying each value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// {
+    ///     let iterator = x.iter_mut();
+    ///
+    ///     for elem in iterator {
+    ///         *elem += 2;
+    ///     }
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn iter_mut(&mut self) -> IterMut<T> {
@@ -419,6 +575,7 @@ pub fn windows(&self, size: usize) -> Windows<T> {
     ///
     /// ```rust
     /// let v = &[1, 2, 3, 4, 5];
+    ///
     /// for chunk in v.chunks(2) {
     ///     println!("{:?}", chunk);
     /// }
@@ -437,6 +594,21 @@ pub fn chunks(&self, size: usize) -> Chunks<T> {
     /// # Panics
     ///
     /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 3]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
@@ -477,7 +649,7 @@ pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
     ///
     /// Panics if `mid > len`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```rust
     /// let mut v = [1, 2, 3, 4, 5, 6];
@@ -508,7 +680,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred`.  The matched element is not contained in the subslices.
+    /// `pred`. The matched element is not contained in the subslices.
     ///
     /// # Examples
     ///
@@ -517,6 +689,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
+    ///
     /// for group in v.split(|num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
@@ -530,7 +703,18 @@ pub fn split<F>(&self, pred: F) -> Split<T, F>
     }
 
     /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`.  The matched element is not contained in the subslices.
+    /// match `pred`. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.split_mut(|num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 1]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
@@ -553,6 +737,7 @@ pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
+    ///
     /// for group in v.splitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
@@ -571,6 +756,17 @@ pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F>
     ///
     /// The last element returned, if any, will contain the remainder of the
     /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.splitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 50]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
@@ -594,6 +790,7 @@ pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
+    ///
     /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
@@ -613,6 +810,17 @@ pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F>
     ///
     /// The last element returned, if any, will contain the remainder of the
     /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut s = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(s, [1, 40, 30, 20, 60, 1]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F>
@@ -848,7 +1056,7 @@ pub fn sort_by<F>(&mut self, compare: F)
 
     /// Copies the elements from `src` into `self`.
     ///
-    /// The length of this slice must be the same as the slice passed in.
+    /// The length of `src` must be the same as `self`.
     ///
     /// # Panics
     ///
@@ -892,6 +1100,14 @@ pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
 
 
     /// Copies `self` into a new `Vec`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = [10, 40, 30];
+    /// let x = s.to_vec();
+    /// // Here, `s` and `x` can be modified independently.
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_vec(&self) -> Vec<T>
@@ -902,6 +1118,16 @@ pub fn to_vec(&self) -> Vec<T>
     }
 
     /// Converts `self` into a vector without clones or allocation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s: Box<[i32]> = Box::new([10, 40, 30]);
+    /// let x = s.into_vec();
+    /// // `s` cannot be used anymore because it has been converted into `x`.
+    ///
+    /// assert_eq!(x, vec!(10, 40, 30));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn into_vec(self: Box<Self>) -> Vec<T> {
index 49304b1f3bfa17d23e632189bfbf942419658292..a452be2565b655e14597eed0116d65386bc53210 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Any: Reflect + 'static {
     /// Gets the `TypeId` of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(get_type_id)]
+    ///
+    /// use std::any::{Any, TypeId};
+    ///
+    /// fn is_string(s: &Any) -> bool {
+    ///     TypeId::of::<String>() == s.get_type_id()
+    /// }
+    ///
+    /// fn main() {
+    ///     assert_eq!(is_string(&0), false);
+    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
+    /// }
+    /// ```
     #[unstable(feature = "get_type_id",
                reason = "this method will likely be replaced by an associated static",
                issue = "27745")]
@@ -125,7 +142,26 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl Any {
-    /// Returns true if the boxed type is the same as `T`
+    /// Returns true if the boxed type is the same as `T`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn is_string(s: &Any) {
+    ///     if s.is::<String>() {
+    ///         println!("It's a string!");
+    ///     } else {
+    ///         println!("Not a string...");
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     is_string(&0);
+    ///     is_string(&"cookie monster".to_owned());
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is<T: Any>(&self) -> bool {
@@ -141,6 +177,25 @@ pub fn is<T: Any>(&self) -> bool {
 
     /// Returns some reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(s: &Any) {
+    ///     if let Some(string) = s.downcast_ref::<String>() {
+    ///         println!("It's a string({}): '{}'", string.len(), string);
+    ///     } else {
+    ///         println!("Not a string...");
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     print_if_string(&0);
+    ///     print_if_string(&"cookie monster".to_owned());
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
@@ -159,6 +214,29 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
 
     /// Returns some mutable reference to the boxed value if it is of type `T`, or
     /// `None` if it isn't.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn modify_if_u32(s: &mut Any) {
+    ///     if let Some(num) = s.downcast_mut::<u32>() {
+    ///         *num = 42;
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let mut x = 10u32;
+    ///     let mut s = "starlord".to_owned();
+    ///
+    ///     modify_if_u32(&mut x);
+    ///     modify_if_u32(&mut s);
+    ///
+    ///     assert_eq!(x, 42);
+    ///     assert_eq!(&s, "starlord");
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
@@ -178,6 +256,25 @@ pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
 
 impl Any+Send {
     /// Forwards to the method defined on the type `Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn is_string(s: &(Any + Send)) {
+    ///     if s.is::<String>() {
+    ///         println!("It's a string!");
+    ///     } else {
+    ///         println!("Not a string...");
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     is_string(&0);
+    ///     is_string(&"cookie monster".to_owned());
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is<T: Any>(&self) -> bool {
@@ -185,6 +282,25 @@ pub fn is<T: Any>(&self) -> bool {
     }
 
     /// Forwards to the method defined on the type `Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(s: &(Any + Send)) {
+    ///     if let Some(string) = s.downcast_ref::<String>() {
+    ///         println!("It's a string({}): '{}'", string.len(), string);
+    ///     } else {
+    ///         println!("Not a string...");
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     print_if_string(&0);
+    ///     print_if_string(&"cookie monster".to_owned());
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
@@ -192,6 +308,29 @@ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
     }
 
     /// Forwards to the method defined on the type `Any`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn modify_if_u32(s: &mut (Any+ Send)) {
+    ///     if let Some(num) = s.downcast_mut::<u32>() {
+    ///         *num = 42;
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let mut x = 10u32;
+    ///     let mut s = "starlord".to_owned();
+    ///
+    ///     modify_if_u32(&mut x);
+    ///     modify_if_u32(&mut s);
+    ///
+    ///     assert_eq!(x, 42);
+    ///     assert_eq!(&s, "starlord");
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
@@ -220,7 +359,24 @@ pub struct TypeId {
 
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been
-    /// instantiated with
+    /// instantiated with.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(get_type_id)]
+    ///
+    /// use std::any::{Any, TypeId};
+    ///
+    /// fn is_string(s: &Any) -> bool {
+    ///     TypeId::of::<String>() == s.get_type_id()
+    /// }
+    ///
+    /// fn main() {
+    ///     assert_eq!(is_string(&0), false);
+    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
         TypeId {
index 9435be3b0124b60bfb1fd36be9842558548ba449..65cb1aaaff6fd1e729d0e9a4ceb9a09ca57269a8 100644 (file)
@@ -237,6 +237,17 @@ pub fn as_unsafe_cell(&self) -> &UnsafeCell<T> {
     ///
     /// This call borrows `Cell` mutably (at compile-time) which guarantees
     /// that we possess the only reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cell::Cell;
+    ///
+    /// let mut c = Cell::new(5);
+    /// *c.get_mut() += 1;
+    ///
+    /// assert_eq!(c.get(), 6);
+    /// ```
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
@@ -388,6 +399,22 @@ impl<T: ?Sized> RefCell<T> {
     ///
     /// The returned value can be dispatched on to determine if a call to
     /// `borrow` or `borrow_mut` would succeed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(borrow_state)]
+    ///
+    /// use std::cell::{BorrowState, RefCell};
+    ///
+    /// let c = RefCell::new(5);
+    ///
+    /// match c.borrow_state() {
+    ///     BorrowState::Writing => println!("Cannot be borrowed"),
+    ///     BorrowState::Reading => println!("Cannot be borrowed mutably"),
+    ///     BorrowState::Unused => println!("Can be borrowed (mutably as well)"),
+    /// }
+    /// ```
     #[unstable(feature = "borrow_state", issue = "27733")]
     #[inline]
     pub fn borrow_state(&self) -> BorrowState {
@@ -498,6 +525,17 @@ pub fn borrow_mut(&self) -> RefMut<T> {
     /// This can be used to circumvent `RefCell`'s safety checks.
     ///
     /// This function is `unsafe` because `UnsafeCell`'s field is public.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(as_unsafe_cell)]
+    ///
+    /// use std::cell::RefCell;
+    ///
+    /// let c = RefCell::new(5);
+    /// let c = unsafe { c.as_unsafe_cell() };
+    /// ```
     #[inline]
     #[unstable(feature = "as_unsafe_cell", issue = "27708")]
     pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell<T> {
@@ -508,6 +546,17 @@ pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell<T> {
     ///
     /// This call borrows `RefCell` mutably (at compile-time) so there is no
     /// need for dynamic checks.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cell::RefCell;
+    ///
+    /// let mut c = RefCell::new(5);
+    /// *c.get_mut() += 1;
+    ///
+    /// assert_eq!(c, RefCell::new(6));
+    /// ```
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
index edb965c1962e3bf6433b487165f8d164c39616e4..1bdcc5bfe119dcce59a62e6fa9d4fe396d57d761 100644 (file)
     /// that `rustc_peek(potentially_uninitialized)` would actually
     /// double-check that dataflow did indeed compute that it is
     /// uninitialized at that point in the control flow.
-    #[cfg(not(stage0))]
     pub fn rustc_peek<T>(_: T) -> T;
 
     /// Aborts the execution of the process.
index dffe9dee022a68704fc565efa10467bc56c2725b..d2de0d46d746ba452c7d3aab0f8d0383b3109f22 100644 (file)
@@ -1244,39 +1244,6 @@ pub fn peek(&mut self) -> Option<&I::Item> {
             None => None,
         }
     }
-
-    /// Checks if the iterator has finished iterating.
-    ///
-    /// Returns `true` if there are no more elements in the iterator, and
-    /// `false` if there are.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// #![feature(peekable_is_empty)]
-    ///
-    /// let xs = [1, 2, 3];
-    ///
-    /// let mut iter = xs.iter().peekable();
-    ///
-    /// // There are still elements to iterate over
-    /// assert_eq!(iter.is_empty(), false);
-    ///
-    /// // Let's consume the iterator
-    /// iter.next();
-    /// iter.next();
-    /// iter.next();
-    ///
-    /// assert_eq!(iter.is_empty(), true);
-    /// ```
-    #[unstable(feature = "peekable_is_empty", issue = "32111")]
-    #[inline]
-    #[rustc_deprecated(since = "1.10.0", reason = "replaced by .peek().is_none()")]
-    pub fn is_empty(&mut self) -> bool {
-        self.peek().is_none()
-    }
 }
 
 /// An iterator that rejects elements while `predicate` is true.
index 7753aae147a88d722d532d7198e1d52bf7b3e9cd..9347ac2a8c82f0eb40d953f9318c39018ee72fa7 100644 (file)
@@ -1929,7 +1929,7 @@ pub trait FnMut<Args> : FnOnce<Args> {
 #[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
-    #[unstable(feature = "fn_traits", issue = "29625")]
+    #[stable(feature = "fn_once_output", since = "1.12.0")]
     type Output;
 
     /// This is called when the call operator is used.
index 18ea17f48162f1b66c168c00d3246d8b9b7712b3..601d3866b02d452be8808bcb3db6c936fa03d771 100644 (file)
@@ -101,7 +101,6 @@ fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
         match pat.node {
             PatKind::Binding(_, _, None) |
             PatKind::Path(..) |
-            PatKind::QPath(..) |
             PatKind::Lit(..) |
             PatKind::Range(..) |
             PatKind::Wild => {
index 72261c473e5c5d6a252733f988b43956f681ef78..218681efb7dc167d033b1da220acc94b901bd215 100644 (file)
@@ -137,15 +137,6 @@ pub fn def_id(&self) -> DefId {
         }
     }
 
-    pub fn variant_def_ids(&self) -> Option<(DefId, DefId)> {
-        match *self {
-            Def::Variant(enum_id, var_id) => {
-                Some((enum_id, var_id))
-            }
-            _ => None
-        }
-    }
-
     pub fn kind_name(&self) -> &'static str {
         match *self {
             Def::Fn(..) => "function",
index 78fd2bbbe0d2590e033ea4d87da820c69aad227f..5e0e6622185f8b50336cc4409b033a5be0f4793b 100644 (file)
@@ -930,12 +930,11 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                     PatKind::TupleStruct(folder.fold_path(pth),
                             pats.move_map(|x| folder.fold_pat(x)), ddpos)
                 }
-                PatKind::Path(pth) => {
-                    PatKind::Path(folder.fold_path(pth))
-                }
-                PatKind::QPath(qself, pth) => {
-                    let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself };
-                    PatKind::QPath(qself, folder.fold_path(pth))
+                PatKind::Path(opt_qself, pth) => {
+                    let opt_qself = opt_qself.map(|qself| {
+                        QSelf { ty: folder.fold_ty(qself.ty), position: qself.position }
+                    });
+                    PatKind::Path(opt_qself, folder.fold_path(pth))
                 }
                 PatKind::Struct(pth, fields, etc) => {
                     let pth = folder.fold_path(pth);
index 2d5c4ebf8d898bbc3bf0bff24f945a712f48045c..442c85af22a262967f707484de232e8b06c443ef 100644 (file)
@@ -460,11 +460,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
             visitor.visit_path(path, pattern.id);
             walk_list!(visitor, visit_pat, children);
         }
-        PatKind::Path(ref path) => {
-            visitor.visit_path(path, pattern.id);
-        }
-        PatKind::QPath(ref qself, ref path) => {
-            visitor.visit_ty(&qself.ty);
+        PatKind::Path(ref opt_qself, ref path) => {
+            if let Some(ref qself) = *opt_qself {
+                visitor.visit_ty(&qself.ty);
+            }
             visitor.visit_path(path, pattern.id)
         }
         PatKind::Struct(ref path, ref fields, _) => {
index 2cc39412182dc5a771417a8f7e714cdf6cad4a3d..9d124dadb766adb911324f8a5cdc78f1eed57e38 100644 (file)
@@ -862,7 +862,8 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                                                       respan(pth1.span, pth1.node.name),
                                                       sub.as_ref().map(|x| this.lower_pat(x)))
                             }
-                            _ => hir::PatKind::Path(hir::Path::from_name(pth1.span, pth1.node.name))
+                            _ => hir::PatKind::Path(None, hir::Path::from_name(pth1.span,
+                                                                               pth1.node.name))
                         }
                     })
                 }
@@ -872,15 +873,11 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                                               pats.iter().map(|x| self.lower_pat(x)).collect(),
                                               ddpos)
                 }
-                PatKind::Path(None, ref pth) => {
-                    hir::PatKind::Path(self.lower_path(pth))
-                }
-                PatKind::Path(Some(ref qself), ref pth) => {
-                    let qself = hir::QSelf {
-                        ty: self.lower_ty(&qself.ty),
-                        position: qself.position,
-                    };
-                    hir::PatKind::QPath(qself, self.lower_path(pth))
+                PatKind::Path(ref opt_qself, ref path) => {
+                    let opt_qself = opt_qself.as_ref().map(|qself| {
+                        hir::QSelf { ty: self.lower_ty(&qself.ty), position: qself.position }
+                    });
+                    hir::PatKind::Path(opt_qself, self.lower_path(path))
                 }
                 PatKind::Struct(ref pth, ref fields, etc) => {
                     let pth = self.lower_path(pth);
@@ -1831,7 +1828,7 @@ fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::
                 -> P<hir::Pat> {
         let def = self.resolver.resolve_generated_global_path(&path, true);
         let pt = if subpats.is_empty() {
-            hir::PatKind::Path(path)
+            hir::PatKind::Path(None, path)
         } else {
             hir::PatKind::TupleStruct(path, subpats, None)
         };
index e1e681b7aff3541e3a8fe2c2589d85aca9128ada..655f80ec07238ff9ba97fdb99057415fd6dec35b 100644 (file)
@@ -487,8 +487,7 @@ fn walk_<G>(&self, it: &mut G) -> bool
             PatKind::Lit(_) |
             PatKind::Range(_, _) |
             PatKind::Binding(..) |
-            PatKind::Path(..) |
-            PatKind::QPath(_, _) => {
+            PatKind::Path(..) => {
                 true
             }
         }
@@ -538,15 +537,9 @@ pub enum PatKind {
     /// 0 <= position <= subpats.len()
     TupleStruct(Path, HirVec<P<Pat>>, Option<usize>),
 
-    /// A path pattern.
+    /// A possibly qualified path pattern.
     /// Such pattern can be resolved to a unit struct/variant or a constant.
-    Path(Path),
-
-    /// An associated const named using the qualified path `<T>::CONST` or
-    /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
-    /// referred to as simply `T::CONST`, in which case they will end up as
-    /// PatKind::Path, and the resolver will have to sort that out.
-    QPath(QSelf, Path),
+    Path(Option<QSelf>, Path),
 
     /// A tuple pattern `(a, b)`.
     /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
index 3bb9b6d260255065bee28fc7986777812297d13e..593d10ef4f7c4a9910c020b9a4218dc5f345fbba 100644 (file)
 use hir::def_id::DefId;
 use hir::{self, PatKind};
 use ty::TyCtxt;
-use util::nodemap::FnvHashMap;
 use syntax::ast;
 use syntax::codemap::Spanned;
 use syntax_pos::{Span, DUMMY_SP};
 
 use std::iter::{Enumerate, ExactSizeIterator};
 
-pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
-
 pub struct EnumerateAndAdjust<I> {
     enumerate: Enumerate<I>,
     gap_pos: usize,
@@ -56,7 +53,7 @@ fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
 
 pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,
+        PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::Path(Some(..), _) => true,
         PatKind::TupleStruct(..) |
         PatKind::Path(..) |
         PatKind::Struct(..) => {
@@ -70,23 +67,9 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     }
 }
 
-pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
-    match pat.node {
-        PatKind::TupleStruct(..) |
-        PatKind::Path(..) |
-        PatKind::Struct(..) => {
-            match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Variant(..)) | Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => true,
-                _ => false
-            }
-        }
-        _ => false
-    }
-}
-
 pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        PatKind::Path(..) | PatKind::QPath(..) => {
+        PatKind::Path(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
                 Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
@@ -96,22 +79,6 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     }
 }
 
-// Same as above, except that partially-resolved defs cause `false` to be
-// returned instead of a panic.
-pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
-    match pat.node {
-        PatKind::Path(..) | PatKind::QPath(..) => {
-            match dm.get(&pat.id)
-                    .and_then(|d| if d.depth == 0 { Some(d.base_def) }
-                                  else { None } ) {
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
-                _ => false
-            }
-        }
-        _ => false
-    }
-}
-
 /// Call `f` on every "binding" in a pattern, e.g., on `a` in
 /// `match foo() { Some(a) => (), None => () }`
 pub fn pat_bindings<F>(pat: &hir::Pat, mut f: F)
index bf6188faa2fbdf160d7c60032e0bb8613c186042..5f2fac5c01b30df8b719ef301e13cafde1a1cbbd 100644 (file)
@@ -1750,10 +1750,10 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
                 }
                 try!(self.pclose());
             }
-            PatKind::Path(ref path) => {
+            PatKind::Path(None, ref path) => {
                 self.print_path(path, true, 0)?;
             }
-            PatKind::QPath(ref qself, ref path) => {
+            PatKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?;
             }
             PatKind::Struct(ref path, ref fields, etc) => {
index 41086b5d1c990651cfdb774e595b3335ee5330a7..3230a08c27630bbbd4095a1792d24630265350a7 100644 (file)
     "unknown crate type found in #[crate_type] directive"
 }
 
-declare_lint! {
-    pub VARIANT_SIZE_DIFFERENCES,
-    Allow,
-    "detects enums with widely varying variant sizes"
-}
-
 declare_lint! {
     pub FAT_PTR_TRANSMUTES,
     Allow,
@@ -230,7 +224,6 @@ fn get_lints(&self) -> LintArray {
             UNUSED_FEATURES,
             STABLE_FEATURES,
             UNKNOWN_CRATE_TYPES,
-            VARIANT_SIZE_DIFFERENCES,
             FAT_PTR_TRANSMUTES,
             TRIVIAL_CASTS,
             TRIVIAL_NUMERIC_CASTS,
index 01e14ad71b39c8c0e7e1e384950b00cc1b046559..ce3d72de9ae99a5378cfbbf598833ae4e7cda408 100644 (file)
 use middle::privacy::AccessLevels;
 use ty::TyCtxt;
 use session::{config, early_error, Session};
-use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
-use lint::{EarlyLintPassObject, LateLintPass, LateLintPassObject};
+use lint::{Level, LevelSource, Lint, LintId, LintPass};
+use lint::{EarlyLintPassObject, LateLintPassObject};
 use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
 use util::nodemap::FnvHashMap;
 
-use std::cell::RefCell;
 use std::cmp;
 use std::default::Default as StdDefault;
 use std::mem;
@@ -311,10 +310,6 @@ pub struct LateContext<'a, 'tcx: 'a> {
     /// levels, this stack keeps track of the previous lint levels of whatever
     /// was modified.
     level_stack: Vec<(LintId, LevelSource)>,
-
-    /// Level of lints for certain NodeIds, stored here because the body of
-    /// the lint needs to run in trans.
-    node_levels: RefCell<FnvHashMap<(ast::NodeId, LintId), LevelSource>>,
 }
 
 /// Context for lint checking of the AST, after expansion, before lowering to
@@ -664,7 +659,6 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             access_levels: access_levels,
             lints: lint_store,
             level_stack: vec![],
-            node_levels: RefCell::new(FnvHashMap()),
         }
     }
 
@@ -1064,38 +1058,6 @@ fn visit_id(&mut self, id: ast::NodeId) {
     }
 }
 
-// This lint pass is defined here because it touches parts of the `LateContext`
-// that we don't want to expose. It records the lint level at certain AST
-// nodes, so that the variant size difference check in trans can call
-// `raw_emit_lint`.
-
-pub struct GatherNodeLevels;
-
-impl LintPass for GatherNodeLevels {
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
-
-impl LateLintPass for GatherNodeLevels {
-    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        match it.node {
-            hir::ItemEnum(..) => {
-                let lint_id = LintId::of(builtin::VARIANT_SIZE_DIFFERENCES);
-                let lvlsrc = cx.lints.get_level_source(lint_id);
-                match lvlsrc {
-                    (lvl, _) if lvl != Allow => {
-                        cx.node_levels.borrow_mut()
-                            .insert((it.id, lint_id), lvlsrc);
-                    },
-                    _ => { }
-                }
-            },
-            _ => { }
-        }
-    }
-}
-
 enum CheckLintNameResult {
     Ok,
     // Lint doesn't exist
@@ -1234,8 +1196,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }
 
-    *tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner();
-
     // Put the lint store back in the session.
     mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), cx.lints);
 }
index 92aa446c265f9f791d3911d063357a0a1a0809ea..121033549c0d5b0554c208a6551dca5d6e2bf766 100644 (file)
@@ -41,7 +41,7 @@
 
 pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
                         raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
-                        raw_struct_lint, GatherNodeLevels, FutureIncompatibleInfo};
+                        raw_struct_lint, FutureIncompatibleInfo};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
index c8b8c5dbdbbcbc878f2d51cc386a49475253a80f..6551e0129f88493dacffff9044ca34b10ea112db 100644 (file)
@@ -945,52 +945,41 @@ fn determine_pat_move_mode(&mut self,
     /// The core driver for walking a pattern; `match_mode` must be
     /// established up front, e.g. via `determine_pat_move_mode` (see
     /// also `walk_irrefutable_pat` for patterns that stand alone).
-    fn walk_pat(&mut self,
-                cmt_discr: mc::cmt<'tcx>,
-                pat: &hir::Pat,
-                match_mode: MatchMode) {
-        debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
-               pat);
+    fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
+        debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
 
         let tcx = &self.tcx();
         let mc = &self.mc;
         let infcx = self.mc.infcx;
         let delegate = &mut self.delegate;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
-            match pat.node {
-                PatKind::Binding(bmode, _, _) => {
-                    debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
-                           cmt_pat,
-                           pat,
-                           match_mode);
-
-                    // pat_ty: the type of the binding being produced.
-                    let pat_ty = return_if_err!(infcx.node_ty(pat.id));
-
-                    // Each match binding is effectively an assignment to the
-                    // binding being produced.
-                    if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
-                                                        tcx.expect_def(pat.id)) {
-                        delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
-                    }
+            if let PatKind::Binding(bmode, _, _) = pat.node {
+                debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
 
-                    // It is also a borrow or copy/move of the value being matched.
-                    match bmode {
-                        hir::BindByRef(m) => {
-                            if let ty::TyRef(&r, _) = pat_ty.sty {
-                                let bk = ty::BorrowKind::from_mutbl(m);
-                                delegate.borrow(pat.id, pat.span, cmt_pat,
-                                                r, bk, RefBinding);
-                            }
-                        }
-                        hir::BindByValue(..) => {
-                            let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
-                            debug!("walk_pat binding consuming pat");
-                            delegate.consume_pat(pat, cmt_pat, mode);
+                // pat_ty: the type of the binding being produced.
+                let pat_ty = return_if_err!(infcx.node_ty(pat.id));
+
+                // Each match binding is effectively an assignment to the
+                // binding being produced.
+                if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
+                                                    tcx.expect_def(pat.id)) {
+                    delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
+                }
+
+                // It is also a borrow or copy/move of the value being matched.
+                match bmode {
+                    hir::BindByRef(m) => {
+                        if let ty::TyRef(&r, _) = pat_ty.sty {
+                            let bk = ty::BorrowKind::from_mutbl(m);
+                            delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding);
                         }
                     }
+                    hir::BindByValue(..) => {
+                        let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
+                        debug!("walk_pat binding consuming pat");
+                        delegate.consume_pat(pat, cmt_pat, mode);
+                    }
                 }
-                _ => {}
             }
         }));
 
@@ -999,72 +988,23 @@ fn walk_pat(&mut self,
         // to the above loop's visit of than the bindings that form
         // the leaves of the pattern tree structure.
         return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
-            match pat.node {
-                PatKind::Struct(..) | PatKind::TupleStruct(..) |
-                PatKind::Path(..) | PatKind::QPath(..) => {
-                    match tcx.expect_def(pat.id) {
-                        Def::Variant(enum_did, variant_did) => {
-                            let downcast_cmt =
-                                if tcx.lookup_adt_def(enum_did).is_univariant() {
-                                    cmt_pat
-                                } else {
-                                    let cmt_pat_ty = cmt_pat.ty;
-                                    mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
-                                };
-
-                            debug!("variant downcast_cmt={:?} pat={:?}",
-                                   downcast_cmt,
-                                   pat);
-
-                            delegate.matched_pat(pat, downcast_cmt, match_mode);
-                        }
-
-                        Def::Struct(..) | Def::TyAlias(..) => {
-                            // A struct (in either the value or type
-                            // namespace; we encounter the former on
-                            // e.g. patterns for unit structs).
-
-                            debug!("struct cmt_pat={:?} pat={:?}",
-                                   cmt_pat,
-                                   pat);
-
-                            delegate.matched_pat(pat, cmt_pat, match_mode);
-                        }
-
-                        Def::Const(..) | Def::AssociatedConst(..) => {
-                            // This is a leaf (i.e. identifier binding
-                            // or constant value to match); thus no
-                            // `matched_pat` call.
-                        }
+            match tcx.expect_def_or_none(pat.id) {
+                Some(Def::Variant(enum_did, variant_did)) => {
+                    let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() {
+                        cmt_pat
+                    } else {
+                        let cmt_pat_ty = cmt_pat.ty;
+                        mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
+                    };
 
-                        def => {
-                            // An enum type should never be in a pattern.
-                            // Remaining cases are e.g. Def::Fn, to
-                            // which identifiers within patterns
-                            // should not resolve. However, we do
-                            // encouter this when using the
-                            // expr-use-visitor during typeck. So just
-                            // ignore it, an error should have been
-                            // reported.
-
-                            if !tcx.sess.has_errors() {
-                                span_bug!(pat.span,
-                                          "Pattern has unexpected def: {:?} and type {:?}",
-                                          def,
-                                          cmt_pat.ty);
-                            }
-                        }
-                    }
+                    debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
+                    delegate.matched_pat(pat, downcast_cmt, match_mode);
                 }
-
-                PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) |
-                PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
-                PatKind::Vec(..) | PatKind::Binding(..) => {
-                    // Each of these cases does not
-                    // correspond to an enum variant or struct, so we
-                    // do not do any `matched_pat` calls for these
-                    // cases either.
+                Some(Def::Struct(..)) | Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => {
+                    debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
+                    delegate.matched_pat(pat, cmt_pat, match_mode);
                 }
+                _ => {}
             }
         }));
     }
index a70829347f1c155deb61449e060f68efe52734bd..28bfb460a14faf75c9fdbbe10fb5a195cfc3e600 100644 (file)
@@ -1050,9 +1050,8 @@ pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McRes
     }
 
     // FIXME(#19596) This is a workaround, but there should be a better way to do this
-    fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
-                       -> McResult<()>
-        where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
+    fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()>
+        where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat)
     {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -1099,21 +1098,14 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         // step out of sync again. So you'll see below that we always
         // get the type of the *subpattern* and use that.
 
-        debug!("cat_pattern: {:?} cmt={:?}",
-               pat,
-               cmt);
-
-        (*op)(self, cmt.clone(), pat);
+        debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
 
-        let opt_def = self.tcx().expect_def_or_none(pat.id);
-        if opt_def == Some(Def::Err) {
-            return Err(());
-        }
+        op(self, cmt.clone(), pat);
 
         // Note: This goes up here (rather than within the PatKind::TupleStruct arm
-        // alone) because struct patterns can refer to struct types or
-        // to struct variants within enums.
-        let cmt = match opt_def {
+        // alone) because PatKind::Struct can also refer to variants.
+        let cmt = match self.tcx().expect_def_or_none(pat.id) {
+            Some(Def::Err) => return Err(()),
             Some(Def::Variant(enum_did, variant_did))
                 // univariant enums do not need downcasts
                 if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
@@ -1123,66 +1115,33 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         };
 
         match pat.node {
-          PatKind::Wild => {
-            // _
-          }
-
           PatKind::TupleStruct(_, ref subpats, ddpos) => {
-            match opt_def {
-                Some(Def::Variant(enum_def, def_id)) => {
-                    // variant(x, y, z)
-                    let expected_len = self.tcx().lookup_adt_def(enum_def)
-                                                 .variant_with_id(def_id).fields.len();
-                    for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                        let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
-
-                        let subcmt =
-                            self.cat_imm_interior(
-                                pat, cmt.clone(), subpat_ty,
-                                InteriorField(PositionalField(i)));
-
-                        self.cat_pattern_(subcmt, &subpat, op)?;
-                    }
+            let expected_len = match self.tcx().expect_def(pat.id) {
+                Def::Variant(enum_def, def_id) => {
+                    self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
                 }
-                Some(Def::Struct(..)) => {
-                    let expected_len = match self.pat_ty(&pat)?.sty {
+                Def::Struct(..) => {
+                    match self.pat_ty(&pat)?.sty {
                         ty::TyStruct(adt_def, _) => {
                             adt_def.struct_variant().fields.len()
                         }
                         ref ty => {
                             span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
                         }
-                    };
-
-                    for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                        let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
-                        let cmt_field =
-                            self.cat_imm_interior(
-                                pat, cmt.clone(), subpat_ty,
-                                InteriorField(PositionalField(i)));
-                        self.cat_pattern_(cmt_field, &subpat, op)?;
                     }
                 }
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {
-                    for subpat in subpats {
-                        self.cat_pattern_(cmt.clone(), &subpat, op)?;
-                    }
-                }
-                _ => {
-                    span_bug!(
-                        pat.span,
-                        "enum pattern didn't resolve to enum or struct {:?}",
-                        opt_def);
+                def => {
+                    span_bug!(pat.span, "tuple struct pattern didn't resolve \
+                                         to variant or struct {:?}", def);
                 }
-            }
-          }
-
-          PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) => {
-              // Lone constant, or unit variant or identifier: ignore
-          }
+            };
 
-          PatKind::Binding(_, _, Some(ref subpat)) => {
-              self.cat_pattern_(cmt, &subpat, op)?;
+            for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
+                let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
+                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
+                                                   InteriorField(PositionalField(i)));
+                self.cat_pattern_(subcmt, &subpat, op)?;
+            }
           }
 
           PatKind::Struct(_, ref field_pats, _) => {
@@ -1194,6 +1153,10 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
             }
           }
 
+          PatKind::Binding(_, _, Some(ref subpat)) => {
+              self.cat_pattern_(cmt, &subpat, op)?;
+          }
+
           PatKind::Tuple(ref subpats, ddpos) => {
             // (p1, ..., pN)
             let expected_len = match self.pat_ty(&pat)?.sty {
@@ -1202,10 +1165,8 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
             };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
                 let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
-                let subcmt =
-                    self.cat_imm_interior(
-                        pat, cmt.clone(), subpat_ty,
-                        InteriorField(PositionalField(i)));
+                let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
+                                                   InteriorField(PositionalField(i)));
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
           }
@@ -1215,25 +1176,26 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
             // PatKind::Ref since that information is already contained
             // in the type.
             let subcmt = self.cat_deref(pat, cmt, 0, None)?;
-              self.cat_pattern_(subcmt, &subpat, op)?;
+            self.cat_pattern_(subcmt, &subpat, op)?;
           }
 
           PatKind::Vec(ref before, ref slice, ref after) => {
-              let context = InteriorOffsetKind::Pattern;
-              let elt_cmt = self.cat_index(pat, cmt, context)?;
-              for before_pat in before {
-                  self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
-              }
-              if let Some(ref slice_pat) = *slice {
-                  self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
-              }
-              for after_pat in after {
-                  self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
-              }
+            let context = InteriorOffsetKind::Pattern;
+            let elt_cmt = self.cat_index(pat, cmt, context)?;
+            for before_pat in before {
+                self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
+            }
+            if let Some(ref slice_pat) = *slice {
+                self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
+            }
+            for after_pat in after {
+                self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
+            }
           }
 
-          PatKind::Lit(_) | PatKind::Range(_, _) => {
-              /*always ok*/
+          PatKind::Path(..) | PatKind::Binding(_, _, None) |
+          PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
+            // always ok
           }
         }
 
index 62d3421770c2f2cefe0a28ce6115ac5e006e21d1..93507246241de62bde905a68e9fde7acc47e7c47 100644 (file)
@@ -1063,7 +1063,7 @@ fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
                             Some(tcx.lookup_item_type(variant_def.did).generics)
                         })?;
 
-                        match variant_def.kind() {
+                        match variant_def.kind {
                             ty::VariantKind::Unit => Ok(()),
                             ty::VariantKind::Tuple => fmt_tuple(fmt, lvs),
                             ty::VariantKind::Struct => {
index 5ccc96210be78d7d56cc8b739544ec05a1fce18e..ab9a0fcb19b97eff6f16872d5d7e519b7600a1ed 100644 (file)
@@ -727,8 +727,6 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
         "load extra plugins"),
     unstable_options: bool = (false, parse_bool,
           "adds unstable command line options to rustc interface"),
-    print_enum_sizes: bool = (false, parse_bool,
-          "print the size of enums and their variants"),
     force_overflow_checks: Option<bool> = (None, parse_opt_bool,
           "force overflow checks on or off"),
     force_dropflag_checks: Option<bool> = (None, parse_opt_bool,
index 57c4af6bed569406138d3096914b43e092ee0ae8..0e516bdc21194b3c9d5ce473d0e8a9228f871aab 100644 (file)
@@ -304,9 +304,6 @@ pub fn no_landing_pads(&self) -> bool {
     pub fn unstable_options(&self) -> bool {
         self.opts.debugging_opts.unstable_options
     }
-    pub fn print_enum_sizes(&self) -> bool {
-        self.opts.debugging_opts.print_enum_sizes
-    }
     pub fn nonzeroing_move_hints(&self) -> bool {
         self.opts.debugging_opts.enable_nonzeroing_move_hints
     }
index 219cb5e383a8d00ebc3b8dc270ca48bcc1e6a593..56938a7a838588d0e0c5d757b1eab9e877e4b763 100644 (file)
@@ -12,7 +12,6 @@
 
 use dep_graph::{DepGraph, DepTrackingMap};
 use session::Session;
-use lint;
 use middle;
 use middle::cstore::LOCAL_CRATE;
 use hir::def::DefMap;
@@ -415,9 +414,6 @@ pub struct GlobalCtxt<'tcx> {
     /// Cache used by const_eval when decoding extern const fns
     pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
 
-    pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
-                                              lint::LevelSource>>,
-
     /// Maps any item's def-id to its stability index.
     pub stability: RefCell<stability::Index<'tcx>>,
 
@@ -591,6 +587,13 @@ pub fn alloc_trait_def(self, def: ty::TraitDef<'gcx>)
         self.global_interners.arenas.trait_defs.alloc(def)
     }
 
+    pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) {
+        // this will need a transmute when reverse-variance is removed
+        if let Some(prev) = self.adt_defs.borrow_mut().insert(did, adt_def) {
+            bug!("Tried to overwrite interned AdtDef: {:?}", prev)
+        }
+    }
+
     pub fn intern_adt_def(self,
                           did: DefId,
                           kind: ty::AdtKind,
@@ -598,10 +601,7 @@ pub fn intern_adt_def(self,
                           -> ty::AdtDefMaster<'gcx> {
         let def = ty::AdtDefData::new(self, did, kind, variants);
         let interned = self.global_interners.arenas.adt_defs.alloc(def);
-        // this will need a transmute when reverse-variance is removed
-        if let Some(prev) = self.adt_defs.borrow_mut().insert(did, interned) {
-            bug!("Tried to overwrite interned AdtDef: {:?}", prev)
-        }
+        self.insert_adt_def(did, interned);
         interned
     }
 
@@ -722,7 +722,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
             extern_const_statics: RefCell::new(DefIdMap()),
             extern_const_fns: RefCell::new(DefIdMap()),
-            node_lint_levels: RefCell::new(FnvHashMap()),
             stability: RefCell::new(stability),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
index 61c8aa8fcebf368688950ccbc70503f57dc1d816..27ed88e929e76dba833a9702e52d896b03072391 100644 (file)
@@ -17,8 +17,6 @@
 use traits;
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 
-use util::common::slice_pat;
-
 use syntax::ast::{FloatTy, IntTy, UintTy};
 use syntax::attr;
 use syntax_pos::DUMMY_SP;
@@ -100,7 +98,7 @@ pub fn parse(sess: &Session) -> TargetDataLayout {
 
         let mut dl = TargetDataLayout::default();
         for spec in sess.target.target.data_layout.split("-") {
-            match slice_pat(&&spec.split(":").collect::<Vec<_>>()[..]) {
+            match &spec.split(":").collect::<Vec<_>>()[..] {
                 &["e"] => dl.endian = Endian::Little,
                 &["E"] => dl.endian = Endian::Big,
                 &["a", ref a..] => dl.aggregate_align = align(a, "a"),
index 14db922d298101e82c941202deb7834743b9f4f4..03e893727d1b58c7d88142ee72bb336dfe509cfd 100644 (file)
@@ -1715,7 +1715,7 @@ pub fn variant_index_with_id(&self, vid: DefId) -> usize {
     pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> {
         match def {
             Def::Variant(_, vid) => self.variant_with_id(vid),
-            Def::Struct(..) | Def::TyAlias(..) => self.struct_variant(),
+            Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => self.struct_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
     }
@@ -1925,14 +1925,6 @@ fn fields_iter(&self) -> slice::Iter<FieldDefData<'tcx, 'container>> {
         self.fields.iter()
     }
 
-    pub fn kind(&self) -> VariantKind {
-        self.kind
-    }
-
-    pub fn is_tuple_struct(&self) -> bool {
-        self.kind() == VariantKind::Tuple
-    }
-
     #[inline]
     pub fn find_field_named(&self,
                             name: ast::Name)
@@ -2454,6 +2446,20 @@ pub fn expect_def_or_none(self, id: NodeId) -> Option<Def> {
         self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
     }
 
+    // Returns `ty::VariantDef` if `def` refers to a struct,
+    // or variant or their constructors, panics otherwise.
+    pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
+        match def {
+            Def::Variant(enum_did, did) => {
+                self.lookup_adt_def(enum_did).variant_with_id(did)
+            }
+            Def::Struct(did) => {
+                self.lookup_adt_def(did).struct_variant()
+            }
+            _ => bug!("expect_variant_def used with unexpected def {:?}", def)
+        }
+    }
+
     pub fn def_key(self, id: DefId) -> ast_map::DefKey {
         if id.is_local() {
             self.map.def_key(id)
index 57c429152c89935d72c8add0e7d2b551afd760d0..bdfb97549d5d512647ce80179eb8d38579cd1378 100644 (file)
@@ -247,15 +247,3 @@ pub fn path2cstr(p: &Path) -> CString {
 pub fn path2cstr(p: &Path) -> CString {
     CString::new(p.to_str().unwrap()).unwrap()
 }
-
-// FIXME(stage0): remove this
-// HACK: this is needed because the interpretation of slice
-// patterns changed between stage0 and now.
-#[cfg(stage0)]
-pub fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'a &'b [T] {
-    t
-}
-#[cfg(not(stage0))]
-pub fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'b [T] {
-    *t
-}
index a5a9dea61ad7c99661851be39303634677eb4198..0de00d9d7f631edc634f6b757ac106361f1a5062 100644 (file)
@@ -43,7 +43,6 @@
 use rustc::hir::print::pat_to_string;
 use syntax::ptr::P;
 use rustc::util::nodemap::FnvHashMap;
-use rustc::util::common::slice_pat;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
     id: DUMMY_NODE_ID,
@@ -246,9 +245,9 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
             let pat_ty = cx.tcx.pat_ty(p);
             if let ty::TyEnum(edef, _) = pat_ty.sty {
                 if let Def::Local(..) = cx.tcx.expect_def(p.id) {
-                    if edef.variants.iter().any(|variant|
-                        variant.name == name.node && variant.kind() == VariantKind::Unit
-                    ) {
+                    if edef.variants.iter().any(|variant| {
+                        variant.name == name.node && variant.kind == VariantKind::Unit
+                    }) {
                         let ty_path = cx.tcx.item_path_str(edef.did);
                         let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
                             "pattern binding `{}` is named the same as one \
@@ -400,7 +399,7 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
                 hir::MatchSource::ForLoopDesugar => {
                     // `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
                     let witness = match witnesses[0].node {
-                        PatKind::TupleStruct(_, ref pats, _) => match slice_pat(&&pats[..]) {
+                        PatKind::TupleStruct(_, ref pats, _) => match &pats[..] {
                             &[ref pat] => &**pat,
                             _ => bug!(),
                         },
@@ -489,7 +488,7 @@ fn visit_id(&mut self, node_id: NodeId) {
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
-            PatKind::Path(..) | PatKind::QPath(..) => {
+            PatKind::Path(..) => {
                 match self.tcx.expect_def(pat.id) {
                     Def::AssociatedConst(did) | Def::Const(did) => {
                         let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
@@ -563,7 +562,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
 
         ty::TyEnum(adt, _) | ty::TyStruct(adt, _)  => {
             let v = ctor.variant_for_adt(adt);
-            match v.kind() {
+            match v.kind {
                 VariantKind::Struct => {
                     let field_pats: hir::HirVec<_> = v.fields.iter()
                         .zip(pats)
@@ -583,7 +582,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
                     PatKind::TupleStruct(def_to_path(cx.tcx, v.did), pats.collect(), None)
                 }
                 VariantKind::Unit => {
-                    PatKind::Path(def_to_path(cx.tcx, v.did))
+                    PatKind::Path(None, def_to_path(cx.tcx, v.did))
                 }
             }
         }
@@ -786,16 +785,12 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     match pat.node {
         PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>
             match cx.tcx.expect_def(pat.id) {
-                Def::Const(..) | Def::AssociatedConst(..) =>
-                    span_bug!(pat.span, "const pattern should've \
-                                         been rewritten"),
-                Def::Struct(..) | Def::TyAlias(..) => vec![Single],
                 Def::Variant(_, id) => vec![Variant(id)],
-                def => span_bug!(pat.span, "pat_constructors: unexpected \
-                                            definition {:?}", def),
+                Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => vec![Single],
+                Def::Const(..) | Def::AssociatedConst(..) =>
+                    span_bug!(pat.span, "const pattern should've been rewritten"),
+                def => span_bug!(pat.span, "pat_constructors: unexpected definition {:?}", def),
             },
-        PatKind::QPath(..) =>
-            span_bug!(pat.span, "const pattern should've been rewritten"),
         PatKind::Lit(ref expr) =>
             vec![ConstantValue(eval_const_expr(cx.tcx, &expr))],
         PatKind::Range(ref lo, ref hi) =>
@@ -934,10 +929,6 @@ pub fn specialize<'a, 'b, 'tcx>(
             }
         }
 
-        PatKind::QPath(_, _) => {
-            span_bug!(pat_span, "const pattern should've been rewritten")
-        }
-
         PatKind::Struct(_, ref pattern_fields, _) => {
             let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
             let variant = constructor.variant_for_adt(adt);
index 6c37662206ce252f5592eeeee86853fe43c4b1e6..a3c707e82a0ff45e45be5c74e951c184296f8cb5 100644 (file)
@@ -323,7 +323,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         hir::ExprPath(_, ref path) => {
             match tcx.expect_def(expr.id) {
-                Def::Struct(..) | Def::Variant(..) => PatKind::Path(path.clone()),
+                Def::Struct(..) | Def::Variant(..) => PatKind::Path(None, path.clone()),
                 Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                     let substs = Some(tcx.node_id_item_substs(expr.id).substs);
                     let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
index 7e9b6f561b9846f1d0b4f09c72b31918ebd63a64..15914838acf0db85289b97ececd3fa5c90696a4b 100644 (file)
@@ -360,7 +360,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
 
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
-        if let PatKind::Path(ref path) = p.node {
+        if let PatKind::Path(None, ref path) = p.node {
             if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
                 if let Def::Const(..) = cx.tcx.expect_def(p.id) {
                     NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
index 4ae5b3afdba19f4bf1d119173c00d92d98da66cd..7b0ee91b69ed0848b82a16252df2905469e3976c 100644 (file)
@@ -108,6 +108,7 @@ macro_rules! add_lint_group {
                  HardwiredLints,
                  WhileTrue,
                  ImproperCTypes,
+                 VariantSizeDifferences,
                  BoxPointers,
                  UnusedAttributes,
                  PathStatements,
@@ -209,9 +210,6 @@ macro_rules! add_lint_group {
         },
         ]);
 
-    // We have one lint pass defined specially
-    store.register_late_pass(sess, false, box lint::GatherNodeLevels);
-
     // Register renamed and removed lints
     store.register_renamed("unknown_features", "unused_features");
     store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
index 97f97a889edc30431de9fe399b0b4afb679fbea0..9b08ddcafab8e7d9e773a2d81e85dd15f2549a21 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::layout::{Layout, Primitive};
+use rustc::traits::ProjectionMode;
 use middle::const_val::ConstVal;
 use rustc_const_eval::eval_const_expr_partial;
 use rustc_const_eval::EvalHint::ExprTypeChecked;
-use util::common::slice_pat;
 use util::nodemap::{FnvHashSet};
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
     "shift exceeds the type's number of bits"
 }
 
+declare_lint! {
+    VARIANT_SIZE_DIFFERENCES,
+    Allow,
+    "detects enums with widely varying variant sizes"
+}
+
 #[derive(Copy, Clone)]
 pub struct TypeLimits {
     /// Id of the last visited negated expression
@@ -461,7 +468,7 @@ fn check_type_for_ffi(&self,
                 // Check for a repr() attribute to specify the size of the
                 // discriminant.
                 let repr_hints = cx.lookup_repr_hints(def.did);
-                match slice_pat(&&**repr_hints) {
+                match &repr_hints[..] {
                     &[] => {
                         // Special-case types like `Option<extern fn()>`.
                         if !is_repr_nullable_ptr(cx, def, substs) {
@@ -676,3 +683,64 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         }
     }
 }
+
+pub struct VariantSizeDifferences;
+
+impl LintPass for VariantSizeDifferences {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(VARIANT_SIZE_DIFFERENCES)
+    }
+}
+
+impl LateLintPass for VariantSizeDifferences {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
+            if gens.ty_params.is_empty() {  // sizes only make sense for non-generic types
+                let t = cx.tcx.node_id_to_type(it.id);
+                let layout = cx.tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+                    t.layout(&infcx).unwrap_or_else(|e| {
+                        bug!("failed to get layout for `{}`: {}", t, e)
+                    })
+                });
+
+                if let Layout::General { ref variants, ref size, discr, .. } = *layout {
+                    let discr_size = Primitive::Int(discr).size(&cx.tcx.data_layout).bytes();
+
+                    debug!("enum `{}` is {} bytes large", t, size.bytes());
+
+                    let (largest, slargest, largest_index) = enum_definition.variants
+                        .iter()
+                        .zip(variants)
+                        .map(|(variant, variant_layout)| {
+                            // Subtract the size of the enum discriminant
+                            let bytes = variant_layout.min_size().bytes()
+                                                                 .saturating_sub(discr_size);
+
+                            debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);
+                            bytes
+                        })
+                        .enumerate()
+                        .fold((0, 0, 0),
+                            |(l, s, li), (idx, size)|
+                                if size > l {
+                                    (size, l, idx)
+                                } else if size > s {
+                                    (l, size, li)
+                                } else {
+                                    (l, s, li)
+                                }
+                        );
+
+                    // we only warn if the largest variant is at least thrice as large as
+                    // the second-largest.
+                    if largest > slargest * 3 && slargest > 0 {
+                        cx.span_lint(VARIANT_SIZE_DIFFERENCES,
+                                     enum_definition.variants[largest_index].span,
+                                     &format!("enum variant is more than three times larger \
+                                               ({} bytes) than the next largest", largest));
+                    }
+                }
+            }
+        }
+    }
+}
index eada2a9cd7a63332f6b30aeb10712a785d047f3e..6d3699e978794f8e3bd4ddb078382d2135e177c4 100644 (file)
@@ -471,28 +471,34 @@ fn get_struct_variant<'tcx>(intr: &IdentInterner,
 
     let doc = cdata.lookup_item(item_id);
     let did = DefId { krate: cdata.cnum, index: item_id };
+    let mut ctor_did = None;
     let (kind, variants) = match item_family(doc) {
         Enum => {
             (ty::AdtKind::Enum,
              get_enum_variants(intr, cdata, doc))
         }
         Struct(..) => {
-            let ctor_did =
-                reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
-                map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
+            // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
+            ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| {
+                translated_def_id(cdata, ctor_doc)
+            });
             (ty::AdtKind::Struct,
-             vec![get_struct_variant(intr, cdata, doc, ctor_did)])
+             vec![get_struct_variant(intr, cdata, doc, ctor_did.unwrap_or(did))])
         }
         _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}",
                   item_family(doc), did)
     };
 
     let adt = tcx.intern_adt_def(did, kind, variants);
+    if let Some(ctor_did) = ctor_did {
+        // Make adt definition available through constructor id as well.
+        tcx.insert_adt_def(ctor_did, adt);
+    }
 
     // this needs to be done *after* the variant is interned,
     // to support recursive structures
     for variant in &adt.variants {
-        if variant.kind() == ty::VariantKind::Tuple &&
+        if variant.kind == ty::VariantKind::Tuple &&
             adt.adt_kind() == ty::AdtKind::Enum {
             // tuple-like enum variant fields aren't real items - get the types
             // from the ctor.
index b6f49569958d68189effffc864b47396c1029410..7314259423592985f68cd4cd512a17247d7d2fd5 100644 (file)
@@ -217,7 +217,7 @@ fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
 fn encode_struct_fields(rbml_w: &mut Encoder,
                         variant: ty::VariantDef) {
     for f in &variant.fields {
-        if variant.is_tuple_struct() {
+        if variant.kind == ty::VariantKind::Tuple {
             rbml_w.start_tag(tag_item_unnamed_field);
         } else {
             rbml_w.start_tag(tag_item_field);
@@ -250,7 +250,7 @@ fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         let _task = index.record(vid, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
         encode_def_id_and_key(ecx, rbml_w, vid);
-        encode_family(rbml_w, match variant.kind() {
+        encode_family(rbml_w, match variant.kind {
             ty::VariantKind::Struct => 'V',
             ty::VariantKind::Tuple => 'v',
             ty::VariantKind::Unit => 'w',
index b5e2ce9de483692054406c1b0371dea674538ae8..88fb65d8eea03569d41c13958d524a7e6cf5fe48 100644 (file)
@@ -700,19 +700,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             ref sty => bug!("unexpected sty: {:?}", sty)
         },
         Def::Const(def_id) |
-        Def::AssociatedConst(def_id) => {
-            let substs = Some(cx.tcx.node_id_item_substs(expr.id).substs);
-            let tcx = cx.tcx.global_tcx();
-            if let Some((e, _)) = const_eval::lookup_const_by_id(tcx, def_id, substs) {
-                // FIXME ConstVal can't be yet used with adjustments, as they would be lost.
-                if !cx.tcx.tables.borrow().adjustments.contains_key(&e.id) {
-                    if let Some(v) = cx.try_const_eval_literal(e) {
-                        return ExprKind::Literal { literal: v };
-                    }
-                }
-            }
-            def_id
-        }
+        Def::AssociatedConst(def_id) => def_id,
 
         Def::Static(node_id, _) => return ExprKind::StaticRef {
             id: node_id,
index 81b098281d6a19c578b84fac946526e7685c55b6..2438f43d24e0a42f8e87854af51e0ffe35c90ddb 100644 (file)
@@ -129,21 +129,6 @@ pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
         }
     }
 
-    pub fn try_const_eval_literal(&mut self, e: &hir::Expr) -> Option<Literal<'tcx>> {
-        let hint = const_eval::EvalHint::ExprTypeChecked;
-        let tcx = self.tcx.global_tcx();
-        const_eval::eval_const_expr_partial(tcx, e, hint, None).ok().and_then(|v| {
-            match v {
-                // All of these contain local IDs, unsuitable for storing in MIR.
-                ConstVal::Struct(_) | ConstVal::Tuple(_) |
-                ConstVal::Array(..) | ConstVal::Repeat(..) |
-                ConstVal::Function(_) => None,
-
-                _ => Some(Literal::Value { value: v })
-            }
-        })
-    }
-
     pub fn trait_method(&mut self,
                         trait_def_id: DefId,
                         method_name: &str,
index b5da50792762f17f33e4202447b0a05f44e143d6..c54c8bfb5981ed6d8469510cc76c47a212992f36 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_const_eval as const_eval;
 use rustc::hir::def::Def;
-use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
+use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::ty::{self, Ty};
 use rustc::mir::repr::*;
 use rustc::hir::{self, PatKind};
@@ -76,9 +76,7 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
                 PatternKind::Range { lo: lo, hi: hi }
             },
 
-            PatKind::Path(..) | PatKind::QPath(..)
-                if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
-            {
+            PatKind::Path(..) => {
                 match self.cx.tcx.expect_def(pat.id) {
                     Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                         let tcx = self.cx.tcx.global_tcx();
@@ -104,11 +102,9 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
                             }
                         }
                     }
-                    def =>
-                        span_bug!(
-                            pat.span,
-                            "def not a constant: {:?}",
-                            def),
+                    _ => {
+                        self.variant_or_leaf(pat, vec![])
+                    }
                 }
             }
 
@@ -199,10 +195,6 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
                 }
             }
 
-            PatKind::Path(..) => {
-                self.variant_or_leaf(pat, vec![])
-            }
-
             PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
                 let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
                 let adt_def = match pat_ty.sty {
@@ -253,10 +245,6 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
 
                 self.variant_or_leaf(pat, subpatterns)
             }
-
-            PatKind::QPath(..) => {
-                span_bug!(pat.span, "unexpanded macro or bad constant etc");
-            }
         };
 
         Pattern {
@@ -325,7 +313,7 @@ fn variant_or_leaf(&mut self,
                 }
             }
 
-            Def::Struct(..) | Def::TyAlias(..) => {
+            Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
index 85a6f732dd52e71716efd93395dbcd210f028a99..acaf9b9b2faeed9d57b1b4da9a0cccd4b3b26238 100644 (file)
@@ -436,7 +436,6 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                 }
             }
             hir::ExprPath(..) => {
-
                 if let Def::Struct(..) = self.tcx.expect_def(expr.id) {
                     let expr_ty = self.tcx.expr_ty(expr);
                     let def = match expr_ty.sty {
index a7fb039c295f8bdbda2e9cb3356e3ab1a8232a08..9079cc8ccb122b86ecf41654a760b6c0e595ef08 100644 (file)
@@ -2180,7 +2180,8 @@ fn fresh_binding(&mut self,
         // because that breaks the assumptions later
         // passes make about or-patterns.)
         let renamed = mtwt::resolve(ident.node);
-        let def = match bindings.get(&renamed).cloned() {
+        let mut def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
+        match bindings.get(&renamed).cloned() {
             Some(id) if id == outer_pat_id => {
                 // `Variant(a, a)`, error
                 resolve_error(
@@ -2189,7 +2190,6 @@ fn fresh_binding(&mut self,
                     ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(
                         &ident.node.name.as_str())
                 );
-                Def::Err
             }
             Some(..) if pat_src == PatternSource::FnParam => {
                 // `fn f(a: u8, a: u8)`, error
@@ -2199,29 +2199,24 @@ fn fresh_binding(&mut self,
                     ResolutionError::IdentifierBoundMoreThanOnceInParameterList(
                         &ident.node.name.as_str())
                 );
-                Def::Err
             }
             Some(..) if pat_src == PatternSource::Match => {
                 // `Variant1(a) | Variant2(a)`, ok
                 // Reuse definition from the first `a`.
-                self.value_ribs.last_mut().unwrap().bindings[&renamed]
+                def = self.value_ribs.last_mut().unwrap().bindings[&renamed];
             }
             Some(..) => {
                 span_bug!(ident.span, "two bindings with the same name from \
                                        unexpected pattern source {:?}", pat_src);
             }
             None => {
-                // A completely fresh binding, add to the lists.
-                // FIXME: Later stages are not ready to deal with `Def::Err` here yet, so
-                // define `Invalid` bindings as `Def::Local`, just don't add them to the lists.
-                let def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
+                // A completely fresh binding, add to the lists if it's valid.
                 if ident.node.name != keywords::Invalid.name() {
                     bindings.insert(renamed, outer_pat_id);
                     self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
                 }
-                def
             }
-        };
+        }
 
         PathResolution::new(def)
     }
@@ -2287,43 +2282,41 @@ 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 local_def = self.resolve_identifier(ident.node, ValueNS, true);
-                    let resolution = if let Some(LocalDef { def, .. }) = local_def {
+                    let resolution = self.resolve_identifier(ident.node, ValueNS, true)
+                                         .map(|local_def| PathResolution::new(local_def.def))
+                                         .and_then(|resolution| {
                         let always_binding = !pat_src.is_refutable() || opt_pat.is_some() ||
                                              bmode != BindingMode::ByValue(Mutability::Immutable);
-                        match def {
+                        match resolution.base_def {
                             Def::Struct(..) | Def::Variant(..) |
                             Def::Const(..) | Def::AssociatedConst(..) if !always_binding => {
                                 // A constant, unit variant, etc pattern.
-                                PathResolution::new(def)
+                                Some(resolution)
                             }
                             Def::Struct(..) | Def::Variant(..) |
                             Def::Const(..) | Def::AssociatedConst(..) | Def::Static(..) => {
                                 // A fresh binding that shadows something unacceptable.
-                                let kind_name = PathResolution::new(def).kind_name();
                                 resolve_error(
                                     self,
                                     ident.span,
                                     ResolutionError::BindingShadowsSomethingUnacceptable(
-                                        pat_src.descr(), kind_name, ident.node.name)
+                                        pat_src.descr(), resolution.kind_name(), ident.node.name)
                                 );
-                                err_path_resolution()
+                                None
                             }
-                            Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Err => {
+                            Def::Local(..) | Def::Upvar(..) | Def::Fn(..) => {
                                 // These entities are explicitly allowed
                                 // to be shadowed by fresh bindings.
-                                self.fresh_binding(ident, pat.id, outer_pat_id,
-                                                   pat_src, bindings)
+                                None
                             }
                             def => {
                                 span_bug!(ident.span, "unexpected definition for an \
                                                        identifier in pattern {:?}", def);
                             }
                         }
-                    } else {
-                        // Fall back to a fresh binding.
+                    }).unwrap_or_else(|| {
                         self.fresh_binding(ident, pat.id, outer_pat_id, pat_src, bindings)
-                    };
+                    });
 
                     self.record_def(pat.id, resolution);
                 }
@@ -2331,7 +2324,7 @@ fn resolve_pattern(&mut self,
                 PatKind::TupleStruct(ref path, _, _) => {
                     self.resolve_pattern_path(pat.id, None, path, ValueNS, |def| {
                         match def {
-                            Def::Struct(..) | Def::Variant(..) | Def::Err => true,
+                            Def::Struct(..) | Def::Variant(..) => true,
                             _ => false,
                         }
                     }, "variant or struct");
@@ -2341,7 +2334,7 @@ fn resolve_pattern(&mut self,
                     self.resolve_pattern_path(pat.id, qself.as_ref(), path, ValueNS, |def| {
                         match def {
                             Def::Struct(..) | Def::Variant(..) |
-                            Def::Const(..) | Def::AssociatedConst(..) | Def::Err => true,
+                            Def::Const(..) | Def::AssociatedConst(..) => true,
                             _ => false,
                         }
                     }, "variant, struct or constant");
@@ -2351,7 +2344,7 @@ fn resolve_pattern(&mut self,
                     self.resolve_pattern_path(pat.id, None, path, TypeNS, |def| {
                         match def {
                             Def::Struct(..) | Def::Variant(..) |
-                            Def::TyAlias(..) | Def::AssociatedTy(..) | Def::Err => true,
+                            Def::TyAlias(..) | Def::AssociatedTy(..) => true,
                             _ => false,
                         }
                     }, "variant, struct or type alias");
@@ -2482,7 +2475,7 @@ fn resolve_identifier(&mut self,
                           record_used: bool)
                           -> Option<LocalDef> {
         if identifier.name == keywords::Invalid.name() {
-            return Some(LocalDef::from_def(Def::Err));
+            return None;
         }
 
         self.resolve_ident_in_lexical_scope(identifier, namespace, record_used)
index 10af326be26a3091af33c7709bae7bd11d9c0f6f..08e894ffbcfd48c4e37fde4d75f6565713c79f80 100644 (file)
@@ -796,7 +796,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool {
             PatKind::Tuple(..) => true,
             PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => {
                 match tcx.expect_def(pat.id) {
-                    Def::Struct(..) | Def::TyAlias(..) => true,
+                    Def::Struct(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => true,
                     _ => false,
                 }
             }
@@ -2003,7 +2003,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         cleanup_scope)
                 });
         }
-        PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild |
+        PatKind::Path(..) | PatKind::Wild |
         PatKind::Lit(..) | PatKind::Range(..) => ()
     }
     return bcx;
index c080d1f06d00f2a0d9a5bdc1d2f0f817f059d546..ee3eeefc124a54b541e9aaa2875851f2b5c24de4 100644 (file)
@@ -30,7 +30,6 @@
 
 use back::link;
 use back::linker::LinkerInfo;
-use lint;
 use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
 use llvm;
 use rustc::cfg;
@@ -75,7 +74,7 @@
 use glue;
 use inline;
 use machine;
-use machine::{llalign_of_min, llsize_of, llsize_of_real};
+use machine::{llalign_of_min, llsize_of};
 use meth;
 use mir;
 use monomorphize::{self, Instance};
@@ -86,7 +85,6 @@
 use tvec;
 use type_::Type;
 use type_of;
-use type_of::*;
 use value::Value;
 use Disr;
 use util::common::indenter;
@@ -2074,87 +2072,6 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     fcx.finish(bcx, DebugLoc::None);
 }
 
-fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &hir::EnumDef, sp: Span, id: ast::NodeId) {
-    let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
-
-    let print_info = ccx.sess().print_enum_sizes();
-
-    let levels = ccx.tcx().node_lint_levels.borrow();
-    let lint_id = lint::LintId::of(lint::builtin::VARIANT_SIZE_DIFFERENCES);
-    let lvlsrc = levels.get(&(id, lint_id));
-    let is_allow = lvlsrc.map_or(true, |&(lvl, _)| lvl == lint::Allow);
-
-    if is_allow && !print_info {
-        // we're not interested in anything here
-        return;
-    }
-
-    let ty = ccx.tcx().node_id_to_type(id);
-    let avar = adt::represent_type(ccx, ty);
-    match *avar {
-        adt::General(_, ref variants, _) => {
-            for var in variants {
-                let mut size = 0;
-                for field in var.fields.iter().skip(1) {
-                    // skip the discriminant
-                    size += llsize_of_real(ccx, sizing_type_of(ccx, *field));
-                }
-                sizes.push(size);
-            }
-        },
-        _ => { /* its size is either constant or unimportant */ }
-    }
-
-    let (largest, slargest, largest_index) = sizes.iter().enumerate().fold((0, 0, 0),
-        |(l, s, li), (idx, &size)|
-            if size > l {
-                (size, l, idx)
-            } else if size > s {
-                (l, size, li)
-            } else {
-                (l, s, li)
-            }
-    );
-
-    // FIXME(#30505) Should use logging for this.
-    if print_info {
-        let llty = type_of::sizing_type_of(ccx, ty);
-
-        let sess = &ccx.tcx().sess;
-        sess.span_note_without_error(sp,
-                                     &format!("total size: {} bytes", llsize_of_real(ccx, llty)));
-        match *avar {
-            adt::General(..) => {
-                for (i, var) in enum_def.variants.iter().enumerate() {
-                    ccx.tcx()
-                       .sess
-                       .span_note_without_error(var.span,
-                                                &format!("variant data: {} bytes", sizes[i]));
-                }
-            }
-            _ => {}
-        }
-    }
-
-    // we only warn if the largest variant is at least thrice as large as
-    // the second-largest.
-    if !is_allow && largest > slargest * 3 && slargest > 0 {
-        // Use lint::raw_emit_lint rather than sess.add_lint because the lint-printing
-        // pass for the latter already ran.
-        lint::raw_struct_lint(&ccx.tcx().sess,
-                              &ccx.tcx().sess.lint_store.borrow(),
-                              lint::builtin::VARIANT_SIZE_DIFFERENCES,
-                              *lvlsrc.unwrap(),
-                              Some(sp),
-                              &format!("enum variant is more than three times larger ({} bytes) \
-                                        than the next largest (ignoring padding)",
-                                       largest))
-            .span_note(enum_def.variants[largest_index].span,
-                       "this variant is the largest")
-            .emit();
-    }
-}
-
 pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
     // applicable to variable declarations and may not really make sense for
@@ -2194,26 +2111,6 @@ pub fn set_link_section(ccx: &CrateContext,
     }
 }
 
-fn trans_item(ccx: &CrateContext, item: &hir::Item) {
-    let _icx = push_ctxt("trans_item");
-
-    match item.node {
-        hir::ItemEnum(ref enum_definition, ref gens) => {
-            if gens.ty_params.is_empty() {
-                // sizes only make sense for non-generic types
-                enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
-            }
-        }
-        hir::ItemFn(..) |
-        hir::ItemImpl(..) |
-        hir::ItemStatic(..) => {
-            // Don't do anything here. Translation has been moved to
-            // being "collector-driven".
-        }
-        _ => {}
-    }
-}
-
 /// Create the `main` function which will initialise the rust runtime and call
 /// users’ main function.
 pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
@@ -2659,19 +2556,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     symbol_names_test::report_symbol_names(&shared_ccx);
 
-    {
-        let ccx = crate_context_list.get_ccx(0);
-
-        // FIXME: #34018
-        // At this point, we only walk the HIR for running
-        // enum_variant_size_lint(). This should arguably be moved somewhere
-        // else.
-        {
-            intravisit::walk_mod(&mut TransItemsWithinModVisitor { ccx: &ccx }, &krate.module);
-            krate.visit_all_items(&mut TransModVisitor { ccx: &ccx });
-        }
-    }
-
     if shared_ccx.sess().trans_stats() {
         let stats = shared_ccx.stats();
         println!("--- trans stats ---");
@@ -2758,72 +2642,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-/// We visit all the items in the krate and translate them.  We do
-/// this in two walks. The first walk just finds module items. It then
-/// walks the full contents of those module items and translates all
-/// the items within. Note that this entire process is O(n). The
-/// reason for this two phased walk is that each module is
-/// (potentially) placed into a distinct codegen-unit. This walk also
-/// ensures that the immediate contents of each module is processed
-/// entirely before we proceed to find more modules, helping to ensure
-/// an equitable distribution amongst codegen-units.
-pub struct TransModVisitor<'a, 'tcx: 'a> {
-    pub ccx: &'a CrateContext<'a, 'tcx>,
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for TransModVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &hir::Item) {
-        match i.node {
-            hir::ItemMod(_) => {
-                let item_ccx = self.ccx.rotate();
-                intravisit::walk_item(&mut TransItemsWithinModVisitor { ccx: &item_ccx }, i);
-            }
-            _ => { }
-        }
-    }
-}
-
-/// Translates all the items within a given module. Expects owner to
-/// invoke `walk_item` on a module item. Ignores nested modules.
-pub struct TransItemsWithinModVisitor<'a, 'tcx: 'a> {
-    pub ccx: &'a CrateContext<'a, 'tcx>,
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
-    fn visit_nested_item(&mut self, item_id: hir::ItemId) {
-        self.visit_item(self.ccx.tcx().map.expect_item(item_id.id));
-    }
-
-    fn visit_item(&mut self, i: &hir::Item) {
-        match i.node {
-            hir::ItemMod(..) => {
-                // skip modules, they will be uncovered by the TransModVisitor
-            }
-            _ => {
-                let def_id = self.ccx.tcx().map.local_def_id(i.id);
-                let tcx = self.ccx.tcx();
-
-                // Create a subtask for trans'ing a particular item. We are
-                // giving `trans_item` access to this item, so also record a read.
-                tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
-                    tcx.dep_graph.read(DepNode::Hir(def_id));
-
-                    // We are going to be accessing various tables
-                    // generated by TypeckItemBody; we also assume
-                    // that the body passes type check. These tables
-                    // are not individually tracked, so just register
-                    // a read here.
-                    tcx.dep_graph.read(DepNode::TypeckItemBody(def_id));
-
-                    trans_item(self.ccx, i);
-                });
-
-                intravisit::walk_item(self, i);
-            }
-        }
-    }
-}
-
 fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
                                                      -> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
     let time_passes = scx.sess().time_passes();
index b992ba362a98321ef64505b7858cff6f021b85ff..90443d9ec4f7067b0406ec02db37d4ab974e0f39 100644 (file)
@@ -169,14 +169,14 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }));
     let llfn = declare::declare_fn(ccx, &symbol, function_type);
 
-    // set an inline hint for all closures
-    attributes::inline(llfn, attributes::InlineAttr::Hint);
     attributes::set_frame_pointer_elimination(ccx, llfn);
 
     debug!("get_or_create_declaration_if_closure(): inserting new \
             closure {:?}: {:?}",
            instance, Value(llfn));
-    ccx.instances().borrow_mut().insert(instance, llfn);
+
+    // NOTE: We do *not* store llfn in the ccx.instances() map here,
+    //       that is only done, when the closures body is translated.
 
     llfn
 }
@@ -197,8 +197,8 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // (*) Note that in the case of inlined functions, the `closure_def_id` will be the
     // defid of the closure in its original crate, whereas `id` will be the id of the local
     // inlined copy.
-
-    let param_substs = closure_substs.func_substs;
+    debug!("trans_closure_expr(id={:?}, closure_def_id={:?}, closure_substs={:?})",
+           id, closure_def_id, closure_substs);
 
     let ccx = match dest {
         Dest::SaveIn(bcx, _) => bcx.ccx(),
@@ -207,41 +207,49 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     let tcx = ccx.tcx();
     let _icx = push_ctxt("closure::trans_closure_expr");
 
-    debug!("trans_closure_expr(id={:?}, closure_def_id={:?}, closure_substs={:?})",
-           id, closure_def_id, closure_substs);
-
-    let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
-    llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
-    llvm::SetUniqueComdat(ccx.llmod(), llfn);
-
-    // Get the type of this closure. Use the current `param_substs` as
-    // the closure substitutions. This makes sense because the closure
-    // takes the same set of type arguments as the enclosing fn, and
-    // this function (`trans_closure`) is invoked at the point
-    // of the closure expression.
-
-    let sig = &tcx.closure_type(closure_def_id, closure_substs).sig;
-    let sig = tcx.erase_late_bound_regions(sig);
-    let sig = tcx.normalize_associated_type(&sig);
-
-    let closure_type = tcx.mk_closure_from_closure_substs(closure_def_id,
-                                                          closure_substs);
-    let sig = ty::FnSig {
-        inputs: Some(get_self_type(tcx, closure_def_id, closure_type))
-                    .into_iter().chain(sig.inputs).collect(),
-        output: sig.output,
-        variadic: false
-    };
-
-    trans_closure(ccx,
-                  decl,
-                  body,
-                  llfn,
-                  Instance::new(closure_def_id, param_substs),
-                  id,
-                  &sig,
-                  Abi::RustCall,
-                  ClosureEnv::Closure(closure_def_id, id));
+    let param_substs = closure_substs.func_substs;
+    let instance = Instance::new(closure_def_id, param_substs);
+
+    // If we have not done so yet, translate this closure's body
+    if  !ccx.instances().borrow().contains_key(&instance) {
+        let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
+        llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
+        llvm::SetUniqueComdat(ccx.llmod(), llfn);
+
+        // set an inline hint for all closures
+        attributes::inline(llfn, attributes::InlineAttr::Hint);
+
+        // Get the type of this closure. Use the current `param_substs` as
+        // the closure substitutions. This makes sense because the closure
+        // takes the same set of type arguments as the enclosing fn, and
+        // this function (`trans_closure`) is invoked at the point
+        // of the closure expression.
+
+        let sig = &tcx.closure_type(closure_def_id, closure_substs).sig;
+        let sig = tcx.erase_late_bound_regions(sig);
+        let sig = tcx.normalize_associated_type(&sig);
+
+        let closure_type = tcx.mk_closure_from_closure_substs(closure_def_id,
+                                                              closure_substs);
+        let sig = ty::FnSig {
+            inputs: Some(get_self_type(tcx, closure_def_id, closure_type))
+                        .into_iter().chain(sig.inputs).collect(),
+            output: sig.output,
+            variadic: false
+        };
+
+        trans_closure(ccx,
+                      decl,
+                      body,
+                      llfn,
+                      Instance::new(closure_def_id, param_substs),
+                      id,
+                      &sig,
+                      Abi::RustCall,
+                      ClosureEnv::Closure(closure_def_id, id));
+
+        ccx.instances().borrow_mut().insert(instance, llfn);
+    }
 
     // Don't hoist this to the top of the function. It's perfectly legitimate
     // to have a zero-size closure (in which case dest will be `Ignore`) and
index 5732fded362f58fd132c16b8313be3ac021783b9..00feb2cd1de0961f5ec1e97965ea1480d3ee3543 100644 (file)
@@ -900,7 +900,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
                 Def::Variant(enum_did, variant_did) => {
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
-                    match vinfo.kind() {
+                    match vinfo.kind {
                         ty::VariantKind::Unit => {
                             let repr = adt::represent_type(cx, ety);
                             adt::trans_const(cx, &repr, Disr::from(vinfo.disr_val), &[])
index b8d231db40a2af48aeda9bc1061b5f3f580f20a2..88903726d64f7bbee90ed58128e6ec7391d566eb 100644 (file)
@@ -219,14 +219,6 @@ pub fn iter<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
         }
     }
 
-    pub fn get_ccx<'b>(&'b self, index: usize) -> CrateContext<'b, 'tcx> {
-        CrateContext {
-            shared: self.shared,
-            index: index,
-            local_ccxs: &self.local_ccxs[..],
-        }
-    }
-
     pub fn shared(&self) -> &'a SharedCrateContext<'a, 'tcx> {
         self.shared
     }
index 2b079e7dcc8d9cd483c5db3786435f2750a2dae0..0b75402486812b4706706c1363a284cdd2341ffd 100644 (file)
@@ -313,7 +313,7 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        PatKind::Path(..) | PatKind::QPath(..) => {
+        PatKind::Path(..) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
         }
 
index 34dedeede98e0c6ef480df93c2374cad40164e05..b84cc028d0ced97d4166f805aefba6ec8acd2a3d 100644 (file)
@@ -1109,7 +1109,7 @@ struct StructMemberDescriptionFactory<'tcx> {
 impl<'tcx> StructMemberDescriptionFactory<'tcx> {
     fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
                                       -> Vec<MemberDescription> {
-        if let ty::VariantKind::Unit = self.variant.kind() {
+        if self.variant.kind == ty::VariantKind::Unit {
             return Vec::new();
         }
 
@@ -1126,7 +1126,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
         };
 
         self.variant.fields.iter().enumerate().map(|(i, f)| {
-            let name = if let ty::VariantKind::Tuple = self.variant.kind() {
+            let name = if self.variant.kind == ty::VariantKind::Tuple {
                 format!("__{}", i)
             } else {
                 f.name.to_string()
@@ -1356,7 +1356,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
                 // For the metadata of the wrapper struct, we need to create a
                 // MemberDescription of the struct's single field.
                 let sole_struct_member_description = MemberDescription {
-                    name: match non_null_variant.kind() {
+                    name: match non_null_variant.kind {
                         ty::VariantKind::Tuple => "__0".to_string(),
                         ty::VariantKind::Struct => {
                             non_null_variant.fields[0].name.to_string()
@@ -1524,7 +1524,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                            containing_scope);
 
     // Get the argument names from the enum variant info
-    let mut arg_names: Vec<_> = match variant.kind() {
+    let mut arg_names: Vec<_> = match variant.kind {
         ty::VariantKind::Unit => vec![],
         ty::VariantKind::Tuple => {
             variant.fields
index b7b18b2631bee91f5148405b28713265fa0b9758..d3271e6d44c3a71877b948dd30fbcee4f2ac5890 100644 (file)
@@ -28,6 +28,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst;
+use rustc::dep_graph::DepNode;
 use std::hash::{Hash, Hasher};
 use syntax::ast::{self, NodeId};
 use syntax::{attr,errors};
@@ -73,6 +74,8 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
                   self.to_raw_string(),
                   ccx.codegen_unit().name);
 
+        self.register_reads(ccx);
+
         match *self {
             TransItem::Static(node_id) => {
                 let item = ccx.tcx().map.expect_item(node_id);
@@ -99,6 +102,46 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
                ccx.codegen_unit().name);
     }
 
+    /// If necessary, creates a subtask for trans'ing a particular item and registers reads on
+    /// `TypeckItemBody` and `Hir`.
+    fn register_reads(&self, ccx: &CrateContext<'a, 'tcx>) {
+        let tcx = ccx.tcx();
+        let def_id = match *self {
+            TransItem::Static(node_id) => {
+                tcx.map.local_def_id(node_id)
+            }
+            TransItem::Fn(instance) => {
+                if let Some(node) = tcx.map.as_local_node_id(instance.def) {
+                    if let hir_map::Node::NodeItem(_) = tcx.map.get(node) {
+                        // This already is a "real" item
+                        instance.def
+                    } else {
+                        // Get the enclosing item and register a read on it
+                        tcx.map.get_parent_did(node)
+                    }
+                } else {
+                    // Translating an inlined item from another crate? Don't track anything.
+                    return;
+                }
+            }
+            TransItem::DropGlue(_) => {
+                // Nothing to track for drop glue
+                return;
+            }
+        };
+
+        tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
+            tcx.dep_graph.read(DepNode::Hir(def_id));
+
+            // We are going to be accessing various tables
+            // generated by TypeckItemBody; we also assume
+            // that the body passes type check. These tables
+            // are not individually tracked, so just register
+            // a read here.
+            tcx.dep_graph.read(DepNode::TypeckItemBody(def_id));
+        });
+    }
+
     pub fn predefine(&self,
                      ccx: &CrateContext<'a, 'tcx>,
                      linkage: llvm::Linkage) {
index 088ac1aac1a4016926e9507b8790a43d6e3eb335..9ff30f9ede26295d85f4e94c853d817ce3bf3d84 100644 (file)
@@ -53,7 +53,7 @@
 use rustc_const_eval::EvalHint::UncheckedExprHint;
 use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
 use hir::{self, SelfKind};
-use hir::def::{self, Def};
+use hir::def::{Def, PathResolution};
 use hir::def_id::DefId;
 use hir::print as pprust;
 use middle::resolve_lifetime as rl;
@@ -1327,7 +1327,7 @@ fn associated_path_def_to_ty(&self,
                 };
 
                 if self.ensure_super_predicates(span, trait_did).is_err() {
-                    return (tcx.types.err, ty_path_def);
+                    return (tcx.types.err, Def::Err);
                 }
 
                 let candidates: Vec<ty::PolyTraitRef> =
@@ -1341,7 +1341,7 @@ fn associated_path_def_to_ty(&self,
                                                     &assoc_name.as_str(),
                                                     span) {
                     Ok(bound) => bound,
-                    Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
             (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
@@ -1351,7 +1351,7 @@ fn associated_path_def_to_ty(&self,
                                                      assoc_name,
                                                      span) {
                     Ok(bound) => bound,
-                    Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
             (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
@@ -1361,7 +1361,7 @@ fn associated_path_def_to_ty(&self,
                                                      assoc_name,
                                                      span) {
                     Ok(bound) => bound,
-                    Err(ErrorReported) => return (tcx.types.err, ty_path_def),
+                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
             _ => {
@@ -1369,7 +1369,7 @@ fn associated_path_def_to_ty(&self,
                                                       &ty.to_string(),
                                                       "Trait",
                                                       &assoc_name.as_str());
-                return (tcx.types.err, ty_path_def);
+                return (tcx.types.err, Def::Err);
             }
         };
 
@@ -1574,45 +1574,46 @@ fn base_def_to_ty(&self,
         }
     }
 
-    // Note that both base_segments and assoc_segments may be empty, although not at
-    // the same time.
+    // Resolve possibly associated type path into a type and final definition.
+    // Note that both base_segments and assoc_segments may be empty, although not at same time.
     pub fn finish_resolving_def_to_ty(&self,
                                       rscope: &RegionScope,
                                       span: Span,
                                       param_mode: PathParamMode,
-                                      mut def: Def,
+                                      base_def: Def,
                                       opt_self_ty: Option<Ty<'tcx>>,
                                       base_path_ref_id: ast::NodeId,
                                       base_segments: &[hir::PathSegment],
                                       assoc_segments: &[hir::PathSegment])
                                       -> (Ty<'tcx>, Def) {
-        debug!("finish_resolving_def_to_ty(def={:?}, \
+        // Convert the base type.
+        debug!("finish_resolving_def_to_ty(base_def={:?}, \
                 base_segments={:?}, \
                 assoc_segments={:?})",
-               def,
+               base_def,
                base_segments,
                assoc_segments);
-        let mut ty = self.base_def_to_ty(rscope,
-                                         span,
-                                         param_mode,
-                                         def,
-                                         opt_self_ty,
-                                         base_path_ref_id,
-                                         base_segments);
-        debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", ty);
+        let base_ty = self.base_def_to_ty(rscope,
+                                          span,
+                                          param_mode,
+                                          base_def,
+                                          opt_self_ty,
+                                          base_path_ref_id,
+                                          base_segments);
+        debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", base_ty);
+
         // If any associated type segments remain, attempt to resolve them.
+        let (mut ty, mut def) = (base_ty, base_def);
         for segment in assoc_segments {
             debug!("finish_resolving_def_to_ty: segment={:?}", segment);
-            if ty.sty == ty::TyError {
+            // This is pretty bad (it will fail except for T::A and Self::A).
+            let (new_ty, new_def) = self.associated_path_def_to_ty(span, ty, def, segment);
+            ty = new_ty;
+            def = new_def;
+
+            if def == Def::Err {
                 break;
             }
-            // This is pretty bad (it will fail except for T::A and Self::A).
-            let (a_ty, a_def) = self.associated_path_def_to_ty(span,
-                                                               ty,
-                                                               def,
-                                                               segment);
-            ty = a_ty;
-            def = a_def;
         }
         (ty, def)
     }
@@ -1719,23 +1720,22 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyPath(ref maybe_qself, ref path) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
                 let path_res = tcx.expect_resolution(ast_ty.id);
-                let def = path_res.base_def;
                 let base_ty_end = path.segments.len() - path_res.depth;
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| {
                     self.ast_ty_to_ty(rscope, &qself.ty)
                 });
-                let (ty, _def) = self.finish_resolving_def_to_ty(rscope,
-                                                                 ast_ty.span,
-                                                                 PathParamMode::Explicit,
-                                                                 def,
-                                                                 opt_self_ty,
-                                                                 ast_ty.id,
-                                                                 &path.segments[..base_ty_end],
-                                                                 &path.segments[base_ty_end..]);
-
-                if path_res.depth != 0 && ty.sty != ty::TyError {
-                    // Write back the new resolution.
-                    tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution::new(def));
+                let (ty, def) = self.finish_resolving_def_to_ty(rscope,
+                                                                ast_ty.span,
+                                                                PathParamMode::Explicit,
+                                                                path_res.base_def,
+                                                                opt_self_ty,
+                                                                ast_ty.id,
+                                                                &path.segments[..base_ty_end],
+                                                                &path.segments[base_ty_end..]);
+
+                // Write back the new resolution.
+                if path_res.depth != 0 {
+                    tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
                 }
 
                 ty
index 069a09183a738e7fd8cb6cd26fa871f1bbb6ef43..e90b32cd5dfc0192c5001b46a8dc2795acab7f39 100644 (file)
 
 use hir::def::Def;
 use rustc::infer::{self, InferOk, TypeOrigin};
-use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
+use hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
+use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference, VariantKind};
 use check::{FnCtxt, Expectation};
 use lint;
 use util::nodemap::FnvHashMap;
-use session::Session;
 
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::cmp;
 use rustc::hir::{self, PatKind};
 use rustc::hir::print as pprust;
 
-// This function exists due to the warning "diagnostic code E0164 already used"
-fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
-    let name = pprust::path_to_string(path);
-    let msg = format!("`{}` does not name a tuple variant or a tuple struct", name);
-    if lint {
-        sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
-                      pat.id,
-                      pat.span,
-                      msg);
-    } else {
-        span_err!(sess, pat.span, E0164, "{}", msg);
-    }
-}
-
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
         let tcx = self.tcx;
@@ -136,22 +121,6 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
                 // subtyping doesn't matter here, as the value is some kind of scalar
                 self.demand_eqtype(pat.span, expected, lhs_ty);
             }
-            PatKind::Path(..) if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
-                let const_did = tcx.expect_def(pat.id).def_id();
-                let const_scheme = tcx.lookup_item_type(const_did);
-                assert!(const_scheme.generics.is_empty());
-                let const_ty = self.instantiate_type_scheme(pat.span,
-                                                            &Substs::empty(),
-                                                            &const_scheme.ty);
-                self.write_ty(pat.id, const_ty);
-
-                // FIXME(#20489) -- we should limit the types here to scalars or something!
-
-                // As with PatKind::Lit, what we really want here is that there
-                // exist a LUB, but for the cases that can occur, subtype
-                // is good enough.
-                self.demand_suptype(pat.span, expected, const_ty);
-            }
             PatKind::Binding(bm, _, ref sub) => {
                 let typ = self.local_ty(pat.span, pat.id);
                 match bm {
@@ -197,33 +166,11 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
                 }
             }
             PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
-                self.check_pat_enum(pat, path, &subpats, ddpos, expected, true);
-            }
-            PatKind::Path(ref path) => {
-                self.check_pat_enum(pat, path, &[], None, expected, false);
+                self.check_pat_tuple_struct(pat, path, &subpats, ddpos, expected);
             }
-            PatKind::QPath(ref qself, ref path) => {
-                let self_ty = self.to_ty(&qself.ty);
-                let path_res = tcx.expect_resolution(pat.id);
-                if path_res.base_def == Def::Err {
-                    self.set_tainted_by_errors();
-                    self.write_error(pat.id);
-                    return;
-                }
-                if let Some((opt_ty, segments, def)) =
-                        self.resolve_ty_and_def_ufcs(path_res, Some(self_ty),
-                                                     path, pat.span, pat.id) {
-                    if self.check_assoc_item_is_const(def, pat.span) {
-                        let scheme = tcx.lookup_item_type(def.def_id());
-                        let predicates = tcx.lookup_predicates(def.def_id());
-                        self.instantiate_path(segments, scheme, &predicates,
-                                              opt_ty, def, pat.span, pat.id);
-                        let const_ty = self.node_ty(pat.id);
-                        self.demand_suptype(pat.span, expected, const_ty);
-                    } else {
-                        self.write_error(pat.id)
-                    }
-                }
+            PatKind::Path(ref opt_qself, ref path) => {
+                let opt_qself_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
+                self.check_pat_path(pat, opt_qself_ty, path, expected);
             }
             PatKind::Struct(ref path, ref fields, etc) => {
                 self.check_pat_struct(pat, path, fields, etc, expected);
@@ -403,20 +350,6 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
         // subtyping.
     }
 
-    fn check_assoc_item_is_const(&self, def: Def, span: Span) -> bool {
-        match def {
-            Def::AssociatedConst(..) => true,
-            Def::Method(..) => {
-                span_err!(self.tcx.sess, span, E0327,
-                          "associated items in match patterns must be constants");
-                false
-            }
-            _ => {
-                span_bug!(span, "non-associated item in check_assoc_item_is_const");
-            }
-        }
-    }
-
     pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
         if let PatKind::Binding(..) = inner.node {
             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
@@ -554,167 +487,166 @@ pub fn check_match(&self,
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
-                            path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
-                            etc: bool, expected: Ty<'tcx>) {
-        let tcx = self.tcx;
-
-        let def = tcx.expect_def(pat.id);
-        let variant = match self.def_struct_variant(def, path.span) {
-            Some((_, variant)) => variant,
-            None => {
-                let name = pprust::path_to_string(path);
-                span_err!(tcx.sess, pat.span, E0163,
-                          "`{}` does not name a struct or a struct variant", name);
-                self.write_error(pat.id);
-
-                for field in fields {
-                    self.check_pat(&field.node.pat, tcx.types.err);
-                }
-                return;
+    fn check_pat_struct(&self,
+                        pat: &'gcx hir::Pat,
+                        path: &hir::Path,
+                        fields: &'gcx [Spanned<hir::FieldPat>],
+                        etc: bool,
+                        expected: Ty<'tcx>)
+    {
+        // Resolve the path and check the definition for errors.
+        let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(path, pat.id,
+                                                                                 pat.span) {
+            variant_ty
+        } else {
+            self.write_error(pat.id);
+            for field in fields {
+                self.check_pat(&field.node.pat, self.tcx.types.err);
             }
+            return;
         };
 
-        let pat_ty = self.instantiate_type(def.def_id(), path);
-        let item_substs = match pat_ty.sty {
+        // Type check the path.
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
+        // Type check subpatterns.
+        let substs = match pat_ty.sty {
             ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
             _ => span_bug!(pat.span, "struct variant is not an ADT")
         };
-        self.demand_eqtype(pat.span, expected, pat_ty);
-        self.check_struct_pat_fields(pat.span, fields, variant, &item_substs, etc);
-
-        self.write_ty(pat.id, pat_ty);
-        self.write_substs(pat.id, ty::ItemSubsts {
-            substs: item_substs
-        });
+        self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
     }
 
-    fn check_pat_enum(&self,
+    fn check_pat_path(&self,
                       pat: &hir::Pat,
+                      opt_self_ty: Option<Ty<'tcx>>,
                       path: &hir::Path,
-                      subpats: &'gcx [P<hir::Pat>],
-                      ddpos: Option<usize>,
-                      expected: Ty<'tcx>,
-                      is_tuple_struct_pat: bool)
+                      expected: Ty<'tcx>)
     {
-        // Typecheck the path.
         let tcx = self.tcx;
-
-        let path_res = tcx.expect_resolution(pat.id);
-        if path_res.base_def == Def::Err {
-            self.set_tainted_by_errors();
+        let report_unexpected_def = || {
+            span_err!(tcx.sess, pat.span, E0533,
+                      "`{}` does not name a unit variant, unit struct or a constant",
+                      pprust::path_to_string(path));
             self.write_error(pat.id);
-
-            for pat in subpats {
-                self.check_pat(&pat, tcx.types.err);
-            }
-            return;
-        }
-
-        let (opt_ty, segments, def) = match self.resolve_ty_and_def_ufcs(path_res,
-                                                                         None, path,
-                                                                         pat.span, pat.id) {
-            Some(resolution) => resolution,
-            // Error handling done inside resolve_ty_and_def_ufcs, so if
-            // resolution fails just return.
-            None => {return;}
         };
 
-        // Items that were partially resolved before should have been resolved to
-        // associated constants (i.e. not methods).
-        if path_res.depth != 0 && !self.check_assoc_item_is_const(def, pat.span) {
-            self.write_error(pat.id);
-            return;
+        // Resolve the path and check the definition for errors.
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
+                                                                   pat.id, pat.span);
+        match def {
+            Def::Err => {
+                self.set_tainted_by_errors();
+                self.write_error(pat.id);
+                return;
+            }
+            Def::Method(..) => {
+                report_unexpected_def();
+                return;
+            }
+            Def::Variant(..) | Def::Struct(..) => {
+                let variant = tcx.expect_variant_def(def);
+                if variant.kind != VariantKind::Unit {
+                    report_unexpected_def();
+                    return;
+                }
+            }
+            Def::Const(..) | Def::AssociatedConst(..) => {} // OK
+            _ => bug!("unexpected pattern definition {:?}", def)
         }
 
-        let enum_def = def.variant_def_ids()
-            .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
+        // Type check the path.
+        let scheme = tcx.lookup_item_type(def.def_id());
+        let predicates = tcx.lookup_predicates(def.def_id());
+        let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
+                                                 opt_ty, def, pat.span, pat.id);
+        self.demand_suptype(pat.span, expected, pat_ty);
+    }
 
-        let ctor_scheme = tcx.lookup_item_type(enum_def);
-        let ctor_predicates = tcx.lookup_predicates(enum_def);
-        let path_scheme = if ctor_scheme.ty.is_fn() {
-            let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
-            ty::TypeScheme {
-                ty: fn_ret.unwrap(),
-                generics: ctor_scheme.generics,
-            }
-        } else {
-            ctor_scheme
-        };
-        self.instantiate_path(segments, path_scheme, &ctor_predicates,
-                              opt_ty, def, pat.span, pat.id);
-        let report_bad_struct_kind = |is_warning| {
-            bad_struct_kind_err(tcx.sess, pat, path, is_warning);
-            if is_warning { return; }
+    fn check_pat_tuple_struct(&self,
+                              pat: &hir::Pat,
+                              path: &hir::Path,
+                              subpats: &'gcx [P<hir::Pat>],
+                              ddpos: Option<usize>,
+                              expected: Ty<'tcx>)
+    {
+        let tcx = self.tcx;
+        let on_error = || {
             self.write_error(pat.id);
             for pat in subpats {
                 self.check_pat(&pat, tcx.types.err);
             }
         };
-
-        // If we didn't have a fully resolved path to start with, we had an
-        // associated const, and we should quit now, since the rest of this
-        // function uses checks specific to structs and enums.
-        if path_res.depth != 0 {
-            if is_tuple_struct_pat {
-                report_bad_struct_kind(false);
+        let report_unexpected_def = |is_lint| {
+            let msg = format!("`{}` does not name a tuple variant or a tuple struct",
+                              pprust::path_to_string(path));
+            if is_lint {
+                tcx.sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
+                                  pat.id, pat.span, msg);
             } else {
-                let pat_ty = self.node_ty(pat.id);
-                self.demand_suptype(pat.span, expected, pat_ty);
+                span_err!(tcx.sess, pat.span, E0164, "{}", msg);
+                on_error();
             }
-            return;
-        }
-
-        let pat_ty = self.node_ty(pat.id);
-        self.demand_eqtype(pat.span, expected, pat_ty);
+        };
 
-        let real_path_ty = self.node_ty(pat.id);
-        let (kind_name, variant, expected_substs) = match real_path_ty.sty {
-            ty::TyEnum(enum_def, expected_substs) => {
-                let variant = enum_def.variant_of_def(def);
-                ("variant", variant, expected_substs)
-            }
-            ty::TyStruct(struct_def, expected_substs) => {
-                let variant = struct_def.struct_variant();
-                ("struct", variant, expected_substs)
-            }
-            _ => {
-                report_bad_struct_kind(false);
+        // Resolve the path and check the definition for errors.
+        let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
+        let variant = match def {
+            Def::Err => {
+                self.set_tainted_by_errors();
+                on_error();
                 return;
             }
-        };
-
-        match (is_tuple_struct_pat, variant.kind()) {
-            (true, ty::VariantKind::Unit) if subpats.is_empty() && ddpos.is_some() => {
-                // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
-                // is allowed for backward compatibility.
-                report_bad_struct_kind(true);
+            Def::Const(..) | Def::AssociatedConst(..) | Def::Method(..) => {
+                report_unexpected_def(false);
+                return;
             }
-            (true, ty::VariantKind::Unit) |
-            (false, ty::VariantKind::Tuple) |
-            (_, ty::VariantKind::Struct) => {
-                report_bad_struct_kind(false);
-                return
+            Def::Variant(..) | Def::Struct(..) => {
+                tcx.expect_variant_def(def)
             }
-            _ => {}
+            _ => bug!("unexpected pattern definition {:?}", def)
+        };
+        if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
+            // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
+            // is allowed for backward compatibility.
+            report_unexpected_def(true);
+        } else if variant.kind != VariantKind::Tuple {
+            report_unexpected_def(false);
+            return;
         }
 
+        // Type check the path.
+        let scheme = tcx.lookup_item_type(def.def_id());
+        let scheme = if scheme.ty.is_fn() {
+            // Replace constructor type with constructed type for tuple struct patterns.
+            let fn_ret = tcx.no_late_bound_regions(&scheme.ty.fn_ret()).unwrap().unwrap();
+            ty::TypeScheme { ty: fn_ret, generics: scheme.generics }
+        } else {
+            // Leave the type as is for unit structs (backward compatibility).
+            scheme
+        };
+        let predicates = tcx.lookup_predicates(def.def_id());
+        let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
+                                                 opt_ty, def, pat.span, pat.id);
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
+        // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
+            let substs = match pat_ty.sty {
+                ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
+                ref ty => bug!("unexpected pattern type {:?}", ty),
+            };
             for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
-                let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs);
+                let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
                 self.check_pat(&subpat, field_ty);
             }
         } else {
             span_err!(tcx.sess, pat.span, E0023,
-                      "this pattern has {} field{}, but the corresponding {} has {} field{}",
-                      subpats.len(), if subpats.len() == 1 {""} else {"s"},
-                      kind_name,
-                      variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
-
-            for pat in subpats {
-                self.check_pat(&pat, tcx.types.err);
-            }
+                      "this pattern has {} field{s}, but the corresponding {} has {} field{s}",
+                      subpats.len(), def.kind_name(), variant.fields.len(),
+                      s = if variant.fields.len() == 1 {""} else {"s"});
+            on_error();
         }
     }
 
index 3bc90f05d2536c2f41ebcef9a45dcfc4bc2a5a29..8daa16180a90515883f2b76516569e62503bb7fa 100644 (file)
@@ -84,7 +84,7 @@
 use dep_graph::DepNode;
 use fmt_macros::{Parser, Piece, Position};
 use middle::cstore::LOCAL_CRATE;
-use hir::def::{self, Def};
+use hir::def::{Def, PathResolution};
 use hir::def_id::DefId;
 use hir::pat_util;
 use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
@@ -1621,64 +1621,32 @@ fn normalize_associated_type(&self,
     ///
     /// Note that this function is only intended to be used with type-paths,
     /// not with value-paths.
-    pub fn instantiate_type(&self,
-                            did: DefId,
-                            path: &hir::Path)
-                            -> Ty<'tcx>
-    {
-        debug!("instantiate_type(did={:?}, path={:?})", did, path);
-        let type_scheme =
-            self.tcx.lookup_item_type(did);
-        let type_predicates =
-            self.tcx.lookup_predicates(did);
+    pub fn instantiate_type_path(&self,
+                                 did: DefId,
+                                 path: &hir::Path,
+                                 node_id: ast::NodeId)
+                                 -> Ty<'tcx> {
+        debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
+        let type_scheme = self.tcx.lookup_item_type(did);
+        let type_predicates = self.tcx.lookup_predicates(did);
         let substs = AstConv::ast_path_substs_for_ty(self, self,
                                                      path.span,
                                                      PathParamMode::Optional,
                                                      &type_scheme.generics,
                                                      path.segments.last().unwrap());
-        debug!("instantiate_type: ty={:?} substs={:?}", &type_scheme.ty, &substs);
-        let bounds =
-            self.instantiate_bounds(path.span, &substs, &type_predicates);
-        self.add_obligations_for_parameters(
-            traits::ObligationCause::new(
-                path.span,
-                self.body_id,
-                traits::ItemObligation(did)),
-            &bounds);
-
-        self.instantiate_type_scheme(path.span, &substs, &type_scheme.ty)
-    }
-
-    /// Return the dict-like variant corresponding to a given `Def`.
-    pub fn def_struct_variant(&self,
-                              def: Def,
-                              _span: Span)
-                              -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
-    {
-        let (adt, variant) = match def {
-            Def::Variant(enum_id, variant_id) => {
-                let adt = self.tcx.lookup_adt_def(enum_id);
-                (adt, adt.variant_with_id(variant_id))
-            }
-            Def::Struct(did) | Def::TyAlias(did) => {
-                let typ = self.tcx.lookup_item_type(did);
-                if let ty::TyStruct(adt, _) = typ.ty.sty {
-                    (adt, adt.struct_variant())
-                } else {
-                    return None;
-                }
-            }
-            _ => return None
-        };
+        let substs = self.tcx.mk_substs(substs);
+        debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
+        let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
+        let cause = traits::ObligationCause::new(path.span, self.body_id,
+                                                 traits::ItemObligation(did));
+        self.add_obligations_for_parameters(cause, &bounds);
 
-        let var_kind = variant.kind();
-        if var_kind == ty::VariantKind::Struct {
-            Some((adt, variant))
-        } else if var_kind == ty::VariantKind::Unit {
-             Some((adt, variant))
-         } else {
-             None
-         }
+        let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
+        self.write_ty(node_id, ty_substituted);
+        self.write_substs(node_id, ty::ItemSubsts {
+            substs: substs
+        });
+        ty_substituted
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
@@ -2998,7 +2966,7 @@ fn check_tup_field(&self,
         while let Some((base_t, autoderefs)) = autoderef.next() {
             let field = match base_t.sty {
                 ty::TyStruct(base_def, substs) => {
-                    tuple_like = base_def.struct_variant().is_tuple_struct();
+                    tuple_like = base_def.struct_variant().kind == ty::VariantKind::Tuple;
                     if !tuple_like { continue }
 
                     debug!("tuple struct named {:?}",  base_t);
@@ -3153,35 +3121,57 @@ fn check_struct_fields_on_error(&self,
         }
     }
 
+    pub fn check_struct_path(&self,
+                         path: &hir::Path,
+                         node_id: ast::NodeId,
+                         span: Span)
+                         -> Option<(ty::VariantDef<'tcx>,  Ty<'tcx>)> {
+        let def = self.finish_resolving_struct_path(path, node_id, span);
+        let variant = match def {
+            Def::Err => {
+                self.set_tainted_by_errors();
+                return None;
+            }
+            Def::Variant(..) | Def::Struct(..) => {
+                Some(self.tcx.expect_variant_def(def))
+            }
+            Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
+                if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did)
+                                                             .map(|scheme| &scheme.ty.sty) {
+                    Some(adt.struct_variant())
+                } else {
+                    None
+                }
+            }
+            _ => None
+        };
+        if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
+            // Reject tuple structs for now, braced and unit structs are allowed.
+            span_err!(self.tcx.sess, span, E0071,
+                      "`{}` does not name a struct or a struct variant",
+                      pprust::path_to_string(path));
+            return None;
+        }
+
+        let ty = self.instantiate_type_path(def.def_id(), path, node_id);
+        Some((variant.unwrap(), ty))
+    }
+
     fn check_expr_struct(&self,
                          expr: &hir::Expr,
                          path: &hir::Path,
                          fields: &'gcx [hir::Field],
                          base_expr: &'gcx Option<P<hir::Expr>>)
     {
-        let tcx = self.tcx;
-
         // Find the relevant variant
-        let def = tcx.expect_def(expr.id);
-        if def == Def::Err {
-            self.set_tainted_by_errors();
+        let (variant, expr_ty) = if let Some(variant_ty) = self.check_struct_path(path, expr.id,
+                                                                                  expr.span) {
+            variant_ty
+        } else {
             self.check_struct_fields_on_error(expr.id, fields, base_expr);
             return;
-        }
-        let variant = match self.def_struct_variant(def, path.span) {
-            Some((_, variant)) => variant,
-            None => {
-                span_err!(self.tcx.sess, path.span, E0071,
-                          "`{}` does not name a structure",
-                          pprust::path_to_string(path));
-                self.check_struct_fields_on_error(expr.id, fields, base_expr);
-                return;
-            }
         };
 
-        let expr_ty = self.instantiate_type(def.def_id(), path);
-        self.write_ty(expr.id, expr_ty);
-
         self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
@@ -3192,13 +3182,13 @@ fn check_expr_struct(&self,
                         expr.id,
                         adt.struct_variant().fields.iter().map(|f| {
                             self.normalize_associated_types_in(
-                                expr.span, &f.ty(tcx, substs)
+                                expr.span, &f.ty(self.tcx, substs)
                             )
                         }).collect()
                     );
                 }
                 _ => {
-                    span_err!(tcx.sess, base_expr.span, E0436,
+                    span_err!(self.tcx.sess, base_expr.span, E0436,
                               "functional record update syntax requires a struct");
                 }
             }
@@ -3349,24 +3339,18 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
             };
             self.write_ty(id, oprnd_t);
           }
-          hir::ExprPath(ref maybe_qself, ref path) => {
-              let opt_self_ty = maybe_qself.as_ref().map(|qself| {
-                  self.to_ty(&qself.ty)
-              });
-
-              let path_res = tcx.expect_resolution(id);
-              if let Some((opt_ty, segments, def)) =
-                      self.resolve_ty_and_def_ufcs(path_res, opt_self_ty, path,
-                                                   expr.span, expr.id) {
-                  if def != Def::Err {
-                      let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
-                                                                                         def);
-                      self.instantiate_path(segments, scheme, &predicates,
-                                            opt_ty, def, expr.span, id);
-                  } else {
-                      self.set_tainted_by_errors();
-                      self.write_ty(id, self.tcx.types.err);
-                  }
+          hir::ExprPath(ref opt_qself, ref path) => {
+              let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
+              let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
+                                                                         expr.id, expr.span);
+              if def != Def::Err {
+                  let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
+                                                                                     def);
+                  self.instantiate_value_path(segments, scheme, &predicates,
+                                              opt_ty, def, expr.span, id);
+              } else {
+                  self.set_tainted_by_errors();
+                  self.write_error(id);
               }
 
               // We always require that the type provided as the value for
@@ -3704,37 +3688,67 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
                expected);
     }
 
+    // Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
+    // The newly resolved definition is written into `def_map`.
+    pub fn finish_resolving_struct_path(&self,
+                                        path: &hir::Path,
+                                        node_id: ast::NodeId,
+                                        span: Span)
+                                        -> Def
+    {
+        let path_res = self.tcx().expect_resolution(node_id);
+        if path_res.depth == 0 {
+            // If fully resolved already, we don't have to do anything.
+            path_res.base_def
+        } else {
+            let base_ty_end = path.segments.len() - path_res.depth;
+            let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span,
+                                                                 PathParamMode::Optional,
+                                                                 path_res.base_def,
+                                                                 None,
+                                                                 node_id,
+                                                                 &path.segments[..base_ty_end],
+                                                                 &path.segments[base_ty_end..]);
+            // Write back the new resolution.
+            self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
+            def
+        }
+    }
+
+    // Resolve associated value path into a base type and associated constant or method definition.
+    // The newly resolved definition is written into `def_map`.
     pub fn resolve_ty_and_def_ufcs<'b>(&self,
-                                       path_res: def::PathResolution,
                                        opt_self_ty: Option<Ty<'tcx>>,
                                        path: &'b hir::Path,
-                                       span: Span,
-                                       node_id: ast::NodeId)
-                                       -> Option<(Option<Ty<'tcx>>, &'b [hir::PathSegment], Def)>
+                                       node_id: ast::NodeId,
+                                       span: Span)
+                                       -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
     {
-
-        // If fully resolved already, we don't have to do anything.
+        let path_res = self.tcx().expect_resolution(node_id);
         if path_res.depth == 0 {
-            Some((opt_self_ty, &path.segments, path_res.base_def))
+            // If fully resolved already, we don't have to do anything.
+            (path_res.base_def, opt_self_ty, &path.segments)
         } else {
-            let def = path_res.base_def;
+            // Try to resolve everything except for the last segment as a type.
             let ty_segments = path.segments.split_last().unwrap().1;
             let base_ty_end = path.segments.len() - path_res.depth;
             let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
                                                                  PathParamMode::Optional,
-                                                                 def,
+                                                                 path_res.base_def,
                                                                  opt_self_ty,
                                                                  node_id,
                                                                  &ty_segments[..base_ty_end],
                                                                  &ty_segments[base_ty_end..]);
+
+            // Resolve an associated constant or method on the previously resolved type.
             let item_segment = path.segments.last().unwrap();
             let item_name = item_segment.name;
             let def = match self.resolve_ufcs(span, item_name, ty, node_id) {
-                Ok(def) => Some(def),
+                Ok(def) => def,
                 Err(error) => {
                     let def = match error {
-                        method::MethodError::PrivateMatch(def) => Some(def),
-                        _ => None,
+                        method::MethodError::PrivateMatch(def) => def,
+                        _ => Def::Err,
                     };
                     if item_name != keywords::Invalid.name() {
                         self.report_method_error(span, ty, item_name, None, error);
@@ -3743,14 +3757,9 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
                 }
             };
 
-            if let Some(def) = def {
-                // Write back the new resolution.
-                self.tcx().def_map.borrow_mut().insert(node_id, def::PathResolution::new(def));
-                Some((Some(ty), slice::ref_slice(item_segment), def))
-            } else {
-                self.write_error(node_id);
-                None
-            }
+            // Write back the new resolution.
+            self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
+            (def, Some(ty), slice::ref_slice(item_segment))
         }
     }
 
@@ -3986,15 +3995,16 @@ fn type_scheme_and_predicates_for_def(&self,
 
     // Instantiates the given path, which must refer to an item with the given
     // number of type parameters and type.
-    pub fn instantiate_path(&self,
-                            segments: &[hir::PathSegment],
-                            type_scheme: TypeScheme<'tcx>,
-                            type_predicates: &ty::GenericPredicates<'tcx>,
-                            opt_self_ty: Option<Ty<'tcx>>,
-                            def: Def,
-                            span: Span,
-                            node_id: ast::NodeId) {
-        debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
+    pub fn instantiate_value_path(&self,
+                                  segments: &[hir::PathSegment],
+                                  type_scheme: TypeScheme<'tcx>,
+                                  type_predicates: &ty::GenericPredicates<'tcx>,
+                                  opt_self_ty: Option<Ty<'tcx>>,
+                                  def: Def,
+                                  span: Span,
+                                  node_id: ast::NodeId)
+                                  -> Ty<'tcx> {
+        debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
                segments,
                def,
                node_id,
@@ -4023,7 +4033,7 @@ pub fn instantiate_path(&self,
         //    actually pass through this function, but rather the
         //    `ast_ty_to_ty` function in `astconv`. However, in the case
         //    of struct patterns (and maybe literals) we do invoke
-        //    `instantiate_path` to get the general type of an instance of
+        //    `instantiate_value_path` to get the general type of an instance of
         //    a struct. (In these cases, there are actually no type
         //    parameters permitted at present, but perhaps we will allow
         //    them in the future.)
@@ -4246,20 +4256,21 @@ pub fn instantiate_path(&self,
                 }
                 Err(_) => {
                     span_bug!(span,
-                        "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
+                        "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                         self_ty,
                         impl_ty);
                 }
             }
         }
 
-        debug!("instantiate_path: type of {:?} is {:?}",
+        debug!("instantiate_value_path: type of {:?} is {:?}",
                node_id,
                ty_substituted);
         self.write_ty(node_id, ty_substituted);
         self.write_substs(node_id, ty::ItemSubsts {
             substs: substs
         });
+        ty_substituted
     }
 
     /// Finds the parameters that the user provided and adds them to `substs`. If too many
index 2c33d1a81556eb9f28cae32520627a8aefa6d822..41e7a467fa33a89ff80aa890306ccdaf63d1b511 100644 (file)
@@ -949,7 +949,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                   scheme: ty::TypeScheme<'tcx>,
                                   predicates: ty::GenericPredicates<'tcx>) {
     let tcx = ccx.tcx;
-    let ctor_ty = match variant.kind() {
+    let ctor_ty = match variant.kind {
         VariantKind::Unit | VariantKind::Struct => scheme.ty,
         VariantKind::Tuple => {
             let inputs: Vec<_> =
@@ -1040,15 +1040,17 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 def: &hir::VariantData)
                                 -> ty::AdtDefMaster<'tcx>
 {
-
     let did = ccx.tcx.map.local_def_id(it.id);
-    let ctor_id = if !def.is_struct() {
-        ccx.tcx.map.local_def_id(def.id())
-    } else {
-        did
-    };
-    ccx.tcx.intern_adt_def(did, ty::AdtKind::Struct,
-        vec![convert_struct_variant(ccx, ctor_id, it.name, ConstInt::Infer(0), def)])
+    // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
+    let ctor_id = if !def.is_struct() { Some(ccx.tcx.map.local_def_id(def.id())) } else { None };
+    let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
+                                               ConstInt::Infer(0), def)];
+    let adt = ccx.tcx.intern_adt_def(did, ty::AdtKind::Struct, variants);
+    if let Some(ctor_id) = ctor_id {
+        // Make adt definition available through constructor id as well.
+        ccx.tcx.insert_adt_def(ctor_id, adt);
+    }
+    adt
 }
 
     fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
index cdac66a2272379f43011c6ed51162afc3d7a5338..8769bc1a32b5080856297c7f7928c14e8b3eeb32 100644 (file)
@@ -1895,33 +1895,6 @@ fn my_start(argc: isize, argv: *const *const u8) -> isize {
 ```
 "##,
 
-E0163: r##"
-This error means that an attempt was made to match an enum variant as a
-struct type when the variant isn't a struct type:
-
-```compile_fail
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        B{i} => i, // error E0163
-    }
-}
-```
-
-Try using `()` instead:
-
-```
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        Foo::B(i) => i,
-    }
-}
-```
-"##,
-
 E0164: r##"
 This error means that an attempt was made to match a struct type enum
 variant as a non-struct type:
@@ -3225,42 +3198,6 @@ impl Foo for Bar {
 ```
 "##,
 
-E0327: r##"
-You cannot use associated items other than constant items as patterns. This
-includes method items. Example of erroneous code:
-
-```compile_fail
-enum B {}
-
-impl B {
-    fn bb() -> i32 { 0 }
-}
-
-fn main() {
-    match 0 {
-        B::bb => {} // error: associated items in match patterns must
-                    // be constants
-    }
-}
-```
-
-Please check that you're not using a method as a pattern. Example:
-
-```
-enum B {
-    ba,
-    bb
-}
-
-fn main() {
-    match B::ba {
-        B::bb => {} // ok!
-        _ => {}
-    }
-}
-```
-"##,
-
 E0329: r##"
 An attempt was made to access an associated constant through either a generic
 type parameter or `Self`. This is not supported yet. An example causing this
@@ -4106,6 +4043,7 @@ fn fly(&self) {} // And now that's ok!
 //  E0129,
 //  E0141,
 //  E0159, // use of trait `{}` as struct constructor
+//  E0163, // merged into E0071
     E0167,
 //  E0168,
 //  E0173, // manual implementations of unboxed closure traits are experimental
@@ -4162,4 +4100,5 @@ fn fly(&self) {} // And now that's ok!
     E0527, // expected {} elements, found {}
     E0528, // expected at least {} elements, found {}
     E0529, // slice pattern expects array or slice, not `{}`
+    E0533, // `{}` does not name a unit variant, unit struct or a constant
 }
index 8894b9732fe89250f32f7ead6c3ab0de0cf60b4d..3d6925041cf5b0e2839e3e1d5fea9e137f406149 100644 (file)
@@ -22,7 +22,6 @@
 use rustc::hir::print as pprust;
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::subst;
-use rustc::util::common::slice_pat;
 
 use rustc_const_eval::lookup_const_by_id;
 
@@ -204,7 +203,7 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let variant = tcx.lookup_adt_def(did).struct_variant();
 
     clean::Struct {
-        struct_type: match slice_pat(&&*variant.fields) {
+        struct_type: match &variant.fields[..] {
             &[] => doctree::Unit,
             &[_] if variant.kind == ty::VariantKind::Tuple => doctree::Newtype,
             &[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple,
index 7827459baa87f310818813f69320e9982cbd0859..7da17b3749104ecff45962ead1407cb111076556 100644 (file)
@@ -1904,7 +1904,7 @@ fn clean(&self, cx: &DocContext) -> Item {
 
 impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
     fn clean(&self, cx: &DocContext) -> Item {
-        let kind = match self.kind() {
+        let kind = match self.kind {
             ty::VariantKind::Unit => CLikeVariant,
             ty::VariantKind::Tuple => {
                 TupleVariant(
@@ -2578,9 +2578,9 @@ fn name_from_pat(p: &hir::Pat) -> String {
     match p.node {
         PatKind::Wild => "_".to_string(),
         PatKind::Binding(_, ref p, _) => p.node.to_string(),
-        PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p),
-        PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
-                                which is not allowed in function arguments"),
+        PatKind::TupleStruct(ref p, _, _) | PatKind::Path(None, ref p) => path_to_string(p),
+        PatKind::Path(..) => panic!("tried to get argument name from qualified PatKind::Path, \
+                                     which is not allowed in function arguments"),
         PatKind::Struct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", path_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
@@ -2653,7 +2653,7 @@ fn resolve_type(cx: &DocContext,
         Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(keywords::SelfType.name().to_string());
         }
-        Def::SelfTy(..) | Def::TyParam(..) => true,
+        Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
         _ => false,
     };
     let did = register_def(&*cx, def);
index 77c4a0f8174a3296d00a2a94a480d912375cead7..11c1b8b09d2cc7299ba2acd1630814b6c9b14109 100644 (file)
@@ -20,7 +20,6 @@
 
 use rustc::middle::cstore::LOCAL_CRATE;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::util::common::slice_pat;
 use syntax::abi::Abi;
 use rustc::hir;
 
@@ -471,7 +470,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        decl.decl)
             }
             clean::Tuple(ref typs) => {
-                match slice_pat(&&**typs) {
+                match &typs[..] {
                     &[] => primitive_link(f, clean::PrimitiveTuple, "()"),
                     &[ref one] => {
                         primitive_link(f, clean::PrimitiveTuple, "(")?;
index 2a2d41112ffae17fb0e156c3d9e4111ccc621181..1459420cdc00ce0b4f446ee5169ba36808f27070 100644 (file)
@@ -66,10 +66,80 @@ pub trait Error: Debug + Display + Reflect {
     /// The description should not contain newlines or sentence-ending
     /// punctuation, to facilitate embedding in larger user-facing
     /// strings.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    ///
+    /// match "xc".parse::<u32>() {
+    ///     Err(e) => {
+    ///         println!("Error: {}", e.description());
+    ///     }
+    ///     _ => println!("No error"),
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn description(&self) -> &str;
 
     /// The lower-level cause of this error, if any.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperError {
+    ///     side: SuperErrorSideKick,
+    /// }
+    ///
+    /// impl fmt::Display for SuperError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperError is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperError {
+    ///     fn description(&self) -> &str {
+    ///         "I'm the superhero of errors!"
+    ///     }
+    ///
+    ///     fn cause(&self) -> Option<&Error> {
+    ///         Some(&self.side)
+    ///     }
+    /// }
+    ///
+    /// #[derive(Debug)]
+    /// struct SuperErrorSideKick;
+    ///
+    /// impl fmt::Display for SuperErrorSideKick {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "SuperErrorSideKick is here!")
+    ///     }
+    /// }
+    ///
+    /// impl Error for SuperErrorSideKick {
+    ///     fn description(&self) -> &str {
+    ///         "I'm SuperError side kick!"
+    ///     }
+    /// }
+    ///
+    /// fn get_super_error() -> Result<(), SuperError> {
+    ///     Err(SuperError { side: SuperErrorSideKick })
+    /// }
+    ///
+    /// fn main() {
+    ///     match get_super_error() {
+    ///         Err(e) => {
+    ///             println!("Error: {}", e.description());
+    ///             println!("Caused by: {}", e.cause().unwrap());
+    ///         }
+    ///         _ => println!("No error"),
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn cause(&self) -> Option<&Error> { None }
 
index 668fa1fb303601cefa74c819c7a9d2cf974fb5f0..83439b3f132153eef1009c507e2bec78318aa408 100644 (file)
@@ -141,7 +141,7 @@ pub struct File {
 
 /// An structure representing a type of file with accessors for each file type.
 #[stable(feature = "file_type", since = "1.1.0")]
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType(fs_imp::FileType);
 
 /// A builder used to create directories in various manners.
index 07f43f72ff55ab1d987b60c70c37b909695f27a3..c8b52fc046769b9ca59986a6ec5e621dee8b9d6b 100644 (file)
@@ -152,8 +152,8 @@ pub struct Sink { _priv: () }
 /// ```rust
 /// use std::io::{self, Write};
 ///
-/// let mut buffer = vec![1, 2, 3, 5, 8];
-/// let num_bytes = io::sink().write(&mut buffer).unwrap();
+/// let buffer = vec![1, 2, 3, 5, 8];
+/// let num_bytes = io::sink().write(&buffer).unwrap();
 /// assert_eq!(num_bytes, 5);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
index a396c7be09ad16db2effaf51845b45085bd80d47..d05a5a0961483f81202dcc14223d20f109223657 100644 (file)
@@ -468,15 +468,3 @@ pub mod __rand {
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
 include!("primitive_docs.rs");
-
-// FIXME(stage0): remove this after a snapshot
-// HACK: this is needed because the interpretation of slice
-// patterns changed between stage0 and now.
-#[cfg(stage0)]
-fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'a &'b [T] {
-    t
-}
-#[cfg(not(stage0))]
-fn slice_pat<'a, 'b, T>(t: &'a &'b [T]) -> &'b [T] {
-    *t
-}
index 2edd1a3063810712f56937201c70b398143d8ddc..16bc81de78ecf6debe8f6371eedf905779e5f3b9 100644 (file)
@@ -27,8 +27,9 @@
 /// Representation of a running or exited child process.
 ///
 /// This structure is used to represent and manage child processes. A child
-/// process is created via the `Command` struct, which configures the spawning
-/// process and can itself be constructed using a builder-style interface.
+/// process is created via the [`Command`] struct, which configures the
+/// spawning process and can itself be constructed using a builder-style
+/// interface.
 ///
 /// # Examples
 ///
 ///
 /// # Note
 ///
-/// Take note that there is no implementation of
-/// [`Drop`](../../core/ops/trait.Drop.html) for child processes, so if you
-/// do not ensure the `Child` has exited then it will continue to run, even
-/// after the `Child` handle to the child process has gone out of scope.
+/// Take note that there is no implementation of [`Drop`] for child processes,
+/// so if you do not ensure the `Child` has exited then it will continue to
+/// run, even after the `Child` handle to the child process has gone out of
+/// scope.
 ///
-/// Calling `wait` (or other functions that wrap around it) will make the
-/// parent process wait until the child has actually exited before continuing.
+/// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
+/// the parent process wait until the child has actually exited before
+/// continuing.
+///
+/// [`Command`]: struct.Command.html
+/// [`Drop`]: ../../core/ops/trait.Drop.html
+/// [`wait`]: #method.wait
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Child {
     handle: imp::Process,
@@ -91,7 +97,11 @@ impl IntoInner<imp::Process> for Child {
     fn into_inner(self) -> imp::Process { self.handle }
 }
 
-/// A handle to a child process's stdin
+/// A handle to a child process's stdin. This struct is used in the [`stdin`]
+/// field on [`Child`].
+///
+/// [`Child`]: struct.Child.html
+/// [`stdin`]: struct.Child.html#structfield.stdin
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdin {
     inner: AnonPipe
@@ -122,7 +132,11 @@ fn from_inner(pipe: AnonPipe) -> ChildStdin {
     }
 }
 
-/// A handle to a child process's stdout
+/// A handle to a child process's stdout. This struct is used in the [`stdout`]
+/// field on [`Child`].
+///
+/// [`Child`]: struct.Child.html
+/// [`stdout`]: struct.Child.html#structfield.stdout
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdout {
     inner: AnonPipe
@@ -152,7 +166,11 @@ fn from_inner(pipe: AnonPipe) -> ChildStdout {
     }
 }
 
-/// A handle to a child process's stderr
+/// A handle to a child process's stderr. This struct is used in the [`stderr`]
+/// field on [`Child`].
+///
+/// [`Child`]: struct.Child.html
+/// [`stderr`]: struct.Child.html#structfield.stderr
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStderr {
     inner: AnonPipe
index bf4b119a0b6669027f1efa0638fa332428a99cd3..3c52ebc72f2cb279f187dbfdd1a1c15af580eebe 100644 (file)
@@ -15,7 +15,7 @@
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
 use sys_common::poison::{self, LockResult};
-use time::{Instant, Duration};
+use time::Duration;
 
 /// A type indicating whether a timed wait on a condition variable returned
 /// due to a time out or not.
@@ -72,59 +72,19 @@ pub fn timed_out(&self) -> bool {
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub struct Condvar { inner: Box<StaticCondvar> }
-
-/// Statically allocated condition variables.
-///
-/// This structure is identical to `Condvar` except that it is suitable for use
-/// in static initializers for other structures.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(static_condvar)]
-///
-/// use std::sync::{StaticCondvar, CONDVAR_INIT};
-///
-/// static CVAR: StaticCondvar = CONDVAR_INIT;
-/// ```
-#[unstable(feature = "static_condvar",
-           reason = "may be merged with Condvar in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Condvar::new` in a static should \
-                             suffice")]
-pub struct StaticCondvar {
-    inner: sys::Condvar,
+pub struct Condvar {
+    inner: Box<sys::Condvar>,
     mutex: AtomicUsize,
 }
 
-/// Constant initializer for a statically allocated condition variable.
-#[unstable(feature = "static_condvar",
-           reason = "may be merged with Condvar in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Condvar::new` in a static should \
-                             suffice")]
-#[allow(deprecated)]
-pub const CONDVAR_INIT: StaticCondvar = StaticCondvar::new();
-
-#[allow(deprecated)]
 impl Condvar {
     /// Creates a new condition variable which is ready to be waited on and
     /// notified.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Condvar {
         Condvar {
-            inner: box StaticCondvar {
-                inner: sys::Condvar::new(),
-                mutex: AtomicUsize::new(0),
-            }
+            inner: box sys::Condvar::new(),
+            mutex: AtomicUsize::new(0),
         }
     }
 
@@ -157,9 +117,16 @@ pub fn new() -> Condvar {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
                        -> LockResult<MutexGuard<'a, T>> {
-        unsafe {
-            let me: &'static Condvar = &*(self as *const _);
-            me.inner.wait(guard)
+        let poisoned = unsafe {
+            let lock = mutex::guard_lock(&guard);
+            self.verify(lock);
+            self.inner.wait(lock);
+            mutex::guard_poison(&guard).get()
+        };
+        if poisoned {
+            Err(PoisonError::new(guard))
+        } else {
+            Ok(guard)
         }
     }
 
@@ -206,9 +173,16 @@ pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
     pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
                                dur: Duration)
                                -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
-        unsafe {
-            let me: &'static Condvar = &*(self as *const _);
-            me.inner.wait_timeout(guard, dur)
+        let (poisoned, result) = unsafe {
+            let lock = mutex::guard_lock(&guard);
+            self.verify(lock);
+            let success = self.inner.wait_timeout(lock, dur);
+            (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
+        };
+        if poisoned {
+            Err(PoisonError::new((guard, result)))
+        } else {
+            Ok((guard, result))
         }
     }
 
@@ -220,7 +194,9 @@ pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
     ///
     /// To wake up all threads, see `notify_all()`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
+    pub fn notify_one(&self) {
+        unsafe { self.inner.notify_one() }
+    }
 
     /// Wakes up all blocked threads on this condvar.
     ///
@@ -230,169 +206,8 @@ pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
     ///
     /// To wake up only one thread, see `notify_one()`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
-}
-
-#[stable(feature = "condvar_default", since = "1.9.0")]
-impl Default for Condvar {
-    fn default() -> Condvar {
-        Condvar::new()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-impl Drop for Condvar {
-    fn drop(&mut self) {
-        unsafe { self.inner.inner.destroy() }
-    }
-}
-
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Condvar::new` in a static should \
-                             suffice")]
-#[unstable(feature = "static_condvar",
-           reason = "may be merged with Condvar in the future",
-           issue = "27717")]
-#[allow(deprecated)]
-impl StaticCondvar {
-    /// Creates a new condition variable
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub const fn new() -> StaticCondvar {
-        StaticCondvar {
-            inner: sys::Condvar::new(),
-            mutex: AtomicUsize::new(0),
-        }
-    }
-
-    /// Blocks the current thread until this condition variable receives a
-    /// notification.
-    ///
-    /// See `Condvar::wait`.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
-                       -> LockResult<MutexGuard<'a, T>> {
-        let poisoned = unsafe {
-            let lock = mutex::guard_lock(&guard);
-            self.verify(lock);
-            self.inner.wait(lock);
-            mutex::guard_poison(&guard).get()
-        };
-        if poisoned {
-            Err(PoisonError::new(guard))
-        } else {
-            Ok(guard)
-        }
-    }
-
-    /// Waits on this condition variable for a notification, timing out after a
-    /// specified duration.
-    ///
-    /// See `Condvar::wait_timeout`.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub fn wait_timeout<'a, T>(&'static self,
-                               guard: MutexGuard<'a, T>,
-                               timeout: Duration)
-                               -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
-        let (poisoned, result) = unsafe {
-            let lock = mutex::guard_lock(&guard);
-            self.verify(lock);
-            let success = self.inner.wait_timeout(lock, timeout);
-            (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
-        };
-        if poisoned {
-            Err(PoisonError::new((guard, result)))
-        } else {
-            Ok((guard, result))
-        }
-    }
-
-    /// Waits on this condition variable for a notification, timing out after a
-    /// specified duration.
-    ///
-    /// The implementation will repeatedly wait while the duration has not
-    /// passed and the function returns `false`.
-    ///
-    /// See `Condvar::wait_timeout_with`.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub fn wait_timeout_with<'a, T, F>(&'static self,
-                                       guard: MutexGuard<'a, T>,
-                                       dur: Duration,
-                                       mut f: F)
-                                       -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
-            where F: FnMut(LockResult<&mut T>) -> bool {
-        // This could be made more efficient by pushing the implementation into
-        // sys::condvar
-        let start = Instant::now();
-        let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard);
-        while !f(guard_result
-                    .as_mut()
-                    .map(|g| &mut **g)
-                    .map_err(|e| PoisonError::new(&mut **e.get_mut()))) {
-            let consumed = start.elapsed();
-            let guard = guard_result.unwrap_or_else(|e| e.into_inner());
-            let (new_guard_result, timed_out) = if consumed > dur {
-                (Ok(guard), WaitTimeoutResult(true))
-            } else {
-                match self.wait_timeout(guard, dur - consumed) {
-                    Ok((new_guard, timed_out)) => (Ok(new_guard), timed_out),
-                    Err(err) => {
-                        let (new_guard, no_timeout) = err.into_inner();
-                        (Err(PoisonError::new(new_guard)), no_timeout)
-                    }
-                }
-            };
-            guard_result = new_guard_result;
-            if timed_out.timed_out() {
-                let result = f(guard_result
-                                    .as_mut()
-                                    .map(|g| &mut **g)
-                                    .map_err(|e| PoisonError::new(&mut **e.get_mut())));
-                let result = WaitTimeoutResult(!result);
-                return poison::map_result(guard_result, |g| (g, result));
-            }
-        }
-
-        poison::map_result(guard_result, |g| (g, WaitTimeoutResult(false)))
-    }
-
-    /// Wakes up one blocked thread on this condvar.
-    ///
-    /// See `Condvar::notify_one`.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
-
-    /// Wakes up all blocked threads on this condvar.
-    ///
-    /// See `Condvar::notify_all`.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
-
-    /// Deallocates all resources associated with this static condvar.
-    ///
-    /// This method is unsafe to call as there is no guarantee that there are no
-    /// active users of the condvar, and this also doesn't prevent any future
-    /// users of the condvar. This method is required to be called to not leak
-    /// memory on all platforms.
-    #[unstable(feature = "static_condvar",
-               reason = "may be merged with Condvar in the future",
-               issue = "27717")]
-    pub unsafe fn destroy(&'static self) {
-        self.inner.destroy()
+    pub fn notify_all(&self) {
+        unsafe { self.inner.notify_all() }
     }
 
     fn verify(&self, mutex: &sys_mutex::Mutex) {
@@ -414,15 +229,26 @@ fn verify(&self, mutex: &sys_mutex::Mutex) {
     }
 }
 
+#[stable(feature = "condvar_default", since = "1.9.0")]
+impl Default for Condvar {
+    fn default() -> Condvar {
+        Condvar::new()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Drop for Condvar {
+    fn drop(&mut self) {
+        unsafe { self.inner.destroy() }
+    }
+}
+
 #[cfg(test)]
-#[allow(deprecated)]
 mod tests {
     use prelude::v1::*;
 
-    use super::StaticCondvar;
     use sync::mpsc::channel;
-    use sync::{StaticMutex, Condvar, Mutex, Arc};
-    use sync::atomic::{AtomicUsize, Ordering};
+    use sync::{Condvar, Mutex, Arc};
     use thread;
     use time::Duration;
     use u32;
@@ -434,27 +260,20 @@ fn smoke() {
         c.notify_all();
     }
 
-    #[test]
-    fn static_smoke() {
-        static C: StaticCondvar = StaticCondvar::new();
-        C.notify_one();
-        C.notify_all();
-        unsafe { C.destroy(); }
-    }
-
     #[test]
     fn notify_one() {
-        static C: StaticCondvar = StaticCondvar::new();
-        static M: StaticMutex = StaticMutex::new();
+        let m = Arc::new(Mutex::new(()));
+        let m2 = m.clone();
+        let c = Arc::new(Condvar::new());
+        let c2 = c.clone();
 
-        let g = M.lock().unwrap();
+        let g = m.lock().unwrap();
         let _t = thread::spawn(move|| {
-            let _g = M.lock().unwrap();
-            C.notify_one();
+            let _g = m2.lock().unwrap();
+            c2.notify_one();
         });
-        let g = C.wait(g).unwrap();
+        let g = c.wait(g).unwrap();
         drop(g);
-        unsafe { C.destroy(); M.destroy(); }
     }
 
     #[test]
@@ -495,84 +314,41 @@ fn notify_all() {
 
     #[test]
     fn wait_timeout_ms() {
-        static C: StaticCondvar = StaticCondvar::new();
-        static M: StaticMutex = StaticMutex::new();
+        let m = Arc::new(Mutex::new(()));
+        let m2 = m.clone();
+        let c = Arc::new(Condvar::new());
+        let c2 = c.clone();
 
-        let g = M.lock().unwrap();
-        let (g, _no_timeout) = C.wait_timeout(g, Duration::from_millis(1)).unwrap();
+        let g = m.lock().unwrap();
+        let (g, _no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap();
         // spurious wakeups mean this isn't necessarily true
         // assert!(!no_timeout);
         let _t = thread::spawn(move || {
-            let _g = M.lock().unwrap();
-            C.notify_one();
+            let _g = m2.lock().unwrap();
+            c2.notify_one();
         });
-        let (g, timeout_res) = C.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap();
+        let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap();
         assert!(!timeout_res.timed_out());
         drop(g);
-        unsafe { C.destroy(); M.destroy(); }
-    }
-
-    #[test]
-    fn wait_timeout_with() {
-        static C: StaticCondvar = StaticCondvar::new();
-        static M: StaticMutex = StaticMutex::new();
-        static S: AtomicUsize = AtomicUsize::new(0);
-
-        let g = M.lock().unwrap();
-        let (g, timed_out) = C.wait_timeout_with(g, Duration::new(0, 1000), |_| {
-            false
-        }).unwrap();
-        assert!(timed_out.timed_out());
-
-        let (tx, rx) = channel();
-        let _t = thread::spawn(move || {
-            rx.recv().unwrap();
-            let g = M.lock().unwrap();
-            S.store(1, Ordering::SeqCst);
-            C.notify_one();
-            drop(g);
-
-            rx.recv().unwrap();
-            let g = M.lock().unwrap();
-            S.store(2, Ordering::SeqCst);
-            C.notify_one();
-            drop(g);
-
-            rx.recv().unwrap();
-            let _g = M.lock().unwrap();
-            S.store(3, Ordering::SeqCst);
-            C.notify_one();
-        });
-
-        let mut state = 0;
-        let day = 24 * 60 * 60;
-        let (_g, timed_out) = C.wait_timeout_with(g, Duration::new(day, 0), |_| {
-            assert_eq!(state, S.load(Ordering::SeqCst));
-            tx.send(()).unwrap();
-            state += 1;
-            match state {
-                1|2 => false,
-                _ => true,
-            }
-        }).unwrap();
-        assert!(!timed_out.timed_out());
     }
 
     #[test]
     #[should_panic]
     fn two_mutexes() {
-        static M1: StaticMutex = StaticMutex::new();
-        static M2: StaticMutex = StaticMutex::new();
-        static C: StaticCondvar = StaticCondvar::new();
+        let m = Arc::new(Mutex::new(()));
+        let m2 = m.clone();
+        let c = Arc::new(Condvar::new());
+        let c2 = c.clone();
 
-        let mut g = M1.lock().unwrap();
+        let mut g = m.lock().unwrap();
         let _t = thread::spawn(move|| {
-            let _g = M1.lock().unwrap();
-            C.notify_one();
+            let _g = m2.lock().unwrap();
+            c2.notify_one();
         });
-        g = C.wait(g).unwrap();
+        g = c.wait(g).unwrap();
         drop(g);
 
-        let _ = C.wait(M2.lock().unwrap()).unwrap();
+        let m = Mutex::new(());
+        let _ = c.wait(m.lock().unwrap()).unwrap();
     }
 }
index 56eb7340c890c4bf88ec97a5af75febe5ea0b078..289b47b34847fbd16a08ae080683e5f605e836a7 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::barrier::{Barrier, BarrierWaitResult};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::condvar::{Condvar, StaticCondvar, WaitTimeoutResult, CONDVAR_INIT};
+pub use self::condvar::{Condvar, WaitTimeoutResult};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::mutex::MUTEX_INIT;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::mutex::{Mutex, MutexGuard, StaticMutex};
+pub use self::mutex::{Mutex, MutexGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::once::{Once, OnceState, ONCE_INIT};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
+pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
 pub mod mpsc;
 
index 34bc210b3c8239eb3bfef6261653a5a35a610a82..d96fd6228e62ebe57a1388159b8431699bfa1edc 100644 (file)
@@ -2180,6 +2180,15 @@ fn oneshot_single_thread_try_recv_closed() {
         assert!(rx.recv().is_err());
     }
 
+    #[test]
+    fn oneshot_single_thread_try_recv_closed_with_data() {
+        let (tx, rx) = sync_channel::<i32>(1);
+        tx.send(10).unwrap();
+        drop(tx);
+        assert_eq!(rx.try_recv(), Ok(10));
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
+    }
+
     #[test]
     fn oneshot_single_thread_peek_data() {
         let (tx, rx) = sync_channel::<i32>(1);
index f021689acad58849a9bc986d5435e3ee06d0eb0b..9d13a71ff95ee29098873374f2e50ec7a9274a38 100644 (file)
@@ -309,7 +309,7 @@ pub fn try_recv(&self) -> Result<T, Failure> {
         let mut guard = self.lock.lock().unwrap();
 
         // Easy cases first
-        if guard.disconnected { return Err(Disconnected) }
+        if guard.disconnected && guard.buf.size() == 0 { return Err(Disconnected) }
         if guard.buf.size() == 0 { return Err(Empty) }
 
         // Be sure to wake up neighbors
index c75a5c09146a495abe9e626efea78e605f9d8b12..6bc458397f1632282a8946cff69c45d1214e31de 100644 (file)
 /// *guard += 1;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 pub struct Mutex<T: ?Sized> {
-    // Note that this static mutex is in a *box*, not inlined into the struct
-    // itself. Once a native mutex has been used once, its address can never
-    // change (it can't be moved). This mutex type can be safely moved at any
-    // time, so to ensure that the native mutex is used correctly we box the
-    // inner lock to give it a constant address.
-    inner: Box<StaticMutex>,
+    // Note that this mutex is in a *box*, not inlined into the struct itself.
+    // Once a native mutex has been used once, its address can never change (it
+    // can't be moved). This mutex type can be safely moved at any time, so to
+    // ensure that the native mutex is used correctly we box the inner lock to
+    // give it a constant address.
+    inner: Box<sys::Mutex>,
+    poison: poison::Flag,
     data: UnsafeCell<T>,
 }
 
@@ -131,42 +131,6 @@ unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
 
-/// The static mutex type is provided to allow for static allocation of mutexes.
-///
-/// Note that this is a separate type because using a Mutex correctly means that
-/// it needs to have a destructor run. In Rust, statics are not allowed to have
-/// destructors. As a result, a `StaticMutex` has one extra method when compared
-/// to a `Mutex`, a `destroy` method. This method is unsafe to call, and
-/// documentation can be found directly on the method.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(static_mutex)]
-///
-/// use std::sync::{StaticMutex, MUTEX_INIT};
-///
-/// static LOCK: StaticMutex = MUTEX_INIT;
-///
-/// {
-///     let _g = LOCK.lock().unwrap();
-///     // do some productive work
-/// }
-/// // lock is unlocked here.
-/// ```
-#[unstable(feature = "static_mutex",
-           reason = "may be merged with Mutex in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Mutex::new` in a static should \
-                             suffice")]
-pub struct StaticMutex {
-    lock: sys::Mutex,
-    poison: poison::Flag,
-}
-
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
@@ -174,48 +138,32 @@ pub struct StaticMutex {
 /// `Deref` and `DerefMut` implementations
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 pub struct MutexGuard<'a, T: ?Sized + 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
-    __lock: &'a StaticMutex,
-    __data: &'a mut T,
+    __lock: &'a Mutex<T>,
     __poison: poison::Guard,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
 
-/// Static initialization of a mutex. This constant can be used to initialize
-/// other mutex constants.
-#[unstable(feature = "static_mutex",
-           reason = "may be merged with Mutex in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Mutex::new` in a static should \
-                             suffice")]
-#[allow(deprecated)]
-pub const MUTEX_INIT: StaticMutex = StaticMutex::new();
-
-#[allow(deprecated)]
 impl<T> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
         let mut m = Mutex {
-            inner: box StaticMutex::new(),
+            inner: box sys::Mutex::new(),
+            poison: poison::Flag::new(),
             data: UnsafeCell::new(t),
         };
         unsafe {
-            m.inner.lock.init();
+            m.inner.init();
         }
         m
     }
 }
 
-#[allow(deprecated)]
 impl<T: ?Sized> Mutex<T> {
     /// Acquires a mutex, blocking the current thread until it is able to do so.
     ///
@@ -240,8 +188,8 @@ impl<T: ?Sized> Mutex<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> LockResult<MutexGuard<T>> {
         unsafe {
-            self.inner.lock.lock();
-            MutexGuard::new(&*self.inner, &self.data)
+            self.inner.lock();
+            MutexGuard::new(self)
         }
     }
 
@@ -261,8 +209,8 @@ pub fn lock(&self) -> LockResult<MutexGuard<T>> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
         unsafe {
-            if self.inner.lock.try_lock() {
-                Ok(MutexGuard::new(&*self.inner, &self.data)?)
+            if self.inner.try_lock() {
+                Ok(MutexGuard::new(self)?)
             } else {
                 Err(TryLockError::WouldBlock)
             }
@@ -277,7 +225,7 @@ pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
     #[inline]
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn is_poisoned(&self) -> bool {
-        self.inner.poison.get()
+        self.poison.get()
     }
 
     /// Consumes this mutex, returning the underlying data.
@@ -289,21 +237,22 @@ pub fn is_poisoned(&self) -> bool {
     #[stable(feature = "mutex_into_inner", since = "1.6.0")]
     pub fn into_inner(self) -> LockResult<T> where T: Sized {
         // We know statically that there are no outstanding references to
-        // `self` so there's no need to lock the inner StaticMutex.
+        // `self` so there's no need to lock the inner lock.
         //
         // To get the inner value, we'd like to call `data.into_inner()`,
         // but because `Mutex` impl-s `Drop`, we can't move out of it, so
         // we'll have to destructure it manually instead.
         unsafe {
-            // Like `let Mutex { inner, data } = self`.
-            let (inner, data) = {
-                let Mutex { ref inner, ref data } = self;
-                (ptr::read(inner), ptr::read(data))
+            // Like `let Mutex { inner, poison, data } = self`.
+            let (inner, poison, data) = {
+                let Mutex { ref inner, ref poison, ref data } = self;
+                (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            inner.lock.destroy();  // Keep in sync with the `Drop` impl.
+            inner.destroy();  // Keep in sync with the `Drop` impl.
+            drop(inner);
 
-            poison::map_result(inner.poison.borrow(), |_| data.into_inner())
+            poison::map_result(poison.borrow(), |_| data.into_inner())
         }
     }
 
@@ -319,14 +268,13 @@ pub fn into_inner(self) -> LockResult<T> where T: Sized {
     #[stable(feature = "mutex_get_mut", since = "1.6.0")]
     pub fn get_mut(&mut self) -> LockResult<&mut T> {
         // We know statically that there are no other references to `self`, so
-        // there's no need to lock the inner StaticMutex.
+        // there's no need to lock the inner lock.
         let data = unsafe { &mut *self.data.get() };
-        poison::map_result(self.inner.poison.borrow(), |_| data )
+        poison::map_result(self.poison.borrow(), |_| data )
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 impl<T: ?Sized> Drop for Mutex<T> {
     #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
@@ -335,7 +283,7 @@ fn drop(&mut self) {
         // dropped, that's not our job)
         //
         // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
-        unsafe { self.inner.lock.destroy() }
+        unsafe { self.inner.destroy() }
     }
 }
 
@@ -359,72 +307,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-struct Dummy(UnsafeCell<()>);
-unsafe impl Sync for Dummy {}
-static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
-
-#[unstable(feature = "static_mutex",
-           reason = "may be merged with Mutex in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `Mutex::new` in a static should \
-                             suffice")]
-#[allow(deprecated)]
-impl StaticMutex {
-    /// Creates a new mutex in an unlocked state ready for use.
-    pub const fn new() -> StaticMutex {
-        StaticMutex {
-            lock: sys::Mutex::new(),
-            poison: poison::Flag::new(),
-        }
-    }
-
-    /// Acquires this lock, see `Mutex::lock`
-    #[inline]
-    pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
-        unsafe {
-            self.lock.lock();
-            MutexGuard::new(self, &DUMMY.0)
-        }
-    }
-
-    /// Attempts to grab this lock, see `Mutex::try_lock`
-    #[inline]
-    pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
-        unsafe {
-            if self.lock.try_lock() {
-                Ok(MutexGuard::new(self, &DUMMY.0)?)
-            } else {
-                Err(TryLockError::WouldBlock)
-            }
-        }
-    }
-
-    /// Deallocates resources associated with this static mutex.
-    ///
-    /// This method is unsafe because it provides no guarantees that there are
-    /// no active users of this mutex, and safety is not guaranteed if there are
-    /// active users of this mutex.
-    ///
-    /// This method is required to ensure that there are no memory leaks on
-    /// *all* platforms. It may be the case that some platforms do not leak
-    /// memory if this method is not called, but this is not guaranteed to be
-    /// true on all platforms.
-    pub unsafe fn destroy(&'static self) {
-        self.lock.destroy()
-    }
-}
-
-#[allow(deprecated)]
 impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
-    unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
-           -> LockResult<MutexGuard<'mutex, T>> {
+    unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
             MutexGuard {
                 __lock: lock,
-                __data: &mut *data.get(),
                 __poison: guard,
             }
         })
@@ -435,43 +322,43 @@ unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
 impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
     type Target = T;
 
-    fn deref(&self) -> &T {self.__data }
+    fn deref(&self) -> &T {
+        unsafe { &*self.__lock.data.get() }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
-    fn deref_mut(&mut self) -> &mut T { self.__data }
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.__lock.data.get() }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
     #[inline]
     fn drop(&mut self) {
         unsafe {
             self.__lock.poison.done(&self.__poison);
-            self.__lock.lock.unlock();
+            self.__lock.inner.unlock();
         }
     }
 }
 
-#[allow(deprecated)]
 pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
-    &guard.__lock.lock
+    &guard.__lock.inner
 }
 
-#[allow(deprecated)]
 pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
     &guard.__lock.poison
 }
 
 #[cfg(test)]
-#[allow(deprecated)]
 mod tests {
     use prelude::v1::*;
 
     use sync::mpsc::channel;
-    use sync::{Arc, Mutex, StaticMutex, Condvar};
+    use sync::{Arc, Mutex, Condvar};
     use sync::atomic::{AtomicUsize, Ordering};
     use thread;
 
@@ -490,48 +377,34 @@ fn smoke() {
         drop(m.lock().unwrap());
     }
 
-    #[test]
-    fn smoke_static() {
-        static M: StaticMutex = StaticMutex::new();
-        unsafe {
-            drop(M.lock().unwrap());
-            drop(M.lock().unwrap());
-            M.destroy();
-        }
-    }
-
     #[test]
     fn lots_and_lots() {
-        static M: StaticMutex = StaticMutex::new();
-        static mut CNT: u32 = 0;
         const J: u32 = 1000;
         const K: u32 = 3;
 
-        fn inc() {
+        let m = Arc::new(Mutex::new(0));
+
+        fn inc(m: &Mutex<u32>) {
             for _ in 0..J {
-                unsafe {
-                    let _g = M.lock().unwrap();
-                    CNT += 1;
-                }
+                *m.lock().unwrap() += 1;
             }
         }
 
         let (tx, rx) = channel();
         for _ in 0..K {
             let tx2 = tx.clone();
-            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
+            let m2 = m.clone();
+            thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
             let tx2 = tx.clone();
-            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
+            let m2 = m.clone();
+            thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
         }
 
         drop(tx);
         for _ in 0..2 * K {
             rx.recv().unwrap();
         }
-        assert_eq!(unsafe {CNT}, J * K * 2);
-        unsafe {
-            M.destroy();
-        }
+        assert_eq!(*m.lock().unwrap(), J * K * 2);
     }
 
     #[test]
index 03d3483902dcf87b899aefcbe1f2a66ea07d2a30..65b5686de869ca7fb05f9369a3435753612d5a35 100644 (file)
@@ -66,9 +66,9 @@
 /// } // write lock is dropped here
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 pub struct RwLock<T: ?Sized> {
-    inner: Box<StaticRwLock>,
+    inner: Box<sys::RWLock>,
+    poison: poison::Flag,
     data: UnsafeCell<T>,
 }
 
@@ -77,64 +77,12 @@ unsafe impl<T: ?Sized + Send + Sync> Send for RwLock<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
 
-/// Structure representing a statically allocated RwLock.
-///
-/// This structure is intended to be used inside of a `static` and will provide
-/// automatic global access as well as lazy initialization. The internal
-/// resources of this RwLock, however, must be manually deallocated.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(static_rwlock)]
-///
-/// use std::sync::{StaticRwLock, RW_LOCK_INIT};
-///
-/// static LOCK: StaticRwLock = RW_LOCK_INIT;
-///
-/// {
-///     let _g = LOCK.read().unwrap();
-///     // ... shared read access
-/// }
-/// {
-///     let _g = LOCK.write().unwrap();
-///     // ... exclusive write access
-/// }
-/// unsafe { LOCK.destroy() } // free all resources
-/// ```
-#[unstable(feature = "static_rwlock",
-           reason = "may be merged with RwLock in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `RwLock::new` in a static should \
-                             suffice")]
-pub struct StaticRwLock {
-    lock: sys::RWLock,
-    poison: poison::Flag,
-}
-
-/// Constant initialization for a statically-initialized rwlock.
-#[unstable(feature = "static_rwlock",
-           reason = "may be merged with RwLock in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `RwLock::new` in a static should \
-                             suffice")]
-#[allow(deprecated)]
-pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new();
-
 /// RAII structure used to release the shared read access of a lock when
 /// dropped.
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
-    __lock: &'a StaticRwLock,
-    __data: &'a T,
+    __lock: &'a RwLock<T>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -144,17 +92,14 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
 /// dropped.
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
-    __lock: &'a StaticRwLock,
-    __data: &'a mut T,
+    __lock: &'a RwLock<T>,
     __poison: poison::Guard,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
 
-#[allow(deprecated)]
 impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     ///
@@ -167,11 +112,14 @@ impl<T> RwLock<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> RwLock<T> {
-        RwLock { inner: box StaticRwLock::new(), data: UnsafeCell::new(t) }
+        RwLock {
+            inner: box sys::RWLock::new(),
+            poison: poison::Flag::new(),
+            data: UnsafeCell::new(t),
+        }
     }
 }
 
-#[allow(deprecated)]
 impl<T: ?Sized> RwLock<T> {
     /// Locks this rwlock with shared read access, blocking the current thread
     /// until it can be acquired.
@@ -194,8 +142,8 @@ impl<T: ?Sized> RwLock<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
         unsafe {
-            self.inner.lock.read();
-            RwLockReadGuard::new(&*self.inner, &self.data)
+            self.inner.read();
+            RwLockReadGuard::new(self)
         }
     }
 
@@ -220,8 +168,8 @@ pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
         unsafe {
-            if self.inner.lock.try_read() {
-                Ok(RwLockReadGuard::new(&*self.inner, &self.data)?)
+            if self.inner.try_read() {
+                Ok(RwLockReadGuard::new(self)?)
             } else {
                 Err(TryLockError::WouldBlock)
             }
@@ -246,8 +194,8 @@ pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
         unsafe {
-            self.inner.lock.write();
-            RwLockWriteGuard::new(&*self.inner, &self.data)
+            self.inner.write();
+            RwLockWriteGuard::new(self)
         }
     }
 
@@ -272,8 +220,8 @@ pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
         unsafe {
-            if self.inner.lock.try_write() {
-                Ok(RwLockWriteGuard::new(&*self.inner, &self.data)?)
+            if self.inner.try_write() {
+                Ok(RwLockWriteGuard::new(self)?)
             } else {
                 Err(TryLockError::WouldBlock)
             }
@@ -288,7 +236,7 @@ pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
     #[inline]
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn is_poisoned(&self) -> bool {
-        self.inner.poison.get()
+        self.poison.get()
     }
 
     /// Consumes this `RwLock`, returning the underlying data.
@@ -302,21 +250,22 @@ pub fn is_poisoned(&self) -> bool {
     #[stable(feature = "rwlock_into_inner", since = "1.6.0")]
     pub fn into_inner(self) -> LockResult<T> where T: Sized {
         // We know statically that there are no outstanding references to
-        // `self` so there's no need to lock the inner StaticRwLock.
+        // `self` so there's no need to lock the inner lock.
         //
         // To get the inner value, we'd like to call `data.into_inner()`,
         // but because `RwLock` impl-s `Drop`, we can't move out of it, so
         // we'll have to destructure it manually instead.
         unsafe {
-            // Like `let RwLock { inner, data } = self`.
-            let (inner, data) = {
-                let RwLock { ref inner, ref data } = self;
-                (ptr::read(inner), ptr::read(data))
+            // Like `let RwLock { inner, poison, data } = self`.
+            let (inner, poison, data) = {
+                let RwLock { ref inner, ref poison, ref data } = self;
+                (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            inner.lock.destroy();  // Keep in sync with the `Drop` impl.
+            inner.destroy();  // Keep in sync with the `Drop` impl.
+            drop(inner);
 
-            poison::map_result(inner.poison.borrow(), |_| data.into_inner())
+            poison::map_result(poison.borrow(), |_| data.into_inner())
         }
     }
 
@@ -334,19 +283,18 @@ pub fn into_inner(self) -> LockResult<T> where T: Sized {
     #[stable(feature = "rwlock_get_mut", since = "1.6.0")]
     pub fn get_mut(&mut self) -> LockResult<&mut T> {
         // We know statically that there are no other references to `self`, so
-        // there's no need to lock the inner StaticRwLock.
+        // there's no need to lock the inner lock.
         let data = unsafe { &mut *self.data.get() };
-        poison::map_result(self.inner.poison.borrow(), |_| data )
+        poison::map_result(self.poison.borrow(), |_| data)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
 impl<T: ?Sized> Drop for RwLock<T> {
     #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`.
-        unsafe { self.inner.lock.destroy() }
+        unsafe { self.inner.destroy() }
     }
 }
 
@@ -370,114 +318,23 @@ fn default() -> RwLock<T> {
     }
 }
 
-struct Dummy(UnsafeCell<()>);
-unsafe impl Sync for Dummy {}
-static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
-
-#[unstable(feature = "static_rwlock",
-           reason = "may be merged with RwLock in the future",
-           issue = "27717")]
-#[rustc_deprecated(since = "1.10.0",
-                   reason = "the lazy-static crate suffices for static sync \
-                             primitives and eventually this type shouldn't \
-                             be necessary as `RwLock::new` in a static should \
-                             suffice")]
-#[allow(deprecated)]
-impl StaticRwLock {
-    /// Creates a new rwlock.
-    pub const fn new() -> StaticRwLock {
-        StaticRwLock {
-            lock: sys::RWLock::new(),
-            poison: poison::Flag::new(),
-        }
-    }
-
-    /// Locks this rwlock with shared read access, blocking the current thread
-    /// until it can be acquired.
-    ///
-    /// See `RwLock::read`.
-    #[inline]
-    pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
-        unsafe {
-            self.lock.read();
-            RwLockReadGuard::new(self, &DUMMY.0)
-        }
-    }
-
-    /// Attempts to acquire this lock with shared read access.
-    ///
-    /// See `RwLock::try_read`.
-    #[inline]
-    pub fn try_read(&'static self)
-                    -> TryLockResult<RwLockReadGuard<'static, ()>> {
-        unsafe {
-            if self.lock.try_read(){
-                Ok(RwLockReadGuard::new(self, &DUMMY.0)?)
-            } else {
-                Err(TryLockError::WouldBlock)
-            }
-        }
-    }
-
-    /// Locks this rwlock with exclusive write access, blocking the current
-    /// thread until it can be acquired.
-    ///
-    /// See `RwLock::write`.
-    #[inline]
-    pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
-        unsafe {
-            self.lock.write();
-            RwLockWriteGuard::new(self, &DUMMY.0)
-        }
-    }
-
-    /// Attempts to lock this rwlock with exclusive write access.
-    ///
-    /// See `RwLock::try_write`.
-    #[inline]
-    pub fn try_write(&'static self)
-                     -> TryLockResult<RwLockWriteGuard<'static, ()>> {
-        unsafe {
-            if self.lock.try_write() {
-                Ok(RwLockWriteGuard::new(self, &DUMMY.0)?)
-            } else {
-                Err(TryLockError::WouldBlock)
-            }
-        }
-    }
-
-    /// Deallocates all resources associated with this static lock.
-    ///
-    /// This method is unsafe to call as there is no guarantee that there are no
-    /// active users of the lock, and this also doesn't prevent any future users
-    /// of this lock. This method is required to be called to not leak memory on
-    /// all platforms.
-    pub unsafe fn destroy(&'static self) {
-        self.lock.destroy()
-    }
-}
-
-#[allow(deprecated)]
 impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
-    unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
-           -> LockResult<RwLockReadGuard<'rwlock, T>> {
+    unsafe fn new(lock: &'rwlock RwLock<T>)
+                  -> LockResult<RwLockReadGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |_| {
             RwLockReadGuard {
                 __lock: lock,
-                __data: &*data.get(),
             }
         })
     }
 }
 
-#[allow(deprecated)]
 impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
-    unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
-           -> LockResult<RwLockWriteGuard<'rwlock, T>> {
+    unsafe fn new(lock: &'rwlock RwLock<T>)
+                  -> LockResult<RwLockWriteGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
             RwLockWriteGuard {
                 __lock: lock,
-                __data: &mut *data.get(),
                 __poison: guard,
             }
         })
@@ -488,42 +345,43 @@ unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
 impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
     type Target = T;
 
-    fn deref(&self) -> &T { self.__data }
+    fn deref(&self) -> &T {
+        unsafe { &*self.__lock.data.get() }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
     type Target = T;
 
-    fn deref(&self) -> &T { self.__data }
+    fn deref(&self) -> &T {
+        unsafe { &*self.__lock.data.get() }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
     fn deref_mut(&mut self) -> &mut T {
-        self.__data
+        unsafe { &mut *self.__lock.data.get() }
     }
 }
 
-#[allow(deprecated)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
     fn drop(&mut self) {
-        unsafe { self.__lock.lock.read_unlock(); }
+        unsafe { self.__lock.inner.read_unlock(); }
     }
 }
 
-#[allow(deprecated)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
     fn drop(&mut self) {
         self.__lock.poison.done(&self.__poison);
-        unsafe { self.__lock.lock.write_unlock(); }
+        unsafe { self.__lock.inner.write_unlock(); }
     }
 }
 
 #[cfg(test)]
-#[allow(deprecated)]
 mod tests {
     #![allow(deprecated)] // rand
 
@@ -532,7 +390,7 @@ mod tests {
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
-    use sync::{Arc, RwLock, StaticRwLock, TryLockError};
+    use sync::{Arc, RwLock, TryLockError};
     use sync::atomic::{AtomicUsize, Ordering};
 
     #[derive(Eq, PartialEq, Debug)]
@@ -547,32 +405,24 @@ fn smoke() {
         drop(l.write().unwrap());
     }
 
-    #[test]
-    fn static_smoke() {
-        static R: StaticRwLock = StaticRwLock::new();
-        drop(R.read().unwrap());
-        drop(R.write().unwrap());
-        drop((R.read().unwrap(), R.read().unwrap()));
-        drop(R.write().unwrap());
-        unsafe { R.destroy(); }
-    }
-
     #[test]
     fn frob() {
-        static R: StaticRwLock = StaticRwLock::new();
         const N: usize = 10;
         const M: usize = 1000;
 
+        let r = Arc::new(RwLock::new(()));
+
         let (tx, rx) = channel::<()>();
         for _ in 0..N {
             let tx = tx.clone();
-            thread::spawn(move|| {
+            let r = r.clone();
+            thread::spawn(move || {
                 let mut rng = rand::thread_rng();
                 for _ in 0..M {
                     if rng.gen_weighted_bool(N) {
-                        drop(R.write().unwrap());
+                        drop(r.write().unwrap());
                     } else {
-                        drop(R.read().unwrap());
+                        drop(r.read().unwrap());
                     }
                 }
                 drop(tx);
@@ -580,7 +430,6 @@ fn frob() {
         }
         drop(tx);
         let _ = rx.recv();
-        unsafe { R.destroy(); }
     }
 
     #[test]
index 6f185437e50af47b3d4b7966210fbaa636284e78..4c23ceb63f287bd4a7c9c5efbc344404ed435d98 100644 (file)
@@ -170,7 +170,9 @@ macro_rules! demangle {
                         "$u20$", => b" ",
                         "$u27$", => b"'",
                         "$u5b$", => b"[",
-                        "$u5d$", => b"]"
+                        "$u5d$", => b"]",
+                        "$u7b$", => b"{",
+                        "$u7d$", => b"}"
                     )
                 } else {
                     let idx = match rest.find('$') {
index 83780a31cceb121437729e00d5d0917b50794013..55212bf35d698656df80e8d0a55cb767411a0b3a 100644 (file)
@@ -8,22 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use cell::Cell;
 use error::{Error};
 use fmt;
 use marker::Reflect;
+use sync::atomic::{AtomicBool, Ordering};
 use thread;
 
-pub struct Flag { failed: Cell<bool> }
+pub struct Flag { failed: AtomicBool }
 
-// This flag is only ever accessed with a lock previously held. Note that this
-// a totally private structure.
-unsafe impl Send for Flag {}
-unsafe impl Sync for Flag {}
+// Note that the Ordering uses to access the `failed` field of `Flag` below is
+// always `Relaxed`, and that's because this isn't actually protecting any data,
+// it's just a flag whether we've panicked or not.
+//
+// The actual location that this matters is when a mutex is **locked** which is
+// where we have external synchronization ensuring that we see memory
+// reads/writes to this flag.
+//
+// As a result, if it matters, we should see the correct value for `failed` in
+// all cases.
 
 impl Flag {
     pub const fn new() -> Flag {
-        Flag { failed: Cell::new(false) }
+        Flag { failed: AtomicBool::new(false) }
     }
 
     #[inline]
@@ -39,13 +45,13 @@ pub fn borrow(&self) -> LockResult<Guard> {
     #[inline]
     pub fn done(&self, guard: &Guard) {
         if !guard.panicking && thread::panicking() {
-            self.failed.set(true);
+            self.failed.store(true, Ordering::Relaxed);
         }
     }
 
     #[inline]
     pub fn get(&self) -> bool {
-        self.failed.get()
+        self.failed.load(Ordering::Relaxed)
     }
 }
 
index b6be85a4dfa2879b04548c74964195a5f3f8c1ce..2c1a656290f946a223274910fa6672a6ceabfab0 100644 (file)
@@ -566,7 +566,7 @@ fn final_lead_surrogate(&self) -> Option<u16> {
         if len < 3 {
             return None
         }
-        match ::slice_pat(&&self.bytes[(len - 3)..]) {
+        match &self.bytes[(len - 3)..] {
             &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None
         }
@@ -578,7 +578,7 @@ fn initial_trail_surrogate(&self) -> Option<u16> {
         if len < 3 {
             return None
         }
-        match ::slice_pat(&&self.bytes[..3]) {
+        match &self.bytes[..3] {
             &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
             _ => None
         }
index 0524851df91abeb0c091a0a254b616388dd4b007..a004ff7afe1ecf12073f35f3a6c8af7208738f85 100644 (file)
@@ -84,7 +84,7 @@ pub struct OpenOptions {
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FilePermissions { mode: mode_t }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType { mode: mode_t }
 
 pub struct DirBuilder { mode: mode_t }
index 0e10a8d8e8dd2619b6da4010a9a5816e722b0d14..82a44c1c1103b4aa7935a5889e11072c0ef05eae 100644 (file)
@@ -30,9 +30,9 @@
 use libc::c_void;
 use mem;
 use ptr;
-use sync::StaticMutex;
 use sys::c;
 use sys::dynamic_lib::DynamicLibrary;
+use sys::mutex::Mutex;
 
 macro_rules! sym {
     ($lib:expr, $e:expr, $t:ident) => (
@@ -101,53 +101,59 @@ fn drop(&mut self) {
 pub fn write(w: &mut Write) -> io::Result<()> {
     // According to windows documentation, all dbghelp functions are
     // single-threaded.
-    static LOCK: StaticMutex = StaticMutex::new();
-    let _g = LOCK.lock();
+    static LOCK: Mutex = Mutex::new();
+    unsafe {
+        LOCK.lock();
+        let res = _write(w);
+        LOCK.unlock();
+        return res
+    }
+}
 
+unsafe fn _write(w: &mut Write) -> io::Result<()> {
     let dbghelp = match DynamicLibrary::open("dbghelp.dll") {
         Ok(lib) => lib,
         Err(..) => return Ok(()),
     };
-    unsafe {
-        // Fetch the symbols necessary from dbghelp.dll
-        let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn);
-        let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn);
-        let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
-
-        // Allocate necessary structures for doing the stack walk
-        let process = c::GetCurrentProcess();
-        let thread = c::GetCurrentThread();
-        let mut context: c::CONTEXT = mem::zeroed();
-        c::RtlCaptureContext(&mut context);
-        let mut frame: c::STACKFRAME64 = mem::zeroed();
-        let image = init_frame(&mut frame, &context);
-
-        // Initialize this process's symbols
-        let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
-        if ret != c::TRUE { return Ok(()) }
-        let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
-
-        // And now that we're done with all the setup, do the stack walking!
-        // Start from -1 to avoid printing this stack frame, which will
-        // always be exactly the same.
-        let mut i = -1;
-        write!(w, "stack backtrace:\n")?;
-        while StackWalk64(image, process, thread, &mut frame, &mut context,
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut(),
-                          ptr::null_mut()) == c::TRUE {
-            let addr = frame.AddrPC.Offset;
-            if addr == frame.AddrReturn.Offset || addr == 0 ||
-               frame.AddrReturn.Offset == 0 { break }
-
-            i += 1;
-
-            if i >= 0 {
-                printing::print(w, i, addr - 1, process, &dbghelp)?;
-            }
-        }
 
-        Ok(())
+    // Fetch the symbols necessary from dbghelp.dll
+    let SymInitialize = sym!(dbghelp, "SymInitialize", SymInitializeFn);
+    let SymCleanup = sym!(dbghelp, "SymCleanup", SymCleanupFn);
+    let StackWalk64 = sym!(dbghelp, "StackWalk64", StackWalk64Fn);
+
+    // Allocate necessary structures for doing the stack walk
+    let process = c::GetCurrentProcess();
+    let thread = c::GetCurrentThread();
+    let mut context: c::CONTEXT = mem::zeroed();
+    c::RtlCaptureContext(&mut context);
+    let mut frame: c::STACKFRAME64 = mem::zeroed();
+    let image = init_frame(&mut frame, &context);
+
+    // Initialize this process's symbols
+    let ret = SymInitialize(process, ptr::null_mut(), c::TRUE);
+    if ret != c::TRUE { return Ok(()) }
+    let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
+
+    // And now that we're done with all the setup, do the stack walking!
+    // Start from -1 to avoid printing this stack frame, which will
+    // always be exactly the same.
+    let mut i = -1;
+    write!(w, "stack backtrace:\n")?;
+    while StackWalk64(image, process, thread, &mut frame, &mut context,
+                      ptr::null_mut(),
+                      ptr::null_mut(),
+                      ptr::null_mut(),
+                      ptr::null_mut()) == c::TRUE {
+        let addr = frame.AddrPC.Offset;
+        if addr == frame.AddrReturn.Offset || addr == 0 ||
+           frame.AddrReturn.Offset == 0 { break }
+
+        i += 1;
+
+        if i >= 0 {
+            printing::print(w, i, addr - 1, process, &dbghelp)?;
+        }
     }
+
+    Ok(())
 }
index c243e890526f78526d1777c7de94862f0b8f87c6..2683e57256dc79afc29a2872a31861f77a788d53 100644 (file)
@@ -38,7 +38,7 @@ pub struct FileAttr {
     reparse_tag: c::DWORD,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum FileType {
     Dir, File, SymlinkFile, SymlinkDir, ReparsePoint, MountPoint,
 }
@@ -117,7 +117,7 @@ fn drop(&mut self) {
 
 impl DirEntry {
     fn new(root: &Arc<PathBuf>, wfd: &c::WIN32_FIND_DATAW) -> Option<DirEntry> {
-        match ::slice_pat(&&wfd.cFileName[0..3]) {
+        match &wfd.cFileName[0..3] {
             // check for '.' and '..'
             &[46, 0, ..] |
             &[46, 46, 0, ..] => return None,
index e01bd2a93aacdfcb9b806a0af3e5960fdff47d12..67f73d4dd4f711e4798a42200002c5ddf50933a3 100644 (file)
@@ -324,7 +324,7 @@ pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Inte
             if let s@Some(_) = attr.value_str() {
                 s
             } else {
-                struct_span_err!(diag, attr.span, E0533,
+                struct_span_err!(diag, attr.span, E0558,
                                  "export_name attribute has invalid format")
                                 .help("use #[export_name=\"*\"]")
                                 .emit();
@@ -373,7 +373,7 @@ pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> In
                     InlineAttr::None
                 }
             }
-            _ => ia
+            _ => ia,
         }
     })
 }
index eb30657bd56ead7a804b8fd7b22c9c10fe6051ed..010b1d638e63cf2085e89ea9f265a3376d228b47 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
 // In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
 register_long_diagnostics! {
 
-E0533: r##"
-```compile_fail,E0533
-#[export_name]
+E0534: r##"
+The `inline` attribute was malformed.
+
+Erroneous code example:
+
+```compile_fail,E0534
+#[inline()] // error: expected one argument
+pub fn something() {}
+
+fn main() {}
+```
+
+The parenthesized `inline` attribute requires the parameter to be specified:
+
+```ignore
+#[inline(always)]
+fn something() {}
+
+// or:
+
+#[inline(never)]
+fn something() {}
+```
+
+Alternatively, a paren-less version of the attribute may be used to hint the
+compiler about inlining opportunity:
+
+```
+#[inline]
+fn something() {}
+```
+
+For more information about the inline attribute, read:
+https://doc.rust-lang.org/reference.html#inline-attributes
+"##,
+
+E0535: r##"
+An unknown argument was given to the `inline` attribute.
+
+Erroneous code example:
+
+```compile_fail,E0535
+#[inline(unknown)] // error: invalid argument
+pub fn something() {}
+
+fn main() {}
+```
+
+The `inline` attribute only supports two arguments:
+
+ * always
+ * never
+
+All other arguments given to the `inline` attribute will return this error.
+Example:
+
+```
+#[inline(never)] // ok!
+pub fn something() {}
+
+fn main() {}
+```
+
+For more information about the inline attribute, https:
+read://doc.rust-lang.org/reference.html#inline-attributes
+"##,
+
+E0536: r##"
+The `not` cfg-predicate was malformed.
+
+Erroneous code example:
+
+```compile_fail,E0536
+#[cfg(not())] // error: expected 1 cfg-pattern
+pub fn something() {}
+
+pub fn main() {}
+```
+
+The `not` predicate expects one cfg-pattern. Example:
+
+```
+#[cfg(not(target_os = "linux"))] // ok!
+pub fn something() {}
+
+pub fn main() {}
+```
+
+For more information about the cfg attribute, read:
+https://doc.rust-lang.org/reference.html#conditional-compilation
+"##,
+
+E0537: r##"
+An unknown predicate was used inside the `cfg` attribute.
+
+Erroneous code example:
+
+```compile_fail,E0537
+#[cfg(unknown())] // error: invalid predicate `unknown`
+pub fn something() {}
+
+pub fn main() {}
+```
+
+The `cfg` attribute supports only three kinds of predicates:
+
+ * any
+ * all
+ * not
+
+Example:
+
+```
+#[cfg(not(target_os = "linux"))] // ok!
+pub fn something() {}
+
+pub fn main() {}
+```
+
+For more information about the cfg attribute, read:
+https://doc.rust-lang.org/reference.html#conditional-compilation
+"##,
+
+E0558: r##"
+The `export_name` attribute was malformed.
+
+Erroneous code example:
+
+```compile_fail,E0558
+#[export_name] // error: export_name attribute has invalid format
+pub fn something() {}
+
+fn main() {}
+```
+
+The `export_name` attribute expects a string in order to determine the name of
+the exported symbol. Example:
+
+```
+#[export_name = "some_function"] // ok!
 pub fn something() {}
 
 fn main() {}
@@ -27,10 +164,6 @@ fn main() {}
 }
 
 register_diagnostics! {
-    E0534, // expected one argument
-    E0535, // invalid argument
-    E0536, // expected 1 cfg-pattern
-    E0537, // invalid predicate
     E0538, // multiple [same] items
     E0539, // incorrect meta item
     E0540, // multiple rustc_deprecated attributes
index 8e46bdfc5b6b81b8534e38d99ef101ca25dd1174..aaf88a67d27499e360c13d89271ec2b3521303f0 100644 (file)
@@ -12,6 +12,6 @@
 # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was
 # released on `$date`
 
-rustc: beta-2016-05-24
-rustc_key: a4922355
-cargo: nightly-2016-05-22
+rustc: beta-2016-07-06
+rustc_key: 411fd48b
+cargo: nightly-2016-07-05
index 4245786295b343fa14df160e11f5d447a65483be..3c32cb947b382f1107473fd6d81d0437c0ca927e 100644 (file)
@@ -16,6 +16,5 @@
 fn main() {
     match () {
         Trait { x: 42 } => () //~ ERROR expected variant, struct or type alias, found trait `Trait`
-        //~^ ERROR `Trait` does not name a struct or a struct variant
     }
 }
diff --git a/src/test/compile-fail/E0163.rs b/src/test/compile-fail/E0163.rs
deleted file mode 100644 (file)
index 5cb6f4d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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.
-
-enum Foo { B(u32) }
-
-fn bar(foo: Foo) -> u32 {
-    match foo {
-        Foo::B { i } => i, //~ ERROR E0163
-    }
-}
-
-fn main() {
-}
index 3100aba4b72be3cfa027c52d61feec6bb0f67470..1049bcd15644fcdd87d25ddec4475fb05263f94f 100644 (file)
@@ -10,6 +10,7 @@
 #![crate_name="lint_stability"]
 #![crate_type = "lib"]
 #![feature(staged_api)]
+#![feature(associated_type_defaults)]
 #![stable(feature = "lint_stability", since = "1.0.0")]
 
 #[stable(feature = "test_feature", since = "1.0.0")]
@@ -92,6 +93,15 @@ fn trait_stable(&self) {}
     fn trait_stable_text(&self) {}
 }
 
+#[stable(feature = "test_feature", since = "1.0.0")]
+pub trait TraitWithAssociatedTypes {
+    #[unstable(feature = "test_feature", issue = "0")]
+    type TypeUnstable = u8;
+    #[stable(feature = "test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    type TypeDeprecated = u8;
+}
+
 #[stable(feature = "test_feature", since = "1.0.0")]
 impl Trait for MethodTester {}
 
index a5c740d9f638a65a94b8fbf9833102f8264bf472..74546152ca90fcf77b85c1742cd89768820c8e27 100644 (file)
@@ -31,12 +31,14 @@ fn main() {
         Empty1 => () // Not an error, `Empty1` is interpreted as a new binding
     }
     match e3 {
-        E::Empty3 => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
+        E::Empty3 => ()
+        //~^ ERROR `E::Empty3` does not name a unit variant, unit struct or a constant
     }
     match xe1 {
         XEmpty1 => () // Not an error, `XEmpty1` is interpreted as a new binding
     }
     match xe3 {
-        XE::XEmpty3 => () //~ ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
+        XE::XEmpty3 => ()
+        //~^ ERROR `XE::XEmpty3` does not name a unit variant, unit struct or a constant
     }
 }
index 4637512216c40b15d3e72110ff0dbcb4ad54e1e9..671232e701f872b33721803aba16349e5ca33ed1 100644 (file)
@@ -16,7 +16,7 @@ pub struct GslResult {
 
 impl GslResult {
     pub fn new() -> GslResult {
-        Result { //~ ERROR: `Result` does not name a structure
+        Result { //~ ERROR: `Result` does not name a struct or a struct variant
             val: 0f64,
             err: 0f64
         }
index 0fee6dc7617005341a60780c17278f4e1e8f903e..218f68714ff929821d1f9b5a975fa7ea0634afd8 100644 (file)
@@ -11,5 +11,5 @@
 mod foo {}
 
 fn main() {
-    let p = foo { x: () }; //~ ERROR `foo` does not name a structure
+    let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant
 }
index db43c1cce9947fa348602ea021e5ccf204575760..2f2c252b947c90f38994c142985e6ae3fdd8cdb1 100644 (file)
@@ -15,6 +15,5 @@ enum Foo {
 fn main() {
     match Foo::Bar(1) {
         Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
-        //~^ ERROR `Foo` does not name a struct or a struct variant
     }
 }
index 93c4f4bfcef8f78684d589600e47d84bbe290998..090b8a0d16e64ca9a890fde406512ce8d22c82bb 100644 (file)
@@ -11,5 +11,5 @@
 mod MyMod {}
 
 fn main() {
-    let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a structure
+    let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant
 }
diff --git a/src/test/compile-fail/issue-22933-1.rs b/src/test/compile-fail/issue-22933-1.rs
new file mode 100644 (file)
index 0000000..afb972f
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+struct CNFParser {
+    token: char,
+}
+
+impl CNFParser {
+    fn is_whitespace(c: char) -> bool {
+        c == ' ' || c == '\n'
+    }
+
+    fn consume_whitespace(&mut self) {
+        self.consume_while(&(CNFParser::is_whitespace))
+    }
+
+    fn consume_while(&mut self, p: &Fn(char) -> bool) {
+        while p(self.token) {
+            return
+        }
+    }
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/issue-22933-2.rs b/src/test/compile-fail/issue-22933-2.rs
new file mode 100644 (file)
index 0000000..7d619c2
--- /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.
+
+enum Delicious {
+    Pie      = 0x1,
+    Apple    = 0x2,
+    ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
+    //~^ ERROR constant evaluation error: unresolved path in constant expression
+}
+
+const FOO: [u32; u8::MIN as usize] = [];
+//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+
+fn main() {}
index 6cadbef33e7f0b4f9eb555b9d7425a9f8f9a2166..24b39eeff0f791c0e3508e77c6e99e82d11ec383 100644 (file)
@@ -12,6 +12,5 @@ fn main() {
     match 'a' {
         char{ch} => true
         //~^ ERROR expected variant, struct or type alias, found builtin type `char`
-        //~| ERROR `char` does not name a struct or a struct variant
     };
 }
index d2f9abd2e316b41539d235ebaaa6599f01cb5049..7a329bac61b22f64a0fa2eee6b1c512423005833 100644 (file)
 mod A {}
 
 fn main() {
-    let u = A { x: 1 }; //~ ERROR `A` does not name a structure
-    let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
+    let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant
+    let v = u32 { x: 1 }; //~ ERROR `u32` does not name a struct or a struct variant
     match () {
         A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
-        //~^ ERROR `A` does not name a struct or a struct variant
         u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
-        //~^ ERROR `u32` does not name a struct or a struct variant
     }
 }
index d014c45ad2d1764e6e23c16e476a37909dff4ea9..e20e6ea23198cd3c885fa4bea2d8d90ec4a94567 100644 (file)
@@ -18,7 +18,7 @@ enum Enum {
 
 fn main() {
     let x = Foo(1);
-    Foo { ..x }; //~ ERROR `Foo` does not name a structure
+    Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
     let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
 
     let x = Bar;
index 8d74154655fcee4b9006a78b57786493f18aceef..576451f7292a894c1b8606e94401e5893849723b 100644 (file)
@@ -18,7 +18,7 @@ enum Foo {
 fn main() {
     match Foo::Baz {
         Foo::Bar => {}
-        //~^ ERROR `Foo::Bar` does not name a tuple variant or a tuple struct
+        //~^ ERROR `Foo::Bar` does not name a unit variant, unit struct or a constant
         _ => {}
     }
 
diff --git a/src/test/compile-fail/issue-34209.rs b/src/test/compile-fail/issue-34209.rs
new file mode 100644 (file)
index 0000000..6fae18d
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum S {
+    A,
+}
+
+fn bug(l: S) {
+    match l {
+        S::B{ } => { },
+        //~^ ERROR ambiguous associated type; specify the type using the syntax `<S as Trait>::B`
+    }
+}
+
+fn main () {}
index 843ff38df49cb6527e53e5b6af644f1b6e6bb444..55983c672aa08a8553ce28932d2db5202f277b63 100644 (file)
@@ -11,5 +11,5 @@
 struct NonCopyable(());
 
 fn main() {
-    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a structure
+    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
 }
index dbcd3f32f3b66f8af89f7029303d7344ce3147d8..505a91f223cc6ceb99afb37edf5540b923105301 100644 (file)
@@ -10,7 +10,7 @@
 
 struct T { i: i32 }
 fn f<T>() {
-    let t = T { i: 0 }; //~ ERROR `T` does not name a structure
+    let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant
 }
 
 mod Foo {
index 414d2a857acc72b0f813ef977a9ffbe8166a1374..953cd4a2ff5eac744efb08592f9c7b13f58da167 100644 (file)
@@ -128,6 +128,11 @@ fn test() {
         <Foo>::trait_stable_text(&foo);
         <Foo as Trait>::trait_stable_text(&foo);
 
+        struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
+        //~^ ERROR use of unstable library feature
+        struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
+        //~^ ERROR use of deprecated item
+
         let _ = DeprecatedStruct { //~ ERROR use of deprecated item
             i: 0 //~ ERROR use of deprecated item
         };
index faf6d255c9afc38c2b26ba93b5ea0105fbbcb59b..ef011c89c622ba184eb6e986834946681cb8165e 100644 (file)
@@ -22,12 +22,13 @@ impl MyTrait for Foo {}
 
 fn main() {
     match 0u32 {
-        Foo::bar => {} //~ ERROR E0327
+        Foo::bar => {} //~ ERROR `Foo::bar` does not name a unit variant, unit struct or a constant
     }
     match 0u32 {
-        <Foo>::bar => {} //~ ERROR E0327
+        <Foo>::bar => {} //~ ERROR `bar` does not name a unit variant, unit struct or a constant
     }
     match 0u32 {
-        <Foo>::trait_bar => {} //~ ERROR E0327
+        <Foo>::trait_bar => {}
+        //~^ ERROR `trait_bar` does not name a unit variant, unit struct or a constant
     }
 }
index 86873022f0ff10b666941c3cd86cdefcac106ffa..9034e24a6fee03fab57aa7f722658c8a72b806f5 100644 (file)
@@ -27,7 +27,8 @@ fn f<T>() {}
 
 fn main() {
     match 10 {
-        <S as Tr>::A::f::<u8> => {} //~ ERROR associated items in match patterns must be constants
+        <S as Tr>::A::f::<u8> => {}
+        //~^ ERROR `Tr::A::f<u8>` does not name a unit variant, unit struct or a constant
         0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
     }
 }
diff --git a/src/test/compile-fail/struct-pat-associated-path.rs b/src/test/compile-fail/struct-pat-associated-path.rs
new file mode 100644 (file)
index 0000000..d3f840f
--- /dev/null
@@ -0,0 +1,37 @@
+// 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 S;
+
+trait Tr {
+    type A;
+}
+
+impl Tr for S {
+    type A = S;
+}
+
+fn f<T: Tr>() {
+    match S {
+        T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
+    }
+}
+
+fn g<T: Tr<A = S>>() {
+    match S {
+        T::A {} => {} //~ ERROR `T::A` does not name a struct or a struct variant
+    }
+}
+
+fn main() {
+    match S {
+        S::A {} => {} //~ ERROR ambiguous associated type
+    }
+}
index 67ccd6b7cd058dd787c75c09230f58a45b72359c..13fdaa302f70a72ee0a800f21b42a93de4c9050d 100644 (file)
@@ -12,5 +12,5 @@ trait TraitNotAStruct {}
 
 fn main() {
     TraitNotAStruct{ value: 0 };
-    //~^ ERROR: `TraitNotAStruct` does not name a structure [E0071]
+    //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
 }
diff --git a/src/test/compile-fail/variant-size-differences.rs b/src/test/compile-fail/variant-size-differences.rs
new file mode 100644 (file)
index 0000000..f2cffee
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+#![deny(variant_size_differences)]
+
+enum _En {
+    V0(u8),
+    VBig([u8; 1024]),   //~ ERROR variant is more than three times larger
+}
+
+fn main() {}
index 04e19b30fd414242ed0014298a4aca5672308bd7..7b7bda302250fd8a30c62432d9a588567c320c11 100644 (file)
@@ -21,7 +21,6 @@
 // This test makes sure that the compiler doesn't crash when trying to assign
 // debug locations to const-expressions.
 
-use std::sync::StaticMutex;
 use std::cell::UnsafeCell;
 
 const CONSTANT: u64 = 3 + 4;
@@ -63,6 +62,5 @@ fn main() {
     let mut _string = STRING;
     let mut _vec = VEC;
     let mut _nested = NESTED;
-    let mut _extern = StaticMutex::new();
     let mut _unsafe_cell = UNSAFE_CELL;
 }
diff --git a/src/test/run-pass/issue34569.rs b/src/test/run-pass/issue34569.rs
new file mode 100644 (file)
index 0000000..41d02e9
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// compile-flags:-g
+
+// In this test we just want to make sure that the code below does not lead to
+// a debuginfo verification assertion during compilation. This was caused by the
+// closure in the guard being translated twice due to how match expressions are
+// handled.
+//
+// See https://github.com/rust-lang/rust/issues/34569 for details.
+
+fn main() {
+    match 0 {
+        e if (|| { e == 0 })() => {},
+        1 => {},
+        _ => {}
+    }
+}
index 7332f098b96fa770d62726a759120718dbb92554..03884e8205bd27a866e5e8cf647c03f5364eb4b7 100644 (file)
@@ -18,9 +18,6 @@
 fn assert_both<T: Sync + Send>() {}
 
 fn main() {
-    assert_both::<sync::StaticMutex>();
-    assert_both::<sync::StaticCondvar>();
-    assert_both::<sync::StaticRwLock>();
     assert_both::<sync::Mutex<()>>();
     assert_both::<sync::Condvar>();
     assert_both::<sync::RwLock<()>>();
index 41869288cc91c70edcf8a407d8702b3d1862863c..3a70e54ff9745d457b24f0f320eee2fbec43e74d 100644 (file)
@@ -25,7 +25,7 @@ pub fn check(path: &Path, bad: &mut bool) {
                 &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                 &mut |file| {
         let filename = file.file_name().unwrap().to_string_lossy();
-        if filename != "diagnostics.rs" {
+        if filename != "diagnostics.rs" && filename != "diagnostic_list.rs" {
             return
         }
 
index 0b989d92b3d1d0df4cdb104efda8186671f7c44a..199e8a77df71797b7eed2b5d7107e634f6a1a6dc 100644 (file)
@@ -46,7 +46,8 @@ pub fn check(path: &Path, bad: &mut bool) {
                 &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                 &mut |file| {
         let filename = file.file_name().unwrap().to_string_lossy();
-        if !filename.ends_with(".rs") || filename == "features.rs" {
+        if !filename.ends_with(".rs") || filename == "features.rs" ||
+           filename == "diagnostic_list.rs" {
             return
         }