diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index 3fbcbc2f47136..3cbe5d6026774 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -183,8 +183,62 @@ pub fn uncompress(src: &[u8]) -> Option> { } ``` -For reference, the examples used here are also available as a [library on -GitHub](https://github.com/thestinger/rust-snappy). +Then, we can add some tests to show how to use them. + +```rust +# #![feature(libc)] +# extern crate libc; +# use libc::{c_int, size_t}; +# unsafe fn snappy_compress(input: *const u8, +# input_length: size_t, +# compressed: *mut u8, +# compressed_length: *mut size_t) +# -> c_int { 0 } +# unsafe fn snappy_uncompress(compressed: *const u8, +# compressed_length: size_t, +# uncompressed: *mut u8, +# uncompressed_length: *mut size_t) +# -> c_int { 0 } +# unsafe fn snappy_max_compressed_length(source_length: size_t) -> size_t { 0 } +# unsafe fn snappy_uncompressed_length(compressed: *const u8, +# compressed_length: size_t, +# result: *mut size_t) +# -> c_int { 0 } +# unsafe fn snappy_validate_compressed_buffer(compressed: *const u8, +# compressed_length: size_t) +# -> c_int { 0 } +# fn main() { } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn valid() { + let d = vec![0xde, 0xad, 0xd0, 0x0d]; + let c: &[u8] = &compress(&d); + assert!(validate_compressed_buffer(c)); + assert!(uncompress(c) == Some(d)); + } + + #[test] + fn invalid() { + let d = vec![0, 0, 0, 0]; + assert!(!validate_compressed_buffer(&d)); + assert!(uncompress(&d).is_none()); + } + + #[test] + fn empty() { + let d = vec![]; + assert!(!validate_compressed_buffer(&d)); + assert!(uncompress(&d).is_none()); + let c = compress(&d); + assert!(validate_compressed_buffer(&c)); + assert!(uncompress(&c) == Some(d)); + } +} +``` # Destructors diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 729d9218a2960..e762e4d8ce9a2 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -12,23 +12,11 @@ //! Threadsafe reference-counted boxes (the `Arc` type). //! -//! The `Arc` type provides shared ownership of an immutable value. -//! Destruction is deterministic, and will occur as soon as the last owner is -//! gone. It is marked as `Send` because it uses atomic reference counting. -//! -//! If you do not need thread-safety, and just need shared ownership, consider -//! the [`Rc` type](../rc/struct.Rc.html). It is the same as `Arc`, but -//! does not use atomics, making it both thread-unsafe as well as significantly -//! faster when updating the reference count. -//! -//! The `downgrade` method can be used to create a non-owning `Weak` pointer -//! to the box. A `Weak` pointer can be upgraded to an `Arc` pointer, but -//! will return `None` if the value has already been dropped. -//! -//! For example, a tree with parent pointers can be represented by putting the -//! nodes behind strong `Arc` pointers, and then storing the parent pointers -//! as `Weak` pointers. +//! The `Arc` type provides shared ownership of an immutable value through +//! atomic reference counting. //! +//! `Weak` is a weak reference to the `Arc` box, and it is created by +//! the `downgrade` method. //! # Examples //! //! Sharing some immutable data between threads: @@ -47,27 +35,6 @@ //! }); //! } //! ``` -//! -//! Sharing mutable data safely between threads with a `Mutex`: -//! -//! ```no_run -//! use std::sync::{Arc, Mutex}; -//! use std::thread; -//! -//! let five = Arc::new(Mutex::new(5)); -//! -//! for _ in 0..10 { -//! let five = five.clone(); -//! -//! thread::spawn(move || { -//! let mut number = five.lock().unwrap(); -//! -//! *number += 1; -//! -//! println!("{}", *number); // prints 6 -//! }); -//! } -//! ``` use boxed::Box; @@ -92,15 +59,19 @@ use heap::deallocate; const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// An atomically reference counted wrapper for shared state. +/// Destruction is deterministic, and will occur as soon as the last owner is +/// gone. It is marked as `Send` because it uses atomic reference counting. /// -/// # Examples +/// If you do not need thread-safety, and just need shared ownership, consider +/// the [`Rc` type](../rc/struct.Rc.html). It is the same as `Arc`, but +/// does not use atomics, making it both thread-unsafe as well as significantly +/// faster when updating the reference count. /// -/// In this example, a large vector is shared between several threads. -/// With simple pipes, without `Arc`, a copy would have to be made for each -/// thread. +/// # Examples /// -/// When you clone an `Arc`, it will create another pointer to the data and -/// increase the reference counter. +/// In this example, a large vector of data will be shared by several threads. First we +/// wrap it with a `Arc::new` and then clone the `Arc` reference for every thread (which will +/// increase the reference count atomically). /// /// ``` /// use std::sync::Arc; @@ -111,6 +82,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// let shared_numbers = Arc::new(numbers); /// /// for _ in 0..10 { +/// // prepare a copy of reference here and it will be moved to the thread /// let child_numbers = shared_numbers.clone(); /// /// thread::spawn(move || { @@ -121,6 +93,29 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// } /// } /// ``` +/// You can also share mutable data between threads safely +/// by putting it inside `Mutex` and then share `Mutex` immutably +/// with `Arc` as shown below. +/// +/// ``` +/// use std::sync::{Arc, Mutex}; +/// use std::thread; +/// +/// let five = Arc::new(Mutex::new(5)); +/// +/// for _ in 0..10 { +/// let five = five.clone(); +/// +/// thread::spawn(move || { +/// let mut number = five.lock().unwrap(); +/// +/// *number += 1; +/// +/// println!("{}", *number); // prints 6 +/// }); +/// } +/// ``` + #[unsafe_no_drop_flag] #[stable(feature = "rust1", since = "1.0.0")] pub struct Arc { @@ -139,6 +134,14 @@ impl, U: ?Sized> CoerceUnsized> for Arc {} /// /// Weak pointers will not keep the data inside of the `Arc` alive, and can be /// used to break cycles between `Arc` pointers. +/// +/// A `Weak` pointer can be upgraded to an `Arc` pointer, but +/// will return `None` if the value has already been dropped. +/// +/// For example, a tree with parent pointers can be represented by putting the +/// nodes behind strong `Arc` pointers, and then storing the parent pointers +/// as `Weak` pointers. + #[unsafe_no_drop_flag] #[stable(feature = "arc_weak", since = "1.4.0")] pub struct Weak { diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 9797113b8ad66..da56b21cf0c05 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1603,6 +1603,12 @@ impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { //////////////////////////////////////////////////////////////////////////////// /// An iterator that moves out of a vector. +/// +/// This `struct` is created by the `into_iter` method on [`Vec`][`Vec`] (provided +/// by the [`IntoIterator`] trait). +/// +/// [`Vec`]: struct.Vec.html +/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { _buf: RawVec, @@ -1710,6 +1716,11 @@ impl Drop for IntoIter { } /// A draining iterator for `Vec`. +/// +/// This `struct` is created by the [`drain`] method on [`Vec`]. +/// +/// [`drain`]: struct.Vec.html#method.drain +/// [`Vec`]: struct.Vec.html #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { /// Index of tail to preserve diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 376d2792c445c..43868d124a22e 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -238,6 +238,8 @@ macro_rules! write { } /// Use the `format!` syntax to write data into a buffer, appending a newline. +/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) +/// alone (no additional CARRIAGE RETURN (`\r`/`U+000D`). /// /// This macro is typically used with a buffer of `&mut `[`Write`][write]. /// diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7dd9ecedb56c8..fcdbde0d19f4f 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2308,26 +2308,45 @@ impl usize { /// /// [`f32::classify()`]: ../../std/primitive.f32.html#method.classify /// [`f64::classify()`]: ../../std/primitive.f64.html#method.classify +/// +/// # Examples +/// +/// ``` +/// use std::num::FpCategory; +/// use std::f32; +/// +/// let num = 12.4_f32; +/// let inf = f32::INFINITY; +/// let zero = 0f32; +/// let sub: f32 = 0.000000000000000000000000000000000000011754942; +/// let nan = f32::NAN; +/// +/// assert_eq!(num.classify(), FpCategory::Normal); +/// assert_eq!(inf.classify(), FpCategory::Infinite); +/// assert_eq!(zero.classify(), FpCategory::Zero); +/// assert_eq!(nan.classify(), FpCategory::Nan); +/// assert_eq!(sub.classify(), FpCategory::Subnormal); +/// ``` #[derive(Copy, Clone, PartialEq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum FpCategory { - /// "Not a Number", often obtained by dividing by zero + /// "Not a Number", often obtained by dividing by zero. #[stable(feature = "rust1", since = "1.0.0")] Nan, - /// Positive or negative infinity + /// Positive or negative infinity. #[stable(feature = "rust1", since = "1.0.0")] Infinite , - /// Positive or negative zero + /// Positive or negative zero. #[stable(feature = "rust1", since = "1.0.0")] Zero, - /// De-normalized floating point representation (less precise than `Normal`) + /// De-normalized floating point representation (less precise than `Normal`). #[stable(feature = "rust1", since = "1.0.0")] Subnormal, - /// A regular floating point number + /// A regular floating point number. #[stable(feature = "rust1", since = "1.0.0")] Normal, } diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 8df68da3786e2..3c46072e17e1a 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -57,6 +57,7 @@ #![allow(private_no_mangle_fns)] use core::any::Any; +use core::ptr; use alloc::boxed::Box; use unwind as uw; @@ -88,7 +89,7 @@ pub unsafe fn panic(data: Box) -> u32 { } pub fn payload() -> *mut u8 { - 0 as *mut u8 + ptr::null_mut() } pub unsafe fn cleanup(ptr: *mut u8) -> Box { diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 12e1a764c5f94..56801e8cb6bcf 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -18,6 +18,7 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; +use core::ptr; use dwarf::eh; use windows as c; @@ -50,7 +51,7 @@ pub unsafe fn panic(data: Box) -> u32 { } pub fn payload() -> *mut u8 { - 0 as *mut u8 + ptr::null_mut() } pub unsafe fn cleanup(ptr: *mut u8) -> Box { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index ee3eeefc124a5..70d142e50edb9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -96,6 +96,7 @@ use libc::c_uint; use std::ffi::{CStr, CString}; use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; +use std::ptr; use std::rc::Rc; use std::str; use std::{i8, i16, i32, i64}; @@ -2201,7 +2202,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { start_fn, args.as_ptr(), args.len() as c_uint, - 0 as *mut _, + ptr::null_mut(), noname()); llvm::LLVMBuildRet(bld, result); diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index d415698660000..e88257dcd4cf8 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { check_call("invoke", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(0 as *mut _); + let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); unsafe { llvm::LLVMRustBuildInvoke(self.llbuilder, @@ -859,7 +859,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { check_call("call", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(0 as *mut _); + let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); unsafe { llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(), @@ -961,7 +961,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.count_insn("trap"); llvm::LLVMRustBuildCall(self.llbuilder, t, args.as_ptr(), args.len() as c_uint, - 0 as *mut _, + ptr::null_mut(), noname()); } } @@ -1000,7 +1000,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { parent: Option, args: &[ValueRef]) -> ValueRef { self.count_insn("cleanuppad"); - let parent = parent.unwrap_or(0 as *mut _); + let parent = parent.unwrap_or(ptr::null_mut()); let name = CString::new("cleanuppad").unwrap(); let ret = unsafe { llvm::LLVMRustBuildCleanupPad(self.llbuilder, @@ -1016,7 +1016,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn cleanup_ret(&self, cleanup: ValueRef, unwind: Option) -> ValueRef { self.count_insn("cleanupret"); - let unwind = unwind.unwrap_or(0 as *mut _); + let unwind = unwind.unwrap_or(ptr::null_mut()); let ret = unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind) }; @@ -1052,8 +1052,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unwind: Option, num_handlers: usize) -> ValueRef { self.count_insn("catchswitch"); - let parent = parent.unwrap_or(0 as *mut _); - let unwind = unwind.unwrap_or(0 as *mut _); + let parent = parent.unwrap_or(ptr::null_mut()); + let unwind = unwind.unwrap_or(ptr::null_mut()); let name = CString::new("catchswitch").unwrap(); let ret = unsafe { llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 26cf8a3199d1b..6f0f6ecab5ba8 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -98,7 +98,9 @@ macro_rules! print { ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); } -/// Macro for printing to the standard output, with a newline. +/// Macro for printing to the standard output, with a newline. On all +/// platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone +/// (no additional CARRIAGE RETURN (`\r`/`U+000D`). /// /// Use the `format!` syntax to write data to the standard output. /// See `std::fmt` for more information. diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 16bc81de78ecf..660c098d30bc2 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -605,6 +605,23 @@ pub struct ExitStatus(imp::ExitStatus); impl ExitStatus { /// Was termination successful? Signal termination not considered a success, /// and success is defined as a zero exit status. + /// + /// # Examples + /// + /// ```rust,no_run + /// use std::process::Command; + /// + /// let status = Command::new("mkdir") + /// .arg("projects") + /// .status() + /// .expect("failed to execute mkdir"); + /// + /// if status.success() { + /// println!("'projects/' directory created"); + /// } else { + /// println!("failed to create 'projects/' directory"); + /// } + /// ``` #[stable(feature = "process", since = "1.0.0")] pub fn success(&self) -> bool { self.0.success() diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e9ea465cc9993..54c1fe6c5640c 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -65,6 +65,7 @@ // it! use marker; +use ptr; use sync::atomic::{AtomicUsize, AtomicBool, Ordering}; use thread::{self, Thread}; @@ -297,7 +298,7 @@ impl Once { let mut node = Waiter { thread: Some(thread::current()), signaled: AtomicBool::new(false), - next: 0 as *mut Waiter, + next: ptr::null_mut(), }; let me = &mut node as *mut Waiter as usize; assert!(me & STATE_MASK == 0); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 34b36b854f495..63e13f0bb4738 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -236,11 +236,11 @@ pub fn current_exe() -> io::Result { libc::KERN_PROC_ARGV]; let mib = mib.as_mut_ptr(); let mut argv_len = 0; - cvt(libc::sysctl(mib, 4, 0 as *mut _, &mut argv_len, - 0 as *mut _, 0))?; + cvt(libc::sysctl(mib, 4, ptr::null_mut(), &mut argv_len, + ptr::null_mut(), 0))?; let mut argv = Vec::<*const libc::c_char>::with_capacity(argv_len as usize); cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, - &mut argv_len, 0 as *mut _, 0))?; + &mut argv_len, ptr::null_mut(), 0))?; argv.set_len(argv_len as usize); if argv[0].is_null() { return Err(io::Error::new(io::ErrorKind::Other, diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 2dde9c0e615f2..010594133387a 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -14,6 +14,7 @@ use cmp; use io; use libc::{self, c_int}; use mem; +use ptr; use sys::cvt_r; use sys::fd::FileDesc; @@ -92,8 +93,8 @@ pub fn read2(p1: AnonPipe, let mut read: libc::fd_set = mem::zeroed(); libc::FD_SET(p1.raw(), &mut read); libc::FD_SET(p2.raw(), &mut read); - libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _, - 0 as *mut _) + libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(), + ptr::null_mut()) })?; // Read as much as we can from each pipe, ignoring EWOULDBLOCK or diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index 98cfdcdf11041..d68867fb3d2ce 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -96,7 +96,7 @@ impl Command { let mut saw_nul = false; let program = os2c(program, &mut saw_nul); Command { - argv: vec![program.as_ptr(), 0 as *const _], + argv: vec![program.as_ptr(), ptr::null()], program: program, args: Vec::new(), env: None, @@ -117,7 +117,7 @@ impl Command { // pointer. let arg = os2c(arg, &mut self.saw_nul); self.argv[self.args.len() + 1] = arg.as_ptr(); - self.argv.push(0 as *const _); + self.argv.push(ptr::null()); // Also make sure we keep track of the owned value to schedule a // destructor for this memory. @@ -134,7 +134,7 @@ impl Command { envp.push(s.as_ptr()); map.insert(k, (envp.len() - 1, s)); } - envp.push(0 as *const _); + envp.push(ptr::null()); self.env = Some(map); self.envp = Some(envp); } @@ -158,7 +158,7 @@ impl Command { Entry::Vacant(e) => { let len = envp.len(); envp[len - 1] = new_key.as_ptr(); - envp.push(0 as *const _); + envp.push(ptr::null()); e.insert((len - 1, new_key)); } } @@ -183,7 +183,7 @@ impl Command { pub fn env_clear(&mut self) { self.env = Some(HashMap::new()); - self.envp = Some(vec![0 as *const _]); + self.envp = Some(vec![ptr::null()]); } pub fn cwd(&mut self, dir: &OsStr) { diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index 68eebba9e7b90..a08cec38f732d 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -9,8 +9,8 @@ // except according to those terms. use cmp::Ordering; -use time::Duration; use libc; +use time::Duration; pub use self::inner::{Instant, SystemTime, UNIX_EPOCH}; @@ -164,12 +164,14 @@ mod inner { impl SystemTime { pub fn now() -> SystemTime { + use ptr; + let mut s = libc::timeval { tv_sec: 0, tv_usec: 0, }; cvt(unsafe { - libc::gettimeofday(&mut s, 0 as *mut _) + libc::gettimeofday(&mut s, ptr::null_mut()) }).unwrap(); return SystemTime::from(s) } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 74546bb893bea..d10abae286527 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -46,10 +46,10 @@ impl Handle { pub fn new_event(manual: bool, init: bool) -> io::Result { unsafe { - let event = c::CreateEventW(0 as *mut _, + let event = c::CreateEventW(ptr::null_mut(), manual as c::BOOL, init as c::BOOL, - 0 as *const _); + ptr::null()); if event.is_null() { Err(io::Error::last_os_error()) } else { diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 8631a63d653a3..6e9c67051a6eb 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -12,9 +12,10 @@ use prelude::v1::*; use os::windows::prelude::*; use ffi::OsStr; -use path::Path; use io; use mem; +use path::Path; +use ptr; use rand::{self, Rng}; use slice; use sys::c; @@ -66,7 +67,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { 4096, 4096, 0, - 0 as *mut _); + ptr::null_mut()); // We pass the FILE_FLAG_FIRST_PIPE_INSTANCE flag above, and we're // also just doing a best effort at selecting a unique name. If diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index c90c93e75acd8..248f6f98650a5 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -959,6 +959,8 @@ fn get_concurrency() -> usize { target_os = "bitrig", target_os = "netbsd"))] fn num_cpus() -> usize { + use std::ptr; + let mut cpus: libc::c_uint = 0; let mut cpus_size = std::mem::size_of_val(&cpus); @@ -972,7 +974,7 @@ fn get_concurrency() -> usize { 2, &mut cpus as *mut _ as *mut _, &mut cpus_size as *mut _ as *mut _, - 0 as *mut _, + ptr::null_mut(), 0); } if cpus < 1 { @@ -984,6 +986,8 @@ fn get_concurrency() -> usize { #[cfg(target_os = "openbsd")] fn num_cpus() -> usize { + use std::ptr; + let mut cpus: libc::c_uint = 0; let mut cpus_size = std::mem::size_of_val(&cpus); let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0]; @@ -993,7 +997,7 @@ fn get_concurrency() -> usize { 2, &mut cpus as *mut _ as *mut _, &mut cpus_size as *mut _ as *mut _, - 0 as *mut _, + ptr::null_mut(), 0); } if cpus < 1 {