]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #29176 - huonw:shared-tracking, r=Gankro
authorSteve Klabnik <steve@steveklabnik.com>
Tue, 20 Oct 2015 13:43:48 +0000 (09:43 -0400)
committerSteve Klabnik <steve@steveklabnik.com>
Tue, 20 Oct 2015 13:43:48 +0000 (09:43 -0400)
16 files changed:
mk/cfg/mips-unknown-linux-gnu.mk
mk/cfg/mipsel-unknown-linux-gnu.mk
mk/dist.mk
mk/install.mk
mk/prepare.mk
src/doc/nomicon/dropck.md
src/doc/nomicon/leaking.md
src/libcollections/vec_deque.rs
src/libcollectionstest/vec_deque.rs
src/libcore/marker.rs
src/libstd/fs.rs
src/libstd/process.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/test/run-pass/sync-send-iterators-in-libcollections.rs

index ba5f6d0e756343af7fb01c1b2e398d9644f56018..65b08774d49a01977ebadb02fd1de6b602f73edd 100644 (file)
@@ -7,8 +7,8 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
-CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
 CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
@@ -20,5 +20,5 @@ CFG_UNIXY_mips-unknown-linux-gnu := 1
 CFG_LDPATH_mips-unknown-linux-gnu :=
 CFG_RUN_mips-unknown-linux-gnu=
 CFG_RUN_TARG_mips-unknown-linux-gnu=
-RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
+RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2" -C soft-float
 CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu
index 539038c7434606dfc4825052af1a35a431445096..4dadfc275d3c5a518021e059ce0570c399f0c2ea 100644 (file)
@@ -1,8 +1,8 @@
 # mipsel-unknown-linux-gnu configuration
-CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
-CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++
-CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
-AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar
+CC_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
+CXX_mipsel-unknown-linux-gnu=mipsel-linux-gnu-g++
+CPP_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
+AR_mipsel-unknown-linux-gnu=mipsel-linux-gnu-ar
 CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
@@ -20,5 +20,5 @@ CFG_UNIXY_mipsel-unknown-linux-gnu := 1
 CFG_LDPATH_mipsel-unknown-linux-gnu :=
 CFG_RUN_mipsel-unknown-linux-gnu=
 CFG_RUN_TARG_mipsel-unknown-linux-gnu=
-RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
+RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32"
 CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu
index 125141c1830d273c9f8f5aca8aa5bd72a41ba541..eb94760e248f6ebea7df728c78e017d7adb7ffeb 100644 (file)
@@ -21,6 +21,7 @@
 # * dist-docs - Stage docs for upload
 
 PKG_NAME := $(CFG_PACKAGE_NAME)
+STD_PKG_NAME := rust-std-$(CFG_PACKAGE_VERS)
 DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
 MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
 
@@ -112,19 +113,25 @@ distcheck-tar-src: dist-tar-src
 # Unix binary installer tarballs
 ######################################################################
 
-define DEF_INSTALLER
+define DEF_START_INSTALLER
+dist-install-dir-$(1)-%: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
+dist-install-dir-$(1)-%: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
+dist-install-dir-$(1)-%: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
+dist-install-dir-$(1)-%: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
+dist-install-dir-$(1)-%: PREPARE_CLEAN=true
 
 $$(eval $$(call DEF_PREPARE,dir-$(1)))
+endef
+
+$(foreach target,$(CFG_TARGET),\
+  $(eval $(call DEF_START_INSTALLER,$(target))))
 
-dist-install-dir-$(1): PREPARE_HOST=$(1)
-dist-install-dir-$(1): PREPARE_TARGETS=$(2)
-dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
-dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
-dist-install-dir-$(1): PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
-dist-install-dir-$(1): PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
-dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
-dist-install-dir-$(1): PREPARE_CLEAN=true
-dist-install-dir-$(1): prepare-base-dir-$(1) docs
+define DEF_INSTALLER
+
+dist-install-dir-$(1)-host: PREPARE_HOST=$(1)
+dist-install-dir-$(1)-host: PREPARE_TARGETS=$(2)
+dist-install-dir-$(1)-host: PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
+dist-install-dir-$(1)-host: prepare-base-dir-$(1)-host docs
        $$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust
        $$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
        $$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust
@@ -141,14 +148,27 @@ prepare-overlay-$(1):
 # This tiny morsel of metadata is used by rust-packaging
        $$(Q)echo "$(CFG_VERSION)" > tmp/dist/$$(PKG_NAME)-$(1)-overlay/version
 
-dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) prepare-overlay-$(1)
+dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)-host prepare-overlay-$(1)
        @$(call E, build: $$@)
-# Copy essential gcc components into installer
-ifdef CFG_WINDOWSY_$(1)
-ifeq ($$(findstring gnu,$(1)),gnu)
-       $$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1)
-       $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1)
-       $$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
+# On a 32-bit MinGW target we've got a few runtime DLL dependencies that we need
+# to include. THe first argument to `make-win-dist` is where to put these DLLs
+# (the image we're creating) and the second argument is a junk directory to
+# ignore all the other MinGW stuff the script creates.
+ifeq ($(2),i686-pc-windows-gnu)
+       $$(Q)rm -Rf tmp/dist/win-rust-gcc-$(2)
+       $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
+               tmp/dist/$$(STD_PKG_NAME)-$(2)-image \
+               tmp/dist/win-rust-gcc-$(2) $(2)
+endif
+# On 32-bit MinGW we're always including a DLL which needs some extra licenses
+# to distribute. On 64-bit MinGW we don't actually distribute anything requiring
+# us to distribute a license but it's likely that the install will *also*
+# include the rust-mingw package down below, which also need licenses, so to be
+# safe we just inlude it here in all MinGW packages.
+ifdef CFG_WINDOWSY_$(2)
+ifeq ($$(findstring $(2),gnu),gnu)
+       $$(Q)cp -r $$(S)src/etc/third-party \
+               tmp/dist/$$(STD_PKG_NAME)-$(2)-image/share/doc/
 endif
 endif
        $$(Q)$$(S)src/rust-installer/gen-installer.sh \
@@ -183,11 +203,16 @@ dist/$$(DOC_PKG_NAME)-$(1).tar.gz: dist-doc-install-dir-$(1)
                --bulk-dirs=share/doc/rust/html
        $$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image
 
+# Creates the rust-mingw package, and the first argument to make-win-dist is a
+# "temporary directory" which is just thrown away (this contains the runtime
+# DLLs included in the rustc package above) and the second argument is where to
+# place all the MinGW components (which is what we want).
 dist-mingw-install-dir-$(1):
        $$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
        $$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
        $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
-               tmp/dist/rust-mingw-tmp-$(1)-image tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
+               tmp/dist/rust-mingw-tmp-$(1)-image \
+               tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
 
 dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
        @$(call E, build: $$@)
@@ -205,15 +230,34 @@ dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
 
 endef
 
-ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),)
-$(foreach host,$(CFG_HOST),\
-  $(eval $(call DEF_INSTALLER,$(host),$(host))))
-else
-$(foreach host,$(CFG_HOST),\
-  $(eval $(call DEF_INSTALLER,$(host),$(CFG_TARGET))))
-endif
+# $(1) - host
+# $(2) - target
+define DEF_INSTALLER_TARGETS
+
+dist-install-dir-$(2)-target: PREPARE_HOST=$(1)
+dist-install-dir-$(2)-target: PREPARE_TARGETS=$(2)
+dist-install-dir-$(2)-target: PREPARE_DEST_DIR=tmp/dist/$$(STD_PKG_NAME)-$(2)-image
+dist-install-dir-$(2)-target: prepare-base-dir-$(2)-target
 
-dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
+dist/$$(STD_PKG_NAME)-$(2).tar.gz: dist-install-dir-$(2)-target
+       @$$(call E, build: $$@)
+       $$(Q)$$(S)src/rust-installer/gen-installer.sh \
+               --product-name=Rust \
+               --rel-manifest-dir=rustlib \
+               --success-message=std-is-standing-at-the-ready. \
+               --image-dir=tmp/dist/$$(STD_PKG_NAME)-$(2)-image \
+               --work-dir=tmp/dist \
+               --output-dir=dist \
+               --package-name=$$(STD_PKG_NAME)-$(2) \
+               --component-name=rust-std-$(2) \
+               --legacy-manifest-dirs=rustlib,cargo
+       $$(Q)rm -R tmp/dist/$$(STD_PKG_NAME)-$(2)-image
+endef
+
+$(foreach host,$(CFG_HOST),\
+  $(eval $(call DEF_INSTALLER,$(host))))
+$(foreach target,$(CFG_TARGET),\
+  $(eval $(call DEF_INSTALLER_TARGETS,$(CFG_BUILD),$(target))))
 
 ifdef CFG_WINDOWSY_$(CFG_BUILD)
 define BUILD_MINGW_TARBALL
@@ -230,7 +274,9 @@ ifeq ($(CFG_DISABLE_DOCS),)
 MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
 endif
 
-dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
+dist-tar-bins: \
+       $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
+       $(foreach target,$(CFG_TARGET),dist/$(STD_PKG_NAME)-$(target).tar.gz) \
        $(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
 
 # Just try to run the compiler for the build host
index cabc97a1e49120073c6e415d7546905f12e2be1b..8b8170220c9168a8db08ddf6884272cdf4346d14 100644 (file)
@@ -8,6 +8,12 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+RUN_INSALLER = cd tmp/empty_dir && \
+       sh ../../tmp/dist/$(1)/install.sh \
+               --prefix="$(DESTDIR)$(CFG_PREFIX)" \
+               --libdir="$(DESTDIR)$(CFG_LIBDIR)" \
+               --mandir="$(DESTDIR)$(CFG_MANDIR)"
+
 install:
 ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
 # Build the dist as the original user
@@ -16,9 +22,11 @@ else
        $(Q)$(MAKE) prepare_install
 endif
 ifeq ($(CFG_DISABLE_DOCS),)
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --disable-ldconfig
 endif
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(foreach target,$(CFG_TARGET),\
+         ($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --disable-ldconfig);)
+       $(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD))
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
@@ -32,9 +40,11 @@ else
        $(Q)$(MAKE) prepare_uninstall
 endif
 ifeq ($(CFG_DISABLE_DOCS),)
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --uninstall
 endif
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD)) --uninstall
+       $(Q)$(foreach target,$(CFG_TARGET),\
+         ($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --uninstall);)
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
index fe619cc7caec76f3d8f4dfcda82a0621c21efee3..e263a6d2e4d32ab6c13c9d8484cfa3fa9c8295a6 100644 (file)
@@ -185,16 +185,16 @@ INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\
 
 define DEF_PREPARE
 
-prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
-prepare-base-$(1): PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
-prepare-base-$(1): PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
-prepare-base-$(1): PREPARE_SOURCE_MAN_DIR=$$(S)/man
-prepare-base-$(1): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
-prepare-base-$(1): PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
-prepare-base-$(1): PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
-prepare-base-$(1): prepare-everything-$(1)
+prepare-base-$(1)-%: PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
+prepare-base-$(1)-%: PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
+prepare-base-$(1)-%: PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
+prepare-base-$(1)-%: PREPARE_SOURCE_MAN_DIR=$$(S)/man
+prepare-base-$(1)-%: PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
+prepare-base-$(1)-%: PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
+prepare-base-$(1)-%: PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
 
-prepare-everything-$(1): prepare-host-$(1) prepare-targets-$(1) prepare-debugger-scripts-$(1)
+prepare-base-$(1)-target: prepare-target-$(1)
+prepare-base-$(1)-host: prepare-host-$(1) prepare-debugger-scripts-$(1)
 
 prepare-host-$(1): prepare-host-tools-$(1)
 
@@ -222,7 +222,7 @@ $$(foreach lib,$$(CRATES), \
   $$(foreach host,$$(CFG_HOST), \
     $$(eval $$(call DEF_PREPARE_HOST_LIB,$$(lib),$$(PREPARE_STAGE),$$(host),$(1)))))
 
-prepare-targets-$(1): \
+prepare-target-$(1): \
         $$(foreach host,$$(CFG_HOST), \
            $$(foreach target,$$(CFG_TARGET), \
              prepare-target-$$(target)-host-$$(host)-$$(PREPARE_STAGE)-$(1)))
index 95bcdc02ba0292da5b0522e09efb66657bfb2b0f..ad7c65032c76995d03896affcc372543b2706a05 100644 (file)
@@ -220,6 +220,7 @@ checking the implicit assertion that no potentially expired data
 It is sometimes obvious that no such access can occur, like the case above.
 However, when dealing with a generic type parameter, such access can
 occur indirectly. Examples of such indirect access are:
+
  * invoking a callback,
  * via a trait method call.
 
index 1f72a4c17247057e92ce65e1512cdafda3d87004..a5d5742a4c62151912fae5e377def09ec5eb8530 100644 (file)
@@ -135,7 +135,7 @@ impl<T> Rc<T> {
     fn new(data: T) -> Self {
         unsafe {
             // Wouldn't it be nice if heap::allocate worked like this?
-            let ptr = heap::allocate<RcBox<T>>();
+            let ptr = heap::allocate::<RcBox<T>>();
             ptr::write(ptr, RcBox {
                 data: data,
                 ref_count: 1,
index d438c27a96fa0621228dfcce5b961cdc891ee00e..4cba1083fd99d1315e54ee334974224a207804d6 100644 (file)
@@ -32,6 +32,8 @@
 
 use alloc::raw_vec::RawVec;
 
+use super::range::RangeArgument;
+
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
 const MINIMUM_CAPACITY: usize = 1; // 2 - 1
 const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two
@@ -168,6 +170,117 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
             len);
     }
 
+    /// Copies a potentially wrapping block of memory len long from src to dest.
+    /// (abs(dst - src) + len) must be no larger than cap() (There must be at
+    /// most one continuous overlapping region between src and dest).
+    unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) {
+        debug_assert!(
+            (if src <= dst { dst - src } else { src - dst }) + len <= self.cap(),
+            "dst={} src={} len={} cap={}", dst, src, len, self.cap());
+
+        if src == dst || len == 0 { return }
+
+        let dst_after_src = self.wrap_sub(dst, src) < len;
+
+        let src_pre_wrap_len = self.cap() - src;
+        let dst_pre_wrap_len = self.cap() - dst;
+        let src_wraps = src_pre_wrap_len < len;
+        let dst_wraps = dst_pre_wrap_len < len;
+
+        match (dst_after_src, src_wraps, dst_wraps) {
+            (_, false, false) => {
+                // src doesn't wrap, dst doesn't wrap
+                //
+                //        S . . .
+                // 1 [_ _ A A B B C C _]
+                // 2 [_ _ A A A A B B _]
+                //            D . . .
+                //
+                self.copy(dst, src, len);
+            }
+            (false, false, true) => {
+                // dst before src, src doesn't wrap, dst wraps
+                //
+                //    S . . .
+                // 1 [A A B B _ _ _ C C]
+                // 2 [A A B B _ _ _ A A]
+                // 3 [B B B B _ _ _ A A]
+                //    . .           D .
+                //
+                self.copy(dst, src, dst_pre_wrap_len);
+                self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
+            }
+            (true, false, true) => {
+                // src before dst, src doesn't wrap, dst wraps
+                //
+                //              S . . .
+                // 1 [C C _ _ _ A A B B]
+                // 2 [B B _ _ _ A A B B]
+                // 3 [B B _ _ _ A A A A]
+                //    . .           D .
+                //
+                self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
+                self.copy(dst, src, dst_pre_wrap_len);
+            }
+            (false, true, false) => {
+                // dst before src, src wraps, dst doesn't wrap
+                //
+                //    . .           S .
+                // 1 [C C _ _ _ A A B B]
+                // 2 [C C _ _ _ B B B B]
+                // 3 [C C _ _ _ B B C C]
+                //              D . . .
+                //
+                self.copy(dst, src, src_pre_wrap_len);
+                self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
+            }
+            (true, true, false) => {
+                // src before dst, src wraps, dst doesn't wrap
+                //
+                //    . .           S .
+                // 1 [A A B B _ _ _ C C]
+                // 2 [A A A A _ _ _ C C]
+                // 3 [C C A A _ _ _ C C]
+                //    D . . .
+                //
+                self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
+                self.copy(dst, src, src_pre_wrap_len);
+            }
+            (false, true, true) => {
+                // dst before src, src wraps, dst wraps
+                //
+                //    . . .         S .
+                // 1 [A B C D _ E F G H]
+                // 2 [A B C D _ E G H H]
+                // 3 [A B C D _ E G H A]
+                // 4 [B C C D _ E G H A]
+                //    . .         D . .
+                //
+                debug_assert!(dst_pre_wrap_len > src_pre_wrap_len);
+                let delta = dst_pre_wrap_len - src_pre_wrap_len;
+                self.copy(dst, src, src_pre_wrap_len);
+                self.copy(dst + src_pre_wrap_len, 0, delta);
+                self.copy(0, delta, len - dst_pre_wrap_len);
+            }
+            (true, true, true) => {
+                // src before dst, src wraps, dst wraps
+                //
+                //    . .         S . .
+                // 1 [A B C D _ E F G H]
+                // 2 [A A B D _ E F G H]
+                // 3 [H A B D _ E F G H]
+                // 4 [H A B D _ E F F G]
+                //    . . .         D .
+                //
+                debug_assert!(src_pre_wrap_len > dst_pre_wrap_len);
+                let delta = src_pre_wrap_len - dst_pre_wrap_len;
+                self.copy(delta, 0, len - src_pre_wrap_len);
+                self.copy(0, self.cap() - delta, delta);
+                self.copy(dst, src, dst_pre_wrap_len);
+            }
+        }
+    }
+
     /// Frobs the head and tail sections around to handle the fact that we
     /// just reallocated. Unsafe because it trusts old_cap.
     #[inline]
@@ -613,8 +726,18 @@ pub fn len(&self) -> usize { count(self.tail, self.head, self.cap()) }
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
-    /// Creates a draining iterator that clears the `VecDeque` and iterates over
-    /// the removed items from start to end.
+    /// Create a draining iterator that removes the specified range in the
+    /// `VecDeque` and yields the removed items from start to end. The element
+    /// range is removed even if the iterator is not consumed until the end.
+    ///
+    /// Note: It is unspecified how many elements are removed from the deque,
+    /// if the `Drain` value is not dropped, but the borrow it holds expires
+    /// (eg. due to mem::forget).
+    ///
+    /// # Panics
+    ///
+    /// Panics if the starting point is greater than the end point or if
+    /// the end point is greater than the length of the vector.
     ///
     /// # Examples
     ///
@@ -623,18 +746,66 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
     ///
     /// use std::collections::VecDeque;
     ///
+    /// // draining using `..` clears the whole deque.
     /// let mut v = VecDeque::new();
     /// v.push_back(1);
-    /// assert_eq!(v.drain().next(), Some(1));
+    /// assert_eq!(v.drain(..).next(), Some(1));
     /// assert!(v.is_empty());
     /// ```
     #[inline]
     #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle",
                issue = "27711")]
-    pub fn drain(&mut self) -> Drain<T> {
+    pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
+        // Memory safety
+        //
+        // When the Drain is first created, the source deque is shortened to
+        // make sure no uninitialized or moved-from elements are accessible at
+        // all if the Drain's destructor never gets to run.
+        //
+        // Drain will ptr::read out the values to remove.
+        // When finished, the remaining data will be copied back to cover the hole,
+        // and the head/tail values will be restored correctly.
+        //
+        let len = self.len();
+        let start = *range.start().unwrap_or(&0);
+        let end = *range.end().unwrap_or(&len);
+        assert!(start <= end, "drain lower bound was too large");
+        assert!(end <= len, "drain upper bound was too large");
+
+        // The deque's elements are parted into three segments:
+        // * self.tail  -> drain_tail
+        // * drain_tail -> drain_head
+        // * drain_head -> self.head
+        //
+        // T = self.tail; H = self.head; t = drain_tail; h = drain_head
+        //
+        // We store drain_tail as self.head, and drain_head and self.head as
+        // after_tail and after_head respectively on the Drain. This also
+        // truncates the effective array such that if the Drain is leaked, we
+        // have forgotten about the potentially moved values after the start of
+        // the drain.
+        //
+        //        T   t   h   H
+        // [. . . o o x x o o . . .]
+        //
+        let drain_tail = self.wrap_add(self.tail, start);
+        let drain_head = self.wrap_add(self.tail, end);
+        let head = self.head;
+
+        // "forget" about the values after the start of the drain until after
+        // the drain is complete and the Drain destructor is run.
+        self.head = drain_tail;
+
         Drain {
-            inner: self,
+            deque: self as *mut _,
+            after_tail: drain_head,
+            after_head: head,
+            iter: Iter {
+                tail: drain_tail,
+                head: drain_head,
+                ring: unsafe { self.buffer_as_mut_slice() },
+            },
         }
     }
 
@@ -653,7 +824,7 @@ pub fn drain(&mut self) -> Drain<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn clear(&mut self) {
-        self.drain();
+        self.drain(..);
     }
 
     /// Provides a reference to the front element, or `None` if the sequence is
@@ -1393,7 +1564,7 @@ pub fn split_off(&mut self, at: usize) -> Self {
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
         // naive impl
-        self.extend(other.drain());
+        self.extend(other.drain(..));
     }
 
     /// Retains only the elements specified by the predicate.
@@ -1627,15 +1798,59 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
            reason = "matches collection reform specification, waiting for dust to settle",
            issue = "27711")]
 pub struct Drain<'a, T: 'a> {
-    inner: &'a mut VecDeque<T>,
+    after_tail: usize,
+    after_head: usize,
+    iter: Iter<'a, T>,
+    deque: *mut VecDeque<T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
+unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         for _ in self.by_ref() {}
-        self.inner.head = 0;
-        self.inner.tail = 0;
+
+        let source_deque = unsafe { &mut *self.deque };
+
+        // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
+        //
+        //        T   t   h   H
+        // [. . . o o x x o o . . .]
+        //
+        let orig_tail = source_deque.tail;
+        let drain_tail = source_deque.head;
+        let drain_head = self.after_tail;
+        let orig_head = self.after_head;
+
+        let tail_len = count(orig_tail, drain_tail, source_deque.cap());
+        let head_len = count(drain_head, orig_head, source_deque.cap());
+
+        // Restore the original head value
+        source_deque.head = orig_head;
+
+        match (tail_len, head_len) {
+            (0, 0) => {
+                source_deque.head = 0;
+                source_deque.tail = 0;
+            }
+            (0, _) => {
+                source_deque.tail = drain_head;
+            }
+            (_, 0) => {
+                source_deque.head = drain_tail;
+            }
+            _ => unsafe {
+                if tail_len <= head_len {
+                    source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
+                    source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
+                } else {
+                    source_deque.head = source_deque.wrap_add(drain_tail, head_len);
+                    source_deque.wrap_copy(drain_tail, drain_head, head_len);
+                }
+            }
+        }
     }
 }
 
@@ -1645,13 +1860,16 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        self.inner.pop_front()
+        self.iter.next().map(|elt|
+            unsafe {
+                ptr::read(elt)
+            }
+        )
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = self.inner.len();
-        (len, Some(len))
+        self.iter.size_hint()
     }
 }
 
@@ -1659,7 +1877,11 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
-        self.inner.pop_back()
+        self.iter.next_back().map(|elt|
+            unsafe {
+                ptr::read(elt)
+            }
+        )
     }
 }
 
@@ -1962,6 +2184,44 @@ fn test_remove() {
         }
     }
 
+    #[test]
+    fn test_drain() {
+        let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
+
+        let cap = tester.capacity();
+        for len in 0..cap + 1 {
+            for tail in 0..cap + 1 {
+                for drain_start in 0..len + 1 {
+                    for drain_end in drain_start..len + 1 {
+                        tester.tail = tail;
+                        tester.head = tail;
+                        for i in 0..len {
+                            tester.push_back(i);
+                        }
+
+                        // Check that we drain the correct values
+                        let drained: VecDeque<_> =
+                            tester.drain(drain_start..drain_end).collect();
+                        let drained_expected: VecDeque<_> =
+                            (drain_start..drain_end).collect();
+                        assert_eq!(drained, drained_expected);
+
+                        // We shouldn't have changed the capacity or made the
+                        // head or tail out of bounds
+                        assert_eq!(tester.capacity(), cap);
+                        assert!(tester.tail < tester.cap());
+                        assert!(tester.head < tester.cap());
+
+                        // We should see the correct values in the VecDeque
+                        let expected: VecDeque<_> =
+                            (0..drain_start).chain(drain_end..len).collect();
+                        assert_eq!(expected, tester);
+                    }
+                }
+            }
+        }
+    }
+
     #[test]
     fn test_shrink_to_fit() {
         // This test checks that every single combination of head and tail position,
index 1931e372aeb91c29c6bb6443094fb3ea407cec6f..5f587789bd865ae86d1abdc3b15b80c6ce95fef7 100644 (file)
@@ -475,7 +475,7 @@ fn test_drain() {
         let mut d: VecDeque<i32> = VecDeque::new();
 
         {
-            let mut iter = d.drain();
+            let mut iter = d.drain(..);
 
             assert_eq!(iter.size_hint(), (0, Some(0)));
             assert_eq!(iter.next(), None);
@@ -492,7 +492,7 @@ fn test_drain() {
             d.push_back(i);
         }
 
-        assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+        assert_eq!(d.drain(..).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
         assert!(d.is_empty());
     }
 
@@ -506,7 +506,7 @@ fn test_drain() {
             d.push_front(i);
         }
 
-        assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
+        assert_eq!(d.drain(..).collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
         assert!(d.is_empty());
     }
 
@@ -521,7 +521,7 @@ fn test_drain() {
         }
 
         {
-            let mut it = d.drain();
+            let mut it = d.drain(..);
             assert_eq!(it.size_hint(), (8, Some(8)));
             assert_eq!(it.next(), Some(8));
             assert_eq!(it.size_hint(), (7, Some(7)));
index f9480b4349d1107ece794503e96edbecfdff04f7..27d8af2e8a88f28b23fee1130f2171091519432d 100644 (file)
@@ -36,6 +36,17 @@ impl<T> !Send for *const T { }
 impl<T> !Send for *mut T { }
 
 /// Types with a constant size known at compile-time.
+///
+/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax
+/// `?Sized` can be used to remove this bound if it is not appropriate.
+///
+/// ```
+/// struct Foo<T>(T);
+/// struct Bar<T: ?Sized>(T);
+///
+/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
+/// struct BarUse(Bar<[i32]>); // OK
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sized"]
 #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
index 0669f545a83325853b8f912af1b86d6f98d85cb9..1da7a1502d92d4ffca9474ef5cb7b6f0afd0badd 100644 (file)
@@ -2162,4 +2162,10 @@ fn dir_entry_methods() {
             }
         }
     }
+
+    #[test]
+    fn read_dir_not_found() {
+        let res = fs::read_dir("/path/that/does/not/exist");
+        assert_eq!(res.err().unwrap().kind(), ErrorKind::NotFound);
+    }
 }
index 6e3c5eaf217f63b62fc721a66466c1ee2caf879a..9d03022bb84e766b57caa326d14874ff04227d57 100644 (file)
@@ -625,8 +625,8 @@ fn exit_reported_right() {
         drop(p.wait());
     }
 
-    #[cfg(unix)]
     #[cfg(all(unix, not(target_os="android")))]
+    #[test]
     fn signal_reported_right() {
         use os::unix::process::ExitStatusExt;
 
index bac5b47eb1a6228e660f3511a34e61f3c49fbd01..a9eb4db2f534e5fdcba1f4914ab007f4521f9c4a 100644 (file)
@@ -83,6 +83,8 @@
 pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
 
+pub const ERROR_PATH_NOT_FOUND: libc::c_int = 3;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
index 85f5d4e5884a2a3ad4c8a584abeeeba0d9499ea3..4df3c561ab1c3d51ced9427cfd486e51d712348c 100644 (file)
@@ -51,6 +51,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists,
         libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe,
         libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound,
+        c::ERROR_PATH_NOT_FOUND => ErrorKind::NotFound,
         libc::ERROR_NO_DATA => ErrorKind::BrokenPipe,
         libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut,
 
index 2a5c4993112a992e54edaafb8c94b6e7f5d2d1a7..11bf6ec24ce9913f01a4bb8ed29ecfa18143d619 100644 (file)
@@ -417,7 +417,7 @@ pub fn expand(&self,
                 let mut attrs = newitem.attrs.clone();
                 attrs.extend(item.attrs.iter().filter(|a| {
                     match &a.name()[..] {
-                        "allow" | "warn" | "deny" | "forbid" => true,
+                        "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
                         _ => false,
                     }
                 }).cloned());
index 8160fe56fd0b27adfcdda9407b2996c15d095705..7fa592105c09d4900d14236fe028016c86cf9329 100644 (file)
@@ -93,7 +93,8 @@ fn from_usize(v: usize) -> Foo {
     }
     all_sync_send!(EnumSet::<Foo>::new(), iter);
 
-    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, drain, into_iter);
+    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, into_iter);
+    is_sync_send!(VecDeque::<usize>::new(), drain(..));
 
     all_sync_send!(Vec::<usize>::new(), into_iter);
     is_sync_send!(Vec::<usize>::new(), drain(..));