save_metrics: config.save_metrics.clone(),
test_shard: config.test_shard.clone(),
nocapture: false,
+ color: test::AutoColor,
}
}
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};
// This fence is needed to prevent reordering of use of the data and
// deletion of the data. Because it is marked `Release`, the
- // decreasing of the reference count sychronizes with this `Acquire`
+ // decreasing of the reference count synchronizes with this `Acquire`
// fence. This means that use of the data happens before decreasing
// the refernce count, which happens before this fence, which
// happens before the deletion of the data.
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, Repeat, Map, Zip};
use core::ops;
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 {
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::iter;
use core::mem;
}
}
+impl<T> Default for DList<T> {
+ #[inline]
+ fn default() -> DList<T> { DList::new() }
+}
+
impl<T> DList<T> {
/// Create an empty DList
#[inline]
use core::prelude::*;
+use core::default::Default;
use core::mem::{zeroed, replace, swap};
use core::ptr;
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.
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::RandomAccessIterator;
}
}
+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> {
use core::prelude::*;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, FilterMap};
use core::mem::replace;
}
}
+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!()} }
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::fmt::Show;
use core::iter::Peekable;
}
}
+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} }
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]
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::mem::zeroed;
use core::mem;
use core::uint;
}
}
+impl<T> Default for TrieMap<T> {
+ #[inline]
+ fn default() -> TrieMap<T> { TrieMap::new() }
+}
+
impl<T> TrieMap<T> {
/// Create an empty TrieMap
#[inline]
}
}
+impl Default for TrieSet {
+ #[inline]
+ fn default() -> TrieSet { TrieSet::new() }
+}
+
impl TrieSet {
/// Create an empty TrieSet
#[inline]
}
/// Runs a callback, emitting the correct padding either before or
- /// afterwards depending on whether right or left alingment is requested.
+ /// afterwards depending on whether right or left alignment is requested.
fn with_padding(&mut self,
padding: uint,
default: rt::Alignment,
//! *Note: The actual definition of `Writer` uses `IoResult`, which
//! is just a synonym for `Result<T, IoError>`.*
//!
-//! This method doesn`t produce a value, but the write may
+//! This method doesn't produce a value, but the write may
//! fail. It's crucial to handle the error case, and *not* write
//! something like this:
//!
pub occur: Occur
}
-/// Describes wether an option is given at all or has a value.
+/// Describes whether an option is given at all or has a value.
#[deriving(Clone, PartialEq)]
enum Optval {
Val(String),
* pattern - see the `glob` function for more details.
*/
pub struct Paths {
- root: Path,
dir_patterns: Vec<Pattern>,
require_dir: bool,
options: MatchOptions,
// FIXME: How do we want to handle verbatim paths? I'm inclined to return nothing,
// since we can't very well find all UNC shares with a 1-letter server name.
return Paths {
- root: root,
dir_patterns: Vec::new(),
require_dir: false,
options: options,
}
Paths {
- root: root,
dir_patterns: dir_patterns,
require_dir: require_dir,
options: options,
// stacks are disabled.
#[cfg(target_arch = "x86")]
+#[repr(C)]
struct Registers {
eax: u32, ebx: u32, ecx: u32, edx: u32,
ebp: u32, esi: u32, edi: u32, esp: u32,
regs[RUSTRT_R14] = procedure.env as uint;
regs[RUSTRT_R15] = fptr as uint;
- // These registers are picked up by the regulard context switch paths. These
+ // These registers are picked up by the regular context switch paths. These
// will put us in "mostly the right context" except for frobbing all the
// arguments to the right place. We have the small trampoline code inside of
// rust_bootstrap_green_task to do that.
run_anything: bool,
/// A fast XorShift rng for scheduler use
rng: XorShiftRng,
- /// A togglable idle callback
+ /// A toggleable idle callback
idle_callback: Option<Box<PausableIdleCallback:Send>>,
/// A countdown that starts at a random value and is decremented
/// every time a yield check is performed. When it hits 0 a task
// After processing a message, we consider doing some more work on the
// event loop. The "keep going" condition changes after the first
- // iteration becase we don't want to spin here infinitely.
+ // iteration because we don't want to spin here infinitely.
//
// Once we start doing work we can keep doing work so long as the
// iteration does something. Note that we don't want to starve the
extern {}
/// A wrapper for a nullable pointer. Don't use this except for interacting
-/// with libc. Basically Option, but without the dependance on libstd.
+/// with libc. Basically Option, but without the dependence on libstd.
// If/when libprim happens, this can be removed in favor of that
pub enum Nullable<T> {
Null,
pub mod funcs {
- // Thankfull most of c95 is universally available and does not vary by OS
+ // Thankfully most of c95 is universally available and does not vary by OS
// or anything. The same is not true of POSIX.
pub mod c95 {
static FD_SETSIZE: uint = 64;
pub static MSG_DONTWAIT: libc::c_int = 0;
+#[repr(C)]
pub struct WSADATA {
pub wVersion: libc::WORD,
pub wHighVersion: libc::WORD,
pub type LPWSADATA = *mut WSADATA;
+#[repr(C)]
pub struct fd_set {
fd_count: libc::c_uint,
fd_array: [libc::SOCKET, ..FD_SETSIZE],
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;
// 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))
})
}
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;
}
}
+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
// 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 {
}
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())
})
}
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;
} 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<()> {
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())
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 {
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> {
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)
+ })
}
IoError {
code: ERROR as uint,
extra: 0,
- detail: None,
+ detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()),
}
}
/// Implementation of rt::rtio's IoFactory trait to generate handles to the
/// native I/O functionality.
pub struct IoFactory {
- cannot_construct_outside_of_this_module: ()
+ _cannot_construct_outside_of_this_module: ()
}
impl IoFactory {
pub fn new() -> IoFactory {
net::init();
- IoFactory { cannot_construct_outside_of_this_module: () }
+ IoFactory { _cannot_construct_outside_of_this_module: () }
}
}
struct Inner {
fd: sock_t,
- lock: mutex::NativeMutex,
+
+ // Unused on Linux, where this lock is not necessary.
+ #[allow(dead_code)]
+ lock: mutex::NativeMutex
}
pub struct Guard<'a> {
struct Inner {
fd: fd_t,
- lock: mutex::NativeMutex,
+
+ // Unused on Linux, where this lock is not necessary.
+ #[allow(dead_code)]
+ lock: mutex::NativeMutex
}
impl Inner {
//! it sounded like named pipes just weren't built for this kind of interaction,
//! and the suggested solution was to use overlapped I/O.
//!
-//! I don't realy know what overlapped I/O is, but my basic understanding after
+//! I don't really know what overlapped I/O is, but my basic understanding after
//! reading about it is that you have an external Event which is used to signal
//! I/O completion, passed around in some OVERLAPPED structures. As to what this
//! is, I'm not exactly sure.
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;
use super::c;
use super::util;
+use super::file::to_utf16;
struct Event(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 }
// 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> {
// 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
// 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
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())
}
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());
+ }
})
});
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())
}
// Register a new SIGCHLD handler, returning the reading half of the
// self-pipe plus the old handler registered (return value of sigaction).
//
- // Be sure to set up the self-pipe first because as soon as we reigster a
+ // Be sure to set up the self-pipe first because as soon as we register a
// handler we're going to start receiving signals.
fn register_sigchld() -> (libc::c_int, c::sigaction) {
unsafe {
//
// On a mildly unrelated note, it should also be pointed out that OS
// condition variables are susceptible to spurious wakeups, which we need to
- // be ready for. In order to accomodate for this fact, we have an extra
+ // be ready for. In order to accommodate for this fact, we have an extra
// `awoken` field which indicates whether we were actually woken up via some
// invocation of `reawaken`. This flag is only ever accessed inside the
// lock, so there's no need to make it atomic.
*/
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.
impl PartialOrd for BigUint {
#[inline]
fn lt(&self, other: &BigUint) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigUint {
#[inline]
- fn default() -> BigUint { BigUint::new(Vec::new()) }
+ fn default() -> BigUint { Zero::zero() }
}
impl fmt::Show for 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)
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)
}
}
///
/// 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`.
/// 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`.
// `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),
14 => (1475789056, 8),
15 => (2562890625, 8),
16 => (4294967296, 8),
- _ => fail!()
+ _ => fail!("The radix must be within (1, 16]")
}
}
impl PartialEq for BigInt {
#[inline]
fn eq(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Equal => true, _ => false }
+ self.cmp(other) == Equal
}
}
impl PartialOrd for BigInt {
#[inline]
fn lt(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigInt {
#[inline]
- fn default() -> BigInt { BigInt::new(Zero, Vec::new()) }
+ fn default() -> BigInt { Zero::zero() }
}
impl fmt::Show for 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))
#[inline]
fn div(&self, other: &BigInt) -> BigInt {
let (q, _) = self.div_rem(other);
- return q;
+ q
}
}
#[inline]
fn rem(&self, other: &BigInt) -> BigInt {
let (_, r) = self.div_rem(other);
- return r;
+ r
}
}
#[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) {
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 {
} else {
Minus
};
- return BigInt::from_biguint(sign, biguint);
+ BigInt::from_biguint(sign, biguint)
}
fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
///
/// 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`.
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`.
}
/// 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;
--- /dev/null
+// 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)
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;
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
- shape: f64,
scale: f64,
c: f64,
d: f64
fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
let d = shape - 1. / 3.;
GammaLargeShape {
- shape: shape,
scale: scale,
c: 1. / (9. * d).sqrt(),
d: d
// The CharClass instruction tries to match one input character against
// the range of characters given.
- // The flags indicate whether to do a case insentivie match and whether
+ // The flags indicate whether to do a case insensitive match and whether
// the character class is negated or not.
CharClass(Vec<(char, char)>, Flags),
EmptyBegin(Flags),
// Matches the end of the string, consumes no characters.
- // The flags indicate whether it matches if the proceding character
+ // The flags indicate whether it matches if the proceeding character
// is a new line.
EmptyEnd(Flags),
}
}
-/// Process command line options. Emits messages as appropirate.If compilation
+/// Process command line options. Emits messages as appropriate. If compilation
/// should continue, returns a getopts::Matches object parsed from args, otherwise
/// returns None.
pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
("linkage", Active),
("struct_inherit", Active),
("overloaded_calls", Active),
+ ("unboxed_closure_sugar", Active),
("quad_precision_float", Active),
},
ast::TyBox(_) => { self.gate_box(t.span); }
+ ast::TyUnboxedFn(_) => {
+ self.gate_feature("unboxed_closure_sugar",
+ t.span,
+ "unboxed closure trait sugar is experimental");
+ }
_ => {}
}
fold.fold_crate(krate)
}
-struct PreludeInjector<'a> {
- sess: &'a Session,
-}
+struct PreludeInjector<'a>;
impl<'a> fold::Folder for PreludeInjector<'a> {
}
}
-fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
- let mut fold = PreludeInjector {
- sess: sess,
- };
+fn inject_prelude(_: &Session, krate: ast::Crate) -> ast::Crate {
+ let mut fold = PreludeInjector;
fold.fold_crate(krate)
}
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)
+}
});
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,
+ }
+}
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;
}
pub struct ArchiveMetadata {
- archive: ArchiveRO,
+ _archive: ArchiveRO,
// See comments in ArchiveMetadata::new for why this is static
data: &'static [u8],
}
unsafe { mem::transmute(data) }
};
Some(ArchiveMetadata {
- archive: ar,
+ _archive: ar,
data: data,
})
}
// Extra parameters are for converting to/from def_ids in the string rep.
// Whatever format you choose should not contain pipe characters.
pub struct ty_abbrev {
- pos: uint,
- len: uint,
s: String
}
if abbrev_len < len {
// I.e. it's actually an abbreviation.
cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
- pos: pos as uint,
- len: len as uint,
s: format!("\\#{:x}:{:x}\\#", pos, len)
});
}
The reasoning here is that a mutable borrow must be the only writer,
therefore it prevents other writes (`MUTATE`), mutable borrows
(`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow
-permits other immutable borrows but forbids writes and mutable borows.
+permits other immutable borrows but forbids writes and mutable borrows.
Finally, a const borrow just wants to be sure that the value is not
moved out from under it, so no actions are forbidden.
cause: euv::LoanCause,
cmt: mc::cmt,
loan_region: ty::Region,
- loan_kind: ty::BorrowKind)
+ _: ty::BorrowKind)
-> Result<(),()> {
debug!("guarantee_lifetime(cmt={}, loan_region={})",
cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
span: span,
cause: cause,
loan_region: loan_region,
- loan_kind: loan_kind,
cmt_original: cmt.clone()};
ctxt.check(&cmt, None)
}
span: Span,
cause: euv::LoanCause,
loan_region: ty::Region,
- loan_kind: ty::BorrowKind,
cmt_original: mc::cmt
}
Loan {
index: self.all_loans.len(),
loan_path: loan_path,
- cmt: cmt,
kind: req_kind,
gen_scope: gen_scope,
kill_scope: kill_scope,
/// This visitor walks static initializer's expressions and makes
/// sure the loans being taken are sound.
struct StaticInitializerCtxt<'a> {
- bccx: &'a BorrowckCtxt<'a>,
- item_ub: ast::NodeId,
+ bccx: &'a BorrowckCtxt<'a>
}
impl<'a> visit::Visitor<()> for StaticInitializerCtxt<'a> {
debug!("gather_loans_in_static_initializer(expr={})", expr.repr(bccx.tcx));
let mut sicx = StaticInitializerCtxt {
- bccx: bccx,
- item_ub: expr.id,
+ bccx: bccx
};
sicx.visit_expr(expr, ());
bccx: bccx,
span: span,
cause: cause,
- cmt_original: cmt.clone(),
loan_region: loan_region,
};
struct RestrictionsContext<'a> {
bccx: &'a BorrowckCtxt<'a>,
span: Span,
- cmt_original: mc::cmt,
loan_region: ty::Region,
cause: euv::LoanCause,
}
pub struct Loan {
index: uint,
loan_path: Rc<LoanPath>,
- cmt: mc::cmt,
kind: ty::BorrowKind,
restrictions: Vec<Restriction>,
gen_scope: ast::NodeId,
}
}
+ fn handle_field_access(&mut self, lhs: &ast::Expr, name: &ast::Ident) {
+ match ty::get(ty::expr_ty_adjusted(self.tcx, lhs)).sty {
+ ty::ty_struct(id, _) => {
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ let field_id = fields.iter()
+ .find(|field| field.name == name.name).unwrap().id;
+ self.live_symbols.insert(field_id.node);
+ },
+ _ => ()
+ }
+ }
+
+ fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
+ match self.tcx.def_map.borrow().get(&lhs.id) {
+ &def::DefStruct(id) | &def::DefVariant(_, id, _) => {
+ let fields = ty::lookup_struct_fields(self.tcx, id);
+ for pat in pats.iter() {
+ let field_id = fields.iter()
+ .find(|field| field.name == pat.ident.name).unwrap().id;
+ self.live_symbols.insert(field_id.node);
+ }
+ }
+ _ => ()
+ }
+ }
+
fn mark_live_symbols(&mut self) {
let mut scanned = HashSet::new();
while self.worklist.len() > 0 {
match *node {
ast_map::NodeItem(item) => {
match item.node {
+ ast::ItemStruct(struct_def, _) => {
+ let has_extern_repr = item.attrs.iter().fold(attr::ReprAny, |acc, attr| {
+ attr::find_repr_attr(self.tcx.sess.diagnostic(), attr, acc)
+ }) == attr::ReprExtern;
+ let live_fields = struct_def.fields.iter().filter(|f| {
+ has_extern_repr || match f.node.kind {
+ ast::NamedField(_, ast::Public) => true,
+ _ => false
+ }
+ });
+ self.live_symbols.extend(live_fields.map(|f| f.node.id));
+ visit::walk_item(self, item, ());
+ }
ast::ItemFn(..)
| ast::ItemTy(..)
| ast::ItemEnum(..)
- | ast::ItemStruct(..)
| ast::ItemStatic(..) => {
visit::walk_item(self, item, ());
}
ast::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.id, expr.span);
}
+ ast::ExprField(ref lhs, ref ident, _) => {
+ self.handle_field_access(*lhs, ident);
+ }
_ => ()
}
visit::walk_expr(self, expr, ())
}
+ fn visit_pat(&mut self, pat: &ast::Pat, _: ()) {
+ match pat.node {
+ ast::PatStruct(_, ref fields, _) => {
+ self.handle_field_pattern_match(pat, fields.as_slice());
+ }
+ _ => ()
+ }
+
+ visit::walk_pat(self, pat, ())
+ }
+
fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId, _: ()) {
self.lookup_and_handle_definition(&id);
visit::walk_path(self, path, ());
}
- fn visit_item(&mut self, _item: &ast::Item, _: ()) {
+ fn visit_item(&mut self, _: &ast::Item, _: ()) {
// Do not recurse into items. These items will be added to the
// worklist and recursed into manually if necessary.
}
}
impl<'a> DeadVisitor<'a> {
+ fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
+ let (is_named, has_leading_underscore) = match node.ident() {
+ Some(ref ident) => (true, token::get_ident(*ident).get()[0] == ('_' as u8)),
+ _ => (false, false)
+ };
+ let field_type = ty::node_id_to_type(self.tcx, node.id);
+ let is_marker_field = match ty::ty_to_def_id(field_type) {
+ Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
+ _ => false
+ };
+ is_named
+ && !self.symbol_is_live(node.id, None)
+ && !has_leading_underscore
+ && !is_marker_field
+ && !has_allow_dead_code_or_lang_attr(node.attrs.as_slice())
+ }
+
// id := node id of an item's definition.
// ctor_id := `Some` if the item is a struct_ctor (tuple struct),
// `None` otherwise.
visit::walk_block(self, block, ());
}
+ fn visit_struct_field(&mut self, field: &ast::StructField, _: ()) {
+ if self.should_warn_about_field(&field.node) {
+ self.warn_dead_code(field.node.id, field.span, field.node.ident().unwrap());
+ }
+
+ visit::walk_struct_field(self, field, ());
+ }
+
// Overwrite so that we don't warn the trait method itself.
fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
match *trait_method {
None => {
self.tcx().sess.span_bug(
callee.span,
- format!("unxpected callee type {}",
+ format!("unexpected callee type {}",
callee_ty.repr(self.tcx())).as_slice());
}
}
//
// A common use for graphs in our compiler is to perform
// fixed-point iteration. In this case, each edge represents a
- // constaint, and the nodes themselves are associated with
+ // constraint, and the nodes themselves are associated with
// variables or other bitsets. This method facilitates such a
// computation.
struct CaptureInfo {
ln: LiveNode,
- is_move: bool,
var_nid: NodeId
}
-enum LocalKind {
- FromMatch(BindingMode),
- FromLetWithInitializer,
- FromLetNoInitializer
-}
-
struct LocalInfo {
id: NodeId,
- ident: Ident,
- is_mutbl: bool,
- kind: LocalKind,
+ ident: Ident
}
enum VarKind {
}
fn visit_local(ir: &mut IrMaps, local: &Local) {
- pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
+ pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |_, p_id, sp, path| {
debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path);
ir.add_live_node_for_node(p_id, VarDefNode(sp));
- let kind = match local.init {
- Some(_) => FromLetWithInitializer,
- None => FromLetNoInitializer
- };
- let mutbl = match bm {
- BindByValue(MutMutable) => true,
- _ => false
- };
ir.add_variable(Local(LocalInfo {
id: p_id,
- ident: name,
- is_mutbl: mutbl,
- kind: kind
+ ident: name
}));
});
visit::walk_local(ir, local, ());
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = ast_util::path_to_ident(path);
- let mutbl = match bm {
- BindByValue(MutMutable) => true,
- _ => false
- };
ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo {
id: p_id,
- ident: name,
- is_mutbl: mutbl,
- kind: FromMatch(bm)
+ ident: name
}));
})
}
// in better error messages than just pointing at the closure
// construction site.
let mut call_caps = Vec::new();
- let fv_mode = freevars::get_capture_mode(ir.tcx, expr.id);
freevars::with_freevars(ir.tcx, expr.id, |freevars| {
for fv in freevars.iter() {
match moved_variable_node_id_from_def(fv.def) {
Some(rv) => {
let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
- let fv_id = fv.def.def_id().node;
- let fv_ty = ty::node_id_to_type(ir.tcx, fv_id);
- let is_move = match fv_mode {
- // var must be dead afterwards
- freevars::CaptureByValue => {
- ty::type_moves_by_default(ir.tcx, fv_ty)
- }
-
- // var can still be used
- freevars::CaptureByRef => {
- false
- }
- };
call_caps.push(CaptureInfo {ln: fv_ln,
- is_move: is_move,
var_nid: rv});
}
None => {}
* is the address of the lvalue. If Expr is an rvalue, this is the address of
* some temporary spot in memory where the result is stored.
*
- * Now, cat_expr() classies the expression Expr and the address A=ToAddr(Expr)
+ * Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr)
* as follows:
*
* - cat: what kind of expression was this? This is a subset of the
*
* The resulting categorization tree differs somewhat from the expressions
* themselves. For example, auto-derefs are explicit. Also, an index a[b] is
- * decomposed into two operations: a derefence to reach the array data and
+ * decomposed into two operations: a dereference to reach the array data and
* then an index to jump forward to the relevant item.
*
* ## By-reference upvars
struct PrivacyVisitor<'a> {
tcx: &'a ty::ctxt,
curitem: ast::NodeId,
- in_fn: bool,
in_foreign: bool,
parents: NodeMap<ast::NodeId>,
external_exports: resolve::ExternalExports,
// Use the parent map to check the privacy of everything
let mut visitor = PrivacyVisitor {
curitem: ast::DUMMY_NODE_ID,
- in_fn: false,
in_foreign: false,
tcx: tcx,
parents: visitor.parents,
- `scope_map` maps from a scope id to the enclosing scope id; this is
usually corresponding to the lexical nesting, though in the case of
- closures the parent scope is the innermost conditinal expression or repeating
+ closures the parent scope is the innermost conditional expression or repeating
block
- `var_map` maps from a variable or binding id to the block in which
/// The main resolver class.
struct Resolver<'a> {
session: &'a Session,
- lang_items: &'a LanguageItems,
graph_root: NameBindings,
// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
- // The four namespaces.
- namespaces: Vec<Namespace> ,
-
def_map: DefMap,
export_map2: ExportMap2,
trait_map: TraitMap,
}
impl<'a> Resolver<'a> {
- fn new(session: &'a Session, lang_items: &'a LanguageItems, crate_span: Span) -> Resolver<'a> {
+ fn new(session: &'a Session, crate_span: Span) -> Resolver<'a> {
let graph_root = NameBindings::new();
graph_root.define_module(NoParentLink,
Resolver {
session: session,
- lang_items: lang_items,
// The outermost module has def ID 0; this is not reflected in the
// AST.
primitive_type_table: PrimitiveTypeTable::new(),
- namespaces: vec!(TypeNS, ValueNS),
-
def_map: RefCell::new(NodeMap::new()),
export_map2: RefCell::new(NodeMap::new()),
trait_map: NodeMap::new(),
}
fn resolve_type_parameter_bound(&mut self,
- id: NodeId,
- type_parameter_bound: &TyParamBound) {
+ id: NodeId,
+ type_parameter_bound: &TyParamBound) {
match *type_parameter_bound {
TraitTyParamBound(ref tref) => {
self.resolve_trait_reference(id, tref, TraitBoundingTypeParameter)
}
- StaticRegionTyParamBound => {}
- OtherRegionTyParamBound(_) => {}
+ UnboxedFnTyParamBound(ref unboxed_function) => {
+ for argument in unboxed_function.decl.inputs.iter() {
+ self.resolve_type(argument.ty);
+ }
+
+ self.resolve_type(unboxed_function.decl.output);
+ }
+ StaticRegionTyParamBound | OtherRegionTyParamBound(_) => {}
}
}
/// Entry point to crate resolution.
pub fn resolve_crate(session: &Session,
- lang_items: &LanguageItems,
+ _: &LanguageItems,
krate: &Crate)
-> CrateMap {
- let mut resolver = Resolver::new(session, lang_items, krate.span);
+ let mut resolver = Resolver::new(session, krate.span);
resolver.resolve(krate);
let Resolver { def_map, export_map2, trait_map, last_private,
external_exports, .. } = resolver;
let datum = datum::rvalue_scratch_datum(bcx, struct_ty, "");
return single_result(Result::new(bcx, datum.val));
}
- lit(ConstLit(lit_id)) => {
- let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id);
- return single_result(Result::new(bcx, llval));
+ lit(l @ ConstLit(ref def_id)) => {
+ let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_to_expr(bcx.tcx(), &l).id);
+ let (llval, _) = consts::get_const_val(bcx.ccx(), *def_id);
+ let lit_datum = immediate_rvalue(llval, lit_ty);
+ let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
+ return single_result(Result::new(bcx, lit_datum.val));
}
var(disr_val, ref repr) => {
return adt::trans_case(bcx, &**repr, disr_val);
let ty = type_of::type_of(bcx.ccx(), *nullfields.get(ix));
assert_eq!(machine::llsize_of_alloc(bcx.ccx(), ty), 0);
// The contents of memory at this pointer can't matter, but use
- // the value that's "reasonable" in case of pointer comparision.
+ // the value that's "reasonable" in case of pointer comparison.
PointerCast(bcx, val, ty.ptr_to())
}
RawNullablePointer { nndiscr, nnty, .. } => {
task_local_insn_key.replace(Some(RefCell::new(Vec::new())));
}
-pub struct _InsnCtxt { _x: () }
+pub struct _InsnCtxt {
+ _cannot_construct_outside_of_this_module: ()
+}
#[unsafe_destructor]
impl Drop for _InsnCtxt {
Some(ctx) => ctx.borrow_mut().push(s),
None => {}
}
- _InsnCtxt { _x: () }
+ _InsnCtxt { _cannot_construct_outside_of_this_module: () }
}
pub struct StatRecorder<'a> {
for var in variants.iter() {
let mut size = 0;
for field in var.fields.iter().skip(1) {
- // skip the dicriminant
+ // skip the discriminant
size += llsize_of_real(ccx, sizing_type_of(ccx, *field));
}
sizes.push(size);
// LLVM code generator emits a ".file filename" directive
// for ELF backends. Value of the "filename" is set as the
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
- // crashes if the module identifer is same as other symbols
+ // crashes if the module identifier is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let mut llmod_id = link_meta.crateid.name.clone();
let len = s.get().len();
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
Type::i8p(cx).to_ref());
- C_struct(cx, [cs, C_uint(cx, len)], false)
+ C_named_struct(cx.tn.find_type("str_slice").unwrap(), [cs, C_uint(cx, len)])
}
}
ccx.int_type = Type::int(&ccx);
ccx.opaque_vec_type = Type::opaque_vec(&ccx);
- ccx.tn.associate_type("tydesc", &Type::tydesc(&ccx));
-
let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type], false);
ccx.tn.associate_type("str_slice", &str_slice_ty);
+ ccx.tn.associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty));
+
if ccx.sess().count_llvm_insns() {
base::init_insn_ctxt()
}
use middle::trans::common::*;
use middle::trans::debuginfo;
use middle::trans::expr;
-use middle::trans::type_of;
use middle::ty;
use util::ppaux::Repr;
fn str_slice_arg<'a>(bcx: &'a Block<'a>, s: InternedString) -> ValueRef {
let ccx = bcx.ccx();
- let t = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable);
let s = C_str_slice(ccx, s);
let slot = alloca(bcx, val_ty(s), "__temp");
Store(bcx, s, slot);
-
- // The type of C_str_slice is { i8*, i64 }, but the type of the &str is
- // %str_slice, so we do a bitcast here to the right type.
- BitCast(bcx, slot, type_of::type_of(ccx, t).ptr_to())
+ slot
}
pub fn trans_fail<'a>(
// As far as debuginfo is concerned, the pointer this enum represents is still
// wrapped in a struct. This is to make the DWARF representation of enums uniform.
- // First create a description of the artifical wrapper struct:
+ // First create a description of the artificial wrapper struct:
let non_null_variant = self.variants.get(non_null_variant_index as uint);
let non_null_variant_ident = non_null_variant.name;
let non_null_variant_name = token::get_ident(non_null_variant_ident);
// function, because the foreign function may opt to return via an
// out pointer.
llret_ty: Type,
-
- // True if *Rust* would use an outpointer for this function.
- sret: bool,
}
let llret_ty = type_of::type_of(ccx, fn_sig.output);
LlvmSignature {
llarg_tys: llarg_tys,
- llret_ty: llret_ty,
- sret: type_of::return_uses_outptr(ccx, fn_sig.output),
+ llret_ty: llret_ty
}
}
Type::func([t], &Type::void(ccx))
}
- pub fn tydesc(ccx: &CrateContext) -> Type {
+ pub fn tydesc(ccx: &CrateContext, str_slice_ty: Type) -> Type {
let mut tydesc = Type::named_struct(ccx, "tydesc");
let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to();
int_ty, // align
glue_fn_ty, // drop
glue_fn_ty, // visit
- Type::struct_(ccx, [Type::i8p(ccx), Type::int(ccx)], false)]; // name
+ str_slice_ty]; // name
tydesc.set_struct_body(elems, false);
tydesc
use middle::const_eval;
use middle::def;
-use middle::subst;
+use middle::lang_items::FnMutTraitLangItem;
use middle::subst::{Subst, Substs};
-use middle::ty::{ty_param_substs_and_ty};
+use middle::subst;
+use middle::ty::ty_param_substs_and_ty;
use middle::ty;
-use middle::typeck::rscope;
-use middle::typeck::rscope::{RegionScope};
use middle::typeck::lookup_def_tcx;
+use middle::typeck::rscope::RegionScope;
+use middle::typeck::rscope;
use util::ppaux::Repr;
use std::rc::Rc;
ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
}
+pub fn trait_ref_for_unboxed_function<AC:AstConv,
+ RS:RegionScope>(
+ this: &AC,
+ rscope: &RS,
+ unboxed_function: &ast::UnboxedFnTy)
+ -> ty::TraitRef {
+ let fn_mut_trait_did = this.tcx()
+ .lang_items
+ .require(FnMutTraitLangItem)
+ .unwrap();
+ let input_types =
+ unboxed_function.decl
+ .inputs
+ .iter()
+ .map(|input| {
+ ast_ty_to_ty(this, rscope, input.ty)
+ }).collect::<Vec<_>>();
+ let input_tuple = ty::mk_tup(this.tcx(), input_types);
+ let output_type = ast_ty_to_ty(this,
+ rscope,
+ unboxed_function.decl.output);
+ let substs = subst::Substs {
+ self_ty: None,
+ tps: vec!(input_tuple, output_type),
+ regions: subst::NonerasedRegions(Vec::new()),
+ };
+ ty::TraitRef {
+ def_id: fn_mut_trait_did,
+ substs: substs,
+ }
+}
+
// Handle `~`, `Box`, and `&` being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
}
return constr(ty::mk_vec(tcx, mt, None));
}
+ ast::TyUnboxedFn(ref unboxed_function) => {
+ let trait_store = match ptr_ty {
+ Uniq => ty::UniqTraitStore,
+ RPtr(r) => {
+ ty::RegionTraitStore(r, a_seq_ty.mutbl)
+ }
+ _ => {
+ tcx.sess.span_err(
+ a_seq_ty.ty.span,
+ "~trait or &trait are the only supported \
+ forms of casting-to-trait");
+ return ty::mk_err();
+ }
+ };
+ let ty::TraitRef {
+ def_id,
+ substs
+ } = trait_ref_for_unboxed_function(this,
+ rscope,
+ *unboxed_function);
+ return ty::mk_trait(this.tcx(),
+ def_id,
+ substs,
+ trait_store,
+ ty::empty_builtin_bounds());
+ }
ast::TyPath(ref path, ref bounds, id) => {
// Note that the "bounds must be empty if path is not a trait"
// restriction is enforced in the below case for ty_path, which
return ty::mk_err();
}
};
- let bounds = conv_builtin_bounds(this.tcx(), bounds, trait_store);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ path.span,
+ bounds,
+ trait_store);
return ty::mk_trait(tcx,
result.def_id,
result.substs.clone(),
// Use corresponding trait store to figure out default bounds
// if none were specified.
- let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, store);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ ast_ty.span,
+ &f.bounds,
+ store);
let fn_decl = ty_of_closure(this,
ast_ty.id,
ast::TyProc(ref f) => {
// Use corresponding trait store to figure out default bounds
// if none were specified.
- let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, ty::UniqTraitStore);
+ let bounds = conv_builtin_bounds(this.tcx(),
+ ast_ty.span,
+ &f.bounds,
+ ty::UniqTraitStore);
let fn_decl = ty_of_closure(this,
ast_ty.id,
None);
ty::mk_closure(tcx, fn_decl)
}
+ ast::TyUnboxedFn(_) => {
+ tcx.sess.span_err(ast_ty.span,
+ "cannot use unboxed functions here");
+ ty::mk_err()
+ }
ast::TyPath(ref path, ref bounds, id) => {
let a_def = match tcx.def_map.borrow().find(&id) {
None => {
}
}
-fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
+fn conv_builtin_bounds(tcx: &ty::ctxt,
+ span: Span,
+ ast_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
store: ty::TraitStore)
-> ty::BuiltinBounds {
//! Converts a list of bounds from the AST into a `BuiltinBounds`
ast::StaticRegionTyParamBound => {
builtin_bounds.add(ty::BoundStatic);
}
+ ast::UnboxedFnTyParamBound(_) => {
+ tcx.sess.span_err(span,
+ "unboxed functions are not allowed \
+ here");
+ }
ast::OtherRegionTyParamBound(span) => {
if !tcx.sess.features.issue_5723_bootstrap.get() {
tcx.sess.span_err(
}
/// Whether `check_binop` is part of an assignment or not.
-/// Used to know wether we allow user overloads and to print
+/// Used to know whether we allow user overloads and to print
/// better messages on error.
#[deriving(PartialEq)]
enum IsBinopAssignment{
e: &ast::Expr,
declty: ty::t) {
// Gather locals in statics (because of block expressions).
- // This is technically uneccessary because locals in static items are forbidden,
+ // This is technically unnecessary because locals in static items are forbidden,
// but prevents type checking from blowing up before const checking can properly
// emit a error.
GatherLocalsVisitor { fcx: fcx }.visit_expr(e, ());
}
None => {
fcx.tcx().sess.span_bug(span,
- "missing default for a not explicitely provided type param")
+ "missing default for a not explicitly provided type param")
}
}
}
use std::rc::Rc;
struct UniversalQuantificationResult {
- monotype: t,
- type_variables: Vec<ty::t> ,
- type_param_defs: Rc<Vec<ty::TypeParameterDef> >
+ monotype: t
}
fn get_base_type(inference_context: &InferCtxt,
let monotype = polytype.ty.subst(self.crate_context.tcx, &substitutions);
UniversalQuantificationResult {
- monotype: monotype,
- type_variables: substitutions.tps,
- type_param_defs: polytype.generics.type_param_defs.clone()
+ monotype: monotype
}
}
use util::ppaux;
use util::ppaux::Repr;
-use std::rc::Rc;
use std::collections::{HashMap, HashSet};
-
+use std::rc::Rc;
use syntax::abi;
-use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound,
- TraitTyParamBound};
+use syntax::ast::{StaticRegionTyParamBound, OtherRegionTyParamBound};
+use syntax::ast::{TraitTyParamBound, UnboxedFnTyParamBound};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{local_def, split_trait_methods};
use syntax::codemap::Span;
use syntax::codemap;
+use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::print::pprust::{path_to_str};
use syntax::visit;
-use syntax::owned_slice::OwnedSlice;
struct CollectItemTypesVisitor<'a> {
ccx: &'a CrateCtxt<'a>
param_bounds.builtin_bounds.add(ty::BoundStatic);
}
+ UnboxedFnTyParamBound(ref unboxed_function) => {
+ let rscope = ExplicitRscope;
+ let mut trait_ref =
+ astconv::trait_ref_for_unboxed_function(
+ ccx,
+ &rscope,
+ unboxed_function);
+ let self_ty = ty::mk_param(ccx.tcx,
+ param_ty.idx,
+ param_ty.def_id);
+ trait_ref.substs.self_ty = Some(self_ty);
+ param_bounds.trait_bounds.push(Rc::new(trait_ref));
+ }
+
OtherRegionTyParamBound(span) => {
if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
ccx.tcx.sess.span_err(
self.unpack_actual_value(a, |sty_a| {
match *sty_a {
ty::ty_bare_fn(ref a_f) => {
- // Bare functions are coercable to any closure type.
+ // Bare functions are coercible to any closure type.
//
// FIXME(#3320) this should go away and be
// replaced with proper inference, got a patch
pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
- // This is a horible hack - historically, [T] was not treated as a type,
+ // This is a horrible hack - historically, [T] was not treated as a type,
// so, for example, &T and &[U] should not unify. In fact the only thing
// &[U] should unify with is &[T]. We preserve that behaviour with this
// check.
the relevant line of code has been type-checked. Therefore, there is
an elaborate system to track why a particular constraint in the
inference graph arose so that we can explain to the user what gave
-rise to a patricular error.
+rise to a particular error.
The basis of the system are the "origin" types. An "origin" is the
reason that a constraint or inference variable arose. There are
match tpb {
&ast::StaticRegionTyParamBound => ast::StaticRegionTyParamBound,
&ast::OtherRegionTyParamBound(s) => ast::OtherRegionTyParamBound(s),
+ &ast::UnboxedFnTyParamBound(unboxed_function_type) => {
+ ast::UnboxedFnTyParamBound(unboxed_function_type)
+ }
&ast::TraitTyParamBound(ref tr) => {
let last_seg = tr.path.segments.last().unwrap();
let mut insert = Vec::new();
* The code in here is defined quite generically so that it can be
* applied both to type variables, which represent types being inferred,
* and fn variables, which represent function types being inferred.
- * It may eventually be applied to ther types as well, who knows.
+ * It may eventually be applied to their types as well, who knows.
* In some cases, the functions are also generic with respect to the
* operation on the lattice (GLB vs LUB).
*
Note that such components must consist solely of region variables; all
of these variables can effectively be unified into a single variable.
Once SCCs are removed, we are left with a DAG. At this point, we
-could walk the DAG in toplogical order once to compute the expanding
+could walk the DAG in topological order once to compute the expanding
nodes, and again in reverse topological order to compute the
contracting nodes. However, as I said, this does not work given the
current treatment of closure bounds, but perhaps in the future we can
contains 'intermediate' variables created to represent the LUB/GLB of
individual regions. Basically, when asked to compute the LUB/GLB of a
region variable with another region, the inferencer cannot oblige
-immediately since the valuese of that variables are not known.
+immediately since the values of that variables are not known.
Therefore, it creates a new variable that is related to the two
regions. For example, the LUB of two variables `$x` and `$y` is a
fresh variable `$z` that is constrained such that `$x <= $z` and `$y
struct InferredInfo<'a> {
item_id: ast::NodeId,
kind: ParamKind,
- index: uint,
param_id: ast::NodeId,
term: VarianceTermPtr<'a>,
}
let term = self.arena.alloc(|| InferredTerm(inf_index));
self.inferred_infos.push(InferredInfo { item_id: item_id,
kind: kind,
- index: index,
param_id: param_id,
term: term });
let newly_added = self.inferred_map.insert(param_id, inf_index);
let variant =
ty::VariantInfo::from_ast_variant(tcx,
ast_variant,
- /*discrimant*/ 0);
+ /*discriminant*/ 0);
for &arg_ty in variant.args.iter() {
self.add_constraints_from_ty(arg_ty, self.covariant);
}
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;
r
}
-pub struct _indenter {
- _i: (),
+pub struct Indenter {
+ _cannot_construct_outside_of_this_module: ()
}
-impl Drop for _indenter {
+impl Drop for Indenter {
fn drop(&mut self) { debug!("<<"); }
}
-pub fn _indenter(_i: ()) -> _indenter {
- _indenter {
- _i: ()
- }
-}
-
-pub fn indenter() -> _indenter {
+pub fn indenter() -> Indenter {
debug!(">>");
- _indenter(())
+ Indenter { _cannot_construct_outside_of_this_module: () }
}
struct LoopQueryVisitor<'a> {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > Zero::zero() {
- fail!("numeric overflow occured.")
+ fail!("numeric overflow occurred.")
}
match bits.checked_add(&new_low_bits) {
Some(x) => return x,
- None => fail!("numeric overflow occured.")
+ None => fail!("numeric overflow occurred.")
}
}
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,
match *self {
ast::StaticRegionTyParamBound => RegionBound,
ast::OtherRegionTyParamBound(_) => RegionBound,
+ ast::UnboxedFnTyParamBound(_) => {
+ // FIXME(pcwalton): Wrong.
+ RegionBound
+ }
ast::TraitTyParamBound(ref t) => TraitBound(t.clean()),
}
}
mod imp {
use libc;
use std::mem;
- use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
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 |
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());
}
//! // ... something using html
//! ```
+#![allow(dead_code)]
#![allow(non_camel_case_types)]
use libc;
}
/// By default this markdown renderer generates anchors for each header in the
-/// rendered document. The anchor name is the contents of the header spearated
+/// rendered document. The anchor name is the contents of the header separated
/// by hyphens, and a task-local map is used to disambiguate among duplicate
/// headers (numbers are appended).
///
#[deriving(PartialEq)]
pub struct TocBuilder {
top_level: Toc,
- /// The current heirachy of parent headings, the levels are
+ /// The current hierarchy of parent headings, the levels are
/// strictly increasing (i.e. chain[0].level < chain[1].level <
- /// ...) with each entry being the most recent occurance of a
+ /// ...) with each entry being the most recent occurrence of a
/// heading with that level (it doesn't include the most recent
- /// occurences of every level, just, if *is* in `chain` then is is
+ /// occurrences of every level, just, if *is* in `chain` then is is
/// the most recent one).
///
/// We also have `chain[0].level <= top_level.entries[last]`.
}
/// Push a level `level` heading into the appropriate place in the
- /// heirarchy, returning a string containing the section number in
+ /// hierarchy, returning a string containing the section number in
/// `<num>.<num>.<num>` format.
pub fn push<'a>(&'a mut self, level: u32, name: String, id: String) -> &'a str {
assert!(level >= 1);
#[test]
fn should_ignore_first_line_indent() {
- // Thi first line of the first paragraph may not be indented as
+ // The first line of the first paragraph may not be indented as
// far due to the way the doc string was written:
//
// #[doc = "Start way over here
use clean;
-use dl = std::unstable::dynamic_lib;
+use dl = std::dynamic_lib;
use serialize::json;
use std::string::String;
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;
static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7;
static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB;
+ #[repr(C)]
pub struct pthread_mutex_t {
__sig: libc::c_long,
__opaque: [u8, ..__PTHREAD_MUTEX_SIZE__],
}
+ #[repr(C)]
pub struct pthread_cond_t {
__sig: libc::c_long,
__opaque: [u8, ..__PTHREAD_COND_SIZE__],
#[cfg(target_arch = "mips")]
static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+ #[repr(C)]
pub struct pthread_mutex_t {
__align: libc::c_longlong,
size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T],
}
+ #[repr(C)]
pub struct pthread_cond_t {
__align: libc::c_longlong,
size: [u8, ..__SIZEOF_PTHREAD_COND_T],
mod os {
use libc;
+ #[repr(C)]
pub struct pthread_mutex_t { value: libc::c_int }
+ #[repr(C)]
pub struct pthread_cond_t { value: libc::c_int }
pub static PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
// Here we must unsafely borrow the task in order to not remove it from
// TLS. When collecting failure, we may attempt to send on a channel (or
- // just run aribitrary code), so we must be sure to still have a local
+ // just run arbitrary code), so we must be sure to still have a local
// task in TLS.
unsafe {
let me: *mut Task = Local::unsafe_borrow();
/// The core of the unwinding.
///
/// This is non-generic to avoid instantiation bloat in other crates
-/// (which makes compilation of small crates noticably slower). (Note:
+/// (which makes compilation of small crates noticeably slower). (Note:
/// we need the `Any` object anyway, we're not just creating it to
/// avoid being generic.)
///
// First, invoke call the user-defined callbacks triggered on task failure.
//
// By the time that we see a callback has been registered (by reading
- // MAX_CALLBACKS), the actuall callback itself may have not been stored yet,
+ // MAX_CALLBACKS), the actual callback itself may have not been stored yet,
// so we just chalk it up to a race condition and move on to the next
// callback. Additionally, CALLBACK_CNT may briefly be higher than
// MAX_CALLBACKS, so we're sure to clamp it as necessary.
pub struct IdleWatcher {
handle: *uvll::uv_idle_t,
idle_flag: bool,
- closed: bool,
callback: Box<Callback:Send>,
}
let me = box IdleWatcher {
handle: handle,
idle_flag: false,
- closed: false,
callback: cb,
};
return me.install();
impl Drop for ForbidSwitch {
fn drop(&mut self) {
assert!(self.io == homing::local_id(),
- "didnt want a scheduler switch: {}",
+ "didn't want a scheduler switch: {}",
self.msg);
}
}
pub struct TcpListener {
home: HomeHandle,
handle: *uvll::uv_pipe_t,
- closing_task: Option<BlockedTask>,
outgoing: Sender<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
incoming: Receiver<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
}
let l = box TcpListener {
home: io.make_handle(),
handle: handle,
- closing_task: None,
outgoing: tx,
incoming: rx,
};
// function is why that wording exists.
//
// Implementation-wise, we must be careful when passing a buffer down to
- // libuv. Most of this implementation avoids allocations becuase of the
+ // libuv. Most of this implementation avoids allocations because of the
// blocking guarantee (all stack local variables are valid for the
// entire read/write request). If our write request can be timed out,
// however, we must heap allocate the data and pass that to the libuv
};
// Send off the request, but be careful to not block until we're sure
- // that the write reqeust is queued. If the reqeust couldn't be queued,
+ // that the write request is queued. If the request couldn't be queued,
// then we should return immediately with an error.
match unsafe {
uvll::uv_write(req.handle, self.handle, [uv_buf], write_cb)
// These fields are private because they must be interfaced with through the
// functions below.
+#[repr(C)]
pub struct uv_stdio_container_t {
flags: libc::c_int,
stream: *uv_stream_t,
}
pub fn move_iter(self) -> MoveEntries<K, V> {
- MoveEntries { table: self, idx: 0, elems_seen: 0 }
+ MoveEntries { table: self, idx: 0 }
}
}
/// Iterator over the entries in a table, consuming the table.
pub struct MoveEntries<K, V> {
table: RawTable<K, V>,
- idx: uint,
- elems_seen: uint,
+ idx: uint
}
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
/// ```
pub fn send_opt(&self, t: T) -> Result<(), T> {
// In order to prevent starvation of other tasks in situations where
- // a task sends repeatedly without ever receiving, we occassionally
+ // a task sends repeatedly without ever receiving, we occasionally
// yield instead of doing a send immediately.
//
// Don't unconditionally attempt to yield because the TLS overhead can
--- /dev/null
+// 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);
+ }
+}
* 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
/* 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]
// 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;
+}
use os::TMPBUF_SZ;
use slice::{MutableVector, ImmutableVector};
use string::String;
- use str::{StrSlice, StrAllocating};
+ use str::StrSlice;
use str;
use vec::Vec;
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())
- }
}
/*
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)
})
})
}
/// 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());
})
}
}
}
#[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());
})
}
}
#[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)
}
}
#[cfg(target_os = "macos")]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use intrinsics;
+ #[repr(C)]
struct Dl_info {
dli_fname: *libc::c_char,
dli_fbase: *libc::c_void,
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" {
/// Options to spawn the new task with
pub opts: TaskOpts,
gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
- nocopy: Option<marker::NoCopy>,
+ nocopy: marker::NoCopy,
}
impl TaskBuilder {
TaskBuilder {
opts: TaskOpts::new(),
gen_body: None,
- nocopy: None,
+ nocopy: marker::NoCopy,
}
}
+++ /dev/null
-// 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);
- }
-}
+++ /dev/null
-// 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;
#[test]
fn test_mutex_arc_nested() {
// Tests nested mutexes and access
- // to underlaying data.
+ // to underlying data.
let arc = Arc::new(Mutex::new(1));
let arc2 = Arc::new(Mutex::new(arc));
task::spawn(proc() {
// Implementation-wise, this would seem like a fairly trivial primitive.
// The stickler part is where our mutexes currently require an
- // allocation, and usage of a `Once` should't leak this allocation.
+ // allocation, and usage of a `Once` shouldn't leak this allocation.
//
// This means that there must be a deterministic destroyer of the mutex
// contained within (because it's not needed after the initialization
/// dropped, this value will release the resource back to the semaphore.
#[must_use]
pub struct SemaphoreGuard<'a> {
- guard: SemGuard<'a, ()>,
+ _guard: SemGuard<'a, ()>,
}
impl Semaphore {
/// Acquire a resource of this semaphore, returning an RAII guard which will
/// release the resource when dropped.
pub fn access<'a>(&'a self) -> SemaphoreGuard<'a> {
- SemaphoreGuard { guard: self.sem.access() }
+ SemaphoreGuard { _guard: self.sem.access() }
}
}
/// corresponding mutex is also unlocked.
#[must_use]
pub struct MutexGuard<'a> {
- guard: SemGuard<'a, Vec<WaitQueue>>,
+ _guard: SemGuard<'a, Vec<WaitQueue>>,
/// Inner condition variable which is connected to the outer mutex, and can
/// be used for atomic-unlock-and-deschedule.
pub cond: Condvar<'a>,
/// also be accessed through the returned guard.
pub fn lock<'a>(&'a self) -> MutexGuard<'a> {
let SemCondGuard { guard, cvar } = self.sem.access_cond();
- MutexGuard { guard: guard, cond: cvar }
+ MutexGuard { _guard: guard, cond: cvar }
}
}
pub enum TyParamBound {
TraitTyParamBound(TraitRef),
StaticRegionTyParamBound,
+ UnboxedFnTyParamBound(UnboxedFnTy),
OtherRegionTyParamBound(Span) // FIXME -- just here until work for #5723 lands
}
pub decl: P<FnDecl>
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+pub struct UnboxedFnTy {
+ pub decl: P<FnDecl>,
+}
+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
pub enum Ty_ {
TyNil,
TyClosure(@ClosureTy, Option<Lifetime>),
TyProc(@ClosureTy),
TyBareFn(@BareFnTy),
+ TyUnboxedFn(@UnboxedFnTy),
TyTup(Vec<P<Ty>> ),
TyPath(Path, Option<OwnedSlice<TyParamBound>>, NodeId), // for #7264; see above
TyTypeof(@Expr),
pub attrs: Vec<Attribute>,
}
+impl StructField_ {
+ pub fn ident(&self) -> Option<Ident> {
+ match self.kind {
+ NamedField(ref ident, _) => Some(ident.clone()),
+ UnnamedField(_) => None
+ }
+ }
+}
+
pub type StructField = Spanned<StructField_>;
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
/// Create a default MacResult that can only be an expression.
///
/// Use this for macros that must expand to an expression, so even
- /// if an error is encountered internally, the user will recieve
+ /// if an error is encountered internally, the user will receive
/// an error that they also used it in the wrong place.
pub fn expr(sp: Span) -> Box<MacResult> {
box DummyResult { expr_only: true, span: sp } as Box<MacResult>
use parse::token::InternedString;
use parse::token;
-pub struct Field {
- ident: ast::Ident,
- ex: @ast::Expr
-}
-
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
pub use ext;
}
}
-struct Duplicator<'a> {
- cx: &'a ExtCtxt<'a>,
-}
+struct Duplicator<'a>;
impl<'a> Folder for Duplicator<'a> {
fn new_id(&mut self, _: NodeId) -> NodeId {
}
impl Duplicate for @ast::Expr {
- fn duplicate(&self, cx: &ExtCtxt) -> @ast::Expr {
- let mut folder = Duplicator {
- cx: cx,
- };
+ fn duplicate(&self, _: &ExtCtxt) -> @ast::Expr {
+ let mut folder = Duplicator;
folder.fold_expr(*self)
}
}
```
The optimiser should remove the redundancy. We explicitly
- get use the binops to avoid auto-deref derefencing too many
+ get use the binops to avoid auto-deref dereferencing too many
layers of pointers, if the type includes pointers.
*/
let other_f = match other_fs {
&Struct(fields));
// make a series of nested matches, to destructure the
- // structs. This is actually right-to-left, but it shoudn't
+ // structs. This is actually right-to-left, but it shouldn't
// matter.
for (&arg_expr, &pat) in self_args.iter().zip(patterns.iter()) {
body = cx.expr_match(trait_.span, arg_expr,
dotdotdoted: false,
sep: None,
}),
- interpolations: match interp { /* just a convienience */
+ interpolations: match interp { /* just a convenience */
None => HashMap::new(),
Some(x) => x,
},
decl: self.fold_fn_decl(f.decl)
})
}
+ TyUnboxedFn(ref f) => {
+ TyUnboxedFn(@UnboxedFnTy {
+ decl: self.fold_fn_decl(f.decl),
+ })
+ }
TyTup(ref tys) => TyTup(tys.iter().map(|&ty| self.fold_ty(ty)).collect()),
TyPath(ref path, ref bounds, id) => {
let id = self.new_id(id);
match *tpb {
TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
StaticRegionTyParamBound => StaticRegionTyParamBound,
+ UnboxedFnTyParamBound(ref unboxed_function_type) => {
+ UnboxedFnTyParamBound(UnboxedFnTy {
+ decl: fld.fold_fn_decl(unboxed_function_type.decl),
+ })
+ }
OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
}
}
}
// Parse attributes that appear after the opening of an item. These should
- // be preceded by an exclaimation mark, but we accept and warn about one
+ // be preceded by an exclamation mark, but we accept and warn about one
// terminated by a semicolon. In addition to a vector of inner attributes,
// this function also returns a vector that may contain the first outer
// attribute of the next item (since we can't know whether the attribute
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
use ast::{TyNil, TyParam, TyParamBound, TyPath, TyPtr, TyRptr};
-use ast::{TyTup, TyU32, TyUniq, TyVec, UnUniq};
-use ast::{UnnamedField, UnsafeBlock, UnsafeFn, ViewItem};
-use ast::{ViewItem_, ViewItemExternCrate, ViewItemUse};
+use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
+use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
+use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::Visibility;
use ast;
Vec::new()
};
- let inputs = if self.eat(&token::OROR) {
- Vec::new()
+ let (is_unboxed, inputs) = if self.eat(&token::OROR) {
+ (false, Vec::new())
} else {
self.expect_or();
+
+ let is_unboxed = self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| {
+ token::is_keyword(keywords::Mut, t)
+ }) &&
+ self.look_ahead(2, |t| *t == token::COLON);
+ if is_unboxed {
+ self.bump();
+ self.bump();
+ self.bump();
+ }
+
let inputs = self.parse_seq_to_before_or(
&token::COMMA,
|p| p.parse_arg_general(false));
self.expect_or();
- inputs
+ (is_unboxed, inputs)
};
let (region, bounds) = self.parse_optional_ty_param_bounds(true);
variadic: false
});
- TyClosure(@ClosureTy {
- fn_style: fn_style,
- onceness: onceness,
- bounds: bounds,
- decl: decl,
- lifetimes: lifetimes,
- }, region)
+ if is_unboxed {
+ TyUnboxedFn(@UnboxedFnTy {
+ decl: decl,
+ })
+ } else {
+ TyClosure(@ClosureTy {
+ fn_style: fn_style,
+ onceness: onceness,
+ bounds: bounds,
+ decl: decl,
+ lifetimes: lifetimes,
+ }, region)
+ }
}
pub fn parse_unsafety(&mut self) -> FnStyle {
self.mk_expr(lo, hi, ExprLoop(body, opt_ident))
}
- // For distingishing between struct literals and blocks
+ // For distinguishing between struct literals and blocks
fn looking_at_struct_literal(&mut self) -> bool {
self.token == token::LBRACE &&
((self.look_ahead(1, |t| token::is_plain_ident(t)) &&
})
}
+ fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
+ let inputs = if self.eat(&token::OROR) {
+ Vec::new()
+ } else {
+ self.expect_or();
+
+ if self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| {
+ token::is_keyword(keywords::Mut, t)
+ }) &&
+ self.look_ahead(2, |t| *t == token::COLON) {
+ self.bump();
+ self.bump();
+ self.bump();
+ }
+
+ let inputs = self.parse_seq_to_before_or(&token::COMMA,
+ |p| {
+ p.parse_arg_general(false)
+ });
+ self.expect_or();
+ inputs
+ };
+
+ let (return_style, output) = self.parse_ret_ty();
+ UnboxedFnTy {
+ decl: P(FnDecl {
+ inputs: inputs,
+ output: output,
+ cf: return_style,
+ variadic: false,
+ })
+ }
+ }
+
// matches optbounds = ( ( : ( boundseq )? )? )
// where boundseq = ( bound + boundseq ) | bound
// and bound = 'static | ty
let tref = self.parse_trait_ref();
result.push(TraitTyParamBound(tref));
}
+ token::BINOP(token::OR) | token::OROR => {
+ let unboxed_function_type =
+ self.parse_unboxed_function_type();
+ result.push(UnboxedFnTyParamBound(unboxed_function_type));
+ }
_ => break,
}
*
* There is a parallel ring buffer, 'size', that holds the calculated size of
* each token. Why calculated? Because for Begin/End pairs, the "size"
- * includes everything betwen the pair. That is, the "size" of Begin is
+ * includes everything between the pair. That is, the "size" of Begin is
* actually the sum of the sizes of everything between Begin and the paired
* End that follows. Since that is arbitrarily far in the future, 'size' is
* being rewritten regularly while the printer runs; in fact most of the
assert!((self.right != self.left));
}
pub fn advance_left(&mut self, x: Token, l: int) -> io::IoResult<()> {
- debug!("advnce_left ~[{},{}], sizeof({})={}", self.left, self.right,
+ debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right,
self.left, l);
if l >= 0 {
let ret = self.print(x.clone(), l);
use abi;
use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound,
- TraitTyParamBound, Required, Provided};
+ TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
use ast;
use ast_util;
use owned_slice::OwnedSlice;
use codemap;
use diagnostic;
use parse::classify::expr_is_simple_block;
-use parse::token::IdentInterner;
use parse::token;
use parse::lexer::comments;
use parse;
use std::io::{IoResult, MemWriter};
use std::io;
use std::mem;
-use std::rc::Rc;
use std::str;
use std::string::String;
pub struct State<'a> {
pub s: pp::Printer,
cm: Option<&'a CodeMap>,
- intr: Rc<token::IdentInterner>,
comments: Option<Vec<comments::Comment> >,
literals: Option<Vec<comments::Literal> >,
cur_cmnt_and_lit: CurrentCommentAndLiteral,
State {
s: pp::mk_printer(writer, default_columns),
cm: None,
- intr: token::get_ident_interner(),
comments: None,
literals: None,
cur_cmnt_and_lit: CurrentCommentAndLiteral {
let mut s = State {
s: pp::mk_printer(out, default_columns),
cm: Some(cm),
- intr: token::get_ident_interner(),
comments: Some(cmnts),
// If the code is post expansion, don't use the table of
// literals, since it doesn't correspond with the literals
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(Some(f.abi), None, &None,
- f.fn_style, ast::Many, f.decl, None, &None,
- Some(&generics), None));
+ try!(self.print_ty_fn(Some(f.abi),
+ None,
+ &None,
+ f.fn_style,
+ ast::Many,
+ f.decl,
+ None,
+ &None,
+ Some(&generics),
+ None,
+ false));
}
ast::TyClosure(f, ref region) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(None, Some('&'), region, f.fn_style,
- f.onceness, f.decl, None, &f.bounds,
- Some(&generics), None));
+ try!(self.print_ty_fn(None,
+ Some('&'),
+ region,
+ f.fn_style,
+ f.onceness,
+ f.decl,
+ None,
+ &f.bounds,
+ Some(&generics),
+ None,
+ false));
}
ast::TyProc(f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
ty_params: OwnedSlice::empty()
};
- try!(self.print_ty_fn(None, Some('~'), &None, f.fn_style,
- f.onceness, f.decl, None, &f.bounds,
- Some(&generics), None));
+ try!(self.print_ty_fn(None,
+ Some('~'),
+ &None,
+ f.fn_style,
+ f.onceness,
+ f.decl,
+ None,
+ &f.bounds,
+ Some(&generics),
+ None,
+ false));
+ }
+ ast::TyUnboxedFn(f) => {
+ try!(self.print_ty_fn(None,
+ None,
+ &None,
+ ast::NormalFn,
+ ast::Many,
+ f.decl,
+ None,
+ &None,
+ None,
+ None,
+ true));
}
ast::TyPath(ref path, ref bounds, _) => {
try!(self.print_bounded_path(path, bounds));
Some(m.ident),
&None,
Some(&m.generics),
- Some(m.explicit_self.node)));
+ Some(m.explicit_self.node),
+ false));
word(&mut self.s, ";")
}
try!(match *bound {
TraitTyParamBound(ref tref) => self.print_trait_ref(tref),
StaticRegionTyParamBound => word(&mut self.s, "'static"),
+ UnboxedFnTyParamBound(ref unboxed_function_type) => {
+ self.print_ty_fn(None,
+ None,
+ &None,
+ ast::NormalFn,
+ ast::Many,
+ unboxed_function_type.decl,
+ None,
+ &None,
+ None,
+ None,
+ true)
+ }
OtherRegionTyParamBound(_) => Ok(())
})
}
id: Option<ast::Ident>,
opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
generics: Option<&ast::Generics>,
- opt_explicit_self: Option<ast::ExplicitSelf_>)
- -> IoResult<()> {
+ opt_explicit_self: Option<ast::ExplicitSelf_>,
+ is_unboxed: bool)
+ -> IoResult<()> {
try!(self.ibox(indent_unit));
// Duplicates the logic in `print_fn_header_info()`. This is because that
try!(self.print_fn_style(fn_style));
try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
try!(self.print_onceness(onceness));
- try!(word(&mut self.s, "fn"));
+ if !is_unboxed {
+ try!(word(&mut self.s, "fn"));
+ }
}
match id {
match generics { Some(g) => try!(self.print_generics(g)), _ => () }
try!(zerobreak(&mut self.s));
- if opt_sigil == Some('&') {
+ if is_unboxed || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
try!(self.popen());
}
+ if is_unboxed {
+ try!(word(&mut self.s, "&mut"));
+ try!(self.word_space(":"));
+ }
+
try!(self.print_fn_args(decl, opt_explicit_self));
- if opt_sigil == Some('&') {
+ if is_unboxed || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
if decl.variadic {
}
/// Each method of the Visitor trait is a hook to be potentially
-/// overriden. Each method's default implementation recursively visits
+/// overridden. Each method's default implementation recursively visits
/// the substructure of the input via the corresponding `walk` method;
/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
///
walk_lifetime_decls(visitor, &function_declaration.lifetimes,
env.clone());
}
+ TyUnboxedFn(ref function_declaration) => {
+ for argument in function_declaration.decl.inputs.iter() {
+ visitor.visit_ty(argument.ty, env.clone())
+ }
+ visitor.visit_ty(function_declaration.decl.output, env.clone());
+ }
TyPath(ref path, ref bounds, id) => {
visitor.visit_path(path, id, env.clone());
for bounds in bounds.iter() {
walk_trait_ref_helper(visitor, typ, env.clone())
}
StaticRegionTyParamBound => {}
+ UnboxedFnTyParamBound(ref function_declaration) => {
+ for argument in function_declaration.decl.inputs.iter() {
+ visitor.visit_ty(argument.ty, env.clone())
+ }
+ visitor.visit_ty(function_declaration.decl.output,
+ env.clone());
+ }
OtherRegionTyParamBound(..) => {}
}
}
Some(dir) => dirs_to_search.push(Path::new(dir)),
None => {
if homedir.is_some() {
- // ncurses compatability;
+ // ncurses compatibility;
dirs_to_search.push(homedir.unwrap().join(".terminfo"))
}
match getenv("TERMINFO_DIRS") {
tests)
}
+pub enum ColorConfig {
+ AutoColor,
+ AlwaysColor,
+ NeverColor,
+}
+
pub struct TestOpts {
pub filter: Option<Regex>,
pub run_ignored: bool,
pub test_shard: Option<(uint,uint)>,
pub logfile: Option<Path>,
pub nocapture: bool,
+ pub color: ColorConfig,
}
impl TestOpts {
test_shard: None,
logfile: None,
nocapture: false,
+ color: AutoColor,
}
}
}
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) {
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,
test_shard: test_shard,
logfile: logfile,
nocapture: nocapture,
+ color: color,
};
Some(Ok(test_opts))
Ok(ConsoleTestState {
out: out,
log_out: log_out,
- use_color: use_color(),
+ use_color: use_color(opts),
total: 0u,
passed: 0u,
failed: 0u,
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)]
/// Parse a hex string and interpret as a UUID
///
/// Accepted formats are a sequence of 32 hexadecimal characters,
- /// with or without hypens (grouped as 8, 4, 4, 4, 12).
+ /// with or without hyphens (grouped as 8, 4, 4, 4, 12).
fn from_str(us: &str) -> Option<Uuid> {
let result = Uuid::parse_string(us);
match result {
// FIXME #9845: Test these more thoroughly
impl<T: Encoder<E>, E> Encodable<T, E> for Uuid {
- /// Encode a UUID as a hypenated string
+ /// Encode a UUID as a hyphenated string
fn encode(&self, e: &mut T) -> Result<(), E> {
e.emit_str(self.to_hyphenated_str().as_slice())
}
// 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(); }
--- /dev/null
+// 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() {}
+
pub type typ = *UsedStruct4;
pub struct PubStruct();
struct PrivStruct; //~ ERROR: code is never used
-struct UsedStruct1 { x: int }
+struct UsedStruct1 {
+ #[allow(dead_code)]
+ x: int
+}
struct UsedStruct2(int);
struct UsedStruct3;
struct UsedStruct4;
struct StructUsedInEnum;
struct StructUsedInGeneric;
pub struct PubStruct2 {
+ #[allow(dead_code)]
struct_used_as_field: *StructUsedAsField
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(struct_variant)]
+#![allow(unused_variable)]
+#![allow(non_camel_case_types)]
+#![deny(dead_code)]
+
+extern crate libc;
+
+use std::num;
+
+struct Foo {
+ x: uint,
+ b: bool, //~ ERROR: code is never used
+ marker: std::kinds::marker::NoCopy
+}
+
+fn field_read(f: Foo) -> uint {
+ num::pow(f.x, 2)
+}
+
+enum XYZ {
+ X,
+ Y {
+ a: String,
+ b: int //~ ERROR: code is never used
+ },
+ Z
+}
+
+fn field_match_in_patterns(b: XYZ) -> String {
+ match b {
+ Y { a: a, .. } => a,
+ _ => "".to_string()
+ }
+}
+
+struct Bar {
+ x: uint, //~ ERROR: code is never used
+ b: bool,
+ _guard: ()
+}
+
+#[repr(C)]
+struct Baz {
+ x: libc::c_uint
+}
+
+fn field_match_in_let(f: Bar) -> bool {
+ let Bar { b, .. } = f;
+ b
+}
+
+fn main() {
+ field_read(Foo { x: 1, b: false, marker: std::kinds::marker::NoCopy });
+ field_match_in_patterns(Z);
+ field_match_in_let(Bar { x: 42u, b: true, _guard: () });
+ let _ = Baz { x: 0 };
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![feature(managed_boxes)]
#![forbid(managed_heap_memory)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![forbid(owned_heap_memory)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
#![deny(uppercase_variables)]
use std::io::File;
// 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() {
--- /dev/null
+
+// 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.
+
+#![feature(unboxed_closure_sugar)]
+
+use std::ops::FnMut;
+
+struct S;
+
+impl FnMut<(int,),int> for S {
+ fn call_mut(&mut self, (x,): (int,)) -> int {
+ x * x
+ }
+}
+
+fn call_it<F:|int|->int>(mut f: F, x: int) -> int {
+ f.call_mut((x,)) + 3
+}
+
+fn call_box(f: &mut |&mut: int|->int, x: int) -> int {
+ f.call_mut((x,)) + 3
+}
+
+fn main() {
+ let x = call_it(S, 1);
+ let y = call_box(&mut S, 1);
+ assert!(x == 4);
+ assert!(y == 4);
+}
+
--- /dev/null
+// 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.
+
+static TEST_STR: &'static str = "abcd";
+
+fn main() {
+ let s = "abcd";
+ match s {
+ TEST_STR => (),
+ _ => unreachable!()
+ }
+}
// 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";