]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #30892 - shepmaster:box-grammar, r=alexcrichton
authorManish Goregaokar <manishsmail@gmail.com>
Thu, 14 Jan 2016 13:42:29 +0000 (19:12 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Thu, 14 Jan 2016 13:42:29 +0000 (19:12 +0530)
45 files changed:
README.md
mk/cfg/x86_64-unknown-bitrig.mk
mk/crates.mk
src/doc/book/bibliography.md
src/doc/book/unsafe.md
src/doc/reference.md
src/liballoc/lib.rs
src/liballoc/oom.rs [new file with mode: 0644]
src/libcollections/lib.rs
src/libcollections/range.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcore/fmt/mod.rs
src/libcore/iter.rs
src/libcore/num/mod.rs
src/librustc/session/config.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/record_exports.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/tvec.rs
src/librustc_unicode/char.rs
src/librustdoc/html/render.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/panicking.rs
src/libstd/rand/os.rs
src/libstd/sys/common/util.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/windows/mod.rs
src/libstd/time/duration.rs
src/libtest/lib.rs
src/test/run-pass/issue-29092.rs [new file with mode: 0644]
src/test/run-pass/issue-30018-nopanic.rs [new file with mode: 0644]
src/test/run-pass/issue-30018-panic.rs [new file with mode: 0644]
src/test/run-pass/issue-30530.rs [new file with mode: 0644]

index 7558065831ace3e52982e76bf9f849d6f7232ff2..636c8adfa91e9f0d9236506d49869220e58780a4 100644 (file)
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Read ["Installing Rust"] from [The Book].
 1. Make sure you have installed the dependencies:
 
    * `g++` 4.7 or `clang++` 3.x
-   * `python` 2.6 or later (but not 3.x)
+   * `python` 2.7 or later (but not 3.x)
    * GNU `make` 3.81 or later
    * `curl`
    * `git`
index dd6d19f7491bb688d8f7c588392afd18c9a6a4c5..afffec1a53a913a398f3c34da36e475314f0a845 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-bitrig=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIC -m64 -I/usr/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIE -fPIC -m64 -I/usr/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
index 7542d91ce6d50afdd9edf90c2660544c16a777e8..be53234cb02e2ca402f07197251ae7b435696f8e 100644 (file)
@@ -103,7 +103,7 @@ DEPS_rustc_lint := rustc log syntax
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_rustc_metadata := rustc rustc_front syntax rbml
 DEPS_rustc_mir := rustc rustc_front syntax
-DEPS_rustc_resolve := rustc rustc_front log syntax
+DEPS_rustc_resolve := arena rustc rustc_front log syntax
 DEPS_rustc_platform_intrinsics := rustc rustc_llvm
 DEPS_rustc_plugin := rustc rustc_metadata syntax
 DEPS_rustc_privacy := rustc rustc_front log syntax
index ba02053b6b8944761e85f9b9cd5feded040cebed..d32b1a91944e46366a5100f62808386619a959ef 100644 (file)
@@ -33,7 +33,7 @@ Rust, as well as publications about Rust.
 * [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
 * [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
 * [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)
-* [Epoc-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf).
+* [Epoch-based reclamation](https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-579.pdf).
 
 ### Others
 
index eb464986af3bed2569ee5c13c426162629451193..ecd196a9f0d1fe5b3b79b4f3b54dd7d8df892ed9 100644 (file)
@@ -41,8 +41,8 @@ unsafe impl Scary for i32 {}
 ```
 
 It’s important to be able to explicitly delineate code that may have bugs that
-cause big problems. If a Rust program segfaults, you can be sure it’s somewhere
-in the sections marked `unsafe`.
+cause big problems. If a Rust program segfaults, you can be sure the cause is
+related to something marked `unsafe`.
 
 # What does ‘safe’ mean?
 
index 5f71ee4437958974f7cd250d1737b9e106df7035..87104b4526f72b670ec916aec08ce7c6627dc57b 100644 (file)
@@ -3677,10 +3677,10 @@ sites are:
 
 * `let` statements where an explicit type is given.
 
-   For example, `128` is coerced to have type `i8` in the following:
+   For example, `42` is coerced to have type `i8` in the following:
 
    ```rust
-   let _: i8 = 128;
+   let _: i8 = 42;
    ```
 
 * `static` and `const` statements (similar to `let` statements).
@@ -3690,36 +3690,36 @@ sites are:
   The value being coerced is the actual parameter, and it is coerced to
   the type of the formal parameter.
 
-  For example, `128` is coerced to have type `i8` in the following:
+  For example, `42` is coerced to have type `i8` in the following:
 
   ```rust
   fn bar(_: i8) { }
 
   fn main() {
-      bar(128);
+      bar(42);
   }
   ```
 
 * Instantiations of struct or variant fields
 
-  For example, `128` is coerced to have type `i8` in the following:
+  For example, `42` is coerced to have type `i8` in the following:
 
   ```rust
   struct Foo { x: i8 }
 
   fn main() {
-      Foo { x: 128 };
+      Foo { x: 42 };
   }
   ```
 
 * Function results, either the final line of a block if it is not
   semicolon-terminated or any expression in a `return` statement
 
-  For example, `128` is coerced to have type `i8` in the following:
+  For example, `42` is coerced to have type `i8` in the following:
 
   ```rust
   fn foo() -> i8 {
-      128
+      42
   }
   ```
 
index 93b84cdedd4cdedab7f36ecc0edde86e9ea8aec6..ffa0ec4917cb3ef02fba42e1cc9171a0124ad576 100644 (file)
 #![feature(unsize)]
 #![feature(drop_in_place)]
 #![feature(fn_traits)]
+#![feature(const_fn)]
 
 #![feature(needs_allocator)]
 
+// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
+// might be unavailable or disabled
+#![cfg_attr(stage0, feature(alloc_system))]
+
 #![cfg_attr(test, feature(test, rustc_private, box_heap))]
 
+#[cfg(stage0)]
+extern crate alloc_system;
+
 // Allow testing this library
 
 #[cfg(test)]
@@ -127,15 +135,6 @@ mod boxed {
 pub mod arc;
 pub mod rc;
 pub mod raw_vec;
+pub mod oom;
 
-/// Common out-of-memory routine
-#[cold]
-#[inline(never)]
-#[unstable(feature = "oom", reason = "not a scrutinized interface",
-           issue = "27700")]
-pub fn oom() -> ! {
-    // FIXME(#14674): This really needs to do something other than just abort
-    //                here, but any printing done must be *guaranteed* to not
-    //                allocate.
-    unsafe { core::intrinsics::abort() }
-}
+pub use oom::oom;
diff --git a/src/liballoc/oom.rs b/src/liballoc/oom.rs
new file mode 100644 (file)
index 0000000..d355d59
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+use core::sync::atomic::{AtomicPtr, Ordering};
+use core::mem;
+use core::intrinsics;
+
+static OOM_HANDLER: AtomicPtr<()> = AtomicPtr::new(default_oom_handler as *mut ());
+
+fn default_oom_handler() -> ! {
+    // The default handler can't do much more since we can't assume the presence
+    // of libc or any way of printing an error message.
+    unsafe { intrinsics::abort() }
+}
+
+/// Common out-of-memory routine
+#[cold]
+#[inline(never)]
+#[unstable(feature = "oom", reason = "not a scrutinized interface",
+           issue = "27700")]
+pub fn oom() -> ! {
+    let value = OOM_HANDLER.load(Ordering::SeqCst);
+    let handler: fn() -> ! = unsafe { mem::transmute(value) };
+    handler();
+}
+
+/// Set a custom handler for out-of-memory conditions
+///
+/// To avoid recursive OOM failures, it is critical that the OOM handler does
+/// not allocate any memory itself.
+#[unstable(feature = "oom", reason = "not a scrutinized interface",
+           issue = "27700")]
+pub fn set_oom_handler(handler: fn() -> !) {
+    OOM_HANDLER.store(handler as *mut (), Ordering::SeqCst);
+}
index 370857287d6e6aea59368b200ddd79eca66b0e21..8b876df32af5245b4b40a417e3cde5b8e62e0465 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Collection types.
 //!
-//! See [std::collections](../std/collections) for a detailed discussion of
+//! See [std::collections](../std/collections/index.html) for a detailed discussion of
 //! collections in Rust.
 
 #![crate_name = "collections"]
index c70aa67366b342edd2fca8a398b86a483306ed45..afcd779ddf19f92db8c6b575b2619905675893a3 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![unstable(feature = "collections_range", reason = "was just added",
-            issue = "27711")]
+#![unstable(feature = "collections_range",
+            reason = "waiting for dust to settle on inclusive ranges",
+            issue = "30877")]
 
 //! Range syntax.
 
index f3bdb0efeef1d82bf72a2e92d76c4d2b43731a9c..766867f284ee1f0c0e5148f7a650b08272501669 100644 (file)
@@ -1384,7 +1384,7 @@ pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
     ///
     /// For iterating from the front, the [`matches()`] method can be used.
     ///
-    /// [`matches`]: #method.matches
+    /// [`matches()`]: #method.matches
     ///
     /// # Examples
     ///
index d2cbcad875f347a5249f547829ca463c424bb431..eb9628d6e39dd7e00975dfff28a0f33758ed0d19 100644 (file)
 //!
 //! [`String`]: struct.String.html
 //! [`ToString`]: trait.ToString.html
+//!
+//! # Examples
+//!
+//! There are multiple ways to create a new `String` from a string literal:
+//!
+//! ```rust
+//! let s = "Hello".to_string();
+//!
+//! let s = String::from("world");
+//! let s: String = "also this".into();
+//! ```
+//!
+//! You can create a new `String` from an existing one by concatenating with
+//! `+`:
+//!
+//! ```rust
+//! let s = "Hello".to_string();
+//!
+//! let message = s + " world!";
+//! ```
+//!
+//! If you have a vector of valid UTF-8 bytes, you can make a `String` out of
+//! it. You can do the reverse too.
+//!
+//! ```rust
+//! let sparkle_heart = vec![240, 159, 146, 150];
+//!
+//! // We know these bytes are valid, so we'll use `unwrap()`.
+//! let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
+//!
+//! assert_eq!("💖", sparkle_heart);
+//!
+//! let bytes = sparkle_heart.into_bytes();
+//!
+//! assert_eq!(bytes, [240, 159, 146, 150]);
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -62,6 +98,7 @@
 /// hello.push_str("orld!");
 /// ```
 ///
+/// [`char`]: ../primitive.char.html
 /// [`push()`]: #method.push
 /// [`push_str()`]: #method.push_str
 ///
 /// ```
 ///
 /// [`as_ptr()`]: #method.as_ptr
-/// [`len()`]: # method.len
-/// [`capacity()`]: # method.capacity
+/// [`len()`]: #method.len
+/// [`capacity()`]: #method.capacity
 ///
 /// If a `String` has enough capacity, adding elements to it will not
 /// re-allocate. For example, consider this program:
@@ -444,7 +481,7 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
     /// Converts a slice of bytes to a `String`, including invalid characters.
     ///
     /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a slice of
-    /// bytes ([`&[u8]`]) is made of bytes, so this function converts between
+    /// bytes ([`&[u8]`][byteslice]) is made of bytes, so this function converts between
     /// the two. Not all byte slices are valid string slices, however: [`&str`]
     /// requires that it is valid UTF-8. During this conversion,
     /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with
@@ -452,7 +489,7 @@ pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
     ///
     /// [`&str`]: ../primitive.str.html
     /// [`u8`]: ../primitive.u8.html
-    /// [`&[u8]`]: ../primitive.slice.html
+    /// [byteslice]: ../primitive.slice.html
     ///
     /// If you are sure that the byte slice is valid UTF-8, and you don't want
     /// to incur the overhead of the conversion, there is an unsafe version
@@ -1311,6 +1348,8 @@ pub fn into_bytes(self) -> Vec<u8> {
     ///
     /// [`Utf8Error`]: ../str/struct.Utf8Error.html
     /// [`std::str`]: ../str/index.html
+    /// [`u8`]: ../primitive.u8.html
+    /// [`&str`]: ../primitive.str.html
     ///
     /// # Examples
     ///
index 628bf654873c7cfc7e8195fbf9d7146d607ef618..4033fea1f8e5d892bd189b9cd8a8098c297869bd 100644 (file)
@@ -1569,7 +1569,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Debug for PhantomData<T> {
+impl<T: ?Sized> Debug for PhantomData<T> {
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.pad("PhantomData")
     }
index c3bea050558035c747d743fa084c928ed26376d8..e3e783329ec812e003d8d6cd915648eac8c86c86 100644 (file)
@@ -1358,7 +1358,7 @@ fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
     /// One of the keys to `collect()`'s power is that many things you might
     /// not think of as 'collections' actually are. For example, a [`String`]
     /// is a collection of [`char`]s. And a collection of [`Result<T, E>`] can
-    /// be thought of as single [`Result<Collection<T>, E>`]. See the examples
+    /// be thought of as single `Result<Collection<T>, E>`. See the examples
     /// below for more.
     ///
     /// [`String`]: ../string/struct.String.html
index f180a513b869d8bf4374cc3af6b0fc12c81c9a79..76214366dc6d4d3cc7a9fe78b51e437ba30acdfc 100644 (file)
@@ -124,7 +124,7 @@ macro_rules! checked_op {
 
 // `Int` + `SignedInt` implemented for signed integers
 macro_rules! int_impl {
-    ($ActualT:ty, $UnsignedT:ty, $BITS:expr,
+    ($ActualT:ident, $UnsignedT:ty, $BITS:expr,
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
@@ -393,7 +393,8 @@ pub fn to_le(self) -> Self {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_add(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $add_with_overflow, self, other)
+            let (a, b) = self.overflowing_add(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer subtraction. Computes `self - other`, returning
@@ -410,7 +411,8 @@ pub fn checked_add(self, other: Self) -> Option<Self> {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_sub(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $sub_with_overflow, self, other)
+            let (a, b) = self.overflowing_sub(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer multiplication. Computes `self * other`, returning
@@ -427,7 +429,8 @@ pub fn checked_sub(self, other: Self) -> Option<Self> {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_mul(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $mul_with_overflow, self, other)
+            let (a, b) = self.overflowing_mul(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer division. Computes `self / other`, returning `None`
@@ -445,14 +448,103 @@ pub fn checked_mul(self, other: Self) -> Option<Self> {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_div(self, other: Self) -> Option<Self> {
-            match other {
-                0    => None,
-               -1 if self == Self::min_value()
-                     => None,
-               other => Some(self / other),
+            if other == 0 {
+                None
+            } else {
+                let (a, b) = self.overflowing_div(other);
+                if b {None} else {Some(a)}
             }
         }
 
+        /// Checked integer remainder. Computes `self % other`, returning `None`
+        /// if `other == 0` or the operation results in underflow or overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.checked_rem(2), Some(1));
+        /// assert_eq!(5i32.checked_rem(0), None);
+        /// assert_eq!(i32::MIN.checked_rem(-1), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_rem(self, other: Self) -> Option<Self> {
+            if other == 0 {
+                None
+            } else {
+                let (a, b) = self.overflowing_rem(other);
+                if b {None} else {Some(a)}
+            }
+        }
+
+        /// Checked negation. Computes `!self`, returning `None` if `self ==
+        /// MIN`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.checked_neg(), Some(-5));
+        /// assert_eq!(i32::MIN.checked_neg(), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_neg(self) -> Option<Self> {
+            let (a, b) = self.overflowing_neg();
+            if b {None} else {Some(a)}
+        }
+
+        /// Checked shift left. Computes `self << rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10i32.checked_shl(4), Some(0x100));
+        /// assert_eq!(0x10i32.checked_shl(33), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_shl(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shl(rhs);
+            if b {None} else {Some(a)}
+        }
+
+        /// Checked shift right. Computes `self >> rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10i32.checked_shr(4), Some(0x1));
+        /// assert_eq!(0x10i32.checked_shr(33), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_shr(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shr(rhs);
+            if b {None} else {Some(a)}
+        }
+
         /// Saturating integer addition. Computes `self + other`, saturating at
         /// the numeric bounds instead of overflowing.
         ///
@@ -468,7 +560,7 @@ pub fn checked_div(self, other: Self) -> Option<Self> {
         #[inline]
         pub fn saturating_add(self, other: Self) -> Self {
             match self.checked_add(other) {
-                Some(x)                       => x,
+                Some(x) => x,
                 None if other >= Self::zero() => Self::max_value(),
                 None => Self::min_value(),
             }
@@ -489,12 +581,40 @@ pub fn saturating_add(self, other: Self) -> Self {
         #[inline]
         pub fn saturating_sub(self, other: Self) -> Self {
             match self.checked_sub(other) {
-                Some(x)                      => x,
+                Some(x) => x,
                 None if other >= Self::zero() => Self::min_value(),
                 None => Self::max_value(),
             }
         }
 
+        /// Saturating integer multiplication. Computes `self * other`,
+        /// saturating at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(100i32.saturating_mul(127), 12700);
+        /// assert_eq!((1i32 << 23).saturating_mul(1 << 23), i32::MAX);
+        /// assert_eq!((-1i32 << 23).saturating_mul(1 << 23), i32::MIN);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn saturating_mul(self, other: Self) -> Self {
+            self.checked_mul(other).unwrap_or_else(|| {
+                if (self < 0 && other < 0) || (self > 0 && other > 0) {
+                    Self::max_value()
+                } else {
+                    Self::min_value()
+                }
+            })
+        }
+
         /// Wrapping (modular) addition. Computes `self + other`,
         /// wrapping around at the boundary of the type.
         ///
@@ -562,6 +682,10 @@ pub fn wrapping_mul(self, rhs: Self) -> Self {
         /// in the type. In such a case, this function returns `MIN`
         /// itself.
         ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
         /// # Examples
         ///
         /// Basic usage:
@@ -584,6 +708,10 @@ pub fn wrapping_div(self, rhs: Self) -> Self {
         /// -1` on a signed type (where `MIN` is the negative
         /// minimal value). In such a case, this function returns `0`.
         ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
         /// # Examples
         ///
         /// Basic usage:
@@ -657,6 +785,230 @@ pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
 
+        /// Calculates `self` + `rhs`
+        ///
+        /// Returns a tuple of the addition along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.overflowing_add(2), (7, false));
+        /// assert_eq!(i32::MAX.overflowing_add(1), (i32::MIN, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $add_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates `self` - `rhs`
+        ///
+        /// Returns a tuple of the subtraction along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.overflowing_sub(2), (3, false));
+        /// assert_eq!(i32::MIN.overflowing_sub(1), (i32::MAX, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $sub_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates the multiplication of `self` and `rhs`.
+        ///
+        /// Returns a tuple of the multiplication along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(5i32.overflowing_mul(2), (10, false));
+        /// assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $mul_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates the divisor when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// occur then self is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.overflowing_div(2), (2, false));
+        /// assert_eq!(i32::MIN.overflowing_div(-1), (i32::MIN, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            if self == Self::min_value() && rhs == -1 {
+                (self, true)
+            } else {
+                (self / rhs, false)
+            }
+        }
+
+        /// Calculates the remainder when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would occur then 0 is returned.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(5i32.overflowing_rem(2), (1, false));
+        /// assert_eq!(i32::MIN.overflowing_rem(-1), (0, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            if self == Self::min_value() && rhs == -1 {
+                (0, true)
+            } else {
+                (self % rhs, false)
+            }
+        }
+
+        /// Negates self, overflowing if this is equal to the minimum value.
+        ///
+        /// Returns a tuple of the negated version of self along with a boolean
+        /// indicating whether an overflow happened. If `self` is the minimum
+        /// value (e.g. `i32::MIN` for values of type `i32`), then the minimum
+        /// value will be returned again and `true` will be returned for an
+        /// overflow happening.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::i32;
+        ///
+        /// assert_eq!(2i32.overflowing_neg(), (-2, false));
+        /// assert_eq!(i32::MIN.overflowing_neg(), (i32::MIN, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_neg(self) -> (Self, bool) {
+            if self == Self::min_value() {
+                (Self::min_value(), true)
+            } else {
+                (-self, false)
+            }
+        }
+
+        /// Shifts self left by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10i32.overflowing_shl(4), (0x100, false));
+        /// assert_eq!(0x10i32.overflowing_shl(36), (0x100, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
+        }
+
+        /// Shifts self right by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10i32.overflowing_shr(4), (0x1, false));
+        /// assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
+        }
+
         /// Raises self to the power of `exp`, using exponentiation by squaring.
         ///
         /// # Examples
@@ -1121,7 +1473,8 @@ pub fn to_le(self) -> Self {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_add(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $add_with_overflow, self, other)
+            let (a, b) = self.overflowing_add(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer subtraction. Computes `self - other`, returning
@@ -1138,7 +1491,8 @@ pub fn checked_add(self, other: Self) -> Option<Self> {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_sub(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $sub_with_overflow, self, other)
+            let (a, b) = self.overflowing_sub(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer multiplication. Computes `self * other`, returning
@@ -1155,7 +1509,8 @@ pub fn checked_sub(self, other: Self) -> Option<Self> {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn checked_mul(self, other: Self) -> Option<Self> {
-            checked_op!($ActualT, $mul_with_overflow, self, other)
+            let (a, b) = self.overflowing_mul(other);
+            if b {None} else {Some(a)}
         }
 
         /// Checked integer division. Computes `self / other`, returning `None`
@@ -1179,6 +1534,69 @@ pub fn checked_div(self, other: Self) -> Option<Self> {
             }
         }
 
+        /// Checked integer remainder. Computes `self % other`, returning `None`
+        /// if `other == 0` or the operation results in underflow or overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(5u32.checked_rem(2), Some(1));
+        /// assert_eq!(5u32.checked_rem(0), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_rem(self, other: Self) -> Option<Self> {
+            if other == 0 {
+                None
+            } else {
+                Some(self % other)
+            }
+        }
+
+        /// Checked shift left. Computes `self << rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10u32.checked_shl(4), Some(0x100));
+        /// assert_eq!(0x10u32.checked_shl(33), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_shl(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shl(rhs);
+            if b {None} else {Some(a)}
+        }
+
+        /// Checked shift right. Computes `self >> rhs`, returning `None`
+        /// if `rhs` is larger than or equal to the number of bits in `self`.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10u32.checked_shr(4), Some(0x1));
+        /// assert_eq!(0x10u32.checked_shr(33), None);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn checked_shr(self, rhs: u32) -> Option<Self> {
+            let (a, b) = self.overflowing_shr(rhs);
+            if b {None} else {Some(a)}
+        }
+
         /// Saturating integer addition. Computes `self + other`, saturating at
         /// the numeric bounds instead of overflowing.
         ///
@@ -1221,6 +1639,27 @@ pub fn saturating_sub(self, other: Self) -> Self {
             }
         }
 
+        /// Saturating integer multiplication. Computes `self * other`,
+        /// saturating at the numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::u32;
+        ///
+        /// assert_eq!(100u32.saturating_mul(127), 12700);
+        /// assert_eq!((1u32 << 23).saturating_mul(1 << 23), u32::MAX);
+        /// ```
+        #[unstable(feature = "wrapping", issue = "27755")]
+        #[inline]
+        pub fn saturating_mul(self, other: Self) -> Self {
+            self.checked_mul(other).unwrap_or(Self::max_value())
+        }
+
         /// Wrapping (modular) addition. Computes `self + other`,
         /// wrapping around at the boundary of the type.
         ///
@@ -1383,6 +1822,211 @@ pub fn wrapping_shr(self, rhs: u32) -> Self {
             self.overflowing_shr(rhs).0
         }
 
+        /// Calculates `self` + `rhs`
+        ///
+        /// Returns a tuple of the addition along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::u32;
+        ///
+        /// assert_eq!(5u32.overflowing_add(2), (7, false));
+        /// assert_eq!(u32::MAX.overflowing_add(1), (0, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $add_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates `self` - `rhs`
+        ///
+        /// Returns a tuple of the subtraction along with a boolean indicating
+        /// whether an arithmetic overflow would occur. If an overflow would
+        /// have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// use std::u32;
+        ///
+        /// assert_eq!(5u32.overflowing_sub(2), (3, false));
+        /// assert_eq!(0u32.overflowing_sub(1), (u32::MAX, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $sub_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates the multiplication of `self` and `rhs`.
+        ///
+        /// Returns a tuple of the multiplication along with a boolean
+        /// indicating whether an arithmetic overflow would occur. If an
+        /// overflow would have occurred then the wrapped value is returned.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(5u32.overflowing_mul(2), (10, false));
+        /// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+            unsafe {
+                let (a, b) = $mul_with_overflow(self as $ActualT,
+                                                rhs as $ActualT);
+                (a as Self, b)
+            }
+        }
+
+        /// Calculates the divisor when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the divisor along with a boolean indicating
+        /// whether an arithmetic overflow would occur. Note that for unsigned
+        /// integers overflow never occurs, so the second value is always
+        /// `false`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(5u32.overflowing_div(2), (2, false));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
+            (self / rhs, false)
+        }
+
+        /// Calculates the remainder when `self` is divided by `rhs`.
+        ///
+        /// Returns a tuple of the remainder after dividing along with a boolean
+        /// indicating whether an arithmetic overflow would occur. Note that for
+        /// unsigned integers overflow never occurs, so the second value is
+        /// always `false`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(5u32.overflowing_rem(2), (1, false));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
+            (self % rhs, false)
+        }
+
+        /// Negates self in an overflowing fashion.
+        ///
+        /// Returns `!self + 1` using wrapping operations to return the value
+        /// that represents the negation of this unsigned value. Note that for
+        /// positive unsigned values overflow always occurs, but negating 0 does
+        /// not overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0u32.overflowing_neg(), (0, false));
+        /// assert_eq!(2u32.overflowing_neg(), (-2i32 as u32, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_neg(self) -> (Self, bool) {
+            ((!self).wrapping_add(1), self != 0)
+        }
+
+        /// Shifts self left by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10u32.overflowing_shl(4), (0x100, false));
+        /// assert_eq!(0x10u32.overflowing_shl(36), (0x100, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
+            (self << (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
+        }
+
+        /// Shifts self right by `rhs` bits.
+        ///
+        /// Returns a tuple of the shifted version of self along with a boolean
+        /// indicating whether the shift value was larger than or equal to the
+        /// number of bits. If the shift value is too large, then value is
+        /// masked (N-1) where N is the number of bits, and this value is then
+        /// used to perform the shift.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(wrapping)]
+        ///
+        /// assert_eq!(0x10u32.overflowing_shr(4), (0x1, false));
+        /// assert_eq!(0x10u32.overflowing_shr(36), (0x1, true));
+        /// ```
+        #[inline]
+        #[unstable(feature = "wrapping", issue = "27755")]
+        pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
+            (self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
+        }
+
         /// Raises self to the power of `exp`, using exponentiation by squaring.
         ///
         /// # Examples
index 0134bcdf1757b2913f6dbcb70b4b13b5157687e3..80bfbe4edda8810dedb47db0085254a450497c89 100644 (file)
@@ -132,7 +132,6 @@ pub struct Options {
     pub prints: Vec<PrintRequest>,
     pub cg: CodegenOptions,
     pub color: ColorConfig,
-    pub show_span: Option<String>,
     pub externs: HashMap<String, Vec<String>>,
     pub crate_name: Option<String>,
     /// An optional name to use as the crate for std during std injection,
@@ -243,7 +242,6 @@ pub fn basic_options() -> Options {
         prints: Vec::new(),
         cg: basic_codegen_options(),
         color: ColorConfig::Auto,
-        show_span: None,
         externs: HashMap::new(),
         crate_name: None,
         alt_std_name: None,
@@ -634,6 +632,8 @@ fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
           "don't clear the resolution tables after analysis"),
     keep_ast: bool = (false, parse_bool,
           "keep the AST after lowering it to HIR"),
+    show_span: Option<String> = (None, parse_opt_string,
+          "show spans for compiler debugging (expr|pat|ty)"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -882,7 +882,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                       `hir` (the HIR), `hir,identified`, or
                       `hir,typed` (HIR with types for each node).",
                      "TYPE"),
-        opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"),
     ]);
     opts
 }
@@ -1123,7 +1122,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         prints: prints,
         cg: cg,
         color: color,
-        show_span: None,
         externs: externs,
         crate_name: crate_name,
         alt_std_name: None,
index d172bfb441358e6ca180ff91b04443c541aec4fb..840260da33086956d30499da09b76782da9453b2 100644 (file)
@@ -428,7 +428,7 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
         println!("Pre-expansion node count:  {}", count_nodes(&krate));
     }
 
-    if let Some(ref s) = sess.opts.show_span {
+    if let Some(ref s) = sess.opts.debugging_opts.show_span {
         syntax::show_span::run(sess.diagnostic(), s, &krate);
     }
 
index 7b8970876f6e3adc7711e9211920ae81971df266..cdac3de3682e57911c104f5df1c15dc5ab813da7 100644 (file)
@@ -138,12 +138,9 @@ macro_rules! do_or_return {($expr: expr) => {
     };
 
     let cstore = Rc::new(CStore::new(token::get_ident_interner()));
-    let mut sess = build_session(sopts, input_file_path, descriptions,
+    let sess = build_session(sopts, input_file_path, descriptions,
                                  cstore.clone());
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    if sess.unstable_options() {
-        sess.opts.show_span = matches.opt_str("show-span");
-    }
     let mut cfg = config::build_configuration(&sess);
     target_features::add_configuration(&mut cfg, &sess);
 
@@ -387,7 +384,7 @@ fn late_callback(&mut self,
     fn build_controller(&mut self, sess: &Session) -> CompileController<'a> {
         let mut control = CompileController::basic();
 
-        if sess.opts.parse_only || sess.opts.show_span.is_some() ||
+        if sess.opts.parse_only || sess.opts.debugging_opts.show_span.is_some() ||
            sess.opts.debugging_opts.ast_json_noexpand {
             control.after_parse.stop = Compilation::Stop;
         }
index 8ed47300a17082ad95370d888330ac7755cf1c6a..2e713a2f50e0fcdb0d5dfe08db3c54f2107f20ab 100644 (file)
@@ -21,7 +21,7 @@
 use Namespace::{TypeNS, ValueNS};
 use NameBindings;
 use {names_to_string, module_to_string};
-use ParentLink::{self, ModuleParentLink, BlockParentLink};
+use ParentLink::{ModuleParentLink, BlockParentLink};
 use Resolver;
 use resolve_imports::Shadowable;
 use {resolve_error, resolve_struct_error, ResolutionError};
@@ -52,7 +52,6 @@
 
 use std::mem::replace;
 use std::ops::{Deref, DerefMut};
-use std::rc::Rc;
 
 // Specifies how duplicates should be handled when adding a child item if
 // another item exists with the same name in some namespace.
@@ -86,7 +85,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
     /// Constructs the reduced graph for the entire crate.
     fn build_reduced_graph(self, krate: &hir::Crate) {
         let mut visitor = BuildReducedGraphVisitor {
-            parent: self.graph_root.clone(),
+            parent: self.graph_root,
             builder: self,
         };
         intravisit::walk_crate(&mut visitor, krate);
@@ -97,12 +96,12 @@ fn build_reduced_graph(self, krate: &hir::Crate) {
     /// Returns the child's corresponding name bindings.
     fn add_child(&self,
                  name: Name,
-                 parent: &Rc<Module>,
+                 parent: Module<'b>,
                  duplicate_checking_mode: DuplicateCheckingMode,
                  // For printing errors
                  sp: Span)
-                 -> NameBindings {
-        self.check_for_conflicts_between_external_crates_and_items(&**parent, name, sp);
+                 -> NameBindings<'b> {
+        self.check_for_conflicts_between_external_crates_and_items(parent, name, sp);
 
         // Add or reuse the child.
         let child = parent.children.borrow().get(&name).cloned();
@@ -178,12 +177,8 @@ fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
         return false;
     }
 
-    fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
-        ModuleParentLink(Rc::downgrade(parent), name)
-    }
-
     /// Constructs the reduced graph for one item.
-    fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
+    fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> Module<'b> {
         let name = item.name;
         let sp = item.span;
         let is_public = item.vis == hir::Public;
@@ -238,7 +233,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                         }
 
                         let subclass = SingleImport(binding, source_name);
-                        self.build_import_directive(&**parent,
+                        self.build_import_directive(parent,
                                                     module_path,
                                                     subclass,
                                                     view_path.span,
@@ -288,7 +283,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                     (module_path.to_vec(), name, rename)
                                 }
                             };
-                            self.build_import_directive(&**parent,
+                            self.build_import_directive(parent,
                                                         module_path,
                                                         SingleImport(rename, name),
                                                         source_item.span,
@@ -298,7 +293,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                         }
                     }
                     ViewPathGlob(_) => {
-                        self.build_import_directive(&**parent,
+                        self.build_import_directive(parent,
                                                     module_path,
                                                     GlobImport,
                                                     view_path.span,
@@ -307,7 +302,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                     shadowable);
                     }
                 }
-                parent.clone()
+                parent
             }
 
             ItemExternCrate(_) => {
@@ -319,32 +314,32 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                         index: CRATE_DEF_INDEX,
                     };
                     self.external_exports.insert(def_id);
-                    let parent_link = ModuleParentLink(Rc::downgrade(parent), name);
+                    let parent_link = ModuleParentLink(parent, name);
                     let def = DefMod(def_id);
-                    let external_module = Module::new(parent_link, Some(def), false, true);
+                    let external_module = self.new_module(parent_link, Some(def), false, true);
 
                     debug!("(build reduced graph for item) found extern `{}`",
                            module_to_string(&*external_module));
-                    self.check_for_conflicts_for_external_crate(&parent, name, sp);
+                    self.check_for_conflicts_for_external_crate(parent, name, sp);
                     parent.external_module_children
                           .borrow_mut()
-                          .insert(name, external_module.clone());
+                          .insert(name, external_module);
                     self.build_reduced_graph_for_external_crate(&external_module);
                 }
-                parent.clone()
+                parent
             }
 
             ItemMod(..) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateTypes, sp);
 
-                let parent_link = self.get_parent_link(parent, name);
+                let parent_link = ModuleParentLink(parent, name);
                 let def = DefMod(self.ast_map.local_def_id(item.id));
-                let module = Module::new(parent_link, Some(def), false, is_public);
+                let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
                 module
             }
 
-            ItemForeignMod(..) => parent.clone(),
+            ItemForeignMod(..) => parent,
 
             // These items live in the value namespace.
             ItemStatic(_, m, _) => {
@@ -354,19 +349,19 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl),
                                            sp,
                                            modifiers);
-                parent.clone()
+                parent
             }
             ItemConst(_, _) => {
                 self.add_child(name, parent, ForbidDuplicateValues, sp)
                     .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers);
-                parent.clone()
+                parent
             }
             ItemFn(_, _, _, _, _, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
 
                 let def = DefFn(self.ast_map.local_def_id(item.id), false);
                 name_bindings.define_value(def, sp, modifiers);
-                parent.clone()
+                parent
             }
 
             // These items live in the type namespace.
@@ -376,11 +371,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                    ForbidDuplicateTypes,
                                                    sp);
 
-                let parent_link = self.get_parent_link(parent, name);
+                let parent_link = ModuleParentLink(parent, name);
                 let def = DefTy(self.ast_map.local_def_id(item.id), false);
-                let module = Module::new(parent_link, Some(def), false, is_public);
+                let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module, sp);
-                parent.clone()
+                parent
             }
 
             ItemEnum(ref enum_definition, _) => {
@@ -389,9 +384,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                    ForbidDuplicateTypes,
                                                    sp);
 
-                let parent_link = self.get_parent_link(parent, name);
+                let parent_link = ModuleParentLink(parent, name);
                 let def = DefTy(self.ast_map.local_def_id(item.id), true);
-                let module = Module::new(parent_link, Some(def), false, is_public);
+                let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
 
                 let variant_modifiers = if is_public {
@@ -404,7 +399,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                     self.build_reduced_graph_for_variant(variant, item_def_id,
                                                          &module, variant_modifiers);
                 }
-                parent.clone()
+                parent
             }
 
             // These items live in both the type and value namespaces.
@@ -444,11 +439,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 let item_def_id = self.ast_map.local_def_id(item.id);
                 self.structs.insert(item_def_id, named_fields);
 
-                parent.clone()
+                parent
             }
 
             ItemDefaultImpl(_, _) |
-            ItemImpl(..) => parent.clone(),
+            ItemImpl(..) => parent,
 
             ItemTrait(_, _, _, ref items) => {
                 let name_bindings = self.add_child(name,
@@ -459,9 +454,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 let def_id = self.ast_map.local_def_id(item.id);
 
                 // Add all the items within to a new module.
-                let parent_link = self.get_parent_link(parent, name);
+                let parent_link = ModuleParentLink(parent, name);
                 let def = DefTrait(def_id);
-                let module_parent = Module::new(parent_link, Some(def), false, is_public);
+                let module_parent = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module_parent.clone(), sp);
 
                 // Add the names of all the items to the trait info.
@@ -494,7 +489,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                     self.trait_item_map.insert((trait_item.name, def_id), trait_item_def_id);
                 }
 
-                parent.clone()
+                parent
             }
         }
     }
@@ -504,7 +499,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
     fn build_reduced_graph_for_variant(&mut self,
                                        variant: &Variant,
                                        item_id: DefId,
-                                       parent: &Rc<Module>,
+                                       parent: Module<'b>,
                                        variant_modifiers: DefModifiers) {
         let name = variant.node.name;
         let is_exported = if variant.node.data.is_struct() {
@@ -534,7 +529,7 @@ fn build_reduced_graph_for_variant(&mut self,
     /// Constructs the reduced graph for one foreign item.
     fn build_reduced_graph_for_foreign_item(&mut self,
                                             foreign_item: &ForeignItem,
-                                            parent: &Rc<Module>) {
+                                            parent: Module<'b>) {
         let name = foreign_item.name;
         let is_public = foreign_item.vis == hir::Public;
         let modifiers = if is_public {
@@ -555,7 +550,7 @@ fn build_reduced_graph_for_foreign_item(&mut self,
         name_bindings.define_value(def, foreign_item.span, modifiers);
     }
 
-    fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
+    fn build_reduced_graph_for_block(&mut self, block: &Block, parent: Module<'b>) -> Module<'b> {
         if self.block_needs_anonymous_module(block) {
             let block_id = block.id;
 
@@ -563,22 +558,22 @@ fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>)
                     {}",
                    block_id);
 
-            let parent_link = BlockParentLink(Rc::downgrade(parent), block_id);
-            let new_module = Module::new(parent_link, None, false, false);
-            parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
+            let parent_link = BlockParentLink(parent, block_id);
+            let new_module = self.new_module(parent_link, None, false, false);
+            parent.anonymous_children.borrow_mut().insert(block_id, new_module);
             new_module
         } else {
-            parent.clone()
+            parent
         }
     }
 
     fn handle_external_def(&mut self,
                            def: Def,
                            vis: Visibility,
-                           child_name_bindings: &NameBindings,
+                           child_name_bindings: &NameBindings<'b>,
                            final_ident: &str,
                            name: Name,
-                           new_parent: &Rc<Module>) {
+                           new_parent: Module<'b>) {
         debug!("(building reduced graph for external crate) building external def {}, priv {:?}",
                final_ident,
                vis);
@@ -609,8 +604,8 @@ fn handle_external_def(&mut self,
                     debug!("(building reduced graph for external crate) building module {} {}",
                            final_ident,
                            is_public);
-                    let parent_link = self.get_parent_link(new_parent, name);
-                    let module = Module::new(parent_link, Some(def), true, is_public);
+                    let parent_link = ModuleParentLink(new_parent, name);
+                    let module = self.new_module(parent_link, Some(def), true, is_public);
                     child_name_bindings.define_module(module, DUMMY_SP);
                 }
             }
@@ -681,8 +676,8 @@ fn handle_external_def(&mut self,
                 }
 
                 // Define a module if necessary.
-                let parent_link = self.get_parent_link(new_parent, name);
-                let module = Module::new(parent_link, Some(def), true, is_public);
+                let parent_link = ModuleParentLink(new_parent, name);
+                let module = self.new_module(parent_link, Some(def), true, is_public);
                 child_name_bindings.define_module(module, DUMMY_SP);
             }
             DefTy(..) | DefAssociatedTy(..) => {
@@ -728,7 +723,7 @@ fn handle_external_def(&mut self,
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_def(&mut self,
-                                                  root: &Rc<Module>,
+                                                  root: Module<'b>,
                                                   xcdef: ChildItem) {
         match xcdef.def {
             DlDef(def) => {
@@ -766,9 +761,9 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
     }
 
     /// Builds the reduced graph rooted at the given external module.
-    fn populate_external_module(&mut self, module: &Rc<Module>) {
+    fn populate_external_module(&mut self, module: Module<'b>) {
         debug!("(populating external module) attempting to populate {}",
-               module_to_string(&**module));
+               module_to_string(module));
 
         let def_id = match module.def_id() {
             None => {
@@ -788,7 +783,7 @@ fn populate_external_module(&mut self, module: &Rc<Module>) {
 
     /// Ensures that the reduced graph rooted at the given external module
     /// is built, building it if it is not.
-    fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
+    fn populate_module_if_necessary(&mut self, module: Module<'b>) {
         if !module.populated.get() {
             self.populate_external_module(module)
         }
@@ -797,7 +792,7 @@ fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
 
     /// Builds the reduced graph rooted at the 'use' directive for an external
     /// crate.
-    fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
+    fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) {
         let root_cnum = root.def_id().unwrap().krate;
         for child in self.session.cstore.crate_top_level_items(root_cnum) {
             self.build_reduced_graph_for_external_crate_def(root, child);
@@ -806,7 +801,7 @@ fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
 
     /// Creates and adds an import directive to the given module.
     fn build_import_directive(&mut self,
-                              module_: &Module,
+                              module_: Module<'b>,
                               module_path: Vec<Name>,
                               subclass: ImportDirectiveSubclass,
                               span: Span,
@@ -866,7 +861,7 @@ fn build_import_directive(&mut self,
 
 struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
     builder: GraphBuilder<'a, 'b, 'tcx>,
-    parent: Rc<Module>,
+    parent: Module<'b>,
 }
 
 impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
@@ -897,6 +892,7 @@ pub fn build_reduced_graph(resolver: &mut Resolver, krate: &hir::Crate) {
     GraphBuilder { resolver: resolver }.build_reduced_graph(krate);
 }
 
-pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
+pub fn populate_module_if_necessary<'a, 'tcx>(resolver: &mut Resolver<'a, 'tcx>,
+                                              module: Module<'a>) {
     GraphBuilder { resolver: resolver }.populate_module_if_necessary(module);
 }
index c7031f72af4639d738a68547f55f79d446938070..9857e83bd621a7ddc47dcee3c60c5950f6fe0458 100644 (file)
@@ -26,6 +26,7 @@
 extern crate log;
 #[macro_use]
 extern crate syntax;
+extern crate arena;
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
@@ -90,7 +91,7 @@
 use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::mem::replace;
-use std::rc::{Rc, Weak};
+use std::rc::Rc;
 
 use resolve_imports::{Target, ImportDirective, ImportResolutionPerNamespace};
 use resolve_imports::Shadowable;
@@ -576,7 +577,7 @@ pub enum Namespace {
 /// a particular namespace. The result is either definitely-resolved,
 /// definitely- unresolved, or unknown.
 #[derive(Clone)]
-enum NamespaceResult {
+enum NamespaceResult<'a> {
     /// Means that resolve hasn't gathered enough information yet to determine
     /// whether the name is bound in this namespace. (That is, it hasn't
     /// resolved all `use` directives yet.)
@@ -586,10 +587,10 @@ enum NamespaceResult {
     UnboundResult,
     /// Means that resolve has determined that the name is bound in the Module
     /// argument, and specified by the NameBinding argument.
-    BoundResult(Rc<Module>, NameBinding),
+    BoundResult(Module<'a>, NameBinding<'a>),
 }
 
-impl NamespaceResult {
+impl<'a> NamespaceResult<'a> {
     fn is_unknown(&self) -> bool {
         match *self {
             UnknownResult => true,
@@ -766,9 +767,9 @@ enum UseLexicalScopeFlag {
     UseLexicalScope,
 }
 
-enum ModulePrefixResult {
+enum ModulePrefixResult<'a> {
     NoPrefixFound,
-    PrefixFound(Rc<Module>, usize),
+    PrefixFound(Module<'a>, usize),
 }
 
 #[derive(Copy, Clone)]
@@ -830,24 +831,24 @@ fn from_def(def: Def) -> Self {
 
 /// The link from a module up to its nearest parent node.
 #[derive(Clone,Debug)]
-enum ParentLink {
+enum ParentLink<'a> {
     NoParentLink,
-    ModuleParentLink(Weak<Module>, Name),
-    BlockParentLink(Weak<Module>, NodeId),
+    ModuleParentLink(Module<'a>, Name),
+    BlockParentLink(Module<'a>, NodeId),
 }
 
 /// One node in the tree of modules.
-pub struct Module {
-    parent_link: ParentLink,
+pub struct ModuleS<'a> {
+    parent_link: ParentLink<'a>,
     def: Cell<Option<Def>>,
     is_public: bool,
 
-    children: RefCell<HashMap<Name, NameBindings>>,
+    children: RefCell<HashMap<Name, NameBindings<'a>>>,
     imports: RefCell<Vec<ImportDirective>>,
 
     // The external module children of this node that were declared with
     // `extern crate`.
-    external_module_children: RefCell<HashMap<Name, Rc<Module>>>,
+    external_module_children: RefCell<HashMap<Name, Module<'a>>>,
 
     // The anonymous children of this node. Anonymous children are pseudo-
     // modules that are implicitly created around items contained within
@@ -863,10 +864,10 @@ pub struct Module {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    anonymous_children: RefCell<NodeMap<Rc<Module>>>,
+    anonymous_children: RefCell<NodeMap<Module<'a>>>,
 
     // The status of resolving each import in this module.
-    import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace>>,
+    import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace<'a>>>,
 
     // The number of unresolved globs that this module exports.
     glob_count: Cell<usize>,
@@ -886,13 +887,11 @@ pub struct Module {
     populated: Cell<bool>,
 }
 
-impl Module {
-    fn new(parent_link: ParentLink,
-           def: Option<Def>,
-           external: bool,
-           is_public: bool)
-           -> Rc<Module> {
-        Rc::new(Module {
+pub type Module<'a> = &'a ModuleS<'a>;
+
+impl<'a> ModuleS<'a> {
+    fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool, is_public: bool) -> Self {
+        ModuleS {
             parent_link: parent_link,
             def: Cell::new(def),
             is_public: is_public,
@@ -906,7 +905,7 @@ fn new(parent_link: ParentLink,
             pub_glob_count: Cell::new(0),
             resolved_import_count: Cell::new(0),
             populated: Cell::new(!external),
-        })
+        }
     }
 
     fn def_id(&self) -> Option<DefId> {
@@ -935,9 +934,7 @@ fn all_imports_resolved(&self) -> bool {
             self.imports.borrow().len() == self.resolved_import_count.get()
         }
     }
-}
 
-impl Module {
     pub fn inc_glob_count(&self) {
         self.glob_count.set(self.glob_count.get() + 1);
     }
@@ -961,7 +958,7 @@ pub fn dec_pub_glob_count(&self) {
     }
 }
 
-impl fmt::Debug for Module {
+impl<'a> fmt::Debug for ModuleS<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "{:?}, {}",
@@ -989,20 +986,20 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 // Records a possibly-private value, type, or module definition.
 #[derive(Debug)]
-struct NsDef {
+struct NsDef<'a> {
     modifiers: DefModifiers, // see note in ImportResolutionPerNamespace about how to use this
-    def_or_module: DefOrModule,
+    def_or_module: DefOrModule<'a>,
     span: Option<Span>,
 }
 
 #[derive(Debug)]
-enum DefOrModule {
+enum DefOrModule<'a> {
     Def(Def),
-    Module(Rc<Module>),
+    Module(Module<'a>),
 }
 
-impl NsDef {
-    fn create_from_module(module: Rc<Module>, span: Option<Span>) -> Self {
+impl<'a> NsDef<'a> {
+    fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
         let modifiers = if module.is_public {
             DefModifiers::PUBLIC
         } else {
@@ -1016,9 +1013,9 @@ fn create_from_def(def: Def, modifiers: DefModifiers, span: Option<Span>) -> Sel
         NsDef { modifiers: modifiers, def_or_module: DefOrModule::Def(def), span: span }
     }
 
-    fn module(&self) -> Option<Rc<Module>> {
+    fn module(&self) -> Option<Module<'a>> {
         match self.def_or_module {
-            DefOrModule::Module(ref module) => Some(module.clone()),
+            DefOrModule::Module(ref module) => Some(module),
             DefOrModule::Def(_) => None,
         }
     }
@@ -1033,18 +1030,18 @@ fn def(&self) -> Option<Def> {
 
 // Records at most one definition that a name in a namespace is bound to
 #[derive(Clone,Debug)]
-pub struct NameBinding(Rc<RefCell<Option<NsDef>>>);
+pub struct NameBinding<'a>(Rc<RefCell<Option<NsDef<'a>>>>);
 
-impl NameBinding {
+impl<'a> NameBinding<'a> {
     fn new() -> Self {
         NameBinding(Rc::new(RefCell::new(None)))
     }
 
-    fn create_from_module(module: Rc<Module>) -> Self {
+    fn create_from_module(module: Module<'a>) -> Self {
         NameBinding(Rc::new(RefCell::new(Some(NsDef::create_from_module(module, None)))))
     }
 
-    fn set(&self, ns_def: NsDef) {
+    fn set(&self, ns_def: NsDef<'a>) {
         *self.0.borrow_mut() = Some(ns_def);
     }
 
@@ -1054,7 +1051,7 @@ fn set_modifiers(&self, modifiers: DefModifiers) {
         }
     }
 
-    fn borrow(&self) -> ::std::cell::Ref<Option<NsDef>> {
+    fn borrow(&self) -> ::std::cell::Ref<Option<NsDef<'a>>> {
         self.0.borrow()
     }
 
@@ -1062,7 +1059,7 @@ fn borrow(&self) -> ::std::cell::Ref<Option<NsDef>> {
     fn def(&self) -> Option<Def> {
         self.borrow().as_ref().and_then(NsDef::def)
     }
-    fn module(&self) -> Option<Rc<Module>> {
+    fn module(&self) -> Option<Module<'a>> {
         self.borrow().as_ref().and_then(NsDef::module)
     }
     fn span(&self) -> Option<Span> {
@@ -1093,20 +1090,20 @@ fn def_and_lp(&self) -> (Def, LastPrivate) {
 // Records the definitions (at most one for each namespace) that a name is
 // bound to.
 #[derive(Clone,Debug)]
-pub struct NameBindings {
-    type_ns: NameBinding, // < Meaning in type namespace.
-    value_ns: NameBinding, // < Meaning in value namespace.
+pub struct NameBindings<'a> {
+    type_ns: NameBinding<'a>, // < Meaning in type namespace.
+    value_ns: NameBinding<'a>, // < Meaning in value namespace.
 }
 
-impl ::std::ops::Index<Namespace> for NameBindings {
-    type Output = NameBinding;
-    fn index(&self, namespace: Namespace) -> &NameBinding {
+impl<'a> ::std::ops::Index<Namespace> for NameBindings<'a> {
+    type Output = NameBinding<'a>;
+    fn index(&self, namespace: Namespace) -> &NameBinding<'a> {
         match namespace { TypeNS => &self.type_ns, ValueNS => &self.value_ns }
     }
 }
 
-impl NameBindings {
-    fn new() -> NameBindings {
+impl<'a> NameBindings<'a> {
+    fn new() -> Self {
         NameBindings {
             type_ns: NameBinding::new(),
             value_ns: NameBinding::new(),
@@ -1114,7 +1111,7 @@ fn new() -> NameBindings {
     }
 
     /// Creates a new module in this set of name bindings.
-    fn define_module(&self, module: Rc<Module>, sp: Span) {
+    fn define_module(&self, module: Module<'a>, sp: Span) {
         self.type_ns.set(NsDef::create_from_module(module, Some(sp)));
     }
 
@@ -1170,7 +1167,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
 
     ast_map: &'a hir_map::Map<'tcx>,
 
-    graph_root: Rc<Module>,
+    graph_root: Module<'a>,
 
     trait_item_map: FnvHashMap<(Name, DefId), DefId>,
 
@@ -1180,7 +1177,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
     unresolved_imports: usize,
 
     // The module that represents the current item scope.
-    current_module: Rc<Module>,
+    current_module: Module<'a>,
 
     // The current set of local scopes, for values.
     // FIXME #4948: Reuse ribs to avoid allocation.
@@ -1226,6 +1223,12 @@ pub struct Resolver<'a, 'tcx: 'a> {
     // The intention is that the callback modifies this flag.
     // Once set, the resolver falls out of the walk, preserving the ribs.
     resolved: bool,
+
+    arenas: &'a ResolverArenas<'a>,
+}
+
+pub struct ResolverArenas<'a> {
+    modules: arena::TypedArena<ModuleS<'a>>,
 }
 
 #[derive(PartialEq)]
@@ -1237,10 +1240,12 @@ enum FallbackChecks {
 impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn new(session: &'a Session,
            ast_map: &'a hir_map::Map<'tcx>,
-           make_glob_map: MakeGlobMap)
+           make_glob_map: MakeGlobMap,
+           arenas: &'a ResolverArenas<'a>)
            -> Resolver<'a, 'tcx> {
         let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
-        let graph_root = Module::new(NoParentLink, Some(DefMod(root_def_id)), false, true);
+        let graph_root = ModuleS::new(NoParentLink, Some(DefMod(root_def_id)), false, true);
+        let graph_root = arenas.modules.alloc(graph_root);
 
         Resolver {
             session: session,
@@ -1249,7 +1254,7 @@ fn new(session: &'a Session,
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
-            graph_root: graph_root.clone(),
+            graph_root: graph_root,
 
             trait_item_map: FnvHashMap(),
             structs: FnvHashMap(),
@@ -1281,9 +1286,25 @@ fn new(session: &'a Session,
 
             callback: None,
             resolved: false,
+
+            arenas: arenas,
+        }
+    }
+
+    fn arenas() -> ResolverArenas<'a> {
+        ResolverArenas {
+            modules: arena::TypedArena::new(),
         }
     }
 
+    fn new_module(&self,
+                  parent_link: ParentLink<'a>,
+                  def: Option<Def>,
+                  external: bool,
+                  is_public: bool) -> Module<'a> {
+        self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public))
+    }
+
     #[inline]
     fn record_import_use(&mut self, import_id: NodeId, name: Name) {
         if !self.make_glob_map {
@@ -1308,7 +1329,7 @@ fn get_trait_name(&self, did: DefId) -> Name {
     }
 
     /// Check that an external crate doesn't collide with items or other external crates.
-    fn check_for_conflicts_for_external_crate(&self, module: &Module, name: Name, span: Span) {
+    fn check_for_conflicts_for_external_crate(&self, module: Module<'a>, name: Name, span: Span) {
         if module.external_module_children.borrow().contains_key(&name) {
             span_err!(self.session,
                       span,
@@ -1328,7 +1349,7 @@ fn check_for_conflicts_for_external_crate(&self, module: &Module, name: Name, sp
 
     /// Checks that the names of items don't collide with external crates.
     fn check_for_conflicts_between_external_crates_and_items(&self,
-                                                             module: &Module,
+                                                             module: Module<'a>,
                                                              name: Name,
                                                              span: Span) {
         if module.external_module_children.borrow().contains_key(&name) {
@@ -1338,19 +1359,20 @@ fn check_for_conflicts_between_external_crates_and_items(&self,
 
     /// Resolves the given module path from the given root `module_`.
     fn resolve_module_path_from_root(&mut self,
-                                     module_: Rc<Module>,
+                                     module_: Module<'a>,
                                      module_path: &[Name],
                                      index: usize,
                                      span: Span,
                                      name_search_type: NameSearchType,
                                      lp: LastPrivate)
-                                     -> ResolveResult<(Rc<Module>, LastPrivate)> {
-        fn search_parent_externals(needle: Name, module: &Rc<Module>) -> Option<Rc<Module>> {
+                                     -> ResolveResult<(Module<'a>, LastPrivate)> {
+        fn search_parent_externals<'a>(needle: Name, module: Module<'a>)
+                                       -> Option<Module<'a>> {
             match module.external_module_children.borrow().get(&needle) {
-                Some(_) => Some(module.clone()),
+                Some(_) => Some(module),
                 None => match module.parent_link {
                     ModuleParentLink(ref parent, _) => {
-                        search_parent_externals(needle, &parent.upgrade().unwrap())
+                        search_parent_externals(needle, parent)
                     }
                     _ => None,
                 },
@@ -1367,14 +1389,14 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>) -> Option<Rc<Modul
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index];
-            match self.resolve_name_in_module(search_module.clone(),
+            match self.resolve_name_in_module(search_module,
                                               name,
                                               TypeNS,
                                               name_search_type,
                                               false) {
                 Failed(None) => {
                     let segment_name = name.as_str();
-                    let module_name = module_to_string(&*search_module);
+                    let module_name = module_to_string(search_module);
                     let mut span = span;
                     let msg = if "???" == &module_name[..] {
                         span.hi = span.lo + Pos::from_usize(segment_name.len());
@@ -1445,12 +1467,12 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>) -> Option<Rc<Modul
     /// On success, returns the resolved module, and the closest *private*
     /// module found to the destination when resolving this path.
     fn resolve_module_path(&mut self,
-                           module_: Rc<Module>,
+                           module_: Module<'a>,
                            module_path: &[Name],
                            use_lexical_scope: UseLexicalScopeFlag,
                            span: Span,
                            name_search_type: NameSearchType)
-                           -> ResolveResult<(Rc<Module>, LastPrivate)> {
+                           -> ResolveResult<(Module<'a>, LastPrivate)> {
         let module_path_len = module_path.len();
         assert!(module_path_len > 0);
 
@@ -1459,7 +1481,7 @@ fn resolve_module_path(&mut self,
                module_to_string(&*module_));
 
         // Resolve the module prefix, if any.
-        let module_prefix_result = self.resolve_module_prefix(module_.clone(), module_path);
+        let module_prefix_result = self.resolve_module_prefix(module_, module_path);
 
         let search_module;
         let start_index;
@@ -1495,7 +1517,7 @@ fn resolve_module_path(&mut self,
                     DontUseLexicalScope => {
                         // This is a crate-relative path. We will start the
                         // resolution process at index zero.
-                        search_module = self.graph_root.clone();
+                        search_module = self.graph_root;
                         start_index = 0;
                         last_private = LastMod(AllPublic);
                     }
@@ -1519,7 +1541,7 @@ fn resolve_module_path(&mut self,
                 }
             }
             Success(PrefixFound(ref containing_module, index)) => {
-                search_module = containing_module.clone();
+                search_module = containing_module;
                 start_index = index;
                 last_private = LastMod(DependsOn(containing_module.def_id()
                                                                   .unwrap()));
@@ -1537,11 +1559,11 @@ fn resolve_module_path(&mut self,
     /// Invariant: This must only be called during main resolution, not during
     /// import resolution.
     fn resolve_item_in_lexical_scope(&mut self,
-                                     module_: Rc<Module>,
+                                     module_: Module<'a>,
                                      name: Name,
                                      namespace: Namespace,
                                      record_used: bool)
-                                     -> ResolveResult<(Target, bool)> {
+                                     -> ResolveResult<(Target<'a>, bool)> {
         debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
                name,
                namespace,
@@ -1554,7 +1576,7 @@ fn resolve_item_in_lexical_scope(&mut self,
         match module_.children.borrow().get(&name) {
             Some(name_bindings) if name_bindings[namespace].defined() => {
                 debug!("top name bindings succeeded");
-                return Success((Target::new(module_.clone(),
+                return Success((Target::new(module_,
                                             name_bindings[namespace].clone(),
                                             Shadowable::Never),
                                 false));
@@ -1594,9 +1616,8 @@ fn resolve_item_in_lexical_scope(&mut self,
 
         // Search for external modules.
         if namespace == TypeNS {
-            // FIXME (21114): In principle unclear `child` *has* to be lifted.
-            let child = module_.external_module_children.borrow().get(&name).cloned();
-            if let Some(module) = child {
+            let children = module_.external_module_children.borrow();
+            if let Some(module) = children.get(&name) {
                 let name_binding = NameBinding::create_from_module(module);
                 debug!("lower name bindings succeeded");
                 return Success((Target::new(module_, name_binding, Shadowable::Never),
@@ -1608,7 +1629,7 @@ fn resolve_item_in_lexical_scope(&mut self,
         let mut search_module = module_;
         loop {
             // Go to the next parent.
-            match search_module.parent_link.clone() {
+            match search_module.parent_link {
                 NoParentLink => {
                     // No more parents. This module was unresolved.
                     debug!("(resolving item in lexical scope) unresolved module");
@@ -1621,16 +1642,16 @@ fn resolve_item_in_lexical_scope(&mut self,
                                 searching through module parents");
                             return Failed(None);
                     } else {
-                        search_module = parent_module_node.upgrade().unwrap();
+                        search_module = parent_module_node;
                     }
                 }
-                BlockParentLink(ref parent_module_node, _) => {
-                    search_module = parent_module_node.upgrade().unwrap();
+                BlockParentLink(parent_module_node, _) => {
+                    search_module = parent_module_node;
                 }
             }
 
             // Resolve the name in the parent module.
-            match self.resolve_name_in_module(search_module.clone(),
+            match self.resolve_name_in_module(search_module,
                                               name,
                                               namespace,
                                               PathSearch,
@@ -1657,9 +1678,9 @@ fn resolve_item_in_lexical_scope(&mut self,
 
     /// Resolves a module name in the current lexical scope.
     fn resolve_module_in_lexical_scope(&mut self,
-                                       module_: Rc<Module>,
+                                       module_: Module<'a>,
                                        name: Name)
-                                       -> ResolveResult<Rc<Module>> {
+                                       -> ResolveResult<Module<'a>> {
         // If this module is an anonymous module, resolve the item in the
         // lexical scope. Otherwise, resolve the item from the crate root.
         let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
@@ -1685,14 +1706,14 @@ fn resolve_module_in_lexical_scope(&mut self,
     }
 
     /// Returns the nearest normal module parent of the given module.
-    fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>) -> Option<Rc<Module>> {
+    fn get_nearest_normal_module_parent(&mut self, module_: Module<'a>) -> Option<Module<'a>> {
         let mut module_ = module_;
         loop {
-            match module_.parent_link.clone() {
+            match module_.parent_link {
                 NoParentLink => return None,
                 ModuleParentLink(new_module, _) |
                 BlockParentLink(new_module, _) => {
-                    let new_module = new_module.upgrade().unwrap();
+                    let new_module = new_module;
                     if new_module.is_normal() {
                         return Some(new_module);
                     }
@@ -1704,11 +1725,11 @@ fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>) -> Option<Rc
 
     /// Returns the nearest normal module parent of the given module, or the
     /// module itself if it is a normal module.
-    fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>) -> Rc<Module> {
+    fn get_nearest_normal_module_parent_or_self(&mut self, module_: Module<'a>) -> Module<'a> {
         if module_.is_normal() {
             return module_;
         }
-        match self.get_nearest_normal_module_parent(module_.clone()) {
+        match self.get_nearest_normal_module_parent(module_) {
             None => module_,
             Some(new_module) => new_module,
         }
@@ -1718,9 +1739,9 @@ fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>) -> R
     /// (b) some chain of `super::`.
     /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
     fn resolve_module_prefix(&mut self,
-                             module_: Rc<Module>,
+                             module_: Module<'a>,
                              module_path: &[Name])
-                             -> ResolveResult<ModulePrefixResult> {
+                             -> ResolveResult<ModulePrefixResult<'a>> {
         // Start at the current module if we see `self` or `super`, or at the
         // top of the crate otherwise.
         let mut i = match &*module_path[0].as_str() {
@@ -1756,12 +1777,12 @@ fn resolve_module_prefix(&mut self,
     /// The boolean returned on success is an indicator of whether this lookup
     /// passed through a public re-export proxy.
     fn resolve_name_in_module(&mut self,
-                              module_: Rc<Module>,
+                              module_: Module<'a>,
                               name: Name,
                               namespace: Namespace,
                               name_search_type: NameSearchType,
                               allow_private_imports: bool)
-                              -> ResolveResult<(Target, bool)> {
+                              -> ResolveResult<(Target<'a>, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                name,
                module_to_string(&*module_));
@@ -1769,10 +1790,11 @@ fn resolve_name_in_module(&mut self,
         // First, check the direct children of the module.
         build_reduced_graph::populate_module_if_necessary(self, &module_);
 
-        match module_.children.borrow().get(&name) {
+        let children = module_.children.borrow();
+        match children.get(&name) {
             Some(name_bindings) if name_bindings[namespace].defined() => {
                 debug!("(resolving name in module) found node as child");
-                return Success((Target::new(module_.clone(),
+                return Success((Target::new(module_,
                                             name_bindings[namespace].clone(),
                                             Shadowable::Never),
                                 false));
@@ -1791,7 +1813,8 @@ fn resolve_name_in_module(&mut self,
         }
 
         // Check the list of resolved imports.
-        match module_.import_resolutions.borrow().get(&name) {
+        let children = module_.import_resolutions.borrow();
+        match children.get(&name) {
             Some(import_resolution) if allow_private_imports ||
                                        import_resolution[namespace].is_public => {
 
@@ -1823,9 +1846,8 @@ fn resolve_name_in_module(&mut self,
 
         // Finally, search through external children.
         if namespace == TypeNS {
-            // FIXME (21114): In principle unclear `child` *has* to be lifted.
-            let child = module_.external_module_children.borrow().get(&name).cloned();
-            if let Some(module) = child {
+            let children = module_.external_module_children.borrow();
+            if let Some(module) = children.get(&name) {
                 let name_binding = NameBinding::create_from_module(module);
                 return Success((Target::new(module_, name_binding, Shadowable::Never),
                                 false));
@@ -1837,7 +1859,7 @@ fn resolve_name_in_module(&mut self,
         return Failed(None);
     }
 
-    fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
+    fn report_unresolved_imports(&mut self, module_: Module<'a>) {
         let index = module_.resolved_import_count.get();
         let imports = module_.imports.borrow();
         let import_count = imports.len();
@@ -1862,7 +1884,7 @@ fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
         }
 
         for (_, module_) in module_.anonymous_children.borrow().iter() {
-            self.report_unresolved_imports(module_.clone());
+            self.report_unresolved_imports(module_);
         }
     }
 
@@ -1887,7 +1909,7 @@ fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
     fn with_scope<F>(&mut self, name: Option<Name>, f: F)
         where F: FnOnce(&mut Resolver)
     {
-        let orig_module = self.current_module.clone();
+        let orig_module = self.current_module;
 
         // Move down in the graph.
         match name {
@@ -2475,14 +2497,14 @@ fn resolve_block(&mut self, block: &Block) {
         self.value_ribs.push(Rib::new(NormalRibKind));
 
         // Move down in the graph, if there's an anonymous module rooted here.
-        let orig_module = self.current_module.clone();
+        let orig_module = self.current_module;
         match orig_module.anonymous_children.borrow().get(&block.id) {
             None => {
                 // Nothing to do.
             }
             Some(anonymous_module) => {
                 debug!("(resolving block) found anonymous module, moving down");
-                self.current_module = anonymous_module.clone();
+                self.current_module = anonymous_module;
             }
         }
 
@@ -2871,7 +2893,7 @@ fn resolve_bare_identifier_pattern(&mut self,
                                        name: Name,
                                        span: Span)
                                        -> BareIdentifierPatternResolution {
-        let module = self.current_module.clone();
+        let module = self.current_module;
         match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
             Success((target, _)) => {
                 debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
@@ -3135,7 +3157,7 @@ fn resolve_module_relative_path(&mut self,
 
         let containing_module;
         let last_private;
-        let current_module = self.current_module.clone();
+        let current_module = self.current_module;
         match self.resolve_module_path(current_module,
                                        &module_path[..],
                                        UseLexicalScope,
@@ -3162,7 +3184,7 @@ fn resolve_module_relative_path(&mut self,
         }
 
         let name = segments.last().unwrap().identifier.name;
-        let def = match self.resolve_name_in_module(containing_module.clone(),
+        let def = match self.resolve_name_in_module(containing_module,
                                                     name,
                                                     namespace,
                                                     NameSearchType::PathSearch,
@@ -3193,7 +3215,7 @@ fn resolve_crate_relative_path(&mut self,
                                   .map(|ps| ps.identifier.name)
                                   .collect::<Vec<_>>();
 
-        let root_module = self.graph_root.clone();
+        let root_module = self.graph_root;
 
         let containing_module;
         let last_private;
@@ -3283,7 +3305,7 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
                                              record_used: bool)
                                              -> Option<Def> {
         // Check the items.
-        let module = self.current_module.clone();
+        let module = self.current_module;
         match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
             Success((target, _)) => {
                 match target.binding.def() {
@@ -3345,11 +3367,11 @@ fn extract_path_and_node_id(t: &Ty,
             }
         }
 
-        fn get_module(this: &mut Resolver,
-                      span: Span,
-                      name_path: &[ast::Name])
-                      -> Option<Rc<Module>> {
-            let root = this.current_module.clone();
+        fn get_module<'a, 'tcx>(this: &mut Resolver<'a, 'tcx>,
+                                span: Span,
+                                name_path: &[ast::Name])
+                                -> Option<Module<'a>> {
+            let root = this.current_module;
             let last_name = name_path.last().unwrap();
 
             if name_path.len() == 1 {
@@ -3603,7 +3625,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                     let name_path = path.segments.iter()
                                                         .map(|seg| seg.identifier.name)
                                                         .collect::<Vec<_>>();
-                                    let current_module = self.current_module.clone();
+                                    let current_module = self.current_module;
 
                                     match self.resolve_module_path(current_module,
                                                    &name_path[..],
@@ -3725,7 +3747,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
         }
 
         let mut found_traits = Vec::new();
-        let mut search_module = self.current_module.clone();
+        let mut search_module = self.current_module;
         loop {
             // Look for the current trait.
             match self.current_trait_ref {
@@ -3778,10 +3800,10 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                 }
             }
 
-            match search_module.parent_link.clone() {
+            match search_module.parent_link {
                 NoParentLink | ModuleParentLink(..) => break,
                 BlockParentLink(parent_module, _) => {
-                    search_module = parent_module.upgrade().unwrap();
+                    search_module = parent_module;
                 }
             }
         }
@@ -3828,7 +3850,7 @@ fn enforce_default_binding_mode(&mut self,
     //
 
     #[allow(dead_code)]   // useful for debugging
-    fn dump_module(&mut self, module_: Rc<Module>) {
+    fn dump_module(&mut self, module_: Module<'a>) {
         debug!("Dump of module `{}`:", module_to_string(&*module_));
 
         debug!("Children:");
@@ -3891,20 +3913,20 @@ fn path_names_to_string(path: &Path, depth: usize) -> String {
 }
 
 /// A somewhat inefficient routine to obtain the name of a module.
-fn module_to_string(module: &Module) -> String {
+fn module_to_string<'a>(module: Module<'a>) -> String {
     let mut names = Vec::new();
 
-    fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
+    fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
         match module.parent_link {
             NoParentLink => {}
             ModuleParentLink(ref module, name) => {
                 names.push(name);
-                collect_mod(names, &*module.upgrade().unwrap());
+                collect_mod(names, module);
             }
             BlockParentLink(ref module, _) => {
                 // danger, shouldn't be ident?
                 names.push(special_idents::opaque.name);
-                collect_mod(names, &*module.upgrade().unwrap());
+                collect_mod(names, module);
             }
         }
     }
@@ -3946,7 +3968,8 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
                                make_glob_map: MakeGlobMap)
                                -> CrateMap {
     let krate = ast_map.krate();
-    let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, None);
+    let arenas = Resolver::arenas();
+    let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas, None);
 
     resolver.resolve_crate(krate);
 
@@ -3978,9 +4001,10 @@ pub fn create_resolver<'a, 'tcx>(session: &'a Session,
                                  ast_map: &'a hir_map::Map<'tcx>,
                                  krate: &'a Crate,
                                  make_glob_map: MakeGlobMap,
+                                 arenas: &'a ResolverArenas<'a>,
                                  callback: Option<Box<Fn(hir_map::Node, &mut bool) -> bool>>)
                                  -> Resolver<'a, 'tcx> {
-    let mut resolver = Resolver::new(session, ast_map, make_glob_map);
+    let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas);
 
     resolver.callback = callback;
 
index 59cf83e91d2da68bc13f4997fa58af3b160abeb2..13f4348f79522052aa2b735df00d24be3f055798 100644 (file)
@@ -28,7 +28,6 @@
 use syntax::ast;
 
 use std::ops::{Deref, DerefMut};
-use std::rc::Rc;
 
 struct ExportRecorder<'a, 'b: 'a, 'tcx: 'b> {
     resolver: &'a mut Resolver<'b, 'tcx>,
@@ -50,7 +49,7 @@ fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
-    fn record_exports_for_module_subtree(&mut self, module_: Rc<Module>) {
+    fn record_exports_for_module_subtree(&mut self, module_: Module<'b>) {
         // If this isn't a local krate, then bail out. We don't need to record
         // exports for nonlocal crates.
 
@@ -59,23 +58,23 @@ fn record_exports_for_module_subtree(&mut self, module_: Rc<Module>) {
                 // OK. Continue.
                 debug!("(recording exports for module subtree) recording exports for local \
                         module `{}`",
-                       module_to_string(&*module_));
+                       module_to_string(module_));
             }
             None => {
                 // Record exports for the root module.
                 debug!("(recording exports for module subtree) recording exports for root module \
                         `{}`",
-                       module_to_string(&*module_));
+                       module_to_string(module_));
             }
             Some(_) => {
                 // Bail out.
                 debug!("(recording exports for module subtree) not recording exports for `{}`",
-                       module_to_string(&*module_));
+                       module_to_string(module_));
                 return;
             }
         }
 
-        self.record_exports_for_module(&*module_);
+        self.record_exports_for_module(module_);
         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
 
         for (_, child_name_bindings) in module_.children.borrow().iter() {
@@ -90,11 +89,11 @@ fn record_exports_for_module_subtree(&mut self, module_: Rc<Module>) {
         }
 
         for (_, child_module) in module_.anonymous_children.borrow().iter() {
-            self.record_exports_for_module_subtree(child_module.clone());
+            self.record_exports_for_module_subtree(child_module);
         }
     }
 
-    fn record_exports_for_module(&mut self, module_: &Module) {
+    fn record_exports_for_module(&mut self, module_: Module<'b>) {
         let mut exports = Vec::new();
 
         self.add_exports_for_module(&mut exports, module_);
@@ -128,7 +127,7 @@ fn add_export_of_namebinding(&mut self,
         }
     }
 
-    fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module) {
+    fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: Module<'b>) {
         for (name, import_resolution) in module_.import_resolutions.borrow().iter() {
             let xs = [TypeNS, ValueNS];
             for &ns in &xs {
@@ -150,6 +149,6 @@ fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module
 
 pub fn record(resolver: &mut Resolver) {
     let mut recorder = ExportRecorder { resolver: resolver };
-    let root_module = recorder.graph_root.clone();
+    let root_module = recorder.graph_root;
     recorder.record_exports_for_module_subtree(root_module);
 }
index 40bf55efde645eb31e8d45c8fe733015a46d066a..53d1b888d8e87a5b0f8c3bfa837efafe01141178 100644 (file)
@@ -36,7 +36,6 @@
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use std::mem::replace;
-use std::rc::Rc;
 
 /// Contains data for specific types of import directives.
 #[derive(Copy, Clone,Debug)]
@@ -84,17 +83,15 @@ pub fn new(module_path: Vec<Name>,
 
 /// The item that an import resolves to.
 #[derive(Clone,Debug)]
-pub struct Target {
-    pub target_module: Rc<Module>,
-    pub binding: NameBinding,
+pub struct Target<'a> {
+    pub target_module: Module<'a>,
+    pub binding: NameBinding<'a>,
     pub shadowable: Shadowable,
 }
 
-impl Target {
-    pub fn new(target_module: Rc<Module>,
-               binding: NameBinding,
-               shadowable: Shadowable)
-               -> Target {
+impl<'a> Target<'a> {
+    pub fn new(target_module: Module<'a>, binding: NameBinding<'a>, shadowable: Shadowable)
+               -> Self {
         Target {
             target_module: target_module,
             binding: binding,
@@ -109,44 +106,44 @@ pub fn new(target_module: Rc<Module>,
 /// and for each namespace, it records the `use` directive importing the name in the namespace
 /// and the `Target` to which the name in the namespace resolves (if applicable).
 /// Different `use` directives may import the same name in different namespaces.
-pub struct ImportResolutionPerNamespace {
+pub struct ImportResolutionPerNamespace<'a> {
     // When outstanding_references reaches zero, outside modules can count on the targets being
     // correct. Before then, all bets are off; future `use` directives could override the name.
     // Since shadowing is forbidden, the only way outstanding_references > 1 in a legal program
     // is if the name is imported by exactly two `use` directives, one of which resolves to a
     // value and the other of which resolves to a type.
     pub outstanding_references: usize,
-    pub type_ns: ImportResolution,
-    pub value_ns: ImportResolution,
+    pub type_ns: ImportResolution<'a>,
+    pub value_ns: ImportResolution<'a>,
 }
 
 /// Records what we know about an imported name in a namespace (see `ImportResolutionPerNamespace`).
 #[derive(Clone,Debug)]
-pub struct ImportResolution {
+pub struct ImportResolution<'a> {
     /// Whether the name in the namespace was imported with a `use` or a `pub use`.
     pub is_public: bool,
 
     /// Resolution of the name in the namespace
-    pub target: Option<Target>,
+    pub target: Option<Target<'a>>,
 
     /// The source node of the `use` directive
     pub id: NodeId,
 }
 
-impl ::std::ops::Index<Namespace> for ImportResolutionPerNamespace {
-    type Output = ImportResolution;
-    fn index(&self, ns: Namespace) -> &ImportResolution {
+impl<'a> ::std::ops::Index<Namespace> for ImportResolutionPerNamespace<'a> {
+    type Output = ImportResolution<'a>;
+    fn index(&self, ns: Namespace) -> &ImportResolution<'a> {
         match ns { TypeNS => &self.type_ns, ValueNS => &self.value_ns }
     }
 }
 
-impl ::std::ops::IndexMut<Namespace> for ImportResolutionPerNamespace {
-    fn index_mut(&mut self, ns: Namespace) -> &mut ImportResolution {
+impl<'a> ::std::ops::IndexMut<Namespace> for ImportResolutionPerNamespace<'a> {
+    fn index_mut(&mut self, ns: Namespace) -> &mut ImportResolution<'a> {
         match ns { TypeNS => &mut self.type_ns, ValueNS => &mut self.value_ns }
     }
 }
 
-impl ImportResolutionPerNamespace {
+impl<'a> ImportResolutionPerNamespace<'a> {
     pub fn new(id: NodeId, is_public: bool) -> Self {
         let resolution = ImportResolution { id: id, is_public: is_public, target: None };
         ImportResolutionPerNamespace {
@@ -191,8 +188,8 @@ fn resolve_imports(&mut self) {
                    i,
                    self.resolver.unresolved_imports);
 
-            let module_root = self.resolver.graph_root.clone();
-            let errors = self.resolve_imports_for_module_subtree(module_root.clone());
+            let module_root = self.resolver.graph_root;
+            let errors = self.resolve_imports_for_module_subtree(module_root);
 
             if self.resolver.unresolved_imports == 0 {
                 debug!("(resolving imports) success");
@@ -225,13 +222,13 @@ fn resolve_imports(&mut self) {
     /// Attempts to resolve imports for the given module and all of its
     /// submodules.
     fn resolve_imports_for_module_subtree(&mut self,
-                                          module_: Rc<Module>)
+                                          module_: Module<'b>)
                                           -> Vec<ImportResolvingError> {
         let mut errors = Vec::new();
         debug!("(resolving imports for module subtree) resolving {}",
                module_to_string(&*module_));
-        let orig_module = replace(&mut self.resolver.current_module, module_.clone());
-        errors.extend(self.resolve_imports_for_module(module_.clone()));
+        let orig_module = replace(&mut self.resolver.current_module, module_);
+        errors.extend(self.resolve_imports_for_module(module_));
         self.resolver.current_module = orig_module;
 
         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
@@ -247,14 +244,14 @@ fn resolve_imports_for_module_subtree(&mut self,
         }
 
         for (_, child_module) in module_.anonymous_children.borrow().iter() {
-            errors.extend(self.resolve_imports_for_module_subtree(child_module.clone()));
+            errors.extend(self.resolve_imports_for_module_subtree(child_module));
         }
 
         errors
     }
 
     /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: Rc<Module>) -> Vec<ImportResolvingError> {
+    fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec<ImportResolvingError> {
         let mut errors = Vec::new();
 
         if module.all_imports_resolved() {
@@ -268,7 +265,7 @@ fn resolve_imports_for_module(&mut self, module: Rc<Module>) -> Vec<ImportResolv
         let mut indeterminate_imports = Vec::new();
         while module.resolved_import_count.get() + indeterminate_imports.len() < import_count {
             let import_index = module.resolved_import_count.get();
-            match self.resolve_import_for_module(module.clone(), &imports[import_index]) {
+            match self.resolve_import_for_module(module, &imports[import_index]) {
                 ResolveResult::Failed(err) => {
                     let import_directive = &imports[import_index];
                     let (span, help) = match err {
@@ -306,7 +303,7 @@ fn resolve_imports_for_module(&mut self, module: Rc<Module>) -> Vec<ImportResolv
     /// currently-unresolved imports, or success if we know the name exists.
     /// If successful, the resolved bindings are written into the module.
     fn resolve_import_for_module(&mut self,
-                                 module_: Rc<Module>,
+                                 module_: Module<'b>,
                                  import_directive: &ImportDirective)
                                  -> ResolveResult<()> {
         let mut resolution_result = ResolveResult::Failed(None);
@@ -319,9 +316,9 @@ fn resolve_import_for_module(&mut self,
         // First, resolve the module path for the directive, if necessary.
         let container = if module_path.is_empty() {
             // Use the crate root.
-            Some((self.resolver.graph_root.clone(), LastMod(AllPublic)))
+            Some((self.resolver.graph_root, LastMod(AllPublic)))
         } else {
-            match self.resolver.resolve_module_path(module_.clone(),
+            match self.resolver.resolve_module_path(module_,
                                                     &module_path[..],
                                                     UseLexicalScopeFlag::DontUseLexicalScope,
                                                     import_directive.span,
@@ -399,8 +396,8 @@ fn resolve_import_for_module(&mut self,
     }
 
     fn resolve_single_import(&mut self,
-                             module_: &Module,
-                             target_module: Rc<Module>,
+                             module_: Module<'b>,
+                             target_module: Module<'b>,
                              target: Name,
                              source: Name,
                              directive: &ImportDirective,
@@ -447,7 +444,7 @@ fn resolve_single_import(&mut self,
                 let mut pub_err = false;
                 if child_name_bindings.value_ns.defined() {
                     debug!("(resolving single import) found value binding");
-                    value_result = BoundResult(target_module.clone(),
+                    value_result = BoundResult(target_module,
                                                child_name_bindings.value_ns.clone());
                     if directive.is_public && !child_name_bindings.value_ns.is_public() {
                         let msg = format!("`{}` is private, and cannot be reexported", source);
@@ -473,7 +470,7 @@ fn resolve_single_import(&mut self,
                 }
                 if child_name_bindings.type_ns.defined() {
                     debug!("(resolving single import) found type binding");
-                    type_result = BoundResult(target_module.clone(),
+                    type_result = BoundResult(target_module,
                                               child_name_bindings.type_ns.clone());
                     if !pub_err && directive.is_public &&
                        !child_name_bindings.type_ns.is_public() {
@@ -543,11 +540,11 @@ fn resolve_single_import(&mut self,
                     }
                     Some(import_resolution) if import_resolution.outstanding_references == 0 => {
 
-                        fn get_binding(this: &mut Resolver,
-                                       import_resolution: &ImportResolutionPerNamespace,
-                                       namespace: Namespace,
-                                       source: Name)
-                                       -> NamespaceResult {
+                        fn get_binding<'a>(this: &mut Resolver,
+                                           import_resolution: &ImportResolutionPerNamespace<'a>,
+                                           namespace: Namespace,
+                                           source: Name)
+                                           -> NamespaceResult<'a> {
 
                             // Import resolutions must be declared with "pub"
                             // in order to be exported.
@@ -640,7 +637,7 @@ fn get_binding(this: &mut Resolver,
         match type_result {
             BoundResult(..) => {}
             _ => {
-                match target_module.external_module_children.borrow_mut().get(&source).cloned() {
+                match target_module.external_module_children.borrow_mut().get(&source) {
                     None => {} // Continue.
                     Some(module) => {
                         debug!("(resolving single import) found external module");
@@ -652,7 +649,7 @@ fn get_binding(this: &mut Resolver,
                             _ => {}
                         }
                         let name_binding = NameBinding::create_from_module(module);
-                        type_result = BoundResult(target_module.clone(), name_binding);
+                        type_result = BoundResult(target_module, name_binding);
                         type_used_public = true;
                     }
                 }
@@ -685,7 +682,7 @@ fn get_binding(this: &mut Resolver,
                                                              target);
 
                         import_resolution[namespace] = ImportResolution {
-                            target: Some(Target::new(target_module.clone(),
+                            target: Some(Target::new(target_module,
                                                      name_binding.clone(),
                                                      directive.shadowable)),
                             id: directive.id,
@@ -777,8 +774,8 @@ fn get_binding(this: &mut Resolver,
     // that exports nothing is valid). target_module is the module we are
     // actually importing, i.e., `foo` in `use foo::*`.
     fn resolve_glob_import(&mut self,
-                           module_: &Module,
-                           target_module: Rc<Module>,
+                           module_: Module<'b>,
+                           target_module: Module<'b>,
                            import_directive: &ImportDirective,
                            lp: LastPrivate)
                            -> ResolveResult<()> {
@@ -841,7 +838,7 @@ fn resolve_glob_import(&mut self,
 
         for (&name, name_bindings) in target_module.children.borrow().iter() {
             self.merge_import_resolution(module_,
-                                         target_module.clone(),
+                                         target_module,
                                          import_directive,
                                          name,
                                          name_bindings.clone());
@@ -863,11 +860,11 @@ fn resolve_glob_import(&mut self,
     }
 
     fn merge_import_resolution(&mut self,
-                               module_: &Module,
-                               containing_module: Rc<Module>,
+                               module_: Module<'b>,
+                               containing_module: Module<'b>,
                                import_directive: &ImportDirective,
                                name: Name,
-                               name_bindings: NameBindings) {
+                               name_bindings: NameBindings<'b>) {
         let id = import_directive.id;
         let is_public = import_directive.is_public;
 
@@ -916,7 +913,7 @@ fn merge_import_resolution(&mut self,
                                   msg);
                     } else {
                         dest_import_resolution[namespace] = ImportResolution {
-                            target: Some(Target::new(containing_module.clone(),
+                            target: Some(Target::new(containing_module,
                                                      name_bindings[namespace].clone(),
                                                      import_directive.shadowable)),
                             id: id,
@@ -993,8 +990,8 @@ fn check_that_import_is_importable(&mut self,
 
     /// Checks that imported names and items don't have the same name.
     fn check_for_conflicts_between_imports_and_items(&mut self,
-                                                     module: &Module,
-                                                     import: &ImportResolutionPerNamespace,
+                                                     module: Module<'b>,
+                                                     import: &ImportResolutionPerNamespace<'b>,
                                                      import_span: Span,
                                                      name: Name) {
         // First, check for conflicts between imports and `extern crate`s.
@@ -1013,8 +1010,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         }
 
         // Check for item conflicts.
-        let children = module.children.borrow();
-        let name_bindings = match children.get(&name) {
+        let name_bindings = match module.children.borrow().get(&name) {
             None => {
                 // There can't be any conflicts.
                 return;
index 0ad780fb0e4d33add43667cb0648c4b333736e4e..f46a7ea67b5f23aa7aadb72d978806d1163a9ce3 100644 (file)
@@ -1760,6 +1760,9 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
     let lvalue = Lvalue::new_with_hint(caller_name, bcx, p_id, HintKind::DontZeroJustUse);
     let datum = Datum::new(llval, var_ty, lvalue);
 
+    debug!("mk_binding_alloca cleanup_scope={:?} llval={} var_ty={:?}",
+           cleanup_scope, bcx.ccx().tn().val_to_string(llval), var_ty);
+
     // Subtle: be sure that we *populate* the memory *before*
     // we schedule the cleanup.
     call_lifetime_start(bcx, llval);
index c744ef321278d0b6d6b6eb10ce7308a74b124708..d22d619b9622754002c18d29f3b14a9c8eb92bee 100644 (file)
@@ -55,6 +55,7 @@
 use syntax::attr;
 use syntax::attr::IntType;
 use trans::_match;
+use trans::base::InitAlloca;
 use trans::build::*;
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
@@ -1279,7 +1280,12 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
             let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum(
                 bcx, tcx.dtor_type(), "drop_flag",
-                cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx
+                InitAlloca::Uninit("drop flag itself has no dtor"),
+                cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| {
+                    debug!("no-op populate call for trans_drop_flag_ptr on dtor_type={:?}",
+                           tcx.dtor_type());
+                    bcx
+                }
             ));
             bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
                 let ptr = struct_field_ptr(variant_cx, st, MaybeSizedValue::sized(value),
index d694374acc927898e8effc4e517ccfb7678f34cc..f8b5f8e48f49930e92c303d91771ff3940212b4b 100644 (file)
@@ -1147,48 +1147,63 @@ pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, val: ValueRef, f: F) ->
     next_cx
 }
 
-pub fn call_lifetime_start(cx: Block, ptr: ValueRef) {
-    if cx.sess().opts.optimize == config::No {
+enum Lifetime { Start, End }
+
+// If LLVM lifetime intrinsic support is enabled (i.e. optimizations
+// on), and `ptr` is nonzero-sized, then extracts the size of `ptr`
+// and the intrinsic for `lt` and passes them to `emit`, which is in
+// charge of generating code to call the passed intrinsic on whatever
+// block of generated code is targetted for the intrinsic.
+//
+// If LLVM lifetime intrinsic support is disabled (i.e.  optimizations
+// off) or `ptr` is zero-sized, then no-op (does not call `emit`).
+fn core_lifetime_emit<'blk, 'tcx, F>(ccx: &'blk CrateContext<'blk, 'tcx>,
+                                     ptr: ValueRef,
+                                     lt: Lifetime,
+                                     emit: F)
+    where F: FnOnce(&'blk CrateContext<'blk, 'tcx>, machine::llsize, ValueRef)
+{
+    if ccx.sess().opts.optimize == config::No {
         return;
     }
 
-    let _icx = push_ctxt("lifetime_start");
-    let ccx = cx.ccx();
+    let _icx = push_ctxt(match lt {
+        Lifetime::Start => "lifetime_start",
+        Lifetime::End => "lifetime_end"
+    });
 
     let size = machine::llsize_of_alloc(ccx, val_ty(ptr).element_type());
     if size == 0 {
         return;
     }
 
-    let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
-    let lifetime_start = ccx.get_intrinsic(&"llvm.lifetime.start");
-    Call(cx,
-         lifetime_start,
-         &[C_u64(ccx, size), ptr],
-         None,
-         DebugLoc::None);
+    let lifetime_intrinsic = ccx.get_intrinsic(match lt {
+        Lifetime::Start => "llvm.lifetime.start",
+        Lifetime::End => "llvm.lifetime.end"
+    });
+    emit(ccx, size, lifetime_intrinsic)
 }
 
-pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
-    if cx.sess().opts.optimize == config::No {
-        return;
-    }
-
-    let _icx = push_ctxt("lifetime_end");
-    let ccx = cx.ccx();
-
-    let size = machine::llsize_of_alloc(ccx, val_ty(ptr).element_type());
-    if size == 0 {
-        return;
-    }
+pub fn call_lifetime_start(cx: Block, ptr: ValueRef) {
+    core_lifetime_emit(cx.ccx(), ptr, Lifetime::Start, |ccx, size, lifetime_start| {
+        let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
+        Call(cx,
+             lifetime_start,
+             &[C_u64(ccx, size), ptr],
+             None,
+             DebugLoc::None);
+    })
+}
 
-    let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
-    let lifetime_end = ccx.get_intrinsic(&"llvm.lifetime.end");
-    Call(cx,
-         lifetime_end,
-         &[C_u64(ccx, size), ptr],
-         None,
-         DebugLoc::None);
+pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
+    core_lifetime_emit(cx.ccx(), ptr, Lifetime::End, |ccx, size, lifetime_end| {
+        let ptr = PointerCast(cx, ptr, Type::i8p(ccx));
+        Call(cx,
+             lifetime_end,
+             &[C_u64(ccx, size), ptr],
+             None,
+             DebugLoc::None);
+    })
 }
 
 // Generates code for resumption of unwind at the end of a landing pad.
@@ -1285,12 +1300,81 @@ fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte:
            None);
 }
 
-pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, name: &str) -> ValueRef {
+/// In general, when we create an scratch value in an alloca, the
+/// creator may not know if the block (that initializes the scratch
+/// with the desired value) actually dominates the cleanup associated
+/// with the scratch value.
+///
+/// To deal with this, when we do an alloca (at the *start* of whole
+/// function body), we optionally can also set the associated
+/// dropped-flag state of the alloca to "dropped."
+#[derive(Copy, Clone, Debug)]
+pub enum InitAlloca {
+    /// Indicates that the state should have its associated drop flag
+    /// set to "dropped" at the point of allocation.
+    Dropped,
+    /// Indicates the value of the associated drop flag is irrelevant.
+    /// The embedded string literal is a programmer provided argument
+    /// for why. This is a safeguard forcing compiler devs to
+    /// document; it might be a good idea to also emit this as a
+    /// comment with the alloca itself when emitting LLVM output.ll.
+    Uninit(&'static str),
+}
+
+
+pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                            t: Ty<'tcx>,
+                            name: &str) -> ValueRef {
+    // pnkfelix: I do not know why alloc_ty meets the assumptions for
+    // passing Uninit, but it was never needed (even back when we had
+    // the original boolean `zero` flag on `lvalue_scratch_datum`).
+    alloc_ty_init(bcx, t, InitAlloca::Uninit("all alloc_ty are uninit"), name)
+}
+
+/// This variant of `fn alloc_ty` does not necessarily assume that the
+/// alloca should be created with no initial value. Instead the caller
+/// controls that assumption via the `init` flag.
+///
+/// Note that if the alloca *is* initialized via `init`, then we will
+/// also inject an `llvm.lifetime.start` before that initialization
+/// occurs, and thus callers should not call_lifetime_start
+/// themselves.  But if `init` says "uninitialized", then callers are
+/// in charge of choosing where to call_lifetime_start and
+/// subsequently populate the alloca.
+///
+/// (See related discussion on PR #30823.)
+pub fn alloc_ty_init<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                             t: Ty<'tcx>,
+                             init: InitAlloca,
+                             name: &str) -> ValueRef {
     let _icx = push_ctxt("alloc_ty");
     let ccx = bcx.ccx();
     let ty = type_of::type_of(ccx, t);
     assert!(!t.has_param_types());
-    alloca(bcx, ty, name)
+    match init {
+        InitAlloca::Dropped => alloca_dropped(bcx, t, name),
+        InitAlloca::Uninit(_) => alloca(bcx, ty, name),
+    }
+}
+
+pub fn alloca_dropped<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, name: &str) -> ValueRef {
+    let _icx = push_ctxt("alloca_dropped");
+    let llty = type_of::type_of(cx.ccx(), ty);
+    if cx.unreachable.get() {
+        unsafe { return llvm::LLVMGetUndef(llty.ptr_to().to_ref()); }
+    }
+    let p = alloca(cx, llty, name);
+    let b = cx.fcx.ccx.builder();
+    b.position_before(cx.fcx.alloca_insert_pt.get().unwrap());
+
+    // This is just like `call_lifetime_start` (but latter expects a
+    // Block, which we do not have for `alloca_insert_pt`).
+    core_lifetime_emit(cx.ccx(), p, Lifetime::Start, |ccx, size, lifetime_start| {
+        let ptr = b.pointercast(p, Type::i8p(ccx));
+        b.call(lifetime_start, &[C_u64(ccx, size), ptr], None);
+    });
+    memfill(&b, p, ty, adt::DTOR_DONE);
+    p
 }
 
 pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef {
@@ -1565,6 +1649,7 @@ pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
     // Create the drop-flag hints for every unfragmented path in the function.
     let tcx = fcx.ccx.tcx();
     let fn_did = tcx.map.local_def_id(fcx.id);
+    let tables = tcx.tables.borrow();
     let mut hints = fcx.lldropflag_hints.borrow_mut();
     let fragment_infos = tcx.fragment_infos.borrow();
 
@@ -1588,12 +1673,22 @@ pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
             let (var, datum) = match info {
                 ty::FragmentInfo::Moved { var, .. } |
                 ty::FragmentInfo::Assigned { var, .. } => {
-                    let datum = seen.get(&var).cloned().unwrap_or_else(|| {
-                        let datum = make_datum(var);
-                        seen.insert(var, datum.clone());
-                        datum
+                    let opt_datum = seen.get(&var).cloned().unwrap_or_else(|| {
+                        let ty = tables.node_types[&var];
+                        if fcx.type_needs_drop(ty) {
+                            let datum = make_datum(var);
+                            seen.insert(var, Some(datum.clone()));
+                            Some(datum)
+                        } else {
+                            // No drop call needed, so we don't need a dropflag hint
+                            None
+                        }
                     });
-                    (var, datum)
+                    if let Some(datum) = opt_datum {
+                        (var, datum)
+                    } else {
+                        continue
+                    }
                 }
             };
             match info {
@@ -1639,6 +1734,8 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
     let fcx = bcx.fcx;
     let arg_scope_id = cleanup::CustomScope(arg_scope);
 
+    debug!("create_datums_for_fn_args");
+
     // Return an array wrapping the ValueRefs that we get from `get_param` for
     // each argument into datums.
     //
@@ -1650,6 +1747,7 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
     // This alloca should be optimized away by LLVM's mem-to-reg pass in
     // the event it's not truly needed.
     let mut idx = fcx.arg_offset() as c_uint;
+    let uninit_reason = InitAlloca::Uninit("fn_arg populate dominates dtor");
     for (i, &arg_ty) in arg_tys.iter().enumerate() {
         let arg_datum = if !has_tupled_arg || i < arg_tys.len() - 1 {
             if type_of::arg_is_indirect(bcx.ccx(), arg_ty) &&
@@ -1669,9 +1767,12 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
                 let data = get_param(fcx.llfn, idx);
                 let extra = get_param(fcx.llfn, idx + 1);
                 idx += 2;
-                unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "",
+                unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx, arg_ty, "", uninit_reason,
                                                         arg_scope_id, (data, extra),
                                                         |(data, extra), bcx, dst| {
+                    debug!("populate call for create_datum_for_fn_args \
+                            early fat arg, on arg[{}] ty={:?}", i, arg_ty);
+
                     Store(bcx, data, expr::get_dataptr(bcx, dst));
                     Store(bcx, extra, expr::get_meta(bcx, dst));
                     bcx
@@ -1684,9 +1785,16 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
                               datum::lvalue_scratch_datum(bcx,
                                                           arg_ty,
                                                           "",
+                                                          uninit_reason,
                                                           arg_scope_id,
                                                           tmp,
-                                                          |tmp, bcx, dst| tmp.store_to(bcx, dst)))
+                                                          |tmp, bcx, dst| {
+
+                        debug!("populate call for create_datum_for_fn_args \
+                                early thin arg, on arg[{}] ty={:?}", i, arg_ty);
+
+                                                              tmp.store_to(bcx, dst)
+                                                          }))
             }
         } else {
             // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
@@ -1696,11 +1804,14 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
                                   datum::lvalue_scratch_datum(bcx,
                                                               arg_ty,
                                                               "tupled_args",
+                                                              uninit_reason,
                                                               arg_scope_id,
                                                               (),
                                                               |(),
                                                                mut bcx,
-                                                               llval| {
+                                                              llval| {
+                        debug!("populate call for create_datum_for_fn_args \
+                                tupled_args, on arg[{}] ty={:?}", i, arg_ty);
                         for (j, &tupled_arg_ty) in
                                     tupled_arg_tys.iter().enumerate() {
                             let lldest = StructGEP(bcx, llval, j);
index 418ff4c8337e7f27dd48da0a72d0ef98c34400fd..32f263746d31e04158742f0abcf12395ad1d44c4 100644 (file)
@@ -288,20 +288,31 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     return DatumBlock::new(bcx, immediate_rvalue(val, ty))
 }
 
-
 /// Allocates temporary space on the stack using alloca() and returns a by-ref Datum pointing to
 /// it. The memory will be dropped upon exit from `scope`. The callback `populate` should
 /// initialize the memory.
+///
+/// The flag `zero` indicates how the temporary space itself should be
+/// initialized at the outset of the function; the only time that
+/// `InitAlloca::Uninit` is a valid value for `zero` is when the
+/// caller can prove that either (1.) the code injected by `populate`
+/// onto `bcx` always dominates the end of `scope`, or (2.) the data
+/// being allocated has no associated destructor.
 pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
                                               ty: Ty<'tcx>,
                                               name: &str,
+                                              zero: InitAlloca,
                                               scope: cleanup::ScopeId,
                                               arg: A,
                                               populate: F)
                                               -> DatumBlock<'blk, 'tcx, Lvalue> where
     F: FnOnce(A, Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>,
 {
-    let scratch = alloc_ty(bcx, ty, name);
+    // Very subtle: potentially initialize the scratch memory at point where it is alloca'ed.
+    // (See discussion at Issue 30530.)
+    let scratch = alloc_ty_init(bcx, ty, zero, name);
+    debug!("lvalue_scratch_datum scope={:?} scratch={} ty={:?}",
+           scope, bcx.ccx().tn().val_to_string(scratch), ty);
 
     // Subtle. Populate the scratch memory *before* scheduling cleanup.
     let bcx = populate(arg, bcx, scratch);
@@ -340,6 +351,8 @@ fn add_rvalue_clean<'a, 'tcx>(mode: RvalueMode,
                               scope: cleanup::ScopeId,
                               val: ValueRef,
                               ty: Ty<'tcx>) {
+    debug!("add_rvalue_clean scope={:?} val={} ty={:?}",
+           scope, fcx.ccx.tn().val_to_string(val), ty);
     match mode {
         ByValue => { fcx.schedule_drop_immediate(scope, val, ty); }
         ByRef => {
@@ -496,9 +509,13 @@ pub fn to_lvalue_datum_in_scope<'blk>(self,
 
             ByValue => {
                 lvalue_scratch_datum(
-                    bcx, self.ty, name, scope, self,
+                    bcx, self.ty, name, InitAlloca::Dropped, scope, self,
                     |this, bcx, llval| {
-                        call_lifetime_start(bcx, llval);
+                        debug!("populate call for Datum::to_lvalue_datum_in_scope \
+                                self.ty={:?}", this.ty);
+                        // do not call_lifetime_start here; the
+                        // `InitAlloc::Dropped` will start scratch
+                        // value's lifetime at open of function body.
                         let bcx = this.store_to(bcx, llval);
                         bcx.fcx.schedule_lifetime_end(scope, llval);
                         bcx
index fb6f2190207ee3c8e33efe303b558371152800ba..57afd0b580f177d40906cf3022e3d2e62b955638 100644 (file)
@@ -1487,6 +1487,8 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
     };
 
+    debug!("trans_adt");
+
     // This scope holds intermediates that must be cleaned should
     // panic occur before the ADT as a whole is ready.
     let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
index c7e1af5853d11a48ca3b34eef95bb3cb75d3b3a6..3a1568a70c9922d8d8804c8daa75b0c6b402a090 100644 (file)
@@ -111,8 +111,15 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Always create an alloca even if zero-sized, to preserve
     // the non-null invariant of the inner slice ptr
-    let llfixed = base::alloc_ty(bcx, fixed_ty, "");
-    call_lifetime_start(bcx, llfixed);
+    let llfixed;
+    // Issue 30018: ensure state is initialized as dropped if necessary.
+    if fcx.type_needs_drop(vt.unit_ty) {
+        llfixed = base::alloc_ty_init(bcx, fixed_ty, InitAlloca::Dropped, "");
+    } else {
+        let uninit = InitAlloca::Uninit("fcx says vt.unit_ty is non-drop");
+        llfixed = base::alloc_ty_init(bcx, fixed_ty, uninit, "");
+        call_lifetime_start(bcx, llfixed);
+    };
 
     if count > 0 {
         // Arrange for the backing array to be cleaned up.
@@ -212,8 +219,8 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         bcx = expr::trans_into(bcx, &**element,
                                                SaveIn(lleltptr));
                         let scope = cleanup::CustomScope(temp_scope);
-                        fcx.schedule_lifetime_end(scope, lleltptr);
-                        fcx.schedule_drop_mem(scope, lleltptr, vt.unit_ty, None);
+                        // Issue #30822: mark memory as dropped after running destructor
+                        fcx.schedule_drop_and_fill_mem(scope, lleltptr, vt.unit_ty, None);
                     }
                     fcx.pop_custom_cleanup_scope(temp_scope);
                 }
index 66f8068eae6571658645754015d5f8fd70bd9ce0..46ecd3a80b5d12e8bc77f855773a888bc16caf36 100644 (file)
@@ -46,8 +46,8 @@
 /// This `struct` is created by the [`to_lowercase()`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`to_lowercase()`]: primitive.char.html#method.escape_to_lowercase
-/// [`char`]: primitive.char.html
+/// [`to_lowercase()`]: ../primitive.char.html#method.to_lowercase
+/// [`char`]: ../primitive.char.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ToLowercase(CaseMappingIter);
 
@@ -64,8 +64,8 @@ fn next(&mut self) -> Option<char> {
 /// This `struct` is created by the [`to_uppercase()`] method on [`char`]. See
 /// its documentation for more.
 ///
-/// [`to_uppercase()`]: primitive.char.html#method.escape_to_uppercase
-/// [`char`]: primitive.char.html
+/// [`to_uppercase()`]: ../primitive.char.html#method.to_uppercase
+/// [`char`]: ../primitive.char.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ToUppercase(CaseMappingIter);
 
index b9ebe977b7bd753eccfcc0a3f6b08486baa15427..8bc1c184d20387daa6939e4534a086637a444deb 100644 (file)
@@ -1819,10 +1819,10 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio
         } else if stab.level == stability::Unstable {
             let unstable_extra = if show_reason {
                 match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) {
-                    (true, &Some(ref tracker_url), Some(issue_no)) =>
+                    (true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
                         format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
                                 Escape(&stab.feature), tracker_url, issue_no, issue_no),
-                    (false, &Some(ref tracker_url), Some(issue_no)) =>
+                    (false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
                         format!(" (<a href=\"{}{}\">#{}</a>)", Escape(&tracker_url), issue_no,
                                 issue_no),
                     (true, _, _) =>
index 16ce05ef2dcaf72497b171796eda90357dc1b624..a9a79fe2c7733f3afc9332c2f99f8f62b4724791 100644 (file)
@@ -772,21 +772,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-struct InternalBufWriter<W: Write>(BufWriter<W>);
-
-impl<W: Read + Write> InternalBufWriter<W> {
-    fn get_mut(&mut self) -> &mut BufWriter<W> {
-        let InternalBufWriter(ref mut w) = *self;
-        return w;
-    }
-}
-
-impl<W: Read + Write> Read for InternalBufWriter<W> {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.get_mut().inner.as_mut().unwrap().read(buf)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
index b5ba6ff54c0e3b7d32b5fcb9ed1b450aae48562d..40533117f06c2353d3a6fe888677c9c32b6ddb96 100644 (file)
 //! ```
 //!
 //! `BufWriter` doesn't add any new ways of writing; it just buffers every call
-//! to [`write()`][write]:
+//! to [`write()`][write()]:
 //!
 //! ```
 //! use std::io;
 //! # }
 //! ```
 //!
-//! [write]: trait.Write.html#tymethod.write
+//! [write()]: trait.Write.html#tymethod.write
 //!
 //! ## Standard input and output
 //!
@@ -399,7 +399,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 ///
 /// [`File`][file]s implement `Read`:
 ///
-/// [file]: ../std/fs/struct.File.html
+/// [file]: ../fs/struct.File.html
 ///
 /// ```
 /// use std::io;
@@ -459,7 +459,7 @@ pub trait Read {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -501,7 +501,7 @@ pub trait Read {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -540,7 +540,7 @@ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -600,7 +600,7 @@ fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -643,7 +643,7 @@ fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -682,7 +682,7 @@ fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -718,7 +718,7 @@ fn bytes(self) -> Bytes<Self> where Self: Sized {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// #![feature(io)]
@@ -753,7 +753,7 @@ fn chars(self) -> Chars<Self> where Self: Sized {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -789,7 +789,7 @@ fn chain<R: Read>(self, next: R) -> Chain<Self, R> where Self: Sized {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -823,7 +823,7 @@ fn take(self, limit: u64) -> Take<Self> where Self: Sized {
     ///
     /// [`File`][file]s implement `Read`:
     ///
-    /// [file]: ../std/fs/struct.File.html
+    /// [file]: ../fs/struct.File.html
     ///
     /// ```
     /// #![feature(io)]
index 3f9a1c30ef4936c6d4767fcc27c1d767aa91af0d..8561ecd9c4cb92d9e21952fe65167c03b9ad9ab5 100644 (file)
@@ -206,7 +206,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
     // debugger provides a useable stacktrace.
     if panics >= 3 {
         util::dumb_print(format_args!("thread panicked while processing \
-                                       panic. aborting."));
+                                       panic. aborting.\n"));
         unsafe { intrinsics::abort() }
     }
 
@@ -232,7 +232,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
         // just abort. In the future we may consider resuming
         // unwinding or otherwise exiting the thread cleanly.
         util::dumb_print(format_args!("thread panicked while panicking. \
-                                       aborting."));
+                                       aborting.\n"));
         unsafe { intrinsics::abort() }
     }
 }
index 0ba0e01ce29102d03968deb06915a4ac07b2a5cb..23a368a30a52bc4cfb67f4d8bfd81cbfb8406289 100644 (file)
@@ -222,7 +222,7 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
             // getentropy(2) permits a maximum buffer size of 256 bytes
             for s in v.chunks_mut(256) {
                 let ret = unsafe {
-                    libc::syscall(libc::NR_GETENTROPY, s.as_mut_ptr(), s.len())
+                    libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len())
                 };
                 if ret == -1 {
                     panic!("unexpected getentropy error: {}", errno());
index 979f1f486698358f25a6e902877e097c56f874f2..b7a6b7650d54079de57495659ba7684dc697264a 100644 (file)
@@ -35,12 +35,12 @@ pub fn dumb_print(args: fmt::Arguments) {
 }
 
 pub fn abort(args: fmt::Arguments) -> ! {
-    dumb_print(format_args!("fatal runtime error: {}", args));
+    dumb_print(format_args!("fatal runtime error: {}\n", args));
     unsafe { intrinsics::abort(); }
 }
 
 #[allow(dead_code)] // stack overflow detection not enabled on all platforms
 pub unsafe fn report_overflow() {
-    dumb_print(format_args!("\nthread '{}' has overflowed its stack",
+    dumb_print(format_args!("\nthread '{}' has overflowed its stack\n",
                             thread::current().name().unwrap_or("<unknown>")));
 }
index e8575a6c21cf13c0eb159766123a3c415df28c05..10fda3fcd7fa5165ce82e70ea0fab45d8517559e 100644 (file)
@@ -204,7 +204,8 @@ pub fn ino(&self) -> raw::ino_t {
 
     #[cfg(any(target_os = "macos",
               target_os = "ios",
-              target_os = "netbsd"))]
+              target_os = "netbsd",
+              target_os = "openbsd"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
@@ -213,8 +214,7 @@ fn name_bytes(&self) -> &[u8] {
     }
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
-              target_os = "bitrig",
-              target_os = "openbsd"))]
+              target_os = "bitrig"))]
     fn name_bytes(&self) -> &[u8] {
         unsafe {
             ::slice::from_raw_parts(self.entry.d_name.as_ptr() as *const u8,
index 929fd2fb0c38b8a0c3dc146d634c1fb63e5b396f..9771b057d8d21f5bfac77a38cbb71b5130e5c899 100644 (file)
@@ -15,6 +15,7 @@
 use libc;
 use num::One;
 use ops::Neg;
+use alloc::oom;
 
 #[cfg(target_os = "android")]   pub use os::android as platform;
 #[cfg(target_os = "bitrig")]    pub use os::bitrig as platform;
 pub mod time;
 pub mod stdio;
 
+// A nicer handler for out-of-memory situations than the default one. This one
+// prints a message to stderr before aborting. It is critical that this code
+// does not allocate any memory since we are in an OOM situation. Any errors are
+// ignored while printing since there's nothing we can do about them and we are
+// about to exit anyways.
+fn oom_handler() -> ! {
+    use intrinsics;
+    let msg = "fatal runtime error: out of memory\n";
+    unsafe {
+        libc::write(libc::STDERR_FILENO,
+                    msg.as_ptr() as *const libc::c_void,
+                    msg.len() as libc::size_t);
+        intrinsics::abort();
+    }
+}
+
 #[cfg(not(any(target_os = "nacl", test)))]
 pub fn init() {
     use libc::signal;
@@ -58,10 +75,14 @@ pub fn init() {
     unsafe {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
     }
+
+    oom::set_oom_handler(oom_handler);
 }
 
 #[cfg(all(target_os = "nacl", not(test)))]
-pub fn init() { }
+pub fn init() {
+    oom::set_oom_handler(oom_handler);
+}
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno as libc::c_int {
index 776acd20b069bbc0598eb417c4f10dd78d1d6ca6..fc49f4257be2ace4908917a38edd0278ce04b774 100644 (file)
@@ -59,19 +59,19 @@ mod imp {
     static mut PAGE_SIZE: usize = 0;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
-    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void {
+    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
         #[repr(C)]
         struct siginfo_t {
             a: [libc::c_int; 3], // si_signo, si_code, si_errno,
             si_addr: *mut libc::c_void,
         }
 
-        (*(info as *const siginfo_t)).si_addr
+        (*(info as *const siginfo_t)).si_addr as usize
     }
 
     #[cfg(not(any(target_os = "linux", target_os = "android")))]
-    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void {
-        (*info).si_addr
+    unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
+        (*info).si_addr as usize
     }
 
     // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
@@ -98,7 +98,7 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> *mut libc::c_void {
         use sys_common::util::report_overflow;
 
         let guard = thread_info::stack_guard().unwrap_or(0);
-        let addr = siginfo_si_addr(info) as usize;
+        let addr = siginfo_si_addr(info);
 
         // If the faulting address is within the guard page, then we print a
         // message saying so.
index 7e5342a3fd4733d2308a60a7205d24e3fc0a5f18..16c4ae8257c132d7018e018fcab09c682f8f8db6 100644 (file)
@@ -20,6 +20,7 @@
 use os::windows::ffi::{OsStrExt, OsStringExt};
 use path::PathBuf;
 use time::Duration;
+use alloc::oom;
 
 #[macro_use] pub mod compat;
 
 pub mod time;
 pub mod stdio;
 
-pub fn init() {}
+// See comment in sys/unix/mod.rs
+fn oom_handler() -> ! {
+    use intrinsics;
+    use ptr;
+    let msg = "fatal runtime error: out of memory\n";
+    unsafe {
+        // WriteFile silently fails if it is passed an invalid handle, so there
+        // is no need to check the result of GetStdHandle.
+        c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE),
+                     msg.as_ptr() as c::LPVOID,
+                     msg.len() as c::DWORD,
+                     ptr::null_mut(),
+                     ptr::null_mut());
+        intrinsics::abort();
+    }
+}
+
+pub fn init() {
+    oom::set_oom_handler(oom_handler);
+}
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno as c::DWORD {
index ad1be82d6d8422a9a28b1b14481c0961a8847056..7ecb3920cc86c9ede483e4a79cf264de587ec15a 100644 (file)
@@ -40,7 +40,7 @@
 /// let ten_millis = Duration::from_millis(10);
 /// ```
 #[stable(feature = "duration", since = "1.3.0")]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
 pub struct Duration {
     secs: u64,
     nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
index 2945d20ceb1b8c641f3dbe8af5fbc8c64505a580..dcc344c4ffd2140f6d6b9965aba5c936bbd12924 100644 (file)
@@ -919,7 +919,6 @@ fn num_cpus() -> usize {
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
-              target_os = "openbsd",
               target_os = "netbsd"))]
     fn num_cpus() -> usize {
         let mut cpus: libc::c_uint = 0;
@@ -946,6 +945,24 @@ fn num_cpus() -> usize {
         }
         cpus as usize
     }
+
+    #[cfg(target_os = "openbsd")]
+    fn num_cpus() -> usize {
+        let mut cpus: libc::c_uint = 0;
+        let mut cpus_size = std::mem::size_of_val(&cpus);
+        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
+
+        unsafe {
+            libc::sysctl(mib.as_mut_ptr(), 2,
+                         &mut cpus as *mut _ as *mut _,
+                         &mut cpus_size as *mut _ as *mut _,
+                         0 as *mut _, 0);
+        }
+        if cpus < 1 {
+            cpus = 1;
+        }
+        cpus as usize
+    }
 }
 
 pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
diff --git a/src/test/run-pass/issue-29092.rs b/src/test/run-pass/issue-29092.rs
new file mode 100644 (file)
index 0000000..c55cc91
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2012-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.
+
+// Regression test for Issue #29092.
+//
+// (Possibly redundant with regression test run-pass/issue-30530.rs)
+
+use self::Term::*;
+
+#[derive(Clone)]
+pub enum Term {
+    Dummy,
+    A(Box<Term>),
+    B(Box<Term>),
+}
+
+// a small-step evaluator
+pub fn small_eval(v: Term) -> Term {
+    match v {
+        A(t) => *t.clone(),
+        B(t) => *t.clone(),
+        _ => Dummy,
+    }
+}
+
+fn main() {
+    small_eval(Dummy);
+}
diff --git a/src/test/run-pass/issue-30018-nopanic.rs b/src/test/run-pass/issue-30018-nopanic.rs
new file mode 100644 (file)
index 0000000..25eff9d
--- /dev/null
@@ -0,0 +1,111 @@
+// Copyright 2012-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.
+
+// More thorough regression test for Issues #30018 and #30822. This
+// attempts to explore different ways that array element construction
+// (for both scratch arrays and non-scratch ones) interacts with
+// breaks in the control-flow, in terms of the order of evaluation of
+// the destructors (which may change; see RFC Issue 744) and the
+// number of times that the destructor evaluates for each value (which
+// should never exceed 1; this latter case is what #30822 is about).
+
+use std::cell::RefCell;
+
+struct D<'a>(&'a RefCell<Vec<i32>>, i32);
+
+impl<'a> Drop for D<'a> {
+    fn drop(&mut self) {
+        println!("Dropping D({})", self.1);
+        (self.0).borrow_mut().push(self.1);
+    }
+}
+
+fn main() {
+    println!("Start");
+    break_during_elem();
+    break_after_whole();
+    println!("Finis");
+}
+
+fn break_during_elem() {
+    let log = &RefCell::new(Vec::new());
+
+    // CASE 1: Fixed-size array itself is stored in _r slot.
+    loop {
+        let _r = [D(log, 10),
+                  D(log, 11),
+                  { D(log, 12); break; },
+                  D(log, 13)];
+    }
+    assert_eq!(&log.borrow()[..], &[12, 11, 10]);
+    log.borrow_mut().clear();
+
+    // CASE 2: Slice (borrow of array) is stored in _r slot.
+    // This is the case that is actually being reported in #30018.
+    loop {
+        let _r = &[D(log, 20),
+                   D(log, 21),
+                   { D(log, 22); break; },
+                   D(log, 23)];
+    }
+    assert_eq!(&log.borrow()[..], &[22, 21, 20]);
+    log.borrow_mut().clear();
+
+    // CASE 3: (Borrow of) slice-index of array is stored in _r slot.
+    loop {
+        let _r = &[D(log, 30),
+                  D(log, 31),
+                  { D(log, 32); break; },
+                  D(log, 33)][..];
+    }
+    assert_eq!(&log.borrow()[..], &[32, 31, 30]);
+    log.borrow_mut().clear();
+}
+
+// The purpose of these functions is to test what happens when we
+// panic after an array has been constructed in its entirety.
+//
+// It is meant to act as proof that we still need to continue
+// scheduling the destruction of an array even after we've scheduling
+// drop for its elements during construction; the latter is tested by
+// `fn break_during_elem()`.
+fn break_after_whole() {
+    let log = &RefCell::new(Vec::new());
+
+    // CASE 1: Fixed-size array itself is stored in _r slot.
+    loop {
+        let _r = [D(log, 10),
+                  D(log, 11),
+                  D(log, 12)];
+        break;
+    }
+    assert_eq!(&log.borrow()[..], &[10, 11, 12]);
+    log.borrow_mut().clear();
+
+    // CASE 2: Slice (borrow of array) is stored in _r slot.
+    loop {
+        let _r = &[D(log, 20),
+                   D(log, 21),
+                   D(log, 22)];
+        break;
+    }
+    assert_eq!(&log.borrow()[..], &[20, 21, 22]);
+    log.borrow_mut().clear();
+
+    // CASE 3: (Borrow of) slice-index of array is stored in _r slot.
+    loop {
+        let _r = &[D(log, 30),
+                   D(log, 31),
+                   D(log, 32)][..];
+        break;
+    }
+    assert_eq!(&log.borrow()[..], &[30, 31, 32]);
+    log.borrow_mut().clear();
+}
diff --git a/src/test/run-pass/issue-30018-panic.rs b/src/test/run-pass/issue-30018-panic.rs
new file mode 100644 (file)
index 0000000..da4d5f1
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2012-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.
+
+// Regression test for Issue #30018. This is very similar to the
+// original reported test, except that the panic is wrapped in a
+// spawned thread to isolate the expected error result from the
+// SIGTRAP injected by the drop-flag consistency checking.
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+fn foo() -> Foo {
+    panic!();
+}
+
+fn main() {
+    use std::thread;
+    let handle = thread::spawn(|| {
+        let _ = &[foo()];
+    });
+    let _ = handle.join();
+}
diff --git a/src/test/run-pass/issue-30530.rs b/src/test/run-pass/issue-30530.rs
new file mode 100644 (file)
index 0000000..d5139c9
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2012-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.
+
+// Regression test for Issue #30530: alloca's created for storing
+// intermediate scratch values during brace-less match arms need to be
+// initialized with their drop-flag set to "dropped" (or else we end
+// up running the destructors on garbage data at the end of the
+// function).
+
+pub enum Handler {
+    Default,
+    #[allow(dead_code)]
+    Custom(*mut Box<Fn()>),
+}
+
+fn main() {
+    take(Handler::Default, Box::new(main));
+}
+
+#[inline(never)]
+pub fn take(h: Handler, f: Box<Fn()>) -> Box<Fn()> {
+    unsafe {
+        match h {
+            Handler::Custom(ptr) => *Box::from_raw(ptr),
+            Handler::Default => f,
+        }
+    }
+}