]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #31052 - bluss:split-at-mut-str, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 21 Jan 2016 20:51:34 +0000 (20:51 +0000)
committerbors <bors@rust-lang.org>
Thu, 21 Jan 2016 20:51:34 +0000 (20:51 +0000)
Use raw pointers to avoid aliasing in str::split_at_mut

Introduce private function  from_raw_parts_mut for str to factor out the logic.

We want to use raw pointers here instead of duplicating a &mut str, to
be on safer ground w.r.t rust aliasing rules.

This has already been fixed for slices in PR #27358, issue #27357

144 files changed:
configure
mk/crates.mk
mk/main.mk
src/doc/book/lifetimes.md
src/doc/book/macros.md
src/doc/nomicon/lifetime-elision.md
src/jemalloc
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/fmt.rs
src/libcollections/str.rs
src/libcollections/vec_deque.rs
src/libcollectionstest/btree/set.rs
src/libcore/marker.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/slice.rs
src/librbml/leb128.rs
src/librbml/lib.rs
src/librbml/opaque.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/middle/astconv_util.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_const.rs [deleted file]
src/librustc/middle/check_loop.rs [deleted file]
src/librustc/middle/check_match.rs
src/librustc/middle/check_rvalues.rs [deleted file]
src/librustc/middle/check_static_recursion.rs [deleted file]
src/librustc/middle/const_eval.rs
src/librustc/middle/const_qualif.rs [new file with mode: 0644]
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/def.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/ty/context.rs
src/librustc/middle/ty/mod.rs
src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
src/librustc_driver/driver.rs
src/librustc_front/lowering.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/loader.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/pattern.rs
src/librustc_passes/consts.rs [new file with mode: 0644]
src/librustc_passes/diagnostics.rs
src/librustc_passes/lib.rs
src/librustc_passes/loops.rs [new file with mode: 0644]
src/librustc_passes/rvalues.rs [new file with mode: 0644]
src/librustc_passes/static_recursion.rs [new file with mode: 0644]
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/save/dump_csv.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/build.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/mir/block.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/libstd/fs.rs
src/libstd/memchr.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/fs.rs
src/libsyntax/codemap.rs
src/libterm/lib.rs
src/libterm/terminfo/mod.rs
src/libterm/win.rs
src/libtest/lib.rs
src/libtest/stats.rs
src/rt/rust_test_helpers.c
src/test/compile-fail/allocator-dylib-is-system.rs
src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs
src/test/compile-fail/empty-struct-braces-expr.rs
src/test/compile-fail/empty-struct-braces-pat-2.rs
src/test/compile-fail/issue-10545.rs
src/test/compile-fail/loop-does-not-diverge.rs
src/test/compile-fail/loop-proper-liveness.rs [new file with mode: 0644]
src/test/compile-fail/loop-properly-diverging-2.rs [new file with mode: 0644]
src/test/compile-fail/loop-properly-diverging.rs [new file with mode: 0644]
src/test/compile-fail/privacy1.rs
src/test/compile-fail/struct-field-privacy.rs
src/test/compile-fail/xcrate-unit-struct.rs
src/test/run-make/c-link-to-rust-dylib/Makefile
src/test/run-make/c-link-to-rust-staticlib/Makefile
src/test/run-make/lto-smoke-c/Makefile
src/test/run-make/output-type-permutations/Makefile
src/test/run-make/static-dylib-by-default/Makefile
src/test/run-pass/allocator-default.rs
src/test/run-pass/allocator-jemalloc.rs
src/test/run-pass/associated-const-match-patterns.rs
src/test/run-pass/mir_trans_calls.rs
src/test/run-pass/mir_trans_calls_variadic.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-binary-heap-push.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-btreemap-insert.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-linkedlist-push.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-vec-deque-push.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-vec-push.rs [new file with mode: 0644]

index 0255b04caa3163a331f1a406b590234ce92e211b..446a6e3feae381c9e41d8971a653b095d88ae33f 100755 (executable)
--- a/configure
+++ b/configure
@@ -550,7 +550,7 @@ CFG_SELF="$0"
 CFG_CONFIGURE_ARGS="$@"
 
 
-case "${CFG_SRC_DIR}" in  
+case "${CFG_SRC_DIR}" in
     *\ * )
         err "The path to the rust source directory contains spaces, which is not supported"
         ;;
@@ -892,6 +892,13 @@ then
     CFG_DISABLE_JEMALLOC=1
 fi
 
+if [ $CFG_OSTYPE = pc-windows-gnu ]
+then
+    # FIXME(#31030) - there's not a great reason to disable jemalloc here
+    step_msg "on Windows, disabling jemalloc"
+    CFG_DISABLE_JEMALLOC=1
+fi
+
 # OS X 10.9, gcc is actually clang. This can cause some confusion in the build
 # system, so if we find that gcc is clang, we should just use clang directly.
 if [ $CFG_OSTYPE = apple-darwin -a -z "$CFG_ENABLE_CLANG" ]
@@ -1035,7 +1042,7 @@ then
         if [ -n "$CFG_OSX_CLANG_VERSION" ]
         then
             case $CFG_OSX_CLANG_VERSION in
-                (7.0*)
+                (7.0* | 7.1* | 7.2*)
                 step_msg "found ok version of APPLE CLANG: $CFG_OSX_CLANG_VERSION"
                 ;;
                 (*)
index 5cc8a46878439740273abc44fc2629219da25819..f47c4857ef86132d99b4a1541430e760de71c1c6 100644 (file)
@@ -102,7 +102,7 @@ DEPS_rustc_front := std syntax log serialize
 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_passes := syntax rustc core
+DEPS_rustc_passes := syntax rustc core rustc_front
 DEPS_rustc_mir := rustc rustc_front syntax
 DEPS_rustc_resolve := arena rustc rustc_front log syntax
 DEPS_rustc_platform_intrinsics := rustc rustc_llvm
index a478cafd6b95880e004059896a96134cb5276aa0..084e08aa339e3658c45279e5bfa3754774a10cbd 100644 (file)
@@ -13,7 +13,7 @@
 ######################################################################
 
 # The version number
-CFG_RELEASE_NUM=1.7.0
+CFG_RELEASE_NUM=1.8.0
 
 # An optional number to put after the label, e.g. '.2' -> '-beta.2'
 # NB Make sure it starts with a dot to conform to semver pre-release
index 8bf90b4ea4d8a882a36ef34b8fe603cb79f1f246..4193c93c894c4fec4a97b19aa3a5ce1ccf1b0509 100644 (file)
@@ -353,8 +353,8 @@ fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is
 fn get_mut(&mut self) -> &mut T; // elided
 fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
 
-fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
-fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
+fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
+fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
 
 fn new(buf: &mut [u8]) -> BufWriter; // elided
 fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
index 7c8b74bd6495d0f44cf279a4c3daec98faa4b55e..f5a0cd5e2c6a30b9793c39f817fa9e2220ed76a9 100644 (file)
@@ -285,9 +285,11 @@ This expands to
 
 ```text
 const char *state = "reticulating splines";
-int state = get_log_state();
-if (state > 0) {
-    printf("log(%d): %s\n", state, state);
+{
+    int state = get_log_state();
+    if (state > 0) {
+        printf("log(%d): %s\n", state, state);
+    }
 }
 ```
 
index 41014f46dd953827374f55791adf5f7d0ed7b135..bcd93a58d859a96d8807f7bd8b10baf6af1264a8 100644 (file)
@@ -55,8 +55,8 @@ fn frob(s: &str, t: &str) -> &str;                      // ILLEGAL
 fn get_mut(&mut self) -> &mut T;                        // elided
 fn get_mut<'a>(&'a mut self) -> &'a mut T;              // expanded
 
-fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command                  // elided
-fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
+fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command                  // elided
+fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
 
 fn new(buf: &mut [u8]) -> BufWriter;                    // elided
 fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>          // expanded
index f84e30927284b0c500ed3eaf09e8e159da20ddaf..e24a1a025a1f214e40eedafe3b9c7b1d69937922 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f84e30927284b0c500ed3eaf09e8e159da20ddaf
+Subproject commit e24a1a025a1f214e40eedafe3b9c7b1d69937922
index 169634a7c82555cb1bf4d2c71f444f0897215978..424a689bcb0b9cfbb575b5a5c07d0c8c00d60be9 100644 (file)
@@ -149,15 +149,15 @@ pub struct Weak<T: ?Sized> {
     _ptr: Shared<ArcInner<T>>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
@@ -681,7 +681,7 @@ fn clone(&self) -> Weak<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
index 2c45e88bb24e802d904875583ce6ddfebe7e04e7..3c4bea95ba1674f55debe08a9cd8e826fafbdcc5 100644 (file)
@@ -715,9 +715,9 @@ pub struct Weak<T: ?Sized> {
     _ptr: Shared<RcBox<T>>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> !marker::Send for Weak<T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
@@ -753,7 +753,7 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
@@ -819,7 +819,7 @@ fn clone(&self) -> Weak<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
index c8a0f60587e9eaa5a89df18e2888b854016d52e6..f07962811fdabda17bd1c4cea7f503a51eaf1bf9 100644 (file)
@@ -1027,6 +1027,8 @@ pub fn merge(mut self)
             }
             self.node.as_leaf_mut().len -= 1;
 
+            left_node.as_leaf_mut().len += right_len as u16 + 1;
+
             if self.node.height > 1 {
                 ptr::copy_nonoverlapping(
                     right_node.cast_unchecked().as_internal().edges.as_ptr(),
@@ -1058,8 +1060,6 @@ pub fn merge(mut self)
                 );
             }
 
-            left_node.as_leaf_mut().len += right_len as u16 + 1;
-
             Handle::new_edge(self.node, self.idx)
         }
     }
index c1381dde762e546548914a62391c20ba8b171acd..91fc8d8217f53b487921e33e45e56f6e39c61124 100644 (file)
@@ -14,7 +14,7 @@
 use core::cmp::Ordering::{self, Less, Greater, Equal};
 use core::fmt::Debug;
 use core::fmt;
-use core::iter::{Peekable, Map, FromIterator};
+use core::iter::{Peekable, FromIterator};
 use core::ops::{BitOr, BitAnd, BitXor, Sub};
 
 use borrow::Borrow;
@@ -52,12 +52,12 @@ pub struct Iter<'a, T: 'a> {
 /// An owning iterator over a BTreeSet's items.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
-    iter: Map<::btree_map::IntoIter<T, ()>, fn((T, ())) -> T>,
+    iter: ::btree_map::IntoIter<T, ()>,
 }
 
 /// An iterator over a sub-range of BTreeSet's items.
 pub struct Range<'a, T: 'a> {
-    iter: Map<::btree_map::Range<'a, T, ()>, fn((&'a T, &'a ())) -> &'a T>,
+    iter: ::btree_map::Range<'a, T, ()>,
 }
 
 /// A lazy iterator producing elements in the set difference (in-order).
@@ -160,12 +160,7 @@ pub fn range<'a, Min: ?Sized + Ord, Max: ?Sized + Ord>(&'a self,
                                                            -> Range<'a, T>
         where T: Borrow<Min> + Borrow<Max>
     {
-        fn first<A, B>((a, _): (A, B)) -> A {
-            a
-        }
-        let first: fn((&'a T, &'a ())) -> &'a T = first; // coerce to fn pointer
-
-        Range { iter: self.map.range(min, max).map(first) }
+        Range { iter: self.map.range(min, max) }
     }
 }
 
@@ -548,12 +543,7 @@ impl<T> IntoIterator for BTreeSet<T> {
     /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     fn into_iter(self) -> IntoIter<T> {
-        fn first<A, B>((a, _): (A, B)) -> A {
-            a
-        }
-        let first: fn((T, ())) -> T = first; // coerce to fn pointer
-
-        IntoIter { iter: self.map.into_iter().map(first) }
+        IntoIter { iter: self.map.into_iter() }
     }
 }
 
@@ -721,7 +711,7 @@ impl<T> Iterator for IntoIter<T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> {
-        self.iter.next()
+        self.iter.next().map(|(k, _)| k)
     }
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
@@ -730,7 +720,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> DoubleEndedIterator for IntoIter<T> {
     fn next_back(&mut self) -> Option<T> {
-        self.iter.next_back()
+        self.iter.next_back().map(|(k, _)| k)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -746,12 +736,12 @@ impl<'a, T> Iterator for Range<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> {
-        self.iter.next()
+        self.iter.next().map(|(k, _)| k)
     }
 }
 impl<'a, T> DoubleEndedIterator for Range<'a, T> {
     fn next_back(&mut self) -> Option<&'a T> {
-        self.iter.next_back()
+        self.iter.next_back().map(|(k, _)| k)
     }
 }
 
index d46a3e7e89e88565c12d2d13b79e795be432a61d..97b01a607f5e602a06ea3d30f9b373f3c9c8fec3 100644 (file)
 //! The fill character is provided normally in conjunction with the `width`
 //! parameter. This indicates that if the value being formatted is smaller than
 //! `width` some extra characters will be printed around it. The extra
-//! characters are specified by `fill`, and the alignment can be one of two
-//! options:
+//! characters are specified by `fill`, and the alignment can be one of the
+//! following options:
 //!
 //! * `<` - the argument is left-aligned in `width` columns
 //! * `^` - the argument is center-aligned in `width` columns
index 766867f284ee1f0c0e5148f7a650b08272501669..9ce1a111cf83a18f36f31dd8543450abb5237101 100644 (file)
@@ -302,7 +302,7 @@ pub fn as_ptr(&self) -> *const u8 {
     /// # Safety
     ///
     /// Callers of this function are responsible that three preconditions are
-    /// satisifed:
+    /// satisfied:
     ///
     /// * `begin` must come before `end`.
     /// * `begin` and `end` must be byte positions within the string slice.
@@ -345,7 +345,7 @@ pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
     /// # Safety
     ///
     /// Callers of this function are responsible that three preconditions are
-    /// satisifed:
+    /// satisfied:
     ///
     /// * `begin` must come before `end`.
     /// * `begin` and `end` must be byte positions within the string slice.
index ba78acc28bccbd88f5c6293f4deca8810466ba47..394f7a975989ae9b1f82a1930c7521148e49e5b7 100644 (file)
@@ -2364,34 +2364,4 @@ fn test_split_off() {
             }
         }
     }
-
-    #[test]
-    fn test_zst_push() {
-        const N: usize = 8;
-
-        // Zero sized type
-        struct Zst;
-
-        // Test that for all possible sequences of push_front / push_back,
-        // we end up with a deque of the correct size
-
-        for len in 0..N {
-            let mut tester = VecDeque::with_capacity(len);
-            assert_eq!(tester.len(), 0);
-            assert!(tester.capacity() >= len);
-            for case in 0..(1 << len) {
-                assert_eq!(tester.len(), 0);
-                for bit in 0..len {
-                    if case & (1 << bit) != 0 {
-                        tester.push_front(Zst);
-                    } else {
-                        tester.push_back(Zst);
-                    }
-                }
-                assert_eq!(tester.len(), len);
-                assert_eq!(tester.iter().count(), len);
-                tester.clear();
-            }
-        }
-    }
 }
index 8fcfe97f42afcb2fcc029c8f1a1e418139a7a05d..fee183433285e305a0ae541ceeb60d6986d20164 100644 (file)
@@ -254,3 +254,13 @@ fn cmp(&self, other: &Self) -> Ordering {
 
     assert_eq!(s.iter().next(), None);
 }
+
+#[test]
+fn test_variance() {
+    use std::collections::btree_set::{IntoIter, Iter, Range};
+
+    fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { v }
+    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> { v }
+    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> { v }
+    fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> { v }
+}
index 621dce3efc86bf8ca7e7c8f13f477e86c5253168..1ed2a219fac3a5f03499d2a1532b90b064bc516a 100644 (file)
@@ -333,7 +333,7 @@ fn default() -> $t<T> {
 /// use std::marker::PhantomData;
 ///
 /// # #[allow(dead_code)]
-/// struct Slice<'a, T:'a> {
+/// struct Slice<'a, T: 'a> {
 ///     start: *const T,
 ///     end: *const T,
 ///     phantom: PhantomData<&'a T>
@@ -428,18 +428,18 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 /// use std::any::Any;
 ///
 /// # #[allow(dead_code)]
-/// fn foo<T:Reflect+'static>(x: &T) {
+/// fn foo<T: Reflect + 'static>(x: &T) {
 ///     let any: &Any = x;
 ///     if any.is::<u32>() { println!("u32"); }
 /// }
 /// ```
 ///
-/// Without the declaration `T:Reflect`, `foo` would not type check
+/// Without the declaration `T: Reflect`, `foo` would not type check
 /// (note: as a matter of style, it would be preferable to write
-/// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but
+/// `T: Any`, because `T: Any` implies `T: Reflect` and `T: 'static`, but
 /// we use `Reflect` here to show how it works). The `Reflect` bound
 /// thus serves to alert `foo`'s caller to the fact that `foo` may
-/// behave differently depending on whether `T=u32` or not. In
+/// behave differently depending on whether `T = u32` or not. In
 /// particular, thanks to the `Reflect` bound, callers know that a
 /// function declared like `fn bar<T>(...)` will always act in
 /// precisely the same way no matter what type `T` is supplied,
index e3e8bcab4f1d71d75697f78662e09f5de07f897f..99a74cf09f571ac5987dab52b02ce18302fdaa6b 100644 (file)
@@ -1153,7 +1153,7 @@ impl isize {
         intrinsics::mul_with_overflow }
 }
 
-// `Int` + `UnsignedInt` implemented for signed integers
+// `Int` + `UnsignedInt` implemented for unsigned integers
 macro_rules! uint_impl {
     ($ActualT:ty, $BITS:expr,
      $ctpop:path,
@@ -1457,8 +1457,8 @@ pub fn checked_add(self, other: Self) -> Option<Self> {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!((-127i8).checked_sub(1), Some(-128));
-        /// assert_eq!((-128i8).checked_sub(1), None);
+        /// assert_eq!(1u8.checked_sub(1), Some(0));
+        /// assert_eq!(0u8.checked_sub(1), None);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1493,9 +1493,8 @@ pub fn checked_mul(self, other: Self) -> Option<Self> {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!((-127i8).checked_div(-1), Some(127));
-        /// assert_eq!((-128i8).checked_div(-1), None);
-        /// assert_eq!((1i8).checked_div(0), None);
+        /// assert_eq!(128u8.checked_div(2), Some(64));
+        /// assert_eq!(1u8.checked_div(0), None);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1591,16 +1590,15 @@ pub fn checked_shr(self, rhs: u32) -> Option<Self> {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(100i8.saturating_add(1), 101);
-        /// assert_eq!(100i8.saturating_add(127), 127);
+        /// assert_eq!(100u8.saturating_add(1), 101);
+        /// assert_eq!(200u8.saturating_add(127), 255);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn saturating_add(self, other: Self) -> Self {
             match self.checked_add(other) {
-                Some(x)                       => x,
-                None if other >= Self::zero() => Self::max_value(),
-                None => Self::min_value(),
+                Some(x) => x,
+                None => Self::max_value(),
             }
         }
 
@@ -1612,16 +1610,15 @@ pub fn saturating_add(self, other: Self) -> Self {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(100i8.saturating_sub(127), -27);
-        /// assert_eq!((-100i8).saturating_sub(127), -128);
+        /// assert_eq!(100u8.saturating_sub(27), 73);
+        /// assert_eq!(13u8.saturating_sub(127), 0);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn saturating_sub(self, other: Self) -> Self {
             match self.checked_sub(other) {
-                Some(x)                       => x,
-                None if other >= Self::zero() => Self::min_value(),
-                None => Self::max_value(),
+                Some(x) => x,
+                None => Self::min_value(),
             }
         }
 
@@ -1652,8 +1649,8 @@ pub fn saturating_mul(self, other: Self) -> Self {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(100i8.wrapping_add(27), 127);
-        /// assert_eq!(100i8.wrapping_add(127), -29);
+        /// assert_eq!(200u8.wrapping_add(55), 255);
+        /// assert_eq!(200u8.wrapping_add(155), 99);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1671,8 +1668,8 @@ pub fn wrapping_add(self, rhs: Self) -> Self {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(0i8.wrapping_sub(127), -127);
-        /// assert_eq!((-2i8).wrapping_sub(127), 127);
+        /// assert_eq!(100u8.wrapping_sub(100), 0);
+        /// assert_eq!(100u8.wrapping_sub(155), 201);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1690,8 +1687,8 @@ pub fn wrapping_sub(self, rhs: Self) -> Self {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(10i8.wrapping_mul(12), 120);
-        /// assert_eq!(11i8.wrapping_mul(12), -124);
+        /// assert_eq!(10u8.wrapping_mul(12), 120);
+        /// assert_eq!(25u8.wrapping_mul(12), 44);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
@@ -1701,15 +1698,11 @@ pub fn wrapping_mul(self, rhs: Self) -> Self {
             }
         }
 
-        /// Wrapping (modular) division. Computes `self / other`,
-        /// wrapping around at the boundary of the type.
-        ///
-        /// The only case where such wrapping can occur is when one
-        /// divides `MIN / -1` on a signed type (where `MIN` is the
-        /// negative minimal value for the type); this is equivalent
-        /// to `-MIN`, a positive value that is too large to represent
-        /// in the type. In such a case, this function returns `MIN`
-        /// itself.
+        /// Wrapping (modular) division. Computes `self / other`.
+        /// Wrapped division on unsigned types is just normal division.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
         ///
         /// # Examples
         ///
@@ -1717,21 +1710,19 @@ pub fn wrapping_mul(self, rhs: Self) -> Self {
         ///
         /// ```
         /// assert_eq!(100u8.wrapping_div(10), 10);
-        /// assert_eq!((-128i8).wrapping_div(-1), -128);
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
         pub fn wrapping_div(self, rhs: Self) -> Self {
-            self.overflowing_div(rhs).0
+            self / rhs
         }
 
-        /// Wrapping (modular) remainder. Computes `self % other`,
-        /// wrapping around at the boundary of the type.
-        ///
-        /// Such wrap-around never actually occurs mathematically;
-        /// implementation artifacts make `x % y` invalid for `MIN /
-        /// -1` on a signed type (where `MIN` is the negative
-        /// minimal value). In such a case, this function returns `0`.
+        /// Wrapping (modular) remainder. Computes `self % other`.
+        /// Wrapped remainder calculation on unsigned types is
+        /// just the regular remainder calculation.
+        /// There's no way wrapping could ever happen.
+        /// This function exists, so that all operations
+        /// are accounted for in the wrapping operations.
         ///
         /// # Examples
         ///
@@ -1739,30 +1730,32 @@ pub fn wrapping_div(self, rhs: Self) -> Self {
         ///
         /// ```
         /// assert_eq!(100i8.wrapping_rem(10), 0);
-        /// assert_eq!((-128i8).wrapping_rem(-1), 0);
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
         pub fn wrapping_rem(self, rhs: Self) -> Self {
-            self.overflowing_rem(rhs).0
+            self % rhs
         }
 
         /// Wrapping (modular) negation. Computes `-self`,
         /// wrapping around at the boundary of the type.
         ///
-        /// The only case where such wrapping can occur is when one
-        /// negates `MIN` on a signed type (where `MIN` is the
-        /// negative minimal value for the type); this is a positive
-        /// value that is too large to represent in the type. In such
-        /// a case, this function returns `MIN` itself.
+        /// Since unsigned types do not have negative equivalents
+        /// all applications of this function will wrap (except for `-0`).
+        /// For values smaller than the corresponding signed type's maximum
+        /// the result is the same as casting the corresponding signed value.
+        /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where
+        /// `MAX` is the corresponding signed type's maximum.
         ///
         /// # Examples
         ///
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(100i8.wrapping_neg(), -100);
-        /// assert_eq!((-128i8).wrapping_neg(), -128);
+        /// assert_eq!(100u8.wrapping_neg(), 156);
+        /// assert_eq!(0u8.wrapping_neg(), 0);
+        /// assert_eq!(180u8.wrapping_neg(), 76);
+        /// assert_eq!(180u8.wrapping_neg(), (127 + 1) - (180u8 - (127 + 1)));
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[inline(always)]
@@ -2002,7 +1995,7 @@ pub fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
         /// Basic usage:
         ///
         /// ```
-        /// assert_eq!(2i32.pow(4), 16);
+        /// assert_eq!(2u32.pow(4), 16);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
index 6144f97b1308094ab349b378f29e550286c187d1..d1c5b175bb03464b94aad403057f21a70046cc28 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
     /// A method called when the value goes out of scope.
+    ///
+    /// When this method has been called, `self` has not yet been deallocated.
+    /// If it were, `self` would be a dangling reference.
+    ///
+    /// After this function is over, the memory of `self` will be deallocated.
+    ///
+    /// # Panics
+    ///
+    /// Given that a `panic!` will call `drop()` as it unwinds, any `panic!` in
+    /// a `drop()` implementation will likely abort.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
index 583bb57a4a6f172c19ebd53a72926724c2b065d1..6107564b4aeff7344cdda938226e8e9904ff8d5b 100644 (file)
@@ -478,8 +478,13 @@ fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord {
     fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
         assert!(self.len() == src.len(),
                 "destination and source slices have different lengths");
-        for (dst, src) in self.iter_mut().zip(src) {
-            dst.clone_from(src);
+        // NOTE: We need to explicitly slice them to the same length
+        // for bounds checking to be elided, and the optimizer will
+        // generate memcpy for simple cases (for example T = u8).
+        let len = self.len();
+        let src = &src[..len];
+        for i in 0..len {
+            self[i].clone_from(&src[i]);
         }
     }
 }
index a5e8522623a2eaf6ae3c3c2238fedd692b03c1f8..0c5356c0222359c70151d13a3da43bdc8aa07ce4 100644 (file)
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 #[inline]
-pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8)
-{
+pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8) {
     if *position == vec.len() {
         vec.push(byte);
     } else {
@@ -20,13 +19,9 @@ pub fn write_to_vec(vec: &mut Vec<u8>, position: &mut usize, byte: u8)
     *position += 1;
 }
 
-pub fn write_unsigned_leb128(out: &mut Vec<u8>,
-                             start_position: usize,
-                             mut value: u64)
-                             -> usize {
+pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, mut value: u64) -> usize {
     let mut position = start_position;
-    loop
-    {
+    loop {
         let mut byte = (value & 0x7F) as u8;
         value >>= 7;
         if value != 0 {
@@ -43,9 +38,7 @@ pub fn write_unsigned_leb128(out: &mut Vec<u8>,
     return position - start_position;
 }
 
-pub fn read_unsigned_leb128(data: &[u8],
-                            start_position: usize)
-                            -> (u64, usize) {
+pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize) {
     let mut result = 0;
     let mut shift = 0;
     let mut position = start_position;
@@ -63,15 +56,13 @@ pub fn read_unsigned_leb128(data: &[u8],
 }
 
 
-pub fn write_signed_leb128(out: &mut Vec<u8>,
-                           start_position: usize,
-                           mut value: i64) -> usize {
+pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, mut value: i64) -> usize {
     let mut position = start_position;
 
     loop {
         let mut byte = (value as u8) & 0x7f;
         value >>= 7;
-        let more = !((((value == 0 ) && ((byte & 0x40) == 0)) ||
+        let more = !((((value == 0) && ((byte & 0x40) == 0)) ||
                       ((value == -1) && ((byte & 0x40) != 0))));
         if more {
             byte |= 0x80; // Mark this byte to show that more bytes will follow.
@@ -87,9 +78,7 @@ pub fn write_signed_leb128(out: &mut Vec<u8>,
     return position - start_position;
 }
 
-pub fn read_signed_leb128(data: &[u8],
-                          start_position: usize)
-                          -> (i64, usize) {
+pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
     let mut result = 0;
     let mut shift = 0;
     let mut position = start_position;
@@ -107,7 +96,7 @@ pub fn read_signed_leb128(data: &[u8],
     }
 
     if (shift < 64) && ((byte & 0x40) != 0) {
-        /* sign extend */
+        // sign extend
         result |= -(1i64 << shift);
     }
 
index fe15f1c53f99257f126d2230fa3fcc87a06d61b7..913314c4899a2260c69eb34c8cd5bb3c07440fb0 100644 (file)
 #[cfg(test)]
 extern crate serialize as rustc_serialize; // Used by RustcEncodable
 
-#[macro_use] extern crate log;
+#[macro_use]
+extern crate log;
 
-#[cfg(test)] extern crate test;
+#[cfg(test)]
+extern crate test;
 
 pub mod opaque;
 pub mod leb128;
@@ -154,7 +156,11 @@ pub struct Doc<'a> {
 
 impl<'doc> Doc<'doc> {
     pub fn new(data: &'doc [u8]) -> Doc<'doc> {
-        Doc { data: data, start: 0, end: data.len() }
+        Doc {
+            data: data,
+            start: 0,
+            end: data.len(),
+        }
     }
 
     pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
@@ -183,36 +189,35 @@ pub struct TaggedDoc<'a> {
 pub enum EbmlEncoderTag {
     // tags 00..1f are reserved for auto-serialization.
     // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
-
-    EsU8       = 0x00, // + 1 byte
-    EsU16      = 0x01, // + 2 bytes
-    EsU32      = 0x02, // + 4 bytes
-    EsU64      = 0x03, // + 8 bytes
-    EsI8       = 0x04, // + 1 byte
-    EsI16      = 0x05, // + 2 bytes
-    EsI32      = 0x06, // + 4 bytes
-    EsI64      = 0x07, // + 8 bytes
-    EsBool     = 0x08, // + 1 byte
-    EsChar     = 0x09, // + 4 bytes
-    EsF32      = 0x0a, // + 4 bytes
-    EsF64      = 0x0b, // + 8 bytes
-    EsSub8     = 0x0c, // + 1 byte
-    EsSub32    = 0x0d, // + 4 bytes
+    EsU8 = 0x00, // + 1 byte
+    EsU16 = 0x01, // + 2 bytes
+    EsU32 = 0x02, // + 4 bytes
+    EsU64 = 0x03, // + 8 bytes
+    EsI8 = 0x04, // + 1 byte
+    EsI16 = 0x05, // + 2 bytes
+    EsI32 = 0x06, // + 4 bytes
+    EsI64 = 0x07, // + 8 bytes
+    EsBool = 0x08, // + 1 byte
+    EsChar = 0x09, // + 4 bytes
+    EsF32 = 0x0a, // + 4 bytes
+    EsF64 = 0x0b, // + 8 bytes
+    EsSub8 = 0x0c, // + 1 byte
+    EsSub32 = 0x0d, // + 4 bytes
     // 0x0e and 0x0f are reserved
-
-    EsStr      = 0x10,
-    EsEnum     = 0x11, // encodes the variant id as the first EsSub*
-    EsVec      = 0x12, // encodes the # of elements as the first EsSub*
-    EsVecElt   = 0x13,
-    EsMap      = 0x14, // encodes the # of pairs as the first EsSub*
-    EsMapKey   = 0x15,
-    EsMapVal   = 0x16,
-    EsOpaque   = 0x17,
+    EsStr = 0x10,
+    EsEnum = 0x11, // encodes the variant id as the first EsSub*
+    EsVec = 0x12, // encodes the # of elements as the first EsSub*
+    EsVecElt = 0x13,
+    EsMap = 0x14, // encodes the # of pairs as the first EsSub*
+    EsMapKey = 0x15,
+    EsMapVal = 0x16,
+    EsOpaque = 0x17,
 }
 
 const NUM_TAGS: usize = 0x1000;
 const NUM_IMPLICIT_TAGS: usize = 0x0e;
 
+#[cfg_attr(rustfmt, rustfmt_skip)]
 static TAG_IMPLICIT_LEN: [i8; NUM_IMPLICIT_TAGS] = [
     1, 2, 4, 8, // EsU*
     1, 2, 4, 8, // ESI*
@@ -228,7 +233,7 @@ pub enum Error {
     InvalidTag(usize),
     Expected(String),
     IoError(std::io::Error),
-    ApplicationError(String)
+    ApplicationError(String),
 }
 
 impl fmt::Display for Error {
@@ -248,11 +253,10 @@ pub mod reader {
     use serialize;
 
     use super::opaque;
-    use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32,
-        EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64,
-        EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
-        EsOpaque, EbmlEncoderTag, Doc, TaggedDoc,
-        Error, IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN };
+    use super::{ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
+                EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32,
+                EsChar, EsStr, EsMapVal, EsOpaque, EbmlEncoderTag, Doc, TaggedDoc, Error,
+                IntTooBig, InvalidTag, Expected, NUM_IMPLICIT_TAGS, TAG_IMPLICIT_LEN};
 
     pub type DecodeResult<T> = Result<T, Error>;
     // rbml reading
@@ -272,15 +276,21 @@ macro_rules! try_or {
     #[derive(Copy, Clone)]
     pub struct Res {
         pub val: usize,
-        pub next: usize
+        pub next: usize,
     }
 
     pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
         let v = data[start] as usize;
         if v < 0xf0 {
-            Ok(Res { val: v, next: start + 1 })
+            Ok(Res {
+                val: v,
+                next: start + 1,
+            })
         } else if v > 0xf0 {
-            Ok(Res { val: ((v & 0xf) << 8) | data[start + 1] as usize, next: start + 2 })
+            Ok(Res {
+                val: ((v & 0xf) << 8) | data[start + 1] as usize,
+                next: start + 2,
+            })
         } else {
             // every tag starting with byte 0xf0 is an overlong form, which is prohibited.
             Err(InvalidTag(v))
@@ -291,25 +301,31 @@ pub fn tag_at(data: &[u8], start: usize) -> DecodeResult<Res> {
     fn vuint_at_slow(data: &[u8], start: usize) -> DecodeResult<Res> {
         let a = data[start];
         if a & 0x80 != 0 {
-            return Ok(Res {val: (a & 0x7f) as usize, next: start + 1});
+            return Ok(Res {
+                val: (a & 0x7f) as usize,
+                next: start + 1,
+            });
         }
         if a & 0x40 != 0 {
-            return Ok(Res {val: ((a & 0x3f) as usize) << 8 |
-                        (data[start + 1] as usize),
-                    next: start + 2});
+            return Ok(Res {
+                val: ((a & 0x3f) as usize) << 8 | (data[start + 1] as usize),
+                next: start + 2,
+            });
         }
         if a & 0x20 != 0 {
-            return Ok(Res {val: ((a & 0x1f) as usize) << 16 |
-                        (data[start + 1] as usize) << 8 |
-                        (data[start + 2] as usize),
-                    next: start + 3});
+            return Ok(Res {
+                val: ((a & 0x1f) as usize) << 16 | (data[start + 1] as usize) << 8 |
+                     (data[start + 2] as usize),
+                next: start + 3,
+            });
         }
         if a & 0x10 != 0 {
-            return Ok(Res {val: ((a & 0x0f) as usize) << 24 |
-                        (data[start + 1] as usize) << 16 |
-                        (data[start + 2] as usize) << 8 |
-                        (data[start + 3] as usize),
-                    next: start + 4});
+            return Ok(Res {
+                val: ((a & 0x0f) as usize) << 24 | (data[start + 1] as usize) << 16 |
+                     (data[start + 2] as usize) << 8 |
+                     (data[start + 3] as usize),
+                next: start + 4,
+            });
         }
         Err(IntTooBig(a as usize))
     }
@@ -338,13 +354,22 @@ pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
         // most significant bit is set etc. we can replace up to three
         // "and+branch" with a single table lookup which gives us a measured
         // speedup of around 2x on x86_64.
-        static SHIFT_MASK_TABLE: [(usize, u32); 16] = [
-            (0, 0x0), (0, 0x0fffffff),
-            (8, 0x1fffff), (8, 0x1fffff),
-            (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
-            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f),
-            (24, 0x7f), (24, 0x7f), (24, 0x7f), (24, 0x7f)
-        ];
+        static SHIFT_MASK_TABLE: [(usize, u32); 16] = [(0, 0x0),
+                                                       (0, 0x0fffffff),
+                                                       (8, 0x1fffff),
+                                                       (8, 0x1fffff),
+                                                       (16, 0x3fff),
+                                                       (16, 0x3fff),
+                                                       (16, 0x3fff),
+                                                       (16, 0x3fff),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f),
+                                                       (24, 0x7f)];
 
         unsafe {
             let ptr = data.as_ptr().offset(start as isize) as *const u32;
@@ -361,7 +386,10 @@ pub fn vuint_at(data: &[u8], start: usize) -> DecodeResult<Res> {
 
     pub fn tag_len_at(data: &[u8], tag: Res) -> DecodeResult<Res> {
         if tag.val < NUM_IMPLICIT_TAGS && TAG_IMPLICIT_LEN[tag.val] >= 0 {
-            Ok(Res { val: TAG_IMPLICIT_LEN[tag.val] as usize, next: tag.next })
+            Ok(Res {
+                val: TAG_IMPLICIT_LEN[tag.val] as usize,
+                next: tag.next,
+            })
         } else {
             vuint_at(data, tag.next)
         }
@@ -373,7 +401,11 @@ pub fn doc_at<'a>(data: &'a [u8], start: usize) -> DecodeResult<TaggedDoc<'a>> {
         let end = elt_size.next + elt_size.val;
         Ok(TaggedDoc {
             tag: elt_tag.val,
-            doc: Doc { data: data, start: elt_size.next, end: end }
+            doc: Doc {
+                data: data,
+                start: elt_size.next,
+                end: end,
+            },
         })
     }
 
@@ -384,8 +416,11 @@ pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
             let elt_size = try_or!(tag_len_at(d.data, elt_tag), None);
             pos = elt_size.next + elt_size.val;
             if elt_tag.val == tg {
-                return Some(Doc { data: d.data, start: elt_size.next,
-                                  end: pos });
+                return Some(Doc {
+                    data: d.data,
+                    start: elt_size.next,
+                    end: pos,
+                });
             }
         }
         None
@@ -402,9 +437,7 @@ pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
     }
 
     pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
-        DocsIterator {
-            d: d
-        }
+        DocsIterator { d: d }
     }
 
     pub struct DocsIterator<'a> {
@@ -465,8 +498,8 @@ fn next(&mut self) -> Option<Doc<'a>> {
         }
     }
 
-    pub fn with_doc_data<T, F>(d: Doc, f: F) -> T where
-        F: FnOnce(&[u8]) -> T,
+    pub fn with_doc_data<T, F>(d: Doc, f: F) -> T
+        where F: FnOnce(&[u8]) -> T
     {
         f(&d.data[d.start..d.end])
     }
@@ -485,30 +518,48 @@ pub fn doc_as_u64(d: Doc) -> u64 {
             // of the page and segfault.
 
             let mut b = [0; 8];
-            b.clone_from_slice(&d.data[d.end-8..d.end]);
+            b.clone_from_slice(&d.data[d.end - 8..d.end]);
             let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() };
             let len = d.end - d.start;
             if len < 8 {
-                data & ((1<<(len*8))-1)
+                data & ((1 << (len * 8)) - 1)
             } else {
                 data
             }
         } else {
             let mut result = 0;
             for b in &d.data[d.start..d.end] {
-                result = (result<<8) + (*b as u64);
+                result = (result << 8) + (*b as u64);
             }
             result
         }
     }
 
-    #[inline] pub fn doc_as_u16(d: Doc) -> u16 { doc_as_u64(d) as u16 }
-    #[inline] pub fn doc_as_u32(d: Doc) -> u32 { doc_as_u64(d) as u32 }
+    #[inline]
+    pub fn doc_as_u16(d: Doc) -> u16 {
+        doc_as_u64(d) as u16
+    }
+    #[inline]
+    pub fn doc_as_u32(d: Doc) -> u32 {
+        doc_as_u64(d) as u32
+    }
 
-    #[inline] pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
-    #[inline] pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
-    #[inline] pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
-    #[inline] pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
+    #[inline]
+    pub fn doc_as_i8(d: Doc) -> i8 {
+        doc_as_u8(d) as i8
+    }
+    #[inline]
+    pub fn doc_as_i16(d: Doc) -> i16 {
+        doc_as_u16(d) as i16
+    }
+    #[inline]
+    pub fn doc_as_i32(d: Doc) -> i32 {
+        doc_as_u32(d) as i32
+    }
+    #[inline]
+    pub fn doc_as_i64(d: Doc) -> i64 {
+        doc_as_u64(d) as i64
+    }
 
     pub struct Decoder<'a> {
         parent: Doc<'a>,
@@ -519,18 +570,16 @@ impl<'doc> Decoder<'doc> {
         pub fn new(d: Doc<'doc>) -> Decoder<'doc> {
             Decoder {
                 parent: d,
-                pos: d.start
+                pos: d.start,
             }
         }
 
         fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
             debug!(". next_doc(exp_tag={:?})", exp_tag);
             if self.pos >= self.parent.end {
-                return Err(Expected(format!("no more documents in \
-                                             current node!")));
+                return Err(Expected(format!("no more documents in current node!")));
             }
-            let TaggedDoc { tag: r_tag, doc: r_doc } =
-                try!(doc_at(self.parent.data, self.pos));
+            let TaggedDoc { tag: r_tag, doc: r_doc } = try!(doc_at(self.parent.data, self.pos));
             debug!("self.parent={:?}-{:?} self.pos={:?} r_tag={:?} r_doc={:?}-{:?}",
                    self.parent.start,
                    self.parent.end,
@@ -539,20 +588,22 @@ fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> DecodeResult<Doc<'doc>> {
                    r_doc.start,
                    r_doc.end);
             if r_tag != (exp_tag as usize) {
-                return Err(Expected(format!("expected EBML doc with tag {:?} but \
-                                             found tag {:?}", exp_tag, r_tag)));
+                return Err(Expected(format!("expected EBML doc with tag {:?} but found tag {:?}",
+                                            exp_tag,
+                                            r_tag)));
             }
             if r_doc.end > self.parent.end {
-                return Err(Expected(format!("invalid EBML, child extends to \
-                                             {:#x}, parent to {:#x}",
-                                            r_doc.end, self.parent.end)));
+                return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \
+                                             {:#x}",
+                                            r_doc.end,
+                                            self.parent.end)));
             }
             self.pos = r_doc.end;
             Ok(r_doc)
         }
 
-        fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn push_doc<T, F>(&mut self, exp_tag: EbmlEncoderTag, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             let d = try!(self.next_doc(exp_tag));
             let old_parent = self.parent;
@@ -571,20 +622,23 @@ fn _next_sub(&mut self) -> DecodeResult<usize> {
                 return Ok(0);
             }
 
-            let TaggedDoc { tag: r_tag, doc: r_doc } =
-                try!(doc_at(self.parent.data, self.pos));
+            let TaggedDoc { tag: r_tag, doc: r_doc } = try!(doc_at(self.parent.data, self.pos));
             let r = if r_tag == (EsSub8 as usize) {
                 doc_as_u8(r_doc) as usize
             } else if r_tag == (EsSub32 as usize) {
                 doc_as_u32(r_doc) as usize
             } else {
-                return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but \
-                                             found tag {:?}", EsSub8, EsSub32, r_tag)));
+                return Err(Expected(format!("expected EBML doc with tag {:?} or {:?} but found \
+                                             tag {:?}",
+                                            EsSub8,
+                                            EsSub32,
+                                            r_tag)));
             };
             if r_doc.end > self.parent.end {
-                return Err(Expected(format!("invalid EBML, child extends to \
-                                             {:#x}, parent to {:#x}",
-                                            r_doc.end, self.parent.end)));
+                return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \
+                                             {:#x}",
+                                            r_doc.end,
+                                            self.parent.end)));
             }
             self.pos = r_doc.end;
             debug!("_next_sub result={:?}", r);
@@ -597,14 +651,13 @@ fn _next_sub(&mut self) -> DecodeResult<usize> {
         // all tags between them should be valid, in the order of u8, u16, u32 and u64.
         fn _next_int(&mut self,
                      first_tag: EbmlEncoderTag,
-                     last_tag: EbmlEncoderTag) -> DecodeResult<u64> {
+                     last_tag: EbmlEncoderTag)
+                     -> DecodeResult<u64> {
             if self.pos >= self.parent.end {
-                return Err(Expected(format!("no more documents in \
-                                             current node!")));
+                return Err(Expected(format!("no more documents in current node!")));
             }
 
-            let TaggedDoc { tag: r_tag, doc: r_doc } =
-                try!(doc_at(self.parent.data, self.pos));
+            let TaggedDoc { tag: r_tag, doc: r_doc } = try!(doc_at(self.parent.data, self.pos));
             let r = if first_tag as usize <= r_tag && r_tag <= last_tag as usize {
                 match r_tag - first_tag as usize {
                     0 => doc_as_u8(r_doc) as u64,
@@ -615,26 +668,29 @@ fn _next_int(&mut self,
                 }
             } else {
                 return Err(Expected(format!("expected EBML doc with tag {:?} through {:?} but \
-                                             found tag {:?}", first_tag, last_tag, r_tag)));
+                                             found tag {:?}",
+                                            first_tag,
+                                            last_tag,
+                                            r_tag)));
             };
             if r_doc.end > self.parent.end {
-                return Err(Expected(format!("invalid EBML, child extends to \
-                                             {:#x}, parent to {:#x}",
-                                            r_doc.end, self.parent.end)));
+                return Err(Expected(format!("invalid EBML, child extends to {:#x}, parent to \
+                                             {:#x}",
+                                            r_doc.end,
+                                            self.parent.end)));
             }
             self.pos = r_doc.end;
             debug!("_next_int({:?}, {:?}) result={:?}", first_tag, last_tag, r);
             Ok(r)
         }
 
-        pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R> where
-            F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult<R>,
+        pub fn read_opaque<R, F>(&mut self, op: F) -> DecodeResult<R>
+            where F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult<R>
         {
             let doc = try!(self.next_doc(EsOpaque));
 
             let result = {
-                let mut opaque_decoder = opaque::Decoder::new(doc.data,
-                                                              doc.start);
+                let mut opaque_decoder = opaque::Decoder::new(doc.data, doc.start);
                 try!(op(&mut opaque_decoder, doc))
             };
 
@@ -652,12 +708,22 @@ pub fn advance(&mut self, bytes: usize) {
 
     impl<'doc> serialize::Decoder for Decoder<'doc> {
         type Error = Error;
-        fn read_nil(&mut self) -> DecodeResult<()> { Ok(()) }
+        fn read_nil(&mut self) -> DecodeResult<()> {
+            Ok(())
+        }
 
-        fn read_u64(&mut self) -> DecodeResult<u64> { self._next_int(EsU8, EsU64) }
-        fn read_u32(&mut self) -> DecodeResult<u32> { Ok(try!(self._next_int(EsU8, EsU32)) as u32) }
-        fn read_u16(&mut self) -> DecodeResult<u16> { Ok(try!(self._next_int(EsU8, EsU16)) as u16) }
-        fn read_u8(&mut self) -> DecodeResult<u8> { Ok(doc_as_u8(try!(self.next_doc(EsU8)))) }
+        fn read_u64(&mut self) -> DecodeResult<u64> {
+            self._next_int(EsU8, EsU64)
+        }
+        fn read_u32(&mut self) -> DecodeResult<u32> {
+            Ok(try!(self._next_int(EsU8, EsU32)) as u32)
+        }
+        fn read_u16(&mut self) -> DecodeResult<u16> {
+            Ok(try!(self._next_int(EsU8, EsU16)) as u16)
+        }
+        fn read_u8(&mut self) -> DecodeResult<u8> {
+            Ok(doc_as_u8(try!(self.next_doc(EsU8))))
+        }
         fn read_uint(&mut self) -> DecodeResult<usize> {
             let v = try!(self._next_int(EsU8, EsU64));
             if v > (::std::usize::MAX as u64) {
@@ -667,10 +733,18 @@ fn read_uint(&mut self) -> DecodeResult<usize> {
             }
         }
 
-        fn read_i64(&mut self) -> DecodeResult<i64> { Ok(try!(self._next_int(EsI8, EsI64)) as i64) }
-        fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self._next_int(EsI8, EsI32)) as i32) }
-        fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self._next_int(EsI8, EsI16)) as i16) }
-        fn read_i8(&mut self) -> DecodeResult<i8> { Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8) }
+        fn read_i64(&mut self) -> DecodeResult<i64> {
+            Ok(try!(self._next_int(EsI8, EsI64)) as i64)
+        }
+        fn read_i32(&mut self) -> DecodeResult<i32> {
+            Ok(try!(self._next_int(EsI8, EsI32)) as i32)
+        }
+        fn read_i16(&mut self) -> DecodeResult<i16> {
+            Ok(try!(self._next_int(EsI8, EsI16)) as i16)
+        }
+        fn read_i8(&mut self) -> DecodeResult<i8> {
+            Ok(doc_as_u8(try!(self.next_doc(EsI8))) as i8)
+        }
         fn read_int(&mut self) -> DecodeResult<isize> {
             let v = try!(self._next_int(EsI8, EsI64)) as i64;
             if v > (isize::MAX as i64) || v < (isize::MIN as i64) {
@@ -701,8 +775,8 @@ fn read_str(&mut self) -> DecodeResult<String> {
         }
 
         // Compound types:
-        fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_enum({})", name);
 
@@ -719,9 +793,8 @@ fn read_enum<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T> where
             Ok(result)
         }
 
-        fn read_enum_variant<T, F>(&mut self, _: &[&str],
-                                   mut f: F) -> DecodeResult<T>
-            where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
+        fn read_enum_variant<T, F>(&mut self, _: &[&str], mut f: F) -> DecodeResult<T>
+            where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>
         {
             debug!("read_enum_variant()");
             let idx = try!(self._next_sub());
@@ -730,16 +803,15 @@ fn read_enum_variant<T, F>(&mut self, _: &[&str],
             f(self, idx)
         }
 
-        fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_enum_variant_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_enum_variant_arg(idx={})", idx);
             f(self)
         }
 
-        fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
-                                          mut f: F) -> DecodeResult<T>
-            where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
+        fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], mut f: F) -> DecodeResult<T>
+            where F: FnMut(&mut Decoder<'doc>, usize) -> DecodeResult<T>
         {
             debug!("read_enum_struct_variant()");
             let idx = try!(self._next_sub());
@@ -752,67 +824,66 @@ fn read_enum_struct_variant_field<T, F>(&mut self,
                                                 name: &str,
                                                 idx: usize,
                                                 f: F)
-                                                -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+                                                -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
-                debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
+            debug!("read_enum_struct_variant_arg(name={}, idx={})", name, idx);
             f(self)
         }
 
-        fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_struct<T, F>(&mut self, name: &str, _: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_struct(name={})", name);
             f(self)
         }
 
-        fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_struct_field<T, F>(&mut self, name: &str, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_struct_field(name={}, idx={})", name, idx);
             f(self)
         }
 
-        fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_tuple()");
             self.read_seq(move |d, len| {
                 if len == tuple_len {
                     f(d)
                 } else {
-                    Err(Expected(format!("Expected tuple of length `{}`, \
-                                          found tuple of length `{}`", tuple_len, len)))
+                    Err(Expected(format!("Expected tuple of length `{}`, found tuple of length \
+                                          `{}`",
+                                         tuple_len,
+                                         len)))
                 }
             })
         }
 
-        fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_tuple_arg(idx={})", idx);
             self.read_seq_elt(idx, f)
         }
 
-        fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_tuple_struct<T, F>(&mut self, name: &str, len: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_tuple_struct(name={})", name);
             self.read_tuple(len, f)
         }
 
-        fn read_tuple_struct_arg<T, F>(&mut self,
-                                       idx: usize,
-                                       f: F)
-                                       -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_tuple_struct_arg(idx={})", idx);
             self.read_tuple_arg(idx, f)
         }
 
-        fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
-            F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
+        fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T>
+            where F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>
         {
             debug!("read_option()");
             self.read_enum("Option", move |this| {
@@ -820,16 +891,14 @@ fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
                     match idx {
                         0 => f(this, false),
                         1 => f(this, true),
-                        _ => {
-                            Err(Expected(format!("Expected None or Some")))
-                        }
+                        _ => Err(Expected(format!("Expected None or Some"))),
                     }
                 })
             })
         }
 
-        fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
+        fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>
         {
             debug!("read_seq()");
             self.push_doc(EsVec, move |d| {
@@ -839,15 +908,15 @@ fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where
             })
         }
 
-        fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_seq_elt(idx={})", idx);
             self.push_doc(EsVecElt, f)
         }
 
-        fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>,
+        fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>, usize) -> DecodeResult<T>
         {
             debug!("read_map()");
             self.push_doc(EsMap, move |d| {
@@ -857,15 +926,15 @@ fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T> where
             })
         }
 
-        fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_map_elt_key(idx={})", idx);
             self.push_doc(EsMapKey, f)
         }
 
-        fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T> where
-            F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>,
+        fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+            where F: FnOnce(&mut Decoder<'doc>) -> DecodeResult<T>
         {
             debug!("read_map_elt_val(idx={})", idx);
             self.push_doc(EsMapVal, f)
@@ -883,10 +952,9 @@ pub mod writer {
     use std::io::{self, SeekFrom, Cursor};
 
     use super::opaque;
-    use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
-        EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
-        EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
-        EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS };
+    use super::{EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16,
+                EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
+                EsOpaque, NUM_IMPLICIT_TAGS, NUM_TAGS};
 
     use serialize;
 
@@ -906,8 +974,7 @@ fn write_tag<W: Write>(w: &mut W, n: usize) -> EncodeResult {
         } else if 0x100 <= n && n < NUM_TAGS {
             w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
         } else {
-            Err(io::Error::new(io::ErrorKind::Other,
-                               &format!("invalid tag: {}", n)[..]))
+            Err(io::Error::new(io::ErrorKind::Other, &format!("invalid tag: {}", n)[..]))
         }
     }
 
@@ -915,29 +982,33 @@ fn write_sized_vuint<W: Write>(w: &mut W, n: usize, size: usize) -> EncodeResult
         match size {
             1 => w.write_all(&[0x80 | (n as u8)]),
             2 => w.write_all(&[0x40 | ((n >> 8) as u8), n as u8]),
-            3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8,
-                            n as u8]),
-            4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
-                            (n >> 8) as u8, n as u8]),
-            _ => Err(io::Error::new(io::ErrorKind::Other,
-                                    &format!("isize too big: {}", n)[..]))
+            3 => w.write_all(&[0x20 | ((n >> 16) as u8), (n >> 8) as u8, n as u8]),
+            4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8, (n >> 8) as u8, n as u8]),
+            _ => Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..])),
         }
     }
 
     pub fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
-        if n < 0x7f { return write_sized_vuint(w, n, 1); }
-        if n < 0x4000 { return write_sized_vuint(w, n, 2); }
-        if n < 0x200000 { return write_sized_vuint(w, n, 3); }
-        if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
-        Err(io::Error::new(io::ErrorKind::Other,
-                           &format!("isize too big: {}", n)[..]))
+        if n < 0x7f {
+            return write_sized_vuint(w, n, 1);
+        }
+        if n < 0x4000 {
+            return write_sized_vuint(w, n, 2);
+        }
+        if n < 0x200000 {
+            return write_sized_vuint(w, n, 3);
+        }
+        if n < 0x10000000 {
+            return write_sized_vuint(w, n, 4);
+        }
+        Err(io::Error::new(io::ErrorKind::Other, &format!("isize too big: {}", n)[..]))
     }
 
     impl<'a> Encoder<'a> {
         pub fn new(w: &'a mut Cursor<Vec<u8>>) -> Encoder<'a> {
             Encoder {
                 writer: w,
-                size_positions: vec!(),
+                size_positions: vec![],
                 relax_limit: 0,
             }
         }
@@ -970,7 +1041,7 @@ pub fn end_tag(&mut self) -> EncodeResult {
                 let mut buf = [0u8; RELAX_MAX_SIZE];
                 {
                     let last_size_pos = last_size_pos as usize;
-                    let data = &self.writer.get_ref()[last_size_pos+4..cur_pos as usize];
+                    let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize];
                     buf[..size].clone_from_slice(data);
                 }
 
@@ -987,8 +1058,8 @@ pub fn end_tag(&mut self) -> EncodeResult {
             Ok(())
         }
 
-        pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult where
-            F: FnOnce() -> EncodeResult,
+        pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult
+            where F: FnOnce() -> EncodeResult
         {
             try!(self.start_tag(tag_id));
             try!(blk());
@@ -1006,12 +1077,12 @@ pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
             let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
             // tagged integers are emitted in big-endian, with no
             // leading zeros.
-            let leading_zero_bytes = v.leading_zeros()/8;
+            let leading_zero_bytes = v.leading_zeros() / 8;
             self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..])
         }
 
         #[inline]
-        pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32)  -> EncodeResult {
+        pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult {
             self.wr_tagged_u64(tag_id, v as u64)
         }
 
@@ -1060,7 +1131,7 @@ fn wr_tagged_raw_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
             self.wr_tagged_raw_bytes(tag_id, &bytes)
         }
 
-        fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32)  -> EncodeResult{
+        fn wr_tagged_raw_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult {
             let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
             self.wr_tagged_raw_bytes(tag_id, &bytes)
         }
@@ -1120,13 +1191,12 @@ fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
                 self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
             } else {
                 Err(io::Error::new(io::ErrorKind::Other,
-                                   &format!("length or variant id too big: {}",
-                                            v)[..]))
+                                   &format!("length or variant id too big: {}", v)[..]))
             }
         }
 
-        pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult where
-            F: FnOnce(&mut opaque::Encoder) -> EncodeResult,
+        pub fn emit_opaque<F>(&mut self, f: F) -> EncodeResult
+            where F: FnOnce(&mut opaque::Encoder) -> EncodeResult
         {
             try!(self.start_tag(EsOpaque as usize));
 
@@ -1223,27 +1293,23 @@ fn emit_str(&mut self, v: &str) -> EncodeResult {
             self.wr_tagged_str(EsStr as usize, v)
         }
 
-        fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             try!(self.start_tag(EsEnum as usize));
             try!(f(self));
             self.end_tag()
         }
 
-        fn emit_enum_variant<F>(&mut self,
-                                _: &str,
-                                v_id: usize,
-                                _: usize,
-                                f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_enum_variant<F>(&mut self, _: &str, v_id: usize, _: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             try!(self._emit_tagged_sub(v_id));
             f(self)
         }
 
-        fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             f(self)
         }
@@ -1252,72 +1318,70 @@ fn emit_enum_struct_variant<F>(&mut self,
                                        v_name: &str,
                                        v_id: usize,
                                        cnt: usize,
-                                       f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+                                       f: F)
+                                       -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_enum_variant(v_name, v_id, cnt, f)
         }
 
-        fn emit_enum_struct_variant_field<F>(&mut self,
-                                             _: &str,
-                                             idx: usize,
-                                             f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_enum_variant_arg(idx, f)
         }
 
-        fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             f(self)
         }
 
-        fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             f(self)
         }
 
-        fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_seq(len, f)
         }
-        fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_seq_elt(idx, f)
         }
 
-        fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_seq(len, f)
         }
-        fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_seq_elt(idx, f)
         }
 
-        fn emit_option<F>(&mut self, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_option<F>(&mut self, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             self.emit_enum("Option", f)
         }
         fn emit_option_none(&mut self) -> EncodeResult {
             self.emit_enum_variant("None", 0, 0, |_| Ok(()))
         }
-        fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_option_some<F>(&mut self, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
 
             self.emit_enum_variant("Some", 1, 1, f)
         }
 
-        fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             if len == 0 {
                 // empty vector optimization
@@ -1330,8 +1394,8 @@ fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
             self.end_tag()
         }
 
-        fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
 
             try!(self.start_tag(EsVecElt as usize));
@@ -1339,8 +1403,8 @@ fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
             self.end_tag()
         }
 
-        fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             if len == 0 {
                 // empty map optimization
@@ -1353,8 +1417,8 @@ fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
             self.end_tag()
         }
 
-        fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
 
             try!(self.start_tag(EsMapKey as usize));
@@ -1362,8 +1426,8 @@ fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
             self.end_tag()
         }
 
-        fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+        fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+            where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
         {
             try!(self.start_tag(EsMapVal as usize));
             try!(f(self));
@@ -1461,12 +1525,14 @@ mod bench {
 
     #[bench]
     pub fn vuint_at_A_aligned(b: &mut Bencher) {
-        let data = (0..4*100).map(|i| {
-            match i % 2 {
-              0 => 0x80,
-              _ => i as u8,
-            }
-        }).collect::<Vec<_>>();
+        let data = (0..4 * 100)
+                       .map(|i| {
+                           match i % 2 {
+                               0 => 0x80,
+                               _ => i as u8,
+                           }
+                       })
+                       .collect::<Vec<_>>();
         let mut sum = 0;
         b.iter(|| {
             let mut i = 0;
@@ -1479,12 +1545,14 @@ pub fn vuint_at_A_aligned(b: &mut Bencher) {
 
     #[bench]
     pub fn vuint_at_A_unaligned(b: &mut Bencher) {
-        let data = (0..4*100+1).map(|i| {
-            match i % 2 {
-              1 => 0x80,
-              _ => i as u8
-            }
-        }).collect::<Vec<_>>();
+        let data = (0..4 * 100 + 1)
+                       .map(|i| {
+                           match i % 2 {
+                               1 => 0x80,
+                               _ => i as u8,
+                           }
+                       })
+                       .collect::<Vec<_>>();
         let mut sum = 0;
         b.iter(|| {
             let mut i = 1;
@@ -1497,13 +1565,15 @@ pub fn vuint_at_A_unaligned(b: &mut Bencher) {
 
     #[bench]
     pub fn vuint_at_D_aligned(b: &mut Bencher) {
-        let data = (0..4*100).map(|i| {
-            match i % 4 {
-              0 => 0x10,
-              3 => i as u8,
-              _ => 0
-            }
-        }).collect::<Vec<_>>();
+        let data = (0..4 * 100)
+                       .map(|i| {
+                           match i % 4 {
+                               0 => 0x10,
+                               3 => i as u8,
+                               _ => 0,
+                           }
+                       })
+                       .collect::<Vec<_>>();
         let mut sum = 0;
         b.iter(|| {
             let mut i = 0;
@@ -1516,13 +1586,15 @@ pub fn vuint_at_D_aligned(b: &mut Bencher) {
 
     #[bench]
     pub fn vuint_at_D_unaligned(b: &mut Bencher) {
-        let data = (0..4*100+1).map(|i| {
-            match i % 4 {
-              1 => 0x10,
-              0 => i as u8,
-              _ => 0
-            }
-        }).collect::<Vec<_>>();
+        let data = (0..4 * 100 + 1)
+                       .map(|i| {
+                           match i % 4 {
+                               1 => 0x10,
+                               0 => i as u8,
+                               _ => 0,
+                           }
+                       })
+                       .collect::<Vec<_>>();
         let mut sum = 0;
         b.iter(|| {
             let mut i = 1;
index 64756090e8b48ee36518e8da871364be552a5919..531a25dc1b766d8047e0e4ee47bd8a044e8825b1 100644 (file)
 
 use Error as DecodeError;
 use writer::EncodeResult;
-use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128,
-             write_unsigned_leb128};
+use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
 use std::io::{self, Write};
 use serialize;
 
-//=-----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
 // Encoder
-//=-----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
 
 pub struct Encoder<'a> {
     pub cursor: &'a mut io::Cursor<Vec<u8>>,
@@ -25,9 +24,7 @@ pub struct Encoder<'a> {
 
 impl<'a> Encoder<'a> {
     pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
-        Encoder {
-            cursor: cursor
-        }
+        Encoder { cursor: cursor }
     }
 }
 
@@ -101,7 +98,11 @@ fn emit_i8(&mut self, v: i8) -> EncodeResult {
     }
 
     fn emit_bool(&mut self, v: bool) -> EncodeResult {
-        self.emit_u8(if v { 1 } else { 0 })
+        self.emit_u8(if v {
+            1
+        } else {
+            0
+        })
     }
 
     fn emit_f64(&mut self, v: f64) -> EncodeResult {
@@ -125,7 +126,8 @@ fn emit_str(&mut self, v: &str) -> EncodeResult {
     }
 
     fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
-        where F: FnOnce(&mut Self) -> EncodeResult {
+        where F: FnOnce(&mut Self) -> EncodeResult
+    {
         f(self)
     }
 
@@ -133,76 +135,75 @@ fn emit_enum_variant<F>(&mut self,
                             _v_name: &str,
                             v_id: usize,
                             _len: usize,
-                            f: F) -> EncodeResult
+                            f: F)
+                            -> EncodeResult
         where F: FnOnce(&mut Self) -> EncodeResult
     {
         try!(self.emit_uint(v_id));
         f(self)
     }
 
-    fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult where
-            F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_enum_variant_arg<F>(&mut self, _: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
 
     fn emit_enum_struct_variant<F>(&mut self,
-                                       v_name: &str,
-                                       v_id: usize,
-                                       cnt: usize,
-                                       f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+                                   v_name: &str,
+                                   v_id: usize,
+                                   cnt: usize,
+                                   f: F)
+                                   -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_enum_variant(v_name, v_id, cnt, f)
     }
 
-    fn emit_enum_struct_variant_field<F>(&mut self,
-                                         _: &str,
-                                         idx: usize,
-                                         f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_enum_variant_arg(idx, f)
     }
 
-    fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_struct<F>(&mut self, _: &str, _len: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
 
-    fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_struct_field<F>(&mut self, _name: &str, _: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
 
-    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_tuple<F>(&mut self, len: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_seq(len, f)
     }
 
-    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_seq(len, f)
     }
 
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_option<F>(&mut self, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_option<F>(&mut self, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_enum("Option", f)
     }
@@ -211,40 +212,40 @@ fn emit_option_none(&mut self) -> EncodeResult {
         self.emit_enum_variant("None", 0, 0, |_| Ok(()))
     }
 
-    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_option_some<F>(&mut self, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         self.emit_enum_variant("Some", 1, 1, f)
     }
 
-    fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_seq<F>(&mut self, len: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         try!(self.emit_uint(len));
         f(self)
     }
 
-    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
 
-    fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_map<F>(&mut self, len: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         try!(self.emit_uint(len));
         f(self)
     }
 
-    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
 
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
+    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+        where F: FnOnce(&mut Encoder<'a>) -> EncodeResult
     {
         f(self)
     }
@@ -256,15 +257,13 @@ pub fn position(&self) -> usize {
     }
 
     pub fn from_rbml<'b: 'c, 'c>(rbml: &'c mut ::writer::Encoder<'b>) -> Encoder<'c> {
-        Encoder {
-            cursor: rbml.writer
-        }
+        Encoder { cursor: rbml.writer }
     }
 }
 
-//=-----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
 // Decoder
-//=-----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
 
 pub struct Decoder<'a> {
     pub data: &'a [u8],
@@ -275,7 +274,7 @@ impl<'a> Decoder<'a> {
     pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
         Decoder {
             data: data,
-            position: position
+            position: position,
         }
     }
 
@@ -349,9 +348,7 @@ fn read_i16(&mut self) -> Result<i16, Self::Error> {
     fn read_i8(&mut self) -> Result<i8, Self::Error> {
         let as_u8 = self.data[self.position];
         self.position += 1;
-        unsafe {
-            Ok(::std::mem::transmute(as_u8))
-        }
+        unsafe { Ok(::std::mem::transmute(as_u8)) }
     }
 
     fn read_int(&mut self) -> Result<isize, Self::Error> {
@@ -380,37 +377,32 @@ fn read_char(&mut self) -> Result<char, Self::Error> {
 
     fn read_str(&mut self) -> Result<String, Self::Error> {
         let len = try!(self.read_uint());
-        let s = ::std::str::from_utf8(&self.data[self.position .. self.position + len]).unwrap();
+        let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap();
         self.position += len;
         Ok(s.to_string())
     }
 
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_enum_variant<T, F>(&mut self,
-                               _: &[&str],
-                               mut f: F)
-                               -> Result<T, Self::Error>
-        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>,
+    fn read_enum_variant<T, F>(&mut self, _: &[&str], mut f: F) -> Result<T, Self::Error>
+        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
     {
         let disr = try!(self.read_uint());
         f(self, disr)
     }
 
-    fn read_enum_variant_arg<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_enum_variant_arg<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_enum_struct_variant<T, F>(&mut self,
-                                      _: &[&str],
-                                      mut f: F) -> Result<T, Self::Error>
-        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>,
+    fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], mut f: F) -> Result<T, Self::Error>
+        where F: FnMut(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
     {
         let disr = try!(self.read_uint());
         f(self, disr)
@@ -420,68 +412,59 @@ fn read_enum_struct_variant_field<T, F>(&mut self,
                                             _name: &str,
                                             _idx: usize,
                                             f: F)
-                                            -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+                                            -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_struct<T, F>(&mut self, _name: &str, _: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_struct<T, F>(&mut self, _name: &str, _: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_struct_field<T, F>(&mut self,
-                               _name: &str,
-                               _idx: usize, f: F)
-                               -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_struct_field<T, F>(&mut self, _name: &str, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         self.read_seq(move |d, len| {
             if len == tuple_len {
                 f(d)
             } else {
                 let err = format!("Invalid tuple length. Expected {}, found {}",
-                                   tuple_len,
-                                   len);
+                                  tuple_len,
+                                  len);
                 Err(DecodeError::Expected(err))
             }
         })
     }
 
-    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         self.read_seq_elt(idx, f)
     }
 
-    fn read_tuple_struct<T, F>(&mut self,
-                               _name: &str,
-                               len: usize, f: F)
-                               -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_tuple_struct<T, F>(&mut self, _name: &str, len: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         self.read_tuple(len, f)
     }
 
-    fn read_tuple_struct_arg<T, F>(&mut self,
-                                   idx: usize,
-                                   f: F)
-                                   -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         self.read_tuple_arg(idx, f)
     }
 
-    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error> where
-        F: FnMut(&mut Decoder<'a>, bool) -> Result<T, Self::Error>,
+    fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error>
+        where F: FnMut(&mut Decoder<'a>, bool) -> Result<T, Self::Error>
     {
         self.read_enum("Option", move |this| {
             this.read_enum_variant(&["None", "Some"], move |this, idx| {
@@ -497,34 +480,34 @@ fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error> where
         })
     }
 
-    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>,
+    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
     {
         let len = try!(self.read_uint());
         f(self, len)
     }
 
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>,
+    fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>, usize) -> Result<T, Self::Error>
     {
         let len = try!(self.read_uint());
         f(self, len)
     }
 
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
 
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error> where
-        F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>,
+    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+        where F: FnOnce(&mut Decoder<'a>) -> Result<T, Self::Error>
     {
         f(self)
     }
@@ -538,7 +521,7 @@ fn error(&mut self, err: &str) -> Self::Error {
 #[cfg(test)]
 mod tests {
     use serialize::{Encodable, Decodable};
-    use std::io::{Cursor};
+    use std::io::Cursor;
     use std::fmt::Debug;
     use super::{Encoder, Decoder};
 
@@ -566,7 +549,7 @@ struct Struct {
     }
 
 
-    fn check_round_trip<T: Encodable+Decodable+PartialEq+Debug>(values: Vec<T>) {
+    fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) {
         let mut cursor = Cursor::new(Vec::new());
 
         for value in &values {
@@ -591,7 +574,7 @@ fn test_unit() {
     #[test]
     fn test_u8() {
         let mut vec = vec![];
-        for i in ::std::u8::MIN .. ::std::u8::MAX {
+        for i in ::std::u8::MIN..::std::u8::MAX {
             vec.push(i);
         }
         check_round_trip(vec);
@@ -599,7 +582,7 @@ fn test_u8() {
 
     #[test]
     fn test_u16() {
-        for i in ::std::u16::MIN .. ::std::u16::MAX {
+        for i in ::std::u16::MIN..::std::u16::MAX {
             check_round_trip(vec![1, 2, 3, i, i, i]);
         }
     }
@@ -622,7 +605,7 @@ fn test_usize() {
     #[test]
     fn test_i8() {
         let mut vec = vec![];
-        for i in ::std::i8::MIN .. ::std::i8::MAX {
+        for i in ::std::i8::MIN..::std::i8::MAX {
             vec.push(i);
         }
         check_round_trip(vec);
@@ -630,7 +613,7 @@ fn test_i8() {
 
     #[test]
     fn test_i16() {
-        for i in ::std::i16::MIN .. ::std::i16::MAX {
+        for i in ::std::i16::MIN..::std::i16::MAX {
             check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
         }
     }
@@ -658,8 +641,8 @@ fn test_bool() {
     #[test]
     fn test_f32() {
         let mut vec = vec![];
-        for i in -100 .. 100 {
-            vec.push( (i as f32) / 3.0 );
+        for i in -100..100 {
+            vec.push((i as f32) / 3.0);
         }
         check_round_trip(vec);
     }
@@ -667,8 +650,8 @@ fn test_f32() {
     #[test]
     fn test_f64() {
         let mut vec = vec![];
-        for i in -100 .. 100 {
-            vec.push( (i as f64) / 3.0 );
+        for i in -100..100 {
+            vec.push((i as f64) / 3.0);
         }
         check_round_trip(vec);
     }
@@ -681,14 +664,13 @@ fn test_char() {
 
     #[test]
     fn test_string() {
-        let vec = vec![
-            "abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
-            "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
-            "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(),
-            "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(),
-            "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
-            "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(),
-            "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()];
+        let vec = vec!["abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
+                       "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
+                       "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(),
+                       "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(),
+                       "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(),
+                       "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(),
+                       "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()];
 
         check_round_trip(vec);
     }
@@ -720,70 +702,82 @@ fn test_option() {
     #[test]
     fn test_struct() {
         check_round_trip(vec![Struct {
-            a: (),
-            b: 10,
-            c: 11,
-            d: 12,
-            e: 13,
-            f: 14,
-
-            g: 15,
-            h: 16,
-            i: 17,
-            j: 18,
-            k: 19,
-
-            l: 'x',
-            m: "abc".to_string(),
-            n: 20.5,
-            o: 21.5,
-            p: false,
-            q: None,
-        }]);
+                                  a: (),
+                                  b: 10,
+                                  c: 11,
+                                  d: 12,
+                                  e: 13,
+                                  f: 14,
+
+                                  g: 15,
+                                  h: 16,
+                                  i: 17,
+                                  j: 18,
+                                  k: 19,
+
+                                  l: 'x',
+                                  m: "abc".to_string(),
+                                  n: 20.5,
+                                  o: 21.5,
+                                  p: false,
+                                  q: None,
+                              }]);
 
         check_round_trip(vec![Struct {
-            a: (),
-            b: 101,
-            c: 111,
-            d: 121,
-            e: 131,
-            f: 141,
-
-            g: -15,
-            h: -16,
-            i: -17,
-            j: -18,
-            k: -19,
-
-            l: 'y',
-            m: "def".to_string(),
-            n: -20.5,
-            o: -21.5,
-            p: true,
-            q: Some(1234567),
-        }]);
+                                  a: (),
+                                  b: 101,
+                                  c: 111,
+                                  d: 121,
+                                  e: 131,
+                                  f: 141,
+
+                                  g: -15,
+                                  h: -16,
+                                  i: -17,
+                                  j: -18,
+                                  k: -19,
+
+                                  l: 'y',
+                                  m: "def".to_string(),
+                                  n: -20.5,
+                                  o: -21.5,
+                                  p: true,
+                                  q: Some(1234567),
+                              }]);
     }
 
     #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
     enum Enum {
         Variant1,
         Variant2(usize, f32),
-        Variant3 { a: i32, b: char, c: bool }
+        Variant3 {
+            a: i32,
+            b: char,
+            c: bool,
+        },
     }
 
     #[test]
     fn test_enum() {
         check_round_trip(vec![Enum::Variant1,
                               Enum::Variant2(1, 2.5),
-                              Enum::Variant3 { a: 3, b: 'b', c: false },
-                              Enum::Variant3 { a: -4, b: 'f', c: true }]);
+                              Enum::Variant3 {
+                                  a: 3,
+                                  b: 'b',
+                                  c: false,
+                              },
+                              Enum::Variant3 {
+                                  a: -4,
+                                  b: 'f',
+                                  c: true,
+                              }]);
     }
 
     #[test]
     fn test_sequence() {
         let mut vec = vec![];
-        for i in -100i64 .. 100i64 {
-            vec.push(i*100000);
+        for i in -100i64..100i64 {
+            vec.push(i * 100000);
         }
 
         check_round_trip(vec![vec]);
@@ -793,8 +787,8 @@ fn test_sequence() {
     fn test_hash_map() {
         use std::collections::HashMap;
         let mut map = HashMap::new();
-        for i in -100i64 .. 100i64 {
-            map.insert(i*100000, i*10000);
+        for i in -100i64..100i64 {
+            map.insert(i * 100000, i * 10000);
         }
 
         check_round_trip(vec![map]);
index aa2f60f71f979765af701a1a13826d3533480432..e5942e64a9e409dab00e72c6cc4fa7ec4bd12d4a 100644 (file)
@@ -215,187 +215,6 @@ struct X { x: (), }
 ```
 "##,
 
-E0010: r##"
-The value of statics and constants must be known at compile time, and they live
-for the entire lifetime of a program. Creating a boxed value allocates memory on
-the heap at runtime, and therefore cannot be done at compile time. Erroneous
-code example:
-
-```
-#![feature(box_syntax)]
-
-const CON : Box<i32> = box 0;
-```
-"##,
-
-E0011: r##"
-Initializers for constants and statics are evaluated at compile time.
-User-defined operators rely on user-defined functions, which cannot be evaluated
-at compile time.
-
-Bad example:
-
-```
-use std::ops::Index;
-
-struct Foo { a: u8 }
-
-impl Index<u8> for Foo {
-    type Output = u8;
-
-    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
-}
-
-const a: Foo = Foo { a: 0u8 };
-const b: u8 = a[0]; // Index trait is defined by the user, bad!
-```
-
-Only operators on builtin types are allowed.
-
-Example:
-
-```
-const a: &'static [i32] = &[1, 2, 3];
-const b: i32 = a[0]; // Good!
-```
-"##,
-
-E0013: r##"
-Static and const variables can refer to other const variables. But a const
-variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
-here:
-
-```
-static X: i32 = 42;
-const Y: i32 = X;
-```
-
-To fix this, the value can be extracted as a const and then used:
-
-```
-const A: i32 = 42;
-static X: i32 = A;
-const Y: i32 = A;
-```
-"##,
-
-E0014: r##"
-Constants can only be initialized by a constant value or, in a future
-version of Rust, a call to a const function. This error indicates the use
-of a path (like a::b, or x) denoting something other than one of these
-allowed items. Example:
-
-```
-const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
-```
-
-To avoid it, you have to replace the non-constant value:
-
-```
-const FOO: i32 = { const X : i32 = 0; X };
-// or even:
-const FOO: i32 = { 0 }; // but brackets are useless here
-```
-"##,
-
-// FIXME(#24111) Change the language here when const fn stabilizes
-E0015: r##"
-The only functions that can be called in static or constant expressions are
-`const` functions, and struct/enum constructors. `const` functions are only
-available on a nightly compiler. Rust currently does not support more general
-compile-time function execution.
-
-```
-const FOO: Option<u8> = Some(1); // enum constructor
-struct Bar {x: u8}
-const BAR: Bar = Bar {x: 1}; // struct constructor
-```
-
-See [RFC 911] for more details on the design of `const fn`s.
-
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
-"##,
-
-E0017: r##"
-References in statics and constants may only refer to immutable values. Example:
-
-```
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &'static mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
-"##,
-
-E0018: r##"
-The value of static and const variables must be known at compile time. You
-can't cast a pointer as an integer because we can't know what value the
-address will take.
-
-However, pointers to other constants' addresses are allowed in constants,
-example:
-
-```
-const X: u32 = 50;
-const Y: *const u32 = &X;
-```
-
-Therefore, casting one of these non-constant pointers to an integer results
-in a non-constant integer which lead to this error. Example:
-
-```
-const X: u32 = 1;
-const Y: usize = &X as *const u32 as usize;
-println!("{}", Y);
-```
-"##,
-
-E0019: r##"
-A function call isn't allowed in the const's initialization expression
-because the expression's value must be known at compile-time. Example of
-erroneous code:
-
-```
-enum Test {
-    V1
-}
-
-impl Test {
-    fn test(&self) -> i32 {
-        12
-    }
-}
-
-fn main() {
-    const FOO: Test = Test::V1;
-
-    const A: i32 = FOO.test(); // You can't call Test::func() here !
-}
-```
-
-Remember: you can't use a function call inside a const's initialization
-expression! However, you can totally use it anywhere else:
-
-```
-fn main() {
-    const FOO: Test = Test::V1;
-
-    FOO.func(); // here is good
-    let x = FOO.func(); // or even here!
-}
-```
-"##,
-
 E0020: r##"
 This error indicates that an attempt was made to divide by zero (or take the
 remainder of a zero divisor) in a static or constant expression. Erroneous
@@ -407,24 +226,6 @@ fn main() {
 ```
 "##,
 
-E0030: r##"
-When matching against a range, the compiler verifies that the range is
-non-empty.  Range patterns include both end-points, so this is equivalent to
-requiring the start of the range to be less than or equal to the end of the
-range.
-
-For example:
-
-```
-match 5u32 {
-    // This range is ok, albeit pointless.
-    1 ... 1 => ...
-    // This range is empty, and the compiler can tell.
-    1000 ... 5 => ...
-}
-```
-"##,
-
 E0038: r####"
 Trait objects like `Box<Trait>` can only be constructed when certain
 requirements are satisfied by the trait in question.
@@ -902,14 +703,6 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
 ```
 "##,
 
-E0161: r##"
-In Rust, you can only move a value when its size is known at compile time.
-
-To work around this restriction, consider "hiding" the value behind a reference:
-either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
-it around as usual.
-"##,
-
 E0162: r##"
 An if-let pattern attempts to match the pattern, and enters the body if the
 match was successful. If the match is irrefutable (when it cannot fail to
@@ -1101,67 +894,6 @@ fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
 ```
 "##,
 
-E0265: r##"
-This error indicates that a static or constant references itself.
-All statics and constants need to resolve to a value in an acyclic manner.
-
-For example, neither of the following can be sensibly compiled:
-
-```
-const X: u32 = X;
-```
-
-```
-const X: u32 = Y;
-const Y: u32 = X;
-```
-"##,
-
-E0267: r##"
-This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Erroneous code example:
-
-```
-let w = || { break; }; // error: `break` inside of a closure
-```
-
-`break` and `continue` keywords can be used as normal inside closures as long as
-they are also contained within a loop. To halt the execution of a closure you
-should instead use a return statement. Example:
-
-```
-let w = || {
-    for _ in 0..10 {
-        break;
-    }
-};
-
-w();
-```
-"##,
-
-E0268: r##"
-This error indicates the use of a loop keyword (`break` or `continue`) outside
-of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken. Erroneous code example:
-
-```
-fn some_func() {
-    break; // error: `break` outside of loop
-}
-```
-
-Please verify that you are using `break` and `continue` only in loops. Example:
-
-```
-fn some_func() {
-    for _ in 0..10 {
-        break; // ok!
-    }
-}
-```
-"##,
-
 E0269: r##"
 Functions must eventually return a value of their return type. For example, in
 the following function
@@ -1892,104 +1624,6 @@ struct Foo<T: 'static> {
 ```
 "##,
 
-E0378: r##"
-Method calls that aren't calls to inherent `const` methods are disallowed
-in statics, constants, and constant functions.
-
-For example:
-
-```
-const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
-
-struct Foo(i32);
-
-impl Foo {
-    const fn foo(&self) -> i32 {
-        self.bar() // error, `bar` isn't `const`
-    }
-
-    fn bar(&self) -> i32 { self.0 }
-}
-```
-
-For more information about `const fn`'s, see [RFC 911].
-
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
-"##,
-
-E0394: r##"
-From [RFC 246]:
-
- > It is invalid for a static to reference another static by value. It is
- > required that all references be borrowed.
-
-[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
-"##,
-
-E0395: r##"
-The value assigned to a constant expression must be known at compile time,
-which is not the case when comparing raw pointers. Erroneous code example:
-
-```
-static foo: i32 = 42;
-static bar: i32 = 43;
-
-static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
-// error: raw pointers cannot be compared in statics!
-```
-
-Please check that the result of the comparison can be determined at compile time
-or isn't assigned to a constant expression. Example:
-
-```
-static foo: i32 = 42;
-static bar: i32 = 43;
-
-let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
-// baz isn't a constant expression so it's ok
-```
-"##,
-
-E0396: r##"
-The value assigned to a constant expression must be known at compile time,
-which is not the case when dereferencing raw pointers. Erroneous code
-example:
-
-```
-const foo: i32 = 42;
-const baz: *const i32 = (&foo as *const i32);
-
-const deref: i32 = *baz;
-// error: raw pointers cannot be dereferenced in constants
-```
-
-To fix this error, please do not assign this value to a constant expression.
-Example:
-
-```
-const foo: i32 = 42;
-const baz: *const i32 = (&foo as *const i32);
-
-unsafe { let deref: i32 = *baz; }
-// baz isn't a constant expression so it's ok
-```
-
-You'll also note that this assignment must be done in an unsafe block!
-"##,
-
-E0397: r##"
-It is not allowed for a mutable static to allocate or have destructors. For
-example:
-
-```
-// error: mutable statics are not allowed to have boxes
-static mut FOO: Option<Box<usize>> = None;
-
-// error: mutable statics are not allowed to have destructors
-static mut BAR: Option<Vec<i32>> = None;
-```
-"##,
-
 E0398: r##"
 In Rust 1.3, the default object lifetime bounds are expected to
 change, as described in RFC #1156 [1]. You are getting a warning
@@ -2026,50 +1660,6 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
 [1]: https://github.com/rust-lang/rfcs/pull/1156
 "##,
 
-E0400: r##"
-A user-defined dereference was attempted in an invalid context. Erroneous
-code example:
-
-```
-use std::ops::Deref;
-
-struct A;
-
-impl Deref for A {
-    type Target = str;
-
-    fn deref(&self)-> &str { "foo" }
-}
-
-const S: &'static str = &A;
-// error: user-defined dereference operators are not allowed in constants
-
-fn main() {
-    let foo = S;
-}
-```
-
-You cannot directly use a dereference operation whilst initializing a constant
-or a static. To fix this error, restructure your code to avoid this dereference,
-perhaps moving it inline:
-
-```
-use std::ops::Deref;
-
-struct A;
-
-impl Deref for A {
-    type Target = str;
-
-    fn deref(&self)-> &str { "foo" }
-}
-
-fn main() {
-    let foo : &str = &A;
-}
-```
-"##,
-
 E0452: r##"
 An invalid lint attribute has been given. Erroneous code example:
 
@@ -2087,136 +1677,6 @@ fn main() {
 ```
 "##,
 
-E0492: r##"
-A borrow of a constant containing interior mutability was attempted. Erroneous
-code example:
-
-```
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
-
-const A: AtomicUsize = ATOMIC_USIZE_INIT;
-static B: &'static AtomicUsize = &A;
-// error: cannot borrow a constant which contains interior mutability, create a
-//        static instead
-```
-
-A `const` represents a constant value that should never change. If one takes
-a `&` reference to the constant, then one is taking a pointer to some memory
-location containing the value. Normally this is perfectly fine: most values
-can't be changed via a shared `&` pointer, but interior mutability would allow
-it. That is, a constant value could be mutated. On the other hand, a `static` is
-explicitly a single memory location, which can be mutated at will.
-
-So, in order to solve this error, either use statics which are `Sync`:
-
-```
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
-
-static A: AtomicUsize = ATOMIC_USIZE_INIT;
-static B: &'static AtomicUsize = &A; // ok!
-```
-
-You can also have this error while using a cell type:
-
-```
-#![feature(const_fn)]
-
-use std::cell::Cell;
-
-const A: Cell<usize> = Cell::new(1);
-const B: &'static Cell<usize> = &A;
-// error: cannot borrow a constant which contains interior mutability, create
-//        a static instead
-
-// or:
-struct C { a: Cell<usize> }
-
-const D: C = C { a: Cell::new(1) };
-const E: &'static Cell<usize> = &D.a; // error
-
-// or:
-const F: &'static C = &D; // error
-```
-
-This is because cell types do operations that are not thread-safe. Due to this,
-they don't implement Sync and thus can't be placed in statics. In this
-case, `StaticMutex` would work just fine, but it isn't stable yet:
-https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
-
-However, if you still wish to use these types, you can achieve this by an unsafe
-wrapper:
-
-```
-#![feature(const_fn)]
-
-use std::cell::Cell;
-use std::marker::Sync;
-
-struct NotThreadSafe<T> {
-    value: Cell<T>,
-}
-
-unsafe impl<T> Sync for NotThreadSafe<T> {}
-
-static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
-static B: &'static NotThreadSafe<usize> = &A; // ok!
-```
-
-Remember this solution is unsafe! You will have to ensure that accesses to the
-cell are synchronized.
-"##,
-
-E0493: r##"
-A type with a destructor was assigned to an invalid type of variable. Erroneous
-code example:
-
-```
-struct Foo {
-    a: u32
-}
-
-impl Drop for Foo {
-    fn drop(&mut self) {}
-}
-
-const F : Foo = Foo { a : 0 };
-// error: constants are not allowed to have destructors
-static S : Foo = Foo { a : 0 };
-// error: statics are not allowed to have destructors
-```
-
-To solve this issue, please use a type which does allow the usage of type with
-destructors.
-"##,
-
-E0494: r##"
-A reference of an interior static was assigned to another const/static.
-Erroneous code example:
-
-```
-struct Foo {
-    a: u32
-}
-
-static S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a;
-// error: cannot refer to the interior of another static, use a
-//        constant instead
-```
-
-The "base" variable has to be a const if you want another static/const variable
-to refer to one of its fields. Example:
-
-```
-struct Foo {
-    a: u32
-}
-
-const S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a; // ok!
-```
-"##,
-
 E0496: r##"
 A lifetime name is shadowing another lifetime name. Erroneous code example:
 
index 501a03f128664ad3ebd0e9bb81700ebb29ed0975..4d772de7835941b1c65cd1564908624739f1db19 100644 (file)
@@ -94,12 +94,9 @@ pub mod middle {
     pub mod astconv_util;
     pub mod expr_use_visitor; // STAGE0: increase glitch immunity
     pub mod cfg;
-    pub mod check_const;
-    pub mod check_static_recursion;
-    pub mod check_loop;
     pub mod check_match;
-    pub mod check_rvalues;
     pub mod const_eval;
+    pub mod const_qualif;
     pub mod cstore;
     pub mod dataflow;
     pub mod dead;
index 2bf749d93cec471c63cdc31b47dc39f4f74cc950..8b1bdc31beb01bf916aed85ab623a9907edd9cc5 100644 (file)
@@ -14,7 +14,7 @@
  * Almost certainly this could (and should) be refactored out of existence.
  */
 
-use middle::def;
+use middle::def::Def;
 use middle::ty::{self, Ty};
 
 use syntax::codemap::Span;
@@ -72,7 +72,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
             }
             Some(d) => d.full_def()
         };
-        if let def::DefPrimTy(nty) = def {
+        if let Def::PrimTy(nty) = def {
             Some(prim_ty_to_ty(tcx, &path.segments, nty))
         } else {
             None
index abe85125215708f38abd8038f0295e6efb8df76b..a6bcf70925ca3eed134366574d61435b12e5d8de 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc_data_structures::graph;
 use middle::cfg::*;
-use middle::def;
+use middle::def::Def;
 use middle::pat_util;
 use middle::ty;
 use syntax::ast;
@@ -591,7 +591,7 @@ fn find_scope(&self,
         }
 
         match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
-            Some(def::DefLabel(loop_id)) => {
+            Some(Def::Label(loop_id)) => {
                 for l in &self.loop_scopes {
                     if l.loop_id == loop_id {
                         return *l;
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
deleted file mode 100644 (file)
index 5822b3d..0000000
+++ /dev/null
@@ -1,949 +0,0 @@
-// Copyright 2012-2014 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.
-
-// Verifies that the types and values of const and static items
-// are safe. The rules enforced by this module are:
-//
-// - For each *mutable* static item, it checks that its **type**:
-//     - doesn't have a destructor
-//     - doesn't own a box
-//
-// - For each *immutable* static item, it checks that its **value**:
-//       - doesn't own a box
-//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
-//           - the type of the struct/enum has a dtor
-//
-// Rules Enforced Elsewhere:
-// - It's not possible to take the address of a static item with unsafe interior. This is enforced
-// by borrowck::gather_loans
-
-use dep_graph::DepNode;
-use middle::ty::cast::{CastKind};
-use middle::const_eval::{self, ConstEvalErr};
-use middle::const_eval::ErrKind::IndexOpFeatureGated;
-use middle::const_eval::EvalHint::ExprTypeChecked;
-use middle::def;
-use middle::def_id::DefId;
-use middle::expr_use_visitor as euv;
-use middle::infer;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Categorization;
-use middle::traits;
-use middle::ty::{self, Ty};
-use util::nodemap::NodeMap;
-
-use rustc_front::hir;
-use syntax::ast;
-use syntax::codemap::Span;
-use syntax::feature_gate::UnstableFeatures;
-use rustc_front::intravisit::{self, FnKind, Visitor};
-
-use std::collections::hash_map::Entry;
-use std::cmp::Ordering;
-
-// Const qualification, from partial to completely promotable.
-bitflags! {
-    #[derive(RustcEncodable, RustcDecodable)]
-    flags ConstQualif: u8 {
-        // Inner mutability (can not be placed behind a reference) or behind
-        // &mut in a non-global expression. Can be copied from static memory.
-        const MUTABLE_MEM        = 1 << 0,
-        // Constant value with a type that implements Drop. Can be copied
-        // from static memory, similar to MUTABLE_MEM.
-        const NEEDS_DROP         = 1 << 1,
-        // Even if the value can be placed in static memory, copying it from
-        // there is more expensive than in-place instantiation, and/or it may
-        // be too large. This applies to [T; N] and everything containing it.
-        // N.B.: references need to clear this flag to not end up on the stack.
-        const PREFER_IN_PLACE    = 1 << 2,
-        // May use more than 0 bytes of memory, doesn't impact the constness
-        // directly, but is not allowed to be borrowed mutably in a constant.
-        const NON_ZERO_SIZED     = 1 << 3,
-        // Actually borrowed, has to always be in static memory. Does not
-        // propagate, and requires the expression to behave like a 'static
-        // lvalue. The set of expressions with this flag is the minimum
-        // that have to be promoted.
-        const HAS_STATIC_BORROWS = 1 << 4,
-        // Invalid const for miscellaneous reasons (e.g. not implemented).
-        const NOT_CONST          = 1 << 5,
-
-        // Borrowing the expression won't produce &'static T if any of these
-        // bits are set, though the value could be copied from static memory
-        // if `NOT_CONST` isn't set.
-        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
-                                   ConstQualif::NEEDS_DROP.bits |
-                                   ConstQualif::NOT_CONST.bits
-    }
-}
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-enum Mode {
-    Const,
-    ConstFn,
-    Static,
-    StaticMut,
-
-    // An expression that occurs outside of any constant context
-    // (i.e. `const`, `static`, array lengths, etc.). The value
-    // can be variable at runtime, but will be promotable to
-    // static memory if we can prove it is actually constant.
-    Var,
-}
-
-struct CheckCrateVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    mode: Mode,
-    qualif: ConstQualif,
-    rvalue_borrows: NodeMap<hir::Mutability>
-}
-
-impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
-    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
-        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R,
-    {
-        let (old_mode, old_qualif) = (self.mode, self.qualif);
-        self.mode = mode;
-        self.qualif = ConstQualif::empty();
-        let r = f(self);
-        self.mode = old_mode;
-        self.qualif = old_qualif;
-        r
-    }
-
-    fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
-        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
-    {
-        let param_env = match item_id {
-            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
-            None => self.tcx.empty_parameter_environment()
-        };
-
-        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
-
-        f(&mut euv::ExprUseVisitor::new(self, &infcx))
-    }
-
-    fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
-        assert!(mode != Mode::Var);
-        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
-        self.with_mode(mode, |this| {
-            this.with_euv(None, |euv| euv.consume_expr(expr));
-            this.visit_expr(expr);
-            this.qualif
-        })
-    }
-
-    fn fn_like(&mut self,
-               fk: FnKind,
-               fd: &hir::FnDecl,
-               b: &hir::Block,
-               s: Span,
-               fn_id: ast::NodeId)
-               -> ConstQualif {
-        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
-
-        let mode = match fk {
-            FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
-                Mode::ConstFn
-            }
-            FnKind::Method(_, m, _) => {
-                if m.constness == hir::Constness::Const {
-                    Mode::ConstFn
-                } else {
-                    Mode::Var
-                }
-            }
-            _ => Mode::Var
-        };
-
-        let qualif = self.with_mode(mode, |this| {
-            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
-            intravisit::walk_fn(this, fk, fd, b, s);
-            this.qualif
-        });
-
-        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
-        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
-        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-
-        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
-        qualif
-    }
-
-    fn add_qualif(&mut self, qualif: ConstQualif) {
-        self.qualif = self.qualif | qualif;
-    }
-
-    /// Returns true if the call is to a const fn or method.
-    fn handle_const_fn_call(&mut self,
-                            expr: &hir::Expr,
-                            def_id: DefId,
-                            ret_ty: Ty<'tcx>)
-                            -> bool {
-        if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
-            if
-                // we are in a static/const initializer
-                self.mode != Mode::Var &&
-
-                // feature-gate is not enabled
-                !self.tcx.sess.features.borrow().const_fn &&
-
-                // this doesn't come from a macro that has #[allow_internal_unstable]
-                !self.tcx.sess.codemap().span_allows_unstable(expr.span)
-            {
-                let mut err = self.tcx.sess.struct_span_err(
-                    expr.span,
-                    "const fns are an unstable feature");
-                fileline_help!(
-                    &mut err,
-                    expr.span,
-                    "in Nightly builds, add `#![feature(const_fn)]` to the crate \
-                     attributes to enable");
-                err.emit();
-            }
-
-            let qualif = self.fn_like(fn_like.kind(),
-                                      fn_like.decl(),
-                                      fn_like.body(),
-                                      fn_like.span(),
-                                      fn_like.id());
-            self.add_qualif(qualif);
-
-            if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                self.add_qualif(ConstQualif::MUTABLE_MEM);
-            }
-
-            true
-        } else {
-            false
-        }
-    }
-
-    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
-        match self.rvalue_borrows.entry(id) {
-            Entry::Occupied(mut entry) => {
-                // Merge the two borrows, taking the most demanding
-                // one, mutability-wise.
-                if mutbl == hir::MutMutable {
-                    entry.insert(mutbl);
-                }
-            }
-            Entry::Vacant(entry) => {
-                entry.insert(mutbl);
-            }
-        }
-    }
-
-    fn msg(&self) -> &'static str {
-        match self.mode {
-            Mode::Const => "constant",
-            Mode::ConstFn => "constant function",
-            Mode::StaticMut | Mode::Static => "static",
-            Mode::Var => unreachable!(),
-        }
-    }
-
-    fn check_static_mut_type(&self, e: &hir::Expr) {
-        let node_ty = self.tcx.node_id_to_type(e.id);
-        let tcontents = node_ty.type_contents(self.tcx);
-
-        let suffix = if tcontents.has_dtor() {
-            "destructors"
-        } else if tcontents.owns_owned() {
-            "boxes"
-        } else {
-            return
-        };
-
-        span_err!(self.tcx.sess, e.span, E0397,
-                 "mutable statics are not allowed to have {}", suffix);
-    }
-
-    fn check_static_type(&self, e: &hir::Expr) {
-        let ty = self.tcx.node_id_to_type(e.id);
-        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
-        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
-        let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
-        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
-        match fulfill_cx.select_all_or_error(&infcx) {
-            Ok(()) => { },
-            Err(ref errors) => {
-                traits::report_fulfillment_errors(&infcx, errors);
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &hir::Item) {
-        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
-        assert_eq!(self.mode, Mode::Var);
-        match i.node {
-            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
-                self.check_static_type(&**expr);
-                self.global_expr(Mode::Static, &**expr);
-            }
-            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
-                self.check_static_mut_type(&**expr);
-                self.global_expr(Mode::StaticMut, &**expr);
-            }
-            hir::ItemConst(_, ref expr) => {
-                self.global_expr(Mode::Const, &**expr);
-            }
-            hir::ItemEnum(ref enum_definition, _) => {
-                for var in &enum_definition.variants {
-                    if let Some(ref ex) = var.node.disr_expr {
-                        self.global_expr(Mode::Const, &**ex);
-                    }
-                }
-            }
-            _ => {
-                intravisit::walk_item(self, i);
-            }
-        }
-    }
-
-    fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
-        match t.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(ref expr) = *default {
-                    self.global_expr(Mode::Const, &*expr);
-                } else {
-                    intravisit::walk_trait_item(self, t);
-                }
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
-        }
-    }
-
-    fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
-        match i.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
-                self.global_expr(Mode::Const, &*expr);
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
-        }
-    }
-
-    fn visit_fn(&mut self,
-                fk: FnKind<'v>,
-                fd: &'v hir::FnDecl,
-                b: &'v hir::Block,
-                s: Span,
-                fn_id: ast::NodeId) {
-        self.fn_like(fk, fd, b, s, fn_id);
-    }
-
-    fn visit_pat(&mut self, p: &hir::Pat) {
-        match p.node {
-            hir::PatLit(ref lit) => {
-                self.global_expr(Mode::Const, &**lit);
-            }
-            hir::PatRange(ref start, ref end) => {
-                self.global_expr(Mode::Const, &**start);
-                self.global_expr(Mode::Const, &**end);
-
-                match const_eval::compare_lit_exprs(self.tcx, start, end) {
-                    Some(Ordering::Less) |
-                    Some(Ordering::Equal) => {}
-                    Some(Ordering::Greater) => {
-                        span_err!(self.tcx.sess, start.span, E0030,
-                            "lower range bound must be less than or equal to upper");
-                    }
-                    None => {
-                        self.tcx.sess.delay_span_bug(start.span,
-                                                     "non-constant path in constant expr");
-                    }
-                }
-            }
-            _ => intravisit::walk_pat(self, p)
-        }
-    }
-
-    fn visit_block(&mut self, block: &hir::Block) {
-        // Check all statements in the block
-        for stmt in &block.stmts {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        hir::DeclLocal(_) => {},
-                        // Item statements are allowed
-                        hir::DeclItem(_) => continue
-                    }
-                }
-                hir::StmtExpr(_, _) => {},
-                hir::StmtSemi(_, _) => {},
-            }
-            self.add_qualif(ConstQualif::NOT_CONST);
-            // anything else should have been caught by check_const_fn
-            assert_eq!(self.mode, Mode::Var);
-        }
-        intravisit::walk_block(self, block);
-    }
-
-    fn visit_expr(&mut self, ex: &hir::Expr) {
-        let mut outer = self.qualif;
-        self.qualif = ConstQualif::empty();
-
-        let node_ty = self.tcx.node_id_to_type(ex.id);
-        check_expr(self, ex, node_ty);
-        check_adjustments(self, ex);
-
-        // Special-case some expressions to avoid certain flags bubbling up.
-        match ex.node {
-            hir::ExprCall(ref callee, ref args) => {
-                for arg in args {
-                    self.visit_expr(&**arg)
-                }
-
-                let inner = self.qualif;
-                self.visit_expr(&**callee);
-                // The callee's size doesn't count in the call.
-                let added = self.qualif - inner;
-                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
-            }
-            hir::ExprRepeat(ref element, _) => {
-                self.visit_expr(&**element);
-                // The count is checked elsewhere (typeck).
-                let count = match node_ty.sty {
-                    ty::TyArray(_, n) => n,
-                    _ => unreachable!()
-                };
-                // [element; 0] is always zero-sized.
-                if count == 0 {
-                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-                }
-            }
-            hir::ExprMatch(ref discr, ref arms, _) => {
-                // Compute the most demanding borrow from all the arms'
-                // patterns and set that on the discriminator.
-                let mut borrow = None;
-                for pat in arms.iter().flat_map(|arm| &arm.pats) {
-                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
-                    match (borrow, pat_borrow) {
-                        (None, _) | (_, Some(hir::MutMutable)) => {
-                            borrow = pat_borrow;
-                        }
-                        _ => {}
-                    }
-                }
-                if let Some(mutbl) = borrow {
-                    self.record_borrow(discr.id, mutbl);
-                }
-                intravisit::walk_expr(self, ex);
-            }
-            // Division by zero and overflow checking.
-            hir::ExprBinary(op, _, _) => {
-                intravisit::walk_expr(self, ex);
-                let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
-                match node_ty.sty {
-                    ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
-                        if !self.qualif.intersects(ConstQualif::NOT_CONST) {
-                            match const_eval::eval_const_expr_partial(
-                                    self.tcx, ex, ExprTypeChecked, None) {
-                                Ok(_) => {}
-                                Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
-                                Err(msg) => {
-                                    self.tcx.sess.add_lint(::lint::builtin::CONST_ERR, ex.id,
-                                                           msg.span,
-                                                           msg.description().into_owned())
-                                }
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            _ => intravisit::walk_expr(self, ex)
-        }
-
-        // Handle borrows on (or inside the autorefs of) this expression.
-        match self.rvalue_borrows.remove(&ex.id) {
-            Some(hir::MutImmutable) => {
-                // Constants cannot be borrowed if they contain interior mutability as
-                // it means that our "silent insertion of statics" could change
-                // initializer values (very bad).
-                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
-                // propagated from another error, so erroring again would be just noise.
-                let tc = node_ty.type_contents(self.tcx);
-                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
-                    outer = outer | ConstQualif::NOT_CONST;
-                    if self.mode != Mode::Var {
-                        span_err!(self.tcx.sess, ex.span, E0492,
-                                  "cannot borrow a constant which contains \
-                                   interior mutability, create a static instead");
-                    }
-                }
-                // If the reference has to be 'static, avoid in-place initialization
-                // as that will end up pointing to the stack instead.
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            Some(hir::MutMutable) => {
-                // `&mut expr` means expr could be mutated, unless it's zero-sized.
-                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
-                    if self.mode == Mode::Var {
-                        outer = outer | ConstQualif::NOT_CONST;
-                        self.add_qualif(ConstQualif::MUTABLE_MEM);
-                    } else {
-                        span_err!(self.tcx.sess, ex.span, E0017,
-                            "references in {}s may only refer \
-                             to immutable values", self.msg())
-                    }
-                }
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            None => {}
-        }
-        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
-        // Don't propagate certain flags.
-        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
-    }
-}
-
-/// This function is used to enforce the constraints on
-/// const/static items. It walks through the *value*
-/// of the item walking down the expression and evaluating
-/// every nested expression. If the expression is not part
-/// of a const/static item, it is qualified for promotion
-/// instead of producing errors.
-fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
-                        e: &hir::Expr, node_ty: Ty<'tcx>) {
-    match node_ty.sty {
-        ty::TyStruct(def, _) |
-        ty::TyEnum(def, _) if def.has_dtor() => {
-            v.add_qualif(ConstQualif::NEEDS_DROP);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0493,
-                          "{}s are not allowed to have destructors",
-                          v.msg());
-            }
-        }
-        _ => {}
-    }
-
-    let method_call = ty::MethodCall::expr(e.id);
-    match e.node {
-        hir::ExprUnary(..) |
-        hir::ExprBinary(..) |
-        hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0011,
-                            "user-defined operators are not allowed in {}s", v.msg());
-            }
-        }
-        hir::ExprBox(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0010,
-                          "allocations are not allowed in {}s", v.msg());
-            }
-        }
-        hir::ExprUnary(op, ref inner) => {
-            match v.tcx.node_id_to_type(inner.id).sty {
-                ty::TyRawPtr(_) => {
-                    assert!(op == hir::UnDeref);
-
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0396,
-                                  "raw pointers cannot be dereferenced in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprBinary(op, ref lhs, _) => {
-            match v.tcx.node_id_to_type(lhs.id).sty {
-                ty::TyRawPtr(_) => {
-                    assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
-                            op.node == hir::BiLe || op.node == hir::BiLt ||
-                            op.node == hir::BiGe || op.node == hir::BiGt);
-
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0395,
-                                  "raw pointers cannot be compared in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprCast(ref from, _) => {
-            debug!("Checking const cast(id={})", from.id);
-            match v.tcx.cast_kinds.borrow().get(&from.id) {
-                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
-                Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0018,
-                                  "raw pointers cannot be cast to integers in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprPath(..) => {
-            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
-            match def {
-                Some(def::DefVariant(_, _, _)) => {
-                    // Count the discriminator or function pointer.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
-                Some(def::DefStruct(_)) => {
-                    if let ty::TyBareFn(..) = node_ty.sty {
-                        // Count the function pointer.
-                        v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    }
-                }
-                Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
-                    // Count the function pointer.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
-                Some(def::DefStatic(..)) => {
-                    match v.mode {
-                        Mode::Static | Mode::StaticMut => {}
-                        Mode::Const | Mode::ConstFn => {
-                            span_err!(v.tcx.sess, e.span, E0013,
-                                "{}s cannot refer to other statics, insert \
-                                 an intermediate constant instead", v.msg());
-                        }
-                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
-                    }
-                }
-                Some(def::DefConst(did)) |
-                Some(def::DefAssociatedConst(did)) => {
-                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
-                                                                       Some(e.id),
-                                                                       None) {
-                        let inner = v.global_expr(Mode::Const, expr);
-                        v.add_qualif(inner);
-                    }
-                }
-                Some(def::DefLocal(..)) if v.mode == Mode::ConstFn => {
-                    // Sadly, we can't determine whether the types are zero-sized.
-                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
-                }
-                def => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        debug!("(checking const) found bad def: {:?}", def);
-                        span_err!(v.tcx.sess, e.span, E0014,
-                                  "paths in {}s may only refer to constants \
-                                   or functions", v.msg());
-                    }
-                }
-            }
-        }
-        hir::ExprCall(ref callee, _) => {
-            let mut callee = &**callee;
-            loop {
-                callee = match callee.node {
-                    hir::ExprBlock(ref block) => match block.expr {
-                        Some(ref tail) => &**tail,
-                        None => break
-                    },
-                    _ => break
-                };
-            }
-            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
-            let is_const = match def {
-                Some(def::DefStruct(..)) => true,
-                Some(def::DefVariant(..)) => {
-                    // Count the discriminator.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    true
-                }
-                Some(def::DefFn(did, _)) => {
-                    v.handle_const_fn_call(e, did, node_ty)
-                }
-                Some(def::DefMethod(did)) => {
-                    match v.tcx.impl_or_trait_item(did).container() {
-                        ty::ImplContainer(_) => {
-                            v.handle_const_fn_call(e, did, node_ty)
-                        }
-                        ty::TraitContainer(_) => false
-                    }
-                }
-                _ => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    // FIXME(#24111) Remove this check when const fn stabilizes
-                    let (msg, note) =
-                        if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
-                        (format!("function calls in {}s are limited to \
-                                  struct and enum constructors",
-                                 v.msg()),
-                         Some("a limited form of compile-time function \
-                               evaluation is available on a nightly \
-                               compiler via `const fn`"))
-                    } else {
-                        (format!("function calls in {}s are limited \
-                                  to constant functions, \
-                                  struct and enum constructors",
-                                 v.msg()),
-                         None)
-                    };
-                    let mut err = struct_span_err!(v.tcx.sess, e.span, E0015, "{}", msg);
-                    if let Some(note) = note {
-                        err.span_note(e.span, note);
-                    }
-                    err.emit();
-                }
-            }
-        }
-        hir::ExprMethodCall(..) => {
-            let method = v.tcx.tables.borrow().method_map[&method_call];
-            let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
-                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
-                ty::TraitContainer(_) => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0378,
-                              "method calls in {}s are limited to \
-                               constant inherent methods", v.msg());
-                }
-            }
-        }
-        hir::ExprStruct(..) => {
-            let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
-            if did == v.tcx.lang_items.unsafe_cell_type() {
-                v.add_qualif(ConstQualif::MUTABLE_MEM);
-            }
-        }
-
-        hir::ExprLit(_) |
-        hir::ExprAddrOf(..) => {
-            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-        }
-
-        hir::ExprRepeat(..) => {
-            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
-        }
-
-        hir::ExprClosure(..) => {
-            // Paths in constant contexts cannot refer to local variables,
-            // as there are none, and thus closures can't have upvars there.
-            if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
-                assert!(v.mode == Mode::Var,
-                        "global closures can't capture anything");
-                v.add_qualif(ConstQualif::NOT_CONST);
-            }
-        }
-
-        hir::ExprBlock(_) |
-        hir::ExprIndex(..) |
-        hir::ExprField(..) |
-        hir::ExprTupField(..) |
-        hir::ExprVec(_) |
-        hir::ExprType(..) |
-        hir::ExprTup(..) => {}
-
-        // Conditional control flow (possible to implement).
-        hir::ExprMatch(..) |
-        hir::ExprIf(..) |
-
-        // Loops (not very meaningful in constants).
-        hir::ExprWhile(..) |
-        hir::ExprLoop(..) |
-
-        // More control flow (also not very meaningful).
-        hir::ExprBreak(_) |
-        hir::ExprAgain(_) |
-        hir::ExprRet(_) |
-
-        // Miscellaneous expressions that could be implemented.
-        hir::ExprRange(..) |
-
-        // Expressions with side-effects.
-        hir::ExprAssign(..) |
-        hir::ExprAssignOp(..) |
-        hir::ExprInlineAsm(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0019,
-                          "{} contains unimplemented expression type", v.msg());
-            }
-        }
-    }
-}
-
-/// Check the adjustments of an expression
-fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
-    match v.tcx.tables.borrow().adjustments.get(&e.id) {
-        None |
-        Some(&ty::adjustment::AdjustReifyFnPointer) |
-        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
-
-        Some(&ty::adjustment::AdjustDerefRef(
-            ty::adjustment::AutoDerefRef { autoderefs, .. }
-        )) => {
-            if (0..autoderefs as u32).any(|autoderef| {
-                    v.tcx.is_overloaded_autoderef(e.id, autoderef)
-            }) {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0400,
-                              "user-defined dereference operators are not allowed in {}s",
-                              v.msg());
-                }
-            }
-        }
-    }
-}
-
-pub fn check_crate(tcx: &ty::ctxt) {
-    tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
-        tcx: tcx,
-        mode: Mode::Var,
-        qualif: ConstQualif::NOT_CONST,
-        rvalue_borrows: NodeMap()
-    });
-    tcx.sess.abort_if_errors();
-}
-
-impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
-    fn consume(&mut self,
-               _consume_id: ast::NodeId,
-               consume_span: Span,
-               cmt: mc::cmt,
-               _mode: euv::ConsumeMode) {
-        let mut cur = &cmt;
-        loop {
-            match cur.cat {
-                Categorization::StaticItem => {
-                    if self.mode != Mode::Var {
-                        // statics cannot be consumed by value at any time, that would imply
-                        // that they're an initializer (what a const is for) or kept in sync
-                        // over time (not feasible), so deny it outright.
-                        span_err!(self.tcx.sess, consume_span, E0394,
-                                  "cannot refer to other statics by value, use the \
-                                   address-of operator or a constant instead");
-                    }
-                    break;
-                }
-                Categorization::Deref(ref cmt, _, _) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => cur = cmt,
-
-                Categorization::Rvalue(..) |
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break
-            }
-        }
-    }
-    fn borrow(&mut self,
-              borrow_id: ast::NodeId,
-              borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
-              _loan_region: ty::Region,
-              bk: ty::BorrowKind,
-              loan_cause: euv::LoanCause)
-    {
-        // Kind of hacky, but we allow Unsafe coercions in constants.
-        // These occur when we convert a &T or *T to a *U, as well as
-        // when making a thin pointer (e.g., `*T`) into a fat pointer
-        // (e.g., `*Trait`).
-        match loan_cause {
-            euv::LoanCause::AutoUnsafe => {
-                return;
-            }
-            _ => { }
-        }
-
-        let mut cur = &cmt;
-        let mut is_interior = false;
-        loop {
-            match cur.cat {
-                Categorization::Rvalue(..) => {
-                    if loan_cause == euv::MatchDiscriminant {
-                        // Ignore the dummy immutable borrow created by EUV.
-                        break;
-                    }
-                    let mutbl = bk.to_mutbl_lossy();
-                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
-                        // Mutable slices are the only `&mut` allowed in
-                        // globals, but only in `static mut`, nowhere else.
-                        // FIXME: This exception is really weird... there isn't
-                        // any fundamental reason to restrict this based on
-                        // type of the expression.  `&mut [1]` has exactly the
-                        // same representation as &mut 1.
-                        match cmt.ty.sty {
-                            ty::TyArray(_, _) | ty::TySlice(_) => break,
-                            _ => {}
-                        }
-                    }
-                    self.record_borrow(borrow_id, mutbl);
-                    break;
-                }
-                Categorization::StaticItem => {
-                    if is_interior && self.mode != Mode::Var {
-                        // Borrowed statics can specifically *only* have their address taken,
-                        // not any number of other borrows such as borrowing fields, reading
-                        // elements of an array, etc.
-                        span_err!(self.tcx.sess, borrow_span, E0494,
-                                  "cannot refer to the interior of another \
-                                   static, use a constant instead");
-                    }
-                    break;
-                }
-                Categorization::Deref(ref cmt, _, _) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => {
-                    is_interior = true;
-                    cur = cmt;
-                }
-
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break
-            }
-        }
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {}
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {}
-
-    fn matched_pat(&mut self,
-                   _: &hir::Pat,
-                   _: mc::cmt,
-                   _: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {}
-}
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
deleted file mode 100644 (file)
index 22e9df6..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2012-2014 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 self::Context::*;
-
-use session::Session;
-
-use syntax::codemap::Span;
-use rustc_front::intravisit::{self, Visitor};
-use rustc_front::hir;
-
-#[derive(Clone, Copy, PartialEq)]
-enum Context {
-    Normal, Loop, Closure
-}
-
-#[derive(Copy, Clone)]
-struct CheckLoopVisitor<'a> {
-    sess: &'a Session,
-    cx: Context
-}
-
-pub fn check_crate(sess: &Session, krate: &hir::Crate) {
-    krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
-}
-
-impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
-    fn visit_item(&mut self, i: &hir::Item) {
-        self.with_context(Normal, |v| intravisit::walk_item(v, i));
-    }
-
-    fn visit_expr(&mut self, e: &hir::Expr) {
-        match e.node {
-            hir::ExprWhile(ref e, ref b, _) => {
-                self.visit_expr(&**e);
-                self.with_context(Loop, |v| v.visit_block(&**b));
-            }
-            hir::ExprLoop(ref b, _) => {
-                self.with_context(Loop, |v| v.visit_block(&**b));
-            }
-            hir::ExprClosure(_, _, ref b) => {
-                self.with_context(Closure, |v| v.visit_block(&**b));
-            }
-            hir::ExprBreak(_) => self.require_loop("break", e.span),
-            hir::ExprAgain(_) => self.require_loop("continue", e.span),
-            _ => intravisit::walk_expr(self, e)
-        }
-    }
-}
-
-impl<'a> CheckLoopVisitor<'a> {
-    fn with_context<F>(&mut self, cx: Context, f: F) where
-        F: FnOnce(&mut CheckLoopVisitor<'a>),
-    {
-        let old_cx = self.cx;
-        self.cx = cx;
-        f(self);
-        self.cx = old_cx;
-    }
-
-    fn require_loop(&self, name: &str, span: Span) {
-        match self.cx {
-            Loop => {}
-            Closure => {
-                span_err!(self.sess, span, E0267,
-                                   "`{}` inside of a closure", name);
-            }
-            Normal => {
-                span_err!(self.sess, span, E0268,
-                                   "`{}` outside of loop", name);
-            }
-        }
-    }
-}
index 8e5c5788201cccb8e45e9928050d7dc4be9d4c29..d52089dbeab5680b1a57567eac5150d9b3e5dd95 100644 (file)
@@ -246,7 +246,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-                    if let Some(DefLocal(..)) = def {
+                    if let Some(Def::Local(..)) = def {
                         if edef.variants.iter().any(|variant|
                             variant.name == ident.node.unhygienic_name
                                 && variant.kind() == VariantKind::Unit
@@ -454,8 +454,8 @@ fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
             hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
-                    Some(DefAssociatedConst(did)) |
-                    Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did,
+                    Some(Def::AssociatedConst(did)) |
+                    Some(Def::Const(did)) => match lookup_const_by_id(self.tcx, did,
                                                                     Some(pat.id), None) {
                         Some(const_expr) => {
                             const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
@@ -757,19 +757,19 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     match pat.node {
         hir::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefStruct(_)) => vec!(Single),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Struct(..)) => vec!(Single),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!()
             },
         hir::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatQPath(..) =>
@@ -777,10 +777,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                                             been rewritten"),
         hir::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatLit(ref expr) =>
@@ -869,10 +869,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
+                Some(Def::Variant(_, id)) => if *constructor == Variant(id) {
                     Some(vec!())
                 } else {
                     None
@@ -884,11 +884,11 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
-                DefConst(..) | DefAssociatedConst(..) =>
+                Def::Const(..) | Def::AssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                DefVariant(_, id, _) if *constructor != Variant(id) => None,
-                DefVariant(..) | DefStruct(..) => {
+                Def::Variant(_, id) if *constructor != Variant(id) => None,
+                Def::Variant(..) | Def::Struct(..) => {
                     Some(match args {
                         &Some(ref args) => args.iter().map(|p| &**p).collect(),
                         &None => vec![DUMMY_WILD_PAT; arity],
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
deleted file mode 100644 (file)
index 5ead8fb..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 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.
-
-// Checks that all rvalues in a crate have statically known size. check_crate
-// is the public starting point.
-
-use dep_graph::DepNode;
-use middle::expr_use_visitor as euv;
-use middle::infer;
-use middle::mem_categorization as mc;
-use middle::ty::ParameterEnvironment;
-use middle::ty;
-
-use rustc_front::hir;
-use rustc_front::intravisit;
-use syntax::ast;
-use syntax::codemap::Span;
-
-pub fn check_crate(tcx: &ty::ctxt) {
-    let mut rvcx = RvalueContext { tcx: tcx };
-    tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
-}
-
-struct RvalueContext<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-}
-
-impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
-    fn visit_fn(&mut self,
-                fk: intravisit::FnKind<'v>,
-                fd: &'v hir::FnDecl,
-                b: &'v hir::Block,
-                s: Span,
-                fn_id: ast::NodeId) {
-        {
-            // FIXME (@jroesch) change this to be an inference context
-            let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
-            let infcx = infer::new_infer_ctxt(self.tcx,
-                                              &self.tcx.tables,
-                                              Some(param_env.clone()));
-            let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
-            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
-            euv.walk_fn(fd, b);
-        }
-        intravisit::walk_fn(self, fk, fd, b, s)
-    }
-}
-
-struct RvalueContextDelegate<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'a,'tcx>,
-}
-
-impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
-    fn consume(&mut self,
-               _: ast::NodeId,
-               span: Span,
-               cmt: mc::cmt<'tcx>,
-               _: euv::ConsumeMode) {
-        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
-        if !cmt.ty.is_sized(self.param_env, span) {
-            span_err!(self.tcx.sess, span, E0161,
-                "cannot move a value of type {0}: the size of {0} cannot be statically determined",
-                cmt.ty);
-        }
-    }
-
-    fn matched_pat(&mut self,
-                   _matched_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {
-    }
-
-    fn borrow(&mut self,
-              _borrow_id: ast::NodeId,
-              _borrow_span: Span,
-              _cmt: mc::cmt,
-              _loan_region: ty::Region,
-              _bk: ty::BorrowKind,
-              _loan_cause: euv::LoanCause) {
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {
-    }
-
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {
-    }
-}
diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs
deleted file mode 100644 (file)
index 0882f3f..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2014 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.
-
-// This compiler pass detects constants that refer to themselves
-// recursively.
-
-use front::map as ast_map;
-use session::Session;
-use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant, DefMap};
-use util::nodemap::NodeMap;
-
-use syntax::{ast};
-use syntax::codemap::Span;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
-use rustc_front::intravisit::{self, Visitor};
-use rustc_front::hir;
-
-use std::cell::RefCell;
-
-struct CheckCrateVisitor<'a, 'ast: 'a> {
-    sess: &'a Session,
-    def_map: &'a DefMap,
-    ast_map: &'a ast_map::Map<'ast>,
-    // `discriminant_map` is a cache that associates the `NodeId`s of local
-    // variant definitions with the discriminant expression that applies to
-    // each one. If the variant uses the default values (starting from `0`),
-    // then `None` is stored.
-    discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
-}
-
-impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast hir::Item) {
-        match it.node {
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) => {
-                let mut recursion_visitor =
-                    CheckItemRecursionVisitor::new(self, &it.span);
-                recursion_visitor.visit_item(it);
-            },
-            hir::ItemEnum(ref enum_def, ref generics) => {
-                // We could process the whole enum, but handling the variants
-                // with discriminant expressions one by one gives more specific,
-                // less redundant output.
-                for variant in &enum_def.variants {
-                    if let Some(_) = variant.node.disr_expr {
-                        let mut recursion_visitor =
-                            CheckItemRecursionVisitor::new(self, &variant.span);
-                        recursion_visitor.populate_enum_discriminants(enum_def);
-                        recursion_visitor.visit_variant(variant, generics, it.id);
-                    }
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_item(self, it)
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
-        match ti.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(_) = *default {
-                    let mut recursion_visitor =
-                        CheckItemRecursionVisitor::new(self, &ti.span);
-                    recursion_visitor.visit_trait_item(ti);
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_trait_item(self, ti)
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
-        match ii.node {
-            hir::ImplItemKind::Const(..) => {
-                let mut recursion_visitor =
-                    CheckItemRecursionVisitor::new(self, &ii.span);
-                recursion_visitor.visit_impl_item(ii);
-            }
-            _ => {}
-        }
-        intravisit::walk_impl_item(self, ii)
-    }
-}
-
-pub fn check_crate<'ast>(sess: &Session,
-                         krate: &'ast hir::Crate,
-                         def_map: &DefMap,
-                         ast_map: &ast_map::Map<'ast>) {
-    let mut visitor = CheckCrateVisitor {
-        sess: sess,
-        def_map: def_map,
-        ast_map: ast_map,
-        discriminant_map: RefCell::new(NodeMap()),
-    };
-    sess.abort_if_new_errors(|| {
-        krate.visit_all_items(&mut visitor);
-    });
-}
-
-struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
-    root_span: &'a Span,
-    sess: &'a Session,
-    ast_map: &'a ast_map::Map<'ast>,
-    def_map: &'a DefMap,
-    discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
-    idstack: Vec<ast::NodeId>,
-}
-
-impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
-    fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span)
-           -> CheckItemRecursionVisitor<'a, 'ast> {
-        CheckItemRecursionVisitor {
-            root_span: span,
-            sess: v.sess,
-            ast_map: v.ast_map,
-            def_map: v.def_map,
-            discriminant_map: &v.discriminant_map,
-            idstack: Vec::new(),
-        }
-    }
-    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
-          where F: Fn(&mut Self) {
-        if self.idstack.iter().any(|&x| x == id) {
-            let any_static = self.idstack.iter().any(|&x| {
-                if let ast_map::NodeItem(item) = self.ast_map.get(x) {
-                    if let hir::ItemStatic(..) = item.node {
-                        true
-                    } else {
-                        false
-                    }
-                } else {
-                    false
-                }
-            });
-            if any_static {
-                if !self.sess.features.borrow().static_recursion {
-                    emit_feature_err(&self.sess.parse_sess.span_diagnostic,
-                                     "static_recursion",
-                                     *self.root_span, GateIssue::Language, "recursive static");
-                }
-            } else {
-                span_err!(self.sess, *self.root_span, E0265, "recursive constant");
-            }
-            return;
-        }
-        self.idstack.push(id);
-        f(self);
-        self.idstack.pop();
-    }
-    // If a variant has an expression specifying its discriminant, then it needs
-    // to be checked just like a static or constant. However, if there are more
-    // variants with no explicitly specified discriminant, those variants will
-    // increment the same expression to get their values.
-    //
-    // So for every variant, we need to track whether there is an expression
-    // somewhere in the enum definition that controls its discriminant. We do
-    // this by starting from the end and searching backward.
-    fn populate_enum_discriminants(&self, enum_definition: &'ast hir::EnumDef) {
-        // Get the map, and return if we already processed this enum or if it
-        // has no variants.
-        let mut discriminant_map = self.discriminant_map.borrow_mut();
-        match enum_definition.variants.first() {
-            None => { return; }
-            Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => {
-                return;
-            }
-            _ => {}
-        }
-
-        // Go through all the variants.
-        let mut variant_stack: Vec<ast::NodeId> = Vec::new();
-        for variant in enum_definition.variants.iter().rev() {
-            variant_stack.push(variant.node.data.id());
-            // When we find an expression, every variant currently on the stack
-            // is affected by that expression.
-            if let Some(ref expr) = variant.node.disr_expr {
-                for id in &variant_stack {
-                    discriminant_map.insert(*id, Some(expr));
-                }
-                variant_stack.clear()
-            }
-        }
-        // If we are at the top, that always starts at 0, so any variant on the
-        // stack has a default value and does not need to be checked.
-        for id in &variant_stack {
-            discriminant_map.insert(*id, None);
-        }
-    }
-}
-
-impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast hir::Item) {
-        self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it));
-    }
-
-    fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
-                      generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) {
-        self.populate_enum_discriminants(enum_definition);
-        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
-    }
-
-    fn visit_variant(&mut self, variant: &'ast hir::Variant,
-                     _: &'ast hir::Generics, _: ast::NodeId) {
-        let variant_id = variant.node.data.id();
-        let maybe_expr;
-        if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
-            // This is necessary because we need to let the `discriminant_map`
-            // borrow fall out of scope, so that we can reborrow farther down.
-            maybe_expr = (*get_expr).clone();
-        } else {
-            self.sess.span_bug(variant.span,
-                               "`check_static_recursion` attempted to visit \
-                                variant with unknown discriminant")
-        }
-        // If `maybe_expr` is `None`, that's because no discriminant is
-        // specified that affects this variant. Thus, no risk of recursion.
-        if let Some(expr) = maybe_expr {
-            self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr));
-        }
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
-        self.with_item_id_pushed(ti.id, |v| intravisit::walk_trait_item(v, ti));
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
-        self.with_item_id_pushed(ii.id, |v| intravisit::walk_impl_item(v, ii));
-    }
-
-    fn visit_expr(&mut self, e: &'ast hir::Expr) {
-        match e.node {
-            hir::ExprPath(..) => {
-                match self.def_map.get(&e.id).map(|d| d.base_def) {
-                    Some(DefStatic(def_id, _)) |
-                    Some(DefAssociatedConst(def_id)) |
-                    Some(DefConst(def_id)) => {
-                        if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
-                            match self.ast_map.get(node_id) {
-                                ast_map::NodeItem(item) =>
-                                    self.visit_item(item),
-                                ast_map::NodeTraitItem(item) =>
-                                    self.visit_trait_item(item),
-                                ast_map::NodeImplItem(item) =>
-                                    self.visit_impl_item(item),
-                                ast_map::NodeForeignItem(_) => {},
-                                _ => {
-                                    self.sess.span_bug(
-                                        e.span,
-                                        &format!("expected item, found {}",
-                                                 self.ast_map.node_to_string(node_id)));
-                                }
-                            }
-                        }
-                    }
-                    // For variants, we only want to check expressions that
-                    // affect the specific variant used, but we need to check
-                    // the whole enum definition to see what expression that
-                    // might be (if any).
-                    Some(DefVariant(enum_id, variant_id, false)) => {
-                        if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) {
-                            if let hir::ItemEnum(ref enum_def, ref generics) =
-                                self.ast_map.expect_item(enum_node_id).node
-                            {
-                                self.populate_enum_discriminants(enum_def);
-                                let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap();
-                                let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap();
-                                let variant = self.ast_map.expect_variant(variant_id);
-                                self.visit_variant(variant, generics, enum_id);
-                            } else {
-                                self.sess.span_bug(e.span,
-                                                   "`check_static_recursion` found \
-                                                    non-enum in DefVariant");
-                            }
-                        }
-                    }
-                    _ => ()
-                }
-            },
-            _ => ()
-        }
-        intravisit::walk_expr(self, e);
-    }
-}
index eae2aa9cb7e736547332d177b6ea48812604bbdb..942f2d6efb1af7e4c7e511af737f0d9807a0afef 100644 (file)
@@ -17,7 +17,8 @@
 use front::map as ast_map;
 use front::map::blocks::FnLikeNode;
 use middle::cstore::{self, CrateStore, InlinedItem};
-use middle::{def, infer, subst, traits};
+use middle::{infer, subst, traits};
+use middle::def::Def;
 use middle::subst::Subst;
 use middle::def_id::DefId;
 use middle::pat_util::def_to_path;
@@ -331,9 +332,9 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
                entry.insert(def);
             }
             let path = match def.full_def() {
-                def::DefStruct(def_id) => def_to_path(tcx, def_id),
-                def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
-                def::DefFn(..) => return P(hir::Pat {
+                Def::Struct(def_id) => def_to_path(tcx, def_id),
+                Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
+                Def::Fn(..) => return P(hir::Pat {
                     id: expr.id,
                     node: hir::PatLit(P(expr.clone())),
                     span: span,
@@ -364,12 +365,12 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
         hir::ExprPath(_, ref path) => {
             let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
-                Some(def::DefStruct(..)) =>
+                Some(Def::Struct(..)) =>
                     hir::PatStruct(path.clone(), hir::HirVec::new(), false),
-                Some(def::DefVariant(..)) =>
+                Some(Def::Variant(..)) =>
                     hir::PatEnum(path.clone(), None),
-                Some(def::DefConst(def_id)) |
-                Some(def::DefAssociatedConst(def_id)) => {
+                Some(Def::Const(def_id)) |
+                Some(Def::AssociatedConst(def_id)) => {
                     let expr = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
                     return const_expr_to_pat(tcx, expr, span);
                 },
@@ -1002,7 +1003,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               None
           };
           let (const_expr, const_ty) = match opt_def {
-              Some(def::DefConst(def_id)) => {
+              Some(Def::Const(def_id)) => {
                   if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                       match tcx.map.find(node_id) {
                           Some(ast_map::NodeItem(it)) => match it.node {
@@ -1017,7 +1018,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
                   }
               }
-              Some(def::DefAssociatedConst(def_id)) => {
+              Some(Def::AssociatedConst(def_id)) => {
                   if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                       match tcx.impl_or_trait_item(def_id).container() {
                           ty::TraitContainer(trait_id) => match tcx.map.find(node_id) {
@@ -1052,21 +1053,21 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
                   }
               }
-              Some(def::DefVariant(enum_def, variant_def, _)) => {
+              Some(Def::Variant(enum_def, variant_def)) => {
                   (lookup_variant_by_id(tcx, enum_def, variant_def), None)
               }
-              Some(def::DefStruct(_)) => {
+              Some(Def::Struct(..)) => {
                   return Ok(ConstVal::Struct(e.id))
               }
-              Some(def::DefLocal(_, id)) => {
-                  debug!("DefLocal({:?}): {:?}", id, fn_args);
+              Some(Def::Local(_, id)) => {
+                  debug!("Def::Local({:?}): {:?}", id, fn_args);
                   if let Some(val) = fn_args.and_then(|args| args.get(&id)) {
                       return Ok(val.clone());
                   } else {
                       (None, None)
                   }
               },
-              Some(def::DefMethod(id)) | Some(def::DefFn(id, _)) => return Ok(Function(id)),
+              Some(Def::Method(id)) | Some(Def::Fn(id)) => return Ok(Function(id)),
               _ => (None, None)
           };
           let const_expr = match const_expr {
diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs
new file mode 100644 (file)
index 0000000..ec98637
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Const qualification, from partial to completely promotable.
+bitflags! {
+    #[derive(RustcEncodable, RustcDecodable)]
+    flags ConstQualif: u8 {
+        // Inner mutability (can not be placed behind a reference) or behind
+        // &mut in a non-global expression. Can be copied from static memory.
+        const MUTABLE_MEM        = 1 << 0,
+        // Constant value with a type that implements Drop. Can be copied
+        // from static memory, similar to MUTABLE_MEM.
+        const NEEDS_DROP         = 1 << 1,
+        // Even if the value can be placed in static memory, copying it from
+        // there is more expensive than in-place instantiation, and/or it may
+        // be too large. This applies to [T; N] and everything containing it.
+        // N.B.: references need to clear this flag to not end up on the stack.
+        const PREFER_IN_PLACE    = 1 << 2,
+        // May use more than 0 bytes of memory, doesn't impact the constness
+        // directly, but is not allowed to be borrowed mutably in a constant.
+        const NON_ZERO_SIZED     = 1 << 3,
+        // Actually borrowed, has to always be in static memory. Does not
+        // propagate, and requires the expression to behave like a 'static
+        // lvalue. The set of expressions with this flag is the minimum
+        // that have to be promoted.
+        const HAS_STATIC_BORROWS = 1 << 4,
+        // Invalid const for miscellaneous reasons (e.g. not implemented).
+        const NOT_CONST          = 1 << 5,
+
+        // Borrowing the expression won't produce &'static T if any of these
+        // bits are set, though the value could be copied from static memory
+        // if `NOT_CONST` isn't set.
+        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
+                                   ConstQualif::NEEDS_DROP.bits |
+                                   ConstQualif::NOT_CONST.bits
+    }
+}
index 380f543f969f06b4c2a77dde7c27233957032325..27745a85935abf00d8c6668ca8da7b61754c81b3 100644 (file)
@@ -24,9 +24,9 @@
 
 use back::svh::Svh;
 use front::map as hir_map;
-use middle::def;
+use middle::def::{self, Def};
 use middle::lang_items;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, VariantKind};
 use middle::def_id::{DefId, DefIndex};
 use mir::repr::Mir;
 use session::Session;
@@ -84,7 +84,7 @@ pub enum NativeLibraryKind {
 // Something that a name can resolve to.
 #[derive(Copy, Clone, Debug)]
 pub enum DefLike {
-    DlDef(def::Def),
+    DlDef(Def),
     DlImpl(DefId),
     DlField
 }
@@ -211,6 +211,8 @@ fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
 
     // resolve
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
     fn item_children(&self, did: DefId) -> Vec<ChildItem>;
@@ -380,6 +382,9 @@ fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
 
     // resolve
     fn def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
+        { unimplemented!() }
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
         { unimplemented!() }
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { unimplemented!() }
index 1386ef91c70bf49e0ec7209f2252cbd9cb1bbcfa..1fa4093853b8199d10867094ac86307bc1c0609c 100644 (file)
@@ -17,7 +17,8 @@
 use rustc_front::hir;
 use rustc_front::intravisit::{self, Visitor};
 
-use middle::{def, pat_util, privacy, ty};
+use middle::{pat_util, privacy, ty};
+use middle::def::Def;
 use middle::def_id::{DefId};
 use lint;
 
@@ -94,13 +95,13 @@ fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
 
         self.tcx.def_map.borrow().get(id).map(|def| {
             match def.full_def() {
-                def::DefConst(_) | def::DefAssociatedConst(..) => {
+                Def::Const(_) | Def::AssociatedConst(..) => {
                     self.check_def_id(def.def_id());
                 }
                 _ if self.ignore_non_const_paths => (),
-                def::DefPrimTy(_) => (),
-                def::DefSelfTy(..) => (),
-                def::DefVariant(enum_id, variant_id, _) => {
+                Def::PrimTy(_) => (),
+                Def::SelfTy(..) => (),
+                Def::Variant(enum_id, variant_id) => {
                     self.check_def_id(enum_id);
                     if !self.ignore_variant_stack.contains(&variant_id) {
                         self.check_def_id(variant_id);
index 9ef2828c947aad2469d7f766ebe799b7e5830aeb..be967da2713b328b352c202d6d2cbb3f5adab7b5 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::Def::*;
-
 use middle::def_id::DefId;
 use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Def {
-    DefFn(DefId, bool /* is_ctor */),
-    DefSelfTy(Option<DefId>,                    // trait id
+    Fn(DefId),
+    SelfTy(Option<DefId>,                    // trait id
               Option<(ast::NodeId, ast::NodeId)>),   // (impl id, self type id)
-    DefMod(DefId),
-    DefForeignMod(DefId),
-    DefStatic(DefId, bool /* is_mutbl */),
-    DefConst(DefId),
-    DefAssociatedConst(DefId),
-    DefLocal(DefId, // def id of variable
+    Mod(DefId),
+    ForeignMod(DefId),
+    Static(DefId, bool /* is_mutbl */),
+    Const(DefId),
+    AssociatedConst(DefId),
+    Local(DefId, // def id of variable
              ast::NodeId), // node id of variable
-    DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
-    DefTy(DefId, bool /* is_enum */),
-    DefAssociatedTy(DefId /* trait */, DefId),
-    DefTrait(DefId),
-    DefPrimTy(hir::PrimTy),
-    DefTyParam(ParamSpace, u32, DefId, ast::Name),
-    DefUpvar(DefId,        // def id of closed over local
+    Variant(DefId /* enum */, DefId /* variant */),
+    Enum(DefId),
+    TyAlias(DefId),
+    AssociatedTy(DefId /* trait */, DefId),
+    Trait(DefId),
+    PrimTy(hir::PrimTy),
+    TyParam(ParamSpace, u32, DefId, ast::Name),
+    Upvar(DefId,        // def id of closed over local
              ast::NodeId,  // node id of closed over local
              usize,        // index in the freevars list of the closure
              ast::NodeId), // expr node that creates the closure
 
-    /// Note that if it's a tuple struct's definition, the node id of the DefId
-    /// may either refer to the item definition's id or the VariantData.ctor_id.
-    ///
-    /// The cases that I have encountered so far are (this is not exhaustive):
-    /// - If it's a ty_path referring to some tuple struct, then DefMap maps
-    ///   it to a def whose id is the item definition's id.
-    /// - If it's an ExprPath referring to some tuple struct, then DefMap maps
-    ///   it to a def whose id is the VariantData.ctor_id.
-    DefStruct(DefId),
-    DefLabel(ast::NodeId),
-    DefMethod(DefId),
-    DefErr,
+    // If Def::Struct lives in type namespace it denotes a struct item and its DefId refers
+    // to NodeId of the struct itself.
+    // If Def::Struct lives in value namespace (e.g. tuple struct, unit struct expressions)
+    // it denotes a constructor and its DefId refers to NodeId of the struct's constructor.
+    Struct(DefId),
+    Label(ast::NodeId),
+    Method(DefId),
+    Err,
 }
 
 /// The result of resolving a path.
@@ -115,16 +110,16 @@ pub struct Export {
 impl Def {
     pub fn var_id(&self) -> ast::NodeId {
         match *self {
-            DefLocal(_, id) |
-            DefUpvar(_, id, _, _) => {
+            Def::Local(_, id) |
+            Def::Upvar(_, id, _, _) => {
                 id
             }
 
-            DefFn(..) | DefMod(..) | DefForeignMod(..) | DefStatic(..) |
-            DefVariant(..) | DefTy(..) | DefAssociatedTy(..) |
-            DefTyParam(..) | DefStruct(..) | DefTrait(..) |
-            DefMethod(..) | DefConst(..) | DefAssociatedConst(..) |
-            DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) | DefErr => {
+            Def::Fn(..) | Def::Mod(..) | Def::ForeignMod(..) | Def::Static(..) |
+            Def::Variant(..) | Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
+            Def::TyParam(..) | Def::Struct(..) | Def::Trait(..) |
+            Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) |
+            Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => {
                 panic!("attempted .def_id() on invalid {:?}", self)
             }
         }
@@ -132,18 +127,18 @@ pub fn var_id(&self) -> ast::NodeId {
 
     pub fn def_id(&self) -> DefId {
         match *self {
-            DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
-            DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
-            DefTyParam(_, _, id, _) | DefStruct(id) | DefTrait(id) |
-            DefMethod(id) | DefConst(id) | DefAssociatedConst(id) |
-            DefLocal(id, _) | DefUpvar(id, _, _, _) => {
+            Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
+            Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
+            Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) |
+            Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
+            Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
                 id
             }
 
-            DefLabel(..)  |
-            DefPrimTy(..) |
-            DefSelfTy(..) |
-            DefErr => {
+            Def::Label(..)  |
+            Def::PrimTy(..) |
+            Def::SelfTy(..) |
+            Def::Err => {
                 panic!("attempted .def_id() on invalid def: {:?}", self)
             }
         }
@@ -151,7 +146,7 @@ pub fn def_id(&self) -> DefId {
 
     pub fn variant_def_ids(&self) -> Option<(DefId, DefId)> {
         match *self {
-            DefVariant(enum_id, var_id, _) => {
+            Def::Variant(enum_id, var_id) => {
                 Some((enum_id, var_id))
             }
             _ => None
index 822faae772611f82c1a3b56385e4cf78f9f6e038..055beac5428440d3e4cd0943692de0cd8e489031 100644 (file)
@@ -12,7 +12,7 @@
 //! `unsafe`.
 use self::RootUnsafeContext::*;
 
-use middle::def;
+use middle::def::Def;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 
@@ -170,7 +170,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
             hir::ExprPath(..) => {
-                if let def::DefStatic(_, true) = self.tcx.resolve_expr(expr) {
+                if let Def::Static(_, true) = self.tcx.resolve_expr(expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
             }
index e746f3ac57914a712f61b39e935902a1219e72fe..b5baf84eef23da34faf5961af7e7c1d0755ee46c 100644 (file)
@@ -19,7 +19,8 @@
 use self::TrackMatchMode::*;
 use self::OverloadedCallType::*;
 
-use middle::{def, pat_util};
+use middle::pat_util;
+use middle::def::Def;
 use middle::def_id::{DefId};
 use middle::infer;
 use middle::mem_categorization as mc;
@@ -1077,7 +1078,7 @@ fn walk_pat(&mut self,
                             // struct or enum pattern.
                         }
 
-                        Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
+                        Some(Def::Variant(enum_did, variant_did)) => {
                             let downcast_cmt =
                                 if tcx.lookup_adt_def(enum_did).is_univariant() {
                                     cmt_pat
@@ -1093,7 +1094,7 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, downcast_cmt, match_mode);
                         }
 
-                        Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
+                        Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => {
                             // A struct (in either the value or type
                             // namespace; we encounter the former on
                             // e.g. patterns for unit structs).
@@ -1105,28 +1106,17 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, cmt_pat, match_mode);
                         }
 
-                        Some(def::DefConst(..)) |
-                        Some(def::DefAssociatedConst(..)) |
-                        Some(def::DefLocal(..)) => {
+                        Some(Def::Const(..)) |
+                        Some(Def::AssociatedConst(..)) |
+                        Some(Def::Local(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
                             // `matched_pat` call.
                         }
 
-                        Some(def @ def::DefTy(_, true)) => {
-                            // An enum's type -- should never be in a
-                            // pattern.
-
-                            if !tcx.sess.has_errors() {
-                                let msg = format!("Pattern has unexpected type: {:?} and type {:?}",
-                                                  def,
-                                                  cmt_pat.ty);
-                                tcx.sess.span_bug(pat.span, &msg)
-                            }
-                        }
-
                         Some(def) => {
-                            // Remaining cases are e.g. DefFn, to
+                            // An enum type should never be in a pattern.
+                            // Remaining cases are e.g. Def::Fn, to
                             // which identifiers within patterns
                             // should not resolve. However, we do
                             // encouter this when using the
@@ -1195,7 +1185,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr) {
     fn cat_captured_var(&mut self,
                         closure_id: ast::NodeId,
                         closure_span: Span,
-                        upvar_def: def::Def)
+                        upvar_def: Def)
                         -> mc::McResult<mc::cmt<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
index 5cc848d2ca3d1516cb0ee15825db05abce6c0820..b83cd60031d13f2736b7b1e551a2cdaa47ff46d4 100644 (file)
@@ -77,7 +77,7 @@
 use rustc_front::print::pprust;
 
 use middle::cstore::CrateStore;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer::{self, TypeOrigin};
 use middle::region;
@@ -1404,7 +1404,7 @@ fn rebuild_arg_ty_or_output(&self,
                         Some(d) => d.full_def()
                     };
                     match a_def {
-                        def::DefTy(did, _) | def::DefStruct(did) => {
+                        Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
                             let generics = self.tcx.lookup_item_type(did).generics;
 
                             let expected =
@@ -1452,7 +1452,6 @@ fn rebuild_arg_ty_or_output(&self,
                         }
                         _ => ()
                     }
-
                 }
 
                 hir::TyPtr(ref mut_ty) => {
index 69b952ca1f3fcf3ae42320e8d02d3c294cdb46cf..9afc1e366eed5793fb96d95488f074c29cc8078c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::DepNode;
-use middle::def::DefFn;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::subst::{Subst, Substs, EnumeratedItems};
 use middle::ty::{TransmuteRestriction, ctxt, TyBareFn};
@@ -235,7 +235,7 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
     fn visit_expr(&mut self, expr: &hir::Expr) {
         if let hir::ExprPath(..) = expr.node {
             match self.tcx.resolve_expr(expr) {
-                DefFn(did, _) if self.def_id_is_transmute(did) => {
+                Def::Fn(did) if self.def_id_is_transmute(did) => {
                     let typ = self.tcx.node_id_to_type(expr.id);
                     match typ.sty {
                         TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
index 29299f01ed36fcc2f4a4829a1906e8ef9549c321..90fa148e0084eb43bed1e683d668f2e453da86bb 100644 (file)
@@ -448,7 +448,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       hir::ExprPath(..) => {
         let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
-        if let DefLocal(..) = def {
+        if let Def::Local(..) = def {
             ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
         }
         intravisit::walk_expr(ir, expr);
@@ -465,7 +465,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         let mut call_caps = Vec::new();
         ir.tcx.with_freevars(expr.id, |freevars| {
             for fv in freevars {
-                if let DefLocal(_, rv) = fv.def {
+                if let Def::Local(_, rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
                     call_caps.push(CaptureInfo {ln: fv_ln,
                                                 var_nid: rv});
@@ -697,7 +697,7 @@ fn find_loop_scope(&self,
                 // Refers to a labeled loop. Use the results of resolve
                 // to find with one
                 match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
-                    Some(DefLabel(loop_id)) => loop_id,
+                    Some(Def::Label(loop_id)) => loop_id,
                     _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
                                                         doesn't refer to a loop")
                 }
@@ -1276,7 +1276,7 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
-          DefLocal(_, nid) => {
+          Def::Local(_, nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
                 self.init_from_succ(ln, succ);
@@ -1531,7 +1531,7 @@ fn check_ret(&self,
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
             hir::ExprPath(..) => {
-                if let DefLocal(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
+                if let Def::Local(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
                                                                       .unwrap()
                                                                       .full_def() {
                     // Assignment to an immutable variable or argument: only legal
index 1eb5efa0bda446eb88fe613d786608c88fb4359f..affd963fb79172fc2dc055ed58493e3f1fd3315f 100644 (file)
@@ -74,8 +74,8 @@
 use middle::def_id::DefId;
 use front::map as ast_map;
 use middle::infer;
-use middle::check_const;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::Def;
 use middle::ty::adjustment;
 use middle::ty::{self, Ty};
 
@@ -542,32 +542,27 @@ pub fn cat_def(&self,
                    id: ast::NodeId,
                    span: Span,
                    expr_ty: Ty<'tcx>,
-                   def: def::Def)
+                   def: Def)
                    -> McResult<cmt<'tcx>> {
         debug!("cat_def: id={} expr={:?} def={:?}",
                id, expr_ty, def);
 
         match def {
-          def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefAssociatedConst(..) | def::DefFn(..) | def::DefMethod(..) => {
+          Def::Struct(..) | Def::Variant(..) | Def::Const(..) |
+          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
-          def::DefMod(_) | def::DefForeignMod(_) |
-          def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
-          def::DefTyParam(..) |
-          def::DefLabel(_) | def::DefSelfTy(..) |
-          def::DefAssociatedTy(..) => {
-              Ok(Rc::new(cmt_ {
-                  id:id,
-                  span:span,
-                  cat:Categorization::StaticItem,
-                  mutbl: McImmutable,
-                  ty:expr_ty,
-                  note: NoteNone
-              }))
+
+          Def::Mod(_) | Def::ForeignMod(_) |
+          Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
+          Def::TyParam(..) |
+          Def::Label(_) | Def::SelfTy(..) |
+          Def::AssociatedTy(..) => {
+              self.tcx().sess.span_bug(span, &format!("Unexpected definition in \
+                                                       memory categorization: {:?}", def));
           }
 
-          def::DefStatic(_, mutbl) => {
+          Def::Static(_, mutbl) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
@@ -578,7 +573,7 @@ pub fn cat_def(&self,
               }))
           }
 
-          def::DefUpvar(_, var_id, _, fn_node_id) => {
+          Def::Upvar(_, var_id, _, fn_node_id) => {
               let ty = try!(self.node_ty(fn_node_id));
               match ty.sty {
                   ty::TyClosure(closure_id, _) => {
@@ -603,7 +598,7 @@ pub fn cat_def(&self,
               }
           }
 
-          def::DefLocal(_, vid) => {
+          Def::Local(_, vid) => {
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
@@ -614,7 +609,7 @@ pub fn cat_def(&self,
             }))
           }
 
-          def::DefErr => panic!("DefErr in memory categorization")
+          Def::Err => panic!("Def::Err in memory categorization")
         }
     }
 
@@ -800,19 +795,19 @@ pub fn cat_rvalue_node(&self,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
         let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
-                               .unwrap_or(check_const::ConstQualif::NOT_CONST);
+                               .unwrap_or(ConstQualif::NOT_CONST);
 
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
         let qualif = match expr_ty.sty {
             ty::TyArray(_, 0) => qualif,
-            _ => check_const::ConstQualif::NOT_CONST
+            _ => ConstQualif::NOT_CONST
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
+        let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
             self.temporary_scope(id)
         } else {
             ty::ReStatic
@@ -1202,7 +1197,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         (*op)(self, cmt.clone(), pat);
 
         let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) {
-            if path_res.depth != 0 || path_res.base_def == def::DefErr {
+            if path_res.depth != 0 || path_res.base_def == Def::Err {
                 // Since patterns can be associated constants
                 // which are resolved during typeck, we might have
                 // some unresolved patterns reaching this stage
@@ -1218,7 +1213,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         // alone) because struct patterns can refer to struct types or
         // to struct variants within enums.
         let cmt = match opt_def {
-            Some(def::DefVariant(enum_did, variant_did, _))
+            Some(Def::Variant(enum_did, variant_did))
                 // univariant enums do not need downcasts
                 if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@@ -1236,7 +1231,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
           }
           hir::PatEnum(_, Some(ref subpats)) => {
             match opt_def {
-                Some(def::DefVariant(..)) => {
+                Some(Def::Variant(..)) => {
                     // variant(x, y, z)
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@@ -1249,7 +1244,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                         try!(self.cat_pattern_(subcmt, &**subpat, op));
                     }
                 }
-                Some(def::DefStruct(..)) => {
+                Some(Def::Struct(..)) => {
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
                         let cmt_field =
@@ -1259,7 +1254,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                         try!(self.cat_pattern_(cmt_field, &**subpat, op));
                     }
                 }
-                Some(def::DefConst(..)) | Some(def::DefAssociatedConst(..)) => {
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
index 1284e9fd1454eab7044b9cdd7e263f0c170f4f2a..41367b9361fbb2866d9979b536f65c73aa4753b4 100644 (file)
@@ -39,7 +39,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
         hir::PatIdent(_, _, None) |
         hir::PatStruct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefVariant(..)) => true,
+                Some(Def::Variant(..)) => true,
                 _ => false
             }
         }
@@ -54,7 +54,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
         hir::PatIdent(_, _, None) |
         hir::PatStruct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefVariant(..)) | Some(DefStruct(..)) => true,
+                Some(Def::Variant(..)) | Some(Def::Struct(..)) => true,
                 _ => false
             }
         }
@@ -66,7 +66,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
         hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
             }
         }
@@ -82,7 +82,7 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
             match dm.get(&pat.id)
                     .and_then(|d| if d.depth == 0 { Some(d.base_def) }
                                   else { None } ) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
             }
         }
@@ -228,7 +228,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
             hir::PatIdent(_, _, None) |
             hir::PatStruct(..) => {
                 match dm.get(&p.id) {
-                    Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
+                    Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => {
                         variants.push(id);
                     }
                     _ => ()
index 738440adf416d9280ff08a92a998db81e66c4f87..6373bfbc55ee65c70e8276916c76d9ad50e6a057 100644 (file)
@@ -17,7 +17,7 @@
 
 use dep_graph::DepNode;
 use front::map as ast_map;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::ty;
 use middle::privacy;
@@ -108,7 +108,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
-                            def::DefConst(..) | def::DefAssociatedConst(..) => {
+                            Def::Const(..) | Def::AssociatedConst(..) => {
                                 self.worklist.push(node_id);
                             }
 
index 543b218a2bc05f128699755cd9c388d3b7a25d46..2f1342a598dc4fae5679baf63389dfb9fcb2c4bf 100644 (file)
@@ -14,7 +14,7 @@
 //! region parameterized.
 //!
 //! Most of the documentation on regions can be found in
-//! `middle/typeck/infer/region_inference.rs`
+//! `middle/infer/region_inference/README.md`
 
 use front::map as ast_map;
 use session::Session;
index 2c74f3a82e41441e39cc501e9436691c96b5a669..af9d0987ff073e41be5363eac012eb4cafe4de56 100644 (file)
@@ -19,7 +19,7 @@
 use self::ScopeChain::*;
 
 use session::Session;
-use middle::def::{self, DefMap};
+use middle::def::{Def, DefMap};
 use middle::region;
 use middle::subst;
 use middle::ty;
@@ -205,7 +205,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
                 match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
-                    Some((def::DefTrait(..), 0)) => {
+                    Some((Def::Trait(..), 0)) => {
                         self.with(LateScope(&[], self.scope), |_, this| {
                             this.visit_path(path, ty.id);
                         });
index 87bc8bb885584a9ec7f599777083fc15c4d3e236..e0d38f1c76f6ceea10b7fd3a0c53d72a5388667c 100644 (file)
@@ -17,7 +17,7 @@
 use session::Session;
 use lint;
 use middle::cstore::{CrateStore, LOCAL_CRATE};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::ty;
 use middle::privacy::AccessLevels;
@@ -561,8 +561,8 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
 pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
-        Some(def::DefPrimTy(..)) => {}
-        Some(def::DefSelfTy(..)) => {}
+        Some(Def::PrimTy(..)) => {}
+        Some(Def::SelfTy(..)) => {}
         Some(def) => {
             maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
         }
@@ -573,7 +573,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
 pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
-        Some(def::DefPrimTy(..)) => {}
+        Some(Def::PrimTy(..)) => {}
         Some(def) => {
             maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
         }
index d1504d25288a8d93c4db24aee8e3ccdd5ed74006..6e56105dd0dae1b174d754f35f763dba967e9e4f 100644 (file)
@@ -373,7 +373,7 @@ pub struct ctxt<'tcx> {
     repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>,
 
     /// Maps Expr NodeId's to their constant qualification.
-    pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
+    pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
index b902a46fea314083d6a0e4d70c42d218b100a43c..a56752db137222f2c5eb125def36144278c1ffa2 100644 (file)
@@ -24,7 +24,7 @@
 use front::map::LinkedPath;
 use middle;
 use middle::cstore::{self, CrateStore, LOCAL_CRATE};
-use middle::def::{self, ExportMap};
+use middle::def::{self, Def, ExportMap};
 use middle::def_id::DefId;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::region::{CodeExtent};
@@ -587,7 +587,7 @@ pub struct UpvarBorrow {
 
 #[derive(Copy, Clone)]
 pub struct ClosureUpvar<'tcx> {
-    pub def: def::Def,
+    pub def: Def,
     pub span: Span,
     pub ty: Ty<'tcx>,
 }
@@ -1429,9 +1429,19 @@ fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> {
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum AdtKind { Struct, Enum }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum VariantKind { Struct, Tuple, Unit }
 
+impl VariantKind {
+    pub fn from_variant_data(vdata: &hir::VariantData) -> Self {
+        match *vdata {
+            hir::VariantData::Struct(..) => VariantKind::Struct,
+            hir::VariantData::Tuple(..) => VariantKind::Tuple,
+            hir::VariantData::Unit(..) => VariantKind::Unit,
+        }
+    }
+}
+
 impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
     fn new(tcx: &ctxt<'tcx>,
            did: DefId,
@@ -1575,10 +1585,10 @@ pub fn variant_index_with_id(&self, vid: DefId) -> usize {
             .expect("variant_index_with_id: unknown variant")
     }
 
-    pub fn variant_of_def(&self, def: def::Def) -> &VariantDefData<'tcx, 'container> {
+    pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'tcx, 'container> {
         match def {
-            def::DefVariant(_, vid, _) => self.variant_with_id(vid),
-            def::DefStruct(..) | def::DefTy(..) => self.struct_variant(),
+            Def::Variant(_, vid) => self.variant_with_id(vid),
+            Def::Struct(..) | Def::TyAlias(..) => self.struct_variant(),
             _ => panic!("unexpected def {:?} in variant_of_def", def)
         }
     }
@@ -1924,7 +1934,7 @@ pub fn local_var_name_str(&self, id: NodeId) -> InternedString {
         }
     }
 
-    pub fn resolve_expr(&self, expr: &hir::Expr) -> def::Def {
+    pub fn resolve_expr(&self, expr: &hir::Expr) -> Def {
         match self.def_map.borrow().get(&expr.id) {
             Some(def) => def.full_def(),
             None => {
@@ -1942,15 +1952,15 @@ pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool {
                 // rvalues.
                 match self.def_map.borrow().get(&expr.id) {
                     Some(&def::PathResolution {
-                        base_def: def::DefStatic(..), ..
+                        base_def: Def::Static(..), ..
                     }) | Some(&def::PathResolution {
-                        base_def: def::DefUpvar(..), ..
+                        base_def: Def::Upvar(..), ..
                     }) | Some(&def::PathResolution {
-                        base_def: def::DefLocal(..), ..
+                        base_def: Def::Local(..), ..
                     }) => {
                         true
                     }
-                    Some(&def::PathResolution { base_def: def::DefErr, .. })=> true,
+                    Some(&def::PathResolution { base_def: Def::Err, .. })=> true,
                     Some(..) => false,
                     None => self.sess.span_bug(expr.span, &format!(
                         "no def for path {}", expr.id))
@@ -2612,7 +2622,7 @@ pub enum ExplicitSelfCategory {
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct Freevar {
     /// The variable being accessed free.
-    pub def: def::Def,
+    pub def: Def,
 
     // First span where it is accessed (there can be multiple).
     pub span: Span
index 83970e73b933ce598fa770b36bac5acfc225b1a9..3ba0c671d2ef0d3fa7627f629a66c526ef3ce6ab 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_base::opts();
+    base.cpu = "ppc64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
index 0f5252fdc23a5cec36fefca01e5409f22387d37a..c82666ffcfe561af5e36167e2cbf5dbe58f9a378 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_base::opts();
+    base.cpu = "ppc64le".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
index 01ffd0efbe3143c4373eec24af55d7af9725a05d..fd5f711c9d6399d189b979a5b13b08892ed154cb 100644 (file)
@@ -34,6 +34,7 @@
 use rustc_plugin as plugin;
 use rustc_front::hir;
 use rustc_front::lowering::{lower_crate, LoweringContext};
+use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
 use super::Compilation;
 
 use serialize::json;
@@ -632,7 +633,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
     time(time_passes,
          "checking for inline asm in case the target doesn't support it",
-         || ::rustc_passes::no_asm::check_crate(sess, &krate));
+         || no_asm::check_crate(sess, &krate));
 
     // One final feature gating of the true AST that gets compiled
     // later, to make sure we've got everything (e.g. configuration
@@ -649,7 +650,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
     time(time_passes,
          "const fn bodies and arguments",
-         || ::rustc_passes::const_fn::check_crate(sess, &krate));
+         || const_fn::check_crate(sess, &krate));
 
     if sess.opts.debugging_opts.input_stats {
         println!("Post-expansion node count: {}", count_nodes(&krate));
@@ -743,11 +744,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
          "loop checking",
-         || middle::check_loop::check_crate(sess, krate));
+         || loops::check_crate(sess, krate));
 
     time(time_passes,
          "static item recursion checking",
-         || middle::check_static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map));
+         || static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map));
 
     ty::ctxt::create_and_enter(sess,
                                arenas,
@@ -764,7 +765,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    time(time_passes,
                                         "const checking",
-                                        || middle::check_const::check_crate(tcx));
+                                        || consts::check_crate(tcx));
 
                                    let access_levels =
                                        time(time_passes, "privacy checking", || {
@@ -805,7 +806,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    time(time_passes,
                                         "rvalue checking",
-                                        || middle::check_rvalues::check_crate(tcx));
+                                        || rvalues::check_crate(tcx));
 
                                    // Avoid overwhelming user with errors if type checking failed.
                                    // I'm not sure how helpful this is, to be honest, but it avoids
index 81d3367ab00dc97ccccb3b2c2ff564315b51c477..f6342831143256ce0709603d945a7cddc07986cb 100644 (file)
@@ -87,7 +87,8 @@ pub struct LoweringContext<'a> {
     cached_id: Cell<u32>,
     // Keep track of gensym'ed idents.
     gensym_cache: RefCell<HashMap<(NodeId, &'static str), hir::Ident>>,
-    // A copy of cached_id, but is also set to an id while it is being cached.
+    // A copy of cached_id, but is also set to an id while a node is lowered for
+    // the first time.
     gensym_key: Cell<u32>,
 }
 
@@ -114,32 +115,79 @@ pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContex
     }
 
     fn next_id(&self) -> NodeId {
-        let cached = self.cached_id.get();
-        if cached == 0 {
+        let cached_id = self.cached_id.get();
+        if cached_id == 0 {
             return self.id_assigner.next_node_id();
         }
 
-        self.cached_id.set(cached + 1);
-        cached
+        self.cached_id.set(cached_id + 1);
+        cached_id
     }
 
     fn str_to_ident(&self, s: &'static str) -> hir::Ident {
-        let cached_id = self.gensym_key.get();
-        if cached_id == 0 {
+        let gensym_key = self.gensym_key.get();
+        if gensym_key == 0 {
             return hir::Ident::from_name(token::gensym(s));
         }
 
-        let cached = self.gensym_cache.borrow().contains_key(&(cached_id, s));
+        let cached = self.gensym_cache.borrow().contains_key(&(gensym_key, s));
         if cached {
-            self.gensym_cache.borrow()[&(cached_id, s)]
+            self.gensym_cache.borrow()[&(gensym_key, s)]
         } else {
             let result = hir::Ident::from_name(token::gensym(s));
-            self.gensym_cache.borrow_mut().insert((cached_id, s), result);
+            self.gensym_cache.borrow_mut().insert((gensym_key, s), result);
             result
         }
     }
 }
 
+// Utility fn for setting and unsetting the cached id.
+fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
+    where OP: FnOnce(&LoweringContext) -> R
+{
+    // Only reset the id if it was previously 0, i.e., was not cached.
+    // If it was cached, we are in a nested node, but our id count will
+    // still count towards the parent's count.
+    let reset_cached_id = lctx.cached_id.get() == 0;
+    // We always reset gensym_key so that if we use the same name in a nested
+    // node and after that node, they get different values.
+    let old_gensym_key = lctx.gensym_key.get();
+
+    {
+        let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
+
+        if id_cache.contains_key(&expr_id) {
+            let cached_id = lctx.cached_id.get();
+            if cached_id == 0 {
+                // We're entering a node where we need to track ids, but are not
+                // yet tracking.
+                lctx.cached_id.set(id_cache[&expr_id]);
+            } else {
+                // We're already tracking - check that the tracked id is the same
+                // as the expected id.
+                assert!(cached_id == id_cache[&expr_id], "id mismatch");
+            }
+            lctx.gensym_key.set(id_cache[&expr_id]);
+        } else {
+            // We've never lowered this node before, remember it for next time.
+            let next_id = lctx.id_assigner.peek_node_id();
+            id_cache.insert(expr_id, next_id);
+            lctx.gensym_key.set(next_id);
+            // self.cached_id is not set when we lower a node for the first time,
+            // only on re-lowering.
+        }
+    }
+
+    let result = op(lctx);
+
+    if reset_cached_id {
+        lctx.cached_id.set(0);
+    }
+    lctx.gensym_key.set(old_gensym_key);
+
+    result
+}
+
 pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
     hir::Ident {
         name: mtwt::resolve(ident),
@@ -918,47 +966,6 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
     })
 }
 
-// Utility fn for setting and unsetting the cached id.
-fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
-    where OP: FnOnce(&LoweringContext) -> R
-{
-    // Only reset the id if it was previously 0, i.e., was not cached.
-    // If it was cached, we are in a nested node, but our id count will
-    // still count towards the parent's count.
-    let reset_cached_id = lctx.cached_id.get() == 0;
-
-    {
-        let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
-
-        if id_cache.contains_key(&expr_id) {
-            let cached_id = lctx.cached_id.get();
-            if cached_id == 0 {
-                // We're entering a node where we need to track ids, but are not
-                // yet tracking.
-                lctx.cached_id.set(id_cache[&expr_id]);
-                lctx.gensym_key.set(id_cache[&expr_id]);
-            } else {
-                // We're already tracking - check that the tracked id is the same
-                // as the expected id.
-                assert!(cached_id == id_cache[&expr_id], "id mismatch");
-            }
-        } else {
-            let next_id = lctx.id_assigner.peek_node_id();
-            id_cache.insert(expr_id, next_id);
-            lctx.gensym_key.set(next_id);
-        }
-    }
-
-    let result = op(lctx);
-
-    if reset_cached_id {
-        lctx.cached_id.set(0);
-        lctx.gensym_key.set(0);
-    }
-
-    result
-}
-
 pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
     P(hir::Expr {
         id: e.id,
@@ -1935,7 +1942,9 @@ fn test_preserves_ids() {
         let ast_while_let = assigner.fold_expr(ast_while_let);
         let ast_for = quote_expr!(&cx,
                                   for i in 0..10 {
-                                      foo(i);
+                                      for j in 0..10 {
+                                          foo(i, j);
+                                      }
                                   });
         let ast_for = assigner.fold_expr(ast_for);
         let ast_in = quote_expr!(&cx, in HEAP { foo() });
index b5f8be496fb02f451867a5d26e61e2d4ca1f5a39..367475a14a2e6d64e26f60f03bb7758aa3594548 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::def;
+use middle::def::Def;
 use middle::ty;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
@@ -274,7 +274,7 @@ fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         if let &hir::PatIdent(_, ref path1, _) = &p.node {
             let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-            if let Some(def::DefLocal(..)) = def {
+            if let Some(Def::Local(..)) = def {
                 self.check_snake_case(cx, "variable", &path1.node.name.as_str(), Some(p.span));
             }
         }
@@ -362,7 +362,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
-            (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
+            (&hir::PatIdent(_, ref path1, _), Some(Def::Const(..))) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
                                                       path1.node.name, p.span);
             }
index 8985b1e56bc0097a2679137adc5c81b7c74046d4..8621743668b9386b58bf78110e233080724bfde9 100644 (file)
@@ -28,7 +28,8 @@
 //! Use the former for unit-like structs and the latter for structs with
 //! a `pub fn new()`.
 
-use middle::{cfg, def, infer, stability, traits};
+use middle::{cfg, infer, stability, traits};
+use middle::def::Def;
 use middle::cstore::CrateStore;
 use middle::def_id::DefId;
 use middle::subst::Substs;
@@ -163,7 +164,7 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                 }
                 let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
                 if let Some(def_id) = cx.tcx.map.opt_local_def_id(fieldpat.node.pat.id) {
-                    def == Some(def::DefLocal(def_id, fieldpat.node.pat.id))
+                    def == Some(Def::Local(def_id, fieldpat.node.pat.id))
                 } else {
                     false
                 }
@@ -819,7 +820,7 @@ fn expr_refers_to_this_method(tcx: &ty::ctxt,
             match tcx.map.get(id) {
                 hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
                     match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) {
-                        Some(def::DefMethod(def_id)) => {
+                        Some(Def::Method(def_id)) => {
                             let item_substs =
                                 tcx.tables.borrow().item_substs
                                                    .get(&callee.id)
@@ -1060,7 +1061,7 @@ fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
                 hir::ExprPath(..) => (),
                 _ => return None
             }
-            if let def::DefFn(did, _) = cx.tcx.resolve_expr(expr) {
+            if let Def::Fn(did) = cx.tcx.resolve_expr(expr) {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
index 8c3bd3c4f8a5352851b919077ad90224bc70c425..e91c7e6ac450687f7584e92377619d60bf814e34 100644 (file)
@@ -29,8 +29,8 @@
 use middle::cstore::{InlinedItem, InlinedItemRef};
 use middle::ty::adjustment;
 use middle::ty::cast;
-use middle::check_const::ConstQualif;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::privacy::{AllPublic, LastMod};
 use middle::region;
@@ -368,49 +368,48 @@ fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
 // ______________________________________________________________________
 // Encoding and decoding of ast::def
 
-fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> def::Def {
-    let def: def::Def = Decodable::decode(dsr).unwrap();
+fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> Def {
+    let def: Def = Decodable::decode(dsr).unwrap();
     def.tr(dcx)
 }
 
-impl tr for def::Def {
-    fn tr(&self, dcx: &DecodeContext) -> def::Def {
+impl tr for Def {
+    fn tr(&self, dcx: &DecodeContext) -> Def {
         match *self {
-          def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
-          def::DefMethod(did) => def::DefMethod(did.tr(dcx)),
-          def::DefSelfTy(opt_did, impl_ids) => { def::DefSelfTy(opt_did.map(|did| did.tr(dcx)),
+          Def::Fn(did) => Def::Fn(did.tr(dcx)),
+          Def::Method(did) => Def::Method(did.tr(dcx)),
+          Def::SelfTy(opt_did, impl_ids) => { Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
                                                                 impl_ids.map(|(nid1, nid2)| {
                                                                     (dcx.tr_id(nid1),
                                                                      dcx.tr_id(nid2))
                                                                 })) }
-          def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
-          def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
-          def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
-          def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
-          def::DefAssociatedConst(did) => def::DefAssociatedConst(did.tr(dcx)),
-          def::DefLocal(_, nid) => {
+          Def::Mod(did) => { Def::Mod(did.tr(dcx)) }
+          Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) }
+          Def::Static(did, m) => { Def::Static(did.tr(dcx), m) }
+          Def::Const(did) => { Def::Const(did.tr(dcx)) }
+          Def::AssociatedConst(did) => Def::AssociatedConst(did.tr(dcx)),
+          Def::Local(_, nid) => {
               let nid = dcx.tr_id(nid);
               let did = dcx.tcx.map.local_def_id(nid);
-              def::DefLocal(did, nid)
+              Def::Local(did, nid)
           }
-          def::DefVariant(e_did, v_did, is_s) => {
-            def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
-          },
-          def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
-          def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
-          def::DefAssociatedTy(trait_did, did) =>
-              def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
-          def::DefPrimTy(p) => def::DefPrimTy(p),
-          def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
-          def::DefUpvar(_, nid1, index, nid2) => {
+          Def::Variant(e_did, v_did) => Def::Variant(e_did.tr(dcx), v_did.tr(dcx)),
+          Def::Trait(did) => Def::Trait(did.tr(dcx)),
+          Def::Enum(did) => Def::Enum(did.tr(dcx)),
+          Def::TyAlias(did) => Def::TyAlias(did.tr(dcx)),
+          Def::AssociatedTy(trait_did, did) =>
+              Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
+          Def::PrimTy(p) => Def::PrimTy(p),
+          Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n),
+          Def::Upvar(_, nid1, index, nid2) => {
               let nid1 = dcx.tr_id(nid1);
               let nid2 = dcx.tr_id(nid2);
               let did1 = dcx.tcx.map.local_def_id(nid1);
-              def::DefUpvar(did1, nid1, index, nid2)
+              Def::Upvar(did1, nid1, index, nid2)
           }
-          def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
-          def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)),
-          def::DefErr => def::DefErr,
+          Def::Struct(did) => Def::Struct(did.tr(dcx)),
+          Def::Label(nid) => Def::Label(dcx.tr_id(nid)),
+          Def::Err => Def::Err,
         }
     }
 }
index ecbc84023309105f9953e0a7babf1a36c43e79d5..802629e8f3e8b8d49c1dbd11485a9eb6f6fdce83 100644 (file)
@@ -18,7 +18,7 @@
 use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
 use middle::def;
 use middle::lang_items;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, VariantKind};
 use middle::def_id::{DefId, DefIndex};
 
 use rustc::front::map as hir_map;
@@ -377,6 +377,17 @@ fn def_path(&self, def: DefId) -> hir_map::DefPath
         local_path.into_iter().chain(path).collect()
     }
 
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> {
+        let cdata = self.get_crate_data(def_id.krate);
+        decoder::get_variant_kind(&cdata, def_id.index)
+    }
+
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
+    {
+        let cdata = self.get_crate_data(struct_def_id.krate);
+        decoder::get_struct_ctor_def_id(&cdata, struct_def_id.index)
+    }
+
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
     {
         let cdata = self.get_crate_data(did.krate);
index def5897e92d9d8aa8d1161ad84577c95315382c0..bca8cb3995ab1ed341b0c2f82615127f819f65ab 100644 (file)
 
 use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
 use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
-use middle::ty::{self, Ty, TypeFoldable};
+use middle::ty::{self, Ty, TypeFoldable, VariantKind};
 
 use rustc::mir;
 use rustc::mir::visit::MutVisitor;
@@ -89,27 +89,22 @@ pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
     index::DenseIndex::from_buf(index.data, index.start, index.end)
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 enum Family {
     ImmStatic,             // c
     MutStatic,             // b
     Fn,                    // f
-    CtorFn,                // o
     StaticMethod,          // F
     Method,                // h
     Type,                  // y
     Mod,                   // m
     ForeignMod,            // n
     Enum,                  // t
-    StructVariant,         // V
-    TupleVariant,          // v
-    UnitVariant,           // w
+    Variant(VariantKind),  // V, v, w
     Impl,                  // i
     DefaultImpl,           // d
     Trait,                 // I
-    Struct,                // S
-    TupleStruct,           // s
-    UnitStruct,            // u
+    Struct(VariantKind),   // S, s, u
     PublicField,           // g
     InheritedField,        // N
     Constant,              // C
@@ -122,22 +117,21 @@ fn item_family(item: rbml::Doc) -> Family {
       'c' => ImmStatic,
       'b' => MutStatic,
       'f' => Fn,
-      'o' => CtorFn,
       'F' => StaticMethod,
       'h' => Method,
       'y' => Type,
       'm' => Mod,
       'n' => ForeignMod,
       't' => Enum,
-      'V' => StructVariant,
-      'v' => TupleVariant,
-      'w' => UnitVariant,
+      'V' => Variant(VariantKind::Struct),
+      'v' => Variant(VariantKind::Tuple),
+      'w' => Variant(VariantKind::Unit),
       'i' => Impl,
       'd' => DefaultImpl,
       'I' => Trait,
-      'S' => Struct,
-      's' => TupleStruct,
-      'u' => UnitStruct,
+      'S' => Struct(VariantKind::Struct),
+      's' => Struct(VariantKind::Tuple),
+      'u' => Struct(VariantKind::Unit),
       'g' => PublicField,
       'N' => InheritedField,
        c => panic!("unexpected family char: {}", c)
@@ -271,6 +265,18 @@ fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
     }
 }
 
+fn family_to_variant_kind<'tcx>(family: Family) -> Option<ty::VariantKind> {
+    match family {
+        Struct(VariantKind::Struct) | Variant(VariantKind::Struct) =>
+            Some(ty::VariantKind::Struct),
+        Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) =>
+            Some(ty::VariantKind::Tuple),
+        Struct(VariantKind::Unit) | Variant(VariantKind::Unit) =>
+            Some(ty::VariantKind::Unit),
+        _ => None,
+    }
+}
+
 fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
     let fam = item_family(item);
     match fam {
@@ -278,42 +284,37 @@ fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
             // Check whether we have an associated const item.
             match item_sort(item) {
                 Some('C') | Some('c') => {
-                    DlDef(def::DefAssociatedConst(did))
+                    DlDef(Def::AssociatedConst(did))
                 }
                 _ => {
                     // Regular const item.
-                    DlDef(def::DefConst(did))
+                    DlDef(Def::Const(did))
                 }
             }
         }
-        ImmStatic => DlDef(def::DefStatic(did, false)),
-        MutStatic => DlDef(def::DefStatic(did, true)),
-        Struct | TupleStruct | UnitStruct => DlDef(def::DefStruct(did)),
-        Fn        => DlDef(def::DefFn(did, false)),
-        CtorFn    => DlDef(def::DefFn(did, true)),
+        ImmStatic => DlDef(Def::Static(did, false)),
+        MutStatic => DlDef(Def::Static(did, true)),
+        Struct(..) => DlDef(Def::Struct(did)),
+        Fn        => DlDef(Def::Fn(did)),
         Method | StaticMethod => {
-            DlDef(def::DefMethod(did))
+            DlDef(Def::Method(did))
         }
         Type => {
             if item_sort(item) == Some('t') {
                 let trait_did = item_require_parent_item(cdata, item);
-                DlDef(def::DefAssociatedTy(trait_did, did))
+                DlDef(Def::AssociatedTy(trait_did, did))
             } else {
-                DlDef(def::DefTy(did, false))
+                DlDef(Def::TyAlias(did))
             }
         }
-        Mod => DlDef(def::DefMod(did)),
-        ForeignMod => DlDef(def::DefForeignMod(did)),
-        StructVariant => {
+        Mod => DlDef(Def::Mod(did)),
+        ForeignMod => DlDef(Def::ForeignMod(did)),
+        Variant(..) => {
             let enum_did = item_require_parent_item(cdata, item);
-            DlDef(def::DefVariant(enum_did, did, true))
+            DlDef(Def::Variant(enum_did, did))
         }
-        TupleVariant | UnitVariant => {
-            let enum_did = item_require_parent_item(cdata, item);
-            DlDef(def::DefVariant(enum_did, did, false))
-        }
-        Trait => DlDef(def::DefTrait(did)),
-        Enum => DlDef(def::DefTy(did, true)),
+        Trait => DlDef(Def::Trait(did)),
+        Enum => DlDef(Def::Enum(did)),
         Impl | DefaultImpl => DlImpl(did),
         PublicField | InheritedField => DlField,
     }
@@ -371,11 +372,9 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                          item_id: DefIndex,
                          tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
 {
-    fn family_to_variant_kind<'tcx>(family: Family, tcx: &ty::ctxt<'tcx>) -> ty::VariantKind {
-        match family {
-            Struct | StructVariant => ty::VariantKind::Struct,
-            TupleStruct | TupleVariant => ty::VariantKind::Tuple,
-            UnitStruct | UnitVariant => ty::VariantKind::Unit,
+    fn expect_variant_kind<'tcx>(family: Family, tcx: &ty::ctxt<'tcx>) -> ty::VariantKind {
+        match family_to_variant_kind(family) {
+            Some(kind) => kind,
             _ => tcx.sess.bug(&format!("unexpected family: {:?}", family)),
         }
     }
@@ -399,7 +398,7 @@ fn get_enum_variants<'tcx>(intr: &IdentInterner,
                 name: item_name(intr, item),
                 fields: get_variant_fields(intr, cdata, item, tcx),
                 disr_val: disr,
-                kind: family_to_variant_kind(item_family(item), tcx),
+                kind: expect_variant_kind(item_family(item), tcx),
             }
         }).collect()
     }
@@ -433,7 +432,7 @@ fn get_struct_variant<'tcx>(intr: &IdentInterner,
             name: item_name(intr, doc),
             fields: get_variant_fields(intr, cdata, doc, tcx),
             disr_val: 0,
-            kind: family_to_variant_kind(item_family(doc), tcx),
+            kind: expect_variant_kind(item_family(doc), tcx),
         }
     }
 
@@ -444,7 +443,7 @@ fn get_struct_variant<'tcx>(intr: &IdentInterner,
             (ty::AdtKind::Enum,
              get_enum_variants(intr, cdata, doc, tcx))
         }
-        Struct | TupleStruct | UnitStruct => {
+        Struct(..) => {
             let ctor_did =
                 reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
                 map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
@@ -1086,6 +1085,19 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
     }).collect()
 }
 
+pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option<VariantKind>
+{
+    let item = cdata.lookup_item(node_id);
+    family_to_variant_kind(item_family(item))
+}
+
+pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option<DefId>
+{
+    let item = cdata.lookup_item(node_id);
+    reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).
+        map(|ctor_doc| translated_def_id(cdata, ctor_doc))
+}
+
 /// If node_id is the constructor of a tuple struct, retrieve the NodeId of
 /// the actual type definition, otherwise, return None
 pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
index ec70a610e0b3afecc7c03e690228f0b5ebad496d..45cbb22e6c95270f3e736125f42364efa5b69148 100644 (file)
@@ -508,15 +508,20 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                          rbml_w: &mut Encoder,
                                          name: Name,
-                                         ctor_id: NodeId,
+                                         struct_def: &hir::VariantData,
                                          index: &mut CrateIndex<'tcx>,
                                          struct_id: NodeId) {
+    let ctor_id = struct_def.id();
     let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
 
     index.record(ctor_def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
     encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
-    encode_family(rbml_w, 'o');
+    encode_family(rbml_w, match *struct_def {
+        hir::VariantData::Struct(..) => 'S',
+        hir::VariantData::Tuple(..) => 's',
+        hir::VariantData::Unit(..) => 'u',
+    });
     encode_bounds_and_type_for_item(rbml_w, ecx, index, ctor_id);
     encode_name(rbml_w, name);
     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
@@ -1084,7 +1089,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
         // If this is a tuple-like struct, encode the type of the constructor.
         if !struct_def.is_struct() {
-            encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id(), index, item.id);
+            encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def, index, item.id);
         }
       }
       hir::ItemDefaultImpl(unsafety, _) => {
index 40665beaa5ac2698b08c92e6107ad139cef5ff17..b0fb12b26b28f96e778c9367a2d5fe7229198e3a 100644 (file)
@@ -388,11 +388,12 @@ fn find_library_crate(&mut self) -> Option<Library> {
         }
 
         let dypair = self.dylibname();
+        let staticpair = self.staticlibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
         let dylib_prefix = format!("{}{}", dypair.0, self.crate_name);
         let rlib_prefix = format!("lib{}", self.crate_name);
-        let staticlib_prefix = format!("lib{}", self.crate_name);
+        let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name);
 
         let mut candidates = HashMap::new();
         let mut staticlibs = vec!();
@@ -425,7 +426,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
                  false)
             } else {
                 if file.starts_with(&staticlib_prefix[..]) &&
-                   file.ends_with(".a") {
+                   file.ends_with(&staticpair.1) {
                     staticlibs.push(CrateMismatch {
                         path: path.to_path_buf(),
                         got: "static".to_string()
@@ -644,6 +645,13 @@ fn dylibname(&self) -> (String, String) {
         (t.options.dll_prefix.clone(), t.options.dll_suffix.clone())
     }
 
+    // Returns the corresponding (prefix, suffix) that files need to have for
+    // static libraries
+    fn staticlibname(&self) -> (String, String) {
+        let t = &self.target;
+        (t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone())
+    }
+
     fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
         // First, filter out all libraries that look suspicious. We only accept
         // files which actually exist that have the correct naming scheme for
index 63eb760720479a750d90779fa96a21c135332975..4261efe8215a8190f478c42d4779727e6c1592d3 100644 (file)
@@ -146,11 +146,13 @@ pub fn into_expr(&mut self,
                 // start the loop
                 this.cfg.terminate(block, Terminator::Goto { target: loop_block });
 
-                this.in_loop_scope(loop_block, exit_block, |this| {
+                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                     // conduct the test, if necessary
                     let body_block;
-                    let opt_cond_expr = opt_cond_expr; // FIXME rustc bug
                     if let Some(cond_expr) = opt_cond_expr {
+                        // This loop has a condition, ergo its exit_block is reachable.
+                        this.find_loop_scope(expr_span, None).might_break = true;
+
                         let loop_block_end;
                         let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                         body_block = this.cfg.start_new_block();
@@ -163,21 +165,22 @@ pub fn into_expr(&mut self,
                         body_block = loop_block;
                     }
 
-                    // execute the body, branching back to the test
-                    // We write body’s “return value” into the destination of loop. This is fine,
-                    // because:
-                    //
-                    // * In Rust both loop expression and its body are required to have `()`
-                    //   as the “return value”;
-                    // * The destination will be considered uninitialised (given it was
-                    //   uninitialised before the loop) during the first iteration, thus
-                    //   disallowing its use inside the body. Alternatively, if it was already
-                    //   initialised, the `destination` can only possibly have a value of `()`,
-                    //   therefore, “mutating” the destination during iteration is fine.
-                    let body_block_end = unpack!(this.into(destination, body_block, body));
+                    // The “return” value of the loop body must always be an unit, but we cannot
+                    // reuse that as a “return” value of the whole loop expressions, because some
+                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
+                    // the destination for the loop body and assign the loop’s own “return” value
+                    // immediately after the iteration is finished.
+                    let tmp = this.get_unit_temp();
+                    // Execute the body, branching back to the test.
+                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                     this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
-                    exit_block.unit()
-                })
+                });
+                // If the loop may reach its exit_block, we assign an empty tuple to the
+                // destination to keep the MIR well-formed.
+                if might_break {
+                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
+                }
+                exit_block.unit()
             }
             ExprKind::Assign { lhs, rhs } => {
                 // Note: we evaluate assignments right-to-left. This
@@ -217,7 +220,10 @@ pub fn into_expr(&mut self,
                                        |loop_scope| loop_scope.continue_block)
             }
             ExprKind::Break { label } => {
-                this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
+                this.break_or_continue(expr_span, label, block, |loop_scope| {
+                    loop_scope.might_break = true;
+                    loop_scope.break_block
+                })
             }
             ExprKind::Return { value } => {
                 block = match value {
@@ -303,11 +309,13 @@ fn break_or_continue<F>(&mut self,
                             block: BasicBlock,
                             exit_selector: F)
                             -> BlockAnd<()>
-        where F: FnOnce(&LoopScope) -> BasicBlock
+        where F: FnOnce(&mut LoopScope) -> BasicBlock
     {
-        let loop_scope = self.find_loop_scope(span, label);
-        let exit_block = exit_selector(&loop_scope);
-        self.exit_scope(span, loop_scope.extent, block, exit_block);
+        let (exit_block, extent) = {
+            let loop_scope = self.find_loop_scope(span, label);
+            (exit_selector(loop_scope), loop_scope.extent)
+        };
+        self.exit_scope(span, extent, block, exit_block);
         self.cfg.start_new_block().unit()
     }
 }
index d217eb066479364de370bdc536bb7d96c3d091f0..a7459d62368e9cfa6e5f72b694f3deace3b93854 100644 (file)
@@ -26,6 +26,7 @@ pub struct Builder<'a, 'tcx: 'a> {
     var_decls: Vec<VarDecl<'tcx>>,
     var_indices: FnvHashMap<ast::NodeId, u32>,
     temp_decls: Vec<TempDecl<'tcx>>,
+    unit_temp: Option<Lvalue<'tcx>>,
 }
 
 struct CFG<'tcx> {
@@ -96,6 +97,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
         temp_decls: vec![],
         var_decls: vec![],
         var_indices: FnvHashMap(),
+        unit_temp: None
     };
 
     assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
@@ -156,6 +158,18 @@ fn args_and_body(&mut self,
             block.and(arg_decls)
         })
     }
+
+    fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
+        match self.unit_temp {
+            Some(ref tmp) => tmp.clone(),
+            None => {
+                let ty = self.hir.unit_ty();
+                let tmp = self.temp(ty);
+                self.unit_temp = Some(tmp.clone());
+                tmp
+            }
+        }
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
index 90d6a90682f6eb1680cd467d1730a56fa6e0ed47..dae525c84d033f53f4018d4dcb7bca201df50f0c 100644 (file)
@@ -103,31 +103,41 @@ pub struct Scope<'tcx> {
 
 #[derive(Clone, Debug)]
 pub struct LoopScope {
-    pub extent: CodeExtent, // extent of the loop
-    pub continue_block: BasicBlock, // where to go on a `loop`
+    /// Extent of the loop
+    pub extent: CodeExtent,
+    /// Where the body of the loop begins
+    pub continue_block: BasicBlock,
+    /// Block to branch into when the loop terminates (either by being `break`-en out from, or by
+    /// having its condition to become false)
     pub break_block: BasicBlock, // where to go on a `break
+    /// Indicates the reachability of the break_block for this loop
+    pub might_break: bool
 }
 
 impl<'a,'tcx> Builder<'a,'tcx> {
     /// Start a loop scope, which tracks where `continue` and `break`
     /// should branch to. See module comment for more details.
-    pub fn in_loop_scope<F, R>(&mut self,
+    ///
+    /// Returns the might_break attribute of the LoopScope used.
+    pub fn in_loop_scope<F>(&mut self,
                                loop_block: BasicBlock,
                                break_block: BasicBlock,
                                f: F)
-                               -> BlockAnd<R>
-        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
+                               -> bool
+        where F: FnOnce(&mut Builder<'a, 'tcx>)
     {
         let extent = self.extent_of_innermost_scope();
         let loop_scope = LoopScope {
             extent: extent.clone(),
             continue_block: loop_block,
             break_block: break_block,
+            might_break: false
         };
         self.loop_scopes.push(loop_scope);
-        let r = f(self);
-        assert!(self.loop_scopes.pop().unwrap().extent == extent);
-        r
+        f(self);
+        let loop_scope = self.loop_scopes.pop().unwrap();
+        assert!(loop_scope.extent == extent);
+        loop_scope.might_break
     }
 
     /// Convenience wrapper that pushes a scope and then executes `f`
@@ -181,28 +191,21 @@ pub fn pop_scope(&mut self, extent: CodeExtent, block: BasicBlock) {
     pub fn find_loop_scope(&mut self,
                            span: Span,
                            label: Option<CodeExtent>)
-                           -> LoopScope {
-        let loop_scope =
-            match label {
-                None => {
-                    // no label? return the innermost loop scope
-                    self.loop_scopes.iter()
-                                    .rev()
-                                    .next()
-                }
-                Some(label) => {
-                    // otherwise, find the loop-scope with the correct id
-                    self.loop_scopes.iter()
-                                    .rev()
-                                    .filter(|loop_scope| loop_scope.extent == label)
-                                    .next()
-                }
-            };
-
-        match loop_scope {
-            Some(loop_scope) => loop_scope.clone(),
-            None => self.hir.span_bug(span, "no enclosing loop scope found?"),
-        }
+                           -> &mut LoopScope {
+        let Builder { ref mut loop_scopes, ref mut hir, .. } = *self;
+        match label {
+            None => {
+                // no label? return the innermost loop scope
+                loop_scopes.iter_mut().rev().next()
+            }
+            Some(label) => {
+                // otherwise, find the loop-scope with the correct id
+                loop_scopes.iter_mut()
+                           .rev()
+                           .filter(|loop_scope| loop_scope.extent == label)
+                           .next()
+            }
+        }.unwrap_or_else(|| hir.span_bug(span, "no enclosing loop scope found?"))
     }
 
     /// Branch out of `block` to `target`, exiting all scopes up to
@@ -214,20 +217,19 @@ pub fn exit_scope(&mut self,
                       extent: CodeExtent,
                       block: BasicBlock,
                       target: BasicBlock) {
-        let popped_scopes =
-            match self.scopes.iter().rev().position(|scope| scope.extent == extent) {
-                Some(p) => p + 1,
-                None => self.hir.span_bug(span, &format!("extent {:?} does not enclose",
-                                                              extent)),
-            };
-
-        for scope in self.scopes.iter_mut().rev().take(popped_scopes) {
+        let Builder { ref mut scopes, ref mut cfg, ref mut hir, .. } = *self;
+
+        let scope_count = 1 + scopes.iter().rev().position(|scope| scope.extent == extent)
+                                                 .unwrap_or_else(||{
+            hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
+        });
+
+        for scope in scopes.iter_mut().rev().take(scope_count) {
             for &(kind, drop_span, ref lvalue) in &scope.drops {
-                self.cfg.push_drop(block, drop_span, kind, lvalue);
+                cfg.push_drop(block, drop_span, kind, lvalue);
             }
         }
-
-        self.cfg.terminate(block, Terminator::Goto { target: target });
+        cfg.terminate(block, Terminator::Goto { target: target });
     }
 
     /// Creates a path that performs all required cleanup for unwinding.
index 8090fca66bb6247904341cb8f1de0cd3bb5e33a4..57a43c3a180f2192f67a486ae35fc345e4294c3a 100644 (file)
@@ -14,7 +14,7 @@
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
 use rustc::front::map;
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::region::CodeExtent;
 use rustc::middle::pat_util;
 use rustc::middle::ty::{self, VariantDef, Ty};
@@ -67,10 +67,10 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                         // Tuple-like ADTs are represented as ExprCall. We convert them here.
                         expr_ty.ty_adt_def().and_then(|adt_def|{
                             match cx.tcx.def_map.borrow()[&fun.id].full_def() {
-                                def::DefVariant(_, variant_id, false) => {
+                                Def::Variant(_, variant_id) => {
                                     Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                                 },
-                                def::DefStruct(_) => {
+                                Def::Struct(..) => {
                                     Some((adt_def, 0))
                                 },
                                 _ => None
@@ -231,7 +231,7 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                     }
                     ty::TyEnum(adt, substs) => {
                         match cx.tcx.def_map.borrow()[&self.id].full_def() {
-                            def::DefVariant(enum_id, variant_id, _) => {
+                            Def::Variant(enum_id, variant_id) => {
                                 debug_assert!(adt.did == enum_id);
                                 let index = adt.variant_index_with_id(variant_id);
                                 let field_refs = field_refs(&adt.variants[index], fields);
@@ -573,9 +573,9 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
     let (def_id, kind) = match def {
         // A regular function.
-        def::DefFn(def_id, _) => (def_id, ItemKind::Function),
-        def::DefMethod(def_id) => (def_id, ItemKind::Method),
-        def::DefStruct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
+        Def::Fn(def_id) => (def_id, ItemKind::Function),
+        Def::Method(def_id) => (def_id, ItemKind::Method),
+        Def::Struct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A tuple-struct constructor. Should only be reached if not called in the same
             // expression.
             ty::TyBareFn(..) => (def_id, ItemKind::Function),
@@ -590,7 +590,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             },
             ref sty => panic!("unexpected sty: {:?}", sty)
         },
-        def::DefVariant(enum_id, variant_id, false) => match cx.tcx.node_id_to_type(expr.id).sty {
+        Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A variant constructor. Should only be reached if not called in the same
             // expression.
             ty::TyBareFn(..) => (variant_id, ItemKind::Function),
@@ -608,8 +608,8 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             },
             ref sty => panic!("unexpected sty: {:?}", sty)
         },
-        def::DefConst(def_id) |
-        def::DefAssociatedConst(def_id) => {
+        Def::Const(def_id) |
+        Def::AssociatedConst(def_id) => {
             if let Some(v) = cx.try_const_eval_literal(expr) {
                 return ExprKind::Literal { literal: v };
             } else {
@@ -617,12 +617,12 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             }
         }
 
-        def::DefStatic(node_id, _) => return ExprKind::StaticRef {
+        Def::Static(node_id, _) => return ExprKind::StaticRef {
             id: node_id,
         },
 
-        def @ def::DefLocal(..) |
-        def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
+        def @ Def::Local(..) |
+        def @ Def::Upvar(..) => return convert_var(cx, expr, def),
 
         def =>
             cx.tcx.sess.span_bug(
@@ -636,18 +636,18 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
 
 fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                              expr: &'tcx hir::Expr,
-                             def: def::Def)
+                             def: Def)
                              -> ExprKind<'tcx> {
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
 
     match def {
-        def::DefLocal(_, node_id) => {
+        Def::Local(_, node_id) => {
             ExprKind::VarRef {
                 id: node_id,
             }
         }
 
-        def::DefUpvar(_, id_var, index, closure_expr_id) => {
+        Def::Upvar(_, id_var, index, closure_expr_id) => {
             debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id);
             let var_ty = cx.tcx.node_id_to_type(id_var);
 
@@ -922,7 +922,7 @@ fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
 
 fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> CodeExtent {
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
-        Some(def::DefLabel(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
+        Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
             cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
         }
index b49dc6d89624265d68b6f82c396acbc75065efbc..7019b40bb252117b73efa8e8ce4c5168b42474dd 100644 (file)
@@ -58,6 +58,10 @@ pub fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
+    pub fn unit_ty(&mut self) -> Ty<'tcx> {
+        self.tcx.mk_nil()
+    }
+
     pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> {
         Literal::Value { value: ConstVal::Str(value) }
     }
index dc377ac731a6581ddf9346c4c7e1cebfb37d61ed..e1a533ce42cca8f7308b49dcf7051c79113f1fb9 100644 (file)
@@ -12,7 +12,7 @@
 use hair::cx::Cx;
 use rustc_data_structures::fnv::FnvHashMap;
 use rustc::middle::const_eval;
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
 use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr::*;
@@ -84,7 +84,7 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
             {
                 let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
                 match def {
-                    def::DefConst(def_id) | def::DefAssociatedConst(def_id) =>
+                    Def::Const(def_id) | Def::AssociatedConst(def_id) =>
                         match const_eval::lookup_const_by_id(self.cx.tcx, def_id,
                                                              Some(pat.id), None) {
                             Some(const_expr) => {
@@ -290,7 +290,7 @@ fn variant_or_leaf(&mut self,
                        -> PatternKind<'tcx> {
         let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
         match def {
-            def::DefVariant(enum_id, variant_id, _) => {
+            Def::Variant(enum_id, variant_id) => {
                 let adt_def = self.cx.tcx.lookup_adt_def(enum_id);
                 if adt_def.variants.len() > 1 {
                     PatternKind::Variant {
@@ -303,9 +303,7 @@ fn variant_or_leaf(&mut self,
                 }
             }
 
-            // NB: resolving to DefStruct means the struct *constructor*,
-            // not the struct as a type.
-            def::DefStruct(..) | def::DefTy(..) => {
+            Def::Struct(..) | Def::TyAlias(..) => {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
new file mode 100644 (file)
index 0000000..60cc658
--- /dev/null
@@ -0,0 +1,916 @@
+// Copyright 2012-2014 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.
+
+// Verifies that the types and values of const and static items
+// are safe. The rules enforced by this module are:
+//
+// - For each *mutable* static item, it checks that its **type**:
+//     - doesn't have a destructor
+//     - doesn't own a box
+//
+// - For each *immutable* static item, it checks that its **value**:
+//       - doesn't own a box
+//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
+//           - the type of the struct/enum has a dtor
+//
+// Rules Enforced Elsewhere:
+// - It's not possible to take the address of a static item with unsafe interior. This is enforced
+// by borrowck::gather_loans
+
+use rustc::dep_graph::DepNode;
+use rustc::middle::ty::cast::{CastKind};
+use rustc::middle::const_eval::{self, ConstEvalErr};
+use rustc::middle::const_eval::ErrKind::IndexOpFeatureGated;
+use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
+use rustc::middle::def::Def;
+use rustc::middle::def_id::DefId;
+use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
+use rustc::middle::mem_categorization as mc;
+use rustc::middle::mem_categorization::Categorization;
+use rustc::middle::traits;
+use rustc::middle::ty::{self, Ty};
+use rustc::util::nodemap::NodeMap;
+use rustc::middle::const_qualif::ConstQualif;
+use rustc::lint::builtin::CONST_ERR;
+
+use rustc_front::hir;
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::feature_gate::UnstableFeatures;
+use rustc_front::intravisit::{self, FnKind, Visitor};
+
+use std::collections::hash_map::Entry;
+use std::cmp::Ordering;
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+enum Mode {
+    Const,
+    ConstFn,
+    Static,
+    StaticMut,
+
+    // An expression that occurs outside of any constant context
+    // (i.e. `const`, `static`, array lengths, etc.). The value
+    // can be variable at runtime, but will be promotable to
+    // static memory if we can prove it is actually constant.
+    Var,
+}
+
+struct CheckCrateVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    mode: Mode,
+    qualif: ConstQualif,
+    rvalue_borrows: NodeMap<hir::Mutability>
+}
+
+impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
+    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
+        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R,
+    {
+        let (old_mode, old_qualif) = (self.mode, self.qualif);
+        self.mode = mode;
+        self.qualif = ConstQualif::empty();
+        let r = f(self);
+        self.mode = old_mode;
+        self.qualif = old_qualif;
+        r
+    }
+
+    fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
+        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
+    {
+        let param_env = match item_id {
+            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
+            None => self.tcx.empty_parameter_environment()
+        };
+
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
+
+        f(&mut euv::ExprUseVisitor::new(self, &infcx))
+    }
+
+    fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
+        assert!(mode != Mode::Var);
+        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
+            Entry::Occupied(entry) => return *entry.get(),
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(ConstQualif::empty());
+            }
+        }
+        self.with_mode(mode, |this| {
+            this.with_euv(None, |euv| euv.consume_expr(expr));
+            this.visit_expr(expr);
+            this.qualif
+        })
+    }
+
+    fn fn_like(&mut self,
+               fk: FnKind,
+               fd: &hir::FnDecl,
+               b: &hir::Block,
+               s: Span,
+               fn_id: ast::NodeId)
+               -> ConstQualif {
+        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
+            Entry::Occupied(entry) => return *entry.get(),
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(ConstQualif::empty());
+            }
+        }
+
+        let mode = match fk {
+            FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
+                Mode::ConstFn
+            }
+            FnKind::Method(_, m, _) => {
+                if m.constness == hir::Constness::Const {
+                    Mode::ConstFn
+                } else {
+                    Mode::Var
+                }
+            }
+            _ => Mode::Var
+        };
+
+        let qualif = self.with_mode(mode, |this| {
+            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
+            intravisit::walk_fn(this, fk, fd, b, s);
+            this.qualif
+        });
+
+        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
+        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
+        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
+
+        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
+        qualif
+    }
+
+    fn add_qualif(&mut self, qualif: ConstQualif) {
+        self.qualif = self.qualif | qualif;
+    }
+
+    /// Returns true if the call is to a const fn or method.
+    fn handle_const_fn_call(&mut self,
+                            expr: &hir::Expr,
+                            def_id: DefId,
+                            ret_ty: Ty<'tcx>)
+                            -> bool {
+        if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
+            if
+                // we are in a static/const initializer
+                self.mode != Mode::Var &&
+
+                // feature-gate is not enabled
+                !self.tcx.sess.features.borrow().const_fn &&
+
+                // this doesn't come from a macro that has #[allow_internal_unstable]
+                !self.tcx.sess.codemap().span_allows_unstable(expr.span)
+            {
+                let mut err = self.tcx.sess.struct_span_err(
+                    expr.span,
+                    "const fns are an unstable feature");
+                fileline_help!(
+                    &mut err,
+                    expr.span,
+                    "in Nightly builds, add `#![feature(const_fn)]` to the crate \
+                     attributes to enable");
+                err.emit();
+            }
+
+            let qualif = self.fn_like(fn_like.kind(),
+                                      fn_like.decl(),
+                                      fn_like.body(),
+                                      fn_like.span(),
+                                      fn_like.id());
+            self.add_qualif(qualif);
+
+            if ret_ty.type_contents(self.tcx).interior_unsafe() {
+                self.add_qualif(ConstQualif::MUTABLE_MEM);
+            }
+
+            true
+        } else {
+            false
+        }
+    }
+
+    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
+        match self.rvalue_borrows.entry(id) {
+            Entry::Occupied(mut entry) => {
+                // Merge the two borrows, taking the most demanding
+                // one, mutability-wise.
+                if mutbl == hir::MutMutable {
+                    entry.insert(mutbl);
+                }
+            }
+            Entry::Vacant(entry) => {
+                entry.insert(mutbl);
+            }
+        }
+    }
+
+    fn msg(&self) -> &'static str {
+        match self.mode {
+            Mode::Const => "constant",
+            Mode::ConstFn => "constant function",
+            Mode::StaticMut | Mode::Static => "static",
+            Mode::Var => unreachable!(),
+        }
+    }
+
+    fn check_static_mut_type(&self, e: &hir::Expr) {
+        let node_ty = self.tcx.node_id_to_type(e.id);
+        let tcontents = node_ty.type_contents(self.tcx);
+
+        let suffix = if tcontents.has_dtor() {
+            "destructors"
+        } else if tcontents.owns_owned() {
+            "boxes"
+        } else {
+            return
+        };
+
+        span_err!(self.tcx.sess, e.span, E0397,
+                 "mutable statics are not allowed to have {}", suffix);
+    }
+
+    fn check_static_type(&self, e: &hir::Expr) {
+        let ty = self.tcx.node_id_to_type(e.id);
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+        let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
+        match fulfill_cx.select_all_or_error(&infcx) {
+            Ok(()) => { },
+            Err(ref errors) => {
+                traits::report_fulfillment_errors(&infcx, errors);
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, i: &hir::Item) {
+        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
+        assert_eq!(self.mode, Mode::Var);
+        match i.node {
+            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
+                self.check_static_type(&**expr);
+                self.global_expr(Mode::Static, &**expr);
+            }
+            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
+                self.check_static_mut_type(&**expr);
+                self.global_expr(Mode::StaticMut, &**expr);
+            }
+            hir::ItemConst(_, ref expr) => {
+                self.global_expr(Mode::Const, &**expr);
+            }
+            hir::ItemEnum(ref enum_definition, _) => {
+                for var in &enum_definition.variants {
+                    if let Some(ref ex) = var.node.disr_expr {
+                        self.global_expr(Mode::Const, &**ex);
+                    }
+                }
+            }
+            _ => {
+                intravisit::walk_item(self, i);
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
+        match t.node {
+            hir::ConstTraitItem(_, ref default) => {
+                if let Some(ref expr) = *default {
+                    self.global_expr(Mode::Const, &*expr);
+                } else {
+                    intravisit::walk_trait_item(self, t);
+                }
+            }
+            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
+        }
+    }
+
+    fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
+        match i.node {
+            hir::ImplItemKind::Const(_, ref expr) => {
+                self.global_expr(Mode::Const, &*expr);
+            }
+            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
+        }
+    }
+
+    fn visit_fn(&mut self,
+                fk: FnKind<'v>,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
+                s: Span,
+                fn_id: ast::NodeId) {
+        self.fn_like(fk, fd, b, s, fn_id);
+    }
+
+    fn visit_pat(&mut self, p: &hir::Pat) {
+        match p.node {
+            hir::PatLit(ref lit) => {
+                self.global_expr(Mode::Const, &**lit);
+            }
+            hir::PatRange(ref start, ref end) => {
+                self.global_expr(Mode::Const, &**start);
+                self.global_expr(Mode::Const, &**end);
+
+                match const_eval::compare_lit_exprs(self.tcx, start, end) {
+                    Some(Ordering::Less) |
+                    Some(Ordering::Equal) => {}
+                    Some(Ordering::Greater) => {
+                        span_err!(self.tcx.sess, start.span, E0030,
+                            "lower range bound must be less than or equal to upper");
+                    }
+                    None => {
+                        self.tcx.sess.delay_span_bug(start.span,
+                                                     "non-constant path in constant expr");
+                    }
+                }
+            }
+            _ => intravisit::walk_pat(self, p)
+        }
+    }
+
+    fn visit_block(&mut self, block: &hir::Block) {
+        // Check all statements in the block
+        for stmt in &block.stmts {
+            match stmt.node {
+                hir::StmtDecl(ref decl, _) => {
+                    match decl.node {
+                        hir::DeclLocal(_) => {},
+                        // Item statements are allowed
+                        hir::DeclItem(_) => continue
+                    }
+                }
+                hir::StmtExpr(_, _) => {},
+                hir::StmtSemi(_, _) => {},
+            }
+            self.add_qualif(ConstQualif::NOT_CONST);
+            // anything else should have been caught by check_const_fn
+            assert_eq!(self.mode, Mode::Var);
+        }
+        intravisit::walk_block(self, block);
+    }
+
+    fn visit_expr(&mut self, ex: &hir::Expr) {
+        let mut outer = self.qualif;
+        self.qualif = ConstQualif::empty();
+
+        let node_ty = self.tcx.node_id_to_type(ex.id);
+        check_expr(self, ex, node_ty);
+        check_adjustments(self, ex);
+
+        // Special-case some expressions to avoid certain flags bubbling up.
+        match ex.node {
+            hir::ExprCall(ref callee, ref args) => {
+                for arg in args {
+                    self.visit_expr(&**arg)
+                }
+
+                let inner = self.qualif;
+                self.visit_expr(&**callee);
+                // The callee's size doesn't count in the call.
+                let added = self.qualif - inner;
+                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
+            }
+            hir::ExprRepeat(ref element, _) => {
+                self.visit_expr(&**element);
+                // The count is checked elsewhere (typeck).
+                let count = match node_ty.sty {
+                    ty::TyArray(_, n) => n,
+                    _ => unreachable!()
+                };
+                // [element; 0] is always zero-sized.
+                if count == 0 {
+                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
+                }
+            }
+            hir::ExprMatch(ref discr, ref arms, _) => {
+                // Compute the most demanding borrow from all the arms'
+                // patterns and set that on the discriminator.
+                let mut borrow = None;
+                for pat in arms.iter().flat_map(|arm| &arm.pats) {
+                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
+                    match (borrow, pat_borrow) {
+                        (None, _) | (_, Some(hir::MutMutable)) => {
+                            borrow = pat_borrow;
+                        }
+                        _ => {}
+                    }
+                }
+                if let Some(mutbl) = borrow {
+                    self.record_borrow(discr.id, mutbl);
+                }
+                intravisit::walk_expr(self, ex);
+            }
+            // Division by zero and overflow checking.
+            hir::ExprBinary(op, _, _) => {
+                intravisit::walk_expr(self, ex);
+                let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
+                match node_ty.sty {
+                    ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
+                        if !self.qualif.intersects(ConstQualif::NOT_CONST) {
+                            match const_eval::eval_const_expr_partial(
+                                    self.tcx, ex, ExprTypeChecked, None) {
+                                Ok(_) => {}
+                                Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
+                                Err(msg) => {
+                                    self.tcx.sess.add_lint(CONST_ERR, ex.id,
+                                                           msg.span,
+                                                           msg.description().into_owned())
+                                }
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => intravisit::walk_expr(self, ex)
+        }
+
+        // Handle borrows on (or inside the autorefs of) this expression.
+        match self.rvalue_borrows.remove(&ex.id) {
+            Some(hir::MutImmutable) => {
+                // Constants cannot be borrowed if they contain interior mutability as
+                // it means that our "silent insertion of statics" could change
+                // initializer values (very bad).
+                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
+                // propagated from another error, so erroring again would be just noise.
+                let tc = node_ty.type_contents(self.tcx);
+                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
+                    outer = outer | ConstQualif::NOT_CONST;
+                    if self.mode != Mode::Var {
+                        span_err!(self.tcx.sess, ex.span, E0492,
+                                  "cannot borrow a constant which contains \
+                                   interior mutability, create a static instead");
+                    }
+                }
+                // If the reference has to be 'static, avoid in-place initialization
+                // as that will end up pointing to the stack instead.
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
+                }
+            }
+            Some(hir::MutMutable) => {
+                // `&mut expr` means expr could be mutated, unless it's zero-sized.
+                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
+                    if self.mode == Mode::Var {
+                        outer = outer | ConstQualif::NOT_CONST;
+                        self.add_qualif(ConstQualif::MUTABLE_MEM);
+                    } else {
+                        span_err!(self.tcx.sess, ex.span, E0017,
+                            "references in {}s may only refer \
+                             to immutable values", self.msg())
+                    }
+                }
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
+                }
+            }
+            None => {}
+        }
+        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
+        // Don't propagate certain flags.
+        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
+    }
+}
+
+/// This function is used to enforce the constraints on
+/// const/static items. It walks through the *value*
+/// of the item walking down the expression and evaluating
+/// every nested expression. If the expression is not part
+/// of a const/static item, it is qualified for promotion
+/// instead of producing errors.
+fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
+                        e: &hir::Expr, node_ty: Ty<'tcx>) {
+    match node_ty.sty {
+        ty::TyStruct(def, _) |
+        ty::TyEnum(def, _) if def.has_dtor() => {
+            v.add_qualif(ConstQualif::NEEDS_DROP);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0493,
+                          "{}s are not allowed to have destructors",
+                          v.msg());
+            }
+        }
+        _ => {}
+    }
+
+    let method_call = ty::MethodCall::expr(e.id);
+    match e.node {
+        hir::ExprUnary(..) |
+        hir::ExprBinary(..) |
+        hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0011,
+                            "user-defined operators are not allowed in {}s", v.msg());
+            }
+        }
+        hir::ExprBox(_) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0010,
+                          "allocations are not allowed in {}s", v.msg());
+            }
+        }
+        hir::ExprUnary(op, ref inner) => {
+            match v.tcx.node_id_to_type(inner.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op == hir::UnDeref);
+
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0396,
+                                  "raw pointers cannot be dereferenced in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprBinary(op, ref lhs, _) => {
+            match v.tcx.node_id_to_type(lhs.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
+                            op.node == hir::BiLe || op.node == hir::BiLt ||
+                            op.node == hir::BiGe || op.node == hir::BiGt);
+
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0395,
+                                  "raw pointers cannot be compared in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprCast(ref from, _) => {
+            debug!("Checking const cast(id={})", from.id);
+            match v.tcx.cast_kinds.borrow().get(&from.id) {
+                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
+                Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0018,
+                                  "raw pointers cannot be cast to integers in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprPath(..) => {
+            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
+            match def {
+                Some(Def::Variant(..)) => {
+                    // Count the discriminator or function pointer.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                }
+                Some(Def::Struct(..)) => {
+                    if let ty::TyBareFn(..) = node_ty.sty {
+                        // Count the function pointer.
+                        v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                    }
+                }
+                Some(Def::Fn(..)) | Some(Def::Method(..)) => {
+                    // Count the function pointer.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                }
+                Some(Def::Static(..)) => {
+                    match v.mode {
+                        Mode::Static | Mode::StaticMut => {}
+                        Mode::Const | Mode::ConstFn => {
+                            span_err!(v.tcx.sess, e.span, E0013,
+                                "{}s cannot refer to other statics, insert \
+                                 an intermediate constant instead", v.msg());
+                        }
+                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
+                    }
+                }
+                Some(Def::Const(did)) |
+                Some(Def::AssociatedConst(did)) => {
+                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
+                                                                       Some(e.id),
+                                                                       None) {
+                        let inner = v.global_expr(Mode::Const, expr);
+                        v.add_qualif(inner);
+                    }
+                }
+                Some(Def::Local(..)) if v.mode == Mode::ConstFn => {
+                    // Sadly, we can't determine whether the types are zero-sized.
+                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
+                }
+                def => {
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        debug!("(checking const) found bad def: {:?}", def);
+                        span_err!(v.tcx.sess, e.span, E0014,
+                                  "paths in {}s may only refer to constants \
+                                   or functions", v.msg());
+                    }
+                }
+            }
+        }
+        hir::ExprCall(ref callee, _) => {
+            let mut callee = &**callee;
+            loop {
+                callee = match callee.node {
+                    hir::ExprBlock(ref block) => match block.expr {
+                        Some(ref tail) => &**tail,
+                        None => break
+                    },
+                    _ => break
+                };
+            }
+            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
+            let is_const = match def {
+                Some(Def::Struct(..)) => true,
+                Some(Def::Variant(..)) => {
+                    // Count the discriminator.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                    true
+                }
+                Some(Def::Fn(did)) => {
+                    v.handle_const_fn_call(e, did, node_ty)
+                }
+                Some(Def::Method(did)) => {
+                    match v.tcx.impl_or_trait_item(did).container() {
+                        ty::ImplContainer(_) => {
+                            v.handle_const_fn_call(e, did, node_ty)
+                        }
+                        ty::TraitContainer(_) => false
+                    }
+                }
+                _ => false
+            };
+            if !is_const {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    // FIXME(#24111) Remove this check when const fn stabilizes
+                    let (msg, note) =
+                        if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
+                        (format!("function calls in {}s are limited to \
+                                  struct and enum constructors",
+                                 v.msg()),
+                         Some("a limited form of compile-time function \
+                               evaluation is available on a nightly \
+                               compiler via `const fn`"))
+                    } else {
+                        (format!("function calls in {}s are limited \
+                                  to constant functions, \
+                                  struct and enum constructors",
+                                 v.msg()),
+                         None)
+                    };
+                    let mut err = struct_span_err!(v.tcx.sess, e.span, E0015, "{}", msg);
+                    if let Some(note) = note {
+                        err.span_note(e.span, note);
+                    }
+                    err.emit();
+                }
+            }
+        }
+        hir::ExprMethodCall(..) => {
+            let method = v.tcx.tables.borrow().method_map[&method_call];
+            let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
+                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
+                ty::TraitContainer(_) => false
+            };
+            if !is_const {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    span_err!(v.tcx.sess, e.span, E0378,
+                              "method calls in {}s are limited to \
+                               constant inherent methods", v.msg());
+                }
+            }
+        }
+        hir::ExprStruct(..) => {
+            let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
+            if did == v.tcx.lang_items.unsafe_cell_type() {
+                v.add_qualif(ConstQualif::MUTABLE_MEM);
+            }
+        }
+
+        hir::ExprLit(_) |
+        hir::ExprAddrOf(..) => {
+            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+        }
+
+        hir::ExprRepeat(..) => {
+            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
+        }
+
+        hir::ExprClosure(..) => {
+            // Paths in constant contexts cannot refer to local variables,
+            // as there are none, and thus closures can't have upvars there.
+            if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
+                assert!(v.mode == Mode::Var,
+                        "global closures can't capture anything");
+                v.add_qualif(ConstQualif::NOT_CONST);
+            }
+        }
+
+        hir::ExprBlock(_) |
+        hir::ExprIndex(..) |
+        hir::ExprField(..) |
+        hir::ExprTupField(..) |
+        hir::ExprVec(_) |
+        hir::ExprType(..) |
+        hir::ExprTup(..) => {}
+
+        // Conditional control flow (possible to implement).
+        hir::ExprMatch(..) |
+        hir::ExprIf(..) |
+
+        // Loops (not very meaningful in constants).
+        hir::ExprWhile(..) |
+        hir::ExprLoop(..) |
+
+        // More control flow (also not very meaningful).
+        hir::ExprBreak(_) |
+        hir::ExprAgain(_) |
+        hir::ExprRet(_) |
+
+        // Miscellaneous expressions that could be implemented.
+        hir::ExprRange(..) |
+
+        // Expressions with side-effects.
+        hir::ExprAssign(..) |
+        hir::ExprAssignOp(..) |
+        hir::ExprInlineAsm(_) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0019,
+                          "{} contains unimplemented expression type", v.msg());
+            }
+        }
+    }
+}
+
+/// Check the adjustments of an expression
+fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
+    match v.tcx.tables.borrow().adjustments.get(&e.id) {
+        None |
+        Some(&ty::adjustment::AdjustReifyFnPointer) |
+        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
+
+        Some(&ty::adjustment::AdjustDerefRef(
+            ty::adjustment::AutoDerefRef { autoderefs, .. }
+        )) => {
+            if (0..autoderefs as u32).any(|autoderef| {
+                    v.tcx.is_overloaded_autoderef(e.id, autoderef)
+            }) {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    span_err!(v.tcx.sess, e.span, E0400,
+                              "user-defined dereference operators are not allowed in {}s",
+                              v.msg());
+                }
+            }
+        }
+    }
+}
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
+        tcx: tcx,
+        mode: Mode::Var,
+        qualif: ConstQualif::NOT_CONST,
+        rvalue_borrows: NodeMap()
+    });
+    tcx.sess.abort_if_errors();
+}
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
+    fn consume(&mut self,
+               _consume_id: ast::NodeId,
+               consume_span: Span,
+               cmt: mc::cmt,
+               _mode: euv::ConsumeMode) {
+        let mut cur = &cmt;
+        loop {
+            match cur.cat {
+                Categorization::StaticItem => {
+                    if self.mode != Mode::Var {
+                        // statics cannot be consumed by value at any time, that would imply
+                        // that they're an initializer (what a const is for) or kept in sync
+                        // over time (not feasible), so deny it outright.
+                        span_err!(self.tcx.sess, consume_span, E0394,
+                                  "cannot refer to other statics by value, use the \
+                                   address-of operator or a constant instead");
+                    }
+                    break;
+                }
+                Categorization::Deref(ref cmt, _, _) |
+                Categorization::Downcast(ref cmt, _) |
+                Categorization::Interior(ref cmt, _) => cur = cmt,
+
+                Categorization::Rvalue(..) |
+                Categorization::Upvar(..) |
+                Categorization::Local(..) => break
+            }
+        }
+    }
+    fn borrow(&mut self,
+              borrow_id: ast::NodeId,
+              borrow_span: Span,
+              cmt: mc::cmt<'tcx>,
+              _loan_region: ty::Region,
+              bk: ty::BorrowKind,
+              loan_cause: euv::LoanCause)
+    {
+        // Kind of hacky, but we allow Unsafe coercions in constants.
+        // These occur when we convert a &T or *T to a *U, as well as
+        // when making a thin pointer (e.g., `*T`) into a fat pointer
+        // (e.g., `*Trait`).
+        match loan_cause {
+            euv::LoanCause::AutoUnsafe => {
+                return;
+            }
+            _ => { }
+        }
+
+        let mut cur = &cmt;
+        let mut is_interior = false;
+        loop {
+            match cur.cat {
+                Categorization::Rvalue(..) => {
+                    if loan_cause == euv::MatchDiscriminant {
+                        // Ignore the dummy immutable borrow created by EUV.
+                        break;
+                    }
+                    let mutbl = bk.to_mutbl_lossy();
+                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
+                        // Mutable slices are the only `&mut` allowed in
+                        // globals, but only in `static mut`, nowhere else.
+                        // FIXME: This exception is really weird... there isn't
+                        // any fundamental reason to restrict this based on
+                        // type of the expression.  `&mut [1]` has exactly the
+                        // same representation as &mut 1.
+                        match cmt.ty.sty {
+                            ty::TyArray(_, _) | ty::TySlice(_) => break,
+                            _ => {}
+                        }
+                    }
+                    self.record_borrow(borrow_id, mutbl);
+                    break;
+                }
+                Categorization::StaticItem => {
+                    if is_interior && self.mode != Mode::Var {
+                        // Borrowed statics can specifically *only* have their address taken,
+                        // not any number of other borrows such as borrowing fields, reading
+                        // elements of an array, etc.
+                        span_err!(self.tcx.sess, borrow_span, E0494,
+                                  "cannot refer to the interior of another \
+                                   static, use a constant instead");
+                    }
+                    break;
+                }
+                Categorization::Deref(ref cmt, _, _) |
+                Categorization::Downcast(ref cmt, _) |
+                Categorization::Interior(ref cmt, _) => {
+                    is_interior = true;
+                    cur = cmt;
+                }
+
+                Categorization::Upvar(..) |
+                Categorization::Local(..) => break
+            }
+        }
+    }
+
+    fn decl_without_init(&mut self,
+                         _id: ast::NodeId,
+                         _span: Span) {}
+    fn mutate(&mut self,
+              _assignment_id: ast::NodeId,
+              _assignment_span: Span,
+              _assignee_cmt: mc::cmt,
+              _mode: euv::MutateMode) {}
+
+    fn matched_pat(&mut self,
+                   _: &hir::Pat,
+                   _: mc::cmt,
+                   _: euv::MatchMode) {}
+
+    fn consume_pat(&mut self,
+                   _consume_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::ConsumeMode) {}
+}
index 380eada18a1e1c0c4d1d23bf20148b6ea03e3317..2c08cbd32338d47ae56713415d882a090e60055c 100644 (file)
 #![allow(non_snake_case)]
 
 register_long_diagnostics! {
+
+E0010: r##"
+The value of statics and constants must be known at compile time, and they live
+for the entire lifetime of a program. Creating a boxed value allocates memory on
+the heap at runtime, and therefore cannot be done at compile time. Erroneous
+code example:
+
+```
+#![feature(box_syntax)]
+
+const CON : Box<i32> = box 0;
+```
+"##,
+
+E0011: r##"
+Initializers for constants and statics are evaluated at compile time.
+User-defined operators rely on user-defined functions, which cannot be evaluated
+at compile time.
+
+Bad example:
+
+```
+use std::ops::Index;
+
+struct Foo { a: u8 }
+
+impl Index<u8> for Foo {
+    type Output = u8;
+
+    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
+}
+
+const a: Foo = Foo { a: 0u8 };
+const b: u8 = a[0]; // Index trait is defined by the user, bad!
+```
+
+Only operators on builtin types are allowed.
+
+Example:
+
+```
+const a: &'static [i32] = &[1, 2, 3];
+const b: i32 = a[0]; // Good!
+```
+"##,
+
+E0013: r##"
+Static and const variables can refer to other const variables. But a const
+variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
+here:
+
+```
+static X: i32 = 42;
+const Y: i32 = X;
+```
+
+To fix this, the value can be extracted as a const and then used:
+
+```
+const A: i32 = 42;
+static X: i32 = A;
+const Y: i32 = A;
+```
+"##,
+
+E0014: r##"
+Constants can only be initialized by a constant value or, in a future
+version of Rust, a call to a const function. This error indicates the use
+of a path (like a::b, or x) denoting something other than one of these
+allowed items. Example:
+
+```
+const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
+```
+
+To avoid it, you have to replace the non-constant value:
+
+```
+const FOO: i32 = { const X : i32 = 0; X };
+// or even:
+const FOO: i32 = { 0 }; // but brackets are useless here
+```
+"##,
+
+// FIXME(#24111) Change the language here when const fn stabilizes
+E0015: r##"
+The only functions that can be called in static or constant expressions are
+`const` functions, and struct/enum constructors. `const` functions are only
+available on a nightly compiler. Rust currently does not support more general
+compile-time function execution.
+
+```
+const FOO: Option<u8> = Some(1); // enum constructor
+struct Bar {x: u8}
+const BAR: Bar = Bar {x: 1}; // struct constructor
+```
+
+See [RFC 911] for more details on the design of `const fn`s.
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
 E0016: r##"
 Blocks in constants may only contain items (such as constant, function
 definition, etc...) and a tail expression. Example:
 ```
 "##,
 
+E0017: r##"
+References in statics and constants may only refer to immutable values. Example:
+
+```
+static X: i32 = 1;
+const C: i32 = 2;
+
+// these three are not allowed:
+const CR: &'static mut i32 = &mut C;
+static STATIC_REF: &'static mut i32 = &mut X;
+static CONST_REF: &'static mut i32 = &mut C;
+```
+
+Statics are shared everywhere, and if they refer to mutable data one might
+violate memory safety since holding multiple mutable references to shared data
+is not allowed.
+
+If you really want global mutable state, try using `static mut` or a global
+`UnsafeCell`.
+"##,
+
+E0018: r##"
+The value of static and const variables must be known at compile time. You
+can't cast a pointer as an integer because we can't know what value the
+address will take.
+
+However, pointers to other constants' addresses are allowed in constants,
+example:
+
+```
+const X: u32 = 50;
+const Y: *const u32 = &X;
+```
+
+Therefore, casting one of these non-constant pointers to an integer results
+in a non-constant integer which lead to this error. Example:
+
+```
+const X: u32 = 1;
+const Y: usize = &X as *const u32 as usize;
+println!("{}", Y);
+```
+"##,
+
+E0019: r##"
+A function call isn't allowed in the const's initialization expression
+because the expression's value must be known at compile-time. Example of
+erroneous code:
+
+```
+enum Test {
+    V1
+}
+
+impl Test {
+    fn test(&self) -> i32 {
+        12
+    }
+}
+
+fn main() {
+    const FOO: Test = Test::V1;
+
+    const A: i32 = FOO.test(); // You can't call Test::func() here !
+}
+```
+
+Remember: you can't use a function call inside a const's initialization
+expression! However, you can totally use it anywhere else:
+
+```
+fn main() {
+    const FOO: Test = Test::V1;
+
+    FOO.func(); // here is good
+    let x = FOO.func(); // or even here!
+}
+```
+"##,
+
 E0022: r##"
 Constant functions are not allowed to mutate anything. Thus, binding to an
 argument with a mutable pattern is not allowed. For example,
@@ -43,6 +225,366 @@ const fn foo(mut x: u8) {
 instead of using a `const fn`, or refactoring the code to a functional style to
 avoid mutation if possible.
 "##,
+
+E0030: r##"
+When matching against a range, the compiler verifies that the range is
+non-empty.  Range patterns include both end-points, so this is equivalent to
+requiring the start of the range to be less than or equal to the end of the
+range.
+
+For example:
+
+```
+match 5u32 {
+    // This range is ok, albeit pointless.
+    1 ... 1 => ...
+    // This range is empty, and the compiler can tell.
+    1000 ... 5 => ...
+}
+```
+"##,
+
+E0161: r##"
+In Rust, you can only move a value when its size is known at compile time.
+
+To work around this restriction, consider "hiding" the value behind a reference:
+either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
+it around as usual.
+"##,
+
+E0265: r##"
+This error indicates that a static or constant references itself.
+All statics and constants need to resolve to a value in an acyclic manner.
+
+For example, neither of the following can be sensibly compiled:
+
+```
+const X: u32 = X;
+```
+
+```
+const X: u32 = Y;
+const Y: u32 = X;
+```
+"##,
+
+E0267: r##"
+This error indicates the use of a loop keyword (`break` or `continue`) inside a
+closure but outside of any loop. Erroneous code example:
+
+```
+let w = || { break; }; // error: `break` inside of a closure
+```
+
+`break` and `continue` keywords can be used as normal inside closures as long as
+they are also contained within a loop. To halt the execution of a closure you
+should instead use a return statement. Example:
+
+```
+let w = || {
+    for _ in 0..10 {
+        break;
+    }
+};
+
+w();
+```
+"##,
+
+E0268: r##"
+This error indicates the use of a loop keyword (`break` or `continue`) outside
+of a loop. Without a loop to break out of or continue in, no sensible action can
+be taken. Erroneous code example:
+
+```
+fn some_func() {
+    break; // error: `break` outside of loop
+}
+```
+
+Please verify that you are using `break` and `continue` only in loops. Example:
+
+```
+fn some_func() {
+    for _ in 0..10 {
+        break; // ok!
+    }
+}
+```
+"##,
+
+E0378: r##"
+Method calls that aren't calls to inherent `const` methods are disallowed
+in statics, constants, and constant functions.
+
+For example:
+
+```
+const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
+
+struct Foo(i32);
+
+impl Foo {
+    const fn foo(&self) -> i32 {
+        self.bar() // error, `bar` isn't `const`
+    }
+
+    fn bar(&self) -> i32 { self.0 }
+}
+```
+
+For more information about `const fn`'s, see [RFC 911].
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
+E0394: r##"
+From [RFC 246]:
+
+ > It is invalid for a static to reference another static by value. It is
+ > required that all references be borrowed.
+
+[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
+"##,
+
+E0395: r##"
+The value assigned to a constant expression must be known at compile time,
+which is not the case when comparing raw pointers. Erroneous code example:
+
+```
+static foo: i32 = 42;
+static bar: i32 = 43;
+
+static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
+// error: raw pointers cannot be compared in statics!
+```
+
+Please check that the result of the comparison can be determined at compile time
+or isn't assigned to a constant expression. Example:
+
+```
+static foo: i32 = 42;
+static bar: i32 = 43;
+
+let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
+// baz isn't a constant expression so it's ok
+```
+"##,
+
+E0396: r##"
+The value assigned to a constant expression must be known at compile time,
+which is not the case when dereferencing raw pointers. Erroneous code
+example:
+
+```
+const foo: i32 = 42;
+const baz: *const i32 = (&foo as *const i32);
+
+const deref: i32 = *baz;
+// error: raw pointers cannot be dereferenced in constants
+```
+
+To fix this error, please do not assign this value to a constant expression.
+Example:
+
+```
+const foo: i32 = 42;
+const baz: *const i32 = (&foo as *const i32);
+
+unsafe { let deref: i32 = *baz; }
+// baz isn't a constant expression so it's ok
+```
+
+You'll also note that this assignment must be done in an unsafe block!
+"##,
+
+E0397: r##"
+It is not allowed for a mutable static to allocate or have destructors. For
+example:
+
+```
+// error: mutable statics are not allowed to have boxes
+static mut FOO: Option<Box<usize>> = None;
+
+// error: mutable statics are not allowed to have destructors
+static mut BAR: Option<Vec<i32>> = None;
+```
+"##,
+
+E0400: r##"
+A user-defined dereference was attempted in an invalid context. Erroneous
+code example:
+
+```
+use std::ops::Deref;
+
+struct A;
+
+impl Deref for A {
+    type Target = str;
+
+    fn deref(&self)-> &str { "foo" }
+}
+
+const S: &'static str = &A;
+// error: user-defined dereference operators are not allowed in constants
+
+fn main() {
+    let foo = S;
+}
+```
+
+You cannot directly use a dereference operation whilst initializing a constant
+or a static. To fix this error, restructure your code to avoid this dereference,
+perhaps moving it inline:
+
+```
+use std::ops::Deref;
+
+struct A;
+
+impl Deref for A {
+    type Target = str;
+
+    fn deref(&self)-> &str { "foo" }
+}
+
+fn main() {
+    let foo : &str = &A;
+}
+```
+"##,
+
+E0492: r##"
+A borrow of a constant containing interior mutability was attempted. Erroneous
+code example:
+
+```
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+
+const A: AtomicUsize = ATOMIC_USIZE_INIT;
+static B: &'static AtomicUsize = &A;
+// error: cannot borrow a constant which contains interior mutability, create a
+//        static instead
+```
+
+A `const` represents a constant value that should never change. If one takes
+a `&` reference to the constant, then one is taking a pointer to some memory
+location containing the value. Normally this is perfectly fine: most values
+can't be changed via a shared `&` pointer, but interior mutability would allow
+it. That is, a constant value could be mutated. On the other hand, a `static` is
+explicitly a single memory location, which can be mutated at will.
+
+So, in order to solve this error, either use statics which are `Sync`:
+
+```
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+
+static A: AtomicUsize = ATOMIC_USIZE_INIT;
+static B: &'static AtomicUsize = &A; // ok!
+```
+
+You can also have this error while using a cell type:
+
+```
+#![feature(const_fn)]
+
+use std::cell::Cell;
+
+const A: Cell<usize> = Cell::new(1);
+const B: &'static Cell<usize> = &A;
+// error: cannot borrow a constant which contains interior mutability, create
+//        a static instead
+
+// or:
+struct C { a: Cell<usize> }
+
+const D: C = C { a: Cell::new(1) };
+const E: &'static Cell<usize> = &D.a; // error
+
+// or:
+const F: &'static C = &D; // error
+```
+
+This is because cell types do operations that are not thread-safe. Due to this,
+they don't implement Sync and thus can't be placed in statics. In this
+case, `StaticMutex` would work just fine, but it isn't stable yet:
+https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
+
+However, if you still wish to use these types, you can achieve this by an unsafe
+wrapper:
+
+```
+#![feature(const_fn)]
+
+use std::cell::Cell;
+use std::marker::Sync;
+
+struct NotThreadSafe<T> {
+    value: Cell<T>,
+}
+
+unsafe impl<T> Sync for NotThreadSafe<T> {}
+
+static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
+static B: &'static NotThreadSafe<usize> = &A; // ok!
+```
+
+Remember this solution is unsafe! You will have to ensure that accesses to the
+cell are synchronized.
+"##,
+
+E0493: r##"
+A type with a destructor was assigned to an invalid type of variable. Erroneous
+code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+const F : Foo = Foo { a : 0 };
+// error: constants are not allowed to have destructors
+static S : Foo = Foo { a : 0 };
+// error: statics are not allowed to have destructors
+```
+
+To solve this issue, please use a type which does allow the usage of type with
+destructors.
+"##,
+
+E0494: r##"
+A reference of an interior static was assigned to another const/static.
+Erroneous code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+static S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a;
+// error: cannot refer to the interior of another static, use a
+//        constant instead
+```
+
+The "base" variable has to be a const if you want another static/const variable
+to refer to one of its fields. Example:
+
+```
+struct Foo {
+    a: u32
+}
+
+const S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a; // ok!
+```
+"##,
+
 }
 
 register_diagnostics! {
index 4adaa0cab7a04e79bb4b880bcc7ab599a59360f6..fcdbd6384d543465653a66515c4b880a2184d477 100644 (file)
 
 extern crate core;
 extern crate rustc;
+extern crate rustc_front;
 
+#[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
 pub mod diagnostics;
+
 pub mod const_fn;
+pub mod consts;
+pub mod loops;
 pub mod no_asm;
+pub mod rvalues;
+pub mod static_recursion;
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
new file mode 100644 (file)
index 0000000..eb2e445
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2012-2014 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 self::Context::*;
+
+use rustc::session::Session;
+
+use syntax::codemap::Span;
+use rustc_front::intravisit::{self, Visitor};
+use rustc_front::hir;
+
+#[derive(Clone, Copy, PartialEq)]
+enum Context {
+    Normal, Loop, Closure
+}
+
+#[derive(Copy, Clone)]
+struct CheckLoopVisitor<'a> {
+    sess: &'a Session,
+    cx: Context
+}
+
+pub fn check_crate(sess: &Session, krate: &hir::Crate) {
+    krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
+}
+
+impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
+    fn visit_item(&mut self, i: &hir::Item) {
+        self.with_context(Normal, |v| intravisit::walk_item(v, i));
+    }
+
+    fn visit_expr(&mut self, e: &hir::Expr) {
+        match e.node {
+            hir::ExprWhile(ref e, ref b, _) => {
+                self.visit_expr(&**e);
+                self.with_context(Loop, |v| v.visit_block(&**b));
+            }
+            hir::ExprLoop(ref b, _) => {
+                self.with_context(Loop, |v| v.visit_block(&**b));
+            }
+            hir::ExprClosure(_, _, ref b) => {
+                self.with_context(Closure, |v| v.visit_block(&**b));
+            }
+            hir::ExprBreak(_) => self.require_loop("break", e.span),
+            hir::ExprAgain(_) => self.require_loop("continue", e.span),
+            _ => intravisit::walk_expr(self, e)
+        }
+    }
+}
+
+impl<'a> CheckLoopVisitor<'a> {
+    fn with_context<F>(&mut self, cx: Context, f: F) where
+        F: FnOnce(&mut CheckLoopVisitor<'a>),
+    {
+        let old_cx = self.cx;
+        self.cx = cx;
+        f(self);
+        self.cx = old_cx;
+    }
+
+    fn require_loop(&self, name: &str, span: Span) {
+        match self.cx {
+            Loop => {}
+            Closure => {
+                span_err!(self.sess, span, E0267,
+                                   "`{}` inside of a closure", name);
+            }
+            Normal => {
+                span_err!(self.sess, span, E0268,
+                                   "`{}` outside of loop", name);
+            }
+        }
+    }
+}
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
new file mode 100644 (file)
index 0000000..f5cc020
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2014 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.
+
+// Checks that all rvalues in a crate have statically known size. check_crate
+// is the public starting point.
+
+use rustc::dep_graph::DepNode;
+use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
+use rustc::middle::mem_categorization as mc;
+use rustc::middle::ty::{self, ParameterEnvironment};
+
+use rustc_front::hir;
+use rustc_front::intravisit;
+use syntax::ast;
+use syntax::codemap::Span;
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    let mut rvcx = RvalueContext { tcx: tcx };
+    tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
+}
+
+struct RvalueContext<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+}
+
+impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
+    fn visit_fn(&mut self,
+                fk: intravisit::FnKind<'v>,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
+                s: Span,
+                fn_id: ast::NodeId) {
+        {
+            // FIXME (@jroesch) change this to be an inference context
+            let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+            let infcx = infer::new_infer_ctxt(self.tcx,
+                                              &self.tcx.tables,
+                                              Some(param_env.clone()));
+            let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
+            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
+            euv.walk_fn(fd, b);
+        }
+        intravisit::walk_fn(self, fk, fd, b, s)
+    }
+}
+
+struct RvalueContextDelegate<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    param_env: &'a ty::ParameterEnvironment<'a,'tcx>,
+}
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
+    fn consume(&mut self,
+               _: ast::NodeId,
+               span: Span,
+               cmt: mc::cmt<'tcx>,
+               _: euv::ConsumeMode) {
+        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
+        if !cmt.ty.is_sized(self.param_env, span) {
+            span_err!(self.tcx.sess, span, E0161,
+                "cannot move a value of type {0}: the size of {0} cannot be statically determined",
+                cmt.ty);
+        }
+    }
+
+    fn matched_pat(&mut self,
+                   _matched_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::MatchMode) {}
+
+    fn consume_pat(&mut self,
+                   _consume_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::ConsumeMode) {
+    }
+
+    fn borrow(&mut self,
+              _borrow_id: ast::NodeId,
+              _borrow_span: Span,
+              _cmt: mc::cmt,
+              _loan_region: ty::Region,
+              _bk: ty::BorrowKind,
+              _loan_cause: euv::LoanCause) {
+    }
+
+    fn decl_without_init(&mut self,
+                         _id: ast::NodeId,
+                         _span: Span) {
+    }
+
+    fn mutate(&mut self,
+              _assignment_id: ast::NodeId,
+              _assignment_span: Span,
+              _assignee_cmt: mc::cmt,
+              _mode: euv::MutateMode) {
+    }
+}
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
new file mode 100644 (file)
index 0000000..b49db16
--- /dev/null
@@ -0,0 +1,290 @@
+// Copyright 2014 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.
+
+// This compiler pass detects constants that refer to themselves
+// recursively.
+
+use rustc::front::map as ast_map;
+use rustc::session::Session;
+use rustc::middle::def::{Def, DefMap};
+use rustc::util::nodemap::NodeMap;
+
+use syntax::{ast};
+use syntax::codemap::Span;
+use syntax::feature_gate::{GateIssue, emit_feature_err};
+use rustc_front::intravisit::{self, Visitor};
+use rustc_front::hir;
+
+use std::cell::RefCell;
+
+struct CheckCrateVisitor<'a, 'ast: 'a> {
+    sess: &'a Session,
+    def_map: &'a DefMap,
+    ast_map: &'a ast_map::Map<'ast>,
+    // `discriminant_map` is a cache that associates the `NodeId`s of local
+    // variant definitions with the discriminant expression that applies to
+    // each one. If the variant uses the default values (starting from `0`),
+    // then `None` is stored.
+    discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
+}
+
+impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
+        match it.node {
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &it.span);
+                recursion_visitor.visit_item(it);
+            },
+            hir::ItemEnum(ref enum_def, ref generics) => {
+                // We could process the whole enum, but handling the variants
+                // with discriminant expressions one by one gives more specific,
+                // less redundant output.
+                for variant in &enum_def.variants {
+                    if let Some(_) = variant.node.disr_expr {
+                        let mut recursion_visitor =
+                            CheckItemRecursionVisitor::new(self, &variant.span);
+                        recursion_visitor.populate_enum_discriminants(enum_def);
+                        recursion_visitor.visit_variant(variant, generics, it.id);
+                    }
+                }
+            }
+            _ => {}
+        }
+        intravisit::walk_item(self, it)
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        match ti.node {
+            hir::ConstTraitItem(_, ref default) => {
+                if let Some(_) = *default {
+                    let mut recursion_visitor =
+                        CheckItemRecursionVisitor::new(self, &ti.span);
+                    recursion_visitor.visit_trait_item(ti);
+                }
+            }
+            _ => {}
+        }
+        intravisit::walk_trait_item(self, ti)
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        match ii.node {
+            hir::ImplItemKind::Const(..) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &ii.span);
+                recursion_visitor.visit_impl_item(ii);
+            }
+            _ => {}
+        }
+        intravisit::walk_impl_item(self, ii)
+    }
+}
+
+pub fn check_crate<'ast>(sess: &Session,
+                         krate: &'ast hir::Crate,
+                         def_map: &DefMap,
+                         ast_map: &ast_map::Map<'ast>) {
+    let mut visitor = CheckCrateVisitor {
+        sess: sess,
+        def_map: def_map,
+        ast_map: ast_map,
+        discriminant_map: RefCell::new(NodeMap()),
+    };
+    sess.abort_if_new_errors(|| {
+        krate.visit_all_items(&mut visitor);
+    });
+}
+
+struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
+    root_span: &'a Span,
+    sess: &'a Session,
+    ast_map: &'a ast_map::Map<'ast>,
+    def_map: &'a DefMap,
+    discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
+    idstack: Vec<ast::NodeId>,
+}
+
+impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
+    fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span)
+           -> CheckItemRecursionVisitor<'a, 'ast> {
+        CheckItemRecursionVisitor {
+            root_span: span,
+            sess: v.sess,
+            ast_map: v.ast_map,
+            def_map: v.def_map,
+            discriminant_map: &v.discriminant_map,
+            idstack: Vec::new(),
+        }
+    }
+    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
+          where F: Fn(&mut Self) {
+        if self.idstack.iter().any(|&x| x == id) {
+            let any_static = self.idstack.iter().any(|&x| {
+                if let ast_map::NodeItem(item) = self.ast_map.get(x) {
+                    if let hir::ItemStatic(..) = item.node {
+                        true
+                    } else {
+                        false
+                    }
+                } else {
+                    false
+                }
+            });
+            if any_static {
+                if !self.sess.features.borrow().static_recursion {
+                    emit_feature_err(&self.sess.parse_sess.span_diagnostic,
+                                     "static_recursion",
+                                     *self.root_span, GateIssue::Language, "recursive static");
+                }
+            } else {
+                span_err!(self.sess, *self.root_span, E0265, "recursive constant");
+            }
+            return;
+        }
+        self.idstack.push(id);
+        f(self);
+        self.idstack.pop();
+    }
+    // If a variant has an expression specifying its discriminant, then it needs
+    // to be checked just like a static or constant. However, if there are more
+    // variants with no explicitly specified discriminant, those variants will
+    // increment the same expression to get their values.
+    //
+    // So for every variant, we need to track whether there is an expression
+    // somewhere in the enum definition that controls its discriminant. We do
+    // this by starting from the end and searching backward.
+    fn populate_enum_discriminants(&self, enum_definition: &'ast hir::EnumDef) {
+        // Get the map, and return if we already processed this enum or if it
+        // has no variants.
+        let mut discriminant_map = self.discriminant_map.borrow_mut();
+        match enum_definition.variants.first() {
+            None => { return; }
+            Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => {
+                return;
+            }
+            _ => {}
+        }
+
+        // Go through all the variants.
+        let mut variant_stack: Vec<ast::NodeId> = Vec::new();
+        for variant in enum_definition.variants.iter().rev() {
+            variant_stack.push(variant.node.data.id());
+            // When we find an expression, every variant currently on the stack
+            // is affected by that expression.
+            if let Some(ref expr) = variant.node.disr_expr {
+                for id in &variant_stack {
+                    discriminant_map.insert(*id, Some(expr));
+                }
+                variant_stack.clear()
+            }
+        }
+        // If we are at the top, that always starts at 0, so any variant on the
+        // stack has a default value and does not need to be checked.
+        for id in &variant_stack {
+            discriminant_map.insert(*id, None);
+        }
+    }
+}
+
+impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
+        self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it));
+    }
+
+    fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
+                      generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) {
+        self.populate_enum_discriminants(enum_definition);
+        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
+    }
+
+    fn visit_variant(&mut self, variant: &'ast hir::Variant,
+                     _: &'ast hir::Generics, _: ast::NodeId) {
+        let variant_id = variant.node.data.id();
+        let maybe_expr;
+        if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
+            // This is necessary because we need to let the `discriminant_map`
+            // borrow fall out of scope, so that we can reborrow farther down.
+            maybe_expr = (*get_expr).clone();
+        } else {
+            self.sess.span_bug(variant.span,
+                               "`check_static_recursion` attempted to visit \
+                                variant with unknown discriminant")
+        }
+        // If `maybe_expr` is `None`, that's because no discriminant is
+        // specified that affects this variant. Thus, no risk of recursion.
+        if let Some(expr) = maybe_expr {
+            self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr));
+        }
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        self.with_item_id_pushed(ti.id, |v| intravisit::walk_trait_item(v, ti));
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        self.with_item_id_pushed(ii.id, |v| intravisit::walk_impl_item(v, ii));
+    }
+
+    fn visit_expr(&mut self, e: &'ast hir::Expr) {
+        match e.node {
+            hir::ExprPath(..) => {
+                match self.def_map.get(&e.id).map(|d| d.base_def) {
+                    Some(Def::Static(def_id, _)) |
+                    Some(Def::AssociatedConst(def_id)) |
+                    Some(Def::Const(def_id)) => {
+                        if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
+                            match self.ast_map.get(node_id) {
+                                ast_map::NodeItem(item) =>
+                                    self.visit_item(item),
+                                ast_map::NodeTraitItem(item) =>
+                                    self.visit_trait_item(item),
+                                ast_map::NodeImplItem(item) =>
+                                    self.visit_impl_item(item),
+                                ast_map::NodeForeignItem(_) => {},
+                                _ => {
+                                    self.sess.span_bug(
+                                        e.span,
+                                        &format!("expected item, found {}",
+                                                 self.ast_map.node_to_string(node_id)));
+                                }
+                            }
+                        }
+                    }
+                    // For variants, we only want to check expressions that
+                    // affect the specific variant used, but we need to check
+                    // the whole enum definition to see what expression that
+                    // might be (if any).
+                    Some(Def::Variant(enum_id, variant_id)) => {
+                        if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) {
+                            if let hir::ItemEnum(ref enum_def, ref generics) =
+                                self.ast_map.expect_item(enum_node_id).node
+                            {
+                                self.populate_enum_discriminants(enum_def);
+                                let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap();
+                                let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap();
+                                let variant = self.ast_map.expect_variant(variant_id);
+                                self.visit_variant(variant, generics, enum_id);
+                            } else {
+                                self.sess.span_bug(e.span,
+                                                   "`check_static_recursion` found \
+                                                    non-enum in Def::Variant");
+                            }
+                        }
+                    }
+                    _ => ()
+                }
+            },
+            _ => ()
+        }
+        intravisit::walk_expr(self, e);
+    }
+}
index d3da93a3e080d53508928af23f0c8b0068568b03..cfd0540cc60e782227f5430e270e76c9c07f5f69 100644 (file)
@@ -37,7 +37,7 @@
 
 use rustc::dep_graph::DepNode;
 use rustc::lint;
-use rustc::middle::def;
+use rustc::middle::def::{self, Def};
 use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::middle::privacy::ImportUse::*;
@@ -172,7 +172,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
         if let hir::TyPath(..) = ty.node {
             match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
+                Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     Some(AccessLevel::Public)
                 }
                 def => {
@@ -294,7 +294,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             hir::ItemTy(ref ty, _) if item_level.is_some() => {
                 if let hir::TyPath(..) = ty.node {
                     match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                        def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {},
+                        Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {},
                         def => {
                             if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
                                 self.update(node_id, Some(AccessLevel::Reachable));
@@ -806,17 +806,17 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) {
         // be accurate and we can get slightly wonky error messages (but type
         // checking is always correct).
         match path_res.full_def() {
-            def::DefFn(..) => ck("function"),
-            def::DefStatic(..) => ck("static"),
-            def::DefConst(..) => ck("const"),
-            def::DefAssociatedConst(..) => ck("associated const"),
-            def::DefVariant(..) => ck("variant"),
-            def::DefTy(_, false) => ck("type"),
-            def::DefTy(_, true) => ck("enum"),
-            def::DefTrait(..) => ck("trait"),
-            def::DefStruct(..) => ck("struct"),
-            def::DefMethod(..) => ck("method"),
-            def::DefMod(..) => ck("module"),
+            Def::Fn(..) => ck("function"),
+            Def::Static(..) => ck("static"),
+            Def::Const(..) => ck("const"),
+            Def::AssociatedConst(..) => ck("associated const"),
+            Def::Variant(..) => ck("variant"),
+            Def::TyAlias(..) => ck("type"),
+            Def::Enum(..) => ck("enum"),
+            Def::Trait(..) => ck("trait"),
+            Def::Struct(..) => ck("struct"),
+            Def::Method(..) => ck("method"),
+            Def::Mod(..) => ck("module"),
             _ => {}
         }
     }
@@ -887,7 +887,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
             }
             hir::ExprPath(..) => {
 
-                if let def::DefStruct(_) = self.tcx.resolve_expr(expr) {
+                if let Def::Struct(..) = self.tcx.resolve_expr(expr) {
                     let expr_ty = self.tcx.expr_ty(expr);
                     let def = match expr_ty.sty {
                         ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
@@ -1132,7 +1132,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
         let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
             // `int` etc. (None doesn't seem to occur.)
-            None | Some(def::DefPrimTy(..)) | Some(def::DefSelfTy(..)) => return false,
+            None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => return false,
             Some(def) => def.def_id(),
         };
 
@@ -1503,10 +1503,10 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyPath(_, ref path) = ty.node {
             let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
             match def {
-                def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
+                Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     // Public
                 }
-                def::DefAssociatedTy(..) if self.is_quiet => {
+                Def::AssociatedTy(..) if self.is_quiet => {
                     // Conservatively approximate the whole type alias as public without
                     // recursing into its components when determining impl publicity.
                     // For example, `impl <Type as Trait>::Alias {...}` may be a public impl
@@ -1515,8 +1515,8 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                     // free type aliases, but this isn't done yet.
                     return
                 }
-                def::DefStruct(def_id) | def::DefTy(def_id, _) |
-                def::DefTrait(def_id) | def::DefAssociatedTy(def_id, _) => {
+                Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
+                Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
                     // Non-local means public (private items can't leave their crate, modulo bugs)
                     if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
                         let item = self.tcx.map.expect_item(node_id);
index 2e713a2f50e0fcdb0d5dfe08db3c54f2107f20ab..5fb33b1ed1777e42b5c188ee42f334c36ccc0f90 100644 (file)
@@ -31,6 +31,7 @@
 use rustc::middle::cstore::{CrateStore, ChildItem, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
 use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::middle::ty::VariantKind;
 
 use syntax::ast::{Name, NodeId};
 use syntax::attr::AttrMetaMethods;
@@ -315,7 +316,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                     };
                     self.external_exports.insert(def_id);
                     let parent_link = ModuleParentLink(parent, name);
-                    let def = DefMod(def_id);
+                    let def = Def::Mod(def_id);
                     let external_module = self.new_module(parent_link, Some(def), false, true);
 
                     debug!("(build reduced graph for item) found extern `{}`",
@@ -333,7 +334,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateTypes, sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefMod(self.ast_map.local_def_id(item.id));
+                let def = Def::Mod(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
                 module
@@ -346,20 +347,20 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
                 let mutbl = m == hir::MutMutable;
 
-                name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl),
+                name_bindings.define_value(Def::Static(self.ast_map.local_def_id(item.id), mutbl),
                                            sp,
                                            modifiers);
                 parent
             }
             ItemConst(_, _) => {
                 self.add_child(name, parent, ForbidDuplicateValues, sp)
-                    .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers);
+                    .define_value(Def::Const(self.ast_map.local_def_id(item.id)), sp, modifiers);
                 parent
             }
             ItemFn(_, _, _, _, _, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
 
-                let def = DefFn(self.ast_map.local_def_id(item.id), false);
+                let def = Def::Fn(self.ast_map.local_def_id(item.id));
                 name_bindings.define_value(def, sp, modifiers);
                 parent
             }
@@ -372,7 +373,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                                                    sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTy(self.ast_map.local_def_id(item.id), false);
+                let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module, sp);
                 parent
@@ -385,7 +386,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                                                    sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTy(self.ast_map.local_def_id(item.id), true);
+                let def = Def::Enum(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
 
@@ -414,14 +415,14 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, forbid, sp);
 
                 // Define a name in the type namespace.
-                name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false),
+                name_bindings.define_type(Def::Struct(self.ast_map.local_def_id(item.id)),
                                           sp,
                                           modifiers);
 
                 // If this is a newtype or unit-like struct, define a name
                 // in the value namespace as well
                 if let Some(cid) = ctor_id {
-                    name_bindings.define_value(DefStruct(self.ast_map.local_def_id(cid)),
+                    name_bindings.define_value(Def::Struct(self.ast_map.local_def_id(cid)),
                                                sp,
                                                modifiers);
                 }
@@ -455,7 +456,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
 
                 // Add all the items within to a new module.
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTrait(def_id);
+                let def = Def::Trait(def_id);
                 let module_parent = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module_parent.clone(), sp);
 
@@ -468,17 +469,18 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
 
                     match trait_item.node {
                         hir::ConstTraitItem(..) => {
-                            let def = DefAssociatedConst(self.ast_map.local_def_id(trait_item.id));
+                            let def = Def::AssociatedConst(self.ast_map.
+                                                                local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::MethodTraitItem(..) => {
-                            let def = DefMethod(self.ast_map.local_def_id(trait_item.id));
+                            let def = Def::Method(self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::TypeTraitItem(..) => {
-                            let def = DefAssociatedTy(self.ast_map.local_def_id(item.id),
+                            let def = Def::AssociatedTy(self.ast_map.local_def_id(item.id),
                                                       self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
@@ -502,26 +504,19 @@ fn build_reduced_graph_for_variant(&mut self,
                                        parent: Module<'b>,
                                        variant_modifiers: DefModifiers) {
         let name = variant.node.name;
-        let is_exported = if variant.node.data.is_struct() {
+        if variant.node.data.is_struct() {
             // Not adding fields for variants as they are not accessed with a self receiver
             let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
             self.structs.insert(variant_def_id, Vec::new());
-            true
-        } else {
-            false
-        };
+        }
 
         let child = self.add_child(name, parent, ForbidDuplicateTypesAndValues, variant.span);
         // variants are always treated as importable to allow them to be glob
         // used
-        child.define_value(DefVariant(item_id,
-                                      self.ast_map.local_def_id(variant.node.data.id()),
-                                      is_exported),
+        child.define_value(Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id())),
                            variant.span,
                            DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
-        child.define_type(DefVariant(item_id,
-                                     self.ast_map.local_def_id(variant.node.data.id()),
-                                     is_exported),
+        child.define_type(Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id())),
                           variant.span,
                           DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
     }
@@ -541,10 +536,10 @@ fn build_reduced_graph_for_foreign_item(&mut self,
 
         let def = match foreign_item.node {
             ForeignItemFn(..) => {
-                DefFn(self.ast_map.local_def_id(foreign_item.id), false)
+                Def::Fn(self.ast_map.local_def_id(foreign_item.id))
             }
             ForeignItemStatic(_, m) => {
-                DefStatic(self.ast_map.local_def_id(foreign_item.id), m)
+                Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
             }
         };
         name_bindings.define_value(def, foreign_item.span, modifiers);
@@ -591,12 +586,18 @@ fn handle_external_def(&mut self,
         if is_exported {
             self.external_exports.insert(def.def_id());
         }
+        let is_struct_ctor = if let Def::Struct(def_id) = def {
+            self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_some()
+        } else {
+            false
+        };
 
         match def {
-            DefMod(_) |
-            DefForeignMod(_) |
-            DefStruct(_) |
-            DefTy(..) => {
+            Def::Mod(_) |
+            Def::ForeignMod(_) |
+            Def::Struct(..) |
+            Def::Enum(..) |
+            Def::TyAlias(..) if !is_struct_ctor => {
                 if let Some(module_def) = child_name_bindings.type_ns.module() {
                     debug!("(building reduced graph for external crate) already created module");
                     module_def.def.set(Some(def));
@@ -613,14 +614,14 @@ fn handle_external_def(&mut self,
         }
 
         match def {
-            DefMod(_) | DefForeignMod(_) => {}
-            DefVariant(_, variant_id, is_struct) => {
+            Def::Mod(_) | Def::ForeignMod(_) => {}
+            Def::Variant(_, variant_id) => {
                 debug!("(building reduced graph for external crate) building variant {}",
                        final_ident);
                 // variants are always treated as importable to allow them to be
                 // glob used
                 let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
-                if is_struct {
+                if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
                     child_name_bindings.define_type(def, DUMMY_SP, modifiers);
                     // Not adding fields for variants as they are not accessed with a self receiver
                     self.structs.insert(variant_id, Vec::new());
@@ -628,16 +629,11 @@ fn handle_external_def(&mut self,
                     child_name_bindings.define_value(def, DUMMY_SP, modifiers);
                 }
             }
-            DefFn(ctor_id, true) => {
-                child_name_bindings.define_value(
-                self.session.cstore.tuple_struct_definition_if_ctor(ctor_id)
-                    .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
-            }
-            DefFn(..) |
-            DefStatic(..) |
-            DefConst(..) |
-            DefAssociatedConst(..) |
-            DefMethod(..) => {
+            Def::Fn(..) |
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Method(..) => {
                 debug!("(building reduced graph for external crate) building value (fn/static) {}",
                        final_ident);
                 // impl methods have already been defined with the correct importability
@@ -652,7 +648,7 @@ fn handle_external_def(&mut self,
                 }
                 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
             }
-            DefTrait(def_id) => {
+            Def::Trait(def_id) => {
                 debug!("(building reduced graph for external crate) building type {}",
                        final_ident);
 
@@ -680,7 +676,7 @@ fn handle_external_def(&mut self,
                 let module = self.new_module(parent_link, Some(def), true, is_public);
                 child_name_bindings.define_module(module, DUMMY_SP);
             }
-            DefTy(..) | DefAssociatedTy(..) => {
+            Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
                 debug!("(building reduced graph for external crate) building type {}",
                        final_ident);
 
@@ -689,33 +685,38 @@ fn handle_external_def(&mut self,
                     _ => modifiers & !DefModifiers::IMPORTABLE,
                 };
 
-                if let DefTy(..) = def {
+                if let Def::Enum(..) = def {
+                    child_name_bindings.type_ns.set_modifiers(modifiers);
+                } else if let Def::TyAlias(..) = def {
                     child_name_bindings.type_ns.set_modifiers(modifiers);
                 } else {
                     child_name_bindings.define_type(def, DUMMY_SP, modifiers);
                 }
             }
-            DefStruct(def_id) => {
+            Def::Struct(..) if is_struct_ctor => {
+                // Do nothing
+            }
+            Def::Struct(def_id) => {
                 debug!("(building reduced graph for external crate) building type and value for \
                         {}",
                        final_ident);
-                child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-                let fields = self.session.cstore.struct_field_names(def_id);
 
-                if fields.is_empty() {
-                    child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+                child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+                if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
+                    child_name_bindings.define_value(Def::Struct(ctor_def_id), DUMMY_SP, modifiers);
                 }
 
                 // Record the def ID and fields of this struct.
+                let fields = self.session.cstore.struct_field_names(def_id);
                 self.structs.insert(def_id, fields);
             }
-            DefLocal(..) |
-            DefPrimTy(..) |
-            DefTyParam(..) |
-            DefUpvar(..) |
-            DefLabel(..) |
-            DefSelfTy(..) |
-            DefErr => {
+            Def::Local(..) |
+            Def::PrimTy(..) |
+            Def::TyParam(..) |
+            Def::Upvar(..) |
+            Def::Label(..) |
+            Def::SelfTy(..) |
+            Def::Err => {
                 panic!("didn't expect `{:?}`", def);
             }
         }
@@ -729,7 +730,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
             DlDef(def) => {
                 // Add the new child item, if necessary.
                 match def {
-                    DefForeignMod(def_id) => {
+                    Def::ForeignMod(def_id) => {
                         // Foreign modules have no names. Recur and populate
                         // eagerly.
                         for child in self.session.cstore.item_children(def_id) {
index 8464d3ef298708187449cd32d5cd78b6ff86b477..444c43163e3c3ad4f1113e8b463ab98c4e0be5cf 100644 (file)
@@ -737,7 +737,7 @@ enum TypeParameters<'a> {
 }
 
 // The rib kind controls the translation of local
-// definitions (`DefLocal`) to upvars (`DefUpvar`).
+// definitions (`Def::Local`) to upvars (`Def::Upvar`).
 #[derive(Copy, Clone, Debug)]
 enum RibKind {
     // No translation needs to be applied.
@@ -913,14 +913,14 @@ fn def_id(&self) -> Option<DefId> {
 
     fn is_normal(&self) -> bool {
         match self.def.get() {
-            Some(DefMod(_)) | Some(DefForeignMod(_)) => true,
+            Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
             _ => false,
         }
     }
 
     fn is_trait(&self) -> bool {
         match self.def.get() {
-            Some(DefTrait(_)) => true,
+            Some(Def::Trait(_)) => true,
             _ => false,
         }
     }
@@ -1243,7 +1243,7 @@ fn new(session: &'a Session,
            arenas: &'a ResolverArenas<'a>)
            -> Resolver<'a, 'tcx> {
         let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
-        let graph_root = ModuleS::new(NoParentLink, Some(DefMod(root_def_id)), false, true);
+        let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, true);
         let graph_root = arenas.modules.alloc(graph_root);
 
         Resolver {
@@ -2020,7 +2020,7 @@ fn resolve_item(&mut self, item: &Item) {
                                                                ItemRibKind),
                                              |this| {
                     let local_def_id = this.ast_map.local_def_id(item.id);
-                    this.with_self_rib(DefSelfTy(Some(local_def_id), None), |this| {
+                    this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_ty_param_bound, bounds);
 
@@ -2076,7 +2076,8 @@ fn resolve_item(&mut self, item: &Item) {
                 // check for imports shadowing primitive types
                 let check_rename = |this: &Self, id, name| {
                     match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
-                        Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
+                        Some(Def::Enum(..)) | Some(Def::TyAlias(..)) | Some(Def::Struct(..)) |
+                        Some(Def::Trait(..)) | None => {
                             this.check_if_primitive_type_name(name, item.span);
                         }
                         _ => {}
@@ -2142,7 +2143,7 @@ fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
                     // plain insert (no renaming)
                     function_type_rib.bindings
                                      .insert(name,
-                                             DlDef(DefTyParam(space,
+                                             DlDef(Def::TyParam(space,
                                                               index as u32,
                                                               self.ast_map
                                                                   .local_def_id(type_parameter.id),
@@ -2225,7 +2226,7 @@ fn resolve_trait_reference(&mut self,
                                path_depth: usize)
                                -> Result<PathResolution, ()> {
         if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
-            if let DefTrait(_) = path_res.base_def {
+            if let Def::Trait(_) = path_res.base_def {
                 debug!("(resolving trait) found trait def: {:?}", path_res);
                 Ok(path_res)
             } else {
@@ -2236,7 +2237,7 @@ fn resolve_trait_reference(&mut self,
                                                                                       path_depth)));
 
                 // If it's a typedef, give a note
-                if let DefTy(..) = path_res.base_def {
+                if let Def::TyAlias(..) = path_res.base_def {
                     err.span_note(trait_path.span,
                                   "`type` aliases cannot be used for traits");
                 }
@@ -2262,7 +2263,7 @@ fn resolve_generics(&mut self, generics: &Generics) {
                 &hir::WherePredicate::RegionPredicate(_) => {}
                 &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                     let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
-                    if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
+                    if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
                         self.record_def(eq_pred.id, path_res.unwrap());
                     } else {
                         resolve_error(self,
@@ -2344,7 +2345,7 @@ fn resolve_implementation(&mut self,
                 // Resolve the self type.
                 this.visit_ty(self_type);
 
-                this.with_self_rib(DefSelfTy(trait_id, Some((item_id, self_type.id))), |this| {
+                this.with_self_rib(Def::SelfTy(trait_id, Some((item_id, self_type.id))), |this| {
                     this.with_current_self_type(self_type, |this| {
                         for impl_item in impl_items {
                             match impl_item.node {
@@ -2680,7 +2681,7 @@ fn resolve_pattern(&mut self,
                             debug!("(resolving pattern) binding `{}`", renamed);
 
                             let def_id = self.ast_map.local_def_id(pattern.id);
-                            let def = DefLocal(def_id, pattern.id);
+                            let def = Def::Local(def_id, pattern.id);
 
                             // Record the definition so that later passes
                             // will be able to distinguish variants from
@@ -2751,10 +2752,13 @@ fn resolve_pattern(&mut self,
                     };
                     if let Some(path_res) = resolution {
                         match path_res.base_def {
-                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
+                            Def::Struct(..) if path_res.depth == 0 => {
                                 self.record_def(pattern.id, path_res);
                             }
-                            DefStatic(..) => {
+                            Def::Variant(..) | Def::Const(..) => {
+                                self.record_def(pattern.id, path_res);
+                            }
+                            Def::Static(..) => {
                                 resolve_error(&self,
                                               path.span,
                                               ResolutionError::StaticVariableReference);
@@ -2829,7 +2833,7 @@ fn resolve_pattern(&mut self,
                         match path_res.base_def {
                             // All `<T as Trait>::CONST` should end up here, and
                             // have the trait already selected.
-                            DefAssociatedConst(..) => {
+                            Def::AssociatedConst(..) => {
                                 self.record_def(pattern.id, path_res);
                             }
                             _ => {
@@ -2906,13 +2910,13 @@ fn resolve_bare_identifier_pattern(&mut self,
                     // For the two success cases, this lookup can be
                     // considered as not having a private component because
                     // the lookup happened only within the current module.
-                    Some(def @ DefVariant(..)) | Some(def @ DefStruct(..)) => {
+                    Some(def @ Def::Variant(..)) | Some(def @ Def::Struct(..)) => {
                         return FoundStructOrEnumVariant(def, LastMod(AllPublic));
                     }
-                    Some(def @ DefConst(..)) | Some(def @ DefAssociatedConst(..)) => {
+                    Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
                         return FoundConst(def, LastMod(AllPublic), name);
                     }
-                    Some(DefStatic(..)) => {
+                    Some(Def::Static(..)) => {
                         resolve_error(self, span, ResolutionError::StaticVariableReference);
                         return BareIdentifierPatternUnresolved;
                     }
@@ -2972,7 +2976,7 @@ fn resolve_possibly_assoc_item(&mut self,
                 resolution = this.resolve_path(id, path, depth, TypeNS, true);
             });
         }
-        if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+        if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
             // A module is not a valid type or value.
             resolution = None;
         }
@@ -3038,7 +3042,7 @@ fn resolve_identifier(&mut self,
             if let Some(&prim_ty) = self.primitive_type_table
                                         .primitive_types
                                         .get(&identifier.unhygienic_name) {
-                return Some(LocalDef::from_def(DefPrimTy(prim_ty)));
+                return Some(LocalDef::from_def(Def::PrimTy(prim_ty)));
             }
         }
 
@@ -3062,10 +3066,10 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
         };
         let mut def = local_def.def;
         match def {
-            DefUpvar(..) => {
+            Def::Upvar(..) => {
                 self.session.span_bug(span, &format!("unexpected {:?} in bindings", def))
             }
-            DefLocal(_, node_id) => {
+            Def::Local(_, node_id) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind => {
@@ -3079,7 +3083,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                                            .entry(function_id)
                                            .or_insert_with(|| NodeMap());
                             if let Some(&index) = seen.get(&node_id) {
-                                def = DefUpvar(node_def_id, node_id, index, function_id);
+                                def = Def::Upvar(node_def_id, node_id, index, function_id);
                                 continue;
                             }
                             let vec = self.freevars
@@ -3091,7 +3095,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                                 span: span,
                             });
 
-                            def = DefUpvar(node_def_id, node_id, depth, function_id);
+                            def = Def::Upvar(node_def_id, node_id, depth, function_id);
                             seen.insert(node_id, depth);
                         }
                         ItemRibKind | MethodRibKind => {
@@ -3113,7 +3117,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                     }
                 }
             }
-            DefTyParam(..) | DefSelfTy(..) => {
+            Def::TyParam(..) | Def::SelfTy(..) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
@@ -3425,9 +3429,10 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
         if allowed == Everything {
             // Look for a field with the same name in the current self_type.
             match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
-                Some(DefTy(did, _)) |
-                Some(DefStruct(did)) |
-                Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
+                Some(Def::Enum(did)) |
+                Some(Def::TyAlias(did)) |
+                Some(Def::Struct(did)) |
+                Some(Def::Variant(_, did)) => match self.structs.get(&did) {
                     None => {}
                     Some(fields) => {
                         if fields.iter().any(|&field_name| name == field_name) {
@@ -3444,7 +3449,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
         // Look for a method in the current self type's impl module.
         if let Some(module) = get_module(self, path.span, &name_path) {
             if let Some(binding) = module.children.borrow().get(&name) {
-                if let Some(DefMethod(did)) = binding.value_ns.def() {
+                if let Some(Def::Method(did)) = binding.value_ns.def() {
                     if is_static_method(self, did) {
                         return StaticMethod(path_names_to_string(&path, 0));
                     }
@@ -3518,7 +3523,13 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 // scopes looking for it.
                 if let Some(path_res) = resolution {
                     // Check if struct variant
-                    if let DefVariant(_, _, true) = path_res.base_def {
+                    let is_struct_variant = if let Def::Variant(_, variant_id) = path_res.base_def {
+                        self.structs.contains_key(&variant_id)
+                    } else {
+                        false
+                    };
+                    if is_struct_variant {
+                        let _ = self.structs.contains_key(&path_res.base_def.def_id());
                         let path_name = path_names_to_string(path, 0);
 
                         let mut err = resolve_struct_error(self,
@@ -3561,7 +3572,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
                     self.record_def(expr.id, err_path_resolution());
                     match type_res.map(|r| r.base_def) {
-                        Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
+                        Some(Def::Struct(..)) => {
                             let mut err = resolve_struct_error(self,
                                 expr.span,
                                 ResolutionError::StructVariantUsedAsFunction(&*path_name));
@@ -3673,7 +3684,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
             ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
                 self.with_label_rib(|this| {
-                    let def_like = DlDef(DefLabel(expr.id));
+                    let def_like = DlDef(Def::Label(expr.id));
 
                     {
                         let rib = this.label_ribs.last_mut().unwrap();
@@ -3692,7 +3703,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                       label.span,
                                       ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
                     }
-                    Some(DlDef(def @ DefLabel(_))) => {
+                    Some(DlDef(def @ Def::Label(_))) => {
                         // Since this def is a label, it is never read.
                         self.record_def(expr.id,
                                         PathResolution {
@@ -3768,7 +3779,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                         None => continue,
                     };
                     let trait_def_id = match def {
-                        DefTrait(trait_def_id) => trait_def_id,
+                        Def::Trait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
                     if self.trait_item_map.contains_key(&(name, trait_def_id)) {
@@ -3784,7 +3795,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                     Some(ref target) => target,
                 };
                 let did = match target.binding.def() {
-                    Some(DefTrait(trait_def_id)) => trait_def_id,
+                    Some(Def::Trait(trait_def_id)) => trait_def_id,
                     Some(..) | None => continue,
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
@@ -3939,7 +3950,7 @@ fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
 
 fn err_path_resolution() -> PathResolution {
     PathResolution {
-        base_def: DefErr,
+        base_def: Def::Err,
         last_private: LastMod(AllPublic),
         depth: 0,
     }
index abaf45cb1704d0abcf2ecf756f9306e2673b277d..7df71fadd89f2b015b623bd8fc26628c2ccc87bb 100644 (file)
@@ -852,7 +852,7 @@ fn resolve_glob_import(&mut self,
         if let Some(did) = target_module.def_id() {
             self.resolver.def_map.borrow_mut().insert(id,
                                                       PathResolution {
-                                                          base_def: DefMod(did),
+                                                          base_def: Def::Mod(did),
                                                           last_private: lp,
                                                           depth: 0,
                                                       });
index ec1383f1f7b2b19ac8b40dc4db49d3e801096b13..6aabf51a9ed9f10b44e7561f0331873c0bee4735 100644 (file)
@@ -490,7 +490,10 @@ pub fn filename_for_input(sess: &Session,
                                                 suffix))
         }
         config::CrateTypeStaticlib => {
-            outputs.out_directory.join(&format!("lib{}.a", libname))
+            let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
+                                    &sess.target.target.options.staticlib_suffix);
+            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
+                                                suffix))
         }
         config::CrateTypeExecutable => {
             let suffix = &sess.target.target.options.exe_suffix;
index f585c65228a825116d0e402eeb7b42f97f74d0c5..9c445737b10eefa01ea58705f216d6095658a3d4 100644 (file)
@@ -210,7 +210,14 @@ impl<'a> Linker for MsvcLinker<'a> {
     fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
     fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
-    fn build_dylib(&mut self, _out_filename: &Path) { self.cmd.arg("/DLL"); }
+
+    fn build_dylib(&mut self, out_filename: &Path) {
+        self.cmd.arg("/DLL");
+        let mut arg: OsString = "/IMPLIB:".into();
+        arg.push(out_filename.with_extension("dll.lib"));
+        self.cmd.arg(arg);
+    }
+
     fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); }
 
     fn link_dylib(&mut self, lib: &str) {
@@ -222,7 +229,7 @@ fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
         // `foo.lib` file if the dll doesn't actually export any symbols, so we
         // check to see if the file is there and just omit linking to it if it's
         // not present.
-        let name = format!("{}.lib", lib);
+        let name = format!("{}.dll.lib", lib);
         if fs::metadata(&path.join(&name)).is_ok() {
             self.cmd.arg(name);
         }
index c34013a7bbbb1b56d8955e44954e748ec32ba02d..b109353fac0bf598a6b260d77580489659c91ef4 100644 (file)
@@ -32,7 +32,7 @@
 
 use session::Session;
 
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::ty;
 
@@ -239,8 +239,8 @@ fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(..) => None,
-            def::DefSelfTy(..) => None,
+            Def::PrimTy(..) => None,
+            Def::SelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
@@ -254,27 +254,28 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
         }
         let def = def_map.get(&ref_id).unwrap().full_def();
         match def {
-            def::DefMod(_) |
-            def::DefForeignMod(_) => Some(recorder::ModRef),
-            def::DefStruct(_) => Some(recorder::TypeRef),
-            def::DefTy(..) |
-            def::DefAssociatedTy(..) |
-            def::DefTrait(_) => Some(recorder::TypeRef),
-            def::DefStatic(_, _) |
-            def::DefConst(_) |
-            def::DefAssociatedConst(..) |
-            def::DefLocal(..) |
-            def::DefVariant(_, _, _) |
-            def::DefUpvar(..) => Some(recorder::VarRef),
-
-            def::DefFn(..) => Some(recorder::FnRef),
-
-            def::DefSelfTy(..) |
-            def::DefLabel(_) |
-            def::DefTyParam(..) |
-            def::DefMethod(..) |
-            def::DefPrimTy(_) |
-            def::DefErr => {
+            Def::Mod(_) |
+            Def::ForeignMod(_) => Some(recorder::ModRef),
+            Def::Struct(..) => Some(recorder::TypeRef),
+            Def::Enum(..) |
+            Def::TyAlias(..) |
+            Def::AssociatedTy(..) |
+            Def::Trait(_) => Some(recorder::TypeRef),
+            Def::Static(_, _) |
+            Def::Const(_) |
+            Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Variant(..) |
+            Def::Upvar(..) => Some(recorder::VarRef),
+
+            Def::Fn(..) => Some(recorder::FnRef),
+
+            Def::SelfTy(..) |
+            Def::Label(_) |
+            Def::TyParam(..) |
+            Def::Method(..) |
+            Def::PrimTy(_) |
+            Def::Err => {
                 self.sess.span_bug(span,
                                    &format!("lookup_def_kind for unexpected item: {:?}", def));
             }
@@ -679,7 +680,7 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
         let def_map = self.tcx.def_map.borrow();
         let def = def_map.get(&id).unwrap().full_def();
         match def {
-            def::DefMethod(did) => {
+            Def::Method(did) => {
                 let ti = self.tcx.impl_or_trait_item(did);
                 if let ty::MethodTraitItem(m) = ti {
                     if m.explicit_self == ty::ExplicitSelfCategory::Static {
@@ -687,13 +688,13 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
                     }
                 }
             }
-            def::DefLocal(..) |
-            def::DefStatic(_,_) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefStruct(_) |
-            def::DefVariant(..) |
-            def::DefFn(..) => self.write_sub_paths_truncated(path, false),
+            Def::Local(..) |
+            Def::Static(_,_) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Struct(..) |
+            Def::Variant(..) |
+            Def::Fn(..) => self.write_sub_paths_truncated(path, false),
             _ => {}
         }
     }
@@ -1163,7 +1164,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
             }
             let def = def_map.get(&id).unwrap().full_def();
             match def {
-                def::DefLocal(_, id) => {
+                Def::Local(_, id) => {
                     let value = if immut == ast::MutImmutable {
                         self.span.snippet(p.span).to_string()
                     } else {
@@ -1174,13 +1175,14 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                             "qualified path for local variable def in arm");
                     self.fmt.variable_str(p.span, Some(p.span), id, &path_to_string(p), &value, "")
                 }
-                def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => {
+                Def::Variant(..) | Def::Enum(..) |
+                Def::TyAlias(..) | Def::Struct(..) => {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
-                def::DefStatic(_, _) |
-                def::DefConst(..) |
-                def::DefAssociatedConst(..) => {}
+                Def::Static(_, _) |
+                Def::Const(..) |
+                Def::AssociatedConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
                             def),
             }
index e1343c73acfa90cfbd0db544dd8b4bdbbecc2a51..00554419e649c673e7ccf9adda0ae4c86e387bb3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use middle::ty;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 
 use std::env;
@@ -533,12 +533,12 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
         let def = def_map.get(&id).unwrap().full_def();
         let sub_span = self.span_utils.span_for_last_ident(path.span);
         match def {
-            def::DefUpvar(..) |
-            def::DefLocal(..) |
-            def::DefStatic(..) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefVariant(..) => {
+            Def::Upvar(..) |
+            Def::Local(..) |
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Variant(..) => {
                 Some(Data::VariableRefData(VariableRefData {
                     name: self.span_utils.snippet(sub_span.unwrap()),
                     span: sub_span.unwrap(),
@@ -546,17 +546,18 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                     ref_id: def.def_id(),
                 }))
             }
-            def::DefStruct(def_id) |
-            def::DefTy(def_id, _) |
-            def::DefTrait(def_id) |
-            def::DefTyParam(_, _, def_id, _) => {
+            Def::Struct(def_id) |
+            Def::Enum(def_id) |
+            Def::TyAlias(def_id) |
+            Def::Trait(def_id) |
+            Def::TyParam(_, _, def_id, _) => {
                 Some(Data::TypeRefData(TypeRefData {
                     span: sub_span.unwrap(),
                     ref_id: def_id,
                     scope: self.enclosing_scope(id),
                 }))
             }
-            def::DefMethod(decl_id) => {
+            Def::Method(decl_id) => {
                 let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.impl_or_trait_item(decl_id);
@@ -591,14 +592,14 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                     decl_id: Some(decl_id),
                 }))
             }
-            def::DefFn(def_id, _) => {
+            Def::Fn(def_id) => {
                 Some(Data::FunctionCallData(FunctionCallData {
                     ref_id: def_id,
                     span: sub_span.unwrap(),
                     scope: self.enclosing_scope(id),
                 }))
             }
-            def::DefMod(def_id) => {
+            Def::Mod(def_id) => {
                 Some(Data::ModRefData(ModRefData {
                     ref_id: def_id,
                     span: sub_span.unwrap(),
@@ -651,7 +652,7 @@ fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(_) | def::DefSelfTy(..) => None,
+            Def::PrimTy(_) | Def::SelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
index 6c1a31738afb960d679513a13b14087c20a46671..9a05135b76e3163cfe8bf2763ed4f6fdbc59ca1e 100644 (file)
 use middle::check_match::StaticInliner;
 use middle::check_match;
 use middle::const_eval;
-use middle::def::{self, DefMap};
+use middle::def::{Def, DefMap};
 use middle::def_id::DefId;
 use middle::expr_use_visitor as euv;
 use middle::infer;
@@ -669,7 +669,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // This is either an enum variant or a variable binding.
                 let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
-                    Some(def::DefVariant(enum_id, var_id, _)) => {
+                    Some(Def::Variant(enum_id, var_id)) => {
                         let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
                         Variant(Disr::from(variant.disr_val),
                                 adt::represent_node(bcx, cur.id),
@@ -800,13 +800,13 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: usize) -> bool {
             hir::PatTup(_) => true,
             hir::PatStruct(..) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(def::DefVariant(..)) => false,
+                    Some(Def::Variant(..)) => false,
                     _ => true,
                 }
             }
             hir::PatEnum(..) | hir::PatIdent(_, _, None) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(def::DefStruct(..)) => true,
+                    Some(Def::Struct(..)) => true,
                     _ => false
                 }
             }
@@ -1452,19 +1452,19 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
     let (vid, field) = match discr.node {
         hir::ExprPath(..) => match bcx.def(discr.id) {
-            def::DefLocal(_, vid) | def::DefUpvar(_, vid, _, _) => (vid, None),
+            Def::Local(_, vid) | Def::Upvar(_, vid, _, _) => (vid, None),
             _ => return false
         },
         hir::ExprField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
+                Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::NamedField(field.node)))
         },
         hir::ExprTupField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
+                Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::PositionalField(field.node)))
@@ -1851,7 +1851,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         hir::PatEnum(_, ref sub_pats) => {
             let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
-                Some(def::DefVariant(enum_id, var_id, _)) => {
+                Some(Def::Variant(enum_id, var_id)) => {
                     let repr = adt::represent_node(bcx, pat.id);
                     let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
                     let args = extract_variant_args(bcx,
@@ -1868,7 +1868,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         }
                     }
                 }
-                Some(def::DefStruct(..)) => {
+                Some(Def::Struct(..)) => {
                     match *sub_pats {
                         None => {
                             // This is a unit-like struct. Nothing to do here.
index 59487c0362c89f10d4bdfdb5db6b473b82272d3d..2c11aad8940441638d4b9a1e4c0515d4197fe501 100644 (file)
@@ -956,7 +956,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     assert_eq!(val_ty(ptr), llty.ptr_to());
     let bits = machine::llbitsize_of_real(bcx.ccx(), llty);
     assert!(bits <= 64);
-    let  bits = bits as usize;
+    let bits = bits as usize;
     let mask = Disr(!0u64 >> (64 - bits));
     // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
     // However, that is fine here (it would still represent the full range),
@@ -969,7 +969,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     } else {
         // llvm::ConstantRange can deal with ranges that wrap around,
         // so an overflow on (max + 1) is fine.
-        LoadRangeAssert(bcx, ptr, min, max.wrapping_add(Disr(1)), /* signed: */ True)
+        LoadRangeAssert(bcx, ptr, min.0, max.0.wrapping_add(1), /* signed: */ True)
     }
 }
 
index 3909cb2df23647a70a44faabae1e4a05c590013f..4c619f895de56a987bf8d9a6e8829ae93503e2be 100644 (file)
@@ -1023,11 +1023,11 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) ->
     }
 
     let val = if t.is_bool() {
-        LoadRangeAssert(cx, ptr, Disr(0), Disr(2), llvm::False)
+        LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
     } else if t.is_char() {
         // a char is a Unicode codepoint, and so takes values from 0
         // to 0x10FFFF inclusive only.
-        LoadRangeAssert(cx, ptr, Disr(0), Disr(0x10FFFF + 1), llvm::False)
+        LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
     } else if (t.is_region_ptr() || t.is_unique()) && !common::type_is_fat_ptr(cx.tcx(), t) {
         LoadNonNull(cx, ptr)
     } else {
index 89e58557179529f0a1d456c61d3a8f69f8728101..5a3fcc8d27f3cb8bf422c6d6e8dabc579eb89d66 100644 (file)
@@ -21,7 +21,6 @@
 use trans::builder::Builder;
 use trans::type_::Type;
 use trans::debuginfo::DebugLoc;
-use trans::Disr;
 
 use libc::{c_uint, c_char};
 
@@ -578,8 +577,8 @@ pub fn AtomicLoad(cx: Block, pointer_val: ValueRef, order: AtomicOrdering) -> Va
 }
 
 
-pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: Disr,
-                       hi: Disr, signed: llvm::Bool) -> ValueRef {
+pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: u64,
+                       hi: u64, signed: llvm::Bool) -> ValueRef {
     if cx.unreachable.get() {
         let ccx = cx.fcx.ccx;
         let ty = val_ty(pointer_val);
@@ -592,7 +591,7 @@ pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: Disr,
             llvm::LLVMGetUndef(eltty.to_ref())
         }
     } else {
-        B(cx).load_range_assert(pointer_val, lo.0, hi.0, signed)
+        B(cx).load_range_assert(pointer_val, lo, hi, signed)
     }
 }
 
index c7ec1c0955146ca82182a4593023bba29d16fd51..2651b3576feb27faf9794b39dae0a8880109ea67 100644 (file)
@@ -22,7 +22,7 @@
 use back::link;
 use llvm::{self, ValueRef, get_params};
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::subst;
@@ -133,13 +133,13 @@ fn fn_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, Rvalue>)
     }
 
     fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             def: def::Def,
+                             def: Def,
                              ref_expr: &hir::Expr)
                              -> Callee<'blk, 'tcx> {
         debug!("trans_def(def={:?}, ref_expr={:?})", def, ref_expr);
         let expr_ty = common::node_id_type(bcx, ref_expr.id);
         match def {
-            def::DefFn(did, _) if {
+            Def::Fn(did) if {
                 let maybe_def_id = inline::get_local_instance(bcx.ccx(), did);
                 let maybe_ast_node = maybe_def_id.and_then(|def_id| {
                     let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
@@ -156,7 +156,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     ty: expr_ty
                 }
             }
-            def::DefFn(did, _) if match expr_ty.sty {
+            Def::Fn(did) if match expr_ty.sty {
                 ty::TyBareFn(_, ref f) => f.abi == synabi::RustIntrinsic ||
                                           f.abi == synabi::PlatformIntrinsic,
                 _ => false
@@ -168,11 +168,11 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
                 Callee { bcx: bcx, data: Intrinsic(node_id, substs), ty: expr_ty }
             }
-            def::DefFn(did, _) => {
+            Def::Fn(did) => {
                 fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
                                             bcx.fcx.param_substs))
             }
-            def::DefMethod(meth_did) => {
+            Def::Method(meth_did) => {
                 let method_item = bcx.tcx().impl_or_trait_item(meth_did);
                 let fn_datum = match method_item.container() {
                     ty::ImplContainer(_) => {
@@ -190,7 +190,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 };
                 fn_callee(bcx, fn_datum)
             }
-            def::DefVariant(tid, vid, _) => {
+            Def::Variant(tid, vid) => {
                 let vinfo = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
                 assert_eq!(vinfo.kind(), ty::VariantKind::Tuple);
 
@@ -200,24 +200,24 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     ty: expr_ty
                 }
             }
-            def::DefStruct(_) => {
+            Def::Struct(..) => {
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(Disr(0)),
                     ty: expr_ty
                 }
             }
-            def::DefStatic(..) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefLocal(..) |
-            def::DefUpvar(..) => {
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Upvar(..) => {
                 datum_callee(bcx, ref_expr)
             }
-            def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
-            def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
-            def::DefLabel(..) | def::DefTyParam(..) |
-            def::DefSelfTy(..) | def::DefErr => {
+            Def::Mod(..) | Def::ForeignMod(..) | Def::Trait(..) |
+            Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(..) |
+            Def::AssociatedTy(..) | Def::Label(..) | Def::TyParam(..) |
+            Def::SelfTy(..) | Def::Err => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     &format!("cannot translate def {:?} \
index b73e5ff3e038eb493f1d88f958a16bd533726648..6c03916af6c5de7d3923c863d7920533f6567ecf 100644 (file)
@@ -19,7 +19,7 @@
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind};
 use llvm::{True, False, Bool};
 use middle::cfg;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::lang_items::LangItem;
@@ -184,7 +184,7 @@ pub struct VariantInfo<'tcx> {
 impl<'tcx> VariantInfo<'tcx> {
     pub fn from_ty(tcx: &ty::ctxt<'tcx>,
                    ty: Ty<'tcx>,
-                   opt_def: Option<def::Def>)
+                   opt_def: Option<Def>)
                    -> Self
     {
         match ty.sty {
@@ -627,7 +627,7 @@ pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
         self.tcx().map.node_to_string(id).to_string()
     }
 
-    pub fn def(&self, nid: ast::NodeId) -> def::Def {
+    pub fn def(&self, nid: ast::NodeId) -> Def {
         match self.tcx().def_map.borrow().get(&nid) {
             Some(v) => v.full_def(),
             None => {
index 0fc879707331df7b2bc62e8f1d4495881970e9c3..0f5d8dbd94db01f2275e2a5ad6b2556bbfc4976e 100644 (file)
@@ -13,7 +13,7 @@
 use llvm;
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
-use middle::{check_const, def};
+use middle::const_qualif::ConstQualif;
 use middle::cstore::LOCAL_CRATE;
 use middle::const_eval::{self, ConstVal, ConstEvalErr};
 use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg};
@@ -26,6 +26,7 @@
 use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
 use middle::const_eval::EvalHint::ExprTypeChecked;
 use middle::const_eval::eval_const_expr_partial;
+use middle::def::Def;
 use middle::def_id::DefId;
 use trans::{adt, closure, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
@@ -273,8 +274,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            -> Result<ValueRef, ConstEvalFailure> {
     let expr = get_const_expr(ccx, def_id, ref_expr, param_substs);
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-    match get_const_expr_as_global(ccx, expr, check_const::ConstQualif::empty(),
-                                   empty_substs, TrueConst::Yes) {
+    match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
         Err(Runtime(err)) => {
             ccx.tcx().sess.span_err(expr.span, &err.description());
             Err(Compiletime(err))
@@ -285,7 +285,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           expr: &hir::Expr,
-                                          qualif: check_const::ConstQualif,
+                                          qualif: ConstQualif,
                                           param_substs: &'tcx Substs<'tcx>,
                                           trueconst: TrueConst)
                                           -> Result<ValueRef, ConstEvalFailure> {
@@ -297,7 +297,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // of just to get the `def` value
         let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
         match def {
-            def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+            Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
                     debug!("get_const_expr_as_global ({:?}): found const {:?}",
                            expr.id, def_id);
@@ -314,7 +314,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
     let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
                                               &ccx.tcx().expr_ty(expr));
-    let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
+    let val = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
         // Avoid autorefs as they would create global instead of stack
         // references, even when only the latter are correct.
         try!(const_expr_unadjusted(ccx, expr, ty, param_substs, None, trueconst))
@@ -792,7 +792,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
             let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
-            if let Some(def::DefStatic(def_id, _)) = opt_def {
+            if let Some(Def::Static(def_id, _)) = opt_def {
                 common::get_static_val(cx, def_id, ety)
             } else {
                 // If this isn't the address of a static, then keep going through
@@ -881,20 +881,20 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprPath(..) => {
             let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
-                def::DefLocal(_, id) => {
+                Def::Local(_, id) => {
                     if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
                         val
                     } else {
                         cx.sess().span_bug(e.span, "const fn argument not found")
                     }
                 }
-                def::DefFn(..) | def::DefMethod(..) => {
+                Def::Fn(..) | Def::Method(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
-                def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+                Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                     const_deref_ptr(cx, try!(get_const_val(cx, def_id, e, param_substs)))
                 }
-                def::DefVariant(enum_did, variant_did, _) => {
+                Def::Variant(enum_did, variant_did) => {
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
                     match vinfo.kind() {
                         ty::VariantKind::Unit => {
@@ -909,7 +909,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         }
                     }
                 }
-                def::DefStruct(_) => {
+                Def::Struct(..) => {
                     if let ty::TyBareFn(..) = ety.sty {
                         // Tuple struct.
                         expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@@ -938,7 +938,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
             let arg_vals = try!(map_list(args));
             match def {
-                def::DefFn(did, _) | def::DefMethod(did) => {
+                Def::Fn(did) | Def::Method(did) => {
                     try!(const_fn_call(
                         cx,
                         ExprId(callee.id),
@@ -948,7 +948,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         trueconst,
                     ))
                 }
-                def::DefStruct(_) => {
+                Def::Struct(..) => {
                     if ety.is_simd() {
                         C_vector(&arg_vals[..])
                     } else {
@@ -956,7 +956,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         adt::trans_const(cx, &*repr, Disr(0), &arg_vals[..])
                     }
                 }
-                def::DefVariant(enum_did, variant_did, _) => {
+                Def::Variant(enum_did, variant_did) => {
                     let repr = adt::represent_type(cx, ety);
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
                     adt::trans_const(cx,
index 45f46410068beb711ed45cd1e70f9428238b26ca..fc3bd4f4d02330de8d693f339bb33b713d05849c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use middle::def;
+use middle::def::Def;
 use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
 use trans::base::*;
 use trans::basic_block::BasicBlock;
@@ -322,7 +322,7 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => fcx.top_loop_scope(),
         Some(_) => {
             match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def())  {
-                Some(def::DefLabel(loop_id)) => loop_id,
+                Some(Def::Label(loop_id)) => loop_id,
                 r => {
                     bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
                 }
index ab2f4462757d57529e43c414c5781e923edc6301..ada37c5d8dfbecc4d8316447ca65759f55630f12 100644 (file)
@@ -53,8 +53,8 @@
 
 use back::abi;
 use llvm::{self, ValueRef, TypeKind};
-use middle::check_const;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::Def;
 use middle::lang_items::CoerceUnsizedTraitLangItem;
 use middle::subst::{Substs, VecPerParamSpace};
 use middle::traits;
@@ -128,11 +128,8 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    if !qualif.intersects(
-        check_const::ConstQualif::NOT_CONST |
-        check_const::ConstQualif::NEEDS_DROP
-    ) {
-        if !qualif.intersects(check_const::ConstQualif::PREFER_IN_PLACE) {
+    if !qualif.intersects(ConstQualif::NOT_CONST | ConstQualif::NEEDS_DROP) {
+        if !qualif.intersects(ConstQualif::PREFER_IN_PLACE) {
             if let SaveIn(lldest) = dest {
                 match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                        bcx.fcx.param_substs,
@@ -165,7 +162,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match expr.node {
                 hir::ExprPath(..) => {
                     match bcx.def(expr.id) {
-                        def::DefConst(did) => {
+                        Def::Const(did) => {
                             let empty_substs = bcx.tcx().mk_substs(Substs::trans_empty());
                             let const_expr = consts::get_const_expr(bcx.ccx(), did, expr,
                                                                     empty_substs);
@@ -231,16 +228,13 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut bcx = bcx;
     let fcx = bcx.fcx;
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
-    let global = if !qualif.intersects(
-        check_const::ConstQualif::NOT_CONST |
-        check_const::ConstQualif::NEEDS_DROP
-    ) {
+    let adjusted_global = !qualif.intersects(ConstQualif::NON_STATIC_BORROWS);
+    let global = if !qualif.intersects(ConstQualif::NOT_CONST | ConstQualif::NEEDS_DROP) {
         match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                             bcx.fcx.param_substs,
                                                             consts::TrueConst::No) {
             Ok(global) => {
-                if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
+                if qualif.intersects(ConstQualif::HAS_STATIC_BORROWS) {
                     // Is borrowed as 'static, must return lvalue.
 
                     // Cast pointer to global, because constants have different types.
@@ -903,25 +897,25 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                          ref_expr: &hir::Expr,
-                         def: def::Def)
+                         def: Def)
                          -> DatumBlock<'blk, 'tcx, Expr> {
     //! Translates a reference to a path.
 
     let _icx = push_ctxt("trans_def_lvalue");
     match def {
-        def::DefFn(..) | def::DefMethod(..) |
-        def::DefStruct(_) | def::DefVariant(..) => {
+        Def::Fn(..) | Def::Method(..) |
+        Def::Struct(..) | Def::Variant(..) => {
             let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
                                                 bcx.fcx.param_substs);
             DatumBlock::new(bcx, datum.to_expr_datum())
         }
-        def::DefStatic(did, _) => {
+        Def::Static(did, _) => {
             let const_ty = expr_ty(bcx, ref_expr);
             let val = get_static_val(bcx.ccx(), did, const_ty);
             let lval = Lvalue::new("expr::trans_def");
             DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr(lval)))
         }
-        def::DefConst(_) => {
+        Def::Const(_) => {
             bcx.sess().span_bug(ref_expr.span,
                 "constant expression should not reach expr::trans_def")
         }
@@ -1272,7 +1266,7 @@ fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
 
 fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         ref_expr: &hir::Expr,
-                                        def: def::Def,
+                                        def: Def,
                                         dest: Dest)
                                         -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_def_dps_unadjusted");
@@ -1283,7 +1277,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     match def {
-        def::DefVariant(tid, vid, _) => {
+        Def::Variant(tid, vid) => {
             let variant = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
             if let ty::VariantKind::Tuple = variant.kind() {
                 // N-ary variant.
@@ -1300,7 +1294,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 return bcx;
             }
         }
-        def::DefStruct(_) => {
+        Def::Struct(..) => {
             let ty = expr_ty(bcx, ref_expr);
             match ty.sty {
                 ty::TyStruct(def, _) if def.has_dtor() => {
@@ -1321,17 +1315,17 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                          ref_expr: &hir::Expr,
-                                         def: def::Def,
+                                         def: Def,
                                          param_substs: &'tcx Substs<'tcx>)
                                          -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
     match def {
-        def::DefFn(did, _) |
-        def::DefStruct(did) | def::DefVariant(_, did, _) => {
+        Def::Fn(did) |
+        Def::Struct(did) | Def::Variant(_, did) => {
             callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
-        def::DefMethod(method_did) => {
+        Def::Method(method_did) => {
             match ccx.tcx().impl_or_trait_item(method_did).container() {
                 ty::ImplContainer(_) => {
                     callee::trans_fn_ref(ccx, method_did,
@@ -1356,12 +1350,12 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 /// Translates a reference to a local variable or argument. This always results in an lvalue datum.
 pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   def: def::Def)
+                                   def: Def)
                                    -> Datum<'tcx, Lvalue> {
     let _icx = push_ctxt("trans_local_var");
 
     match def {
-        def::DefUpvar(_, nid, _, _) => {
+        Def::Upvar(_, nid, _, _) => {
             // Can't move upvars, so this is never a ZeroMemLastUse.
             let local_ty = node_id_type(bcx, nid);
             let lval = Lvalue::new_with_hint("expr::trans_local_var (upvar)",
@@ -1375,7 +1369,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        def::DefLocal(_, nid) => {
+        Def::Local(_, nid) => {
             let datum = match bcx.fcx.lllocals.borrow().get(&nid) {
                 Some(&v) => v,
                 None => {
@@ -2587,7 +2581,7 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
     match expr.node {
         hir::ExprPath(..) => {
             match tcx.resolve_expr(expr) {
-                def::DefStruct(_) | def::DefVariant(..) => {
+                Def::Struct(..) | Def::Variant(..) => {
                     if let ty::TyBareFn(..) = tcx.node_id_to_type(expr.id).sty {
                         // ctor function
                         ExprKind::RvalueDatum
@@ -2596,24 +2590,18 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
                     }
                 }
 
-                // Special case: A unit like struct's constructor must be called without () at the
-                // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
-                // of unit structs this is should not be interpreted as function pointer but as
-                // call to the constructor.
-                def::DefFn(_, true) => ExprKind::RvalueDps,
-
                 // Fn pointers are just scalar values.
-                def::DefFn(..) | def::DefMethod(..) => ExprKind::RvalueDatum,
+                Def::Fn(..) | Def::Method(..) => ExprKind::RvalueDatum,
 
                 // Note: there is actually a good case to be made that
                 // DefArg's, particularly those of immediate type, ought to
                 // considered rvalues.
-                def::DefStatic(..) |
-                def::DefUpvar(..) |
-                def::DefLocal(..) => ExprKind::Lvalue,
+                Def::Static(..) |
+                Def::Upvar(..) |
+                Def::Local(..) => ExprKind::Lvalue,
 
-                def::DefConst(..) |
-                def::DefAssociatedConst(..) => ExprKind::RvalueDatum,
+                Def::Const(..) |
+                Def::AssociatedConst(..) => ExprKind::RvalueDatum,
 
                 def => {
                     tcx.sess.span_bug(
index 217310d6610b70b488f841be4826f4e8e6d74ebd..b1f62477bb7672ef059e655f98ba78eaf1c9bfa4 100644 (file)
@@ -27,7 +27,6 @@
 use trans::type_::Type;
 use trans::type_of::*;
 use trans::type_of;
-use trans::Disr;
 use middle::infer;
 use middle::ty::{self, Ty};
 use middle::subst::Substs;
@@ -335,7 +334,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             llarg_rust
         } else {
             if passed_arg_tys[i].is_bool() {
-                let val = LoadRangeAssert(bcx, llarg_rust, Disr(0), Disr(2), llvm::False);
+                let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, llvm::False);
                 Trunc(bcx, val, Type::i1(bcx.ccx()))
             } else {
                 Load(bcx, llarg_rust)
index 5446bbda4c26dbe64534d507e731ce450ea29900..852f08a0d343c84b8f295c67c7be840eddc16ecf 100644 (file)
@@ -9,13 +9,16 @@
 // except according to those terms.
 
 use llvm::{BasicBlockRef, ValueRef};
+use rustc::middle::ty;
 use rustc::mir::repr as mir;
+use syntax::abi::Abi;
 use trans::adt;
+use trans::attributes;
 use trans::base;
 use trans::build;
-use trans::attributes;
 use trans::common::{self, Block};
 use trans::debuginfo::DebugLoc;
+use trans::foreign;
 use trans::type_of;
 use trans::type_::Type;
 use trans::Disr;
@@ -57,7 +60,6 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                 // The else branch of the Switch can't be hit, so branch to an unreachable
                 // instruction so LLVM knows that
                 let unreachable_blk = self.unreachable_block();
-
                 let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len());
                 assert_eq!(adt_def.variants.len(), targets.len());
                 for (adt_variant, target) in adt_def.variants.iter().zip(targets) {
@@ -98,12 +100,24 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                 let debugloc = DebugLoc::None;
                 // The arguments we'll be passing. Plus one to account for outptr, if used.
                 let mut llargs = Vec::with_capacity(args.len() + 1);
+                // Types of the arguments. We do not preallocate, because this vector is only
+                // filled when `is_foreign` is `true` and foreign calls are minority of the cases.
+                let mut arg_tys = Vec::new();
+
+                // Foreign-ABI functions are translated differently
+                let is_foreign = if let ty::TyBareFn(_, ref f) = callee.ty.sty {
+                    // We do not translate intrinsics here (they shouldn’t be functions)
+                    assert!(f.abi != Abi::RustIntrinsic && f.abi != Abi::PlatformIntrinsic);
+                    f.abi != Abi::Rust && f.abi != Abi::RustCall
+                } else {
+                    false
+                };
 
                 // Prepare the return value destination
                 let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
                     let dest = self.trans_lvalue(bcx, d);
                     let ret_ty = dest.ty.to_ty(bcx.tcx());
-                    if type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
+                    if !is_foreign && type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
                         llargs.push(dest.llval);
                         (Some((dest, ret_ty)), false)
                     } else {
@@ -115,30 +129,35 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
 
                 // Process the rest of the args.
                 for arg in args {
-                    match self.trans_operand(bcx, arg).val {
+                    let operand = self.trans_operand(bcx, arg);
+                    match operand.val {
                         Ref(llval) | Immediate(llval) => llargs.push(llval),
                         FatPtr(b, e) => {
                             llargs.push(b);
                             llargs.push(e);
                         }
                     }
+                    if is_foreign {
+                        arg_tys.push(operand.ty);
+                    }
                 }
 
                 // Many different ways to call a function handled here
-                match (base::avoid_invoke(bcx), kind) {
+                match (is_foreign, base::avoid_invoke(bcx), kind) {
                     // The two cases below are the only ones to use LLVM’s `invoke`.
-                    (false, &mir::CallKind::DivergingCleanup(cleanup)) => {
+                    (false, false, &mir::CallKind::DivergingCleanup(cleanup)) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
+                        let unreachable_blk = self.unreachable_block();
                         build::Invoke(bcx,
                                       callee.immediate(),
                                       &llargs[..],
-                                      self.unreachable_block().llbb,
+                                      unreachable_blk.llbb,
                                       landingpad.llbb,
                                       Some(attrs),
                                       debugloc);
                     },
-                    (false, &mir::CallKind::ConvergingCleanup { ref targets, .. }) => {
+                    (false, false, &mir::CallKind::ConvergingCleanup { ref targets, .. }) => {
                         let cleanup = self.bcx(targets.1);
                         let landingpad = self.make_landing_pad(cleanup);
                         let (target, postinvoke) = if must_copy_dest {
@@ -184,14 +203,14 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                             build::Br(target, postinvoketarget.llbb, debugloc);
                         }
                     },
-                    (_, &mir::CallKind::DivergingCleanup(_)) |
-                    (_, &mir::CallKind::Diverging) => {
+                    (false, _, &mir::CallKind::DivergingCleanup(_)) |
+                    (false, _, &mir::CallKind::Diverging) => {
                         build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
                         build::Unreachable(bcx);
                     }
-                    (_, k@&mir::CallKind::ConvergingCleanup { .. }) |
-                    (_, k@&mir::CallKind::Converging { .. }) => {
-                        // Bug #20046
+                    (false, _, k@&mir::CallKind::ConvergingCleanup { .. }) |
+                    (false, _, k@&mir::CallKind::Converging { .. }) => {
+                        // FIXME: Bug #20046
                         let target = match *k {
                             mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
                             mir::CallKind::Converging { target, .. } => target,
@@ -209,6 +228,25 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                         }
                         build::Br(bcx, self.llblock(target), debugloc);
                     }
+                    // Foreign functions
+                    (true, _, k) => {
+                        let (dest, _) = ret_dest_ty
+                            .expect("return destination is not set");
+                        bcx = foreign::trans_native_call(bcx,
+                                                   callee.ty,
+                                                   callee.immediate(),
+                                                   dest.llval,
+                                                   &llargs[..],
+                                                   arg_tys,
+                                                   debugloc);
+                        match *k {
+                            mir::CallKind::ConvergingCleanup { targets, .. } =>
+                                build::Br(bcx, self.llblock(targets.0), debugloc),
+                            mir::CallKind::Converging { target, .. } =>
+                                build::Br(bcx, self.llblock(target), debugloc),
+                            _ => ()
+                        };
+                    },
                 }
             }
         }
index 98effeefad2a74fa9aaba4cc421683248c295368..da4265dda54d7867b0db55fa47138a3f7c95ff0b 100644 (file)
@@ -51,7 +51,7 @@
 use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
 use middle::const_eval::{self, ConstVal};
 use middle::const_eval::EvalHint::UncheckedExprHint;
-use middle::def;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use middle::privacy::{AllPublic, LastMod};
@@ -718,8 +718,8 @@ pub fn instantiate_mono_trait_ref<'tcx>(
 fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId {
     let path = &trait_ref.path;
     match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
-        def::DefTrait(trait_def_id) => trait_def_id,
-        def::DefErr => {
+        Def::Trait(trait_def_id) => trait_def_id,
+        Def::Err => {
             this.tcx().sess.fatal("cannot continue compilation due to previous error");
         }
         _ => {
@@ -1028,7 +1028,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                 _ => None
             };
             match def {
-                Some(def::DefTrait(trait_def_id)) => {
+                Some(Def::Trait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
                     let trait_ref = object_path_to_poly_trait_ref(this,
                                                                   rscope,
@@ -1263,9 +1263,9 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    span: Span,
                                    ty: Ty<'tcx>,
-                                   ty_path_def: def::Def,
+                                   ty_path_def: Def,
                                    item_segment: &hir::PathSegment)
-                                   -> (Ty<'tcx>, def::Def)
+                                   -> (Ty<'tcx>, Def)
 {
     let tcx = this.tcx();
     let assoc_name = item_segment.identifier.name;
@@ -1277,7 +1277,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     // Find the type of the associated item, and the trait where the associated
     // item is declared.
     let bound = match (&ty.sty, ty_path_def) {
-        (_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => {
+        (_, Def::SelfTy(Some(trait_did), Some((impl_id, _)))) => {
             // `Self` in an impl of a trait - we have a concrete self type and a
             // trait reference.
             let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
@@ -1306,7 +1306,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
-        (&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => {
+        (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
             let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
             match find_bound_for_assoc_item(this,
                                             trait_node_id,
@@ -1317,7 +1317,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
-        (&ty::TyParam(_), def::DefTyParam(_, _, param_did, param_name)) => {
+        (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
             let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
             match find_bound_for_assoc_item(this,
                                             param_node_id,
@@ -1359,7 +1359,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         item.expect("missing associated type").def_id()
     };
 
-    (ty, def::DefAssociatedTy(trait_did, item_did))
+    (ty, Def::AssociatedTy(trait_did, item_did))
 }
 
 fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
@@ -1443,14 +1443,14 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                         rscope: &RegionScope,
                         span: Span,
                         param_mode: PathParamMode,
-                        def: &def::Def,
+                        def: &Def,
                         opt_self_ty: Option<Ty<'tcx>>,
                         base_segments: &[hir::PathSegment])
                         -> Ty<'tcx> {
     let tcx = this.tcx();
 
     match *def {
-        def::DefTrait(trait_def_id) => {
+        Def::Trait(trait_def_id) => {
             // N.B. this case overlaps somewhat with
             // TyObjectSum, see that fn for details
             let mut projection_bounds = Vec::new();
@@ -1471,7 +1471,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                      projection_bounds,
                                      &[])
         }
-        def::DefTy(did, _) | def::DefStruct(did) => {
+        Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
             prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
             ast_path_to_ty(this,
                            rscope,
@@ -1480,11 +1480,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                            did,
                            base_segments.last().unwrap())
         }
-        def::DefTyParam(space, index, _, name) => {
+        Def::TyParam(space, index, _, name) => {
             prohibit_type_params(tcx, base_segments);
             tcx.mk_param(space, index, name)
         }
-        def::DefSelfTy(_, Some((_, self_ty_id))) => {
+        Def::SelfTy(_, Some((_, self_ty_id))) => {
             // Self in impl (we know the concrete type).
             prohibit_type_params(tcx, base_segments);
             if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
@@ -1497,12 +1497,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 tcx.sess.span_bug(span, "self type has not been fully resolved")
             }
         }
-        def::DefSelfTy(Some(_), None) => {
+        Def::SelfTy(Some(_), None) => {
             // Self in trait.
             prohibit_type_params(tcx, base_segments);
             tcx.mk_self_type()
         }
-        def::DefAssociatedTy(trait_did, _) => {
+        Def::AssociatedTy(trait_did, _) => {
             prohibit_type_params(tcx, &base_segments[..base_segments.len()-2]);
             qpath_to_ty(this,
                         rscope,
@@ -1513,7 +1513,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                         &base_segments[base_segments.len()-2],
                         base_segments.last().unwrap())
         }
-        def::DefMod(id) => {
+        Def::Mod(id) => {
             // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
             // FIXME(#22519) This part of the resolution logic should be
             // avoided entirely for that form, once we stop needed a Def
@@ -1534,10 +1534,10 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 
             opt_self_ty.expect("missing T in <T>::a::b::c")
         }
-        def::DefPrimTy(prim_ty) => {
+        Def::PrimTy(prim_ty) => {
             prim_ty_to_ty(tcx, base_segments, prim_ty)
         }
-        def::DefErr => {
+        Def::Err => {
             return this.tcx().types.err;
         }
         _ => {
@@ -1556,7 +1556,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                         rscope: &RegionScope,
                                         span: Span,
                                         param_mode: PathParamMode,
-                                        def: &def::Def,
+                                        def: &Def,
                                         opt_self_ty: Option<Ty<'tcx>>,
                                         base_segments: &[hir::PathSegment],
                                         assoc_segments: &[hir::PathSegment])
@@ -1658,7 +1658,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
+                    base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -2177,7 +2177,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
         match *ast_bound {
             hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
                 match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
-                    def::DefTrait(trait_did) => {
+                    Def::Trait(trait_did) => {
                         if tcx.try_add_builtin_trait(trait_did,
                                                      &mut builtin_bounds) {
                             let segments = &b.trait_ref.path.segments;
index dfa144699b217ad0a6ec540dbf96f096ca41dccc..c43349f88104dd149522bcc6ee8f994db4cf2a54 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::def;
+use middle::def::{self, Def};
 use middle::infer::{self, TypeOrigin};
 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
 use middle::pat_util::pat_is_resolved_const;
@@ -214,7 +214,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         hir::PatQPath(ref qself, ref path) => {
             let self_ty = fcx.to_ty(&qself.ty);
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
-                if d.base_def == def::DefErr {
+                if d.base_def == Def::Err {
                     fcx.write_error(pat.id);
                     return;
                 }
@@ -223,7 +223,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 // This is just a sentinel for finish_resolving_def_to_ty.
                 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
                 def::PathResolution {
-                    base_def: def::DefMod(sentinel),
+                    base_def: Def::Mod(sentinel),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -410,10 +410,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     // subtyping.
 }
 
-fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool {
+fn check_assoc_item_is_const(pcx: &pat_ctxt, def: Def, span: Span) -> bool {
     match def {
-        def::DefAssociatedConst(..) => true,
-        def::DefMethod(..) => {
+        Def::AssociatedConst(..) => true,
+        Def::Method(..) => {
             span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
                       "associated items in match patterns must be constants");
             false
@@ -616,7 +616,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let tcx = pcx.fcx.ccx.tcx;
 
     let path_res = match tcx.def_map.borrow().get(&pat.id) {
-        Some(&path_res) if path_res.base_def != def::DefErr => path_res,
+        Some(&path_res) if path_res.base_def != Def::Err => path_res,
         _ => {
             fcx.write_error(pat.id);
 
@@ -693,10 +693,12 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     let real_path_ty = fcx.node_ty(pat.id);
     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
-        ty::TyEnum(enum_def, expected_substs)
-            if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
-        {
+        ty::TyEnum(enum_def, expected_substs) => {
             let variant = enum_def.variant_of_def(def);
+            if variant.kind() == ty::VariantKind::Struct {
+                report_bad_struct_kind(false);
+                return;
+            }
             if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
                 // Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
                 // is allowed for backward compatibility.
index a1b378d84d0010faf8f9a1fbbb3a4c1c612d748f..84c436c59c1d29b35b3b9137ff1a606d9db96a0d 100644 (file)
@@ -26,7 +26,7 @@
 
 use CrateCtxt;
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::ty::{self, LvaluePreference, Ty};
@@ -236,7 +236,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             if let hir::ExprCall(ref expr, _) = call_expr.node {
                 let tcx = fcx.tcx();
                 if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
-                    if pr.depth == 0 && pr.base_def != def::DefErr {
+                    if pr.depth == 0 && pr.base_def != Def::Err {
                         if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
                             err.span_note(span, "defined here");
                         }
index d462e2b45b28121d44d85cfe1d200197c2331834..fc2dd4475e3ffabf135a56b5fb95ac42b8427a70 100644 (file)
@@ -12,7 +12,7 @@
 
 use astconv::AstConv;
 use check::FnCtxt;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
 use middle::subst;
@@ -334,7 +334,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               method_name: ast::Name,
                               self_ty: ty::Ty<'tcx>,
                               expr_id: ast::NodeId)
-                              -> Result<(def::Def, LastPrivate), MethodError<'tcx>>
+                              -> Result<(Def, LastPrivate), MethodError<'tcx>>
 {
     let mode = probe::Mode::Path;
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
@@ -346,8 +346,8 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
     }
     let def_result = match pick.item {
-        ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id),
-        ty::ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id),
+        ty::ImplOrTraitItem::MethodTraitItem(..) => Def::Method(def_id),
+        ty::ImplOrTraitItem::ConstTraitItem(..) => Def::AssociatedConst(def_id),
         ty::ImplOrTraitItem::TypeTraitItem(..) => {
             fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type");
         }
index 560e84b52d1d6966a8e2ee9fd70ff9703ce0632a..21bf67d2d5c7529e911c0d9d4832bfe675d64410 100644 (file)
@@ -18,7 +18,7 @@
 use front::map as hir_map;
 use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use middle::cstore::{self, CrateStore, DefLike};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::lang_items::FnOnceTraitLangItem;
 use middle::subst::Substs;
@@ -432,10 +432,10 @@ fn handle_external_def(traits: &mut AllTraitsVec,
                                cstore: &for<'a> cstore::CrateStore<'a>,
                                dl: cstore::DefLike) {
             match dl {
-                cstore::DlDef(def::DefTrait(did)) => {
+                cstore::DlDef(Def::Trait(did)) => {
                     traits.push(TraitInfo::new(did));
                 }
-                cstore::DlDef(def::DefMod(did)) => {
+                cstore::DlDef(Def::Mod(did)) => {
                     if !external_mods.insert(did) {
                         return;
                     }
index 03508b07b7adce47458452e15fba944e32f5c049..f49b25df66e872341bcb0cbd79ce33cc6c82846b 100644 (file)
@@ -86,7 +86,7 @@
 use fmt_macros::{Parser, Piece, Position};
 use middle::astconv_util::prohibit_type_params;
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::infer;
 use middle::infer::{TypeOrigin, type_variable};
@@ -1416,16 +1416,16 @@ pub fn instantiate_type(&self,
 
     /// Return the dict-like variant corresponding to a given `Def`.
     pub fn def_struct_variant(&self,
-                              def: def::Def,
+                              def: Def,
                               span: Span)
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
-            def::DefVariant(enum_id, variant_id, _) => {
+            Def::Variant(enum_id, variant_id) => {
                 let adt = self.tcx().lookup_adt_def(enum_id);
                 (adt, adt.variant_with_id(variant_id))
             }
-            def::DefTy(did, _) | def::DefStruct(did) => {
+            Def::Struct(did) | Def::TyAlias(did) => {
                 let typ = self.tcx().lookup_item_type(did);
                 if let ty::TyStruct(adt, _) = typ.ty.sty {
                     (adt, adt.struct_variant())
@@ -3167,7 +3167,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
         // Find the relevant variant
         let def = lookup_full_def(tcx, path.span, expr.id);
-        if def == def::DefErr {
+        if def == Def::Err {
             check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
             return;
         }
@@ -3337,7 +3337,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
           } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
+                    base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -3349,7 +3349,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
           if let Some((opt_ty, segments, def)) =
                   resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
                                           expr.span, expr.id) {
-              if def != def::DefErr {
+              if def != Def::Err {
                   let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
                                                                                 expr.span,
                                                                                 def);
@@ -3758,7 +3758,7 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                              node_id: ast::NodeId)
                                              -> Option<(Option<Ty<'tcx>>,
                                                         &'a [hir::PathSegment],
-                                                        def::Def)>
+                                                        Def)>
 {
 
     // If fully resolved already, we don't have to do anything.
@@ -4263,29 +4263,30 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 // Returns the type parameter count and the type for the given definition.
 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 sp: Span,
-                                                defn: def::Def)
+                                                defn: Def)
                                                 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
     match defn {
-        def::DefLocal(_, nid) | def::DefUpvar(_, nid, _, _) => {
+        Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => {
             let typ = fcx.local_ty(sp, nid);
             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
              ty::GenericPredicates::empty())
         }
-        def::DefFn(id, _) | def::DefMethod(id) |
-        def::DefStatic(id, _) | def::DefVariant(_, id, _) |
-        def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id) => {
+        Def::Fn(id) | Def::Method(id) |
+        Def::Static(id, _) | Def::Variant(_, id) |
+        Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => {
             (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
         }
-        def::DefTrait(_) |
-        def::DefTy(..) |
-        def::DefAssociatedTy(..) |
-        def::DefPrimTy(_) |
-        def::DefTyParam(..) |
-        def::DefMod(..) |
-        def::DefForeignMod(..) |
-        def::DefLabel(..) |
-        def::DefSelfTy(..) |
-        def::DefErr => {
+        Def::Trait(_) |
+        Def::Enum(..) |
+        Def::TyAlias(..) |
+        Def::AssociatedTy(..) |
+        Def::PrimTy(_) |
+        Def::TyParam(..) |
+        Def::Mod(..) |
+        Def::ForeignMod(..) |
+        Def::Label(..) |
+        Def::SelfTy(..) |
+        Def::Err => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
         }
     }
@@ -4298,7 +4299,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
-                                  def: def::Def,
+                                  def: Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
     debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
@@ -4382,14 +4383,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
-        def::DefSelfTy(..) |
-        def::DefStruct(..) |
-        def::DefVariant(..) |
-        def::DefTy(..) |
-        def::DefAssociatedTy(..) |
-        def::DefTrait(..) |
-        def::DefPrimTy(..) |
-        def::DefTyParam(..) => {
+        Def::SelfTy(..) |
+        Def::Struct(..) |
+        Def::Variant(..) |
+        Def::Enum(..) |
+        Def::TyAlias(..) |
+        Def::AssociatedTy(..) |
+        Def::Trait(..) |
+        Def::PrimTy(..) |
+        Def::TyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
             segment_spaces = vec![None; segments.len() - 1];
@@ -4397,15 +4399,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         // Case 2. Reference to a top-level value.
-        def::DefFn(..) |
-        def::DefConst(..) |
-        def::DefStatic(..) => {
+        Def::Fn(..) |
+        Def::Const(..) |
+        Def::Static(..) => {
             segment_spaces = vec![None; segments.len() - 1];
             segment_spaces.push(Some(subst::FnSpace));
         }
 
         // Case 3. Reference to a method.
-        def::DefMethod(def_id) => {
+        Def::Method(def_id) => {
             let container = fcx.tcx().impl_or_trait_item(def_id).container();
             match container {
                 ty::TraitContainer(trait_did) => {
@@ -4426,7 +4428,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
 
-        def::DefAssociatedConst(def_id) => {
+        Def::AssociatedConst(def_id) => {
             let container = fcx.tcx().impl_or_trait_item(def_id).container();
             match container {
                 ty::TraitContainer(trait_did) => {
@@ -4450,12 +4452,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         // Other cases. Various nonsense that really shouldn't show up
         // here. If they do, an error will have been reported
         // elsewhere. (I hope)
-        def::DefMod(..) |
-        def::DefForeignMod(..) |
-        def::DefLocal(..) |
-        def::DefLabel(..) |
-        def::DefUpvar(..) |
-        def::DefErr => {
+        Def::Mod(..) |
+        Def::ForeignMod(..) |
+        Def::Local(..) |
+        Def::Label(..) |
+        Def::Upvar(..) |
+        Def::Err => {
             segment_spaces = vec![None; segments.len()];
         }
     }
@@ -4856,7 +4858,7 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool {
     // <id> nested anywhere inside the loop?
     (block_query(b, |e| {
         if let hir::ExprBreak(Some(_)) = e.node {
-            lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
+            lookup_full_def(cx, e.span, e.id) == Def::Label(id)
         } else {
             false
         }
index eb204c5641495ed11d248ad1e4be8b3b80468a27..0e095ed674d0e18080a5130c98edfbea2c734ef1 100644 (file)
@@ -60,7 +60,7 @@
 
 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
 use lint;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
@@ -512,10 +512,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
     if let hir::TyPath(None, _) = ast_ty.node {
         let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
         match path_res.base_def {
-            def::DefSelfTy(Some(def_id), None) => {
+            Def::SelfTy(Some(def_id), None) => {
                 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
-            def::DefTyParam(_, _, def_id, _) => {
+            Def::TyParam(_, _, def_id, _) => {
                 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
             _ => {
@@ -1007,11 +1007,7 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
         name: name,
         disr_val: disr_val,
         fields: fields,
-        kind: match *def {
-            hir::VariantData::Struct(..) => ty::VariantKind::Struct,
-            hir::VariantData::Tuple(..) => ty::VariantKind::Tuple,
-            hir::VariantData::Unit(..) => ty::VariantKind::Unit,
-        }
+        kind: VariantKind::from_variant_data(def),
     }
 }
 
index acffbeabb24c13bd68e4efe4b390231922b3725a..17d71fa7be9a6b38d585e7d36c978176928e639f 100644 (file)
 pub use rustc::util;
 
 use front::map as hir_map;
-use middle::def;
+use middle::def::Def;
 use middle::infer::{self, TypeOrigin};
 use middle::subst;
 use middle::ty::{self, Ty, TypeFoldable};
@@ -162,7 +162,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
+fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> Def {
     match tcx.def_map.borrow().get(&id) {
         Some(x) => x.full_def(),
         None => {
index 30b478f486e0a8b1f771f0666b9e1824746152cd..9eac2fd41fa1e3a5863979d1a250b12dbe4fa8e2 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_front::hir;
 
 use rustc::middle::cstore::{self, CrateStore};
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::def_id::DefId;
 use rustc::middle::ty;
 use rustc::middle::subst;
@@ -68,46 +68,47 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
 }
 
 fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
-                  def: def::Def) -> Option<Vec<clean::Item>> {
+                  def: Def) -> Option<Vec<clean::Item>> {
     let mut ret = Vec::new();
     let did = def.def_id();
     let inner = match def {
-        def::DefTrait(did) => {
+        Def::Trait(did) => {
             record_extern_fqn(cx, did, clean::TypeTrait);
             clean::TraitItem(build_external_trait(cx, tcx, did))
         }
-        def::DefFn(did, false) => {
-            // If this function is a tuple struct constructor, we just skip it
+        Def::Fn(did) => {
             record_extern_fqn(cx, did, clean::TypeFunction);
             clean::FunctionItem(build_external_function(cx, tcx, did))
         }
-        def::DefStruct(did) => {
+        Def::Struct(did)
+                // If this is a struct constructor, we skip it
+                if tcx.sess.cstore.tuple_struct_definition_if_ctor(did).is_none() => {
             record_extern_fqn(cx, did, clean::TypeStruct);
             ret.extend(build_impls(cx, tcx, did));
             clean::StructItem(build_struct(cx, tcx, did))
         }
-        def::DefTy(did, false) => {
+        Def::TyAlias(did) => {
             record_extern_fqn(cx, did, clean::TypeTypedef);
             ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
-        def::DefTy(did, true) => {
+        Def::Enum(did) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
             ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
         // Assume that the enum type is reexported next to the variant, and
         // variants don't show up in documentation specially.
-        def::DefVariant(..) => return Some(Vec::new()),
-        def::DefMod(did) => {
+        Def::Variant(..) => return Some(Vec::new()),
+        Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeModule);
             clean::ModuleItem(build_module(cx, tcx, did))
         }
-        def::DefStatic(did, mtbl) => {
+        Def::Static(did, mtbl) => {
             record_extern_fqn(cx, did, clean::TypeStatic);
             clean::StaticItem(build_static(cx, tcx, did, mtbl))
         }
-        def::DefConst(did) | def::DefAssociatedConst(did) => {
+        Def::Const(did) | Def::AssociatedConst(did) => {
             record_extern_fqn(cx, did, clean::TypeConst);
             clean::ConstantItem(build_const(cx, tcx, did))
         }
@@ -258,7 +259,7 @@ fn populate_impls(cx: &DocContext, tcx: &ty::ctxt,
                           impls: &mut Vec<clean::Item>) {
             match def {
                 cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
-                cstore::DlDef(def::DefMod(did)) => {
+                cstore::DlDef(Def::Mod(did)) => {
                     for item in tcx.sess.cstore.item_children(did) {
                         populate_impls(cx, tcx, item.def, impls)
                     }
@@ -455,7 +456,7 @@ fn fill_in(cx: &DocContext, tcx: &ty::ctxt, did: DefId,
         let mut visited = HashSet::new();
         for item in tcx.sess.cstore.item_children(did) {
             match item.def {
-                cstore::DlDef(def::DefForeignMod(did)) => {
+                cstore::DlDef(Def::ForeignMod(did)) => {
                     fill_in(cx, tcx, did, items);
                 }
                 cstore::DlDef(def) if item.vis == hir::Public => {
index d2a5fd457d2fba4cdc9183f06796ad1d05ee037b..03e2a7139b278c03c8ff67488a47998a94fc77e9 100644 (file)
@@ -36,7 +36,7 @@
 
 use rustc_trans::back::link;
 use rustc::middle::cstore::{self, CrateStore};
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::def_id::{DefId, DefIndex};
 use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::middle::ty;
@@ -230,7 +230,7 @@ fn clean(&self, cx: &DocContext) -> ExternalCrate {
         cx.tcx_opt().map(|tcx| {
             for item in tcx.sess.cstore.crate_top_level_items(self.0) {
                 let did = match item.def {
-                    cstore::DlDef(def::DefMod(did)) => did,
+                    cstore::DlDef(Def::Mod(did)) => did,
                     _ => continue
                 };
                 let attrs = inline::load_attrs(cx, tcx, did);
@@ -2607,7 +2607,7 @@ fn resolve_type(cx: &DocContext,
     debug!("resolve_type: def={:?}", def);
 
     let is_generic = match def {
-        def::DefPrimTy(p) => match p {
+        Def::PrimTy(p) => match p {
             hir::TyStr => return Primitive(Str),
             hir::TyBool => return Primitive(Bool),
             hir::TyChar => return Primitive(Char),
@@ -2624,30 +2624,30 @@ fn resolve_type(cx: &DocContext,
             hir::TyFloat(ast::TyF32) => return Primitive(F32),
             hir::TyFloat(ast::TyF64) => return Primitive(F64),
         },
-        def::DefSelfTy(..) if path.segments.len() == 1 => {
+        Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(special_idents::type_self.name.to_string());
         }
-        def::DefSelfTy(..) | def::DefTyParam(..) => true,
+        Def::SelfTy(..) | Def::TyParam(..) => true,
         _ => false,
     };
     let did = register_def(&*cx, def);
     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
 }
 
-fn register_def(cx: &DocContext, def: def::Def) -> DefId {
+fn register_def(cx: &DocContext, def: Def) -> DefId {
     debug!("register_def({:?})", def);
 
     let (did, kind) = match def {
-        def::DefFn(i, _) => (i, TypeFunction),
-        def::DefTy(i, false) => (i, TypeTypedef),
-        def::DefTy(i, true) => (i, TypeEnum),
-        def::DefTrait(i) => (i, TypeTrait),
-        def::DefStruct(i) => (i, TypeStruct),
-        def::DefMod(i) => (i, TypeModule),
-        def::DefStatic(i, _) => (i, TypeStatic),
-        def::DefVariant(i, _, _) => (i, TypeEnum),
-        def::DefSelfTy(Some(def_id), _) => (def_id, TypeTrait),
-        def::DefSelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
+        Def::Fn(i) => (i, TypeFunction),
+        Def::TyAlias(i) => (i, TypeTypedef),
+        Def::Enum(i) => (i, TypeEnum),
+        Def::Trait(i) => (i, TypeTrait),
+        Def::Struct(i) => (i, TypeStruct),
+        Def::Mod(i) => (i, TypeModule),
+        Def::Static(i, _) => (i, TypeStatic),
+        Def::Variant(i, _) => (i, TypeEnum),
+        Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
+        Def::SelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
         _ => return def.def_id()
     };
     if did.is_local() { return did }
index 635ed91f35da41c5335c36d4c5cd57e569de3d53..414a0ebd11fa27ce0cc8c4b79f68b45a252229cc 100644 (file)
@@ -375,7 +375,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 }
 
 impl OpenOptions {
-    /// Creates a blank net set of options ready for configuration.
+    /// Creates a blank new set of options ready for configuration.
     ///
     /// All options are initially set to `false`.
     ///
@@ -384,7 +384,8 @@ impl OpenOptions {
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().open("foo.txt");
+    /// let mut options = OpenOptions::new();
+    /// let file = options.read(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> OpenOptions {
@@ -413,6 +414,9 @@ pub fn read(&mut self, read: bool) -> &mut OpenOptions {
     /// This option, when true, will indicate that the file should be
     /// `write`-able if opened.
     ///
+    /// If a file already exist, any write calls on the file will overwrite its
+    /// contents, without truncating it.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -429,13 +433,30 @@ pub fn write(&mut self, write: bool) -> &mut OpenOptions {
     ///
     /// This option, when true, means that writes will append to a file instead
     /// of overwriting previous contents.
+    /// Note that setting `.write(true).append(true)` has the same effect as
+    /// setting only `.append(true)`.
+    ///
+    /// For most filesystems the operating system guarantees all writes are
+    /// atomic: no writes get mangled because another process writes at the same
+    /// time.
+    ///
+    /// One maybe obvious note when using append-mode: make sure that all data
+    /// that belongs together, is written the the file in one operation. This
+    /// can be done by concatenating strings before passing them to `write()`,
+    /// or using a buffered writer (with a more than adequately sized buffer)
+    /// and calling `flush()` when the message is complete.
+    ///
+    /// If a file is opened with both read and append access, beware that after
+    /// opening and after every write the position for reading may be set at the
+    /// end of the file. So before writing save the current position (using
+    /// `seek(SeekFrom::Current(0))`, and restore it before the next read.
     ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().write(true).append(true).open("foo.txt");
+    /// let file = OpenOptions::new().append(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, append: bool) -> &mut OpenOptions {
@@ -447,6 +468,8 @@ pub fn append(&mut self, append: bool) -> &mut OpenOptions {
     /// If a file is successfully opened with this option set it will truncate
     /// the file to 0 length if it already exists.
     ///
+    /// The file must be opened with write access for truncate to work.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -464,18 +487,54 @@ pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
     /// This option indicates whether a new file will be created if the file
     /// does not yet already exist.
     ///
+    /// The file must be opened with write or append access in order to create
+    /// a new file.
+    ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().create(true).open("foo.txt");
+    /// let file = OpenOptions::new().write(true).create(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn create(&mut self, create: bool) -> &mut OpenOptions {
         self.0.create(create); self
     }
 
+    /// Sets the option to always create a new file.
+    ///
+    /// This option indicates whether a new file will be created.
+    /// No file is allowed to exist at the target location, also no (dangling)
+    /// symlink.
+    ///
+    /// This option is usefull because it as atomic. Otherwise between checking
+    /// whether a file exists and creating a new one, the file may have been
+    /// created by another process (a TOCTOU race condition / attack).
+    ///
+    /// If `.create_new(true)` is set, `.create()` and `.truncate()` are
+    /// ignored.
+    ///
+    /// The file must be opened with write or append access in order to create
+    /// a new file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(expand_open_options)]
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().write(true)
+    ///                              .create_new(true)
+    ///                              .open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
+        self.0.create_new(create_new); self
+    }
+
     /// Opens a file at `path` with the options specified by `self`.
     ///
     /// # Errors
@@ -483,10 +542,13 @@ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
     /// This function will return an error under a number of different
     /// circumstances, to include but not limited to:
     ///
-    /// * Opening a file that does not exist with read access.
+    /// * Opening a file that does not exist without setting `create` or
+    ///   `create_new`.
     /// * Attempting to open a file with access that the user lacks
     ///   permissions for
     /// * Filesystem-level errors (full disk, etc)
+    /// * Invalid combinations of open options (truncate without write access,
+    ///   no access mode set, etc)
     ///
     /// # Examples
     ///
@@ -2098,61 +2160,114 @@ fn c<T: Clone>(t: &T) -> T { t.clone() }
 
         let mut r = OO::new(); r.read(true);
         let mut w = OO::new(); w.write(true);
-        let mut rw = OO::new(); rw.write(true).read(true);
-
-        match r.open(&tmpdir.join("a")) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-
-        // Perform each one twice to make sure that it succeeds the second time
-        // (where the file exists)
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        assert!(tmpdir.join("b").exists());
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        check!(w.open(&tmpdir.join("b")));
-
+        let mut rw = OO::new(); rw.read(true).write(true);
+        let mut a = OO::new(); a.append(true);
+        let mut ra = OO::new(); ra.read(true).append(true);
+
+        let invalid_options = if cfg!(windows) { "The parameter is incorrect" }
+                              else { "Invalid argument" };
+
+        // Test various combinations of creation modes and access modes.
+        //
+        // Allowed:
+        // creation mode           | read  | write | read-write | append | read-append |
+        // :-----------------------|:-----:|:-----:|:----------:|:------:|:-----------:|
+        // not set (open existing) |   X   |   X   |     X      |   X    |      X      |
+        // create                  |       |   X   |     X      |   X    |      X      |
+        // truncate                |       |   X   |     X      |        |             |
+        // create and truncate     |       |   X   |     X      |        |             |
+        // create_new              |       |   X   |     X      |   X    |      X      |
+        //
+        // tested in reverse order, so 'create_new' creates the file, and 'open existing' opens it.
+
+        // write-only
+        check!(c(&w).create_new(true).open(&tmpdir.join("a")));
+        check!(c(&w).create(true).truncate(true).open(&tmpdir.join("a")));
+        check!(c(&w).truncate(true).open(&tmpdir.join("a")));
+        check!(c(&w).create(true).open(&tmpdir.join("a")));
+        check!(c(&w).open(&tmpdir.join("a")));
+
+        // read-only
+        error!(c(&r).create_new(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).create(true).truncate(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).truncate(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).create(true).open(&tmpdir.join("b")), invalid_options);
+        check!(c(&r).open(&tmpdir.join("a"))); // try opening the file created with write_only
+
+        // read-write
+        check!(c(&rw).create_new(true).open(&tmpdir.join("c")));
+        check!(c(&rw).create(true).truncate(true).open(&tmpdir.join("c")));
+        check!(c(&rw).truncate(true).open(&tmpdir.join("c")));
         check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        assert!(tmpdir.join("c").exists());
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        check!(rw.open(&tmpdir.join("c")));
-
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        assert!(tmpdir.join("d").exists());
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        check!(c(&w).append(true).open(&tmpdir.join("d")));
-
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        assert!(tmpdir.join("e").exists());
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        check!(c(&rw).append(true).open(&tmpdir.join("e")));
-
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        assert!(tmpdir.join("f").exists());
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
-
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        assert!(tmpdir.join("g").exists());
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
-
-        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
+        check!(c(&rw).open(&tmpdir.join("c")));
+
+        // append
+        check!(c(&a).create_new(true).open(&tmpdir.join("d")));
+        error!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options);
+        error!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options);
+        check!(c(&a).create(true).open(&tmpdir.join("d")));
+        check!(c(&a).open(&tmpdir.join("d")));
+
+        // read-append
+        check!(c(&ra).create_new(true).open(&tmpdir.join("e")));
+        error!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options);
+        error!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options);
+        check!(c(&ra).create(true).open(&tmpdir.join("e")));
+        check!(c(&ra).open(&tmpdir.join("e")));
+
+        // Test opening a file without setting an access mode
+        let mut blank = OO::new();
+         error!(blank.create(true).open(&tmpdir.join("f")), invalid_options);
+
+        // Test write works
+        check!(check!(File::create(&tmpdir.join("h"))).write("foobar".as_bytes()));
+
+        // Test write fails for read-only
         check!(r.open(&tmpdir.join("h")));
         {
             let mut f = check!(r.open(&tmpdir.join("h")));
             assert!(f.write("wut".as_bytes()).is_err());
         }
+
+        // Test write overwrites
+        {
+            let mut f = check!(c(&w).open(&tmpdir.join("h")));
+            check!(f.write("baz".as_bytes()));
+        }
+        {
+            let mut f = check!(c(&r).open(&tmpdir.join("h")));
+            let mut b = vec![0; 6];
+            check!(f.read(&mut b));
+            assert_eq!(b, "bazbar".as_bytes());
+        }
+
+        // Test truncate works
+        {
+            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
+            check!(f.write("foo".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+
+        // Test append works
         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
         {
-            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            let mut f = check!(c(&a).open(&tmpdir.join("h")));
             check!(f.write("bar".as_bytes()));
         }
         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
+
+        // Test .append(true) equals .write(true).append(true)
         {
-            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
+            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            check!(f.write("baz".as_bytes()));
         }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 9);
+    }
+
+    #[test]
+    fn _assert_send_sync() {
+        fn _assert_send_sync<T: Send + Sync>() {}
+        _assert_send_sync::<OpenOptions>();
     }
 
     #[test]
index c043b41ed21f0e3403a5dd2ef76acb4606cc3346..27702e2e59aefdac347ba4fe00f2f61094b6bebc 100644 (file)
@@ -98,7 +98,7 @@ fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
 
     #[cfg(not(target_os = "linux"))]
     fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        haystack.iter().rposition(|&b| b == needle)
+        fallback::memrchr(needle, haystack)
     }
 
     memrchr_specific(needle, haystack)
index 3eb5db09bc0728332e045c38a829b91ef7b6e843..64230c9e016ac349e22ea5bcb3fe1af6d14a0dd5 100644 (file)
@@ -635,6 +635,13 @@ fn drop(&mut self) {
     }
 }
 
+#[stable(feature = "mpsc_debug", since = "1.7.0")]
+impl<T> fmt::Debug for Sender<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Sender {{ .. }}")
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // SyncSender
 ////////////////////////////////////////////////////////////////////////////////
@@ -693,6 +700,13 @@ fn drop(&mut self) {
     }
 }
 
+#[stable(feature = "mpsc_debug", since = "1.7.0")]
+impl<T> fmt::Debug for SyncSender<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "SyncSender {{ .. }}")
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Receiver
 ////////////////////////////////////////////////////////////////////////////////
@@ -987,6 +1001,13 @@ fn drop(&mut self) {
     }
 }
 
+#[stable(feature = "mpsc_debug", since = "1.7.0")]
+impl<T> fmt::Debug for Receiver<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Receiver {{ .. }}")
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for SendError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2199,4 +2220,22 @@ fn repro() {
             repro()
         }
     }
+
+    #[test]
+    fn fmt_debug_sender() {
+        let (tx, _) = channel::<i32>();
+        assert_eq!(format!("{:?}", tx), "Sender { .. }");
+    }
+
+    #[test]
+    fn fmt_debug_recv() {
+        let (_, rx) = channel::<i32>();
+        assert_eq!(format!("{:?}", rx), "Receiver { .. }");
+    }
+
+    #[test]
+    fn fmt_debug_sync_sender() {
+        let (tx, _) = sync_channel::<i32>(1);
+        assert_eq!(format!("{:?}", tx), "SyncSender { .. }");
+    }
 }
index cc068fd1dea55bfbdc67287cd5cee22f9e3bb22d..d743cbb18909f005d557f38d9906a7557182b24f 100644 (file)
@@ -58,6 +58,8 @@
             issue = "27800")]
 
 
+use fmt;
+
 use core::cell::{Cell, UnsafeCell};
 use core::marker;
 use core::ptr;
@@ -350,6 +352,20 @@ fn next(&mut self) -> Option<*mut Handle<'static, ()>> {
     }
 }
 
+#[stable(feature = "mpsc_debug", since = "1.7.0")]
+impl fmt::Debug for Select {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Select {{ .. }}")
+    }
+}
+
+#[stable(feature = "mpsc_debug", since = "1.7.0")]
+impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Handle {{ .. }}")
+    }
+}
+
 #[cfg(test)]
 #[allow(unused_imports)]
 mod tests {
@@ -762,4 +778,18 @@ fn sync3() {
             }
         }
     }
+
+    #[test]
+    fn fmt_debug_select() {
+        let sel = Select::new();
+        assert_eq!(format!("{:?}", sel), "Select { .. }");
+    }
+
+    #[test]
+    fn fmt_debug_handle() {
+        let (_, rx) = channel::<i32>();
+        let sel = Select::new();
+        let mut handle = sel.handle(&rx);
+        assert_eq!(format!("{:?}", handle), "Handle { .. }");
+    }
 }
index 8d21ba8f661c80f53c5e8d694b8f919c77c11ea2..2a3117864d06336584490f11dd4593ad91bedb3a 100644 (file)
@@ -118,8 +118,38 @@ pub trait OpenOptionsExt {
     ///
     /// If a new file is created as part of a `File::open_opts` call then this
     /// specified `mode` will be used as the permission bits for the new file.
+    /// If no `mode` is set, the default of `0o666` will be used.
+    /// The operating system masks out bits with the systems `umask`, to produce
+    /// the final permissions.
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
+
+    /// Pass custom flags to the `flags` agument of `open`.
+    ///
+    /// The bits that define the access mode are masked out with `O_ACCMODE`, to
+    /// ensure they do not interfere with the access mode set by Rusts options.
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.write(true);
+    /// if cfg!(unix) {
+    ///     options.custom_flags(libc::O_NOFOLLOW);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    fn custom_flags(&mut self, flags: i32) -> &mut Self;
 }
 
 #[stable(feature = "fs_ext", since = "1.1.0")]
@@ -127,6 +157,10 @@ impl OpenOptionsExt for OpenOptions {
     fn mode(&mut self, mode: raw::mode_t) -> &mut OpenOptions {
         self.as_inner_mut().mode(mode); self
     }
+
+    fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
+    }
 }
 
 // Hm, why are there casts here to the returned type, shouldn't the types always
@@ -281,4 +315,3 @@ fn mode(&mut self, mode: raw::mode_t) -> &mut fs::DirBuilder {
         self
     }
 }
-
index 10fda3fcd7fa5165ce82e70ea0fab45d8517559e..d2d2ce35d84a0adfe401f80935293cb91929f701 100644 (file)
@@ -50,9 +50,15 @@ pub struct DirEntry {
 
 #[derive(Clone)]
 pub struct OpenOptions {
-    flags: c_int,
+    // generic
     read: bool,
     write: bool,
+    append: bool,
+    truncate: bool,
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: i32,
     mode: mode_t,
 }
 
@@ -233,43 +239,60 @@ fn name_bytes(&self) -> &[u8] {
 impl OpenOptions {
     pub fn new() -> OpenOptions {
         OpenOptions {
-            flags: libc::O_CLOEXEC,
+            // generic
             read: false,
             write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
             mode: 0o666,
         }
     }
 
-    pub fn read(&mut self, read: bool) {
-        self.read = read;
-    }
-
-    pub fn write(&mut self, write: bool) {
-        self.write = write;
-    }
-
-    pub fn append(&mut self, append: bool) {
-        self.flag(libc::O_APPEND, append);
-    }
-
-    pub fn truncate(&mut self, truncate: bool) {
-        self.flag(libc::O_TRUNC, truncate);
-    }
-
-    pub fn create(&mut self, create: bool) {
-        self.flag(libc::O_CREAT, create);
-    }
-
-    pub fn mode(&mut self, mode: raw::mode_t) {
-        self.mode = mode as mode_t;
+    pub fn read(&mut self, read: bool) { self.read = read; }
+    pub fn write(&mut self, write: bool) { self.write = write; }
+    pub fn append(&mut self, append: bool) { self.append = append; }
+    pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+
+    pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; }
+    pub fn mode(&mut self, mode: raw::mode_t) { self.mode = mode as mode_t; }
+
+    fn get_access_mode(&self) -> io::Result<c_int> {
+        match (self.read, self.write, self.append) {
+            (true,  false, false) => Ok(libc::O_RDONLY),
+            (false, true,  false) => Ok(libc::O_WRONLY),
+            (true,  true,  false) => Ok(libc::O_RDWR),
+            (false, _,     true)  => Ok(libc::O_WRONLY | libc::O_APPEND),
+            (true,  _,     true)  => Ok(libc::O_RDWR | libc::O_APPEND),
+            (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
+        }
     }
 
-    fn flag(&mut self, bit: c_int, on: bool) {
-        if on {
-            self.flags |= bit;
-        } else {
-            self.flags &= !bit;
+    fn get_creation_mode(&self) -> io::Result<c_int> {
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
         }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => 0,
+                (true,  false, false) => libc::O_CREAT,
+                (false, true,  false) => libc::O_TRUNC,
+                (true,  true,  false) => libc::O_CREAT | libc::O_TRUNC,
+                (_,      _,    true)  => libc::O_CREAT | libc::O_EXCL,
+           })
     }
 }
 
@@ -280,12 +303,10 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
     }
 
     pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
-        let flags = opts.flags | match (opts.read, opts.write) {
-            (true, true) => libc::O_RDWR,
-            (false, true) => libc::O_WRONLY,
-            (true, false) |
-            (false, false) => libc::O_RDONLY,
-        };
+        let flags = libc::O_CLOEXEC |
+                    try!(opts.get_access_mode()) |
+                    try!(opts.get_creation_mode()) |
+                    (opts.custom_flags as c_int & !libc::O_ACCMODE);
         let fd = try!(cvt_r(|| unsafe {
             libc::open(path.as_ptr(), flags, opts.mode as c_int)
         }));
index 34e32d0d5b62af67e27ef641967cc5514fb5ad88..6e8090a223516434662df5b4f5497422cce35a2b 100644 (file)
 pub const OPEN_ALWAYS: DWORD = 4;
 pub const OPEN_EXISTING: DWORD = 3;
 pub const TRUNCATE_EXISTING: DWORD = 5;
-pub const FILE_APPEND_DATA: DWORD = 0x00000004;
+
 pub const FILE_READ_DATA: DWORD = 0x00000001;
 pub const FILE_WRITE_DATA: DWORD = 0x00000002;
-pub const STANDARD_RIGHTS_READ: DWORD = 0x20000;
-pub const STANDARD_RIGHTS_WRITE: DWORD = 0x20000;
-pub const FILE_WRITE_EA: DWORD = 0x00000010;
+pub const FILE_APPEND_DATA: DWORD = 0x00000004;
 pub const FILE_READ_EA: DWORD = 0x00000008;
-pub const SYNCHRONIZE: DWORD = 0x00100000;
-pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
+pub const FILE_WRITE_EA: DWORD = 0x00000010;
+pub const FILE_EXECUTE: DWORD = 0x00000020;
 pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080;
+pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
+
+pub const DELETE: DWORD = 0x00008000;
+pub const READ_CONTROL: DWORD = 0x00020000;
+pub const WRITE_DAC: DWORD = 0x00040000;
+pub const WRITE_OWNER: DWORD = 0x00080000;
+pub const SYNCHRONIZE: DWORD = 0x00100000;
+
+pub const GENERIC_READ: DWORD = 0x80000000;
+pub const GENERIC_WRITE: DWORD = 0x40000000;
+pub const GENERIC_EXECUTE: DWORD = 0x20000000;
+pub const GENERIC_ALL: DWORD = 0x10000000;
+
+pub const STANDARD_RIGHTS_READ: DWORD = READ_CONTROL;
+pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL;
+pub const STANDARD_RIGHTS_EXECUTE: DWORD = READ_CONTROL;
 pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA |
                                      FILE_READ_ATTRIBUTES |
                                      FILE_READ_EA |
                                       FILE_APPEND_DATA |
                                       SYNCHRONIZE;
 
+pub const SECURITY_ANONYMOUS: DWORD = 0 << 16;
+pub const SECURITY_IDENTIFICATION: DWORD = 1 << 16;
+pub const SECURITY_IMPERSONATION: DWORD = 2 << 16;
+pub const SECURITY_DELEGATION: DWORD = 3 << 16;
+pub const SECURITY_CONTEXT_TRACKING: DWORD = 0x00040000;
+pub const SECURITY_EFFECTIVE_ONLY: DWORD = 0x00080000;
+pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
+
 #[repr(C)]
 #[derive(Copy)]
 pub struct WIN32_FIND_DATAW {
index 0d78d4de42b299a2e1dcf4557743250ec5ede742..d060c902fba2fe27a38feef827a2fe6f6cb291ca 100644 (file)
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
     /// with the specified value.
-    fn desired_access(&mut self, access: u32) -> &mut Self;
-
-    /// Overrides the `dwCreationDisposition` argument to the call to
-    /// `CreateFile` with the specified value.
     ///
-    /// This will override any values of the standard `create` flags, for
-    /// example.
-    fn creation_disposition(&mut self, val: u32) -> &mut Self;
-
-    /// Overrides the `dwFlagsAndAttributes` argument to the call to
-    /// `CreateFile` with the specified value.
+    /// This will override the `read`, `write`, and `append` flags on the
+    /// `OpenOptions` structure. This method provides fine-grained control over
+    /// the permissions to read, write and append data, attributes (like hidden
+    /// and system) and extended attributes.
+    ///
+    /// # Examples
     ///
-    /// This will override any values of the standard flags on the
-    /// `OpenOptions` structure.
-    fn flags_and_attributes(&mut self, val: u32) -> &mut Self;
+    /// ```no_run
+    /// #![feature(open_options_ext)]
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// // Open without read and write permission, for example if you only need
+    /// // to call `stat()` on the file
+    /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
+    /// ```
+    fn access_mode(&mut self, access: u32) -> &mut Self;
 
     /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
     /// the specified value.
     ///
-    /// This will override any values of the standard flags on the
-    /// `OpenOptions` structure.
+    /// By default `share_mode` is set to
+    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. Specifying
+    /// less permissions denies others to read from, write to and/or delete the
+    /// file while it is open.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(open_options_ext)]
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// // Do not allow others to read or modify this file while we have it open
+    /// // for writing
+    /// let file = OpenOptions::new().write(true)
+    ///                              .share_mode(0)
+    ///                              .open("foo.txt");
+    /// ```
     fn share_mode(&mut self, val: u32) -> &mut Self;
+
+    /// Sets extra flags for the `dwFileFlags` argument to the call to
+    /// `CreateFile2` (or combines it with `attributes` and `security_qos_flags`
+    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate winapi;
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.create(true).write(true);
+    /// if cfg!(windows) {
+    ///     options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    fn custom_flags(&mut self, flags: u32) -> &mut Self;
+
+    /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
+    /// the specified value (or combines it with `custom_flags` and
+    /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
+    /// `CreateFile`).
+    ///
+    /// If a _new_ file is created because it does not yet exist and
+    ///`.create(true)` or `.create_new(true)` are specified, the new file is
+    /// given the attributes declared with `.attributes()`.
+    ///
+    /// If an _existing_ file is opened with `.create(true).truncate(true)`, its
+    /// existing attributes are preserved and combined with the ones declared
+    /// with `.attributes()`.
+    ///
+    /// In all other cases the attributes get ignored.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// #![feature(open_options_ext)]
+    /// extern crate winapi;
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// let file = OpenOptions::new().write(true).create(true)
+    ///                              .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
+    ///                              .open("foo.txt");
+    /// ```
+    fn attributes(&mut self, val: u32) -> &mut Self;
+
+    /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
+    /// the specified value (or combines it with `custom_flags` and `attributes`
+    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
 }
 
 #[unstable(feature = "open_options_ext",
            reason = "may require more thought/methods",
            issue = "27720")]
 impl OpenOptionsExt for OpenOptions {
-    fn desired_access(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().desired_access(access); self
+    fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
+        self.as_inner_mut().access_mode(access); self
     }
-    fn creation_disposition(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().creation_disposition(access); self
+
+    fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
+        self.as_inner_mut().share_mode(share); self
     }
-    fn flags_and_attributes(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().flags_and_attributes(access); self
+
+    fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
     }
-    fn share_mode(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().share_mode(access); self
+
+    fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
+        self.as_inner_mut().attributes(attributes); self
+    }
+
+    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().security_qos_flags(flags); self
     }
 }
 
index 9db7ab534590ab23eb55f3e5826d9cdb03d385b1..60e3f7c22bd58c0484be6c0ba684e1e6fb714f0b 100644 (file)
@@ -54,18 +54,22 @@ pub struct DirEntry {
     data: c::WIN32_FIND_DATAW,
 }
 
-#[derive(Clone, Default)]
+#[derive(Clone)]
 pub struct OpenOptions {
-    create: bool,
-    append: bool,
+    // generic
     read: bool,
     write: bool,
+    append: bool,
     truncate: bool,
-    desired_access: Option<c::DWORD>,
-    share_mode: Option<c::DWORD>,
-    creation_disposition: Option<c::DWORD>,
-    flags_and_attributes: Option<c::DWORD>,
-    security_attributes: usize, // *mut T doesn't have a Default impl
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: u32,
+    access_mode: Option<c::DWORD>,
+    attributes: c::DWORD,
+    share_mode: c::DWORD,
+    security_qos_flags: c::DWORD,
+    security_attributes: usize, // FIXME: should be a reference
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -151,68 +155,86 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
 }
 
 impl OpenOptions {
-    pub fn new() -> OpenOptions { Default::default() }
+    pub fn new() -> OpenOptions {
+        OpenOptions {
+            // generic
+            read: false,
+            write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
+            access_mode: None,
+            share_mode: c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE,
+            attributes: 0,
+            security_qos_flags: 0,
+            security_attributes: 0,
+        }
+    }
+
     pub fn read(&mut self, read: bool) { self.read = read; }
     pub fn write(&mut self, write: bool) { self.write = write; }
     pub fn append(&mut self, append: bool) { self.append = append; }
-    pub fn create(&mut self, create: bool) { self.create = create; }
     pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
-    pub fn creation_disposition(&mut self, val: u32) {
-        self.creation_disposition = Some(val);
-    }
-    pub fn flags_and_attributes(&mut self, val: u32) {
-        self.flags_and_attributes = Some(val);
-    }
-    pub fn desired_access(&mut self, val: u32) {
-        self.desired_access = Some(val);
-    }
-    pub fn share_mode(&mut self, val: u32) {
-        self.share_mode = Some(val);
-    }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+
+    pub fn custom_flags(&mut self, flags: u32) { self.custom_flags = flags; }
+    pub fn access_mode(&mut self, access_mode: u32) { self.access_mode = Some(access_mode); }
+    pub fn share_mode(&mut self, share_mode: u32) { self.share_mode = share_mode; }
+    pub fn attributes(&mut self, attrs: u32) { self.attributes = attrs; }
+    pub fn security_qos_flags(&mut self, flags: u32) { self.security_qos_flags = flags; }
     pub fn security_attributes(&mut self, attrs: c::LPSECURITY_ATTRIBUTES) {
         self.security_attributes = attrs as usize;
     }
 
-    fn get_desired_access(&self) -> c::DWORD {
-        self.desired_access.unwrap_or({
-            let mut base = if self.read {c::FILE_GENERIC_READ} else {0} |
-                           if self.write {c::FILE_GENERIC_WRITE} else {0};
-            if self.append {
-                base &= !c::FILE_WRITE_DATA;
-                base |= c::FILE_APPEND_DATA;
-            }
-            base
-        })
+    fn get_access_mode(&self) -> io::Result<c::DWORD> {
+        const ERROR_INVALID_PARAMETER: i32 = 87;
+
+        match (self.read, self.write, self.append, self.access_mode) {
+            (_, _, _, Some(mode)) => Ok(mode),
+            (true,  false, false, None) => Ok(c::GENERIC_READ),
+            (false, true,  false, None) => Ok(c::GENERIC_WRITE),
+            (true,  true,  false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE),
+            (false, _,     true,  None) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA),
+            (true,  _,     true,  None) => Ok(c::GENERIC_READ |
+                                              (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)),
+            (false, false, false, None) => Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER)),
+        }
     }
 
-    fn get_share_mode(&self) -> c::DWORD {
-        // libuv has a good comment about this, but the basic idea is that
-        // we try to emulate unix semantics by enabling all sharing by
-        // allowing things such as deleting a file while it's still open.
-        self.share_mode.unwrap_or(c::FILE_SHARE_READ |
-                                  c::FILE_SHARE_WRITE |
-                                  c::FILE_SHARE_DELETE)
-    }
-
-    fn get_creation_disposition(&self) -> c::DWORD {
-        self.creation_disposition.unwrap_or({
-            match (self.create, self.truncate) {
-                (true, true) => c::CREATE_ALWAYS,
-                (true, false) => c::OPEN_ALWAYS,
-                (false, false) => c::OPEN_EXISTING,
-                (false, true) => {
-                    if self.write && !self.append {
-                        c::CREATE_ALWAYS
-                    } else {
-                        c::TRUNCATE_EXISTING
-                    }
-                }
-            }
-        })
+    fn get_creation_mode(&self) -> io::Result<c::DWORD> {
+        const ERROR_INVALID_PARAMETER: i32 = 87;
+
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                },
+        }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => c::OPEN_EXISTING,
+                (true,  false, false) => c::OPEN_ALWAYS,
+                (false, true,  false) => c::TRUNCATE_EXISTING,
+                (true,  true,  false) => c::CREATE_ALWAYS,
+                (_,      _,    true)  => c::CREATE_NEW,
+           })
     }
 
     fn get_flags_and_attributes(&self) -> c::DWORD {
-        self.flags_and_attributes.unwrap_or(c::FILE_ATTRIBUTE_NORMAL)
+        self.custom_flags |
+        self.attributes |
+        self.security_qos_flags |
+        if self.security_qos_flags != 0 { c::SECURITY_SQOS_PRESENT } else { 0 } |
+        if self.create_new { c::FILE_FLAG_OPEN_REPARSE_POINT } else { 0 }
     }
 }
 
@@ -221,8 +243,8 @@ fn open_reparse_point(path: &Path, write: bool) -> io::Result<File> {
         let mut opts = OpenOptions::new();
         opts.read(!write);
         opts.write(write);
-        opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT |
-                                  c::FILE_FLAG_BACKUP_SEMANTICS);
+        opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT |
+                          c::FILE_FLAG_BACKUP_SEMANTICS);
         File::open(path, &opts)
     }
 
@@ -230,10 +252,10 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
         let path = try!(to_u16s(path));
         let handle = unsafe {
             c::CreateFileW(path.as_ptr(),
-                           opts.get_desired_access(),
-                           opts.get_share_mode(),
+                           try!(opts.get_access_mode()),
+                           opts.share_mode,
                            opts.security_attributes as *mut _,
-                           opts.get_creation_disposition(),
+                           try!(opts.get_creation_mode()),
                            opts.get_flags_and_attributes(),
                            ptr::null_mut())
         };
@@ -533,7 +555,10 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
     // metadata information is.
     if attr.is_reparse_point() {
         let mut opts = OpenOptions::new();
-        opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
+        // No read or write permissions are necessary
+        opts.access_mode(0);
+        // This flag is so we can open directories too
+        opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
         let file = try!(File::open(p, &opts));
         file.file_attr()
     } else {
@@ -577,9 +602,10 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
 
 pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     let mut opts = OpenOptions::new();
-    opts.read(true);
+    // No read or write permissions are necessary
+    opts.access_mode(0);
     // This flag is so we can open directories too
-    opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
+    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
     let f = try!(File::open(p, &opts));
     get_path(&f)
 }
index 19236f2cd98a80302e463ffd5d9112ac111f42c4..8d6c0df981f23d09eaa9f4c56b9800c3656fe70a 100644 (file)
@@ -164,16 +164,31 @@ impl Eq for Span {}
 
 impl Encodable for Span {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        try!(s.emit_u32(self.lo.0));
-        s.emit_u32(self.hi.0)
+        s.emit_struct("Span", 2, |s| {
+            try!(s.emit_struct_field("lo", 0, |s| {
+                self.lo.encode(s)
+            }));
+
+            s.emit_struct_field("hi", 1, |s| {
+                self.hi.encode(s)
+            })
+        })
     }
 }
 
 impl Decodable for Span {
     fn decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
-        let lo = BytePos(try! { d.read_u32() });
-        let hi = BytePos(try! { d.read_u32() });
-        Ok(mk_sp(lo, hi))
+        d.read_struct("Span", 2, |d| {
+            let lo = try!(d.read_struct_field("lo", 0, |d| {
+                BytePos::decode(d)
+            }));
+
+            let hi = try!(d.read_struct_field("hi", 1, |d| {
+                BytePos::decode(d)
+            }));
+
+            Ok(mk_sp(lo, hi))
+        })
     }
 }
 
index d4c9cb8e2541b4017c7b7c6a7a798006e23303c4..df1fedf3d4e6610c23ee2a5fe341f28e9c44aca1 100644 (file)
@@ -74,9 +74,9 @@
 mod win;
 
 /// Alias for stdout terminals.
-pub type StdoutTerminal = Terminal<Output=Stdout> + Send;
+pub type StdoutTerminal = Terminal<Output = Stdout> + Send;
 /// Alias for stderr terminals.
-pub type StderrTerminal = Terminal<Output=Stderr> + Send;
+pub type StderrTerminal = Terminal<Output = Stderr> + Send;
 
 #[cfg(not(windows))]
 /// Return a Terminal wrapping stdout, or None if a terminal couldn't be
index a4e5d00ee7a77646e68082cde6c28a5e1e8e7413..04486132c84de27c720e8d720ab6cdc217b46b3e 100644 (file)
@@ -151,7 +151,7 @@ pub struct TerminfoTerminal<T> {
     ti: TermInfo,
 }
 
-impl<T: Write+Send> Terminal for TerminfoTerminal<T> {
+impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
     type Output = T;
     fn fg(&mut self, color: color::Color) -> io::Result<bool> {
         let color = self.dim_if_necessary(color);
@@ -220,7 +220,7 @@ fn into_inner(self) -> T
     }
 }
 
-impl<T: Write+Send> TerminfoTerminal<T> {
+impl<T: Write + Send> TerminfoTerminal<T> {
     /// Create a new TerminfoTerminal with the given TermInfo and Write.
     pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
         let nc = if terminfo.strings.contains_key("setaf") &&
index 2cb7018669d3daacdfd212f2efc70d32cc3e004f..d36b182710b9790655d60910c3241b4249f9f22a 100644 (file)
@@ -91,7 +91,7 @@ fn bits_to_color(bits: u16) -> color::Color {
     color | (bits & 0x8) // copy the hi-intensity bit
 }
 
-impl<T: Write+Send+'static> WinConsole<T> {
+impl<T: Write + Send + 'static> WinConsole<T> {
     fn apply(&mut self) {
         let _unused = self.buf.flush();
         let mut accum: WORD = 0;
@@ -148,7 +148,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-impl<T: Write+Send+'static> Terminal for WinConsole<T> {
+impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
     type Output = T;
 
     fn fg(&mut self, color: color::Color) -> io::Result<bool> {
index 00c9d30c5633730c3474fbf9eb0a70c82008563d..ac5b235854a04cc54fb174cd94ea2fdc1f99026c 100644 (file)
 
 // to be used by rustc to compile tests in libtest
 pub mod test {
-    pub use {Bencher, TestName, TestResult, TestDesc,
-             TestDescAndFn, TestOpts, TrFailed, TrIgnored, TrOk,
-             Metric, MetricMap,
-             StaticTestFn, StaticTestName, DynTestName, DynTestFn,
-             run_test, test_main, test_main_static, filter_tests,
-             parse_opts, StaticBenchFn, ShouldPanic};
+    pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed,
+             TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName, DynTestName,
+             DynTestFn, run_test, test_main, test_main_static, filter_tests, parse_opts,
+             StaticBenchFn, ShouldPanic};
 }
 
 pub mod stats;
@@ -95,13 +93,13 @@ pub mod test {
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub enum TestName {
     StaticTestName(&'static str),
-    DynTestName(String)
+    DynTestName(String),
 }
 impl TestName {
     fn as_slice(&self) -> &str {
         match *self {
             StaticTestName(s) => s,
-            DynTestName(ref s) => s
+            DynTestName(ref s) => s,
         }
     }
 }
@@ -146,19 +144,19 @@ pub enum TestFn {
     StaticBenchFn(fn(&mut Bencher)),
     StaticMetricFn(fn(&mut MetricMap)),
     DynTestFn(Box<FnBox() + Send>),
-    DynMetricFn(Box<FnBox(&mut MetricMap)+Send>),
-    DynBenchFn(Box<TDynBenchFn+'static>)
+    DynMetricFn(Box<FnBox(&mut MetricMap) + Send>),
+    DynBenchFn(Box<TDynBenchFn + 'static>),
 }
 
 impl TestFn {
     fn padding(&self) -> NamePadding {
         match *self {
-            StaticTestFn(..)   => PadNone,
-            StaticBenchFn(..)  => PadOnRight,
+            StaticTestFn(..) => PadNone,
+            StaticBenchFn(..) => PadOnRight,
             StaticMetricFn(..) => PadOnRight,
-            DynTestFn(..)      => PadNone,
-            DynMetricFn(..)    => PadOnRight,
-            DynBenchFn(..)     => PadOnRight,
+            DynTestFn(..) => PadNone,
+            DynMetricFn(..) => PadOnRight,
+            DynBenchFn(..) => PadOnRight,
         }
     }
 }
@@ -171,7 +169,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             StaticMetricFn(..) => "StaticMetricFn(..)",
             DynTestFn(..) => "DynTestFn(..)",
             DynMetricFn(..) => "DynMetricFn(..)",
-            DynBenchFn(..) => "DynBenchFn(..)"
+            DynBenchFn(..) => "DynBenchFn(..)",
         })
     }
 }
@@ -192,7 +190,7 @@ pub struct Bencher {
 pub enum ShouldPanic {
     No,
     Yes,
-    YesWithMessage(&'static str)
+    YesWithMessage(&'static str),
 }
 
 // The definition of a single test. A test runner will run a list of
@@ -215,17 +213,20 @@ pub struct TestDescAndFn {
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Copy)]
 pub struct Metric {
     value: f64,
-    noise: f64
+    noise: f64,
 }
 
 impl Metric {
     pub fn new(value: f64, noise: f64) -> Metric {
-        Metric {value: value, noise: noise}
+        Metric {
+            value: value,
+            noise: noise,
+        }
     }
 }
 
 #[derive(PartialEq)]
-pub struct MetricMap(BTreeMap<String,Metric>);
+pub struct MetricMap(BTreeMap<String, Metric>);
 
 impl Clone for MetricMap {
     fn clone(&self) -> MetricMap {
@@ -236,13 +237,12 @@ fn clone(&self) -> MetricMap {
 
 // The default console test runner. It accepts the command line
 // arguments and a vector of test_descs.
-pub fn test_main(args: &[String], tests: Vec<TestDescAndFn> ) {
-    let opts =
-        match parse_opts(args) {
-            Some(Ok(o)) => o,
-            Some(Err(msg)) => panic!("{:?}", msg),
-            None => return
-        };
+pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>) {
+    let opts = match parse_opts(args) {
+        Some(Ok(o)) => o,
+        Some(Err(msg)) => panic!("{:?}", msg),
+        None => return,
+    };
     match run_tests_console(&opts, tests) {
         Ok(true) => {}
         Ok(false) => std::process::exit(101),
@@ -259,13 +259,25 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn> ) {
 // rather than a &[].
 pub fn test_main_static(tests: &[TestDescAndFn]) {
     let args = env::args().collect::<Vec<_>>();
-    let owned_tests = tests.iter().map(|t| {
-        match t.testfn {
-            StaticTestFn(f) => TestDescAndFn { testfn: StaticTestFn(f), desc: t.desc.clone() },
-            StaticBenchFn(f) => TestDescAndFn { testfn: StaticBenchFn(f), desc: t.desc.clone() },
-            _ => panic!("non-static tests passed to test::test_main_static")
-        }
-    }).collect();
+    let owned_tests = tests.iter()
+                           .map(|t| {
+                               match t.testfn {
+                                   StaticTestFn(f) => {
+                                       TestDescAndFn {
+                                           testfn: StaticTestFn(f),
+                                           desc: t.desc.clone(),
+                                       }
+                                   }
+                                   StaticBenchFn(f) => {
+                                       TestDescAndFn {
+                                           testfn: StaticBenchFn(f),
+                                           desc: t.desc.clone(),
+                                       }
+                                   }
+                                   _ => panic!("non-static tests passed to test::test_main_static"),
+                               }
+                           })
+                           .collect();
     test_main(&args, owned_tests)
 }
 
@@ -304,6 +316,7 @@ fn new() -> TestOpts {
 /// Result of parsing the options.
 pub type OptRes = Result<TestOpts, String>;
 
+#[cfg_attr(rustfmt, rustfmt_skip)]
 fn optgroups() -> Vec<getopts::OptGroup> {
     vec!(getopts::optflag("", "ignored", "Run ignored tests"),
       getopts::optflag("", "test", "Run tests and not benchmarks"),
@@ -353,13 +366,15 @@ fn usage(binary: &str) {
 // Parses command line arguments into test options
 pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     let args_ = &args[1..];
-    let matches =
-        match getopts::getopts(args_, &optgroups()) {
-          Ok(m) => m,
-          Err(f) => return Some(Err(f.to_string()))
-        };
+    let matches = match getopts::getopts(args_, &optgroups()) {
+        Ok(m) => m,
+        Err(f) => return Some(Err(f.to_string())),
+    };
 
-    if matches.opt_present("h") { usage(&args[0]); return None; }
+    if matches.opt_present("h") {
+        usage(&args[0]);
+        return None;
+    }
 
     let filter = if !matches.free.is_empty() {
         Some(matches.free[0].clone())
@@ -373,8 +388,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     let logfile = logfile.map(|s| PathBuf::from(&s));
 
     let bench_benchmarks = matches.opt_present("bench");
-    let run_tests = ! bench_benchmarks ||
-        matches.opt_present("test");
+    let run_tests = !bench_benchmarks || matches.opt_present("test");
 
     let mut nocapture = matches.opt_present("nocapture");
     if !nocapture {
@@ -386,9 +400,11 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         Some("always") => AlwaysColor,
         Some("never") => NeverColor,
 
-        Some(v) => return Some(Err(format!("argument for --color must be \
-                                            auto, always, or never (was {})",
-                                            v))),
+        Some(v) => {
+            return Some(Err(format!("argument for --color must be auto, always, or never (was \
+                                     {})",
+                                    v)))
+        }
     };
 
     let test_opts = TestOpts {
@@ -436,20 +452,19 @@ struct ConsoleTestState<T> {
     ignored: usize,
     measured: usize,
     metrics: MetricMap,
-    failures: Vec<(TestDesc, Vec<u8> )> ,
+    failures: Vec<(TestDesc, Vec<u8>)>,
     max_name_len: usize, // number of columns to fill when aligning names
 }
 
 impl<T: Write> ConsoleTestState<T> {
-    pub fn new(opts: &TestOpts,
-               _: Option<T>) -> io::Result<ConsoleTestState<io::Stdout>> {
+    pub fn new(opts: &TestOpts, _: Option<T>) -> io::Result<ConsoleTestState<io::Stdout>> {
         let log_out = match opts.logfile {
             Some(ref path) => Some(try!(File::create(path))),
-            None => None
+            None => None,
         };
         let out = match term::stdout() {
             None => Raw(io::stdout()),
-            Some(t) => Pretty(t)
+            Some(t) => Pretty(t),
         };
 
         Ok(ConsoleTestState {
@@ -487,9 +502,7 @@ pub fn write_bench(&mut self) -> io::Result<()> {
         self.write_pretty("bench", term::color::CYAN)
     }
 
-    pub fn write_pretty(&mut self,
-                        word: &str,
-                        color: term::color::Color) -> io::Result<()> {
+    pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
         match self.out {
             Pretty(ref mut term) => {
                 if self.use_color {
@@ -513,22 +526,25 @@ pub fn write_plain(&mut self, s: &str) -> io::Result<()> {
             Pretty(ref mut term) => {
                 try!(term.write_all(s.as_bytes()));
                 term.flush()
-            },
+            }
             Raw(ref mut stdout) => {
                 try!(stdout.write_all(s.as_bytes()));
                 stdout.flush()
-            },
+            }
         }
     }
 
     pub fn write_run_start(&mut self, len: usize) -> io::Result<()> {
         self.total = len;
-        let noun = if len != 1 { "tests" } else { "test" };
+        let noun = if len != 1 {
+            "tests"
+        } else {
+            "test"
+        };
         self.write_plain(&format!("\nrunning {} {}\n", len, noun))
     }
 
-    pub fn write_test_start(&mut self, test: &TestDesc,
-                            align: NamePadding) -> io::Result<()> {
+    pub fn write_test_start(&mut self, test: &TestDesc, align: NamePadding) -> io::Result<()> {
         let name = test.padded_name(self.max_name_len, align);
         self.write_plain(&format!("test {} ... ", name))
     }
@@ -553,18 +569,19 @@ pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> {
         self.write_plain("\n")
     }
 
-    pub fn write_log(&mut self, test: &TestDesc,
-                     result: &TestResult) -> io::Result<()> {
+    pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> {
         match self.log_out {
             None => Ok(()),
             Some(ref mut o) => {
-                let s = format!("{} {}\n", match *result {
-                        TrOk => "ok".to_owned(),
-                        TrFailed => "failed".to_owned(),
-                        TrIgnored => "ignored".to_owned(),
-                        TrMetrics(ref mm) => mm.fmt_metrics(),
-                        TrBench(ref bs) => fmt_bench_samples(bs)
-                    }, test.name);
+                let s = format!("{} {}\n",
+                                match *result {
+                                    TrOk => "ok".to_owned(),
+                                    TrFailed => "failed".to_owned(),
+                                    TrIgnored => "ignored".to_owned(),
+                                    TrMetrics(ref mm) => mm.fmt_metrics(),
+                                    TrBench(ref bs) => fmt_bench_samples(bs),
+                                },
+                                test.name);
                 o.write_all(s.as_bytes())
             }
         }
@@ -612,7 +629,10 @@ pub fn write_run_finish(&mut self) -> io::Result<bool> {
             try!(self.write_failed());
         }
         let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
-                        self.passed, self.failed, self.ignored, self.measured);
+                        self.passed,
+                        self.failed,
+                        self.ignored,
+                        self.measured);
         try!(self.write_plain(&s));
         return Ok(success);
     }
@@ -650,8 +670,9 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
     let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize;
 
     output.write_fmt(format_args!("{:>11} ns/iter (+/- {})",
-                     fmt_thousands_sep(median, ','),
-                     fmt_thousands_sep(deviation, ','))).unwrap();
+                                  fmt_thousands_sep(median, ','),
+                                  fmt_thousands_sep(deviation, ',')))
+          .unwrap();
     if bs.mb_s != 0 {
         output.write_fmt(format_args!(" = {} MB/s", bs.mb_s)).unwrap();
     }
@@ -659,10 +680,9 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> String {
 }
 
 // A simple console test runner
-pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> io::Result<bool> {
+pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<bool> {
 
-    fn callback<T: Write>(event: &TestEvent,
-                          st: &mut ConsoleTestState<T>) -> io::Result<()> {
+    fn callback<T: Write>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::Result<()> {
         match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
             TeWait(ref test, padding) => st.write_test_start(test, padding),
@@ -675,13 +695,9 @@ fn callback<T: Write>(event: &TestEvent,
                     TrMetrics(mm) => {
                         let tname = test.name;
                         let MetricMap(mm) = mm;
-                        for (k,v) in &mm {
+                        for (k, v) in &mm {
                             st.metrics
-                              .insert_metric(&format!("{}.{}",
-                                                      tname,
-                                                      k),
-                                             v.value,
-                                             v.noise);
+                              .insert_metric(&format!("{}.{}", tname, k), v.value, v.noise);
                         }
                         st.measured += 1
                     }
@@ -708,11 +724,11 @@ fn len_if_padded(t: &TestDescAndFn) -> usize {
             PadOnRight => t.desc.name.as_slice().len(),
         }
     }
-    match tests.iter().max_by_key(|t|len_if_padded(*t)) {
+    match tests.iter().max_by_key(|t| len_if_padded(*t)) {
         Some(t) => {
             let n = t.desc.name.as_slice();
             st.max_name_len = n.len();
-        },
+        }
         None => {}
     }
     try!(run_tests(opts, tests, |x| callback(&x, &mut st)));
@@ -724,13 +740,13 @@ fn should_sort_failures_before_printing_them() {
     let test_a = TestDesc {
         name: StaticTestName("a"),
         ignore: false,
-        should_panic: ShouldPanic::No
+        should_panic: ShouldPanic::No,
     };
 
     let test_b = TestDesc {
         name: StaticTestName("b"),
         ignore: false,
-        should_panic: ShouldPanic::No
+        should_panic: ShouldPanic::No,
     };
 
     let mut st = ConsoleTestState {
@@ -744,13 +760,13 @@ fn should_sort_failures_before_printing_them() {
         measured: 0,
         max_name_len: 10,
         metrics: MetricMap::new(),
-        failures: vec!((test_b, Vec::new()), (test_a, Vec::new()))
+        failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
     };
 
     st.write_failures().unwrap();
     let s = match st.out {
         Raw(ref m) => String::from_utf8_lossy(&m[..]),
-        Pretty(_) => unreachable!()
+        Pretty(_) => unreachable!(),
     };
 
     let apos = s.find("a").unwrap();
@@ -790,18 +806,16 @@ fn stdout_isatty() -> bool {
 
 #[derive(Clone)]
 enum TestEvent {
-    TeFiltered(Vec<TestDesc> ),
+    TeFiltered(Vec<TestDesc>),
     TeWait(TestDesc, NamePadding),
-    TeResult(TestDesc, TestResult, Vec<u8> ),
+    TeResult(TestDesc, TestResult, Vec<u8>),
 }
 
-pub type MonitorMsg = (TestDesc, TestResult, Vec<u8> );
+pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
 
 
-fn run_tests<F>(opts: &TestOpts,
-                tests: Vec<TestDescAndFn> ,
-                mut callback: F) -> io::Result<()> where
-    F: FnMut(TestEvent) -> io::Result<()>,
+fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
+    where F: FnMut(TestEvent) -> io::Result<()>
 {
     let mut filtered_tests = filter_tests(opts, tests);
     if !opts.bench_benchmarks {
@@ -818,7 +832,7 @@ fn run_tests<F>(opts: &TestOpts,
         filtered_tests.into_iter().partition(|e| {
             match e.testfn {
                 StaticTestFn(_) | DynTestFn(_) => true,
-                _ => false
+                _ => false,
             }
         });
 
@@ -873,7 +887,10 @@ fn get_concurrency() -> usize {
             let opt_n: Option<usize> = s.parse().ok();
             match opt_n {
                 Some(n) if n > 0 => n,
-                _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s)
+                _ => {
+                    panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.",
+                           s)
+                }
             }
         }
         Err(..) => num_cpus(),
@@ -911,9 +928,7 @@ struct SYSTEM_INFO {
               target_os = "ios",
               target_os = "android"))]
     fn num_cpus() -> usize {
-        unsafe {
-            libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
-        }
+        unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize }
     }
 
     #[cfg(any(target_os = "freebsd",
@@ -926,18 +941,22 @@ fn num_cpus() -> usize {
         let mut mib = [libc::CTL_HW, libc::HW_AVAILCPU, 0, 0];
 
         unsafe {
-            libc::sysctl(mib.as_mut_ptr(), 2,
+            libc::sysctl(mib.as_mut_ptr(),
+                         2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
-                         0 as *mut _, 0);
+                         0 as *mut _,
+                         0);
         }
         if cpus < 1 {
             mib[1] = libc::HW_NCPU;
             unsafe {
-                libc::sysctl(mib.as_mut_ptr(), 2,
+                libc::sysctl(mib.as_mut_ptr(),
+                             2,
                              &mut cpus as *mut _ as *mut _,
                              &mut cpus_size as *mut _ as *mut _,
-                             0 as *mut _, 0);
+                             0 as *mut _,
+                             0);
             }
             if cpus < 1 {
                 cpus = 1;
@@ -953,10 +972,12 @@ fn num_cpus() -> usize {
         let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
 
         unsafe {
-            libc::sysctl(mib.as_mut_ptr(), 2,
+            libc::sysctl(mib.as_mut_ptr(),
+                         2,
                          &mut cpus as *mut _ as *mut _,
                          &mut cpus_size as *mut _ as *mut _,
-                         0 as *mut _, 0);
+                         0 as *mut _,
+                         0);
         }
         if cpus < 1 {
             cpus = 1;
@@ -972,9 +993,9 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
     filtered = match opts.filter {
         None => filtered,
         Some(ref filter) => {
-            filtered.into_iter().filter(|test| {
-                test.desc.name.as_slice().contains(&filter[..])
-            }).collect()
+            filtered.into_iter()
+                    .filter(|test| test.desc.name.as_slice().contains(&filter[..]))
+                    .collect()
         }
     };
 
@@ -986,8 +1007,8 @@ fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
             if test.desc.ignore {
                 let TestDescAndFn {desc, testfn} = test;
                 Some(TestDescAndFn {
-                    desc: TestDesc {ignore: false, ..desc},
-                    testfn: testfn
+                    desc: TestDesc { ignore: false, ..desc },
+                    testfn: testfn,
                 })
             } else {
                 None
@@ -1004,18 +1025,23 @@ fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
 
 pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
     // convert benchmarks to tests, if we're not benchmarking them
-    tests.into_iter().map(|x| {
-        let testfn = match x.testfn {
-            DynBenchFn(bench) => {
-                DynTestFn(Box::new(move || bench::run_once(|b| bench.run(b))))
-            }
-            StaticBenchFn(benchfn) => {
-                DynTestFn(Box::new(move || bench::run_once(|b| benchfn(b))))
-            }
-            f => f
-        };
-        TestDescAndFn { desc: x.desc, testfn: testfn }
-    }).collect()
+    tests.into_iter()
+         .map(|x| {
+             let testfn = match x.testfn {
+                 DynBenchFn(bench) => {
+                     DynTestFn(Box::new(move || bench::run_once(|b| bench.run(b))))
+                 }
+                 StaticBenchFn(benchfn) => {
+                     DynTestFn(Box::new(move || bench::run_once(|b| benchfn(b))))
+                 }
+                 f => f,
+             };
+             TestDescAndFn {
+                 desc: x.desc,
+                 testfn: testfn,
+             }
+         })
+         .collect()
 }
 
 pub fn run_test(opts: &TestOpts,
@@ -1039,7 +1065,9 @@ impl Write for Sink {
             fn write(&mut self, data: &[u8]) -> io::Result<usize> {
                 Write::write(&mut *self.0.lock().unwrap(), data)
             }
-            fn flush(&mut self) -> io::Result<()> { Ok(()) }
+            fn flush(&mut self) -> io::Result<()> {
+                Ok(())
+            }
         }
 
         thread::spawn(move || {
@@ -1051,12 +1079,13 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
             });
 
             let result_guard = cfg.spawn(move || {
-                if !nocapture {
-                    io::set_print(box Sink(data2.clone()));
-                    io::set_panic(box Sink(data2));
-                }
-                testfn()
-            }).unwrap();
+                                      if !nocapture {
+                                          io::set_print(box Sink(data2.clone()));
+                                          io::set_panic(box Sink(data2));
+                                      }
+                                      testfn()
+                                  })
+                                  .unwrap();
             let test_result = calc_result(&desc, result_guard.join());
             let stdout = data.lock().unwrap().to_vec();
             monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
@@ -1087,27 +1116,25 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
             return;
         }
         DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
-        StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
-                                          Box::new(f))
+        StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(f)),
     }
 }
 
-fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any+Send>>) -> TestResult {
+fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> TestResult {
     match (&desc.should_panic, task_result) {
         (&ShouldPanic::No, Ok(())) |
         (&ShouldPanic::Yes, Err(_)) => TrOk,
         (&ShouldPanic::YesWithMessage(msg), Err(ref err))
             if err.downcast_ref::<String>()
-                .map(|e| &**e)
-                .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
-                .map(|e| e.contains(msg))
-                .unwrap_or(false) => TrOk,
+               .map(|e| &**e)
+               .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
+               .map(|e| e.contains(msg))
+               .unwrap_or(false) => TrOk,
         _ => TrFailed,
     }
 }
 
 impl MetricMap {
-
     pub fn new() -> MetricMap {
         MetricMap(BTreeMap::new())
     }
@@ -1128,7 +1155,7 @@ pub fn new() -> MetricMap {
     pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) {
         let m = Metric {
             value: value,
-            noise: noise
+            noise: noise,
         };
         let MetricMap(ref mut map) = *self;
         map.insert(name.to_owned(), m);
@@ -1136,10 +1163,9 @@ pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) {
 
     pub fn fmt_metrics(&self) -> String {
         let MetricMap(ref mm) = *self;
-        let v : Vec<String> = mm.iter()
-            .map(|(k,v)| format!("{}: {} (+/- {})", *k,
-                                 v.value, v.noise))
-            .collect();
+        let v: Vec<String> = mm.iter()
+                               .map(|(k, v)| format!("{}: {} (+/- {})", *k, v.value, v.noise))
+                               .collect();
         v.join(", ")
     }
 }
@@ -1156,17 +1182,21 @@ pub fn fmt_metrics(&self) -> String {
 pub fn black_box<T>(dummy: T) -> T {
     // we need to "use" the argument in some way LLVM can't
     // introspect.
-    unsafe {asm!("" : : "r"(&dummy))}
+    unsafe { asm!("" : : "r"(&dummy)) }
     dummy
 }
 #[cfg(all(target_os = "nacl", target_arch = "le32"))]
 #[inline(never)]
-pub fn black_box<T>(dummy: T) -> T { dummy }
+pub fn black_box<T>(dummy: T) -> T {
+    dummy
+}
 
 
 impl Bencher {
     /// Callback for benchmark functions to run in their body.
-    pub fn iter<T, F>(&mut self, mut inner: F) where F: FnMut() -> T {
+    pub fn iter<T, F>(&mut self, mut inner: F)
+        where F: FnMut() -> T
+    {
         let start = Instant::now();
         let k = self.iterations;
         for _ in 0..k {
@@ -1187,13 +1217,17 @@ pub fn ns_per_iter(&mut self) -> u64 {
         }
     }
 
-    pub fn bench_n<F>(&mut self, n: u64, f: F) where F: FnOnce(&mut Bencher) {
+    pub fn bench_n<F>(&mut self, n: u64, f: F)
+        where F: FnOnce(&mut Bencher)
+    {
         self.iterations = n;
         f(self);
     }
 
     // This is a more statistics-driven benchmark algorithm
-    pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) {
+    pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary
+        where F: FnMut(&mut Bencher)
+    {
         // Initial bench run to get ballpark figure.
         let mut n = 1;
         self.bench_n(n, |x| f(x));
@@ -1210,17 +1244,19 @@ pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut
         // side effect of not being able to do as many runs is
         // automatically handled by the statistical analysis below
         // (i.e. larger error bars).
-        if n == 0 { n = 1; }
+        if n == 0 {
+            n = 1;
+        }
 
         let mut total_run = Duration::new(0, 0);
-        let samples : &mut [f64] = &mut [0.0_f64; 50];
+        let samples: &mut [f64] = &mut [0.0_f64; 50];
         loop {
             let loop_start = Instant::now();
 
             for p in &mut *samples {
                 self.bench_n(n, |x| f(x));
                 *p = self.ns_per_iter() as f64;
-            };
+            }
 
             stats::winsorize(samples, 5.0);
             let summ = stats::Summary::new(samples);
@@ -1228,7 +1264,7 @@ pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut
             for p in &mut *samples {
                 self.bench_n(5 * n, |x| f(x));
                 *p = self.ns_per_iter() as f64;
-            };
+            }
 
             stats::winsorize(samples, 5.0);
             let summ5 = stats::Summary::new(samples);
@@ -1236,9 +1272,8 @@ pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut
 
             // If we've run for 100ms and seem to have converged to a
             // stable median.
-            if loop_run > Duration::from_millis(100) &&
-                summ.median_abs_dev_pct < 1.0 &&
-                summ.median - summ5.median < summ5.median_abs_dev {
+            if loop_run > Duration::from_millis(100) && summ.median_abs_dev_pct < 1.0 &&
+               summ.median - summ5.median < summ5.median_abs_dev {
                 return summ5;
             }
 
@@ -1265,11 +1300,13 @@ pub mod bench {
     use std::time::Duration;
     use super::{Bencher, BenchSamples};
 
-    pub fn benchmark<F>(f: F) -> BenchSamples where F: FnMut(&mut Bencher) {
+    pub fn benchmark<F>(f: F) -> BenchSamples
+        where F: FnMut(&mut Bencher)
+    {
         let mut bs = Bencher {
             iterations: 0,
             dur: Duration::new(0, 0),
-            bytes: 0
+            bytes: 0,
         };
 
         let ns_iter_summ = bs.auto_bench(f);
@@ -1279,15 +1316,17 @@ pub fn benchmark<F>(f: F) -> BenchSamples where F: FnMut(&mut Bencher) {
 
         BenchSamples {
             ns_iter_summ: ns_iter_summ,
-            mb_s: mb_s as usize
+            mb_s: mb_s as usize,
         }
     }
 
-    pub fn run_once<F>(f: F) where F: FnOnce(&mut Bencher) {
+    pub fn run_once<F>(f: F)
+        where F: FnOnce(&mut Bencher)
+    {
         let mut bs = Bencher {
             iterations: 0,
             dur: Duration::new(0, 0),
-            bytes: 0
+            bytes: 0,
         };
         bs.bench_n(1, f);
     }
@@ -1295,22 +1334,22 @@ pub fn run_once<F>(f: F) where F: FnOnce(&mut Bencher) {
 
 #[cfg(test)]
 mod tests {
-    use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts,
-               TestDesc, TestDescAndFn, TestOpts, run_test,
-               MetricMap,
-               StaticTestName, DynTestName, DynTestFn, ShouldPanic};
+    use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, TestDescAndFn,
+               TestOpts, run_test, MetricMap, StaticTestName, DynTestName, DynTestFn, ShouldPanic};
     use std::sync::mpsc::channel;
 
     #[test]
     pub fn do_not_run_ignored_tests() {
-        fn f() { panic!(); }
+        fn f() {
+            panic!();
+        }
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1320,14 +1359,14 @@ pub fn do_not_run_ignored_tests() {
 
     #[test]
     pub fn ignored_tests_result_in_ignored() {
-        fn f() { }
+        fn f() {}
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1337,14 +1376,16 @@ fn f() { }
 
     #[test]
     fn test_should_panic() {
-        fn f() { panic!(); }
+        fn f() {
+            panic!();
+        }
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1354,14 +1395,16 @@ fn test_should_panic() {
 
     #[test]
     fn test_should_panic_good_message() {
-        fn f() { panic!("an error message"); }
+        fn f() {
+            panic!("an error message");
+        }
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage("error message"),
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1371,14 +1414,16 @@ fn test_should_panic_good_message() {
 
     #[test]
     fn test_should_panic_bad_message() {
-        fn f() { panic!("an error message"); }
+        fn f() {
+            panic!("an error message");
+        }
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage("foobar"),
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1388,14 +1433,14 @@ fn test_should_panic_bad_message() {
 
     #[test]
     fn test_should_panic_but_succeeds() {
-        fn f() { }
+        fn f() {}
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
             },
-            testfn: DynTestFn(Box::new(move|| f())),
+            testfn: DynTestFn(Box::new(move || f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1405,12 +1450,10 @@ fn f() { }
 
     #[test]
     fn parse_ignored_flag() {
-        let args = vec!("progname".to_string(),
-                        "filter".to_string(),
-                        "--ignored".to_string());
+        let args = vec!["progname".to_string(), "filter".to_string(), "--ignored".to_string()];
         let opts = match parse_opts(&args) {
             Some(Ok(o)) => o,
-            _ => panic!("Malformed arg in parse_ignored_flag")
+            _ => panic!("Malformed arg in parse_ignored_flag"),
         };
         assert!((opts.run_ignored));
     }
@@ -1424,28 +1467,26 @@ pub fn filter_for_ignored_option() {
         opts.run_tests = true;
         opts.run_ignored = true;
 
-        let tests = vec!(
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("1"),
-                    ignore: true,
-                    should_panic: ShouldPanic::No,
-                },
-                testfn: DynTestFn(Box::new(move|| {})),
-            },
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("2"),
-                    ignore: false,
-                    should_panic: ShouldPanic::No,
-                },
-                testfn: DynTestFn(Box::new(move|| {})),
-            });
+        let tests = vec![TestDescAndFn {
+                             desc: TestDesc {
+                                 name: StaticTestName("1"),
+                                 ignore: true,
+                                 should_panic: ShouldPanic::No,
+                             },
+                             testfn: DynTestFn(Box::new(move || {})),
+                         },
+                         TestDescAndFn {
+                             desc: TestDesc {
+                                 name: StaticTestName("2"),
+                                 ignore: false,
+                                 should_panic: ShouldPanic::No,
+                             },
+                             testfn: DynTestFn(Box::new(move || {})),
+                         }];
         let filtered = filter_tests(&opts, tests);
 
         assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].desc.name.to_string(),
-                   "1");
+        assert_eq!(filtered[0].desc.name.to_string(), "1");
         assert!(filtered[0].desc.ignore == false);
     }
 
@@ -1454,19 +1495,17 @@ pub fn sort_tests() {
         let mut opts = TestOpts::new();
         opts.run_tests = true;
 
-        let names =
-            vec!("sha1::test".to_string(),
-                 "isize::test_to_str".to_string(),
-                 "isize::test_pow".to_string(),
-                 "test::do_not_run_ignored_tests".to_string(),
-                 "test::ignored_tests_result_in_ignored".to_string(),
-                 "test::first_free_arg_should_be_a_filter".to_string(),
-                 "test::parse_ignored_flag".to_string(),
-                 "test::filter_for_ignored_option".to_string(),
-                 "test::sort_tests".to_string());
-        let tests =
-        {
-            fn testfn() { }
+        let names = vec!["sha1::test".to_string(),
+                         "isize::test_to_str".to_string(),
+                         "isize::test_pow".to_string(),
+                         "test::do_not_run_ignored_tests".to_string(),
+                         "test::ignored_tests_result_in_ignored".to_string(),
+                         "test::first_free_arg_should_be_a_filter".to_string(),
+                         "test::parse_ignored_flag".to_string(),
+                         "test::filter_for_ignored_option".to_string(),
+                         "test::sort_tests".to_string()];
+        let tests = {
+            fn testfn() {}
             let mut tests = Vec::new();
             for name in &names {
                 let test = TestDescAndFn {
@@ -1483,16 +1522,15 @@ fn testfn() { }
         };
         let filtered = filter_tests(&opts, tests);
 
-        let expected =
-            vec!("isize::test_pow".to_string(),
-                 "isize::test_to_str".to_string(),
-                 "sha1::test".to_string(),
-                 "test::do_not_run_ignored_tests".to_string(),
-                 "test::filter_for_ignored_option".to_string(),
-                 "test::first_free_arg_should_be_a_filter".to_string(),
-                 "test::ignored_tests_result_in_ignored".to_string(),
-                 "test::parse_ignored_flag".to_string(),
-                 "test::sort_tests".to_string());
+        let expected = vec!["isize::test_pow".to_string(),
+                            "isize::test_to_str".to_string(),
+                            "sha1::test".to_string(),
+                            "test::do_not_run_ignored_tests".to_string(),
+                            "test::filter_for_ignored_option".to_string(),
+                            "test::first_free_arg_should_be_a_filter".to_string(),
+                            "test::ignored_tests_result_in_ignored".to_string(),
+                            "test::parse_ignored_flag".to_string(),
+                            "test::sort_tests".to_string()];
 
         for (a, b) in expected.iter().zip(filtered) {
             assert!(*a == b.desc.name.to_string());
index c1ba1260f67e120fdd058c04f6fbf68fc0f13b4a..335b6d67209dedcde22a3ecbcaf0a1cc0298094d 100644 (file)
@@ -111,7 +111,7 @@ pub trait Stats {
     /// is otherwise equivalent.
     ///
     /// See also: https://en.wikipedia.org/wiki/Quartile
-    fn quartiles(&self) -> (f64,f64,f64);
+    fn quartiles(&self) -> (f64, f64, f64);
 
     /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
     /// percentile (3rd quartile). See `quartiles`.
@@ -134,7 +134,7 @@ pub struct Summary {
     pub std_dev_pct: f64,
     pub median_abs_dev: f64,
     pub median_abs_dev_pct: f64,
-    pub quartiles: (f64,f64,f64),
+    pub quartiles: (f64, f64, f64),
     pub iqr: f64,
 }
 
@@ -153,7 +153,7 @@ pub fn new(samples: &[f64]) -> Summary {
             median_abs_dev: samples.median_abs_dev(),
             median_abs_dev_pct: samples.median_abs_dev_pct(),
             quartiles: samples.quartiles(),
-            iqr: samples.iqr()
+            iqr: samples.iqr(),
         }
     }
 }
@@ -187,7 +187,7 @@ fn sum(&self) -> f64 {
                 partials.push(x);
             } else {
                 partials[j] = x;
-                partials.truncate(j+1);
+                partials.truncate(j + 1);
             }
         }
         let zero: f64 = 0.0;
@@ -221,13 +221,13 @@ fn var(&self) -> f64 {
             let mut v: f64 = 0.0;
             for s in self {
                 let x = *s - mean;
-                v = v + x*x;
+                v = v + x * x;
             }
             // NB: this is _supposed to be_ len-1, not len. If you
             // change it back to len, you will be calculating a
             // population variance, not a sample variance.
             let denom = (self.len() - 1) as f64;
-            v/denom
+            v / denom
         }
     }
 
@@ -260,7 +260,7 @@ fn percentile(&self, pct: f64) -> f64 {
         percentile_of_sorted(&tmp, pct)
     }
 
-    fn quartiles(&self) -> (f64,f64,f64) {
+    fn quartiles(&self) -> (f64, f64, f64) {
         let mut tmp = self.to_vec();
         local_sort(&mut tmp);
         let first = 25f64;
@@ -269,11 +269,11 @@ fn quartiles(&self) -> (f64,f64,f64) {
         let b = percentile_of_sorted(&tmp, secound);
         let third = 75f64;
         let c = percentile_of_sorted(&tmp, third);
-        (a,b,c)
+        (a, b, c)
     }
 
     fn iqr(&self) -> f64 {
-        let (a,_,c) = self.quartiles();
+        let (a, _, c) = self.quartiles();
         c - a
     }
 }
@@ -299,7 +299,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
     let d = rank - lrank;
     let n = lrank as usize;
     let lo = sorted_samples[n];
-    let hi = sorted_samples[n+1];
+    let hi = sorted_samples[n + 1];
     lo + (hi - lo) * d
 }
 
@@ -316,7 +316,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) {
     local_sort(&mut tmp);
     let lo = percentile_of_sorted(&tmp, pct);
     let hundred = 100 as f64;
-    let hi = percentile_of_sorted(&tmp, hundred-pct);
+    let hi = percentile_of_sorted(&tmp, hundred - pct);
     for samp in samples {
         if *samp > hi {
             *samp = hi
@@ -380,10 +380,7 @@ fn test_min_max_nan() {
 
     #[test]
     fn test_norm2() {
-        let val = &[
-            958.0000000000,
-            924.0000000000,
-        ];
+        let val = &[958.0000000000, 924.0000000000];
         let summ = &Summary {
             sum: 1882.0000000000,
             min: 924.0000000000,
@@ -395,25 +392,23 @@ fn test_norm2() {
             std_dev_pct: 2.5549022912,
             median_abs_dev: 25.2042000000,
             median_abs_dev_pct: 2.6784484591,
-            quartiles: (932.5000000000,941.0000000000,949.5000000000),
+            quartiles: (932.5000000000, 941.0000000000, 949.5000000000),
             iqr: 17.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_norm10narrow() {
-        let val = &[
-            966.0000000000,
-            985.0000000000,
-            1110.0000000000,
-            848.0000000000,
-            821.0000000000,
-            975.0000000000,
-            962.0000000000,
-            1157.0000000000,
-            1217.0000000000,
-            955.0000000000,
-        ];
+        let val = &[966.0000000000,
+                    985.0000000000,
+                    1110.0000000000,
+                    848.0000000000,
+                    821.0000000000,
+                    975.0000000000,
+                    962.0000000000,
+                    1157.0000000000,
+                    1217.0000000000,
+                    955.0000000000];
         let summ = &Summary {
             sum: 9996.0000000000,
             min: 821.0000000000,
@@ -425,25 +420,23 @@ fn test_norm10narrow() {
             std_dev_pct: 12.6742097933,
             median_abs_dev: 102.2994000000,
             median_abs_dev_pct: 10.5408964451,
-            quartiles: (956.7500000000,970.5000000000,1078.7500000000),
+            quartiles: (956.7500000000, 970.5000000000, 1078.7500000000),
             iqr: 122.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_norm10medium() {
-        let val = &[
-            954.0000000000,
-            1064.0000000000,
-            855.0000000000,
-            1000.0000000000,
-            743.0000000000,
-            1084.0000000000,
-            704.0000000000,
-            1023.0000000000,
-            357.0000000000,
-            869.0000000000,
-        ];
+        let val = &[954.0000000000,
+                    1064.0000000000,
+                    855.0000000000,
+                    1000.0000000000,
+                    743.0000000000,
+                    1084.0000000000,
+                    704.0000000000,
+                    1023.0000000000,
+                    357.0000000000,
+                    869.0000000000];
         let summ = &Summary {
             sum: 8653.0000000000,
             min: 357.0000000000,
@@ -455,25 +448,23 @@ fn test_norm10medium() {
             std_dev_pct: 25.4846418487,
             median_abs_dev: 195.7032000000,
             median_abs_dev_pct: 21.4704552935,
-            quartiles: (771.0000000000,911.5000000000,1017.2500000000),
+            quartiles: (771.0000000000, 911.5000000000, 1017.2500000000),
             iqr: 246.2500000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_norm10wide() {
-        let val = &[
-            505.0000000000,
-            497.0000000000,
-            1591.0000000000,
-            887.0000000000,
-            1026.0000000000,
-            136.0000000000,
-            1580.0000000000,
-            940.0000000000,
-            754.0000000000,
-            1433.0000000000,
-        ];
+        let val = &[505.0000000000,
+                    497.0000000000,
+                    1591.0000000000,
+                    887.0000000000,
+                    1026.0000000000,
+                    136.0000000000,
+                    1580.0000000000,
+                    940.0000000000,
+                    754.0000000000,
+                    1433.0000000000];
         let summ = &Summary {
             sum: 9349.0000000000,
             min: 136.0000000000,
@@ -485,40 +476,38 @@ fn test_norm10wide() {
             std_dev_pct: 52.3146817750,
             median_abs_dev: 611.5725000000,
             median_abs_dev_pct: 66.9482758621,
-            quartiles: (567.2500000000,913.5000000000,1331.2500000000),
+            quartiles: (567.2500000000, 913.5000000000, 1331.2500000000),
             iqr: 764.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_norm25verynarrow() {
-        let val = &[
-            991.0000000000,
-            1018.0000000000,
-            998.0000000000,
-            1013.0000000000,
-            974.0000000000,
-            1007.0000000000,
-            1014.0000000000,
-            999.0000000000,
-            1011.0000000000,
-            978.0000000000,
-            985.0000000000,
-            999.0000000000,
-            983.0000000000,
-            982.0000000000,
-            1015.0000000000,
-            1002.0000000000,
-            977.0000000000,
-            948.0000000000,
-            1040.0000000000,
-            974.0000000000,
-            996.0000000000,
-            989.0000000000,
-            1015.0000000000,
-            994.0000000000,
-            1024.0000000000,
-        ];
+        let val = &[991.0000000000,
+                    1018.0000000000,
+                    998.0000000000,
+                    1013.0000000000,
+                    974.0000000000,
+                    1007.0000000000,
+                    1014.0000000000,
+                    999.0000000000,
+                    1011.0000000000,
+                    978.0000000000,
+                    985.0000000000,
+                    999.0000000000,
+                    983.0000000000,
+                    982.0000000000,
+                    1015.0000000000,
+                    1002.0000000000,
+                    977.0000000000,
+                    948.0000000000,
+                    1040.0000000000,
+                    974.0000000000,
+                    996.0000000000,
+                    989.0000000000,
+                    1015.0000000000,
+                    994.0000000000,
+                    1024.0000000000];
         let summ = &Summary {
             sum: 24926.0000000000,
             min: 948.0000000000,
@@ -530,25 +519,23 @@ fn test_norm25verynarrow() {
             std_dev_pct: 1.9888308788,
             median_abs_dev: 22.2390000000,
             median_abs_dev_pct: 2.2283567134,
-            quartiles: (983.0000000000,998.0000000000,1013.0000000000),
+            quartiles: (983.0000000000, 998.0000000000, 1013.0000000000),
             iqr: 30.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_exp10a() {
-        let val = &[
-            23.0000000000,
-            11.0000000000,
-            2.0000000000,
-            57.0000000000,
-            4.0000000000,
-            12.0000000000,
-            5.0000000000,
-            29.0000000000,
-            3.0000000000,
-            21.0000000000,
-        ];
+        let val = &[23.0000000000,
+                    11.0000000000,
+                    2.0000000000,
+                    57.0000000000,
+                    4.0000000000,
+                    12.0000000000,
+                    5.0000000000,
+                    29.0000000000,
+                    3.0000000000,
+                    21.0000000000];
         let summ = &Summary {
             sum: 167.0000000000,
             min: 2.0000000000,
@@ -560,25 +547,23 @@ fn test_exp10a() {
             std_dev_pct: 101.5828843560,
             median_abs_dev: 13.3434000000,
             median_abs_dev_pct: 116.0295652174,
-            quartiles: (4.2500000000,11.5000000000,22.5000000000),
+            quartiles: (4.2500000000, 11.5000000000, 22.5000000000),
             iqr: 18.2500000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_exp10b() {
-        let val = &[
-            24.0000000000,
-            17.0000000000,
-            6.0000000000,
-            38.0000000000,
-            25.0000000000,
-            7.0000000000,
-            51.0000000000,
-            2.0000000000,
-            61.0000000000,
-            32.0000000000,
-        ];
+        let val = &[24.0000000000,
+                    17.0000000000,
+                    6.0000000000,
+                    38.0000000000,
+                    25.0000000000,
+                    7.0000000000,
+                    51.0000000000,
+                    2.0000000000,
+                    61.0000000000,
+                    32.0000000000];
         let summ = &Summary {
             sum: 263.0000000000,
             min: 2.0000000000,
@@ -590,25 +575,23 @@ fn test_exp10b() {
             std_dev_pct: 74.4671410520,
             median_abs_dev: 22.9803000000,
             median_abs_dev_pct: 93.7971428571,
-            quartiles: (9.5000000000,24.5000000000,36.5000000000),
+            quartiles: (9.5000000000, 24.5000000000, 36.5000000000),
             iqr: 27.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_exp10c() {
-        let val = &[
-            71.0000000000,
-            2.0000000000,
-            32.0000000000,
-            1.0000000000,
-            6.0000000000,
-            28.0000000000,
-            13.0000000000,
-            37.0000000000,
-            16.0000000000,
-            36.0000000000,
-        ];
+        let val = &[71.0000000000,
+                    2.0000000000,
+                    32.0000000000,
+                    1.0000000000,
+                    6.0000000000,
+                    28.0000000000,
+                    13.0000000000,
+                    37.0000000000,
+                    16.0000000000,
+                    36.0000000000];
         let summ = &Summary {
             sum: 242.0000000000,
             min: 1.0000000000,
@@ -620,40 +603,38 @@ fn test_exp10c() {
             std_dev_pct: 88.4507754589,
             median_abs_dev: 21.4977000000,
             median_abs_dev_pct: 97.7168181818,
-            quartiles: (7.7500000000,22.0000000000,35.0000000000),
+            quartiles: (7.7500000000, 22.0000000000, 35.0000000000),
             iqr: 27.2500000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_exp25() {
-        let val = &[
-            3.0000000000,
-            24.0000000000,
-            1.0000000000,
-            19.0000000000,
-            7.0000000000,
-            5.0000000000,
-            30.0000000000,
-            39.0000000000,
-            31.0000000000,
-            13.0000000000,
-            25.0000000000,
-            48.0000000000,
-            1.0000000000,
-            6.0000000000,
-            42.0000000000,
-            63.0000000000,
-            2.0000000000,
-            12.0000000000,
-            108.0000000000,
-            26.0000000000,
-            1.0000000000,
-            7.0000000000,
-            44.0000000000,
-            25.0000000000,
-            11.0000000000,
-        ];
+        let val = &[3.0000000000,
+                    24.0000000000,
+                    1.0000000000,
+                    19.0000000000,
+                    7.0000000000,
+                    5.0000000000,
+                    30.0000000000,
+                    39.0000000000,
+                    31.0000000000,
+                    13.0000000000,
+                    25.0000000000,
+                    48.0000000000,
+                    1.0000000000,
+                    6.0000000000,
+                    42.0000000000,
+                    63.0000000000,
+                    2.0000000000,
+                    12.0000000000,
+                    108.0000000000,
+                    26.0000000000,
+                    1.0000000000,
+                    7.0000000000,
+                    44.0000000000,
+                    25.0000000000,
+                    11.0000000000];
         let summ = &Summary {
             sum: 593.0000000000,
             min: 1.0000000000,
@@ -665,40 +646,38 @@ fn test_exp25() {
             std_dev_pct: 103.3565983562,
             median_abs_dev: 19.2738000000,
             median_abs_dev_pct: 101.4410526316,
-            quartiles: (6.0000000000,19.0000000000,31.0000000000),
+            quartiles: (6.0000000000, 19.0000000000, 31.0000000000),
             iqr: 25.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_binom25() {
-        let val = &[
-            18.0000000000,
-            17.0000000000,
-            27.0000000000,
-            15.0000000000,
-            21.0000000000,
-            25.0000000000,
-            17.0000000000,
-            24.0000000000,
-            25.0000000000,
-            24.0000000000,
-            26.0000000000,
-            26.0000000000,
-            23.0000000000,
-            15.0000000000,
-            23.0000000000,
-            17.0000000000,
-            18.0000000000,
-            18.0000000000,
-            21.0000000000,
-            16.0000000000,
-            15.0000000000,
-            31.0000000000,
-            20.0000000000,
-            17.0000000000,
-            15.0000000000,
-        ];
+        let val = &[18.0000000000,
+                    17.0000000000,
+                    27.0000000000,
+                    15.0000000000,
+                    21.0000000000,
+                    25.0000000000,
+                    17.0000000000,
+                    24.0000000000,
+                    25.0000000000,
+                    24.0000000000,
+                    26.0000000000,
+                    26.0000000000,
+                    23.0000000000,
+                    15.0000000000,
+                    23.0000000000,
+                    17.0000000000,
+                    18.0000000000,
+                    18.0000000000,
+                    21.0000000000,
+                    16.0000000000,
+                    15.0000000000,
+                    31.0000000000,
+                    20.0000000000,
+                    17.0000000000,
+                    15.0000000000];
         let summ = &Summary {
             sum: 514.0000000000,
             min: 15.0000000000,
@@ -710,40 +689,38 @@ fn test_binom25() {
             std_dev_pct: 22.2037202539,
             median_abs_dev: 5.9304000000,
             median_abs_dev_pct: 29.6520000000,
-            quartiles: (17.0000000000,20.0000000000,24.0000000000),
+            quartiles: (17.0000000000, 20.0000000000, 24.0000000000),
             iqr: 7.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_pois25lambda30() {
-        let val = &[
-            27.0000000000,
-            33.0000000000,
-            34.0000000000,
-            34.0000000000,
-            24.0000000000,
-            39.0000000000,
-            28.0000000000,
-            27.0000000000,
-            31.0000000000,
-            28.0000000000,
-            38.0000000000,
-            21.0000000000,
-            33.0000000000,
-            36.0000000000,
-            29.0000000000,
-            37.0000000000,
-            32.0000000000,
-            34.0000000000,
-            31.0000000000,
-            39.0000000000,
-            25.0000000000,
-            31.0000000000,
-            32.0000000000,
-            40.0000000000,
-            24.0000000000,
-        ];
+        let val = &[27.0000000000,
+                    33.0000000000,
+                    34.0000000000,
+                    34.0000000000,
+                    24.0000000000,
+                    39.0000000000,
+                    28.0000000000,
+                    27.0000000000,
+                    31.0000000000,
+                    28.0000000000,
+                    38.0000000000,
+                    21.0000000000,
+                    33.0000000000,
+                    36.0000000000,
+                    29.0000000000,
+                    37.0000000000,
+                    32.0000000000,
+                    34.0000000000,
+                    31.0000000000,
+                    39.0000000000,
+                    25.0000000000,
+                    31.0000000000,
+                    32.0000000000,
+                    40.0000000000,
+                    24.0000000000];
         let summ = &Summary {
             sum: 787.0000000000,
             min: 21.0000000000,
@@ -755,40 +732,38 @@ fn test_pois25lambda30() {
             std_dev_pct: 16.3814245145,
             median_abs_dev: 5.9304000000,
             median_abs_dev_pct: 18.5325000000,
-            quartiles: (28.0000000000,32.0000000000,34.0000000000),
+            quartiles: (28.0000000000, 32.0000000000, 34.0000000000),
             iqr: 6.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_pois25lambda40() {
-        let val = &[
-            42.0000000000,
-            50.0000000000,
-            42.0000000000,
-            46.0000000000,
-            34.0000000000,
-            45.0000000000,
-            34.0000000000,
-            49.0000000000,
-            39.0000000000,
-            28.0000000000,
-            40.0000000000,
-            35.0000000000,
-            37.0000000000,
-            39.0000000000,
-            46.0000000000,
-            44.0000000000,
-            32.0000000000,
-            45.0000000000,
-            42.0000000000,
-            37.0000000000,
-            48.0000000000,
-            42.0000000000,
-            33.0000000000,
-            42.0000000000,
-            48.0000000000,
-        ];
+        let val = &[42.0000000000,
+                    50.0000000000,
+                    42.0000000000,
+                    46.0000000000,
+                    34.0000000000,
+                    45.0000000000,
+                    34.0000000000,
+                    49.0000000000,
+                    39.0000000000,
+                    28.0000000000,
+                    40.0000000000,
+                    35.0000000000,
+                    37.0000000000,
+                    39.0000000000,
+                    46.0000000000,
+                    44.0000000000,
+                    32.0000000000,
+                    45.0000000000,
+                    42.0000000000,
+                    37.0000000000,
+                    48.0000000000,
+                    42.0000000000,
+                    33.0000000000,
+                    42.0000000000,
+                    48.0000000000];
         let summ = &Summary {
             sum: 1019.0000000000,
             min: 28.0000000000,
@@ -800,40 +775,38 @@ fn test_pois25lambda40() {
             std_dev_pct: 14.3978417577,
             median_abs_dev: 5.9304000000,
             median_abs_dev_pct: 14.1200000000,
-            quartiles: (37.0000000000,42.0000000000,45.0000000000),
+            quartiles: (37.0000000000, 42.0000000000, 45.0000000000),
             iqr: 8.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_pois25lambda50() {
-        let val = &[
-            45.0000000000,
-            43.0000000000,
-            44.0000000000,
-            61.0000000000,
-            51.0000000000,
-            53.0000000000,
-            59.0000000000,
-            52.0000000000,
-            49.0000000000,
-            51.0000000000,
-            51.0000000000,
-            50.0000000000,
-            49.0000000000,
-            56.0000000000,
-            42.0000000000,
-            52.0000000000,
-            51.0000000000,
-            43.0000000000,
-            48.0000000000,
-            48.0000000000,
-            50.0000000000,
-            42.0000000000,
-            43.0000000000,
-            42.0000000000,
-            60.0000000000,
-        ];
+        let val = &[45.0000000000,
+                    43.0000000000,
+                    44.0000000000,
+                    61.0000000000,
+                    51.0000000000,
+                    53.0000000000,
+                    59.0000000000,
+                    52.0000000000,
+                    49.0000000000,
+                    51.0000000000,
+                    51.0000000000,
+                    50.0000000000,
+                    49.0000000000,
+                    56.0000000000,
+                    42.0000000000,
+                    52.0000000000,
+                    51.0000000000,
+                    43.0000000000,
+                    48.0000000000,
+                    48.0000000000,
+                    50.0000000000,
+                    42.0000000000,
+                    43.0000000000,
+                    42.0000000000,
+                    60.0000000000];
         let summ = &Summary {
             sum: 1235.0000000000,
             min: 42.0000000000,
@@ -845,40 +818,38 @@ fn test_pois25lambda50() {
             std_dev_pct: 11.3913245723,
             median_abs_dev: 4.4478000000,
             median_abs_dev_pct: 8.8956000000,
-            quartiles: (44.0000000000,50.0000000000,52.0000000000),
+            quartiles: (44.0000000000, 50.0000000000, 52.0000000000),
             iqr: 8.0000000000,
         };
         check(val, summ);
     }
     #[test]
     fn test_unif25() {
-        let val = &[
-            99.0000000000,
-            55.0000000000,
-            92.0000000000,
-            79.0000000000,
-            14.0000000000,
-            2.0000000000,
-            33.0000000000,
-            49.0000000000,
-            3.0000000000,
-            32.0000000000,
-            84.0000000000,
-            59.0000000000,
-            22.0000000000,
-            86.0000000000,
-            76.0000000000,
-            31.0000000000,
-            29.0000000000,
-            11.0000000000,
-            41.0000000000,
-            53.0000000000,
-            45.0000000000,
-            44.0000000000,
-            98.0000000000,
-            98.0000000000,
-            7.0000000000,
-        ];
+        let val = &[99.0000000000,
+                    55.0000000000,
+                    92.0000000000,
+                    79.0000000000,
+                    14.0000000000,
+                    2.0000000000,
+                    33.0000000000,
+                    49.0000000000,
+                    3.0000000000,
+                    32.0000000000,
+                    84.0000000000,
+                    59.0000000000,
+                    22.0000000000,
+                    86.0000000000,
+                    76.0000000000,
+                    31.0000000000,
+                    29.0000000000,
+                    11.0000000000,
+                    41.0000000000,
+                    53.0000000000,
+                    45.0000000000,
+                    44.0000000000,
+                    98.0000000000,
+                    98.0000000000,
+                    7.0000000000];
         let summ = &Summary {
             sum: 1242.0000000000,
             min: 2.0000000000,
@@ -890,7 +861,7 @@ fn test_unif25() {
             std_dev_pct: 64.1488719719,
             median_abs_dev: 45.9606000000,
             median_abs_dev_pct: 102.1346666667,
-            quartiles: (29.0000000000,45.0000000000,79.0000000000),
+            quartiles: (29.0000000000, 45.0000000000, 79.0000000000),
             iqr: 50.0000000000,
         };
         check(val, summ);
@@ -920,7 +891,7 @@ pub fn sum_three_items(b: &mut Bencher) {
     #[bench]
     pub fn sum_many_f64(b: &mut Bencher) {
         let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
-        let v = (0..500).map(|i| nums[i%5]).collect::<Vec<_>>();
+        let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
 
         b.iter(|| {
             v.sum();
index f7895d694c8246923e15c57a8839c0811ff62ff6..320cd3dbd851a4e638f5c008da30c4de74413c46 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <stdint.h>
 #include <assert.h>
+#include <stdarg.h>
 
 // These functions are used in the unit tests for C ABI calls.
 
@@ -222,3 +223,18 @@ uint64_t get_z(struct S s) {
 uint64_t get_c_many_params(void *a, void *b, void *c, void *d, struct quad f) {
     return f.c;
 }
+
+// Calculates the average of `(x + y) / n` where x: i64, y: f64. There must be exactly n pairs
+// passed as variadic arguments.
+double rust_interesting_average(uint64_t n, ...) {
+    va_list pairs;
+    double sum = 0.0;
+    int i;
+    va_start(pairs, n);
+    for(i = 0; i < n; i += 1) {
+        sum += (double)va_arg(pairs, int64_t);
+        sum += va_arg(pairs, double);
+    }
+    va_end(pairs);
+    return sum / n;
+}
index b862fc1a1f461b00f3f670173fe10e8882fec305..5f8948ac5f1e9e41efa0e2eb9fb2c9bc940d699f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-msvc everything is the system allocator on msvc
+// ignore-windows everything is the system allocator on windows
 // ignore-musl no dylibs on musl yet
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
index e75cb2a75cf580036e5492dbbb6a21460fed593b..b29797f3295262b8daa1716169f730b5968913d9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-msvc everything is the system allocator on msvc
+// ignore-windows everything is the system allocator on windows
 // ignore-musl no dylibs on musl right now
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
index 6ae0dad0e7bfbd485a4370d0b2fd06f86c770423..61e4a1ea3975ccd9d2f966421bd4ef2a92ad871d 100644 (file)
@@ -29,9 +29,8 @@ fn main() {
     let e3 = E::Empty3; //~ ERROR `E::Empty3` is the name of a struct or struct variant
     let e3 = E::Empty3(); //~ ERROR `E::Empty3` is the name of a struct or struct variant
 
-    // FIXME: non-local struct kind should be known early (e.g. kept in `DefStruct`)
-    // let xe1 = XEmpty1; // ERROR `XEmpty1` is the name of a struct or struct variant
-    let xe1 = XEmpty1(); //~ ERROR expected function, found `empty_struct::XEmpty1`
+    let xe1 = XEmpty1; //~ ERROR `XEmpty1` is the name of a struct or struct variant
+    let xe1 = XEmpty1(); //~ ERROR `XEmpty1` is the name of a struct or struct variant
     let xe3 = XE::Empty3; //~ ERROR no associated item named `Empty3` found for type
     let xe3 = XE::Empty3(); //~ ERROR no associated item named `Empty3` found for type
 }
index 3436e2a2cd752c298ea13b6971583909d6967784..ac6fbc7e06d5b68d60ff9fe3ad9c2d577904db17 100644 (file)
@@ -34,6 +34,6 @@ fn main() {
         Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
     }
     match xe1 {
-        XEmpty1(..) => () //~ ERROR `XEmpty1` does not name a tuple variant or a tuple struct
+        XEmpty1(..) => () //~ ERROR unresolved enum variant, struct or const `XEmpty1`
     }
 }
index f6c62bb855720c8956f3b855a7e719cf2d4556e9..708eea39a9571b73dd58d24b5ebc4cd13cef3501 100644 (file)
@@ -14,7 +14,7 @@ mod a {
     impl S { }
 }
 
-fn foo(_: a::S) { //~ ERROR: type `S` is private
+fn foo(_: a::S) { //~ ERROR: struct `S` is private
 }
 
 fn main() {}
index cd320ba148aba8fe02323db6fa3fcbae88ac67f3..451b30629b625f5795bfd3733df37bdc505db090 100644 (file)
@@ -18,5 +18,4 @@ fn forever() -> ! {
 }
 
 fn main() {
-  if 1 == 2 { forever(); }
 }
diff --git a/src/test/compile-fail/loop-proper-liveness.rs b/src/test/compile-fail/loop-proper-liveness.rs
new file mode 100644 (file)
index 0000000..e411313
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+fn test1() {
+    // In this test the outer 'a loop may terminate without `x` getting initialised. Although the
+    // `x = loop { ... }` statement is reached, the value itself ends up never being computed and
+    // thus leaving `x` uninit.
+    let x: i32;
+    'a: loop {
+        x = loop { break 'a };
+    }
+    println!("{:?}", x); //~ ERROR use of possibly uninitialized variable
+}
+
+// test2 and test3 should not fail.
+fn test2() {
+    // In this test the `'a` loop will never terminate thus making the use of `x` unreachable.
+    let x: i32;
+    'a: loop {
+        x = loop { continue 'a };
+    }
+    println!("{:?}", x);
+}
+
+fn test3() {
+    let x: i32;
+    // Similarly, the use of variable `x` is unreachable.
+    'a: loop {
+        x = loop { return };
+    }
+    println!("{:?}", x);
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/loop-properly-diverging-2.rs b/src/test/compile-fail/loop-properly-diverging-2.rs
new file mode 100644 (file)
index 0000000..c22091c
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 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.
+
+fn forever2() -> i32 {
+  let x: i32 = loop { break }; //~ ERROR mismatched types
+  x
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/loop-properly-diverging.rs b/src/test/compile-fail/loop-properly-diverging.rs
new file mode 100644 (file)
index 0000000..01dfbcc
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 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.
+
+fn forever2() -> ! { //~ ERROR computation may converge in a function marked as diverging
+  loop { break }
+}
+
+fn main() {}
index 7c8b91741ea5bdec4735fe43d464d9dfe2e6f943..593068c2aea9dcdc2e0b95e88d66fdc8b0036a74 100644 (file)
@@ -164,7 +164,7 @@ pub mod mytest {
     // Even though the inner `A` struct is a publicly exported item (usable from
     // external crates through `foo::foo`, it should not be accessible through
     // its definition path (which has the private `i` module).
-    use self::foo::i::A; //~ ERROR: type `A` is inaccessible
+    use self::foo::i::A; //~ ERROR: struct `A` is inaccessible
                          //~^ NOTE: module `i` is private
 
     pub mod foo {
index aae09cc0eae5cb985376d02a0697dced7c56e5a4..2ff48b73e294c415bcb02f51f05046d8dbb02f95 100644 (file)
@@ -28,7 +28,7 @@ pub struct B {
 }
 
 fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) {
-    //~^ ERROR: type `A` is private
+    //~^ ERROR: struct `A` is private
     //~^^ ERROR: struct `A` is private
 
     a.a;
index cccb7e500213f4871ce96b61639ae27d4fbfbe75..214a2a371baaf63d882403b03dc8b588e511d5e4 100644 (file)
@@ -16,6 +16,7 @@
 extern crate xcrate_unit_struct;
 
 fn main() {
-    let _ = xcrate_unit_struct::StructWithFields; //~ ERROR: unresolved name
+    let _ = xcrate_unit_struct::StructWithFields;
+    //~^ ERROR: `xcrate_unit_struct::StructWithFields` is the name of a struct or struct variant
     let _ = xcrate_unit_struct::Struct;
 }
index 7b2130cd4ed96bdc2dc402c67b677da4907bdfe5..98e112a374423910cf249c8170e6a6e123a7d5c6 100644 (file)
@@ -7,7 +7,7 @@ all: $(TMPDIR)/$(call BIN,bar)
 
 ifdef IS_MSVC
 $(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
-       $(CC) bar.c $(TMPDIR)/foo.lib $(call OUT_EXE,bar)
+       $(CC) bar.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,bar)
 else
 $(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
        $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR)
index 3d44b3c256efcaa4da06c40f260b2f88fd0e88ac..47264e82165b4a96b80bba72fc96c0ac0214212f 100644 (file)
@@ -4,11 +4,10 @@
 ifneq ($(shell uname),FreeBSD)
 all:
        $(RUSTC) foo.rs
-       cp $(TMPDIR)/libfoo.a $(call NATIVE_STATICLIB,foo2)
-       $(CC) bar.c $(call NATIVE_STATICLIB,foo2) $(call OUT_EXE,bar) \
+       $(CC) bar.c $(call STATICLIB,foo) $(call OUT_EXE,bar) \
                $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
-       rm $(call STATICLIB,foo*)
+       rm $(call STATICLIB,foo)
        $(call RUN,bar)
 
 else
index 72c161abe9113f10665f6ea3449b843b4adecf55..0f61f5de938bc37d6bf5fbfae13b58e533ad5c1c 100644 (file)
@@ -5,7 +5,7 @@ CC := $(CC:-g=)
 
 all:
        $(RUSTC) foo.rs -C lto
-       $(CC) bar.c $(TMPDIR)/libfoo.a \
+       $(CC) bar.c $(call STATICLIB,foo) \
                $(call OUT_EXE,bar) \
                $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
index 6cfa7043a2e382b53adf69da58d03782dbe1ab19..c2715027bc1f904470285ddc0ce97fde9df967a2 100644 (file)
@@ -4,8 +4,8 @@ all:
        $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib
        $(call REMOVE_RLIBS,bar)
        $(call REMOVE_DYLIBS,bar)
-       rm $(TMPDIR)/libbar.a
-       rm -f $(TMPDIR)/bar.{exp,lib,pdb}
+       rm $(call STATICLIB,bar)
+       rm -f $(TMPDIR)/bar.{dll.exp,dll.lib,pdb}
        # Check that $(TMPDIR) is empty.
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
@@ -78,7 +78,7 @@ all:
        rm $(TMPDIR)/$(call BIN,foo)
        $(RUSTC) foo.rs --crate-type=dylib --emit=link=$(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
-       rm -f $(TMPDIR)/foo.{exp,lib,pdb}
+       rm -f $(TMPDIR)/foo.{dll.exp,dll.lib,pdb}
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
@@ -133,7 +133,7 @@ all:
        rm $(TMPDIR)/bar.ll
        rm $(TMPDIR)/bar.s
        rm $(TMPDIR)/bar.o
-       rm $(TMPDIR)/libbar.a
+       rm $(call STATICLIB,bar)
        mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc
        # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later
        # comparison.
index 8bd05dc201fcfa1bf0b97ad3aef3aac29d029536..6409aa66ae061879f2055606e83b573b8dc75bce 100644 (file)
@@ -2,7 +2,7 @@
 
 TO_LINK := $(call DYLIB,bar)
 ifdef IS_MSVC
-LINK_ARG = $(TO_LINK:dll=lib)
+LINK_ARG = $(TO_LINK:dll=dll.lib)
 else
 LINK_ARG = $(TO_LINK)
 endif
index 52ad8b1709338c48297bbdc093eb8e8427caddda..aed7e5a8c13a6eab6ec4be3dedefb77b761755e6 100644 (file)
@@ -10,9 +10,9 @@
 
 #![feature(alloc_jemalloc, alloc_system)]
 
-#[cfg(not(any(target_env = "msvc", target_os = "bitrig", target_os = "openbsd")))]
+#[cfg(not(any(windows, target_os = "bitrig", target_os = "openbsd")))]
 extern crate alloc_jemalloc;
-#[cfg(any(target_env = "msvc", target_os = "bitrig", target_os = "openbsd"))]
+#[cfg(any(windows, target_os = "bitrig", target_os = "openbsd"))]
 extern crate alloc_system;
 
 fn main() {
index c8a9aeb706e8ce7951a8196d743bed79a0527297..3744aafdc5b2845ff999390444f26d7ffb5a7a5f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // no-prefer-dynamic
-// ignore-msvc no jemalloc on msvc
+// ignore-windows no jemalloc on windows
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
 
index 62e90d7a6e22b0f105b51812c5a42e59aad350b4..605ca6b65e2cff94f7077cd8ef9e3609d77ecea2 100644 (file)
@@ -8,8 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// aux-build:empty-struct.rs
+
 #![feature(associated_consts)]
 
+extern crate empty_struct;
+use empty_struct::XEmpty2 as XFoo;
+
 struct Foo;
 
 enum Bar {
@@ -30,6 +35,10 @@ impl HasBar for Foo {
     const THEBAR: Bar = Bar::Var1;
 }
 
+impl HasBar for XFoo {
+    const THEBAR: Bar = Bar::Var1;
+}
+
 fn main() {
     // Inherent impl
     assert!(match Bar::Var2 {
@@ -53,4 +62,16 @@ fn main() {
         <Foo as HasBar>::THEBAR => true,
         _ => false,
     });
+    assert!(match Bar::Var1 {
+        XFoo::THEBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var1 {
+        <XFoo>::THEBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var1 {
+        <XFoo as HasBar>::THEBAR => true,
+        _ => false,
+    });
 }
index bca72330c85ad99aa8419e21b58fa3acd452be68..8fdedb6581fab9541ec8bc91bc777909549381a9 100644 (file)
@@ -88,6 +88,15 @@ fn test8() -> isize {
     Two::two()
 }
 
+extern fn simple_extern(x: u32, y: (u32, u32)) -> u32 {
+    x + y.0 * y.1
+}
+
+#[rustc_mir]
+fn test9() -> u32 {
+    simple_extern(41, (42, 43))
+}
+
 #[rustc_mir]
 fn test_closure<F>(f: &F, x: i32, y: i32) -> i32
     where F: Fn(i32, i32) -> i32
@@ -117,6 +126,7 @@ fn main() {
     assert_eq!(test6(&Foo, 12367), 12367);
     assert_eq!(test7(), 1);
     assert_eq!(test8(), 2);
+    assert_eq!(test9(), 41 + 42 * 43);
 
     let closure = |x: i32, y: i32| { x + y };
     assert_eq!(test_closure(&closure, 100, 1), 101);
diff --git a/src/test/run-pass/mir_trans_calls_variadic.rs b/src/test/run-pass/mir_trans_calls_variadic.rs
new file mode 100644 (file)
index 0000000..ff66daa
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+#![feature(rustc_attrs)]
+
+#[link(name = "rust_test_helpers")]
+extern {
+    fn rust_interesting_average(_: i64, ...) -> f64;
+}
+
+#[rustc_mir]
+fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: i64) -> i64 {
+    unsafe {
+        rust_interesting_average(6, a, a as f64,
+                                    b, b as f64,
+                                    c, c as f64,
+                                    d, d as f64,
+                                    e, e as f64,
+                                    f, f as f64) as i64
+    }
+}
+
+fn main(){
+    assert_eq!(test(10, 20, 30, 40, 50, 60), 70);
+}
diff --git a/src/test/run-pass/zero-sized-binary-heap-push.rs b/src/test/run-pass/zero-sized-binary-heap-push.rs
new file mode 100644 (file)
index 0000000..0866a76
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::BinaryHeap;
+use std::iter::Iterator;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = BinaryHeap::with_capacity(len);
+        assert_eq!(tester.len(), 0);
+        assert!(tester.capacity() >= len);
+        for bit in 0..len {
+            tester.push(());
+        }
+        assert_eq!(tester.len(), len);
+        assert_eq!(tester.iter().count(), len);
+        tester.clear();
+    }
+}
diff --git a/src/test/run-pass/zero-sized-btreemap-insert.rs b/src/test/run-pass/zero-sized-btreemap-insert.rs
new file mode 100644 (file)
index 0000000..aff124c
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp::{Ord, Ordering, PartialOrd};
+use std::collections::BTreeMap;
+use std::iter::Iterator;
+
+#[derive(Eq, Hash, Debug, Ord, PartialEq, PartialOrd)]
+struct Zst;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = BTreeMap::new();
+        assert_eq!(tester.len(), 0);
+        for bit in 0..len {
+            tester.insert(Zst, ());
+        }
+        assert_eq!(tester.len(), if len == 0 { 0 } else { 1 });
+        assert_eq!(tester.iter().count(), if len == 0 { 0 } else { 1 });
+        assert_eq!(tester.get(&Zst).is_some(), len > 0);
+        tester.clear();
+    }
+}
diff --git a/src/test/run-pass/zero-sized-linkedlist-push.rs b/src/test/run-pass/zero-sized-linkedlist-push.rs
new file mode 100644 (file)
index 0000000..9c42485
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::LinkedList;
+use std::iter::Iterator;
+
+fn main() {
+    const N: usize = 8;
+
+    // Test that for all possible sequences of push_front / push_back,
+    // we end up with a LinkedList of the correct size
+
+    for len in 0..N {
+        let mut tester = LinkedList::new();
+        assert_eq!(tester.len(), 0);
+        assert_eq!(tester.front(), None);
+        for case in 0..(1 << len) {
+            assert_eq!(tester.len(), 0);
+            for bit in 0..len {
+                if case & (1 << bit) != 0 {
+                    tester.push_front(());
+                } else {
+                    tester.push_back(());
+                }
+            }
+            assert_eq!(tester.len(), len);
+            assert_eq!(tester.iter().count(), len);
+            tester.clear();
+        }
+    }
+}
diff --git a/src/test/run-pass/zero-sized-vec-deque-push.rs b/src/test/run-pass/zero-sized-vec-deque-push.rs
new file mode 100644 (file)
index 0000000..d7c7cd2
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::VecDeque;
+use std::iter::Iterator;
+
+fn main() {
+    const N: usize = 8;
+
+    // Zero sized type
+    struct Zst;
+
+    // Test that for all possible sequences of push_front / push_back,
+    // we end up with a deque of the correct size
+
+    for len in 0..N {
+        let mut tester = VecDeque::with_capacity(len);
+        assert_eq!(tester.len(), 0);
+        assert!(tester.capacity() >= len);
+        for case in 0..(1 << len) {
+            assert_eq!(tester.len(), 0);
+            for bit in 0..len {
+                if case & (1 << bit) != 0 {
+                    tester.push_front(Zst);
+                } else {
+                    tester.push_back(Zst);
+                }
+            }
+            assert_eq!(tester.len(), len);
+            assert_eq!(tester.iter().count(), len);
+            tester.clear();
+        }
+    }
+}
diff --git a/src/test/run-pass/zero-sized-vec-push.rs b/src/test/run-pass/zero-sized-vec-push.rs
new file mode 100644 (file)
index 0000000..e472e93
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::iter::Iterator;
+use std::vec::Vec;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = Vec::with_capacity(len);
+        assert_eq!(tester.len(), 0);
+        assert!(tester.capacity() >= len);
+        for bit in 0..len {
+            tester.push(());
+        }
+        assert_eq!(tester.len(), len);
+        assert_eq!(tester.iter().count(), len);
+        tester.clear();
+    }
+}