]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #14606 : pcwalton/rust/fn-trait-sugar, r=alexcrichton
authorbors <bors@rust-lang.org>
Tue, 10 Jun 2014 06:41:53 +0000 (23:41 -0700)
committerbors <bors@rust-lang.org>
Tue, 10 Jun 2014 06:41:53 +0000 (23:41 -0700)
r? @alexcrichton

37 files changed:
src/compiletest/compiletest.rs
src/compiletest/procsrv.rs
src/libcollections/bitv.rs
src/libcollections/dlist.rs
src/libcollections/priority_queue.rs
src/libcollections/ringbuf.rs
src/libcollections/smallintmap.rs
src/libcollections/treemap.rs
src/libcollections/trie.rs
src/libnative/io/c_win32.rs
src/libnative/io/file_win32.rs
src/libnative/io/mod.rs
src/libnative/io/pipe_win32.rs
src/libnative/io/process.rs
src/libnum/bigint.rs
src/libnum/integer.rs [new file with mode: 0644]
src/libnum/lib.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/plugin/load.rs
src/librustdoc/clean/inline.rs
src/librustdoc/flock.rs
src/librustdoc/plugins.rs
src/librustdoc/test.rs
src/libstd/dynamic_lib.rs [new file with mode: 0644]
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/rt/backtrace.rs
src/libstd/unstable/dynamic_lib.rs [deleted file]
src/libstd/unstable/mod.rs [deleted file]
src/libtest/lib.rs
src/test/auxiliary/linkage-visibility.rs
src/test/compile-fail/issue-13446.rs [new file with mode: 0644]
src/test/run-make/extern-fn-reachable/main.rs
src/test/run-pass/linkage-visibility.rs

index de0ca4971f5c2ba085bd1185dcfa5ed6f3f3d38f..977b7dc32c5658b7d01e9bd4c4b79137bd647bff 100644 (file)
@@ -292,6 +292,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
         save_metrics: config.save_metrics.clone(),
         test_shard: config.test_shard.clone(),
         nocapture: false,
+        color: test::AutoColor,
     }
 }
 
index a48a9f1be754133af968a123c297bc9506cb0e2c..8fa34dd6d27c91ff254c139ac6df1c006766842b 100644 (file)
@@ -11,7 +11,7 @@
 use std::os;
 use std::str;
 use std::io::process::{ProcessExit, Command, Process, ProcessOutput};
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 
 fn target_env(lib_path: &str, prog: &str) -> Vec<(String, String)> {
     let prog = if cfg!(windows) {prog.slice_to(prog.len() - 4)} else {prog};
index 42c8177977057323d89d71363dab68d1defd5390..e100baa1e3ac493bd329842ff40c592cb9d121e2 100644 (file)
@@ -13,6 +13,7 @@
 use core::prelude::*;
 
 use core::cmp;
+use core::default::Default;
 use core::fmt;
 use core::iter::{Enumerate, Repeat, Map, Zip};
 use core::ops;
@@ -698,6 +699,11 @@ pub struct BitvSet {
     bitv: BigBitv
 }
 
+impl Default for BitvSet {
+    #[inline]
+    fn default() -> BitvSet { BitvSet::new() }
+}
+
 impl BitvSet {
     /// Creates a new bit vector set with initially no contents
     pub fn new() -> BitvSet {
index 5a2312456913824a385371596b0b46597620418f..ac8c5c5557ed9cff4921f08afa9e252fddd51fc6 100644 (file)
@@ -24,6 +24,7 @@
 use core::prelude::*;
 
 use alloc::owned::Box;
+use core::default::Default;
 use core::fmt;
 use core::iter;
 use core::mem;
@@ -262,6 +263,11 @@ fn pop_back(&mut self) -> Option<T> {
     }
 }
 
+impl<T> Default for DList<T> {
+    #[inline]
+    fn default() -> DList<T> { DList::new() }
+}
+
 impl<T> DList<T> {
     /// Create an empty DList
     #[inline]
index ea3e7d1747170d0d6a1ba197fc7d61de7069af3f..f25864933f2eba691de2dddcb257aeeb11430c48 100644 (file)
@@ -14,6 +14,7 @@
 
 use core::prelude::*;
 
+use core::default::Default;
 use core::mem::{zeroed, replace, swap};
 use core::ptr;
 
@@ -37,6 +38,11 @@ impl<T: Ord> Mutable for PriorityQueue<T> {
     fn clear(&mut self) { self.data.truncate(0) }
 }
 
+impl<T: Ord> Default for PriorityQueue<T> {
+    #[inline]
+    fn default() -> PriorityQueue<T> { PriorityQueue::new() }
+}
+
 impl<T: Ord> PriorityQueue<T> {
     /// An iterator visiting all values in underlying vector, in
     /// arbitrary order.
index addf73d67a88e7f8e0e2cb804c5f8652710f21f6..ae1925126cae7055f8ef8b2cc0bb8fd395705ed8 100644 (file)
@@ -16,6 +16,7 @@
 use core::prelude::*;
 
 use core::cmp;
+use core::default::Default;
 use core::fmt;
 use core::iter::RandomAccessIterator;
 
@@ -112,6 +113,11 @@ fn push_back(&mut self, t: T) {
     }
 }
 
+impl<T> Default for RingBuf<T> {
+    #[inline]
+    fn default() -> RingBuf<T> { RingBuf::new() }
+}
+
 impl<T> RingBuf<T> {
     /// Create an empty RingBuf
     pub fn new() -> RingBuf<T> {
index cc901864ab532b3eab8bbb9ba95a1ac5527b59e0..6b4982de0821699816e94a85214d2e87681d54cf 100644 (file)
@@ -17,6 +17,7 @@
 
 use core::prelude::*;
 
+use core::default::Default;
 use core::fmt;
 use core::iter::{Enumerate, FilterMap};
 use core::mem::replace;
@@ -114,6 +115,11 @@ fn pop(&mut self, key: &uint) -> Option<V> {
     }
 }
 
+impl<V> Default for SmallIntMap<V> {
+    #[inline]
+    fn default() -> SmallIntMap<V> { SmallIntMap::new() }
+}
+
 impl<V> SmallIntMap<V> {
     /// Create an empty SmallIntMap
     pub fn new() -> SmallIntMap<V> { SmallIntMap{v: vec!()} }
index 489fe60cebf0ec021c8bb744a57dc7ee1be9aa98..1f4ee52008cdc56833056a95fe6288dadb0f8e3c 100644 (file)
@@ -15,6 +15,7 @@
 use core::prelude::*;
 
 use alloc::owned::Box;
+use core::default::Default;
 use core::fmt;
 use core::fmt::Show;
 use core::iter::Peekable;
@@ -135,6 +136,11 @@ fn pop(&mut self, key: &K) -> Option<V> {
     }
 }
 
+impl<K: Ord, V> Default for TreeMap<K,V> {
+    #[inline]
+    fn default() -> TreeMap<K, V> { TreeMap::new() }
+}
+
 impl<K: Ord, V> TreeMap<K, V> {
     /// Create an empty TreeMap
     pub fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
@@ -633,6 +639,11 @@ fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
     fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
 }
 
+impl<T: Ord> Default for TreeSet<T> {
+    #[inline]
+    fn default() -> TreeSet<T> { TreeSet::new() }
+}
+
 impl<T: Ord> TreeSet<T> {
     /// Create an empty TreeSet
     #[inline]
index 6e99d6054a56453b099a1211c8b89c55040be939..3f4fdd66b802accf5b46a9ed5036783a66d5a100 100644 (file)
@@ -13,6 +13,7 @@
 use core::prelude::*;
 
 use alloc::owned::Box;
+use core::default::Default;
 use core::mem::zeroed;
 use core::mem;
 use core::uint;
@@ -105,6 +106,11 @@ fn pop(&mut self, key: &uint) -> Option<T> {
     }
 }
 
+impl<T> Default for TrieMap<T> {
+    #[inline]
+    fn default() -> TrieMap<T> { TrieMap::new() }
+}
+
 impl<T> TrieMap<T> {
     /// Create an empty TrieMap
     #[inline]
@@ -332,6 +338,11 @@ fn remove(&mut self, value: &uint) -> bool {
     }
 }
 
+impl Default for TrieSet {
+    #[inline]
+    fn default() -> TrieSet { TrieSet::new() }
+}
+
 impl TrieSet {
     /// Create an empty TrieSet
     #[inline]
index 93b3ec7ccefbf204f1b1d8ea9c31dc7013440271..1ec25933eec3c2ea1bfafc0cb2fe6156f7a51ca7 100644 (file)
@@ -69,7 +69,6 @@ pub fn CancelIoEx(hFile: libc::HANDLE,
 pub mod compat {
     use std::intrinsics::{atomic_store_relaxed, transmute};
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
-    use std::os::win32::as_utf16_p;
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
@@ -80,12 +79,11 @@ pub mod compat {
     // This way, calling a function in this compatibility layer (after it's loaded) shouldn't
     // be any slower than a regular DLL call.
     unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
-        as_utf16_p(module, |module| {
-            symbol.with_c_str(|symbol| {
-                let handle = GetModuleHandleW(module);
-                let func: Option<T> = transmute(GetProcAddress(handle, symbol));
-                atomic_store_relaxed(ptr, func.unwrap_or(fallback))
-            })
+        let module = module.to_utf16().append_one(0);
+        symbol.with_c_str(|symbol| {
+            let handle = GetModuleHandleW(module.as_ptr());
+            let func: Option<T> = transmute(GetProcAddress(handle, symbol));
+            atomic_store_relaxed(ptr, func.unwrap_or(fallback))
         })
     }
 
index 2a5b78e55067cb75e5ef369981b210157f6f2309..5ace8e347c67ef7d5c4e521f91ec125d5314d908 100644 (file)
 use libc;
 use std::c_str::CString;
 use std::mem;
-use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+use std::os::win32::fill_utf16_buf_and_decode;
 use std::ptr;
 use std::rt::rtio;
-use std::rt::rtio::IoResult;
+use std::rt::rtio::{IoResult, IoError};
 use std::str;
 use std::vec;
 
@@ -253,6 +253,17 @@ fn drop(&mut self) {
     }
 }
 
+pub fn to_utf16(s: &CString) -> IoResult<Vec<u16>> {
+    match s.as_str() {
+        Some(s) => Ok(s.to_utf16().append_one(0)),
+        None => Err(IoError {
+            code: libc::ERROR_INVALID_NAME as uint,
+            extra: 0,
+            detail: Some("valid unicode input required".to_str()),
+        })
+    }
+}
+
 pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
         -> IoResult<FileDesc> {
     // Flags passed to open_osfhandle
@@ -299,15 +310,16 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
     // Compat with unix, this allows opening directories (see libuv)
     dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS;
 
-    let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe {
-        libc::CreateFileW(buf,
+    let path = try!(to_utf16(path));
+    let handle = unsafe {
+        libc::CreateFileW(path.as_ptr(),
                           dwDesiredAccess,
                           dwShareMode,
                           ptr::mut_null(),
                           dwCreationDisposition,
                           dwFlagsAndAttributes,
                           ptr::mut_null())
-    });
+    };
     if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
         Err(super::last_error())
     } else {
@@ -324,11 +336,10 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
 }
 
 pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
+    let p = try!(to_utf16(p));
     super::mkerr_winbool(unsafe {
         // FIXME: turn mode into something useful? #2623
-        as_utf16_p(p.as_str().unwrap(), |buf| {
-            libc::CreateDirectoryW(buf, ptr::mut_null())
-        })
+        libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null())
     })
 }
 
@@ -351,9 +362,11 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
     let star = Path::new(unsafe {
         CString::new(p.with_ref(|p| p), false)
     }).join("*");
-    as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe {
+    let path = try!(to_utf16(&star.to_c_str()));
+
+    unsafe {
         let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
-        let find_handle = libc::FindFirstFileW(path_ptr, wfd_ptr as libc::HANDLE);
+        let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE);
         if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE {
             let mut paths = vec!();
             let mut more_files = 1 as libc::c_int;
@@ -377,37 +390,35 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
         } else {
             Err(super::last_error())
         }
-    })
+    }
 }
 
 pub fn unlink(p: &CString) -> IoResult<()> {
+    let p = try!(to_utf16(p));
     super::mkerr_winbool(unsafe {
-        as_utf16_p(p.as_str().unwrap(), |buf| {
-            libc::DeleteFileW(buf)
-        })
+        libc::DeleteFileW(p.as_ptr())
     })
 }
 
 pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
+    let old = try!(to_utf16(old));
+    let new = try!(to_utf16(new));
     super::mkerr_winbool(unsafe {
-        as_utf16_p(old.as_str().unwrap(), |old| {
-            as_utf16_p(new.as_str().unwrap(), |new| {
-                libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
-            })
-        })
+        libc::MoveFileExW(old.as_ptr(), new.as_ptr(),
+                          libc::MOVEFILE_REPLACE_EXISTING)
     })
 }
 
 pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
-    super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
-        libc::wchmod(p, mode as libc::c_int)
-    }))
+    let p = try!(to_utf16(p));
+    super::mkerr_libc(unsafe {
+        libc::wchmod(p.as_ptr(), mode as libc::c_int)
+    })
 }
 
 pub fn rmdir(p: &CString) -> IoResult<()> {
-    super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
-        libc::wrmdir(p)
-    }))
+    let p = try!(to_utf16(p));
+    super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) })
 }
 
 pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
@@ -418,16 +429,15 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
 pub fn readlink(p: &CString) -> IoResult<CString> {
     // FIXME: I have a feeling that this reads intermediate symlinks as well.
     use io::c::compat::kernel32::GetFinalPathNameByHandleW;
+    let p = try!(to_utf16(p));
     let handle = unsafe {
-        as_utf16_p(p.as_str().unwrap(), |p| {
-            libc::CreateFileW(p,
-                              libc::GENERIC_READ,
-                              libc::FILE_SHARE_READ,
-                              ptr::mut_null(),
-                              libc::OPEN_EXISTING,
-                              libc::FILE_ATTRIBUTE_NORMAL,
-                              ptr::mut_null())
-        })
+        libc::CreateFileW(p.as_ptr(),
+                          libc::GENERIC_READ,
+                          libc::FILE_SHARE_READ,
+                          ptr::mut_null(),
+                          libc::OPEN_EXISTING,
+                          libc::FILE_ATTRIBUTE_NORMAL,
+                          ptr::mut_null())
     };
     if handle as int == libc::INVALID_HANDLE_VALUE as int {
         return Err(super::last_error())
@@ -453,19 +463,19 @@ pub fn readlink(p: &CString) -> IoResult<CString> {
 
 pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
     use io::c::compat::kernel32::CreateSymbolicLinkW;
-    super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
-        as_utf16_p(dst.as_str().unwrap(), |dst| {
-            unsafe { CreateSymbolicLinkW(dst, src, 0) }
-        }) as libc::BOOL
-    }))
+    let src = try!(to_utf16(src));
+    let dst = try!(to_utf16(dst));
+    super::mkerr_winbool(unsafe {
+        CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
+    })
 }
 
 pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
-    super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
-        as_utf16_p(dst.as_str().unwrap(), |dst| {
-            unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
-        })
-    }))
+    let src = try!(to_utf16(src));
+    let dst = try!(to_utf16(dst));
+    super::mkerr_winbool(unsafe {
+        libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null())
+    })
 }
 
 fn mkstat(stat: &libc::stat) -> rtio::FileStat {
@@ -491,12 +501,11 @@ fn mkstat(stat: &libc::stat) -> rtio::FileStat {
 
 pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
     let mut stat: libc::stat = unsafe { mem::zeroed() };
-    as_utf16_p(p.as_str().unwrap(), |up| {
-        match unsafe { libc::wstat(up, &mut stat) } {
-            0 => Ok(mkstat(&stat)),
-            _ => Err(super::last_error()),
-        }
-    })
+    let p = try!(to_utf16(p));
+    match unsafe { libc::wstat(p.as_ptr(), &mut stat) } {
+        0 => Ok(mkstat(&stat)),
+        _ => Err(super::last_error()),
+    }
 }
 
 pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
@@ -509,7 +518,8 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
         actime: (atime / 1000) as libc::time64_t,
         modtime: (mtime / 1000) as libc::time64_t,
     };
-    super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
-        libc::wutime(p, &buf)
-    }))
+    let p = try!(to_utf16(p));
+    super::mkerr_libc(unsafe {
+        libc::wutime(p.as_ptr(), &buf)
+    })
 }
index 3b0dbe2d0dce978e63be79d4c53ef6cdfd302e2a..4c5929ef2233f0e3315a80c37f2a922170f85371 100644 (file)
@@ -77,7 +77,7 @@ fn unimpl() -> IoError {
     IoError {
         code: ERROR as uint,
         extra: 0,
-        detail: None,
+        detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()),
     }
 }
 
index a5694436b97200016f91a4d4463493a7029b6531..45b12aa7007ff307320d33bd8be67816c0c13ce4 100644 (file)
@@ -88,7 +88,6 @@
 use libc;
 use std::c_str::CString;
 use std::mem;
-use std::os::win32::as_utf16_p;
 use std::os;
 use std::ptr;
 use std::rt::rtio;
@@ -98,6 +97,7 @@
 
 use super::c;
 use super::util;
+use super::file::to_utf16;
 
 struct Event(libc::HANDLE);
 
@@ -261,67 +261,66 @@ fn try_connect(p: *u16) -> Option<libc::HANDLE> {
     }
 
     pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
-        as_utf16_p(addr.as_str().unwrap(), |p| {
-            let start = ::io::timer::now();
-            loop {
-                match UnixStream::try_connect(p) {
-                    Some(handle) => {
-                        let inner = Inner::new(handle);
-                        let mut mode = libc::PIPE_TYPE_BYTE |
-                                       libc::PIPE_READMODE_BYTE |
-                                       libc::PIPE_WAIT;
-                        let ret = unsafe {
-                            libc::SetNamedPipeHandleState(inner.handle,
-                                                          &mut mode,
-                                                          ptr::mut_null(),
-                                                          ptr::mut_null())
-                        };
-                        return if ret == 0 {
-                            Err(super::last_error())
-                        } else {
-                            Ok(UnixStream {
-                                inner: Arc::new(inner),
-                                read: None,
-                                write: None,
-                                read_deadline: 0,
-                                write_deadline: 0,
-                            })
-                        }
+        let addr = try!(to_utf16(addr));
+        let start = ::io::timer::now();
+        loop {
+            match UnixStream::try_connect(addr.as_ptr()) {
+                Some(handle) => {
+                    let inner = Inner::new(handle);
+                    let mut mode = libc::PIPE_TYPE_BYTE |
+                                   libc::PIPE_READMODE_BYTE |
+                                   libc::PIPE_WAIT;
+                    let ret = unsafe {
+                        libc::SetNamedPipeHandleState(inner.handle,
+                                                      &mut mode,
+                                                      ptr::mut_null(),
+                                                      ptr::mut_null())
+                    };
+                    return if ret == 0 {
+                        Err(super::last_error())
+                    } else {
+                        Ok(UnixStream {
+                            inner: Arc::new(inner),
+                            read: None,
+                            write: None,
+                            read_deadline: 0,
+                            write_deadline: 0,
+                        })
                     }
-                    None => {}
                 }
+                None => {}
+            }
 
-                // On windows, if you fail to connect, you may need to call the
-                // `WaitNamedPipe` function, and this is indicated with an error
-                // code of ERROR_PIPE_BUSY.
-                let code = unsafe { libc::GetLastError() };
-                if code as int != libc::ERROR_PIPE_BUSY as int {
-                    return Err(super::last_error())
-                }
+            // On windows, if you fail to connect, you may need to call the
+            // `WaitNamedPipe` function, and this is indicated with an error
+            // code of ERROR_PIPE_BUSY.
+            let code = unsafe { libc::GetLastError() };
+            if code as int != libc::ERROR_PIPE_BUSY as int {
+                return Err(super::last_error())
+            }
 
-                match timeout {
-                    Some(timeout) => {
-                        let now = ::io::timer::now();
-                        let timed_out = (now - start) >= timeout || unsafe {
-                            let ms = (timeout - (now - start)) as libc::DWORD;
-                            libc::WaitNamedPipeW(p, ms) == 0
-                        };
-                        if timed_out {
-                            return Err(util::timeout("connect timed out"))
-                        }
+            match timeout {
+                Some(timeout) => {
+                    let now = ::io::timer::now();
+                    let timed_out = (now - start) >= timeout || unsafe {
+                        let ms = (timeout - (now - start)) as libc::DWORD;
+                        libc::WaitNamedPipeW(addr.as_ptr(), ms) == 0
+                    };
+                    if timed_out {
+                        return Err(util::timeout("connect timed out"))
                     }
+                }
 
-                    // An example I found on microsoft's website used 20
-                    // seconds, libuv uses 30 seconds, hence we make the
-                    // obvious choice of waiting for 25 seconds.
-                    None => {
-                        if unsafe { libc::WaitNamedPipeW(p, 25000) } == 0 {
-                            return Err(super::last_error())
-                        }
+                // An example I found on microsoft's website used 20
+                // seconds, libuv uses 30 seconds, hence we make the
+                // obvious choice of waiting for 25 seconds.
+                None => {
+                    if unsafe { libc::WaitNamedPipeW(addr.as_ptr(), 25000) } == 0 {
+                        return Err(super::last_error())
                     }
                 }
             }
-        })
+        }
     }
 
     fn handle(&self) -> libc::HANDLE { self.inner.handle }
@@ -564,14 +563,13 @@ pub fn bind(addr: &CString) -> IoResult<UnixListener> {
         // Although we technically don't need the pipe until much later, we
         // create the initial handle up front to test the validity of the name
         // and such.
-        as_utf16_p(addr.as_str().unwrap(), |p| {
-            let ret = unsafe { pipe(p, true) };
-            if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
-                Err(super::last_error())
-            } else {
-                Ok(UnixListener { handle: ret, name: addr.clone() })
-            }
-        })
+        let addr_v = try!(to_utf16(addr));
+        let ret = unsafe { pipe(addr_v.as_ptr(), true) };
+        if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
+            Err(super::last_error())
+        } else {
+            Ok(UnixListener { handle: ret, name: addr.clone() })
+        }
     }
 
     pub fn native_listen(self) -> IoResult<UnixAcceptor> {
@@ -639,6 +637,8 @@ pub fn native_accept(&mut self) -> IoResult<UnixStream> {
         // using the original server pipe.
         let handle = self.listener.handle;
 
+        let name = try!(to_utf16(&self.listener.name));
+
         // Once we've got a "server handle", we need to wait for a client to
         // connect. The ConnectNamedPipe function will block this thread until
         // someone on the other end connects. This function can "fail" if a
@@ -678,9 +678,7 @@ pub fn native_accept(&mut self) -> IoResult<UnixStream> {
         // Now that we've got a connected client to our handle, we need to
         // create a second server pipe. If this fails, we disconnect the
         // connected client and return an error (see comments above).
-        let new_handle = as_utf16_p(self.listener.name.as_str().unwrap(), |p| {
-            unsafe { pipe(p, false) }
-        });
+        let new_handle = unsafe { pipe(name.as_ptr(), false) };
         if new_handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
             let ret = Err(super::last_error());
             // If our disconnection fails, then there's not really a whole lot
index 2c2b7cec1dec4806a3d32835de56b458b825d85f..97b227ae1d8d3b6ee14f1b4b3b56fab34b0bd7ce 100644 (file)
@@ -296,16 +296,15 @@ fn spawn_process_os(cfg: ProcessConfig,
                     lpSecurityDescriptor: ptr::mut_null(),
                     bInheritHandle: 1,
                 };
-                *slot = os::win32::as_utf16_p("NUL", |filename| {
-                    libc::CreateFileW(filename,
-                                      access,
-                                      libc::FILE_SHARE_READ |
-                                          libc::FILE_SHARE_WRITE,
-                                      &mut sa,
-                                      libc::OPEN_EXISTING,
-                                      0,
-                                      ptr::mut_null())
-                });
+                let filename = "NUL".to_utf16().append_one(0);
+                *slot = libc::CreateFileW(filename.as_ptr(),
+                                          access,
+                                          libc::FILE_SHARE_READ |
+                                              libc::FILE_SHARE_WRITE,
+                                          &mut sa,
+                                          libc::OPEN_EXISTING,
+                                          0,
+                                          ptr::mut_null());
                 if *slot == INVALID_HANDLE_VALUE as libc::HANDLE {
                     return Err(super::last_error())
                 }
@@ -338,18 +337,17 @@ fn spawn_process_os(cfg: ProcessConfig,
 
         with_envp(cfg.env, |envp| {
             with_dirp(cfg.cwd, |dirp| {
-                os::win32::as_mut_utf16_p(cmd_str.as_slice(), |cmdp| {
-                    let created = CreateProcessW(ptr::null(),
-                                                 cmdp,
-                                                 ptr::mut_null(),
-                                                 ptr::mut_null(),
-                                                 TRUE,
-                                                 flags, envp, dirp,
-                                                 &mut si, &mut pi);
-                    if created == FALSE {
-                        create_err = Some(super::last_error());
-                    }
-                })
+                let mut cmd_str = cmd_str.to_utf16().append_one(0);
+                let created = CreateProcessW(ptr::null(),
+                                             cmd_str.as_mut_ptr(),
+                                             ptr::mut_null(),
+                                             ptr::mut_null(),
+                                             TRUE,
+                                             flags, envp, dirp,
+                                             &mut si, &mut pi);
+                if created == FALSE {
+                    create_err = Some(super::last_error());
+                }
             })
         });
 
@@ -740,7 +738,8 @@ fn with_dirp<T>(d: Option<&CString>, cb: |*u16| -> T) -> T {
       Some(dir) => {
           let dir_str = dir.as_str()
                            .expect("expected workingdirectory to be utf-8 encoded");
-          os::win32::as_utf16_p(dir_str, cb)
+          let dir_str = dir_str.to_utf16().append_one(0);
+          cb(dir_str.as_ptr())
       },
       None => cb(ptr::null())
     }
index 67501c9795d18fda7fdc10eb46075db760a507a0..0933301970d1969a3901a1c9f6b196107653e7b4 100644 (file)
 */
 
 use Integer;
+use rand::Rng;
 
-use std::cmp;
+use std::{cmp, fmt};
 use std::default::Default;
-use std::fmt;
 use std::from_str::FromStr;
 use std::num::CheckedDiv;
 use std::num::{Bitwise, ToPrimitive, FromPrimitive};
 use std::num::{Zero, One, ToStrRadix, FromStrRadix};
-use rand::Rng;
 use std::string::String;
-use std::uint;
-use std::{i64, u64};
+use std::{uint, i64, u64};
 
 /**
 A `BigDigit` is a `BigUint`'s composing element.
@@ -94,7 +92,7 @@ impl Eq for BigUint {}
 impl PartialOrd for BigUint {
     #[inline]
     fn lt(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
+        self.cmp(other) == Less
     }
 }
 
@@ -115,7 +113,7 @@ fn cmp(&self, other: &BigUint) -> Ordering {
 
 impl Default for BigUint {
     #[inline]
-    fn default() -> BigUint { BigUint::new(Vec::new()) }
+    fn default() -> BigUint { Zero::zero() }
 }
 
 impl fmt::Show for BigUint {
@@ -605,7 +603,7 @@ fn to_biguint(&self) -> Option<BigUint> {
 
 impl ToStrRadix for BigUint {
     fn to_str_radix(&self, radix: uint) -> String {
-        assert!(1 < radix && radix <= 16);
+        assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
         let (base, max_len) = get_radix_base(radix);
         if base == BigDigit::base {
             return fill_concat(self.data.as_slice(), radix, max_len)
@@ -645,8 +643,7 @@ fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> String {
 impl FromStrRadix for BigUint {
     /// Creates and initializes a `BigUint`.
     #[inline]
-    fn from_str_radix(s: &str, radix: uint)
-        -> Option<BigUint> {
+    fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
         BigUint::parse_bytes(s.as_bytes(), radix)
     }
 }
@@ -656,14 +653,11 @@ impl BigUint {
     ///
     /// The digits are be in base 2^32.
     #[inline]
-    pub fn new(v: Vec<BigDigit>) -> BigUint {
+    pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
         // omit trailing zeros
-        let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
-
-        if new_len == v.len() { return BigUint { data: v }; }
-        let mut v = v;
-        v.truncate(new_len);
-        return BigUint { data: v };
+        let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
+        digits.truncate(new_len);
+        BigUint { data: digits }
     }
 
     /// Creates and initializes a `BigUint`.
@@ -671,7 +665,7 @@ pub fn new(v: Vec<BigDigit>) -> BigUint {
     /// The digits are be in base 2^32.
     #[inline]
     pub fn from_slice(slice: &[BigDigit]) -> BigUint {
-        return BigUint::new(Vec::from_slice(slice));
+        BigUint::new(Vec::from_slice(slice))
     }
 
     /// Creates and initializes a `BigUint`.
@@ -768,7 +762,6 @@ pub fn bits(&self) -> uint {
 // `DoubleBigDigit` size dependent
 #[inline]
 fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
-    assert!(1 < radix && radix <= 16);
     match radix {
         2  => (4294967296, 32),
         3  => (3486784401, 20),
@@ -785,7 +778,7 @@ fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
         14 => (1475789056, 8),
         15 => (2562890625, 8),
         16 => (4294967296, 8),
-        _  => fail!()
+        _  => fail!("The radix must be within (1, 16]")
     }
 }
 
@@ -815,7 +808,7 @@ pub struct BigInt {
 impl PartialEq for BigInt {
     #[inline]
     fn eq(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Equal => true, _ => false }
+        self.cmp(other) == Equal
     }
 }
 
@@ -824,7 +817,7 @@ impl Eq for BigInt {}
 impl PartialOrd for BigInt {
     #[inline]
     fn lt(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
+        self.cmp(other) == Less
     }
 }
 
@@ -844,7 +837,7 @@ fn cmp(&self, other: &BigInt) -> Ordering {
 
 impl Default for BigInt {
     #[inline]
-    fn default() -> BigInt { BigInt::new(Zero, Vec::new()) }
+    fn default() -> BigInt { Zero::zero() }
 }
 
 impl fmt::Show for BigInt {
@@ -929,8 +922,7 @@ fn add(&self, other: &BigInt) -> BigInt {
         match (self.sign, other.sign) {
             (Zero, _)      => other.clone(),
             (_,    Zero)   => self.clone(),
-            (Plus, Plus)   => BigInt::from_biguint(Plus,
-                                                   self.data + other.data),
+            (Plus, Plus)   => BigInt::from_biguint(Plus, self.data + other.data),
             (Plus, Minus)  => self - (-*other),
             (Minus, Plus)  => other - (-*self),
             (Minus, Minus) => -((-self) + (-*other))
@@ -975,7 +967,7 @@ impl Div<BigInt, BigInt> for BigInt {
     #[inline]
     fn div(&self, other: &BigInt) -> BigInt {
         let (q, _) = self.div_rem(other);
-        return q;
+        q
     }
 }
 
@@ -983,7 +975,7 @@ impl Rem<BigInt, BigInt> for BigInt {
     #[inline]
     fn rem(&self, other: &BigInt) -> BigInt {
         let (_, r) = self.div_rem(other);
-        return r;
+        r
     }
 }
 
@@ -1045,13 +1037,13 @@ fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
     #[inline]
     fn div_floor(&self, other: &BigInt) -> BigInt {
         let (d, _) = self.div_mod_floor(other);
-        return d;
+        d
     }
 
     #[inline]
     fn mod_floor(&self, other: &BigInt) -> BigInt {
         let (_, m) = self.div_mod_floor(other);
-        return m;
+        m
     }
 
     fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
@@ -1265,7 +1257,7 @@ fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
             let final_digit: BigDigit = self.gen();
             data.push(final_digit >> (BigDigit::bits - rem));
         }
-        return BigUint::new(data);
+        BigUint::new(data)
     }
 
     fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
@@ -1287,7 +1279,7 @@ fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
         } else {
             Minus
         };
-        return BigInt::from_biguint(sign, biguint);
+        BigInt::from_biguint(sign, biguint)
     }
 
     fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
@@ -1322,8 +1314,8 @@ impl BigInt {
     ///
     /// The digits are be in base 2^32.
     #[inline]
-    pub fn new(sign: Sign, v: Vec<BigDigit>) -> BigInt {
-        BigInt::from_biguint(sign, BigUint::new(v))
+    pub fn new(sign: Sign, digits: Vec<BigDigit>) -> BigInt {
+        BigInt::from_biguint(sign, BigUint::new(digits))
     }
 
     /// Creates and initializes a `BigInt`.
@@ -1334,7 +1326,7 @@ pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
         if sign == Zero || data.is_zero() {
             return BigInt { sign: Zero, data: Zero::zero() };
         }
-        return BigInt { sign: sign, data: data };
+        BigInt { sign: sign, data: data }
     }
 
     /// Creates and initializes a `BigInt`.
@@ -1344,8 +1336,7 @@ pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
     }
 
     /// Creates and initializes a `BigInt`.
-    pub fn parse_bytes(buf: &[u8], radix: uint)
-        -> Option<BigInt> {
+    pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
         if buf.is_empty() { return None; }
         let mut sign  = Plus;
         let mut start = 0;
diff --git a/src/libnum/integer.rs b/src/libnum/integer.rs
new file mode 100644 (file)
index 0000000..d958d40
--- /dev/null
@@ -0,0 +1,411 @@
+// Copyright 2013-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.
+
+//! Integer trait and functions
+
+pub trait Integer: Num + PartialOrd
+                 + Div<Self, Self>
+                 + Rem<Self, Self> {
+    /// Simultaneous truncated integer division and modulus
+    #[inline]
+    fn div_rem(&self, other: &Self) -> (Self, Self) {
+        (*self / *other, *self % *other)
+    }
+
+    /// Floored integer division
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// assert!(( 8i).div_floor(& 3) ==  2);
+    /// assert!(( 8i).div_floor(&-3) == -3);
+    /// assert!((-8i).div_floor(& 3) == -3);
+    /// assert!((-8i).div_floor(&-3) ==  2);
+    ///
+    /// assert!(( 1i).div_floor(& 2) ==  0);
+    /// assert!(( 1i).div_floor(&-2) == -1);
+    /// assert!((-1i).div_floor(& 2) == -1);
+    /// assert!((-1i).div_floor(&-2) ==  0);
+    /// ~~~
+    fn div_floor(&self, other: &Self) -> Self;
+
+    /// Floored integer modulo, satisfying:
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// # let n = 1i; let d = 1i;
+    /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
+    /// ~~~
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// # use num::Integer;
+    /// assert!(( 8i).mod_floor(& 3) ==  2);
+    /// assert!(( 8i).mod_floor(&-3) == -1);
+    /// assert!((-8i).mod_floor(& 3) ==  1);
+    /// assert!((-8i).mod_floor(&-3) == -2);
+    ///
+    /// assert!(( 1i).mod_floor(& 2) ==  1);
+    /// assert!(( 1i).mod_floor(&-2) == -1);
+    /// assert!((-1i).mod_floor(& 2) ==  1);
+    /// assert!((-1i).mod_floor(&-2) == -1);
+    /// ~~~
+    fn mod_floor(&self, other: &Self) -> Self;
+
+    /// Simultaneous floored integer division and modulus
+    fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
+        (self.div_floor(other), self.mod_floor(other))
+    }
+
+    /// Greatest Common Divisor (GCD)
+    fn gcd(&self, other: &Self) -> Self;
+
+    /// Lowest Common Multiple (LCM)
+    fn lcm(&self, other: &Self) -> Self;
+
+    /// Returns `true` if `other` divides evenly into `self`
+    fn divides(&self, other: &Self) -> bool;
+
+    /// Returns `true` if the number is even
+    fn is_even(&self) -> bool;
+
+    /// Returns `true` if the number is odd
+    fn is_odd(&self) -> bool;
+}
+
+/// Simultaneous integer division and modulus
+#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
+/// Floored integer division
+#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
+/// Floored integer modulus
+#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
+/// Simultaneous floored integer division and modulus
+#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
+
+/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
+/// result is always positive.
+#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
+/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
+#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
+
+macro_rules! impl_integer_for_int {
+    ($T:ty, $test_mod:ident) => (
+        impl Integer for $T {
+            /// Floored integer division
+            #[inline]
+            fn div_floor(&self, other: &$T) -> $T {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match self.div_rem(other) {
+                    (d, r) if (r > 0 && *other < 0)
+                           || (r < 0 && *other > 0) => d - 1,
+                    (d, _)                          => d,
+                }
+            }
+
+            /// Floored integer modulo
+            #[inline]
+            fn mod_floor(&self, other: &$T) -> $T {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match *self % *other {
+                    r if (r > 0 && *other < 0)
+                      || (r < 0 && *other > 0) => r + *other,
+                    r                          => r,
+                }
+            }
+
+            /// Calculates `div_floor` and `mod_floor` simultaneously
+            #[inline]
+            fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
+                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+                match self.div_rem(other) {
+                    (d, r) if (r > 0 && *other < 0)
+                           || (r < 0 && *other > 0) => (d - 1, r + *other),
+                    (d, r)                          => (d, r),
+                }
+            }
+
+            /// Calculates the Greatest Common Divisor (GCD) of the number and
+            /// `other`. The result is always positive.
+            #[inline]
+            fn gcd(&self, other: &$T) -> $T {
+                // Use Euclid's algorithm
+                let mut m = *self;
+                let mut n = *other;
+                while m != 0 {
+                    let temp = m;
+                    m = n % temp;
+                    n = temp;
+                }
+                n.abs()
+            }
+
+            /// Calculates the Lowest Common Multiple (LCM) of the number and
+            /// `other`.
+            #[inline]
+            fn lcm(&self, other: &$T) -> $T {
+                // should not have to recalculate abs
+                ((*self * *other) / self.gcd(other)).abs()
+            }
+
+            /// Returns `true` if the number can be divided by `other` without
+            /// leaving a remainder
+            #[inline]
+            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+            /// Returns `true` if the number is divisible by `2`
+            #[inline]
+            fn is_even(&self) -> bool { self & 1 == 0 }
+
+            /// Returns `true` if the number is not divisible by `2`
+            #[inline]
+            fn is_odd(&self) -> bool { !self.is_even() }
+        }
+
+        #[cfg(test)]
+        mod $test_mod {
+            use Integer;
+
+            /// Checks that the division rule holds for:
+            ///
+            /// - `n`: numerator (dividend)
+            /// - `d`: denominator (divisor)
+            /// - `qr`: quotient and remainder
+            #[cfg(test)]
+            fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
+                assert_eq!(d * q + r, n);
+            }
+
+            #[test]
+            fn test_div_rem() {
+                fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
+                    let (n,d) = nd;
+                    let separate_div_rem = (n / d, n % d);
+                    let combined_div_rem = n.div_rem(&d);
+
+                    assert_eq!(separate_div_rem, qr);
+                    assert_eq!(combined_div_rem, qr);
+
+                    test_division_rule(nd, separate_div_rem);
+                    test_division_rule(nd, combined_div_rem);
+                }
+
+                test_nd_dr(( 8,  3), ( 2,  2));
+                test_nd_dr(( 8, -3), (-2,  2));
+                test_nd_dr((-8,  3), (-2, -2));
+                test_nd_dr((-8, -3), ( 2, -2));
+
+                test_nd_dr(( 1,  2), ( 0,  1));
+                test_nd_dr(( 1, -2), ( 0,  1));
+                test_nd_dr((-1,  2), ( 0, -1));
+                test_nd_dr((-1, -2), ( 0, -1));
+            }
+
+            #[test]
+            fn test_div_mod_floor() {
+                fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
+                    let (n,d) = nd;
+                    let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+                    let combined_div_mod_floor = n.div_mod_floor(&d);
+
+                    assert_eq!(separate_div_mod_floor, dm);
+                    assert_eq!(combined_div_mod_floor, dm);
+
+                    test_division_rule(nd, separate_div_mod_floor);
+                    test_division_rule(nd, combined_div_mod_floor);
+                }
+
+                test_nd_dm(( 8,  3), ( 2,  2));
+                test_nd_dm(( 8, -3), (-3, -1));
+                test_nd_dm((-8,  3), (-3,  1));
+                test_nd_dm((-8, -3), ( 2, -2));
+
+                test_nd_dm(( 1,  2), ( 0,  1));
+                test_nd_dm(( 1, -2), (-1, -1));
+                test_nd_dm((-1,  2), (-1,  1));
+                test_nd_dm((-1, -2), ( 0, -1));
+            }
+
+            #[test]
+            fn test_gcd() {
+                assert_eq!((10 as $T).gcd(&2), 2 as $T);
+                assert_eq!((10 as $T).gcd(&3), 1 as $T);
+                assert_eq!((0 as $T).gcd(&3), 3 as $T);
+                assert_eq!((3 as $T).gcd(&3), 3 as $T);
+                assert_eq!((56 as $T).gcd(&42), 14 as $T);
+                assert_eq!((3 as $T).gcd(&-3), 3 as $T);
+                assert_eq!((-6 as $T).gcd(&3), 3 as $T);
+                assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
+            }
+
+            #[test]
+            fn test_lcm() {
+                assert_eq!((1 as $T).lcm(&0), 0 as $T);
+                assert_eq!((0 as $T).lcm(&1), 0 as $T);
+                assert_eq!((1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((-1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((1 as $T).lcm(&-1), 1 as $T);
+                assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
+                assert_eq!((8 as $T).lcm(&9), 72 as $T);
+                assert_eq!((11 as $T).lcm(&5), 55 as $T);
+            }
+
+            #[test]
+            fn test_even() {
+                assert_eq!((-4 as $T).is_even(), true);
+                assert_eq!((-3 as $T).is_even(), false);
+                assert_eq!((-2 as $T).is_even(), true);
+                assert_eq!((-1 as $T).is_even(), false);
+                assert_eq!((0 as $T).is_even(), true);
+                assert_eq!((1 as $T).is_even(), false);
+                assert_eq!((2 as $T).is_even(), true);
+                assert_eq!((3 as $T).is_even(), false);
+                assert_eq!((4 as $T).is_even(), true);
+            }
+
+            #[test]
+            fn test_odd() {
+                assert_eq!((-4 as $T).is_odd(), false);
+                assert_eq!((-3 as $T).is_odd(), true);
+                assert_eq!((-2 as $T).is_odd(), false);
+                assert_eq!((-1 as $T).is_odd(), true);
+                assert_eq!((0 as $T).is_odd(), false);
+                assert_eq!((1 as $T).is_odd(), true);
+                assert_eq!((2 as $T).is_odd(), false);
+                assert_eq!((3 as $T).is_odd(), true);
+                assert_eq!((4 as $T).is_odd(), false);
+            }
+        }
+    )
+}
+
+impl_integer_for_int!(i8,   test_integer_i8)
+impl_integer_for_int!(i16,  test_integer_i16)
+impl_integer_for_int!(i32,  test_integer_i32)
+impl_integer_for_int!(i64,  test_integer_i64)
+impl_integer_for_int!(int,  test_integer_int)
+
+macro_rules! impl_integer_for_uint {
+    ($T:ty, $test_mod:ident) => (
+        impl Integer for $T {
+            /// Unsigned integer division. Returns the same result as `div` (`/`).
+            #[inline]
+            fn div_floor(&self, other: &$T) -> $T { *self / *other }
+
+            /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+            #[inline]
+            fn mod_floor(&self, other: &$T) -> $T { *self % *other }
+
+            /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+            #[inline]
+            fn gcd(&self, other: &$T) -> $T {
+                // Use Euclid's algorithm
+                let mut m = *self;
+                let mut n = *other;
+                while m != 0 {
+                    let temp = m;
+                    m = n % temp;
+                    n = temp;
+                }
+                n
+            }
+
+            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+            #[inline]
+            fn lcm(&self, other: &$T) -> $T {
+                (*self * *other) / self.gcd(other)
+            }
+
+            /// Returns `true` if the number can be divided by `other` without leaving a remainder
+            #[inline]
+            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+            /// Returns `true` if the number is divisible by `2`
+            #[inline]
+            fn is_even(&self) -> bool { self & 1 == 0 }
+
+            /// Returns `true` if the number is not divisible by `2`
+            #[inline]
+            fn is_odd(&self) -> bool { !self.is_even() }
+        }
+
+        #[cfg(test)]
+        mod $test_mod {
+            use Integer;
+
+            #[test]
+            fn test_div_mod_floor() {
+                assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
+                assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
+                assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
+                assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
+                assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
+                assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
+                assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
+                assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
+                assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
+            }
+
+            #[test]
+            fn test_gcd() {
+                assert_eq!((10 as $T).gcd(&2), 2 as $T);
+                assert_eq!((10 as $T).gcd(&3), 1 as $T);
+                assert_eq!((0 as $T).gcd(&3), 3 as $T);
+                assert_eq!((3 as $T).gcd(&3), 3 as $T);
+                assert_eq!((56 as $T).gcd(&42), 14 as $T);
+            }
+
+            #[test]
+            fn test_lcm() {
+                assert_eq!((1 as $T).lcm(&0), 0 as $T);
+                assert_eq!((0 as $T).lcm(&1), 0 as $T);
+                assert_eq!((1 as $T).lcm(&1), 1 as $T);
+                assert_eq!((8 as $T).lcm(&9), 72 as $T);
+                assert_eq!((11 as $T).lcm(&5), 55 as $T);
+                assert_eq!((99 as $T).lcm(&17), 1683 as $T);
+            }
+
+            #[test]
+            fn test_divides() {
+                assert!((6 as $T).divides(&(6 as $T)));
+                assert!((6 as $T).divides(&(3 as $T)));
+                assert!((6 as $T).divides(&(1 as $T)));
+            }
+
+            #[test]
+            fn test_even() {
+                assert_eq!((0 as $T).is_even(), true);
+                assert_eq!((1 as $T).is_even(), false);
+                assert_eq!((2 as $T).is_even(), true);
+                assert_eq!((3 as $T).is_even(), false);
+                assert_eq!((4 as $T).is_even(), true);
+            }
+
+            #[test]
+            fn test_odd() {
+                assert_eq!((0 as $T).is_odd(), false);
+                assert_eq!((1 as $T).is_odd(), true);
+                assert_eq!((2 as $T).is_odd(), false);
+                assert_eq!((3 as $T).is_odd(), true);
+                assert_eq!((4 as $T).is_odd(), false);
+            }
+        }
+    )
+}
+
+impl_integer_for_uint!(u8,   test_integer_u8)
+impl_integer_for_uint!(u16,  test_integer_u16)
+impl_integer_for_uint!(u32,  test_integer_u32)
+impl_integer_for_uint!(u64,  test_integer_u64)
+impl_integer_for_uint!(uint, test_integer_uint)
index fae21e80f307256101498420fc2459bc9109e80a..709882c87cedb970b3be3f693517592507fefd77 100644 (file)
 
 extern crate rand;
 
+pub use bigint::{BigInt, BigUint};
+pub use rational::{Rational, BigRational};
+pub use complex::Complex;
+pub use integer::Integer;
+
 pub mod bigint;
-pub mod rational;
 pub mod complex;
-
-pub trait Integer: Num + PartialOrd
-                 + Div<Self, Self>
-                 + Rem<Self, Self> {
-    /// Simultaneous truncated integer division and modulus
-    #[inline]
-    fn div_rem(&self, other: &Self) -> (Self, Self) {
-        (*self / *other, *self % *other)
-    }
-
-    /// Floored integer division
-    ///
-    /// # Examples
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// assert!(( 8i).div_floor(& 3) ==  2);
-    /// assert!(( 8i).div_floor(&-3) == -3);
-    /// assert!((-8i).div_floor(& 3) == -3);
-    /// assert!((-8i).div_floor(&-3) ==  2);
-    ///
-    /// assert!(( 1i).div_floor(& 2) ==  0);
-    /// assert!(( 1i).div_floor(&-2) == -1);
-    /// assert!((-1i).div_floor(& 2) == -1);
-    /// assert!((-1i).div_floor(&-2) ==  0);
-    /// ~~~
-    fn div_floor(&self, other: &Self) -> Self;
-
-    /// Floored integer modulo, satisfying:
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// # let n = 1i; let d = 1i;
-    /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
-    /// ~~~
-    ///
-    /// # Examples
-    ///
-    /// ~~~
-    /// # use num::Integer;
-    /// assert!(( 8i).mod_floor(& 3) ==  2);
-    /// assert!(( 8i).mod_floor(&-3) == -1);
-    /// assert!((-8i).mod_floor(& 3) ==  1);
-    /// assert!((-8i).mod_floor(&-3) == -2);
-    ///
-    /// assert!(( 1i).mod_floor(& 2) ==  1);
-    /// assert!(( 1i).mod_floor(&-2) == -1);
-    /// assert!((-1i).mod_floor(& 2) ==  1);
-    /// assert!((-1i).mod_floor(&-2) == -1);
-    /// ~~~
-    fn mod_floor(&self, other: &Self) -> Self;
-
-    /// Simultaneous floored integer division and modulus
-    fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
-        (self.div_floor(other), self.mod_floor(other))
-    }
-
-    /// Greatest Common Divisor (GCD)
-    fn gcd(&self, other: &Self) -> Self;
-
-    /// Lowest Common Multiple (LCM)
-    fn lcm(&self, other: &Self) -> Self;
-
-    /// Returns `true` if `other` divides evenly into `self`
-    fn divides(&self, other: &Self) -> bool;
-
-    /// Returns `true` if the number is even
-    fn is_even(&self) -> bool;
-
-    /// Returns `true` if the number is odd
-    fn is_odd(&self) -> bool;
-}
-
-/// Simultaneous integer division and modulus
-#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
-/// Floored integer division
-#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
-/// Floored integer modulus
-#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
-/// Simultaneous floored integer division and modulus
-#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
-
-/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
-/// result is always positive.
-#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
-/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
-#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
-
-macro_rules! impl_integer_for_int {
-    ($T:ty, $test_mod:ident) => (
-        impl Integer for $T {
-            /// Floored integer division
-            #[inline]
-            fn div_floor(&self, other: &$T) -> $T {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match self.div_rem(other) {
-                    (d, r) if (r > 0 && *other < 0)
-                           || (r < 0 && *other > 0) => d - 1,
-                    (d, _)                          => d,
-                }
-            }
-
-            /// Floored integer modulo
-            #[inline]
-            fn mod_floor(&self, other: &$T) -> $T {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match *self % *other {
-                    r if (r > 0 && *other < 0)
-                      || (r < 0 && *other > 0) => r + *other,
-                    r                          => r,
-                }
-            }
-
-            /// Calculates `div_floor` and `mod_floor` simultaneously
-            #[inline]
-            fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
-                // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
-                // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-                match self.div_rem(other) {
-                    (d, r) if (r > 0 && *other < 0)
-                           || (r < 0 && *other > 0) => (d - 1, r + *other),
-                    (d, r)                          => (d, r),
-                }
-            }
-
-            /// Calculates the Greatest Common Divisor (GCD) of the number and
-            /// `other`. The result is always positive.
-            #[inline]
-            fn gcd(&self, other: &$T) -> $T {
-                // Use Euclid's algorithm
-                let mut m = *self;
-                let mut n = *other;
-                while m != 0 {
-                    let temp = m;
-                    m = n % temp;
-                    n = temp;
-                }
-                n.abs()
-            }
-
-            /// Calculates the Lowest Common Multiple (LCM) of the number and
-            /// `other`.
-            #[inline]
-            fn lcm(&self, other: &$T) -> $T {
-                // should not have to recalculate abs
-                ((*self * *other) / self.gcd(other)).abs()
-            }
-
-            /// Returns `true` if the number can be divided by `other` without
-            /// leaving a remainder
-            #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
-            /// Returns `true` if the number is divisible by `2`
-            #[inline]
-            fn is_even(&self) -> bool { self & 1 == 0 }
-
-            /// Returns `true` if the number is not divisible by `2`
-            #[inline]
-            fn is_odd(&self) -> bool { !self.is_even() }
-        }
-
-        #[cfg(test)]
-        mod $test_mod {
-            use Integer;
-
-            /// Checks that the division rule holds for:
-            ///
-            /// - `n`: numerator (dividend)
-            /// - `d`: denominator (divisor)
-            /// - `qr`: quotient and remainder
-            #[cfg(test)]
-            fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
-                assert_eq!(d * q + r, n);
-            }
-
-            #[test]
-            fn test_div_rem() {
-                fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
-                    let (n,d) = nd;
-                    let separate_div_rem = (n / d, n % d);
-                    let combined_div_rem = n.div_rem(&d);
-
-                    assert_eq!(separate_div_rem, qr);
-                    assert_eq!(combined_div_rem, qr);
-
-                    test_division_rule(nd, separate_div_rem);
-                    test_division_rule(nd, combined_div_rem);
-                }
-
-                test_nd_dr(( 8,  3), ( 2,  2));
-                test_nd_dr(( 8, -3), (-2,  2));
-                test_nd_dr((-8,  3), (-2, -2));
-                test_nd_dr((-8, -3), ( 2, -2));
-
-                test_nd_dr(( 1,  2), ( 0,  1));
-                test_nd_dr(( 1, -2), ( 0,  1));
-                test_nd_dr((-1,  2), ( 0, -1));
-                test_nd_dr((-1, -2), ( 0, -1));
-            }
-
-            #[test]
-            fn test_div_mod_floor() {
-                fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
-                    let (n,d) = nd;
-                    let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
-                    let combined_div_mod_floor = n.div_mod_floor(&d);
-
-                    assert_eq!(separate_div_mod_floor, dm);
-                    assert_eq!(combined_div_mod_floor, dm);
-
-                    test_division_rule(nd, separate_div_mod_floor);
-                    test_division_rule(nd, combined_div_mod_floor);
-                }
-
-                test_nd_dm(( 8,  3), ( 2,  2));
-                test_nd_dm(( 8, -3), (-3, -1));
-                test_nd_dm((-8,  3), (-3,  1));
-                test_nd_dm((-8, -3), ( 2, -2));
-
-                test_nd_dm(( 1,  2), ( 0,  1));
-                test_nd_dm(( 1, -2), (-1, -1));
-                test_nd_dm((-1,  2), (-1,  1));
-                test_nd_dm((-1, -2), ( 0, -1));
-            }
-
-            #[test]
-            fn test_gcd() {
-                assert_eq!((10 as $T).gcd(&2), 2 as $T);
-                assert_eq!((10 as $T).gcd(&3), 1 as $T);
-                assert_eq!((0 as $T).gcd(&3), 3 as $T);
-                assert_eq!((3 as $T).gcd(&3), 3 as $T);
-                assert_eq!((56 as $T).gcd(&42), 14 as $T);
-                assert_eq!((3 as $T).gcd(&-3), 3 as $T);
-                assert_eq!((-6 as $T).gcd(&3), 3 as $T);
-                assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
-            }
-
-            #[test]
-            fn test_lcm() {
-                assert_eq!((1 as $T).lcm(&0), 0 as $T);
-                assert_eq!((0 as $T).lcm(&1), 0 as $T);
-                assert_eq!((1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((-1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((1 as $T).lcm(&-1), 1 as $T);
-                assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
-                assert_eq!((8 as $T).lcm(&9), 72 as $T);
-                assert_eq!((11 as $T).lcm(&5), 55 as $T);
-            }
-
-            #[test]
-            fn test_even() {
-                assert_eq!((-4 as $T).is_even(), true);
-                assert_eq!((-3 as $T).is_even(), false);
-                assert_eq!((-2 as $T).is_even(), true);
-                assert_eq!((-1 as $T).is_even(), false);
-                assert_eq!((0 as $T).is_even(), true);
-                assert_eq!((1 as $T).is_even(), false);
-                assert_eq!((2 as $T).is_even(), true);
-                assert_eq!((3 as $T).is_even(), false);
-                assert_eq!((4 as $T).is_even(), true);
-            }
-
-            #[test]
-            fn test_odd() {
-                assert_eq!((-4 as $T).is_odd(), false);
-                assert_eq!((-3 as $T).is_odd(), true);
-                assert_eq!((-2 as $T).is_odd(), false);
-                assert_eq!((-1 as $T).is_odd(), true);
-                assert_eq!((0 as $T).is_odd(), false);
-                assert_eq!((1 as $T).is_odd(), true);
-                assert_eq!((2 as $T).is_odd(), false);
-                assert_eq!((3 as $T).is_odd(), true);
-                assert_eq!((4 as $T).is_odd(), false);
-            }
-        }
-    )
-}
-
-impl_integer_for_int!(i8,   test_integer_i8)
-impl_integer_for_int!(i16,  test_integer_i16)
-impl_integer_for_int!(i32,  test_integer_i32)
-impl_integer_for_int!(i64,  test_integer_i64)
-impl_integer_for_int!(int,  test_integer_int)
-
-macro_rules! impl_integer_for_uint {
-    ($T:ty, $test_mod:ident) => (
-        impl Integer for $T {
-            /// Unsigned integer division. Returns the same result as `div` (`/`).
-            #[inline]
-            fn div_floor(&self, other: &$T) -> $T { *self / *other }
-
-            /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
-            #[inline]
-            fn mod_floor(&self, other: &$T) -> $T { *self % *other }
-
-            /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
-            #[inline]
-            fn gcd(&self, other: &$T) -> $T {
-                // Use Euclid's algorithm
-                let mut m = *self;
-                let mut n = *other;
-                while m != 0 {
-                    let temp = m;
-                    m = n % temp;
-                    n = temp;
-                }
-                n
-            }
-
-            /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
-            #[inline]
-            fn lcm(&self, other: &$T) -> $T {
-                (*self * *other) / self.gcd(other)
-            }
-
-            /// Returns `true` if the number can be divided by `other` without leaving a remainder
-            #[inline]
-            fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
-            /// Returns `true` if the number is divisible by `2`
-            #[inline]
-            fn is_even(&self) -> bool { self & 1 == 0 }
-
-            /// Returns `true` if the number is not divisible by `2`
-            #[inline]
-            fn is_odd(&self) -> bool { !self.is_even() }
-        }
-
-        #[cfg(test)]
-        mod $test_mod {
-            use Integer;
-
-            #[test]
-            fn test_div_mod_floor() {
-                assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
-                assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
-                assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
-                assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
-                assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
-                assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
-                assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
-                assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
-                assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
-            }
-
-            #[test]
-            fn test_gcd() {
-                assert_eq!((10 as $T).gcd(&2), 2 as $T);
-                assert_eq!((10 as $T).gcd(&3), 1 as $T);
-                assert_eq!((0 as $T).gcd(&3), 3 as $T);
-                assert_eq!((3 as $T).gcd(&3), 3 as $T);
-                assert_eq!((56 as $T).gcd(&42), 14 as $T);
-            }
-
-            #[test]
-            fn test_lcm() {
-                assert_eq!((1 as $T).lcm(&0), 0 as $T);
-                assert_eq!((0 as $T).lcm(&1), 0 as $T);
-                assert_eq!((1 as $T).lcm(&1), 1 as $T);
-                assert_eq!((8 as $T).lcm(&9), 72 as $T);
-                assert_eq!((11 as $T).lcm(&5), 55 as $T);
-                assert_eq!((99 as $T).lcm(&17), 1683 as $T);
-            }
-
-            #[test]
-            fn test_divides() {
-                assert!((6 as $T).divides(&(6 as $T)));
-                assert!((6 as $T).divides(&(3 as $T)));
-                assert!((6 as $T).divides(&(1 as $T)));
-            }
-
-            #[test]
-            fn test_even() {
-                assert_eq!((0 as $T).is_even(), true);
-                assert_eq!((1 as $T).is_even(), false);
-                assert_eq!((2 as $T).is_even(), true);
-                assert_eq!((3 as $T).is_even(), false);
-                assert_eq!((4 as $T).is_even(), true);
-            }
-
-            #[test]
-            fn test_odd() {
-                assert_eq!((0 as $T).is_odd(), false);
-                assert_eq!((1 as $T).is_odd(), true);
-                assert_eq!((2 as $T).is_odd(), false);
-                assert_eq!((3 as $T).is_odd(), true);
-                assert_eq!((4 as $T).is_odd(), false);
-            }
-        }
-    )
-}
-
-impl_integer_for_uint!(u8,   test_integer_u8)
-impl_integer_for_uint!(u16,  test_integer_u16)
-impl_integer_for_uint!(u32,  test_integer_u32)
-impl_integer_for_uint!(u64,  test_integer_u64)
-impl_integer_for_uint!(uint, test_integer_uint)
+pub mod integer;
+pub mod rational;
index c7ad74dce571c5fcae73c6900728d68fa3fe0fd0..0a88abd67d9dfffab5e5c96512b81598c23f745c 100644 (file)
@@ -321,3 +321,8 @@ pub fn get_reachable_extern_fns(cstore: &cstore::CStore, cnum: ast::CrateNum)
     let cdata = cstore.get_crate_data(cnum);
     decoder::get_reachable_extern_fns(&*cdata)
 }
+
+pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(did.krate);
+    decoder::is_typedef(&*cdata, did.node)
+}
index 8a2c3c08d419ae8b1c319366173901758b1332d7..56d6766e1b719f6be681c7f2d0bdb7d820194c2f 100644 (file)
@@ -1339,3 +1339,11 @@ pub fn get_reachable_extern_fns(cdata: Cmd) -> Vec<ast::DefId> {
     });
     return ret;
 }
+
+pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
+    let item_doc = lookup_item(id, cdata.data());
+    match item_family(item_doc) {
+        Type => true,
+        _ => false,
+    }
+}
index 9033b83d47420cacf22e2d3c6088f5cc8efb9cd9..ec46e7f8592d3391ffbc4e69e101bf47df625e61 100644 (file)
@@ -13,7 +13,7 @@
 use std::cell::RefCell;
 use std::os;
 use std::io::fs;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 use std::collections::HashSet;
 
 use myfs = util::fs;
index ba50a15a82ba7d4ce795c3331689a198ce216309..97ffcf279ae737770234cc0f6aaf42f49e9a364e 100644 (file)
@@ -16,7 +16,7 @@
 
 use std::mem;
 use std::os;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 use syntax::ast;
 use syntax::attr;
 use syntax::visit;
index 2a4774ffd84d4f5574edc73f1b7ef0c79fe00f4c..d243c61ddaff8ba3d91bdab8fb135e9888352d12 100644 (file)
@@ -203,7 +203,7 @@ fn build_struct(tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
 fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
     let t = ty::lookup_item_type(tcx, did);
     match ty::get(t.ty).sty {
-        ty::ty_enum(edid, _) => {
+        ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
             return clean::EnumItem(clean::Enum {
                 generics: t.generics.clean(),
                 variants_stripped: false,
index fea6748660bde2c0e2df962032226a7503a7b6e2..8ad10a686e677677778e4ce92efb73b5f6424094 100644 (file)
@@ -135,7 +135,6 @@ fn drop(&mut self) {
 mod imp {
     use libc;
     use std::mem;
-    use std::os::win32::as_utf16_p;
     use std::os;
     use std::ptr;
 
@@ -162,8 +161,9 @@ pub struct Lock {
 
     impl Lock {
         pub fn new(p: &Path) -> Lock {
-            let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
-                libc::CreateFileW(p,
+            let p_16 = p.as_str().unwrap().to_utf16().append_one(0);
+            let handle = unsafe {
+                libc::CreateFileW(p_16.as_ptr(),
                                   libc::FILE_GENERIC_READ |
                                     libc::FILE_GENERIC_WRITE,
                                   libc::FILE_SHARE_READ |
@@ -173,7 +173,7 @@ pub fn new(p: &Path) -> Lock {
                                   libc::CREATE_ALWAYS,
                                   libc::FILE_ATTRIBUTE_NORMAL,
                                   ptr::mut_null())
-            });
+            };
             if handle as uint == libc::INVALID_HANDLE_VALUE as uint {
                 fail!("create file error: {}", os::last_os_error());
             }
index 7a796e97f412f2ee98bf4158a7c05a8a167779a5..fee1d63a274d51ab7530e157bb98d8c0de1e2db1 100644 (file)
@@ -10,7 +10,7 @@
 
 use clean;
 
-use dl = std::unstable::dynamic_lib;
+use dl = std::dynamic_lib;
 use serialize::json;
 use std::string::String;
 
index 3436305829791456662c98b6cc355ced2f88b37d..0d77764127465bcee61ad89cb2aefe8c9579efb5 100644 (file)
@@ -15,7 +15,7 @@
 use std::os;
 use std::str;
 use std::string::String;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 
 use std::collections::{HashSet, HashMap};
 use testing;
diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs
new file mode 100644 (file)
index 0000000..fa6efc8
--- /dev/null
@@ -0,0 +1,332 @@
+// Copyright 2013-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.
+
+/*!
+
+Dynamic library facilities.
+
+A simple wrapper over the platform's dynamic library facilities
+
+*/
+
+#![experimental]
+#![allow(missing_doc)]
+
+use clone::Clone;
+use c_str::ToCStr;
+use iter::Iterator;
+use mem;
+use ops::*;
+use option::*;
+use os;
+use path::{Path,GenericPath};
+use result::*;
+use slice::{Vector,ImmutableVector};
+use str;
+use string::String;
+use vec::Vec;
+
+pub struct DynamicLibrary { handle: *u8}
+
+impl Drop for DynamicLibrary {
+    fn drop(&mut self) {
+        match dl::check_for_errors_in(|| {
+            unsafe {
+                dl::close(self.handle)
+            }
+        }) {
+            Ok(()) => {},
+            Err(str) => fail!("{}", str)
+        }
+    }
+}
+
+impl DynamicLibrary {
+    // FIXME (#12938): Until DST lands, we cannot decompose &str into
+    // & and str, so we cannot usefully take ToCStr arguments by
+    // reference (without forcing an additional & around &str). So we
+    // are instead temporarily adding an instance for &Path, so that
+    // we can take ToCStr as owned. When DST lands, the &Path instance
+    // should be removed, and arguments bound by ToCStr should be
+    // passed by reference. (Here: in the `open` method.)
+
+    /// Lazily open a dynamic library. When passed None it gives a
+    /// handle to the calling process
+    pub fn open<T: ToCStr>(filename: Option<T>)
+                        -> Result<DynamicLibrary, String> {
+        unsafe {
+            let mut filename = filename;
+            let maybe_library = dl::check_for_errors_in(|| {
+                match filename.take() {
+                    Some(name) => dl::open_external(name),
+                    None => dl::open_internal()
+                }
+            });
+
+            // The dynamic library must not be constructed if there is
+            // an error opening the library so the destructor does not
+            // run.
+            match maybe_library {
+                Err(err) => Err(err),
+                Ok(handle) => Ok(DynamicLibrary { handle: handle })
+            }
+        }
+    }
+
+    /// Prepends a path to this process's search path for dynamic libraries
+    pub fn prepend_search_path(path: &Path) {
+        let mut search_path = DynamicLibrary::search_path();
+        search_path.insert(0, path.clone());
+        let newval = DynamicLibrary::create_path(search_path.as_slice());
+        os::setenv(DynamicLibrary::envvar(),
+                   str::from_utf8(newval.as_slice()).unwrap());
+    }
+
+    /// From a slice of paths, create a new vector which is suitable to be an
+    /// environment variable for this platforms dylib search path.
+    pub fn create_path(path: &[Path]) -> Vec<u8> {
+        let mut newvar = Vec::new();
+        for (i, path) in path.iter().enumerate() {
+            if i > 0 { newvar.push(DynamicLibrary::separator()); }
+            newvar.push_all(path.as_vec());
+        }
+        return newvar;
+    }
+
+    /// Returns the environment variable for this process's dynamic library
+    /// search path
+    pub fn envvar() -> &'static str {
+        if cfg!(windows) {
+            "PATH"
+        } else if cfg!(target_os = "macos") {
+            "DYLD_LIBRARY_PATH"
+        } else {
+            "LD_LIBRARY_PATH"
+        }
+    }
+
+    fn separator() -> u8 {
+        if cfg!(windows) {';' as u8} else {':' as u8}
+    }
+
+    /// Returns the current search path for dynamic libraries being used by this
+    /// process
+    pub fn search_path() -> Vec<Path> {
+        let mut ret = Vec::new();
+        match os::getenv_as_bytes(DynamicLibrary::envvar()) {
+            Some(env) => {
+                for portion in
+                        env.as_slice()
+                           .split(|a| *a == DynamicLibrary::separator()) {
+                    ret.push(Path::new(portion));
+                }
+            }
+            None => {}
+        }
+        return ret;
+    }
+
+    /// Access the value at the symbol of the dynamic library
+    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
+        // This function should have a lifetime constraint of 'a on
+        // T but that feature is still unimplemented
+
+        let maybe_symbol_value = dl::check_for_errors_in(|| {
+            symbol.with_c_str(|raw_string| {
+                dl::symbol(self.handle, raw_string)
+            })
+        });
+
+        // The value must not be constructed if there is an error so
+        // the destructor does not run.
+        match maybe_symbol_value {
+            Err(err) => Err(err),
+            Ok(symbol_value) => Ok(mem::transmute(symbol_value))
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use prelude::*;
+    use libc;
+
+    #[test]
+    #[ignore(cfg(windows))] // FIXME #8818
+    #[ignore(cfg(target_os="android"))] // FIXME(#10379)
+    fn test_loading_cosine() {
+        // The math library does not need to be loaded since it is already
+        // statically linked in
+        let none: Option<Path> = None; // appease the typechecker
+        let libm = match DynamicLibrary::open(none) {
+            Err(error) => fail!("Could not load self as module: {}", error),
+            Ok(libm) => libm
+        };
+
+        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
+            match libm.symbol("cos") {
+                Err(error) => fail!("Could not load function cos: {}", error),
+                Ok(cosine) => cosine
+            }
+        };
+
+        let argument = 0.0;
+        let expected_result = 1.0;
+        let result = cosine(argument);
+        if result != expected_result {
+            fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
+                   expected_result, result)
+        }
+    }
+
+    #[test]
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    fn test_errors_do_not_crash() {
+        // Open /dev/null as a library to get an error, and make sure
+        // that only causes an error, and not a crash.
+        let path = Path::new("/dev/null");
+        match DynamicLibrary::open(Some(&path)) {
+            Err(_) => {}
+            Ok(_) => fail!("Successfully opened the empty library.")
+        }
+    }
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+pub mod dl {
+    use prelude::*;
+
+    use c_str::{CString, ToCStr};
+    use libc;
+    use ptr;
+    use result::*;
+    use str::StrAllocating;
+    use string::String;
+
+    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+        filename.with_c_str(|raw_name| {
+            dlopen(raw_name, Lazy as libc::c_int) as *u8
+        })
+    }
+
+    pub unsafe fn open_internal() -> *u8 {
+        dlopen(ptr::null(), Lazy as libc::c_int) as *u8
+    }
+
+    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+        use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+        static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
+        unsafe {
+            // dlerror isn't thread safe, so we need to lock around this entire
+            // sequence
+            let _guard = lock.lock();
+            let _old_error = dlerror();
+
+            let result = f();
+
+            let last_error = dlerror();
+            let ret = if ptr::null() == last_error {
+                Ok(result)
+            } else {
+                Err(CString::new(last_error, false).as_str()
+                                                   .unwrap()
+                                                   .to_string())
+            };
+
+            ret
+        }
+    }
+
+    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+        dlsym(handle as *libc::c_void, symbol) as *u8
+    }
+    pub unsafe fn close(handle: *u8) {
+        dlclose(handle as *libc::c_void); ()
+    }
+
+    pub enum RTLD {
+        Lazy = 1,
+        Now = 2,
+        Global = 256,
+        Local = 0,
+    }
+
+    #[link_name = "dl"]
+    extern {
+        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
+        fn dlerror() -> *libc::c_char;
+        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
+        fn dlclose(handle: *libc::c_void) -> libc::c_int;
+    }
+}
+
+#[cfg(target_os = "win32")]
+pub mod dl {
+    use c_str::ToCStr;
+    use libc;
+    use os;
+    use ptr;
+    use result::{Ok, Err, Result};
+    use str::StrAllocating;
+    use str;
+    use string::String;
+
+    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+        // Windows expects Unicode data
+        let filename_cstr = filename.to_c_str();
+        let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+        let filename_str = filename_str.to_utf16().append_one(0);
+        LoadLibraryW(filename_str.as_ptr() as *libc::c_void) as *u8
+    }
+
+    pub unsafe fn open_internal() -> *u8 {
+        let handle = ptr::null();
+        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
+        handle as *u8
+    }
+
+    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+        unsafe {
+            SetLastError(0);
+
+            let result = f();
+
+            let error = os::errno();
+            if 0 == error {
+                Ok(result)
+            } else {
+                Err(format!("Error code {}", error))
+            }
+        }
+    }
+
+    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+        GetProcAddress(handle as *libc::c_void, symbol) as *u8
+    }
+    pub unsafe fn close(handle: *u8) {
+        FreeLibrary(handle as *libc::c_void); ()
+    }
+
+    #[allow(non_snake_case_functions)]
+    extern "system" {
+        fn SetLastError(error: libc::size_t);
+        fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
+        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
+                              handle: **libc::c_void) -> *libc::c_void;
+        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
+        fn FreeLibrary(handle: *libc::c_void);
+    }
+}
index 6f3eec01e8e34678b8ed133e57422e44021680ba..a1e0fa889789f39b3b59a1f3a50c6cdd781d1641 100644 (file)
 
 * Make a simple TCP client connection and request
 
-    ```rust,should_fail
+    ```rust
     # #![allow(unused_must_use)]
     use std::io::net::tcp::TcpStream;
 
+    # // connection doesn't fail if a server is running on 8080
+    # // locally, we still want to be type checking this code, so lets
+    # // just stop it running (#11576)
+    # if false {
     let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap();
     socket.write(bytes!("GET / HTTP/1.0\n\n"));
     let response = socket.read_to_end();
+    # }
     ```
 
 * Make a simple TCP server
index 85813c02d5535be8c25e49515123caf37260e805..e147997334ccc4259296366d347a96c18824c427 100644 (file)
@@ -241,15 +241,12 @@ fn start(argc: int, argv: **u8) -> int {
 /* Runtime and platform support */
 
 pub mod c_vec;
+pub mod dynamic_lib;
 pub mod os;
 pub mod io;
 pub mod path;
 pub mod fmt;
 
-// Private APIs
-#[unstable]
-pub mod unstable;
-
 // FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
 // but name resolution doesn't work without it being pub.
 #[unstable]
@@ -279,3 +276,11 @@ mod std {
     // The test runner requires std::slice::Vector, so re-export std::slice just for it.
     #[cfg(test)] pub use slice;
 }
+
+#[deprecated]
+#[allow(missing_doc)]
+#[doc(hiden)]
+pub mod unstable {
+    #[deprecated = "use std::dynamic_lib"]
+    pub use dynamic_lib;
+}
index 90df18106f0a5b758f8a0ecf18e321ed830b346f..fa882e7d016fe21783efe91b2ed1cebd09c62af4 100644 (file)
@@ -133,7 +133,7 @@ pub mod win32 {
     use os::TMPBUF_SZ;
     use slice::{MutableVector, ImmutableVector};
     use string::String;
-    use str::{StrSlice, StrAllocating};
+    use str::StrSlice;
     use str;
     use vec::Vec;
 
@@ -171,17 +171,6 @@ pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD)
             return res;
         }
     }
-
-    pub fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
-        as_mut_utf16_p(s, |t| { f(t as *u16) })
-    }
-
-    pub fn as_mut_utf16_p<T>(s: &str, f: |*mut u16| -> T) -> T {
-        let mut t = s.to_utf16();
-        // Null terminate before passing on.
-        t.push(0u16);
-        f(t.as_mut_ptr())
-    }
 }
 
 /*
@@ -356,11 +345,10 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
 pub fn getenv(n: &str) -> Option<String> {
     unsafe {
         with_env_lock(|| {
-            use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
-            as_utf16_p(n, |u| {
-                fill_utf16_buf_and_decode(|buf, sz| {
-                    libc::GetEnvironmentVariableW(u, buf, sz)
-                })
+            use os::win32::{fill_utf16_buf_and_decode};
+            let n = n.to_utf16().append_one(0);
+            fill_utf16_buf_and_decode(|buf, sz| {
+                libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
             })
         })
     }
@@ -398,14 +386,11 @@ pub fn setenv(n: &str, v: &str) {
 /// Sets the environment variable `n` to the value `v` for the currently running
 /// process
 pub fn setenv(n: &str, v: &str) {
+    let n = n.to_utf16().append_one(0);
+    let v = v.to_utf16().append_one(0);
     unsafe {
         with_env_lock(|| {
-            use os::win32::as_utf16_p;
-            as_utf16_p(n, |nbuf| {
-                as_utf16_p(v, |vbuf| {
-                    libc::SetEnvironmentVariableW(nbuf, vbuf);
-                })
-            })
+            libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
         })
     }
 }
@@ -428,12 +413,10 @@ fn _unsetenv(n: &str) {
     }
     #[cfg(windows)]
     fn _unsetenv(n: &str) {
+        let n = n.to_utf16().append_one(0);
         unsafe {
             with_env_lock(|| {
-                use os::win32::as_utf16_p;
-                as_utf16_p(n, |nbuf| {
-                    libc::SetEnvironmentVariableW(nbuf, ptr::null());
-                })
+                libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null());
             })
         }
     }
@@ -732,11 +715,12 @@ pub fn change_dir(p: &Path) -> bool {
 
     #[cfg(windows)]
     fn chdir(p: &Path) -> bool {
+        let p = match p.as_str() {
+            Some(s) => s.to_utf16().append_one(0),
+            None => return false,
+        };
         unsafe {
-            use os::win32::as_utf16_p;
-            return as_utf16_p(p.as_str().unwrap(), |buf| {
-                libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
-            });
+            libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL)
         }
     }
 
index 83fc95267afdf3333d82335e367bf18e793514c5..423f372f018fdbe799be5fa83abc43d442097350 100644 (file)
@@ -614,7 +614,7 @@ mod imp {
     use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
     use slice::ImmutableVector;
     use str::StrSlice;
-    use unstable::dynamic_lib::DynamicLibrary;
+    use dynamic_lib::DynamicLibrary;
 
     #[allow(non_snake_case_functions)]
     extern "system" {
diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs
deleted file mode 100644 (file)
index c05cdc8..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2013-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.
-
-/*!
-
-Dynamic library facilities.
-
-A simple wrapper over the platform's dynamic library facilities
-
-*/
-
-use clone::Clone;
-use c_str::ToCStr;
-use iter::Iterator;
-use mem;
-use ops::*;
-use option::*;
-use os;
-use path::{Path,GenericPath};
-use result::*;
-use slice::{Vector,ImmutableVector};
-use str;
-use string::String;
-use vec::Vec;
-
-pub struct DynamicLibrary { handle: *u8}
-
-impl Drop for DynamicLibrary {
-    fn drop(&mut self) {
-        match dl::check_for_errors_in(|| {
-            unsafe {
-                dl::close(self.handle)
-            }
-        }) {
-            Ok(()) => {},
-            Err(str) => fail!("{}", str)
-        }
-    }
-}
-
-impl DynamicLibrary {
-    // FIXME (#12938): Until DST lands, we cannot decompose &str into
-    // & and str, so we cannot usefully take ToCStr arguments by
-    // reference (without forcing an additional & around &str). So we
-    // are instead temporarily adding an instance for &Path, so that
-    // we can take ToCStr as owned. When DST lands, the &Path instance
-    // should be removed, and arguments bound by ToCStr should be
-    // passed by reference. (Here: in the `open` method.)
-
-    /// Lazily open a dynamic library. When passed None it gives a
-    /// handle to the calling process
-    pub fn open<T: ToCStr>(filename: Option<T>)
-                        -> Result<DynamicLibrary, String> {
-        unsafe {
-            let mut filename = filename;
-            let maybe_library = dl::check_for_errors_in(|| {
-                match filename.take() {
-                    Some(name) => dl::open_external(name),
-                    None => dl::open_internal()
-                }
-            });
-
-            // The dynamic library must not be constructed if there is
-            // an error opening the library so the destructor does not
-            // run.
-            match maybe_library {
-                Err(err) => Err(err),
-                Ok(handle) => Ok(DynamicLibrary { handle: handle })
-            }
-        }
-    }
-
-    /// Prepends a path to this process's search path for dynamic libraries
-    pub fn prepend_search_path(path: &Path) {
-        let mut search_path = DynamicLibrary::search_path();
-        search_path.insert(0, path.clone());
-        let newval = DynamicLibrary::create_path(search_path.as_slice());
-        os::setenv(DynamicLibrary::envvar(),
-                   str::from_utf8(newval.as_slice()).unwrap());
-    }
-
-    /// From a slice of paths, create a new vector which is suitable to be an
-    /// environment variable for this platforms dylib search path.
-    pub fn create_path(path: &[Path]) -> Vec<u8> {
-        let mut newvar = Vec::new();
-        for (i, path) in path.iter().enumerate() {
-            if i > 0 { newvar.push(DynamicLibrary::separator()); }
-            newvar.push_all(path.as_vec());
-        }
-        return newvar;
-    }
-
-    /// Returns the environment variable for this process's dynamic library
-    /// search path
-    pub fn envvar() -> &'static str {
-        if cfg!(windows) {
-            "PATH"
-        } else if cfg!(target_os = "macos") {
-            "DYLD_LIBRARY_PATH"
-        } else {
-            "LD_LIBRARY_PATH"
-        }
-    }
-
-    fn separator() -> u8 {
-        if cfg!(windows) {';' as u8} else {':' as u8}
-    }
-
-    /// Returns the current search path for dynamic libraries being used by this
-    /// process
-    pub fn search_path() -> Vec<Path> {
-        let mut ret = Vec::new();
-        match os::getenv_as_bytes(DynamicLibrary::envvar()) {
-            Some(env) => {
-                for portion in
-                        env.as_slice()
-                           .split(|a| *a == DynamicLibrary::separator()) {
-                    ret.push(Path::new(portion));
-                }
-            }
-            None => {}
-        }
-        return ret;
-    }
-
-    /// Access the value at the symbol of the dynamic library
-    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
-        // This function should have a lifetime constraint of 'a on
-        // T but that feature is still unimplemented
-
-        let maybe_symbol_value = dl::check_for_errors_in(|| {
-            symbol.with_c_str(|raw_string| {
-                dl::symbol(self.handle, raw_string)
-            })
-        });
-
-        // The value must not be constructed if there is an error so
-        // the destructor does not run.
-        match maybe_symbol_value {
-            Err(err) => Err(err),
-            Ok(symbol_value) => Ok(mem::transmute(symbol_value))
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use prelude::*;
-    use libc;
-
-    #[test]
-    #[ignore(cfg(windows))] // FIXME #8818
-    #[ignore(cfg(target_os="android"))] // FIXME(#10379)
-    fn test_loading_cosine() {
-        // The math library does not need to be loaded since it is already
-        // statically linked in
-        let none: Option<Path> = None; // appease the typechecker
-        let libm = match DynamicLibrary::open(none) {
-            Err(error) => fail!("Could not load self as module: {}", error),
-            Ok(libm) => libm
-        };
-
-        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
-            match libm.symbol("cos") {
-                Err(error) => fail!("Could not load function cos: {}", error),
-                Ok(cosine) => cosine
-            }
-        };
-
-        let argument = 0.0;
-        let expected_result = 1.0;
-        let result = cosine(argument);
-        if result != expected_result {
-            fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
-                   expected_result, result)
-        }
-    }
-
-    #[test]
-    #[cfg(target_os = "linux")]
-    #[cfg(target_os = "macos")]
-    #[cfg(target_os = "freebsd")]
-    fn test_errors_do_not_crash() {
-        // Open /dev/null as a library to get an error, and make sure
-        // that only causes an error, and not a crash.
-        let path = Path::new("/dev/null");
-        match DynamicLibrary::open(Some(&path)) {
-            Err(_) => {}
-            Ok(_) => fail!("Successfully opened the empty library.")
-        }
-    }
-}
-
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "android")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-pub mod dl {
-    use prelude::*;
-
-    use c_str::{CString, ToCStr};
-    use libc;
-    use ptr;
-    use result::*;
-    use str::StrAllocating;
-    use string::String;
-
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
-        filename.with_c_str(|raw_name| {
-            dlopen(raw_name, Lazy as libc::c_int) as *u8
-        })
-    }
-
-    pub unsafe fn open_internal() -> *u8 {
-        dlopen(ptr::null(), Lazy as libc::c_int) as *u8
-    }
-
-    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
-        use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-        static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
-        unsafe {
-            // dlerror isn't thread safe, so we need to lock around this entire
-            // sequence
-            let _guard = lock.lock();
-            let _old_error = dlerror();
-
-            let result = f();
-
-            let last_error = dlerror();
-            let ret = if ptr::null() == last_error {
-                Ok(result)
-            } else {
-                Err(CString::new(last_error, false).as_str()
-                                                   .unwrap()
-                                                   .to_string())
-            };
-
-            ret
-        }
-    }
-
-    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
-        dlsym(handle as *libc::c_void, symbol) as *u8
-    }
-    pub unsafe fn close(handle: *u8) {
-        dlclose(handle as *libc::c_void); ()
-    }
-
-    pub enum RTLD {
-        Lazy = 1,
-        Now = 2,
-        Global = 256,
-        Local = 0,
-    }
-
-    #[link_name = "dl"]
-    extern {
-        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
-        fn dlerror() -> *libc::c_char;
-        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
-        fn dlclose(handle: *libc::c_void) -> libc::c_int;
-    }
-}
-
-#[cfg(target_os = "win32")]
-pub mod dl {
-    use libc;
-    use os;
-    use ptr;
-    use result::{Ok, Err, Result};
-    use string::String;
-    use str;
-    use c_str::ToCStr;
-
-    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
-        // Windows expects Unicode data
-        let filename_cstr = filename.to_c_str();
-        let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
-        os::win32::as_utf16_p(filename_str, |raw_name| {
-            LoadLibraryW(raw_name as *libc::c_void) as *u8
-        })
-    }
-
-    pub unsafe fn open_internal() -> *u8 {
-        let handle = ptr::null();
-        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
-        handle as *u8
-    }
-
-    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
-        unsafe {
-            SetLastError(0);
-
-            let result = f();
-
-            let error = os::errno();
-            if 0 == error {
-                Ok(result)
-            } else {
-                Err(format!("Error code {}", error))
-            }
-        }
-    }
-
-    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
-        GetProcAddress(handle as *libc::c_void, symbol) as *u8
-    }
-    pub unsafe fn close(handle: *u8) {
-        FreeLibrary(handle as *libc::c_void); ()
-    }
-
-    #[allow(non_snake_case_functions)]
-    extern "system" {
-        fn SetLastError(error: libc::size_t);
-        fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
-        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
-                              handle: **libc::c_void) -> *libc::c_void;
-        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
-        fn FreeLibrary(handle: *libc::c_void);
-    }
-}
diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs
deleted file mode 100644 (file)
index 985ef2e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2012-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.
-
-#![doc(hidden)]
-
-pub mod dynamic_lib;
index 9e562a08ff95e9a1ee893e1fba41804490711227..7d94e46a88a6e74b5769e57e1f5fc4e979422482 100644 (file)
@@ -271,6 +271,12 @@ pub fn test_main_static_x(args: &[~str], tests: &[TestDescAndFn]) {
                      tests)
 }
 
+pub enum ColorConfig {
+    AutoColor,
+    AlwaysColor,
+    NeverColor,
+}
+
 pub struct TestOpts {
     pub filter: Option<Regex>,
     pub run_ignored: bool,
@@ -282,6 +288,7 @@ pub struct TestOpts {
     pub test_shard: Option<(uint,uint)>,
     pub logfile: Option<Path>,
     pub nocapture: bool,
+    pub color: ColorConfig,
 }
 
 impl TestOpts {
@@ -298,6 +305,7 @@ fn new() -> TestOpts {
             test_shard: None,
             logfile: None,
             nocapture: false,
+            color: AutoColor,
         }
     }
 }
@@ -324,7 +332,11 @@ fn optgroups() -> Vec<getopts::OptGroup> {
       getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite",
                      "A.B"),
       getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
-                                         task, allow printing directly"))
+                                         task, allow printing directly"),
+      getopts::optopt("", "color", "Configure coloring of output:
+            auto   = colorize if stdout is a tty and tests are run on serially (default);
+            always = always colorize output;
+            never  = never colorize output;", "auto|always|never"))
 }
 
 fn usage(binary: &str) {
@@ -406,6 +418,16 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
     }
 
+    let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
+        Some("auto") | None => AutoColor,
+        Some("always") => AlwaysColor,
+        Some("never") => NeverColor,
+
+        Some(v) => return Some(Err(format!("argument for --color must be \
+                                            auto, always, or never (was {})",
+                                            v))),
+    };
+
     let test_opts = TestOpts {
         filter: filter,
         run_ignored: run_ignored,
@@ -417,6 +439,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         test_shard: test_shard,
         logfile: logfile,
         nocapture: nocapture,
+        color: color,
     };
 
     Some(Ok(test_opts))
@@ -492,7 +515,7 @@ pub fn new(opts: &TestOpts,
         Ok(ConsoleTestState {
             out: out,
             log_out: log_out,
-            use_color: use_color(),
+            use_color: use_color(opts),
             total: 0u,
             passed: 0u,
             failed: 0u,
@@ -867,8 +890,12 @@ fn should_sort_failures_before_printing_them() {
     assert!(apos < bpos);
 }
 
-fn use_color() -> bool {
-    get_concurrency() == 1 && io::stdout().get_ref().isatty()
+fn use_color(opts: &TestOpts) -> bool {
+    match opts.color {
+        AutoColor => get_concurrency() == 1 && io::stdout().get_ref().isatty(),
+        AlwaysColor => true,
+        NeverColor => false,
+    }
 }
 
 #[deriving(Clone)]
index 4ae0b6f14f59d4fcd009a629edf46aa8f0e38b55..0b4bea49fa2499d0481dbdcbe5178c20c8401fe9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 
 #[no_mangle]
 pub fn foo() { bar(); }
diff --git a/src/test/compile-fail/issue-13446.rs b/src/test/compile-fail/issue-13446.rs
new file mode 100644 (file)
index 0000000..0bb6ded
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+
+// Used to cause ICE
+
+static VEC: [u32, ..256] = vec!(); //~ ERROR mismatched types
+
+fn main() {}
+
index e05d43145d7e2e365d3004113989ca814dde77da..0f759efb02539bc874d624f4511cd767b819f89e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
 use std::os;
 
 pub fn main() {
index e263767990a65d188dd08e823a41788308d8fd4f..58f66314e4430dd7fca25b6b6046b192787d9eb1 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:linkage-visibility.rs
 // ignore-android: FIXME(#10379)
-// ignore-win32: std::unstable::dynamic_lib does not work on win32 well
+// ignore-win32: std::dynamic_lib does not work on win32 well
 
 extern crate foo = "linkage-visibility";