]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #33997 - jseyfried:resolve_in_phase_2, r=nrc
authorbors <bors@rust-lang.org>
Fri, 3 Jun 2016 15:22:54 +0000 (08:22 -0700)
committerbors <bors@rust-lang.org>
Fri, 3 Jun 2016 15:22:54 +0000 (08:22 -0700)
Move name resolution into phase 2

r? @nrc

81 files changed:
.travis.yml
src/doc/book/choosing-your-guarantees.md
src/doc/book/documentation.md
src/doc/book/error-handling.md
src/doc/book/using-rust-without-the-standard-library.md
src/doc/book/vectors.md
src/doc/nomicon/README.md
src/etc/Dockerfile [new file with mode: 0644]
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/str.rs
src/libcollectionstest/btree/map.rs
src/libcollectionstest/btree/mod.rs
src/libcollectionstest/btree/set.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/str.rs
src/libcore/cell.rs
src/libcore/raw.rs
src/libcore/str/mod.rs
src/libcoretest/cell.rs
src/liblibc
src/librustc_const_eval/diagnostics.rs
src/librustc_mir/build/matches/test.rs
src/librustc_resolve/lib.rs
src/librustc_typeck/diagnostics.rs
src/libstd/fs.rs
src/libstd/panic.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/common/mutex.rs
src/libstd/sys/common/util.rs
src/libstd/sys/unix/ext/process.rs
src/libstd/sys/unix/mutex.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/rwlock.rs
src/libstd/sys/windows/mutex.rs
src/libstd/thread/mod.rs
src/libstd/thread/scoped_tls.rs [deleted file]
src/libstd/time/mod.rs
src/rt/hoedown
src/test/compile-fail/E0162.rs [new file with mode: 0644]
src/test/compile-fail/E0163.rs [new file with mode: 0644]
src/test/compile-fail/E0164.rs [new file with mode: 0644]
src/test/compile-fail/E0165.rs [new file with mode: 0644]
src/test/compile-fail/E0166.rs [new file with mode: 0644]
src/test/compile-fail/E0172.rs [new file with mode: 0644]
src/test/compile-fail/E0178.rs [new file with mode: 0644]
src/test/compile-fail/E0184.rs [new file with mode: 0644]
src/test/compile-fail/E0185.rs [new file with mode: 0644]
src/test/compile-fail/E0186.rs [new file with mode: 0644]
src/test/compile-fail/E0191.rs [new file with mode: 0644]
src/test/compile-fail/E0192.rs [new file with mode: 0644]
src/test/compile-fail/E0194.rs [new file with mode: 0644]
src/test/compile-fail/E0195.rs [new file with mode: 0644]
src/test/compile-fail/E0197.rs [new file with mode: 0644]
src/test/compile-fail/E0199.rs [new file with mode: 0644]
src/test/compile-fail/E0200.rs [new file with mode: 0644]
src/test/compile-fail/issue-16338.rs
src/test/compile-fail/issue-16401.rs
src/test/compile-fail/issue-2356.rs
src/test/compile-fail/issue-33876.rs [new file with mode: 0644]
src/test/compile-fail/not-panic-safe-2.rs
src/test/compile-fail/not-panic-safe-3.rs
src/test/compile-fail/not-panic-safe-4.rs
src/test/compile-fail/not-panic-safe-5.rs
src/test/compile-fail/not-panic-safe-6.rs
src/test/compile-fail/suggest-path-instead-of-mod-dot-item.rs
src/test/run-fail/panic-set-handler.rs
src/test/run-fail/panic-set-unset-handler.rs
src/test/run-fail/panic-take-handler-nop.rs
src/test/run-pass/binary-heap-panic-safe.rs
src/test/run-pass/exhaustive-bool-match-sanity.rs [new file with mode: 0644]
src/test/run-pass/issue-33770.rs [new file with mode: 0644]
src/test/run-pass/panic-recover-propagate.rs
src/test/run-pass/reachable-unnameable-items.rs
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/utf8_chars.rs
src/test/run-pass/variadic-ffi.rs

index cc93b1127c3a73069dd5d6a7053ee741f9781984..87197a37f1d4919a4d239cc3423fa57d61f35799 100644 (file)
@@ -1,6 +1,7 @@
 language: generic
 sudo: required
-dist: trusty
+services:
+  - docker
 
 # LLVM takes awhile to check out and otherwise we'll manage the submodules in
 # our configure script, so disable auto submodule management.
@@ -8,15 +9,15 @@ git:
   submodules: false
 
 before_install:
-  - echo 0 | sudo tee /proc/sys/net/ipv6/conf/lo/disable_ipv6
-  - echo 'deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main' | sudo tee -a /etc/apt/sources.list
-  - echo 'deb-src http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main' | sudo tee -a /etc/apt/sources.list
-  - sudo apt-get update
-  - sudo apt-get --force-yes install curl make g++ python2.7 git zlib1g-dev libedit-dev llvm-3.7-tools
+  - docker build -t rust -f src/etc/Dockerfile src/etc
 
 script:
-  - ./configure --llvm-root=/usr/lib/llvm-3.7
-  - make tidy && make check-notidy -j4
+  - docker run -v `pwd`:/build rust
+    sh -c "
+      ./configure --llvm-root=/usr/lib/llvm-3.7 &&
+      make tidy &&
+      make check-notidy -j4
+    "
 
 # Real testing happens on http://buildbot.rust-lang.org/
 #
index 50350213074bf3a2cd2368db61d0d7acce5c7a23..d88f619260ac0ca4d95a3edc5a6a12b63480991a 100644 (file)
@@ -232,7 +232,7 @@ indicator (one word in size) along with the data.
 
 At runtime each borrow causes a modification/check of the refcount.
 
-[cell-mod]: ../std/cell/
+[cell-mod]: ../std/cell/index.html
 [cell]: ../std/cell/struct.Cell.html
 [refcell]: ../std/cell/struct.RefCell.html
 
index 4a41bb7b7f37eee595870bb26f5680de4122587b..3c6643fbfe1554e0ae02c5bc551f0a04353715c2 100644 (file)
@@ -76,7 +76,7 @@ This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
 correct; documentation comments apply to the thing after them, and there's
 nothing after that last comment.
 
-[rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
+[rc-new]: ../std/rc/struct.Rc.html#method.new
 
 ### Writing documentation comments
 
index c914c33a5a4b989e369e01489ff8aca199130c00..bca3418706771e08259946c1d36935a47345201c 100644 (file)
@@ -2205,7 +2205,7 @@ heuristics!
 [3]: ../std/option/enum.Option.html#method.unwrap_or
 [4]: ../std/option/enum.Option.html#method.unwrap_or_else
 [5]: ../std/option/enum.Option.html
-[6]: ../std/result/
+[6]: ../std/result/index.html
 [7]: ../std/result/enum.Result.html#method.unwrap
 [8]: ../std/fmt/trait.Debug.html
 [9]: ../std/primitive.str.html#method.parse
index 1179aebe54c552462099174392100468f29a1608..69958dd3e68a41c717527cc05347eb9d064705d1 100644 (file)
@@ -22,11 +22,12 @@ fn plus_one(x: i32) -> i32 {
 ```
 
 Much of the functionality that’s exposed in the standard library is also
-available via the [`core` crate](../core/). When we’re using the standard
-library, Rust automatically brings `std` into scope, allowing you to use
-its features without an explicit import. By the same token, when using
+available via the [`core` crate](../core/index.html). When we’re using the
+standard library, Rust automatically brings `std` into scope, allowing you to
+use its features without an explicit import. By the same token, when using
 `#![no_std]`, Rust will bring `core` into scope for you, as well as [its
-prelude](../core/prelude/v1/). This means that a lot of code will Just Work:
+prelude](../core/prelude/v1/index.html). This means that a lot of code will Just
+Work:
 
 ```rust
 #![no_std]
index 1c44af2f21a7198db6ff597fca3bec4188a27b85..f3854b8ffddce4598749fca9625996f11b03d21d 100644 (file)
@@ -152,5 +152,5 @@ API documentation][vec].
 [box]: ../std/boxed/index.html
 [generic]: generics.html
 [panic]: concurrency.html#panics
-[get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get
-[get_mut]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_mut
+[get]: ../std/vec/struct.Vec.html#method.get
+[get_mut]: ../std/vec/struct.Vec.html#method.get_mut
index 4554652a17a2a40732f03e879a27bdc56e3a139e..b2e1eac5e0dccea7692c23a131faae5b288280d6 100644 (file)
@@ -35,4 +35,4 @@ exception-safety, pointer aliasing, memory models, and even some type-theory.
 We will also be spending a lot of time talking about the different kinds
 of safety and guarantees.
 
-[trpl]: ../book/
+[trpl]: ../book/index.html
diff --git a/src/etc/Dockerfile b/src/etc/Dockerfile
new file mode 100644 (file)
index 0000000..58fa147
--- /dev/null
@@ -0,0 +1,25 @@
+FROM ubuntu:xenial
+
+# curl
+#   Download stage0, see src/bootstrap/bootstrap.py
+# g++
+#   Compile LLVM binding in src/rustllvm
+# git
+#   Get commit hash and commit date in version string
+# make
+#   Run build scripts in mk
+# libedit-dev zlib1g-dev
+#   LLVM dependencies as packaged in Ubuntu
+#   (They are optional, but Ubuntu package enables them)
+# llvm-3.7-dev (installed by llvm-3.7-tools)
+#   LLVM
+# llvm-3.7-tools
+#   FileCheck is used to run tests in src/test/codegen
+
+RUN apt-get update && apt-get -y install \
+    curl g++ git make \
+    libedit-dev zlib1g-dev \
+    llvm-3.7-tools
+
+RUN mkdir /build
+WORKDIR /build
index ec2f4a9f7f0b82208b230a687c95cd28e8c51a7e..29f3e4b1b6159cd4a02d23baf4468d653180af39 100644 (file)
@@ -842,13 +842,13 @@ fn fix_right_edge(&mut self) {
             // Check if right-most child is underfull.
             let mut last_edge = internal.last_edge();
             let right_child_len = last_edge.reborrow().descend().len();
-            if right_child_len < node::CAPACITY / 2 {
+            if right_child_len < node::MIN_LEN {
                 // We need to steal.
                 let mut last_kv = match last_edge.left_kv() {
                     Ok(left) => left,
                     Err(_) => unreachable!(),
                 };
-                last_kv.bulk_steal_left(node::CAPACITY/2 - right_child_len);
+                last_kv.bulk_steal_left(node::MIN_LEN - right_child_len);
                 last_edge = last_kv.right_edge();
             }
 
@@ -856,6 +856,174 @@ fn fix_right_edge(&mut self) {
             cur_node = last_edge.descend();
         }
     }
+
+    /// Splits the collection into two at the given key. Returns everything after the given key,
+    /// including the key.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(btree_split_off)]
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut a = BTreeMap::new();
+    /// a.insert(1, "a");
+    /// a.insert(2, "b");
+    /// a.insert(3, "c");
+    /// a.insert(17, "d");
+    /// a.insert(41, "e");
+    ///
+    /// let b = a.split_off(&3);
+    ///
+    /// assert_eq!(a.len(), 2);
+    /// assert_eq!(b.len(), 3);
+    ///
+    /// assert_eq!(a[&1], "a");
+    /// assert_eq!(a[&2], "b");
+    ///
+    /// assert_eq!(b[&3], "c");
+    /// assert_eq!(b[&17], "d");
+    /// assert_eq!(b[&41], "e");
+    /// ```
+    #[unstable(feature = "btree_split_off",
+               reason = "recently added as part of collections reform 2",
+               issue = "19986")]
+    pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where K: Borrow<Q> {
+        if self.is_empty() {
+            return Self::new();
+        }
+
+        let total_num = self.len();
+
+        let mut right = Self::new();
+        for _ in 0..(self.root.as_ref().height()) {
+            right.root.push_level();
+        }
+
+        {
+            let mut left_node = self.root.as_mut();
+            let mut right_node = right.root.as_mut();
+
+            loop {
+                let mut split_edge = match search::search_node(left_node, key) {
+                    // key is going to the right tree
+                    Found(handle) => handle.left_edge(),
+                    GoDown(handle) => handle
+                };
+
+                split_edge.move_suffix(&mut right_node);
+
+                match (split_edge.force(), right_node.force()) {
+                    (Internal(edge), Internal(node)) => {
+                        left_node = edge.descend();
+                        right_node = node.first_edge().descend();
+                    }
+                    (Leaf(_), Leaf(_)) => { break; },
+                    _ => { unreachable!(); }
+                }
+            }
+        }
+
+        self.fix_right_border();
+        right.fix_left_border();
+
+        if self.root.as_ref().height() < right.root.as_ref().height() {
+            self.recalc_length();
+            right.length = total_num - self.len();
+        } else {
+            right.recalc_length();
+            self.length = total_num - right.len();
+        }
+
+        right
+    }
+
+    /// Calculates the number of elements if it is incorrect.
+    fn recalc_length(&mut self) {
+        fn dfs<K, V>(node: NodeRef<marker::Immut, K, V, marker::LeafOrInternal>) -> usize {
+            let mut res = node.len();
+
+            if let Internal(node) = node.force() {
+                let mut edge = node.first_edge();
+                loop {
+                    res += dfs(edge.reborrow().descend());
+                    match edge.right_kv() {
+                        Ok(right_kv) => { edge = right_kv.right_edge(); },
+                        Err(_) => { break; }
+                    }
+                }
+            }
+
+            res
+        }
+
+        self.length = dfs(self.root.as_ref());
+    }
+
+    /// Removes empty levels on the top.
+    fn fix_top(&mut self) {
+        loop {
+            {
+                let node = self.root.as_ref();
+                if node.height() == 0 || node.len() > 0 {
+                    break;
+                }
+            }
+            self.root.pop_level();
+        }
+    }
+
+    fn fix_right_border(&mut self) {
+        self.fix_top();
+
+        {
+            let mut cur_node = self.root.as_mut();
+
+            while let Internal(node) = cur_node.force() {
+                let mut last_kv = node.last_kv();
+
+                if last_kv.can_merge() {
+                    cur_node = last_kv.merge().descend();
+                } else {
+                    let right_len = last_kv.reborrow().right_edge().descend().len();
+                    // `MINLEN + 1` to avoid readjust if merge happens on the next level.
+                    if right_len < node::MIN_LEN + 1 {
+                        last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
+                    }
+                    cur_node = last_kv.right_edge().descend();
+                }
+            }
+        }
+
+        self.fix_top();
+    }
+
+    /// The symmetric clone of `fix_right_border`.
+    fn fix_left_border(&mut self) {
+        self.fix_top();
+
+        {
+            let mut cur_node = self.root.as_mut();
+
+            while let Internal(node) = cur_node.force() {
+                let mut first_kv = node.first_kv();
+
+                if first_kv.can_merge() {
+                    cur_node = first_kv.merge().descend();
+                } else {
+                    let left_len = first_kv.reborrow().left_edge().descend().len();
+                    if left_len < node::MIN_LEN + 1 {
+                        first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
+                    }
+                    cur_node = first_kv.left_edge().descend();
+                }
+            }
+        }
+
+        self.fix_top();
+    }
 }
 
 impl<'a, K: 'a, V: 'a> IntoIterator for &'a BTreeMap<K, V> {
index ca1cf6bcc50280c81fe56a4445a6df2f13f72968..e9bc29118d508aa6b4bf36e926c16bfd4cae40f3 100644 (file)
@@ -51,6 +51,7 @@
 use boxed::Box;
 
 const B: usize = 6;
+pub const MIN_LEN: usize = B - 1;
 pub const CAPACITY: usize = 2 * B - 1;
 
 /// The underlying representation of leaf nodes. Note that it is often unsafe to actually store
@@ -413,6 +414,19 @@ pub fn last_edge(self) -> Handle<Self, marker::Edge> {
         let len = self.len();
         Handle::new_edge(self, len)
     }
+
+    /// Note that `self` must be nonempty.
+    pub fn first_kv(self) -> Handle<Self, marker::KV> {
+        debug_assert!(self.len() > 0);
+        Handle::new_kv(self, 0)
+    }
+
+    /// Note that `self` must be nonempty.
+    pub fn last_kv(self) -> Handle<Self, marker::KV> {
+        let len = self.len();
+        debug_assert!(len > 0);
+        Handle::new_kv(self, len - 1)
+    }
 }
 
 impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
@@ -602,6 +616,17 @@ pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
         }
     }
 
+    fn correct_childrens_parent_links(&mut self, first: usize, after_last: usize) {
+        for i in first..after_last {
+            Handle::new_edge(unsafe { self.reborrow_mut() }, i).correct_parent_link();
+        }
+    }
+
+    fn correct_all_childrens_parent_links(&mut self) {
+        let len = self.len();
+        self.correct_childrens_parent_links(0, len + 1);
+    }
+
     /// Adds a key/value pair and an edge to go to the left of that pair to
     /// the beginning of the node.
     pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
@@ -623,11 +648,8 @@ pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
 
             self.as_leaf_mut().len += 1;
 
-            for i in 0..self.len()+1 {
-                Handle::new_edge(self.reborrow_mut(), i).correct_parent_link();
-            }
+            self.correct_all_childrens_parent_links();
         }
-
     }
 }
 
@@ -696,6 +718,13 @@ pub fn pop_front(&mut self) -> (K, V, Option<Root<K, V>>) {
             (key, val, edge)
         }
     }
+
+    fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
+        (
+            self.keys_mut().as_mut_ptr(),
+            self.vals_mut().as_mut_ptr()
+        )
+    }
 }
 
 impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
@@ -1275,105 +1304,155 @@ pub fn steal_right(&mut self) {
     }
 
     /// This does stealing similar to `steal_left` but steals multiple elements at once.
-    pub fn bulk_steal_left(&mut self, n: usize) {
+    pub fn bulk_steal_left(&mut self, count: usize) {
         unsafe {
-            // Get raw pointers to left child's keys, values and edges.
-            let (left_len, left_k, left_v, left_e) = {
-                let mut left = self.reborrow_mut().left_edge().descend();
-
-                (left.len(),
-                 left.keys_mut().as_mut_ptr(),
-                 left.vals_mut().as_mut_ptr(),
-                 match left.force() {
-                     ForceResult::Leaf(_) => None,
-                     ForceResult::Internal(mut i) => Some(i.as_internal_mut().edges.as_mut_ptr()),
-                 })
-            };
-
-            // Get raw pointers to right child's keys, values and edges.
-            let (right_len, right_k, right_v, right_e) = {
-                let mut right = self.reborrow_mut().right_edge().descend();
-
-                (right.len(),
-                 right.keys_mut().as_mut_ptr(),
-                 right.vals_mut().as_mut_ptr(),
-                 match right.force() {
-                     ForceResult::Leaf(_) => None,
-                     ForceResult::Internal(mut i) => Some(i.as_internal_mut().edges.as_mut_ptr()),
-                 })
-            };
-
-            // Get raw pointers to parent's key and value.
-            let (parent_k, parent_v) = {
-                let kv = self.reborrow_mut().into_kv_mut();
-                (kv.0 as *mut K, kv.1 as *mut V)
-            };
+            let mut left_node = ptr::read(self).left_edge().descend();
+            let left_len = left_node.len();
+            let mut right_node = ptr::read(self).right_edge().descend();
+            let right_len = right_node.len();
 
             // Make sure that we may steal safely.
-            debug_assert!(right_len + n <= CAPACITY);
-            debug_assert!(left_len >= n);
-
-            // Make room for stolen elements in right child.
-            ptr::copy(right_k,
-                      right_k.offset(n as isize),
-                      right_len);
-            ptr::copy(right_v,
-                      right_v.offset(n as isize),
-                      right_len);
-            if let Some(edges) = right_e {
-                ptr::copy(edges,
-                          edges.offset(n as isize),
-                          right_len+1);
+            debug_assert!(right_len + count <= CAPACITY);
+            debug_assert!(left_len >= count);
+
+            let new_left_len = left_len - count;
+
+            // Move data.
+            {
+                let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
+                let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
+                let parent_kv = {
+                    let kv = self.reborrow_mut().into_kv_mut();
+                    (kv.0 as *mut K, kv.1 as *mut V)
+                };
+
+                // Make room for stolen elements in the right child.
+                ptr::copy(right_kv.0,
+                          right_kv.0.offset(count as isize),
+                          right_len);
+                ptr::copy(right_kv.1,
+                          right_kv.1.offset(count as isize),
+                          right_len);
+
+                // Move elements from the left child to the right one.
+                move_kv(left_kv, new_left_len + 1, right_kv, 0, count - 1);
+
+                // Move parent's key/value pair to the right child.
+                move_kv(parent_kv, 0, right_kv, count - 1, 1);
+
+                // Move the left-most stolen pair to the parent.
+                move_kv(left_kv, new_left_len, parent_kv, 0, 1);
             }
 
-            // Move elements from the left child to the right one.
-            let left_ind = (left_len - n) as isize;
-            ptr::copy_nonoverlapping(left_k.offset(left_ind + 1),
-                                     right_k,
-                                     n - 1);
-            ptr::copy_nonoverlapping(left_v.offset(left_ind + 1),
-                                     right_v,
-                                     n - 1);
-            match (left_e, right_e) {
-                (Some(left), Some(right)) => {
-                    ptr::copy_nonoverlapping(left.offset(left_ind + 1),
-                                             right,
-                                             n);
+            left_node.reborrow_mut().as_leaf_mut().len -= count as u16;
+            right_node.reborrow_mut().as_leaf_mut().len += count as u16;
+
+            match (left_node.force(), right_node.force()) {
+                (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
+                    // Make room for stolen edges.
+                    let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr();
+                    ptr::copy(right_edges,
+                              right_edges.offset(count as isize),
+                              right_len + 1);
+                    right.correct_childrens_parent_links(count, count + right_len + 1);
+
+                    move_edges(left, new_left_len + 1, right, 0, count);
                 },
-                (Some(_), None) => unreachable!(),
-                (None, Some(_)) => unreachable!(),
-                (None, None) => {},
+                (ForceResult::Leaf(_), ForceResult::Leaf(_)) => { }
+                _ => { unreachable!(); }
             }
+        }
+    }
 
-            // Copy parent key/value pair to right child.
-            ptr::copy_nonoverlapping(parent_k,
-                                     right_k.offset(n as isize - 1),
-                                     1);
-            ptr::copy_nonoverlapping(parent_v,
-                                     right_v.offset(n as isize - 1),
-                                     1);
-            // Copy left-most stolen pair to parent.
-            ptr::copy_nonoverlapping(left_k.offset(left_ind),
-                                     parent_k,
-                                     1);
-            ptr::copy_nonoverlapping(left_v.offset(left_ind),
-                                     parent_v,
-                                     1);
-
-            // Fix lengths of left and right child and parent pointers in children of the right
-            // child.
-            self.reborrow_mut().left_edge().descend().as_leaf_mut().len -= n as u16;
-            let mut right = self.reborrow_mut().right_edge().descend();
-            right.as_leaf_mut().len += n as u16;
-            if let ForceResult::Internal(mut node) = right.force() {
-                for i in 0..(right_len+n+1) {
-                    Handle::new_edge(node.reborrow_mut(), i as usize).correct_parent_link();
-                }
+    /// The symmetric clone of `bulk_steal_left`.
+    pub fn bulk_steal_right(&mut self, count: usize) {
+        unsafe {
+            let mut left_node = ptr::read(self).left_edge().descend();
+            let left_len = left_node.len();
+            let mut right_node = ptr::read(self).right_edge().descend();
+            let right_len = right_node.len();
+
+            // Make sure that we may steal safely.
+            debug_assert!(left_len + count <= CAPACITY);
+            debug_assert!(right_len >= count);
+
+            let new_right_len = right_len - count;
+
+            // Move data.
+            {
+                let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
+                let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
+                let parent_kv = {
+                    let kv = self.reborrow_mut().into_kv_mut();
+                    (kv.0 as *mut K, kv.1 as *mut V)
+                };
+
+                // Move parent's key/value pair to the left child.
+                move_kv(parent_kv, 0, left_kv, left_len, 1);
+
+                // Move elements from the right child to the left one.
+                move_kv(right_kv, 0, left_kv, left_len + 1, count - 1);
+
+                // Move the right-most stolen pair to the parent.
+                move_kv(right_kv, count - 1, parent_kv, 0, 1);
+
+                // Fix right indexing
+                ptr::copy(right_kv.0.offset(count as isize),
+                          right_kv.0,
+                          new_right_len);
+                ptr::copy(right_kv.1.offset(count as isize),
+                          right_kv.1,
+                          new_right_len);
+            }
+
+            left_node.reborrow_mut().as_leaf_mut().len += count as u16;
+            right_node.reborrow_mut().as_leaf_mut().len -= count as u16;
+
+            match (left_node.force(), right_node.force()) {
+                (ForceResult::Internal(left), ForceResult::Internal(mut right)) => {
+                    move_edges(right.reborrow_mut(), 0, left, left_len + 1, count);
+
+                    // Fix right indexing.
+                    let right_edges = right.reborrow_mut().as_internal_mut().edges.as_mut_ptr();
+                    ptr::copy(right_edges.offset(count as isize),
+                              right_edges,
+                              new_right_len + 1);
+                    right.correct_childrens_parent_links(0, new_right_len + 1);
+                },
+                (ForceResult::Leaf(_), ForceResult::Leaf(_)) => { }
+                _ => { unreachable!(); }
             }
         }
     }
 }
 
+unsafe fn move_kv<K, V>(
+    source: (*mut K, *mut V), source_offset: usize,
+    dest: (*mut K, *mut V), dest_offset: usize,
+    count: usize)
+{
+    ptr::copy_nonoverlapping(source.0.offset(source_offset as isize),
+                             dest.0.offset(dest_offset as isize),
+                             count);
+    ptr::copy_nonoverlapping(source.1.offset(source_offset as isize),
+                             dest.1.offset(dest_offset as isize),
+                             count);
+}
+
+// Source and destination must have the same height.
+unsafe fn move_edges<K, V>(
+    mut source: NodeRef<marker::Mut, K, V, marker::Internal>, source_offset: usize,
+    mut dest: NodeRef<marker::Mut, K, V, marker::Internal>, dest_offset: usize,
+    count: usize)
+{
+    let source_ptr = source.as_internal_mut().edges.as_mut_ptr();
+    let dest_ptr = dest.as_internal_mut().edges.as_mut_ptr();
+    ptr::copy_nonoverlapping(source_ptr.offset(source_offset as isize),
+                             dest_ptr.offset(dest_offset as isize),
+                             count);
+    dest.correct_childrens_parent_links(dest_offset, dest_offset + count);
+}
+
 impl<BorrowType, K, V, HandleType>
         Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, HandleType> {
 
@@ -1397,6 +1476,41 @@ pub fn force(self) -> ForceResult<
     }
 }
 
+impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::Edge> {
+    /// Move the suffix after `self` from one node to another one. `right` must be empty.
+    /// The first edge of `right` remains unchanged.
+    pub fn move_suffix(&mut self,
+            right: &mut NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>) {
+        unsafe {
+            let left_new_len = self.idx;
+            let mut left_node = self.reborrow_mut().into_node();
+
+            let right_new_len = left_node.len() - left_new_len;
+            let mut right_node = right.reborrow_mut();
+
+            debug_assert!(right_node.len() == 0);
+            debug_assert!(left_node.height == right_node.height);
+
+            let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
+            let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
+
+
+            move_kv(left_kv, left_new_len, right_kv, 0, right_new_len);
+
+            left_node.reborrow_mut().as_leaf_mut().len = left_new_len as u16;
+            right_node.reborrow_mut().as_leaf_mut().len = right_new_len as u16;
+
+            match (left_node.force(), right_node.force()) {
+                (ForceResult::Internal(left), ForceResult::Internal(right)) => {
+                    move_edges(left, left_new_len + 1, right, 1, right_new_len);
+                },
+                (ForceResult::Leaf(_), ForceResult::Leaf(_)) => { }
+                _ => { unreachable!(); }
+            }
+        }
+    }
+}
+
 pub enum ForceResult<Leaf, Internal> {
     Leaf(Leaf),
     Internal(Internal)
index 3ee42499a38f868c5d4b4ebf00896fbd68a83f37..765595be317c117b705aaa8c90933d383cd1019d 100644 (file)
@@ -580,6 +580,43 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
     pub fn append(&mut self, other: &mut Self) {
         self.map.append(&mut other.map);
     }
+
+    /// Splits the collection into two at the given key. Returns everything after the given key,
+    /// including the key.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(btree_split_off)]
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut a = BTreeMap::new();
+    /// a.insert(1, "a");
+    /// a.insert(2, "b");
+    /// a.insert(3, "c");
+    /// a.insert(17, "d");
+    /// a.insert(41, "e");
+    ///
+    /// let b = a.split_off(&3);
+    ///
+    /// assert_eq!(a.len(), 2);
+    /// assert_eq!(b.len(), 3);
+    ///
+    /// assert_eq!(a[&1], "a");
+    /// assert_eq!(a[&2], "b");
+    ///
+    /// assert_eq!(b[&3], "c");
+    /// assert_eq!(b[&17], "d");
+    /// assert_eq!(b[&41], "e");
+    /// ```
+    #[unstable(feature = "btree_split_off",
+               reason = "recently added as part of collections reform 2",
+               issue = "19986")]
+    pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where T: Borrow<Q> {
+        BTreeSet { map: self.map.split_off(key) }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index f3770816cb6b3aa184f1b398df3a37ebaf7adc9a..d7c11f32404395db1b82cdac20348658d62ab828 100644 (file)
@@ -112,11 +112,6 @@ fn connect(&self, sep: &str) -> String {
     }
 }
 
-/// Deprecated, renamed to EncodeUtf16
-#[unstable(feature = "str_utf16", issue = "27714")]
-#[rustc_deprecated(since = "1.8.0", reason = "renamed to EncodeUtf16")]
-pub type Utf16Units<'a> = EncodeUtf16<'a>;
-
 /// External iterator for a string's UTF-16 code units.
 ///
 /// For use with the `std::iter` module.
@@ -352,230 +347,6 @@ pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut s
         core_str::StrExt::slice_mut_unchecked(self, begin, end)
     }
 
-    /// Given a byte position, returns the next `char` and its index.
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 sequence.
-    ///
-    /// # Examples
-    ///
-    /// This example manually iterates through the code points of a string;
-    /// this should normally be
-    /// done by `.chars()` or `.char_indices()`.
-    ///
-    /// ```
-    /// #![feature(str_char)]
-    /// #![allow(deprecated)]
-    ///
-    /// use std::str::CharRange;
-    ///
-    /// let s = "中华Việt Nam";
-    /// let mut i = 0;
-    /// while i < s.len() {
-    ///     let CharRange {ch, next} = s.char_range_at(i);
-    ///     println!("{}: {}", i, ch);
-    ///     i = next;
-    /// }
-    /// ```
-    ///
-    /// This outputs:
-    ///
-    /// ```text
-    /// 0: 中
-    /// 3: 华
-    /// 6: V
-    /// 7: i
-    /// 8: e
-    /// 9:
-    /// 11:
-    /// 13: t
-    /// 14:
-    /// 15: N
-    /// 16: a
-    /// 17: m
-    /// ```
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at() or eventually \
-                         removed altogether",
-               issue = "27754")]
-    #[inline]
-    #[rustc_deprecated(reason = "use slicing plus chars() plus len_utf8",
-                       since = "1.9.0")]
-    #[allow(deprecated)]
-    pub fn char_range_at(&self, start: usize) -> CharRange {
-        core_str::StrExt::char_range_at(self, start)
-    }
-
-    /// Given a byte position, returns the previous `char` and its position.
-    ///
-    /// Note that Unicode has many features, such as combining marks, ligatures,
-    /// and direction marks, that need to be taken into account to correctly reverse a string.
-    ///
-    /// Returns 0 for next index if called on start index 0.
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than the length of the string.
-    /// If `i` is not an index following a valid UTF-8 sequence.
-    ///
-    /// # Examples
-    ///
-    /// This example manually iterates through the code points of a string;
-    /// this should normally be
-    /// done by `.chars().rev()` or `.char_indices()`.
-    ///
-    /// ```
-    /// #![feature(str_char)]
-    /// #![allow(deprecated)]
-    ///
-    /// use std::str::CharRange;
-    ///
-    /// let s = "中华Việt Nam";
-    /// let mut i = s.len();
-    /// while i > 0 {
-    ///     let CharRange {ch, next} = s.char_range_at_reverse(i);
-    ///     println!("{}: {}", i, ch);
-    ///     i = next;
-    /// }
-    /// ```
-    ///
-    /// This outputs:
-    ///
-    /// ```text
-    /// 18: m
-    /// 17: a
-    /// 16: N
-    /// 15:
-    /// 14: t
-    /// 13:
-    /// 11:
-    /// 9: e
-    /// 8: i
-    /// 7: V
-    /// 6: 华
-    /// 3: 中
-    /// ```
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at_reverse() or \
-                         eventually removed altogether",
-               issue = "27754")]
-    #[inline]
-    #[rustc_deprecated(reason = "use slicing plus chars().rev() plus len_utf8",
-                       since = "1.9.0")]
-    #[allow(deprecated)]
-    pub fn char_range_at_reverse(&self, start: usize) -> CharRange {
-        core_str::StrExt::char_range_at_reverse(self, start)
-    }
-
-    /// Given a byte position, returns the `char` at that position.
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 sequence.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(str_char)]
-    /// #![allow(deprecated)]
-    ///
-    /// let s = "abπc";
-    /// assert_eq!(s.char_at(1), 'b');
-    /// assert_eq!(s.char_at(2), 'π');
-    /// assert_eq!(s.char_at(4), 'c');
-    /// ```
-    #[unstable(feature = "str_char",
-               reason = "frequently replaced by the chars() iterator, this \
-                         method may be removed or possibly renamed in the \
-                         future; it is normally replaced by chars/char_indices \
-                         iterators or by getting the first char from a \
-                         subslice",
-               issue = "27754")]
-    #[inline]
-    #[allow(deprecated)]
-    #[rustc_deprecated(reason = "use slicing plus chars()",
-                       since = "1.9.0")]
-    pub fn char_at(&self, i: usize) -> char {
-        core_str::StrExt::char_at(self, i)
-    }
-
-    /// Given a byte position, returns the `char` at that position, counting
-    /// from the end.
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than the length of the string.
-    /// If `i` is not an index following a valid UTF-8 sequence.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(str_char)]
-    /// #![allow(deprecated)]
-    ///
-    /// let s = "abπc";
-    /// assert_eq!(s.char_at_reverse(1), 'a');
-    /// assert_eq!(s.char_at_reverse(2), 'b');
-    /// assert_eq!(s.char_at_reverse(3), 'π');
-    /// ```
-    #[unstable(feature = "str_char",
-               reason = "see char_at for more details, but reverse semantics \
-                         are also somewhat unclear, especially with which \
-                         cases generate panics",
-               issue = "27754")]
-    #[inline]
-    #[rustc_deprecated(reason = "use slicing plus chars().rev()",
-                       since = "1.9.0")]
-    #[allow(deprecated)]
-    pub fn char_at_reverse(&self, i: usize) -> char {
-        core_str::StrExt::char_at_reverse(self, i)
-    }
-
-    /// Retrieves the first `char` from a `&str` and returns it.
-    ///
-    /// Note that a single Unicode character (grapheme cluster)
-    /// can be composed of multiple `char`s.
-    ///
-    /// This does not allocate a new string; instead, it returns a slice that
-    /// points one code point beyond the code point that was shifted.
-    ///
-    /// `None` is returned if the slice is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(str_char)]
-    /// #![allow(deprecated)]
-    ///
-    /// let s = "Łódź"; // \u{141}o\u{301}dz\u{301}
-    /// let (c, s1) = s.slice_shift_char().unwrap();
-    ///
-    /// assert_eq!(c, 'Ł');
-    /// assert_eq!(s1, "ódź");
-    ///
-    /// let (c, s2) = s1.slice_shift_char().unwrap();
-    ///
-    /// assert_eq!(c, 'o');
-    /// assert_eq!(s2, "\u{301}dz\u{301}");
-    /// ```
-    #[unstable(feature = "str_char",
-               reason = "awaiting conventions about shifting and slices and \
-                         may not be warranted with the existence of the chars \
-                         and/or char_indices iterators",
-               issue = "27754")]
-    #[inline]
-    #[rustc_deprecated(reason = "use chars() plus Chars::as_str",
-                       since = "1.9.0")]
-    #[allow(deprecated)]
-    pub fn slice_shift_char(&self) -> Option<(char, &str)> {
-        core_str::StrExt::slice_shift_char(self)
-    }
-
     /// Divide one string slice into two at an index.
     ///
     /// The argument, `mid`, should be a byte offset from the start of the
@@ -867,16 +638,6 @@ pub fn lines_any(&self) -> LinesAny {
         core_str::StrExt::lines_any(self)
     }
 
-    /// Returns an iterator of `u16` over the string encoded as UTF-16.
-    #[unstable(feature = "str_utf16",
-               reason = "this functionality may only be provided by libunicode",
-               issue = "27714")]
-    #[rustc_deprecated(since = "1.8.0", reason = "renamed to encode_utf16")]
-    #[allow(deprecated)]
-    pub fn utf16_units(&self) -> Utf16Units {
-        Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
-    }
-
     /// Returns an iterator of `u16` over the string encoded as UTF-16.
     #[stable(feature = "encode_utf16", since = "1.8.0")]
     pub fn encode_utf16(&self) -> EncodeUtf16 {
index e19090c7599ecd3d6e6b4fc35fd26c365469403e..49fce68d15e542138a720a59b05d19c880951dd7 100644 (file)
@@ -13,6 +13,9 @@
 use std::collections::btree_map::Entry::{Occupied, Vacant};
 use std::rc::Rc;
 
+use std::iter::FromIterator;
+use super::DeterministicRng;
+
 #[test]
 fn test_basic_large() {
     let mut map = BTreeMap::new();
@@ -528,6 +531,51 @@ fn $name() {
 create_append_test!(test_append_239, 239);
 create_append_test!(test_append_1700, 1700);
 
+fn rand_data(len: usize) -> Vec<(u32, u32)> {
+    let mut rng = DeterministicRng::new();
+    Vec::from_iter(
+        (0..len).map(|_| (rng.next(), rng.next()))
+    )
+}
+
+#[test]
+fn test_split_off_empty_right() {
+    let mut data = rand_data(173);
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
+
+    data.sort();
+    assert!(map.into_iter().eq(data));
+    assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+    let mut data = rand_data(314);
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let right = map.split_off(&data.iter().min().unwrap().0);
+
+    data.sort();
+    assert!(map.into_iter().eq(None));
+    assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+    let mut data = rand_data(1529);
+    // special case with maximum height.
+    data.sort();
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let key = data[data.len() / 2].0;
+    let right = map.split_off(&key);
+
+    assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
+    assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
+}
+
 mod bench {
     use std::collections::BTreeMap;
     use std::__rand::{Rng, thread_rng};
index 0db48f3ce9edb4bac58c1b4f2596a48f5eca20da..ea43f423b7c1f0bf7e60570c110cd317444202fe 100644 (file)
 
 mod map;
 mod set;
+
+/// XorShiftRng
+struct DeterministicRng {
+    x: u32,
+    y: u32,
+    z: u32,
+    w: u32,
+}
+
+impl DeterministicRng {
+    fn new() -> Self {
+        DeterministicRng {
+            x: 0x193a6754,
+            y: 0xa8a7d469,
+            z: 0x97830e05,
+            w: 0x113ba7bb
+        }
+    }
+
+    fn next(&mut self) -> u32 {
+        let x = self.x;
+        let t = x ^ (x << 11);
+        self.x = self.y;
+        self.y = self.z;
+        self.z = self.w;
+        let w_ = self.w;
+        self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
+        self.w
+    }
+}
index 53ccfd5b4e26dc0c4dbd3325457b46828cf03616..f7b647d7772db4a57d91ec37d1cfc300703f23e6 100644 (file)
@@ -10,6 +10,9 @@
 
 use std::collections::BTreeSet;
 
+use std::iter::FromIterator;
+use super::DeterministicRng;
+
 #[test]
 fn test_clone_eq() {
   let mut m = BTreeSet::new();
@@ -289,3 +292,48 @@ fn test_append() {
     assert_eq!(a.contains(&4), true);
     assert_eq!(a.contains(&5), true);
 }
+
+fn rand_data(len: usize) -> Vec<u32> {
+    let mut rng = DeterministicRng::new();
+    Vec::from_iter(
+        (0..len).map(|_| rng.next())
+    )
+}
+
+#[test]
+fn test_split_off_empty_right() {
+    let mut data = rand_data(173);
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let right = set.split_off(&(data.iter().max().unwrap() + 1));
+
+    data.sort();
+    assert!(set.into_iter().eq(data));
+    assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+    let mut data = rand_data(314);
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let right = set.split_off(data.iter().min().unwrap());
+
+    data.sort();
+    assert!(set.into_iter().eq(None));
+    assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+    let mut data = rand_data(1529);
+    // special case with maximum height.
+    data.sort();
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let key = data[data.len() / 2];
+    let right = set.split_off(&key);
+
+    assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
+    assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
+}
index bae21f1bd9b8fe41454d2bee5ce5758ede1a0ecc..400d614094862a83445d8d251a56047d069bc950 100644 (file)
@@ -14,6 +14,7 @@
 #![feature(binary_heap_append)]
 #![feature(box_syntax)]
 #![feature(btree_append)]
+#![feature(btree_split_off)]
 #![feature(btree_range)]
 #![feature(collections)]
 #![feature(collections_bound)]
@@ -25,7 +26,6 @@
 #![feature(pattern)]
 #![feature(rand)]
 #![feature(step_by)]
-#![feature(str_char)]
 #![feature(str_escape)]
 #![feature(test)]
 #![feature(unboxed_closures)]
index a1820a1cb96e3901b973454ce802f4a23494c909..124b85bfca872bbfb15f26ca9897dee61ba72806 100644 (file)
@@ -479,20 +479,6 @@ fn test_is_whitespace() {
     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
 }
 
-#[test]
-#[allow(deprecated)]
-fn test_slice_shift_char() {
-    let data = "ประเทศไทย中";
-    assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_slice_shift_char_2() {
-    let empty = "";
-    assert_eq!(empty.slice_shift_char(), None);
-}
-
 #[test]
 fn test_is_utf8() {
     // deny overlong encodings
@@ -674,30 +660,6 @@ fn test_contains_char() {
     assert!(!"".contains('a'));
 }
 
-#[test]
-#[allow(deprecated)]
-fn test_char_at() {
-    let s = "ศไทย中华Việt Nam";
-    let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
-    let mut pos = 0;
-    for ch in &v {
-        assert!(s.char_at(pos) == *ch);
-        pos += ch.to_string().len();
-    }
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_char_at_reverse() {
-    let s = "ศไทย中华Việt Nam";
-    let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
-    let mut pos = s.len();
-    for ch in v.iter().rev() {
-        assert!(s.char_at_reverse(pos) == *ch);
-        pos -= ch.to_string().len();
-    }
-}
-
 #[test]
 fn test_split_at() {
     let s = "ศไทย中华Việt Nam";
@@ -764,26 +726,6 @@ fn test_total_ord() {
     assert_eq!("22".cmp("1234"), Greater);
 }
 
-#[test]
-#[allow(deprecated)]
-fn test_char_range_at() {
-    let data = "b¢€𤭢𤭢€¢b";
-    assert_eq!('b', data.char_range_at(0).ch);
-    assert_eq!('¢', data.char_range_at(1).ch);
-    assert_eq!('€', data.char_range_at(3).ch);
-    assert_eq!('𤭢', data.char_range_at(6).ch);
-    assert_eq!('𤭢', data.char_range_at(10).ch);
-    assert_eq!('€', data.char_range_at(14).ch);
-    assert_eq!('¢', data.char_range_at(17).ch);
-    assert_eq!('b', data.char_range_at(19).ch);
-}
-
-#[test]
-#[allow(deprecated)]
-fn test_char_range_at_reverse_underflow() {
-    assert_eq!("abc".char_range_at_reverse(0).next, 0);
-}
-
 #[test]
 fn test_iterator() {
     let s = "ศไทย中华Việt Nam";
index 97a85f6aa43d006cf77930df3169168e95b53bfa..2700f016751dcd83fe279530e0f3a10a5ae392fd 100644 (file)
@@ -694,40 +694,6 @@ pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
             borrow: orig.borrow,
         }
     }
-
-    /// Make a new `Ref` for an optional component of the borrowed data, e.g. an
-    /// enum variant.
-    ///
-    /// The `RefCell` is already immutably borrowed, so this cannot fail.
-    ///
-    /// This is an associated function that needs to be used as
-    /// `Ref::filter_map(...)`.  A method would interfere with methods of the
-    /// same name on the contents of a `RefCell` used through `Deref`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # #![feature(cell_extras)]
-    /// use std::cell::{RefCell, Ref};
-    ///
-    /// let c = RefCell::new(Ok(5));
-    /// let b1: Ref<Result<u32, ()>> = c.borrow();
-    /// let b2: Ref<u32> = Ref::filter_map(b1, |o| o.as_ref().ok()).unwrap();
-    /// assert_eq!(*b2, 5)
-    /// ```
-    #[unstable(feature = "cell_extras", reason = "recently added",
-               issue = "27746")]
-    #[rustc_deprecated(since = "1.8.0", reason = "can be built on `Ref::map`: \
-        https://crates.io/crates/ref_filter_map")]
-    #[inline]
-    pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>>
-        where F: FnOnce(&T) -> Option<&U>
-    {
-        f(orig.value).map(move |new| Ref {
-            value: new,
-            borrow: orig.borrow,
-        })
-    }
 }
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
@@ -767,47 +733,6 @@ pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
             borrow: orig.borrow,
         }
     }
-
-    /// Make a new `RefMut` for an optional component of the borrowed data, e.g.
-    /// an enum variant.
-    ///
-    /// The `RefCell` is already mutably borrowed, so this cannot fail.
-    ///
-    /// This is an associated function that needs to be used as
-    /// `RefMut::filter_map(...)`.  A method would interfere with methods of the
-    /// same name on the contents of a `RefCell` used through `Deref`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # #![feature(cell_extras)]
-    /// use std::cell::{RefCell, RefMut};
-    ///
-    /// let c = RefCell::new(Ok(5));
-    /// {
-    ///     let b1: RefMut<Result<u32, ()>> = c.borrow_mut();
-    ///     let mut b2: RefMut<u32> = RefMut::filter_map(b1, |o| {
-    ///         o.as_mut().ok()
-    ///     }).unwrap();
-    ///     assert_eq!(*b2, 5);
-    ///     *b2 = 42;
-    /// }
-    /// assert_eq!(*c.borrow(), Ok(42));
-    /// ```
-    #[unstable(feature = "cell_extras", reason = "recently added",
-               issue = "27746")]
-    #[rustc_deprecated(since = "1.8.0", reason = "can be built on `RefMut::map`: \
-        https://crates.io/crates/ref_filter_map")]
-    #[inline]
-    pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>>
-        where F: FnOnce(&mut T) -> Option<&mut U>
-    {
-        let RefMut { value, borrow } = orig;
-        f(value).map(move |new| RefMut {
-            value: new,
-            borrow: borrow,
-        })
-    }
 }
 
 struct BorrowRefMut<'b> {
index 19226d81f16882000966fcd514a046d1f16abe86..6b2122451db8fbf164190d84d485a09067229113 100644 (file)
 //!
 //! Their definition should always match the ABI defined in `rustc::back::abi`.
 
-use clone::Clone;
-use marker::Copy;
-use mem;
-
-/// The representation of a slice like `&[T]`.
-///
-/// This struct is guaranteed to have the layout of types like `&[T]`,
-/// `&str`, and `Box<[T]>`, but is not the type of such slices
-/// (e.g. the fields are not directly accessible on a `&[T]`) nor does
-/// it control that layout (changing the definition will not change
-/// the layout of a `&[T]`). It is only designed to be used by unsafe
-/// code that needs to manipulate the low-level details.
-///
-/// However, it is not recommended to use this type for such code,
-/// since there are alternatives which may be safer:
-///
-/// - Creating a slice from a data pointer and length can be done with
-///   `std::slice::from_raw_parts` or `std::slice::from_raw_parts_mut`
-///   instead of `std::mem::transmute`ing a value of type `Slice`.
-/// - Extracting the data pointer and length from a slice can be
-///   performed with the `as_ptr` (or `as_mut_ptr`) and `len`
-///   methods.
-///
-/// If one does decide to convert a slice value to a `Slice`, the
-/// `Repr` trait in this module provides a method for a safe
-/// conversion from `&[T]` (and `&str`) to a `Slice`, more type-safe
-/// than a call to `transmute`.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(raw)]
-///
-/// use std::raw::{self, Repr};
-///
-/// let slice: &[u16] = &[1, 2, 3, 4];
-///
-/// let repr: raw::Slice<u16> = slice.repr();
-/// println!("data pointer = {:?}, length = {}", repr.data, repr.len);
-/// ```
-#[repr(C)]
-#[allow(missing_debug_implementations)]
-#[rustc_deprecated(reason = "use raw accessors/constructors in `slice` module",
-                   since = "1.9.0")]
-#[unstable(feature = "raw", issue = "27751")]
-pub struct Slice<T> {
-    pub data: *const T,
-    pub len: usize,
-}
-
-#[allow(deprecated)]
-impl<T> Copy for Slice<T> {}
-#[allow(deprecated)]
-impl<T> Clone for Slice<T> {
-    fn clone(&self) -> Slice<T> { *self }
-}
-
 /// The representation of a trait object like `&SomeTrait`.
 ///
 /// This struct has the same layout as types like `&SomeTrait` and
@@ -154,22 +97,3 @@ pub struct TraitObject {
     pub data: *mut (),
     pub vtable: *mut (),
 }
-
-/// This trait is meant to map equivalences between raw structs and their
-/// corresponding rust values.
-#[rustc_deprecated(reason = "use raw accessors/constructors in `slice` module",
-                   since = "1.9.0")]
-#[unstable(feature = "raw", issue = "27751")]
-pub unsafe trait Repr<T> {
-    /// This function "unwraps" a rust value (without consuming it) into its raw
-    /// struct representation. This can be used to read/write different values
-    /// for the struct. This is a safe method because by default it does not
-    /// enable write-access to the fields of the return value in safe code.
-    #[inline]
-    fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } }
-}
-
-#[allow(deprecated)]
-unsafe impl<T> Repr<Slice<T>> for [T] {}
-#[allow(deprecated)]
-unsafe impl Repr<Slice<u8>> for str {}
index 32b81ab7f53a8ab19b69487bf98167ad0dd964a7..5fc15fae5199bd344a1920248201adb721fd92ad 100644 (file)
@@ -17,7 +17,7 @@
 use self::pattern::Pattern;
 use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
-use char::{self, CharExt};
+use char;
 use clone::Clone;
 use convert::AsRef;
 use default::Default;
@@ -1664,40 +1664,6 @@ fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
         where P::Searcher: ReverseSearcher<'a>;
     #[stable(feature = "is_char_boundary", since = "1.9.0")]
     fn is_char_boundary(&self, index: usize) -> bool;
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at() or eventually \
-                         removed altogether",
-               issue = "27754")]
-    #[rustc_deprecated(reason = "use slicing plus chars() plus len_utf8",
-                       since = "1.9.0")]
-    fn char_range_at(&self, start: usize) -> CharRange;
-    #[unstable(feature = "str_char",
-               reason = "often replaced by char_indices, this method may \
-                         be removed in favor of just char_at_reverse() or \
-                         eventually removed altogether",
-               issue = "27754")]
-    #[rustc_deprecated(reason = "use slicing plus chars().rev() plus len_utf8",
-                       since = "1.9.0")]
-    fn char_range_at_reverse(&self, start: usize) -> CharRange;
-    #[unstable(feature = "str_char",
-               reason = "frequently replaced by the chars() iterator, this \
-                         method may be removed or possibly renamed in the \
-                         future; it is normally replaced by chars/char_indices \
-                         iterators or by getting the first char from a \
-                         subslice",
-               issue = "27754")]
-    #[rustc_deprecated(reason = "use slicing plus chars()",
-                       since = "1.9.0")]
-    fn char_at(&self, i: usize) -> char;
-    #[unstable(feature = "str_char",
-               reason = "see char_at for more details, but reverse semantics \
-                         are also somewhat unclear, especially with which \
-                         cases generate panics",
-               issue = "27754")]
-    #[rustc_deprecated(reason = "use slicing plus chars().rev()",
-                       since = "1.9.0")]
-    fn char_at_reverse(&self, i: usize) -> char;
     #[stable(feature = "core", since = "1.6.0")]
     fn as_bytes(&self) -> &[u8];
     #[stable(feature = "core", since = "1.6.0")]
@@ -1710,14 +1676,6 @@ fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
     fn split_at(&self, mid: usize) -> (&str, &str);
     #[stable(feature = "core", since = "1.6.0")]
     fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str);
-    #[unstable(feature = "str_char",
-               reason = "awaiting conventions about shifting and slices and \
-                         may not be warranted with the existence of the chars \
-                         and/or char_indices iterators",
-               issue = "27754")]
-    #[rustc_deprecated(reason = "use chars() plus Chars::as_str",
-                       since = "1.9.0")]
-    fn slice_shift_char(&self) -> Option<(char, &str)>;
     #[stable(feature = "core", since = "1.6.0")]
     fn as_ptr(&self) -> *const u8;
     #[stable(feature = "core", since = "1.6.0")]
@@ -1946,55 +1904,6 @@ fn is_char_boundary(&self, index: usize) -> bool {
         }
     }
 
-    #[inline]
-    fn char_range_at(&self, i: usize) -> CharRange {
-        let (c, n) = char_range_at_raw(self.as_bytes(), i);
-        CharRange { ch: unsafe { char::from_u32_unchecked(c) }, next: n }
-    }
-
-    #[inline]
-    fn char_range_at_reverse(&self, start: usize) -> CharRange {
-        let mut prev = start;
-
-        prev = prev.saturating_sub(1);
-        if self.as_bytes()[prev] < 128 {
-            return CharRange{ch: self.as_bytes()[prev] as char, next: prev}
-        }
-
-        // Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
-        fn multibyte_char_range_at_reverse(s: &str, mut i: usize) -> CharRange {
-            // while there is a previous byte == 10......
-            while i > 0 && s.as_bytes()[i] & !CONT_MASK == TAG_CONT_U8 {
-                i -= 1;
-            }
-
-            let first= s.as_bytes()[i];
-            let w = UTF8_CHAR_WIDTH[first as usize];
-            assert!(w != 0);
-
-            let mut val = utf8_first_byte(first, w as u32);
-            val = utf8_acc_cont_byte(val, s.as_bytes()[i + 1]);
-            if w > 2 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 2]); }
-            if w > 3 { val = utf8_acc_cont_byte(val, s.as_bytes()[i + 3]); }
-
-            CharRange {ch: unsafe { char::from_u32_unchecked(val) }, next: i}
-        }
-
-        multibyte_char_range_at_reverse(self, prev)
-    }
-
-    #[inline]
-    #[allow(deprecated)]
-    fn char_at(&self, i: usize) -> char {
-        self.char_range_at(i).ch
-    }
-
-    #[inline]
-    #[allow(deprecated)]
-    fn char_at_reverse(&self, i: usize) -> char {
-        self.char_range_at_reverse(i).ch
-    }
-
     #[inline]
     fn as_bytes(&self) -> &[u8] {
         unsafe { mem::transmute(self) }
@@ -2041,18 +1950,6 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         }
     }
 
-    #[inline]
-    #[allow(deprecated)]
-    fn slice_shift_char(&self) -> Option<(char, &str)> {
-        if self.is_empty() {
-            None
-        } else {
-            let ch = self.char_at(0);
-            let next_s = unsafe { self.slice_unchecked(ch.len_utf8(), self.len()) };
-            Some((ch, next_s))
-        }
-    }
-
     #[inline]
     fn as_ptr(&self) -> *const u8 {
         self as *const str as *const u8
@@ -2078,31 +1975,6 @@ fn as_ref(&self) -> &[u8] {
     }
 }
 
-/// Pluck a code point out of a UTF-8-like byte slice and return the
-/// index of the next code point.
-#[inline]
-fn char_range_at_raw(bytes: &[u8], i: usize) -> (u32, usize) {
-    if bytes[i] < 128 {
-        return (bytes[i] as u32, i + 1);
-    }
-
-    // Multibyte case is a fn to allow char_range_at to inline cleanly
-    fn multibyte_char_range_at(bytes: &[u8], i: usize) -> (u32, usize) {
-        let first = bytes[i];
-        let w = UTF8_CHAR_WIDTH[first as usize];
-        assert!(w != 0);
-
-        let mut val = utf8_first_byte(first, w as u32);
-        val = utf8_acc_cont_byte(val, bytes[i + 1]);
-        if w > 2 { val = utf8_acc_cont_byte(val, bytes[i + 2]); }
-        if w > 3 { val = utf8_acc_cont_byte(val, bytes[i + 3]); }
-
-        (val, i + w as usize)
-    }
-
-    multibyte_char_range_at(bytes, i)
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Default for &'a str {
     fn default() -> &'a str { "" }
index c0b22274ee9d628f09c36b4b7081629844d102f5..a635620d12abd3618e3acda562b0c2ed49686153 100644 (file)
@@ -158,20 +158,6 @@ fn accessor(&self) -> Ref<u32> {
     assert_eq!(*d, 7);
 }
 
-#[test]
-#[allow(deprecated)]
-fn ref_filter_map_accessor() {
-    struct X(RefCell<Result<u32, ()>>);
-    impl X {
-        fn accessor(&self) -> Option<Ref<u32>> {
-            Ref::filter_map(self.0.borrow(), |r| r.as_ref().ok())
-        }
-    }
-    let x = X(RefCell::new(Ok(7)));
-    let d: Ref<u32> = x.accessor().unwrap();
-    assert_eq!(*d, 7);
-}
-
 #[test]
 fn ref_mut_map_accessor() {
     struct X(RefCell<(u32, char)>);
@@ -189,24 +175,6 @@ fn accessor(&self) -> RefMut<u32> {
     assert_eq!(*x.0.borrow(), (8, 'z'));
 }
 
-#[test]
-#[allow(deprecated)]
-fn ref_mut_filter_map_accessor() {
-    struct X(RefCell<Result<u32, ()>>);
-    impl X {
-        fn accessor(&self) -> Option<RefMut<u32>> {
-            RefMut::filter_map(self.0.borrow_mut(), |r| r.as_mut().ok())
-        }
-    }
-    let x = X(RefCell::new(Ok(7)));
-    {
-        let mut d: RefMut<u32> = x.accessor().unwrap();
-        assert_eq!(*d, 7);
-        *d += 1;
-    }
-    assert_eq!(*x.0.borrow(), Ok(8));
-}
-
 #[test]
 fn as_unsafe_cell() {
     let c1: Cell<usize> = Cell::new(0);
index b19b5465a1235be3323363cdc11838739b593029..45d85899e99d33e291b2bf3259881b46cc5365d7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b19b5465a1235be3323363cdc11838739b593029
+Subproject commit 45d85899e99d33e291b2bf3259881b46cc5365d7
index 8b1d7bed7c42d8fba4ee947cb640c090f31c12b5..f2abdf831a3b8fdbdae8c6033bbc17085e38b3cc 100644 (file)
@@ -384,18 +384,19 @@ struct X { x: (), }
 
 // This fails to compile because the match is irrefutable.
 while let Irrefutable(x) = irr {
-    ...
+    // ...
 }
+```
 
 Try this instead:
 
-```
+```no_run
 struct Irrefutable(i32);
 let irr = Irrefutable(0);
 
 loop {
     let Irrefutable(x) = irr;
-    ...
+    // ...
 }
 ```
 "##,
index e53584a3f8b11ee42b733572caaa30f1b1da8631..79656ea21f755bacbbf0debd5ba1d225962c56ad 100644 (file)
@@ -162,21 +162,53 @@ pub fn perform_test(&mut self,
             }
 
             TestKind::SwitchInt { switch_ty, ref options, indices: _ } => {
-                let otherwise = self.cfg.start_new_block();
-                let targets: Vec<_> =
-                    options.iter()
-                           .map(|_| self.cfg.start_new_block())
-                           .chain(Some(otherwise))
-                           .collect();
+                let (targets, term) = match switch_ty.sty {
+                    // If we're matching on boolean we can
+                    // use the If TerminatorKind instead
+                    ty::TyBool => {
+                        assert!(options.len() > 0 && options.len() <= 2);
+
+                        let (true_bb, else_bb) =
+                            (self.cfg.start_new_block(),
+                             self.cfg.start_new_block());
+
+                        let targets = match &options[0] {
+                            &ConstVal::Bool(true) => vec![true_bb, else_bb],
+                            &ConstVal::Bool(false) => vec![else_bb, true_bb],
+                            v => span_bug!(test.span, "expected boolean value but got {:?}", v)
+                        };
+
+                        (targets,
+                         TerminatorKind::If {
+                             cond: Operand::Consume(lvalue.clone()),
+                             targets: (true_bb, else_bb)
+                         })
+
+                    }
+                    _ => {
+                        // The switch may be inexhaustive so we
+                        // add a catch all block
+                        let otherwise = self.cfg.start_new_block();
+                        let targets: Vec<_> =
+                            options.iter()
+                                   .map(|_| self.cfg.start_new_block())
+                                   .chain(Some(otherwise))
+                                   .collect();
+
+                        (targets.clone(),
+                         TerminatorKind::SwitchInt {
+                             discr: lvalue.clone(),
+                             switch_ty: switch_ty,
+                             values: options.clone(),
+                             targets: targets
+                         })
+                    }
+                };
+
                 self.cfg.terminate(block,
                                    scope_id,
                                    test.span,
-                                   TerminatorKind::SwitchInt {
-                                       discr: lvalue.clone(),
-                                       switch_ty: switch_ty,
-                                       values: options.clone(),
-                                       targets: targets.clone(),
-                                   });
+                                   term);
                 targets
             }
 
index 36053d3c4ffa78da45e937b69d55541f6b335a2a..4941f867f0657e4d44f629a3d767d28f5641254b 100644 (file)
@@ -153,7 +153,8 @@ enum ResolutionError<'a> {
         message: &'a str,
         context: UnresolvedNameContext<'a>,
         is_static_method: bool,
-        is_field: bool
+        is_field: bool,
+        def: Def,
     },
     /// error E0426: use of undeclared label
     UndeclaredLabel(&'a str),
@@ -413,7 +414,7 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
                              argument is missing?")
         }
         ResolutionError::UnresolvedName { path, message: msg, context, is_static_method,
-                                          is_field } => {
+                                          is_field, def } => {
             let mut err = struct_span_err!(resolver.session,
                                            span,
                                            E0425,
@@ -430,19 +431,20 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
                 UnresolvedNameContext::PathIsMod(parent) => {
                     err.help(&match parent.map(|parent| &parent.node) {
                         Some(&ExprKind::Field(_, ident)) => {
-                            format!("To reference an item from the `{module}` module, \
+                            format!("to reference an item from the `{module}` module, \
                                      use `{module}::{ident}`",
                                     module = path,
                                     ident = ident.node)
                         }
                         Some(&ExprKind::MethodCall(ident, _, _)) => {
-                            format!("To call a function from the `{module}` module, \
+                            format!("to call a function from the `{module}` module, \
                                      use `{module}::{ident}(..)`",
                                     module = path,
                                     ident = ident.node)
                         }
                         _ => {
-                            format!("Module `{module}` cannot be used as an expression",
+                            format!("{def} `{module}` cannot be used as an expression",
+                                    def = def.kind_name(),
                                     module = path)
                         }
                     });
@@ -1113,7 +1115,8 @@ fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) ->
                         message: "",
                         context: UnresolvedNameContext::Other,
                         is_static_method: false,
-                        is_field: false
+                        is_field: false,
+                        def: Def::Err,
                     };
                 resolve_error(self, path.span, error);
                 Def::Err
@@ -3063,6 +3066,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                                 };
 
                                 let mut context =  UnresolvedNameContext::Other;
+                                let mut def = Def::Err;
                                 if !msg.is_empty() {
                                     msg = format!(". Did you mean {}?", msg);
                                 } else {
@@ -3075,7 +3079,10 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                                     match self.resolve_module_path(&name_path[..],
                                                                    UseLexicalScope,
                                                                    expr.span) {
-                                        Success(_) => {
+                                        Success(e) => {
+                                            if let Some(def_type) = e.def {
+                                                def = def_type;
+                                            }
                                             context = UnresolvedNameContext::PathIsMod(parent);
                                         },
                                         _ => {},
@@ -3090,6 +3097,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                                                   context: context,
                                                   is_static_method: method_scope && is_static,
                                                   is_field: is_field,
+                                                  def: def,
                                               });
                             }
                         }
index d06030637afd8cc3b23a318c057219f279d9a048..e9e52a0121a3695467d6518adc732571e313f486 100644 (file)
@@ -2040,6 +2040,7 @@ impl Foo for Bar {
     // the trait
     fn foo(&self) {}
 }
+```
 "##,
 
 E0186: r##"
index 734f774043d6dd4bdcc194424adb9b42049a1b46..0180c3118a586f41c813e65b5ddfa207e3b945f6 100644 (file)
@@ -32,6 +32,8 @@
 /// it was opened with. Files also implement `Seek` to alter the logical cursor
 /// that the file contains internally.
 ///
+/// Files are automatically closed when they go out of scope.
+///
 /// # Examples
 ///
 /// ```no_run
@@ -1341,8 +1343,9 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///     if dir.is_dir() {
 ///         for entry in try!(fs::read_dir(dir)) {
 ///             let entry = try!(entry);
-///             if try!(entry.file_type()).is_dir() {
-///                 try!(visit_dirs(&entry.path(), cb));
+///             let path = entry.path();
+///             if path.is_dir() {
+///                 try!(visit_dirs(&path, cb));
 ///             } else {
 ///                 cb(&entry);
 ///             }
index 016130e99989e3630c00c986495a731459349aed..d8cadf09cb2a4c3a3c8ae9ea78b6ab0059627b04 100644 (file)
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub use panicking::{take_hook, set_hook, PanicInfo, Location};
 
-///
-#[rustc_deprecated(since = "1.9.0", reason = "renamed to set_hook")]
-#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
-pub fn set_handler<F>(handler: F) where F: Fn(&PanicInfo) + 'static + Sync + Send {
-    set_hook(Box::new(handler))
-}
-
-///
-#[rustc_deprecated(since = "1.9.0", reason = "renamed to take_hook")]
-#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
-pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
-    take_hook()
-}
-
-/// A marker trait which represents "unwind safe" types in Rust.
+/// A marker trait which represents "panic safe" types in Rust.
 ///
 /// This trait is implemented by default for many types and behaves similarly in
 /// terms of inference of implementation to the `Send` and `Sync` traits. The
@@ -117,14 +103,6 @@ pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
                             across an unwind boundary"]
 pub trait UnwindSafe {}
 
-/// Deprecated, renamed to UnwindSafe
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-#[rustc_deprecated(reason = "renamed to `UnwindSafe`", since = "1.9.0")]
-pub trait RecoverSafe {}
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-#[allow(deprecated)]
-impl<T: UnwindSafe> RecoverSafe for T {}
-
 /// A marker trait representing types where a shared reference is considered
 /// unwind safe.
 ///
@@ -202,11 +180,6 @@ pub struct AssertUnwindSafe<T>(
     pub T
 );
 
-/// Deprecated, renamed to `AssertUnwindSafe`
-#[unstable(feature = "recover", issue = "27719")]
-#[rustc_deprecated(reason = "renamed to `AssertUnwindSafe`", since = "1.9.0")]
-pub struct AssertRecoverSafe<T>(pub T);
-
 // Implementations of the `UnwindSafe` trait:
 //
 // * By default everything is unwind safe
@@ -234,9 +207,6 @@ impl<T: ?Sized> UnwindSafe for Mutex<T> {}
 impl<T: ?Sized> UnwindSafe for RwLock<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> UnwindSafe for AssertUnwindSafe<T> {}
-#[unstable(feature = "recover", issue = "27719")]
-#[allow(deprecated)]
-impl<T> UnwindSafe for AssertRecoverSafe<T> {}
 
 // not covered via the Shared impl above b/c the inner contents use
 // Cell/AtomicUsize, but the usage here is unwind safe so we can lift the
@@ -256,9 +226,6 @@ impl RefUnwindSafe for .. {}
 impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> RefUnwindSafe for AssertUnwindSafe<T> {}
-#[unstable(feature = "recover", issue = "27719")]
-#[allow(deprecated)]
-impl<T> RefUnwindSafe for AssertRecoverSafe<T> {}
 
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> Deref for AssertUnwindSafe<T> {
@@ -285,53 +252,6 @@ extern "rust-call" fn call_once(self, _args: ()) -> R {
     }
 }
 
-#[allow(deprecated)]
-impl<T> AssertRecoverSafe<T> {
-    /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
-    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-    #[rustc_deprecated(reason = "the type's field is now public, construct it directly",
-                       since = "1.9.0")]
-    pub fn new(t: T) -> AssertRecoverSafe<T> {
-        AssertRecoverSafe(t)
-    }
-
-    /// Consumes the `AssertRecoverSafe`, returning the wrapped value.
-    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-    #[rustc_deprecated(reason = "the type's field is now public, access it directly",
-                       since = "1.9.0")]
-    pub fn into_inner(self) -> T {
-        self.0
-    }
-}
-
-#[unstable(feature = "recover", issue = "27719")]
-#[allow(deprecated)]
-impl<T> Deref for AssertRecoverSafe<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        &self.0
-    }
-}
-
-#[unstable(feature = "recover", issue = "27719")]
-#[allow(deprecated)]
-impl<T> DerefMut for AssertRecoverSafe<T> {
-    fn deref_mut(&mut self) -> &mut T {
-        &mut self.0
-    }
-}
-
-#[unstable(feature = "recover", issue = "27719")]
-#[allow(deprecated)]
-impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
-    type Output = R;
-
-    extern "rust-call" fn call_once(self, _args: ()) -> R {
-        (self.0)()
-    }
-}
-
 /// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
 ///
 /// This function will return `Ok` with the closure's result if the closure
@@ -388,13 +308,6 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
     }
 }
 
-/// Deprecated, renamed to `catch_unwind`
-#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
-#[rustc_deprecated(reason = "renamed to `catch_unwind`", since = "1.9.0")]
-pub fn recover<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
-    catch_unwind(f)
-}
-
 /// Triggers a panic without invoking the panic hook.
 ///
 /// This is designed to be used in conjunction with `catch_unwind` to, for
@@ -424,10 +337,3 @@ pub fn recover<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
     panicking::rust_panic(payload)
 }
-
-/// Deprecated, use resume_unwind instead
-#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
-#[rustc_deprecated(reason = "renamed to `resume_unwind`", since = "1.9.0")]
-pub fn propagate(payload: Box<Any + Send>) -> ! {
-    resume_unwind(payload)
-}
index e083605a2acd5bf1ed38d6b1d7b29023b38cd296..11af768c5b9b0a0abc8c186a4fae546b00040370 100644 (file)
@@ -28,7 +28,7 @@
 /// ```
 ///
 /// [`assert!`]: macro.assert!.html
-/// [`if` conditionals]: ../book/if.html
+/// [`if`]: ../book/if.html
 /// [`BitAnd`]: ops/trait.BitAnd.html
 /// [`BitOr`]: ops/trait.BitOr.html
 /// [`Not`]: ops/trait.Not.html
index 1b6f6c3e875c98f12267fd362054b326d32046b3..3ce9bcc79f24ad8dfdedceb315286d0deba49188 100644 (file)
@@ -195,7 +195,7 @@ fn from_inner(pipe: AnonPipe) -> ChildStderr {
 ///                      .arg("-c")
 ///                      .arg("echo hello")
 ///                      .output()
-///                      .expect("failed to execute proces");
+///                      .expect("failed to execute process");
 ///
 /// let hello = output.stdout;
 /// ```
index 15e69628c7a5d20df96a0aab5e24d3f79b4e6d79..c75a5c09146a495abe9e626efea78e605f9d8b12 100644 (file)
@@ -204,10 +204,14 @@ 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> {
-        Mutex {
+        let mut m = Mutex {
             inner: box StaticMutex::new(),
             data: UnsafeCell::new(t),
+        };
+        unsafe {
+            m.inner.lock.init();
         }
+        m
     }
 }
 
index e1e764bd255cbd7302cf26b2eb4368330042f060..03d3483902dcf87b899aefcbe1f2a66ea07d2a30 100644 (file)
@@ -468,42 +468,6 @@ unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
             }
         })
     }
-
-    /// Transform this guard to hold a sub-borrow of the original data.
-    ///
-    /// Applies the supplied closure to the data, returning a new lock
-    /// guard referencing the borrow returned by the closure.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// # #![feature(guard_map)]
-    /// # use std::sync::{RwLockReadGuard, RwLock};
-    /// let x = RwLock::new(vec![1, 2]);
-    ///
-    /// let y = RwLockReadGuard::map(x.read().unwrap(), |v| &v[0]);
-    /// assert_eq!(*y, 1);
-    /// ```
-    #[unstable(feature = "guard_map",
-               reason = "recently added, needs RFC for stabilization,
-                         questionable interaction with Condvar",
-               issue = "27746")]
-    #[rustc_deprecated(since = "1.8.0",
-                       reason = "unsound on Mutex because of Condvar and \
-                                 RwLock may also with to be used with Condvar \
-                                 one day")]
-    pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockReadGuard<'rwlock, U>
-        where F: FnOnce(&T) -> &U
-    {
-        let new = RwLockReadGuard {
-            __lock: this.__lock,
-            __data: cb(this.__data)
-        };
-
-        mem::forget(this);
-
-        new
-    }
 }
 
 #[allow(deprecated)]
@@ -518,57 +482,6 @@ unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
             }
         })
     }
-
-    /// Transform this guard to hold a sub-borrow of the original data.
-    ///
-    /// Applies the supplied closure to the data, returning a new lock
-    /// guard referencing the borrow returned by the closure.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// # #![feature(guard_map)]
-    /// # use std::sync::{RwLockWriteGuard, RwLock};
-    /// let x = RwLock::new(vec![1, 2]);
-    ///
-    /// {
-    ///     let mut y = RwLockWriteGuard::map(x.write().unwrap(), |v| &mut v[0]);
-    ///     assert_eq!(*y, 1);
-    ///
-    ///     *y = 10;
-    /// }
-    ///
-    /// assert_eq!(&**x.read().unwrap(), &[10, 2]);
-    /// ```
-    #[unstable(feature = "guard_map",
-               reason = "recently added, needs RFC for stabilization,
-                         questionable interaction with Condvar",
-               issue = "27746")]
-    #[rustc_deprecated(since = "1.8.0",
-                       reason = "unsound on Mutex because of Condvar and \
-                                 RwLock may also with to be used with Condvar \
-                                 one day")]
-    pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockWriteGuard<'rwlock, U>
-        where F: FnOnce(&mut T) -> &mut U
-    {
-        // Compute the new data while still owning the original lock
-        // in order to correctly poison if the callback panics.
-        let data = unsafe { ptr::read(&this.__data) };
-        let new_data = cb(data);
-
-        // We don't want to unlock the lock by running the destructor of the
-        // original lock, so just read the fields we need and forget it.
-        let (poison, lock) = unsafe {
-            (ptr::read(&this.__poison), ptr::read(&this.__lock))
-        };
-        mem::forget(this);
-
-        RwLockWriteGuard {
-            __lock: lock,
-            __data: new_data,
-            __poison: poison
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -619,7 +532,7 @@ mod tests {
     use rand::{self, Rng};
     use sync::mpsc::channel;
     use thread;
-    use sync::{Arc, RwLock, StaticRwLock, TryLockError, RwLockWriteGuard};
+    use sync::{Arc, RwLock, StaticRwLock, TryLockError};
     use sync::atomic::{AtomicUsize, Ordering};
 
     #[derive(Eq, PartialEq, Debug)]
@@ -867,20 +780,4 @@ fn test_get_mut_poison() {
             Ok(x) => panic!("get_mut of poisoned RwLock is Ok: {:?}", x),
         }
     }
-
-    #[test]
-    fn test_rwlock_write_map_poison() {
-        let rwlock = Arc::new(RwLock::new(vec![1, 2]));
-        let rwlock2 = rwlock.clone();
-
-        thread::spawn(move || {
-            let _ = RwLockWriteGuard::map::<usize, _>(rwlock2.write().unwrap(), |_| panic!());
-        }).join().unwrap_err();
-
-        match rwlock.read() {
-            Ok(r) => panic!("Read lock on poisioned RwLock is Ok: {:?}", &*r),
-            Err(_) => {}
-        };
-    }
 }
-
index 5a6dfe7fb1a1507739b6b47447490ec60d426b92..7a2183c522f5b92154b198e55aea3cdc4455a5f4 100644 (file)
@@ -27,6 +27,12 @@ impl Mutex {
     /// first used with any of the functions below.
     pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) }
 
+    /// Prepare the mutex for use.
+    ///
+    /// This should be called once the mutex is at a stable memory address.
+    #[inline]
+    pub unsafe fn init(&mut self) { self.0.init() }
+
     /// Locks the mutex blocking the current thread until it is available.
     ///
     /// Behavior is undefined if the mutex has been moved between this and any
index 1df511a8818c414849262f14df1926e7e1818741..b5d0357633875829c1164e6f8e1685456c77d0f3 100644 (file)
@@ -42,20 +42,28 @@ pub fn dumb_print(args: fmt::Arguments) {
 // implemented as an illegal instruction.
 #[cfg(unix)]
 unsafe fn abort_internal() -> ! {
-    use libc;
-    libc::abort()
+    ::libc::abort()
 }
 
-// On Windows, we want to avoid using libc, and there isn't a direct
-// equivalent of libc::abort.  The __failfast intrinsic may be a reasonable
-// substitute, but desireability of using it over the abort instrinsic is
-// debateable; see https://github.com/rust-lang/rust/pull/31519 for details.
-#[cfg(not(unix))]
+// On Windows, use the processor-specific __fastfail mechanism.  In Windows 8
+// and later, this will terminate the process immediately without running any
+// in-process exception handlers.  In earlier versions of Windows, this
+// sequence of instructions will be treated as an access violation,
+// terminating the process but without necessarily bypassing all exception
+// handlers.
+//
+// https://msdn.microsoft.com/en-us/library/dn774154.aspx
+#[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))]
 unsafe fn abort_internal() -> ! {
-    use intrinsics;
-    intrinsics::abort()
+    asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+    ::intrinsics::unreachable();
 }
 
+// Other platforms should use the appropriate platform-specific mechanism for
+// aborting the process.  If no platform-specific mechanism is available,
+// ::intrinsics::abort() may be used instead.  The above implementations cover
+// all targets currently supported by libstd.
+
 pub fn abort(args: fmt::Arguments) -> ! {
     dumb_print(format_args!("fatal runtime error: {}\n", args));
     unsafe { abort_internal(); }
index b0fed2f4694bfcd4163fc53509e1ab9e0de9d225..430ec5f94a6f85da5a0444ddfa0e73b4f52d9f33 100644 (file)
@@ -34,21 +34,6 @@ pub trait CommandExt {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn gid(&mut self, id: u32) -> &mut process::Command;
 
-    /// Create a new session (cf. `setsid(2)`) for the child process. This means
-    /// that the child is the leader of a new process group. The parent process
-    /// remains the child reaper of the new process.
-    ///
-    /// This is not enough to create a daemon process. The *init* process should
-    /// be the child reaper of a daemon. This can be achieved if the parent
-    /// process exit. Moreover, a daemon should not have a controlling terminal.
-    /// To achieve this, a session leader (the child) must spawn another process
-    /// (the daemon) in the same session.
-    #[unstable(feature = "process_session_leader", reason = "recently added",
-               issue = "27811")]
-    #[rustc_deprecated(reason = "use `before_exec` instead",
-                       since = "1.9.0")]
-    fn session_leader(&mut self, on: bool) -> &mut process::Command;
-
     /// Schedules a closure to be run just before the `exec` function is
     /// invoked.
     ///
@@ -112,11 +97,6 @@ fn gid(&mut self, id: u32) -> &mut process::Command {
         self
     }
 
-    fn session_leader(&mut self, on: bool) -> &mut process::Command {
-        self.as_inner_mut().session_leader(on);
-        self
-    }
-
     fn before_exec<F>(&mut self, f: F) -> &mut process::Command
         where F: FnMut() -> io::Result<()> + Send + Sync + 'static
     {
index 4e4abcfbeee4ddb9256451e8f6bdb54e9a0f3d4f..52cf3f97c5c83ba49e12fb37a746710d87840160 100644 (file)
@@ -30,6 +30,39 @@ pub const fn new() -> Mutex {
         Mutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
     }
     #[inline]
+    pub unsafe fn init(&mut self) {
+        // Issue #33770
+        //
+        // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have
+        // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you
+        // try to re-lock it from the same thread when you already hold a lock.
+        //
+        // In practice, glibc takes advantage of this undefined behavior to
+        // implement hardware lock elision, which uses hardware transactional
+        // memory to avoid acquiring the lock. While a transaction is in
+        // progress, the lock appears to be unlocked. This isn't a problem for
+        // other threads since the transactional memory will abort if a conflict
+        // is detected, however no abort is generated if re-locking from the
+        // same thread.
+        //
+        // Since locking the same mutex twice will result in two aliasing &mut
+        // references, we instead create the mutex with type
+        // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
+        // re-lock it from the same thread, thus avoiding undefined behavior.
+        //
+        // We can't do anything for StaticMutex, but that type is deprecated
+        // anyways.
+        let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
+        let r = libc::pthread_mutexattr_init(&mut attr);
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutexattr_settype(&mut attr, libc::PTHREAD_MUTEX_NORMAL);
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutex_init(self.inner.get(), &attr);
+        debug_assert_eq!(r, 0);
+        let r = libc::pthread_mutexattr_destroy(&mut attr);
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
     pub unsafe fn lock(&self) {
         let r = libc::pthread_mutex_lock(self.inner.get());
         debug_assert_eq!(r, 0);
index d57191675426455a6856527dad9aab8e5e9e4dce..98cfdcdf11041510049283485fac0d5a8a22b337 100644 (file)
@@ -55,7 +55,6 @@ pub struct Command {
     cwd: Option<CString>,
     uid: Option<uid_t>,
     gid: Option<gid_t>,
-    session_leader: bool,
     saw_nul: bool,
     closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
     stdin: Option<Stdio>,
@@ -105,7 +104,6 @@ pub fn new(program: &OsStr) -> Command {
             cwd: None,
             uid: None,
             gid: None,
-            session_leader: false,
             saw_nul: saw_nul,
             closures: Vec::new(),
             stdin: None,
@@ -197,9 +195,6 @@ pub fn uid(&mut self, id: uid_t) {
     pub fn gid(&mut self, id: gid_t) {
         self.gid = Some(id);
     }
-    pub fn session_leader(&mut self, session_leader: bool) {
-        self.session_leader = session_leader;
-    }
 
     pub fn before_exec(&mut self,
                        f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
@@ -367,12 +362,6 @@ macro_rules! t {
 
             t!(cvt(libc::setuid(u as uid_t)));
         }
-        if self.session_leader {
-            // Don't check the error of setsid because it fails if we're the
-            // process leader already. We just forked so it shouldn't return
-            // error, but ignore it anyway.
-            let _ = libc::setsid();
-        }
         if let Some(ref cwd) = self.cwd {
             t!(cvt(libc::chdir(cwd.as_ptr())));
         }
index 44bd5d895f2e4373af64e753349c799b193be556..fbd4e1d120817ebc21a0b5e4e08d2f8593ff02d2 100644 (file)
 
 use libc;
 use cell::UnsafeCell;
+use sync::atomic::{AtomicUsize, Ordering};
 
-pub struct RWLock { inner: UnsafeCell<libc::pthread_rwlock_t> }
+pub struct RWLock {
+    inner: UnsafeCell<libc::pthread_rwlock_t>,
+    write_locked: UnsafeCell<bool>,
+    num_readers: AtomicUsize,
+}
 
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
 impl RWLock {
     pub const fn new() -> RWLock {
-        RWLock { inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER) }
+        RWLock {
+            inner: UnsafeCell::new(libc::PTHREAD_RWLOCK_INITIALIZER),
+            write_locked: UnsafeCell::new(false),
+            num_readers: AtomicUsize::new(0),
+        }
     }
     #[inline]
     pub unsafe fn read(&self) {
@@ -35,37 +44,86 @@ pub unsafe fn read(&self) {
         //
         // We roughly maintain the deadlocking behavior by panicking to ensure
         // that this lock acquisition does not succeed.
-        if r == libc::EDEADLK {
+        //
+        // We also check whether there this lock is already write locked. This
+        // is only possible if it was write locked by the current thread and
+        // the implementation allows recursive locking. The POSIX standard
+        // doesn't require recursivly locking a rwlock to deadlock, but we can't
+        // allow that because it could lead to aliasing issues.
+        if r == libc::EDEADLK || *self.write_locked.get() {
+            if r == 0 {
+                self.raw_unlock();
+            }
             panic!("rwlock read lock would result in deadlock");
         } else {
             debug_assert_eq!(r, 0);
+            self.num_readers.fetch_add(1, Ordering::Relaxed);
         }
     }
     #[inline]
     pub unsafe fn try_read(&self) -> bool {
-        libc::pthread_rwlock_tryrdlock(self.inner.get()) == 0
+        let r = libc::pthread_rwlock_tryrdlock(self.inner.get());
+        if r == 0 {
+            if *self.write_locked.get() {
+                self.raw_unlock();
+                false
+            } else {
+                self.num_readers.fetch_add(1, Ordering::Relaxed);
+                true
+            }
+        } else {
+            false
+        }
     }
     #[inline]
     pub unsafe fn write(&self) {
         let r = libc::pthread_rwlock_wrlock(self.inner.get());
-        // see comments above for why we check for EDEADLK
-        if r == libc::EDEADLK {
+        // See comments above for why we check for EDEADLK and write_locked. We
+        // also need to check that num_readers is 0.
+        if r == libc::EDEADLK || *self.write_locked.get() ||
+           self.num_readers.load(Ordering::Relaxed) != 0 {
+            if r == 0 {
+                self.raw_unlock();
+            }
             panic!("rwlock write lock would result in deadlock");
         } else {
             debug_assert_eq!(r, 0);
         }
+        *self.write_locked.get() = true;
     }
     #[inline]
     pub unsafe fn try_write(&self) -> bool {
-        libc::pthread_rwlock_trywrlock(self.inner.get()) == 0
+        let r = libc::pthread_rwlock_trywrlock(self.inner.get());
+        if r == 0 {
+            if *self.write_locked.get() || self.num_readers.load(Ordering::Relaxed) != 0 {
+                self.raw_unlock();
+                false
+            } else {
+                *self.write_locked.get() = true;
+                true
+            }
+        } else {
+            false
+        }
     }
     #[inline]
-    pub unsafe fn read_unlock(&self) {
+    unsafe fn raw_unlock(&self) {
         let r = libc::pthread_rwlock_unlock(self.inner.get());
         debug_assert_eq!(r, 0);
     }
     #[inline]
-    pub unsafe fn write_unlock(&self) { self.read_unlock() }
+    pub unsafe fn read_unlock(&self) {
+        debug_assert!(!*self.write_locked.get());
+        self.num_readers.fetch_sub(1, Ordering::Relaxed);
+        self.raw_unlock();
+    }
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        debug_assert_eq!(self.num_readers.load(Ordering::Relaxed), 0);
+        debug_assert!(*self.write_locked.get());
+        *self.write_locked.get() = false;
+        self.raw_unlock();
+    }
     #[inline]
     pub unsafe fn destroy(&self) {
         let r = libc::pthread_rwlock_destroy(self.inner.get());
index b770156582d3bd6ff87ba053d1fd7af9833bc235..8762b34e3da484df7fbf49854f4ac57f754a8a1d 100644 (file)
@@ -64,6 +64,8 @@ pub const fn new() -> Mutex {
             held: UnsafeCell::new(false),
         }
     }
+    #[inline]
+    pub unsafe fn init(&mut self) {}
     pub unsafe fn lock(&self) {
         match kind() {
             Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
index dc26370590cf825297e0e9d5901e79d1191ed144..c8783a60c4117d23ee12211de55de900f111ec1e 100644 (file)
 ////////////////////////////////////////////////////////////////////////////////
 
 #[macro_use] mod local;
-#[macro_use] mod scoped_tls;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::local::{LocalKey, LocalKeyState};
 
-#[unstable(feature = "scoped_tls",
-           reason = "scoped TLS has yet to have wide enough use to fully \
-                     consider stabilizing its interface",
-           issue = "27715")]
-#[allow(deprecated)]
-pub use self::scoped_tls::ScopedKey;
-
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[cfg(target_thread_local)]
 #[doc(hidden)] pub use self::local::elf::Key as __ElfLocalKeyInner;
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
-#[unstable(feature = "libstd_thread_internals", issue = "0")]
-#[doc(hidden)] pub use self::scoped_tls::__KeyInner as __ScopedKeyInner;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs
deleted file mode 100644 (file)
index dea58d0..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2014-2015 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.
-
-//! Scoped thread-local storage
-//!
-//! This module provides the ability to generate *scoped* thread-local
-//! variables. In this sense, scoped indicates that thread local storage
-//! actually stores a reference to a value, and this reference is only placed
-//! in storage for a scoped amount of time.
-//!
-//! There are no restrictions on what types can be placed into a scoped
-//! variable, but all scoped variables are initialized to the equivalent of
-//! null. Scoped thread local storage is useful when a value is present for a known
-//! period of time and it is not required to relinquish ownership of the
-//! contents.
-//!
-//! # Examples
-//!
-//! ```
-//! #![feature(scoped_tls)]
-//!
-//! scoped_thread_local!(static FOO: u32);
-//!
-//! // Initially each scoped slot is empty.
-//! assert!(!FOO.is_set());
-//!
-//! // When inserting a value, the value is only in place for the duration
-//! // of the closure specified.
-//! FOO.set(&1, || {
-//!     FOO.with(|slot| {
-//!         assert_eq!(*slot, 1);
-//!     });
-//! });
-//! ```
-
-#![unstable(feature = "thread_local_internals", issue = "0")]
-#![allow(deprecated)]
-
-#[doc(hidden)]
-pub use self::imp::KeyInner as __KeyInner;
-
-/// Type representing a thread local storage key corresponding to a reference
-/// to the type parameter `T`.
-///
-/// Keys are statically allocated and can contain a reference to an instance of
-/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
-/// and `with`, both of which currently use closures to control the scope of
-/// their contents.
-#[unstable(feature = "scoped_tls",
-           reason = "scoped TLS has yet to have wide enough use to fully consider \
-                     stabilizing its interface",
-           issue = "27715")]
-#[rustc_deprecated(since = "1.8.0",
-                   reason = "hasn't proven itself over LocalKey")]
-pub struct ScopedKey<T:'static> { inner: fn() -> &'static imp::KeyInner<T> }
-
-/// Declare a new scoped thread local storage key.
-///
-/// This macro declares a `static` item on which methods are used to get and
-/// set the value stored within.
-///
-/// See [ScopedKey documentation](thread/struct.ScopedKey.html) for more
-/// information.
-#[unstable(feature = "thread_local_internals",
-           reason = "should not be necessary",
-           issue = "0")]
-#[rustc_deprecated(since = "1.8.0",
-                   reason = "hasn't proven itself over LocalKey")]
-#[macro_export]
-#[allow_internal_unstable]
-macro_rules! scoped_thread_local {
-    (static $name:ident: $t:ty) => (
-        static $name: $crate::thread::ScopedKey<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-    (pub static $name:ident: $t:ty) => (
-        pub static $name: $crate::thread::ScopedKey<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-}
-
-#[doc(hidden)]
-#[unstable(feature = "thread_local_internals",
-           reason = "should not be necessary",
-           issue = "0")]
-#[rustc_deprecated(since = "1.8.0",
-                   reason = "hasn't proven itself over LocalKey")]
-#[macro_export]
-#[allow_internal_unstable]
-macro_rules! __scoped_thread_local_inner {
-    ($t:ty) => {{
-        #[cfg_attr(target_thread_local, thread_local)]
-        static _KEY: $crate::thread::__ScopedKeyInner<$t> =
-            $crate::thread::__ScopedKeyInner::new();
-        fn _getit() -> &'static $crate::thread::__ScopedKeyInner<$t> { &_KEY }
-        $crate::thread::ScopedKey::new(_getit)
-    }}
-}
-
-#[unstable(feature = "scoped_tls",
-           reason = "scoped TLS has yet to have wide enough use to fully consider \
-                     stabilizing its interface",
-           issue = "27715")]
-#[rustc_deprecated(since = "1.8.0",
-                   reason = "hasn't proven itself over LocalKey")]
-impl<T> ScopedKey<T> {
-    #[doc(hidden)]
-    pub const fn new(inner: fn() -> &'static imp::KeyInner<T>) -> ScopedKey<T> {
-        ScopedKey { inner: inner }
-    }
-
-    /// Inserts a value into this scoped thread local storage slot for a
-    /// duration of a closure.
-    ///
-    /// While `cb` is running, the value `t` will be returned by `get` unless
-    /// this function is called recursively inside of `cb`.
-    ///
-    /// Upon return, this function will restore the previous value, if any
-    /// was available.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(scoped_tls)]
-    ///
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// FOO.set(&100, || {
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    ///
-    ///     // set can be called recursively
-    ///     FOO.set(&101, || {
-    ///         // ...
-    ///     });
-    ///
-    ///     // Recursive calls restore the previous value.
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    /// });
-    /// ```
-    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
-        F: FnOnce() -> R,
-    {
-        struct Reset<'a, T: 'a> {
-            key: &'a imp::KeyInner<T>,
-            val: *mut T,
-        }
-                impl<'a, T> Drop for Reset<'a, T> {
-            fn drop(&mut self) {
-                unsafe { self.key.set(self.val) }
-            }
-        }
-
-        let inner = (self.inner)();
-        let prev = unsafe {
-            let prev = inner.get();
-            inner.set(t as *const T as *mut T);
-            prev
-        };
-
-        let _reset = Reset { key: inner, val: prev };
-        cb()
-    }
-
-    /// Gets a value out of this scoped variable.
-    ///
-    /// This function takes a closure which receives the value of this
-    /// variable.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `set` has not previously been called.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(scoped_tls)]
-    ///
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// FOO.with(|slot| {
-    ///     // work with `slot`
-    /// });
-    /// ```
-    pub fn with<R, F>(&'static self, cb: F) -> R where
-        F: FnOnce(&T) -> R
-    {
-        unsafe {
-            let ptr = (self.inner)().get();
-            assert!(!ptr.is_null(), "cannot access a scoped thread local \
-                                     variable without calling `set` first");
-            cb(&*ptr)
-        }
-    }
-
-    /// Test whether this TLS key has been `set` for the current thread.
-    pub fn is_set(&'static self) -> bool {
-        unsafe { !(self.inner)().get().is_null() }
-    }
-}
-
-#[cfg(target_thread_local)]
-#[doc(hidden)]
-mod imp {
-    use cell::Cell;
-    use ptr;
-
-    pub struct KeyInner<T> { inner: Cell<*mut T> }
-
-    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
-
-    impl<T> KeyInner<T> {
-        pub const fn new() -> KeyInner<T> {
-            KeyInner { inner: Cell::new(ptr::null_mut()) }
-        }
-        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr); }
-        pub unsafe fn get(&self) -> *mut T { self.inner.get() }
-    }
-}
-
-#[cfg(not(target_thread_local))]
-#[doc(hidden)]
-mod imp {
-    use cell::Cell;
-    use marker;
-    use sys_common::thread_local::StaticKey as OsStaticKey;
-
-    pub struct KeyInner<T> {
-        pub inner: OsStaticKey,
-        pub marker: marker::PhantomData<Cell<T>>,
-    }
-
-    unsafe impl<T> marker::Sync for KeyInner<T> { }
-
-    impl<T> KeyInner<T> {
-        pub const fn new() -> KeyInner<T> {
-            KeyInner {
-                inner: OsStaticKey::new(None),
-                marker: marker::PhantomData
-            }
-        }
-        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
-        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use cell::Cell;
-
-    scoped_thread_local!(static FOO: u32);
-
-    #[test]
-    fn smoke() {
-        scoped_thread_local!(static BAR: u32);
-
-        assert!(!BAR.is_set());
-        BAR.set(&1, || {
-            assert!(BAR.is_set());
-            BAR.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!BAR.is_set());
-    }
-
-    #[test]
-    fn cell_allowed() {
-        scoped_thread_local!(static BAR: Cell<u32>);
-
-        BAR.set(&Cell::new(1), || {
-            BAR.with(|slot| {
-                assert_eq!(slot.get(), 1);
-            });
-        });
-    }
-
-    #[test]
-    fn scope_item_allowed() {
-        assert!(!FOO.is_set());
-        FOO.set(&1, || {
-            assert!(FOO.is_set());
-            FOO.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!FOO.is_set());
-    }
-}
index 80963a9b735a5e32294d0753d953d8247f27d0e8..0e1508a1c4c28d130baf1813096a7c5ac2960cc8 100644 (file)
@@ -143,13 +143,6 @@ pub fn duration_since(&self, earlier: Instant) -> Duration {
         self.0.sub_instant(&earlier.0)
     }
 
-    /// Deprecated, renamed to `duration_since`
-    #[unstable(feature = "time2_old", issue = "29866")]
-    #[rustc_deprecated(since = "1.8.0", reason = "renamed to duration_since")]
-    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
-        self.0.sub_instant(&earlier.0)
-    }
-
     /// Returns the amount of time elapsed since this instant was created.
     ///
     /// # Panics
@@ -235,14 +228,6 @@ pub fn duration_since(&self, earlier: SystemTime)
         self.0.sub_time(&earlier.0).map_err(SystemTimeError)
     }
 
-    /// Deprecated, renamed to `duration_since`
-    #[unstable(feature = "time2_old", issue = "29866")]
-    #[rustc_deprecated(since = "1.8.0", reason = "renamed to duration_since")]
-    pub fn duration_from_earlier(&self, earlier: SystemTime)
-                                 -> Result<Duration, SystemTimeError> {
-        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
-    }
-
     /// Returns the amount of time elapsed since this system time was created.
     ///
     /// This function may fail as the underlying system clock is susceptible to
index 4638c60dedfa581fd5fa7c6420d8f32274c9ca0b..a3736a0a1907cbc8bf619708738815a5fd789c80 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4638c60dedfa581fd5fa7c6420d8f32274c9ca0b
+Subproject commit a3736a0a1907cbc8bf619708738815a5fd789c80
diff --git a/src/test/compile-fail/E0162.rs b/src/test/compile-fail/E0162.rs
new file mode 100644 (file)
index 0000000..e13b0af
--- /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.
+
+struct Irrefutable(i32);
+
+fn main() {
+    let irr = Irrefutable(0);
+    if let Irrefutable(x) = irr { //~ ERROR E0162
+        println!("{}", x);
+    }
+}
diff --git a/src/test/compile-fail/E0163.rs b/src/test/compile-fail/E0163.rs
new file mode 100644 (file)
index 0000000..5cb6f4d
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo { B(u32) }
+
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B { i } => i, //~ ERROR E0163
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0164.rs b/src/test/compile-fail/E0164.rs
new file mode 100644 (file)
index 0000000..491b2e9
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo { B { i: u32 } }
+
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B(i) => i, //~ ERROR E0164
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0165.rs b/src/test/compile-fail/E0165.rs
new file mode 100644 (file)
index 0000000..cca714b
--- /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.
+
+struct Irrefutable(i32);
+
+fn main() {
+    let irr = Irrefutable(0);
+    while let Irrefutable(x) = irr { //~ ERROR E0165
+        // ...
+    }
+}
diff --git a/src/test/compile-fail/E0166.rs b/src/test/compile-fail/E0166.rs
new file mode 100644 (file)
index 0000000..9fa4124
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> ! { return; } //~ ERROR E0166
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0172.rs b/src/test/compile-fail/E0172.rs
new file mode 100644 (file)
index 0000000..7011bf0
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(bar: i32+std::fmt::Display) {} //~ ERROR E0172
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0178.rs b/src/test/compile-fail/E0178.rs
new file mode 100644 (file)
index 0000000..f34f383
--- /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.
+
+trait Foo {}
+
+struct Bar<'a> {
+    w: &'a Foo + Copy, //~ ERROR E0178
+    x: &'a Foo + 'a, //~ ERROR E0178
+    y: &'a mut Foo + 'a, //~ ERROR E0178
+    z: fn() -> Foo + 'a, //~ ERROR E0178
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0184.rs b/src/test/compile-fail/E0184.rs
new file mode 100644 (file)
index 0000000..5d72d00
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Copy)] //~ ERROR E0184
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0185.rs b/src/test/compile-fail/E0185.rs
new file mode 100644 (file)
index 0000000..0e33687
--- /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.
+
+trait Foo {
+    fn foo();
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo(&self) {} //~ ERROR E0185
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0186.rs b/src/test/compile-fail/E0186.rs
new file mode 100644 (file)
index 0000000..aa0a38b
--- /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.
+
+trait Foo {
+    fn foo(&self);
+}
+
+struct Bar;
+
+impl Foo for Bar {
+    fn foo() {} //~ ERROR E0186
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0191.rs b/src/test/compile-fail/E0191.rs
new file mode 100644 (file)
index 0000000..489ebb0
--- /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.
+
+trait Trait {
+    type Bar;
+}
+
+type Foo = Trait; //~ ERROR E0191
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0192.rs b/src/test/compile-fail/E0192.rs
new file mode 100644 (file)
index 0000000..92f5876
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+trait Trait {
+    type Bar;
+}
+
+struct Foo;
+
+impl !Trait for Foo { } //~ ERROR E0192
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0194.rs b/src/test/compile-fail/E0194.rs
new file mode 100644 (file)
index 0000000..96b3062
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo<T> {
+    fn do_something(&self) -> T;
+    fn do_something_else<T: Clone>(&self, bar: T); //~ ERROR E0194
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0195.rs b/src/test/compile-fail/E0195.rs
new file mode 100644 (file)
index 0000000..0630dfe
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Trait {
+    fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
+}
+
+struct Foo;
+
+impl Trait for Foo {
+    fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0197.rs b/src/test/compile-fail/E0197.rs
new file mode 100644 (file)
index 0000000..f25fa9b
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo;
+
+unsafe impl Foo { } //~ ERROR E0197
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0199.rs b/src/test/compile-fail/E0199.rs
new file mode 100644 (file)
index 0000000..8bd3ffd
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+struct Foo;
+
+unsafe impl !Clone for Foo { } //~ ERROR E0199
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0200.rs b/src/test/compile-fail/E0200.rs
new file mode 100644 (file)
index 0000000..6bfea0e
--- /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.
+
+struct Foo;
+
+unsafe trait Bar { }
+
+impl Bar for Foo { } //~ ERROR E0200
+
+fn main() {
+}
index da6d081a7acb57e654e2fdadd9862246db842b2e..c6ce0c4c95b8bcbf97a3e0024e391ac4b9e34ccf 100644 (file)
@@ -8,12 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::raw::Slice;
+struct Slice<T> {
+    data: *const T,
+    len: usize,
+}
 
 fn main() {
     let Slice { data: data, len: len } = "foo";
     //~^ ERROR mismatched types
     //~| expected type `&str`
-    //~| found type `std::raw::Slice<_>`
-    //~| expected &-ptr, found struct `std::raw::Slice`
+    //~| found type `Slice<_>`
+    //~| expected &-ptr, found struct `Slice`
 }
index df272a71cee4f70af8daf73c6cb9475e79c76cd6..3060bbea43c3bf8ea0b2520ef1e8ba60136382ba 100644 (file)
@@ -8,15 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::raw::Slice;
+struct Slice<T> {
+    data: *const T,
+    len: usize,
+}
 
 fn main() {
     match () {
         Slice { data: data, len: len } => (),
         //~^ ERROR mismatched types
         //~| expected type `()`
-        //~| found type `std::raw::Slice<_>`
-        //~| expected (), found struct `std::raw::Slice`
+        //~| found type `Slice<_>`
+        //~| expected (), found struct `Slice`
         _ => unreachable!()
     }
 }
index 5e816bcfa61e44493aa733db8782595ea55a13c6..d7ec1ed67397fe939d1585dc32b60f535a8958f2 100644 (file)
@@ -88,6 +88,6 @@ pub fn grow_older(other:usize) {
 fn main() {
     self += 1;
     //~^ ERROR: unresolved name `self`
-    //~| HELP: Module
+    //~| HELP: module `self`
     // it's a bug if this suggests a missing `self` as we're not in a method
 }
diff --git a/src/test/compile-fail/issue-33876.rs b/src/test/compile-fail/issue-33876.rs
new file mode 100644 (file)
index 0000000..d958907
--- /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.
+
+#![feature(reflect_marker)]
+
+use std::marker::Reflect;
+use std::any::Any;
+
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn main() {
+    let any: &Any = &Bar; //~ ERROR E0425
+                          //~| HELP trait `Bar`
+    if any.is::<u32>() { println!("u32"); }
+}
index 58c0791b84ec5b25c05e30dc063c1a6a444e9b4c..7107211fc914b47479b2569515fee614191cca08 100644 (file)
@@ -9,13 +9,12 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::UnwindSafe;
 use std::rc::Rc;
 use std::cell::RefCell;
 
-fn assert<T: RecoverSafe + ?Sized>() {}
+fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
     assert::<Rc<RefCell<i32>>>();
index 481ffb802812a02f30718384c32fa9b4f6690d57..76c34e4dc0b448613ddaef1d2041ad8bc15f18dd 100644 (file)
@@ -9,13 +9,12 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::UnwindSafe;
 use std::sync::Arc;
 use std::cell::RefCell;
 
-fn assert<T: RecoverSafe + ?Sized>() {}
+fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
     assert::<Arc<RefCell<i32>>>();
index 47302d3af78b2909d8159a4d3fb5dab267267e23..177a43e2a7f71650a74955496b37f75cfc1b508f 100644 (file)
@@ -9,12 +9,11 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::UnwindSafe;
 use std::cell::RefCell;
 
-fn assert<T: RecoverSafe + ?Sized>() {}
+fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
     assert::<&RefCell<i32>>();
index 0301c8dd935c7fe71876b226c9d18041028c5959..627a0fe78cf06ae9bb8cb6c56fdbd637e4eb27e6 100644 (file)
@@ -9,12 +9,11 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::UnwindSafe;
 use std::cell::UnsafeCell;
 
-fn assert<T: RecoverSafe + ?Sized>() {}
+fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
     assert::<*const UnsafeCell<i32>>(); //~ ERROR E0277
index fe13b0a75c9eb18dd7f7de6ad99b7e42c74e7543..f03e1d545a8083786f324118f27ebc25eb9f9a94 100644 (file)
@@ -9,12 +9,11 @@
 // except according to those terms.
 
 #![allow(dead_code)]
-#![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::UnwindSafe;
 use std::cell::RefCell;
 
-fn assert<T: RecoverSafe + ?Sized>() {}
+fn assert<T: UnwindSafe + ?Sized>() {}
 
 fn main() {
     assert::<*mut RefCell<i32>>();
index 412c90fd214c17ae5c3a585e0cd3d22fc032d4d9..4a816ea75727669eef145b565c648e82b4a8d9b7 100644 (file)
@@ -26,51 +26,51 @@ pub fn g() -> i32 { 4 }
 fn h1() -> i32 {
     a.I
         //~^ ERROR E0425
-        //~| HELP To reference an item from the `a` module, use `a::I`
+        //~| HELP to reference an item from the `a` module, use `a::I`
 }
 
 fn h2() -> i32 {
     a.g()
         //~^ ERROR E0425
-        //~| HELP To call a function from the `a` module, use `a::g(..)`
+        //~| HELP to call a function from the `a` module, use `a::g(..)`
 }
 
 fn h3() -> i32 {
     a.b.J
         //~^ ERROR E0425
-        //~| HELP To reference an item from the `a` module, use `a::b`
+        //~| HELP to reference an item from the `a` module, use `a::b`
 }
 
 fn h4() -> i32 {
     a::b.J
         //~^ ERROR E0425
-        //~| HELP To reference an item from the `a::b` module, use `a::b::J`
+        //~| HELP to reference an item from the `a::b` module, use `a::b::J`
 }
 
 fn h5() {
     a.b.f();
         //~^ ERROR E0425
-        //~| HELP To reference an item from the `a` module, use `a::b`
+        //~| HELP to reference an item from the `a` module, use `a::b`
     let v = Vec::new();
     v.push(a::b);
         //~^ ERROR E0425
-        //~| HELP Module `a::b` cannot be used as an expression
+        //~| HELP module `a::b` cannot be used as an expression
 }
 
 fn h6() -> i32 {
     a::b.f()
         //~^ ERROR E0425
-        //~| HELP To call a function from the `a::b` module, use `a::b::f(..)`
+        //~| HELP to call a function from the `a::b` module, use `a::b::f(..)`
 }
 
 fn h7() {
     a::b
         //~^ ERROR E0425
-        //~| HELP Module `a::b` cannot be used as an expression
+        //~| HELP module `a::b` cannot be used as an expression
 }
 
 fn h8() -> i32 {
     a::b()
         //~^ ERROR E0425
-        //~| HELP Module `a::b` cannot be used as an expression
+        //~| HELP module `a::b` cannot be used as an expression
 }
index bfeb407dd25a439dbfb51497fb1fe2883de0cc4e..b589544ae156359eb62e260d9f232856090ebf89 100644 (file)
 
 // error-pattern:greetings from the panic handler
 
-#![feature(std_panic, panic_handler)]
+#![feature(panic_handler)]
+
 use std::panic;
 use std::io::{self, Write};
 
 fn main() {
-    panic::set_handler(|i| {
+    panic::set_hook(Box::new(|i| {
         write!(io::stderr(), "greetings from the panic handler");
-    });
+    }));
     panic!("foobar");
 }
index 6999aa715e791b7d2346581afe5cb9c2bab60b15..4c895ea52aa1d5b4e3bced9aaa6fb14f7319824c 100644 (file)
 
 // error-pattern:thread '<main>' panicked at 'foobar'
 
-#![feature(std_panic, panic_handler)]
+#![feature(panic_handler)]
+
 use std::panic;
 use std::io::{self, Write};
 
 fn main() {
-    panic::set_handler(|i| {
+    panic::set_hook(Box::new(|i| {
         write!(io::stderr(), "greetings from the panic handler");
-    });
-    panic::take_handler();
+    }));
+    panic::take_hook();
     panic!("foobar");
 }
index fec1db24adf09cc50446bff45b74ef0eb0a2f6b7..58e57528e8a24e1527c9d22191fbceb7fa02309f 100644 (file)
 
 // error-pattern:thread '<main>' panicked at 'foobar'
 
-#![feature(std_panic, panic_handler)]
+#![feature(panic_handler)]
+
 use std::panic;
 
 fn main() {
-    panic::take_handler();
+    panic::take_hook();
     panic!("foobar");
 }
index 7fbd8dc4786baf1de47c2d7735e6700c8fe11b18..93d3345a8099121041059f62c9fbdf535ece6218 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(recover, rand, std_panic)]
+#![feature(rand, std_panic)]
 
 use std::__rand::{thread_rng, Rng};
-use std::panic::{self, AssertRecoverSafe};
+use std::panic::{self, AssertUnwindSafe};
 
 use std::collections::BinaryHeap;
 use std::cmp;
@@ -70,8 +70,8 @@ fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
             {
                 // push the panicking item to the heap and catch the panic
                 let thread_result = {
-                    let mut heap_ref = AssertRecoverSafe(&mut heap);
-                    panic::recover(move || {
+                    let mut heap_ref = AssertUnwindSafe(&mut heap);
+                    panic::catch_unwind(move || {
                         heap_ref.push(panic_item);
                     })
                 };
diff --git a/src/test/run-pass/exhaustive-bool-match-sanity.rs b/src/test/run-pass/exhaustive-bool-match-sanity.rs
new file mode 100644 (file)
index 0000000..d88a5f1
--- /dev/null
@@ -0,0 +1,34 @@
+// 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.
+
+// Issue #33540
+// We previously used to generate a 3-armed boolean `SwitchInt` in the
+// MIR of the function `foo` below. #33583 changed rustc to
+// generate an `If` terminator instead. This test is to just ensure
+// sanity in that we generate an if-else chain giving the correct
+// results.
+
+#![feature(rustc_attrs)]
+
+#[rustc_mir]
+fn foo(x: bool, y: bool) -> u32 {
+    match (x, y) {
+        (false, _) => 0,
+        (_, false) => 1,
+        (true, true) => 2
+    }
+}
+
+fn main() {
+    assert_eq!(foo(false, true), 0);
+    assert_eq!(foo(false, false), 0);
+    assert_eq!(foo(true, false), 1);
+    assert_eq!(foo(true, true), 2);
+}
diff --git a/src/test/run-pass/issue-33770.rs b/src/test/run-pass/issue-33770.rs
new file mode 100644 (file)
index 0000000..f5635fd
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::process::{Command, Stdio};
+use std::env;
+use std::sync::{Mutex, RwLock};
+use std::time::Duration;
+use std::thread;
+
+fn test_mutex() {
+    let m = Mutex::new(0);
+    let _g = m.lock().unwrap();
+    let _g2 = m.lock().unwrap();
+}
+
+fn test_try_mutex() {
+    let m = Mutex::new(0);
+    let _g = m.lock().unwrap();
+    let _g2 = m.try_lock().unwrap();
+}
+
+fn test_rwlock_ww() {
+    let m = RwLock::new(0);
+    let _g = m.write().unwrap();
+    let _g2 = m.write().unwrap();
+}
+
+fn test_try_rwlock_ww() {
+    let m = RwLock::new(0);
+    let _g = m.write().unwrap();
+    let _g2 = m.try_write().unwrap();
+}
+
+fn test_rwlock_rw() {
+    let m = RwLock::new(0);
+    let _g = m.read().unwrap();
+    let _g2 = m.write().unwrap();
+}
+
+fn test_try_rwlock_rw() {
+    let m = RwLock::new(0);
+    let _g = m.read().unwrap();
+    let _g2 = m.try_write().unwrap();
+}
+
+fn test_rwlock_wr() {
+    let m = RwLock::new(0);
+    let _g = m.write().unwrap();
+    let _g2 = m.read().unwrap();
+}
+
+fn test_try_rwlock_wr() {
+    let m = RwLock::new(0);
+    let _g = m.write().unwrap();
+    let _g2 = m.try_read().unwrap();
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() > 1 {
+        match &*args[1] {
+            "mutex" => test_mutex(),
+            "try_mutex" => test_try_mutex(),
+            "rwlock_ww" => test_rwlock_ww(),
+            "try_rwlock_ww" => test_try_rwlock_ww(),
+            "rwlock_rw" => test_rwlock_rw(),
+            "try_rwlock_rw" => test_try_rwlock_rw(),
+            "rwlock_wr" => test_rwlock_wr(),
+            "try_rwlock_wr" => test_try_rwlock_wr(),
+            _ => unreachable!(),
+        }
+        // If we reach this point then the test failed
+        println!("TEST FAILED: {}", args[1]);
+    } else {
+        let mut v = vec![];
+        v.push(Command::new(&args[0]).arg("mutex").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("try_mutex").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("rwlock_ww").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("try_rwlock_ww").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("rwlock_rw").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("try_rwlock_rw").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("rwlock_wr").stderr(Stdio::null()).spawn().unwrap());
+        v.push(Command::new(&args[0]).arg("try_rwlock_wr").stderr(Stdio::null()).spawn().unwrap());
+
+        thread::sleep(Duration::new(1, 0));
+
+        // Make sure all subprocesses either panicked or were killed because they deadlocked
+        for mut c in v {
+            c.kill().ok();
+            assert!(!c.wait().unwrap().success());
+        }
+    }
+}
index 2c87c6b92686ca6beff5ec22a731364b745bb352..0210017b47efb63f20519c12d648a24777f4f353 100644 (file)
 
 // ignore-emscripten no threads support
 
-#![feature(std_panic, recover, panic_propagate, panic_handler, const_fn)]
+#![feature(panic_handler)]
 
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 use std::panic;
 use std::thread;
 
-static A: AtomicUsize = AtomicUsize::new(0);
+static A: AtomicUsize = ATOMIC_USIZE_INIT;
 
 fn main() {
-    panic::set_handler(|_| {
+    panic::set_hook(Box::new(|_| {
         A.fetch_add(1, Ordering::SeqCst);
-    });
+    }));
 
     let result = thread::spawn(|| {
-        let result = panic::recover(|| {
+        let result = panic::catch_unwind(|| {
             panic!("hi there");
         });
 
-        panic::propagate(result.unwrap_err());
+        panic::resume_unwind(result.unwrap_err());
     }).join();
 
     let msg = *result.unwrap_err().downcast::<&'static str>().unwrap();
index 8a23403359f9a148f16ecafd46a0ad802b7e099b..75a2e36ffb7a4a3f1ad0d5497fab556a5a0c4063 100644 (file)
@@ -10,8 +10,6 @@
 
 // aux-build:reachable-unnameable-items.rs
 
-#![feature(recover)]
-
 extern crate reachable_unnameable_items;
 use reachable_unnameable_items::*;
 
@@ -37,5 +35,5 @@ fn main() {
 
     let none = None;
     function_accepting_unnameable_type(none);
-    let _guard = std::panic::recover(|| none.unwrap().method_of_unnameable_type3());
+    let _guard = std::panic::catch_unwind(|| none.unwrap().method_of_unnameable_type3());
 }
index c67bc8c8368e8738191e24ed30e0fac935892095..23d5a08e216443bf5e8a5b74c04fc4e5ab969491 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_panic, recover, start)]
+#![feature(start)]
 
 use std::ffi::CStr;
 use std::process::{Command, Output};
@@ -22,8 +22,8 @@ fn start(argc: isize, argv: *const *const u8) -> isize {
             match **argv.offset(1) as char {
                 '1' => {}
                 '2' => println!("foo"),
-                '3' => assert!(panic::recover(|| {}).is_ok()),
-                '4' => assert!(panic::recover(|| panic!()).is_err()),
+                '3' => assert!(panic::catch_unwind(|| {}).is_ok()),
+                '4' => assert!(panic::catch_unwind(|| panic!()).is_err()),
                 '5' => assert!(Command::new("test").spawn().is_err()),
                 _ => panic!()
             }
index 4d369ba4d872db10d68159c890bd72c48e6ed335..0f751501293f538cdda52298994a86599dc74363 100644 (file)
@@ -23,8 +23,6 @@ pub fn main() {
     assert_eq!(s.chars().count(), 4);
     assert_eq!(schs.len(), 4);
     assert_eq!(schs.iter().cloned().collect::<String>(), s);
-    assert_eq!(s.char_at(0), 'e');
-    assert_eq!(s.char_at(1), 'é');
 
     assert!((str::from_utf8(s.as_bytes()).is_ok()));
     // invalid prefix
index abd1709825c974b605f03b011c5113f0bb3afc25..0131563d36d35e05838561731a5ca21c156b7fbd 100644 (file)
@@ -8,60 +8,39 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-msvc -- sprintf isn't a symbol in msvcrt? maybe a #define?
-
-#![feature(libc, std_misc)]
-
-extern crate libc;
-
-use std::ffi::{CStr, CString};
-use libc::{c_char, c_int};
-
-
+#[link(name = "rust_test_helpers")]
 extern {
-    fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int;
-}
-
-unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T {
-    let mut x = [0 as c_char; 50];
-    f(&mut x[0] as *mut c_char);
-    assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes());
+    fn rust_interesting_average(_: u64, ...) -> f64;
 }
 
 pub fn main() {
-
+    // Call without variadic arguments
     unsafe {
-        // Call with just the named parameter
-        let c = CString::new(&b"Hello World\n"[..]).unwrap();
-        check("Hello World\n", |s| sprintf(s, c.as_ptr()));
-
-        // Call with variable number of arguments
-        let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap();
-        check("42 42.500000 a %d %f %c %s\n\n", |s| {
-            sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
-        });
+        assert!(rust_interesting_average(0).is_nan());
+    }
 
-        // Make a function pointer
-        let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
+    // Call with direct arguments
+    unsafe {
+        assert_eq!(rust_interesting_average(1, 10i64, 10.0f64) as i64, 20);
+    }
 
-        // A function that takes a function pointer
-        unsafe fn call(fp: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
-            // Call with just the named parameter
-            let c = CString::new(&b"Hello World\n"[..]).unwrap();
-            check("Hello World\n", |s| fp(s, c.as_ptr()));
+    // Call with named arguments, variable number of them
+    let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64);
+    unsafe {
+        assert_eq!(rust_interesting_average(2, x1, x2, x3, x4) as i64, 30);
+    }
 
-            // Call with variable number of arguments
-            let c = CString::new(&b"%d %f %c %s\n"[..]).unwrap();
-            check("42 42.500000 a %d %f %c %s\n\n", |s| {
-                fp(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
-            });
-        }
+    // A function that takes a function pointer
+    unsafe fn call(fp: unsafe extern fn(u64, ...) -> f64) {
+        let (x1, x2, x3, x4) = (10i64, 10.0f64, 20i64, 20.0f64);
+        assert_eq!(fp(2, x1, x2, x3, x4) as i64, 30);
+    }
 
-        // Pass sprintf directly
-        call(sprintf);
+    unsafe {
+        call(rust_interesting_average);
 
-        // Pass sprintf indirectly
+        // Make a function pointer, pass indirectly
+        let x: unsafe extern fn(u64, ...) -> f64 = rust_interesting_average;
         call(x);
     }
-
 }