auto merge of #15949 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2014-07-24 16:11:23 +00:00
commit 4461f03a36
51 changed files with 929 additions and 374 deletions

View File

@ -3864,13 +3864,13 @@ Function parameters are immutable unless declared with `mut`. The
and `fn f(mut x: Box<int>, y: Box<int>)` declare one mutable variable `x` and
one immutable variable `y`).
Methods that take either `self` or `~self` can optionally place them in a
Methods that take either `self` or `Box<Self>` can optionally place them in a
mutable slot by prefixing them with `mut` (similar to regular arguments):
~~~
trait Changer {
fn change(mut self) -> Self;
fn modify(mut ~self) -> Box<Self>;
fn modify(mut self: Box<Self>) -> Box<Self>;
}
~~~

View File

@ -1971,7 +1971,7 @@ like any other function, except for the name `self`.
The type of `self` is the type on which the method is implemented,
or a pointer thereof. As an argument it is written either `self`,
`&self`, or `~self`.
`&self`, or `self: TYPE`.
A caller must in turn have a compatible pointer type to call the method.
~~~
@ -1984,7 +1984,7 @@ A caller must in turn have a compatible pointer type to call the method.
# }
impl Shape {
fn draw_reference(&self) { /* ... */ }
fn draw_owned(~self) { /* ... */ }
fn draw_owned(self: Box<Shape>) { /* ... */ }
fn draw_value(self) { /* ... */ }
}
@ -2009,7 +2009,7 @@ to a reference.
# }
# impl Shape {
# fn draw_reference(&self) { /* ... */ }
# fn draw_owned(~self) { /* ... */ }
# fn draw_owned(self: Box<Shape>) { /* ... */ }
# fn draw_value(self) { /* ... */ }
# }
# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);

View File

@ -71,7 +71,7 @@ pub mod bench {
// measure
let mut i = 0;
b.iter(|| {
map.find(keys.get(i));
map.find(&keys[i]);
i = (i + 1) % n;
})
}

View File

@ -8,10 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
* A simple map based on a vector for small integer keys. Space requirements
* are O(highest integer key).
*/
//! A simple map based on a vector for small integer keys. Space requirements
//! are O(highest integer key).
#![allow(missing_doc)]
@ -26,18 +24,50 @@ use {Collection, Mutable, Map, MutableMap, MutableSeq};
use {vec, slice};
use vec::Vec;
#[allow(missing_doc)]
/// A map optimized for small integer keys.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
///
/// let mut months = SmallIntMap::new();
/// months.insert(1, "Jan");
/// months.insert(2, "Feb");
/// months.insert(3, "Mar");
///
/// if !months.contains_key(&12) {
/// println!("The end is near!");
/// }
///
/// assert_eq!(months.find(&1), Some(&"Jan"));
///
/// match months.find_mut(&3) {
/// Some(value) => *value = "Venus",
/// None => (),
/// }
///
/// assert_eq!(months.find(&3), Some(&"Venus"));
///
/// // Print out all months
/// for (key, value) in months.iter() {
/// println!("month {} is {}", key, value);
/// }
///
/// months.clear();
/// assert!(months.is_empty());
/// ```
pub struct SmallIntMap<T> {
v: Vec<Option<T>>,
}
impl<V> Collection for SmallIntMap<V> {
/// Return the number of elements in the map
/// Return the number of elements in the map.
fn len(&self) -> uint {
self.v.iter().filter(|elt| elt.is_some()).count()
}
/// Return true if there are no elements in the map
/// Return `true` if there are no elements in the map.
fn is_empty(&self) -> bool {
self.v.iter().all(|elt| elt.is_none())
}
@ -49,7 +79,7 @@ impl<V> Mutable for SmallIntMap<V> {
}
impl<V> Map<uint, V> for SmallIntMap<V> {
/// Return a reference to the value corresponding to the key
/// Return a reference to the value corresponding to the key.
fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
if *key < self.v.len() {
match *self.v.get(*key) {
@ -63,7 +93,7 @@ impl<V> Map<uint, V> for SmallIntMap<V> {
}
impl<V> MutableMap<uint, V> for SmallIntMap<V> {
/// Return a mutable reference to the value corresponding to the key
/// Return a mutable reference to the value corresponding to the key.
fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> {
if *key < self.v.len() {
match *self.v.get_mut(*key) {
@ -76,7 +106,7 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
}
/// Insert a key-value pair into the map. An existing value for a
/// key is replaced by the new value. Return true if the key did
/// key is replaced by the new value. Return `true` if the key did
/// not already exist in the map.
fn insert(&mut self, key: uint, value: V) -> bool {
let exists = self.contains_key(&key);
@ -88,14 +118,14 @@ impl<V> MutableMap<uint, V> for SmallIntMap<V> {
!exists
}
/// Remove a key-value pair from the map. Return true if the key
/// was present in the map, otherwise false.
/// Remove a key-value pair from the map. Return `true` if the key
/// was present in the map, otherwise `false`.
fn remove(&mut self, key: &uint) -> bool {
self.pop(key).is_some()
}
/// Insert a key-value pair from the map. If the key already had a value
/// present in the map, that value is returned. Otherwise None is returned.
/// present in the map, that value is returned. Otherwise `None` is returned.
fn swap(&mut self, key: uint, value: V) -> Option<V> {
match self.find_mut(&key) {
Some(loc) => { return Some(replace(loc, value)); }
@ -121,20 +151,67 @@ impl<V> Default for SmallIntMap<V> {
}
impl<V> SmallIntMap<V> {
/// Create an empty SmallIntMap
/// Create an empty SmallIntMap.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
/// let mut map: SmallIntMap<&str> = SmallIntMap::new();
/// ```
pub fn new() -> SmallIntMap<V> { SmallIntMap{v: vec!()} }
/// Create an empty SmallIntMap with capacity `capacity`
/// Create an empty SmallIntMap with space for at least `capacity` elements
/// before resizing.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
/// let mut map: SmallIntMap<&str> = SmallIntMap::with_capacity(10);
/// ```
pub fn with_capacity(capacity: uint) -> SmallIntMap<V> {
SmallIntMap { v: Vec::with_capacity(capacity) }
}
/// Retrieves a value for the given key.
/// See [`find`](../trait.Map.html#tymethod.find) for a non-failing alternative.
///
/// # Failure
///
/// Fails if the key is not present.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
///
/// let mut map = SmallIntMap::new();
/// map.insert(1, "a");
/// assert_eq!(map.get(&1), &"a");
/// ```
pub fn get<'a>(&'a self, key: &uint) -> &'a V {
self.find(key).expect("key not present")
}
/// An iterator visiting all key-value pairs in ascending order by the keys.
/// Iterator element type is (uint, &'r V)
/// Iterator element type is `(uint, &'r V)`.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
///
/// let mut map = SmallIntMap::new();
/// map.insert(1, "a");
/// map.insert(3, "c");
/// map.insert(2, "b");
///
/// // Print `1: a` then `2: b` then `3: c`
/// for (key, value) in map.iter() {
/// println!("{}: {}", key, value);
/// }
/// ```
pub fn iter<'r>(&'r self) -> Entries<'r, V> {
Entries {
front: 0,
@ -145,7 +222,26 @@ impl<V> SmallIntMap<V> {
/// An iterator visiting all key-value pairs in ascending order by the keys,
/// with mutable references to the values
/// Iterator element type is (uint, &'r mut V)
/// Iterator element type is `(uint, &'r mut V)`.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
///
/// let mut map = SmallIntMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// map.insert(3, "c");
///
/// for (key, value) in map.mut_iter() {
/// *value = "x";
/// }
///
/// for (key, value) in map.iter() {
/// assert_eq!(value, &"x");
/// }
/// ```
pub fn mut_iter<'r>(&'r mut self) -> MutEntries<'r, V> {
MutEntries {
front: 0,
@ -154,7 +250,23 @@ impl<V> SmallIntMap<V> {
}
}
/// Empties the hash map, moving all values into the specified closure
/// Empties the hash map, moving all values into the specified closure.
///
/// # Example
///
/// ```
/// use std::collections::SmallIntMap;
///
/// let mut map = SmallIntMap::new();
/// map.insert(1, "a");
/// map.insert(3, "c");
/// map.insert(2, "b");
///
/// // Not possible with .iter()
/// let vec: Vec<(uint, &str)> = map.move_iter().collect();
///
/// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
/// ```
pub fn move_iter(&mut self)
-> FilterMap<(uint, Option<V>), (uint, V),
Enumerate<vec::MoveItems<Option<V>>>>
@ -249,6 +361,7 @@ macro_rules! double_ended_iterator {
}
}
/// Forward iterator over a map.
pub struct Entries<'a, T> {
front: uint,
back: uint,
@ -258,6 +371,8 @@ pub struct Entries<'a, T> {
iterator!(impl Entries -> (uint, &'a T), get_ref)
double_ended_iterator!(impl Entries -> (uint, &'a T), get_ref)
/// Forward iterator over the key-value pairs of a map, with the
/// values being mutable.
pub struct MutEntries<'a, T> {
front: uint,
back: uint,

View File

@ -555,10 +555,7 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
/// Unsafe operations
pub mod raw {
use core::prelude::*;
use core::mem;
use core::raw::Slice;
use string;
use string::String;
use vec::Vec;
@ -567,57 +564,28 @@ pub mod raw {
pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
pub use core::str::raw::{slice_unchecked};
/// Create a Rust string from a *u8 buffer of the given length
/// Deprecated. Replaced by `string::raw::from_buf_len`
#[deprecated = "Use string::raw::from_buf_len"]
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String {
let mut result = String::new();
result.push_bytes(mem::transmute(Slice {
data: buf,
len: len,
}));
result
string::raw::from_buf_len(buf, len)
}
/// Create a Rust string from a null-terminated C string
/// Deprecated. Use `string::raw::from_buf`
#[deprecated = "Use string::raw::from_buf"]
pub unsafe fn from_c_str(c_string: *const i8) -> String {
let mut buf = String::new();
let mut len = 0;
while *c_string.offset(len) != 0 {
len += 1;
}
buf.push_bytes(mem::transmute(Slice {
data: c_string,
len: len as uint,
}));
buf
string::raw::from_buf(c_string as *const u8)
}
/// Converts an owned vector of bytes to a new owned string. This assumes
/// that the utf-8-ness of the vector has already been validated
#[inline]
/// Deprecated. Replaced by `string::raw::from_utf8`
#[deprecated = "Use string::raw::from_utf8"]
pub unsafe fn from_utf8_owned(v: Vec<u8>) -> String {
mem::transmute(v)
string::raw::from_utf8(v)
}
/// Converts a byte to a string.
/// Deprecated. Use `string::raw::from_utf8`
#[deprecated = "Use string::raw::from_utf8"]
pub unsafe fn from_byte(u: u8) -> String {
from_utf8_owned(vec![u])
}
/// Sets the length of a string
///
/// This will explicitly set the size of the string, without actually
/// modifying its buffers, so it is up to the caller to ensure that
/// the string is actually the specified size.
#[test]
fn test_from_buf_len() {
use slice::ImmutableVector;
unsafe {
let a = vec![65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = a.as_ptr();
let c = from_buf_len(b, 3u);
assert_eq!(c, String::from_str("AAA"));
}
string::raw::from_utf8(vec![u])
}
}
@ -785,30 +753,6 @@ impl<'a> StrAllocating for &'a str {
}
}
/// Methods for owned strings
pub trait OwnedStr {
/// Consumes the string, returning the underlying byte buffer.
///
/// The buffer does not have a null terminator.
fn into_bytes(self) -> Vec<u8>;
/// Pushes the given string onto this string, returning the concatenation of the two strings.
fn append(self, rhs: &str) -> String;
}
impl OwnedStr for String {
#[inline]
fn into_bytes(self) -> Vec<u8> {
unsafe { mem::transmute(self) }
}
#[inline]
fn append(mut self, rhs: &str) -> String {
self.push_str(rhs);
self
}
}
#[cfg(test)]
mod tests {
use std::iter::AdditiveIterator;
@ -1377,16 +1321,6 @@ mod tests {
[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]);
}
#[test]
fn test_raw_from_c_str() {
unsafe {
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = raw::from_c_str(b);
assert_eq!(c, String::from_str("AAAAAAA"));
}
}
#[test]
fn test_as_bytes() {
// no null

View File

@ -49,14 +49,6 @@ impl String {
}
}
/// Creates a new string buffer from length, capacity, and a pointer.
#[inline]
pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
String {
vec: Vec::from_raw_parts(length, capacity, ptr),
}
}
/// Creates a new string buffer from the given string.
#[inline]
pub fn from_str(string: &str) -> String {
@ -65,6 +57,13 @@ impl String {
}
}
/// Deprecated. Replaced by `string::raw::from_parts`
#[inline]
#[deprecated = "Replaced by string::raw::from_parts"]
pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
raw::from_parts(ptr, length, capacity)
}
#[allow(missing_doc)]
#[deprecated = "obsoleted by the removal of ~str"]
#[inline]
@ -570,6 +569,62 @@ impl<S: Str> Add<S, String> for String {
}
}
pub mod raw {
use core::mem;
use core::ptr::RawPtr;
use core::raw::Slice;
use super::String;
use vec::Vec;
/// Creates a new `String` from length, capacity, and a pointer.
///
/// This is unsafe because:
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`
/// * We assume that the `Vec` contains valid UTF-8
#[inline]
pub unsafe fn from_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
vec: Vec::from_raw_parts(length, capacity, buf),
}
}
/// Create `String` from a *u8 buffer of the given length
///
/// This function is unsafe because of two reasons:
/// * A raw pointer is dereferenced and transmuted to `&[u8]`
/// * The slice is not checked to see whether it contains valid UTF-8
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String {
use slice::CloneableVector;
let slice: &[u8] = mem::transmute(Slice {
data: buf,
len: len,
});
self::from_utf8(slice.to_vec())
}
/// Create a `String` from a null-terminated *u8 buffer
///
/// This function is unsafe because we dereference memory until we find the NUL character,
/// which is not guaranteed to be present. Additionaly, the slice is not checked to see
/// whether it contains valid UTF-8
pub unsafe fn from_buf(buf: *const u8) -> String {
let mut len = 0;
while *buf.offset(len) != 0 {
len += 1;
}
self::from_buf_len(buf, len as uint)
}
/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the utf-8-ness of the vector has already been validated.
#[inline]
pub unsafe fn from_utf8(bytes: Vec<u8>) -> String {
String { vec: bytes }
}
}
#[cfg(test)]
mod tests {
use std::prelude::*;
@ -727,6 +782,24 @@ mod tests {
String::from_str("\uFFFD𐒋\uFFFD"));
}
#[test]
fn test_from_buf_len() {
unsafe {
let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
assert_eq!(super::raw::from_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
}
}
#[test]
fn test_from_buf() {
unsafe {
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = super::raw::from_buf(b);
assert_eq!(c, String::from_str("AAAAAAA"));
}
}
#[test]
fn test_push_bytes() {
let mut s = String::from_str("ABC");

View File

@ -8,7 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
//! Ordered containers with unsigned integer keys,
//! implemented as radix tries (`TrieSet` and `TrieMap` types).
use core::prelude::*;
@ -35,7 +36,44 @@ enum Child<T> {
Nothing
}
#[allow(missing_doc)]
/// A map implemented as a radix trie.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
///
/// let mut map = TrieMap::new();
/// map.insert(27, "Olaf");
/// map.insert(1, "Edgar");
/// map.insert(13, "Ruth");
/// map.insert(1, "Martin");
///
/// assert_eq!(map.len(), 3);
/// assert_eq!(map.find(&1), Some(&"Martin"));
///
/// if !map.contains_key(&90) {
/// println!("Nobody is keyed 90");
/// }
///
/// // Update a key
/// match map.find_mut(&1) {
/// Some(value) => *value = "Olga",
/// None => (),
/// }
///
/// map.remove(&13);
/// assert_eq!(map.len(), 2);
///
/// // Print the key value pairs, ordered by key.
/// for (key, value) in map.iter() {
/// // Prints `1: Olga` then `27: Olaf`
/// println!("{}: {}", key, value);
/// }
///
/// map.clear();
/// assert!(map.is_empty());
/// ```
pub struct TrieMap<T> {
root: TrieNode<T>,
length: uint
@ -51,7 +89,7 @@ impl<T: PartialEq> PartialEq for TrieMap<T> {
impl<T: Eq> Eq for TrieMap<T> {}
impl<T> Collection for TrieMap<T> {
/// Return the number of elements in the map
/// Return the number of elements in the map.
#[inline]
fn len(&self) -> uint { self.length }
}
@ -66,7 +104,7 @@ impl<T> Mutable for TrieMap<T> {
}
impl<T> Map<uint, T> for TrieMap<T> {
/// Return a reference to the value corresponding to the key
/// Return a reference to the value corresponding to the key.
#[inline]
fn find<'a>(&'a self, key: &uint) -> Option<&'a T> {
let mut node: &'a TrieNode<T> = &self.root;
@ -89,7 +127,7 @@ impl<T> Map<uint, T> for TrieMap<T> {
}
impl<T> MutableMap<uint, T> for TrieMap<T> {
/// Return a mutable reference to the value corresponding to the key
/// Return a mutable reference to the value corresponding to the key.
#[inline]
fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> {
find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1)
@ -122,19 +160,54 @@ impl<T> Default for TrieMap<T> {
}
impl<T> TrieMap<T> {
/// Create an empty TrieMap
/// Create an empty TrieMap.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let mut map: TrieMap<&str> = TrieMap::new();
/// ```
#[inline]
pub fn new() -> TrieMap<T> {
TrieMap{root: TrieNode::new(), length: 0}
}
/// Visit all key-value pairs in reverse order
/// Visit all key-value pairs in reverse order. Abort traversal when f returns false.
/// Return true if f returns true for all elements.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let map: TrieMap<&str> = [(1, "a"), (2, "b"), (3, "c")].iter().map(|&x| x).collect();
///
/// let mut vec = Vec::new();
/// assert_eq!(true, map.each_reverse(|&key, &value| { vec.push((key, value)); true }));
/// assert_eq!(vec, vec![(3, "c"), (2, "b"), (1, "a")]);
///
/// // Stop when we reach 2
/// let mut vec = Vec::new();
/// assert_eq!(false, map.each_reverse(|&key, &value| { vec.push(value); key != 2 }));
/// assert_eq!(vec, vec!["c", "b"]);
/// ```
#[inline]
pub fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool {
self.root.each_reverse(f)
}
/// Get an iterator over the key-value pairs in the map
/// Get an iterator over the key-value pairs in the map, ordered by keys.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let map: TrieMap<&str> = [(3, "c"), (1, "a"), (2, "b")].iter().map(|&x| x).collect();
///
/// for (key, value) in map.iter() {
/// println!("{}: {}", key, value);
/// }
/// ```
pub fn iter<'a>(&'a self) -> Entries<'a, T> {
let mut iter = unsafe {Entries::new()};
iter.stack[0] = self.root.children.iter();
@ -147,6 +220,21 @@ impl<T> TrieMap<T> {
/// Get an iterator over the key-value pairs in the map, with the
/// ability to mutate the values.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let mut map: TrieMap<int> = [(1, 2), (2, 4), (3, 6)].iter().map(|&x| x).collect();
///
/// for (key, value) in map.mut_iter() {
/// *value = -(key as int);
/// }
///
/// assert_eq!(map.find(&1), Some(&-1));
/// assert_eq!(map.find(&2), Some(&-2));
/// assert_eq!(map.find(&3), Some(&-3));
/// ```
pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, T> {
let mut iter = unsafe {MutEntries::new()};
iter.stack[0] = self.root.children.mut_iter();
@ -255,12 +343,34 @@ impl<T> TrieMap<T> {
/// Get an iterator pointing to the first key-value pair whose key is not less than `key`.
/// If all keys in the map are less than `key` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect();
///
/// assert_eq!(map.lower_bound(4).next(), Some((4, &"b")));
/// assert_eq!(map.lower_bound(5).next(), Some((6, &"c")));
/// assert_eq!(map.lower_bound(10).next(), None);
/// ```
pub fn lower_bound<'a>(&'a self, key: uint) -> Entries<'a, T> {
self.bound(key, false)
}
/// Get an iterator pointing to the first key-value pair whose key is greater than `key`.
/// If all keys in the map are not greater than `key` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect();
///
/// assert_eq!(map.upper_bound(4).next(), Some((6, &"c")));
/// assert_eq!(map.upper_bound(5).next(), Some((6, &"c")));
/// assert_eq!(map.upper_bound(10).next(), None);
/// ```
pub fn upper_bound<'a>(&'a self, key: uint) -> Entries<'a, T> {
self.bound(key, true)
}
@ -275,12 +385,50 @@ impl<T> TrieMap<T> {
/// Get an iterator pointing to the first key-value pair whose key is not less than `key`.
/// If all keys in the map are less than `key` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect();
///
/// assert_eq!(map.mut_lower_bound(4).next(), Some((4, &mut "b")));
/// assert_eq!(map.mut_lower_bound(5).next(), Some((6, &mut "c")));
/// assert_eq!(map.mut_lower_bound(10).next(), None);
///
/// for (key, value) in map.mut_lower_bound(4) {
/// *value = "changed";
/// }
///
/// assert_eq!(map.find(&2), Some(&"a"));
/// assert_eq!(map.find(&4), Some(&"changed"));
/// assert_eq!(map.find(&6), Some(&"changed"));
/// ```
pub fn mut_lower_bound<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> {
self.mut_bound(key, false)
}
/// Get an iterator pointing to the first key-value pair whose key is greater than `key`.
/// If all keys in the map are not greater than `key` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieMap;
/// let mut map: TrieMap<&str> = [(2, "a"), (4, "b"), (6, "c")].iter().map(|&x| x).collect();
///
/// assert_eq!(map.mut_upper_bound(4).next(), Some((6, &mut "c")));
/// assert_eq!(map.mut_upper_bound(5).next(), Some((6, &mut "c")));
/// assert_eq!(map.mut_upper_bound(10).next(), None);
///
/// for (key, value) in map.mut_upper_bound(4) {
/// *value = "changed";
/// }
///
/// assert_eq!(map.find(&2), Some(&"a"));
/// assert_eq!(map.find(&4), Some(&"b"));
/// assert_eq!(map.find(&6), Some(&"changed"));
/// ```
pub fn mut_upper_bound<'a>(&'a mut self, key: uint) -> MutEntries<'a, T> {
self.mut_bound(key, true)
}
@ -310,14 +458,42 @@ impl<S: Writer, T: Hash<S>> Hash<S> for TrieMap<T> {
}
}
#[allow(missing_doc)]
/// A set implemented as a radix trie.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let mut set = TrieSet::new();
/// set.insert(6);
/// set.insert(28);
/// set.insert(6);
///
/// assert_eq!(set.len(), 2);
///
/// if !set.contains(&3) {
/// println!("3 is not in the set");
/// }
///
/// // Print contents in order
/// for x in set.iter() {
/// println!("{}", x);
/// }
///
/// set.remove(&6);
/// assert_eq!(set.len(), 1);
///
/// set.clear();
/// assert!(set.is_empty());
/// ```
#[deriving(Hash, PartialEq, Eq)]
pub struct TrieSet {
map: TrieMap<()>
}
impl Collection for TrieSet {
/// Return the number of elements in the set
/// Return the number of elements in the set.
#[inline]
fn len(&self) -> uint { self.map.len() }
}
@ -368,19 +544,61 @@ impl Default for TrieSet {
}
impl TrieSet {
/// Create an empty TrieSet
/// Create an empty TrieSet.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
/// let mut set = TrieSet::new();
/// ```
#[inline]
pub fn new() -> TrieSet {
TrieSet{map: TrieMap::new()}
}
/// Visit all values in reverse order
/// Visit all values in reverse order. Abort traversal when `f` returns false.
/// Return `true` if `f` returns `true` for all elements.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let set: TrieSet = [1, 2, 3, 4, 5].iter().map(|&x| x).collect();
///
/// let mut vec = Vec::new();
/// assert_eq!(true, set.each_reverse(|&x| { vec.push(x); true }));
/// assert_eq!(vec, vec![5, 4, 3, 2, 1]);
///
/// // Stop when we reach 3
/// let mut vec = Vec::new();
/// assert_eq!(false, set.each_reverse(|&x| { vec.push(x); x != 3 }));
/// assert_eq!(vec, vec![5, 4, 3]);
/// ```
#[inline]
pub fn each_reverse(&self, f: |&uint| -> bool) -> bool {
self.map.each_reverse(|k, _| f(k))
}
/// Get an iterator over the values in the set
/// Get an iterator over the values in the set, in sorted order.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let mut set = TrieSet::new();
/// set.insert(3);
/// set.insert(2);
/// set.insert(1);
/// set.insert(2);
///
/// // Print 1, 2, 3
/// for x in set.iter() {
/// println!("{}", x);
/// }
/// ```
#[inline]
pub fn iter<'a>(&'a self) -> SetItems<'a> {
SetItems{iter: self.map.iter()}
@ -388,12 +606,34 @@ impl TrieSet {
/// Get an iterator pointing to the first value that is not less than `val`.
/// If all values in the set are less than `val` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect();
/// assert_eq!(set.lower_bound(4).next(), Some(4));
/// assert_eq!(set.lower_bound(5).next(), Some(6));
/// assert_eq!(set.lower_bound(10).next(), None);
/// ```
pub fn lower_bound<'a>(&'a self, val: uint) -> SetItems<'a> {
SetItems{iter: self.map.lower_bound(val)}
}
/// Get an iterator pointing to the first value that key is greater than `val`.
/// If all values in the set are not greater than `val` an empty iterator is returned.
/// If all values in the set are less than or equal to `val` an empty iterator is returned.
///
/// # Example
///
/// ```
/// use std::collections::TrieSet;
///
/// let set: TrieSet = [2, 4, 6, 8].iter().map(|&x| x).collect();
/// assert_eq!(set.upper_bound(4).next(), Some(6));
/// assert_eq!(set.upper_bound(5).next(), Some(6));
/// assert_eq!(set.upper_bound(10).next(), None);
/// ```
pub fn upper_bound<'a>(&'a self, val: uint) -> SetItems<'a> {
SetItems{iter: self.map.upper_bound(val)}
}
@ -526,7 +766,7 @@ fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
return ret;
}
/// Forward iterator over a map
/// Forward iterator over a map.
pub struct Entries<'a, T> {
stack: [slice::Items<'a, Child<T>>, .. NUM_CHUNKS],
length: uint,
@ -660,7 +900,7 @@ macro_rules! iterator_impl {
iterator_impl! { Entries, iter = iter, mutability = }
iterator_impl! { MutEntries, iter = mut_iter, mutability = mut }
/// Forward iterator over a set
/// Forward iterator over a set.
pub struct SetItems<'a> {
iter: Entries<'a, ()>
}

View File

@ -1217,6 +1217,14 @@ impl<T: CheckedAdd + CheckedSub + Zero + PartialOrd + Bounded> Saturating for T
/// Performs addition that returns `None` instead of wrapping around on overflow.
pub trait CheckedAdd: Add<Self, Self> {
/// Adds two numbers, checking for overflow. If overflow happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedAdd;
/// assert_eq!(5u16.checked_add(&65530), Some(65535));
/// assert_eq!(6u16.checked_add(&65530), None);
/// ```
fn checked_add(&self, v: &Self) -> Option<Self>;
}
@ -1270,6 +1278,14 @@ checked_impl!(CheckedAdd, checked_add, i64, intrinsics::i64_add_with_overflow)
/// Performs subtraction that returns `None` instead of wrapping around on underflow.
pub trait CheckedSub: Sub<Self, Self> {
/// Subtracts two numbers, checking for underflow. If underflow happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedSub;
/// assert_eq!((-127i8).checked_sub(&1), Some(-128));
/// assert_eq!((-128i8).checked_sub(&1), None);
/// ```
fn checked_sub(&self, v: &Self) -> Option<Self>;
}
@ -1298,6 +1314,14 @@ checked_impl!(CheckedSub, checked_sub, i64, intrinsics::i64_sub_with_overflow)
pub trait CheckedMul: Mul<Self, Self> {
/// Multiplies two numbers, checking for underflow or overflow. If underflow or overflow
/// happens, `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedMul;
/// assert_eq!(5u8.checked_mul(&51), Some(255));
/// assert_eq!(5u8.checked_mul(&52), None);
/// ```
fn checked_mul(&self, v: &Self) -> Option<Self>;
}
@ -1325,6 +1349,14 @@ checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow)
pub trait CheckedDiv: Div<Self, Self> {
/// Divides two numbers, checking for underflow or overflow. If underflow or overflow happens,
/// `None` is returned.
///
/// # Example
///
/// ```rust
/// use std::num::CheckedDiv;
/// assert_eq!((-127i8).checked_div(&-1), Some(127));
/// assert_eq!((-128i8).checked_div(&-1), None);
/// ```
fn checked_div(&self, v: &Self) -> Option<Self>;
}

View File

@ -769,3 +769,37 @@ pub trait FnOnce<Args,Result> {
fn call_once(self, args: Args) -> Result;
}
macro_rules! def_fn_mut(
($($args:ident)*) => (
#[cfg(not(stage0))]
impl<Result$(,$args)*>
FnMut<($($args,)*),Result>
for extern "Rust" fn($($args: $args,)*) -> Result {
#[rust_call_abi_hack]
#[allow(uppercase_variables)]
fn call_mut(&mut self, args: ($($args,)*)) -> Result {
let ($($args,)*) = args;
(*self)($($args,)*)
}
}
)
)
def_fn_mut!()
def_fn_mut!(A0)
def_fn_mut!(A0 A1)
def_fn_mut!(A0 A1 A2)
def_fn_mut!(A0 A1 A2 A3)
def_fn_mut!(A0 A1 A2 A3 A4)
def_fn_mut!(A0 A1 A2 A3 A4 A5)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
def_fn_mut!(A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)

View File

@ -11,8 +11,8 @@
use core::ptr::*;
use libc::c_char;
use core::mem;
use std::str;
use libc;
use std::c_str::CString;
#[test]
fn test() {
@ -186,9 +186,8 @@ fn test_ptr_array_each_with_len() {
let mut ctr = 0;
let mut iteration_count = 0;
array_each_with_len(arr.as_ptr(), arr.len(), |e| {
let actual = str::raw::from_c_str(e);
let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr());
assert_eq!(actual.as_slice(), expected.as_slice());
let actual = CString::new(e, false);
assert_eq!(actual.as_str(), expected_arr[ctr].as_str());
ctr += 1;
iteration_count += 1;
});
@ -217,9 +216,8 @@ fn test_ptr_array_each() {
let mut ctr = 0u;
let mut iteration_count = 0u;
array_each(arr_ptr, |e| {
let actual = str::raw::from_c_str(e);
let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr());
assert_eq!(actual.as_slice(), expected.as_slice());
let actual = CString::new(e, false);
assert_eq!(actual.as_str(), expected_arr[ctr].as_str());
ctr += 1;
iteration_count += 1;
});
@ -232,7 +230,7 @@ fn test_ptr_array_each() {
fn test_ptr_array_each_with_len_null_ptr() {
unsafe {
array_each_with_len(0 as *const *const libc::c_char, 1, |e| {
str::raw::from_c_str(e);
CString::new(e, false).as_str().unwrap();
});
}
}
@ -241,7 +239,7 @@ fn test_ptr_array_each_with_len_null_ptr() {
fn test_ptr_array_each_null_ptr() {
unsafe {
array_each(0 as *const *const libc::c_char, |e| {
str::raw::from_c_str(e);
CString::new(e, false).as_str().unwrap();
});
}
}

View File

@ -180,7 +180,7 @@ impl Scheduler {
// Take a main task to run, and a scheduler to run it in. Create a
// scheduler task and bootstrap into it.
pub fn bootstrap(mut ~self) {
pub fn bootstrap(mut self: Box<Scheduler>) {
// Build an Idle callback.
let cb = box SchedRunner as Box<Callback + Send>;
@ -224,7 +224,8 @@ impl Scheduler {
// This does not return a scheduler, as the scheduler is placed
// inside the task.
pub fn run(mut ~self, stask: Box<GreenTask>) -> Box<GreenTask> {
pub fn run(mut self: Box<Scheduler>, stask: Box<GreenTask>)
-> Box<GreenTask> {
// This is unsafe because we need to place the scheduler, with
// the event_loop inside, inside our task. But we still need a
@ -271,7 +272,7 @@ impl Scheduler {
// If we try really hard to do some work, but no work is available to be
// done, then we fall back to epoll() to block this thread waiting for more
// work (instead of busy waiting).
fn run_sched_once(mut ~self, stask: Box<GreenTask>) {
fn run_sched_once(mut self: Box<Scheduler>, stask: Box<GreenTask>) {
// Make sure that we're not lying in that the `stask` argument is indeed
// the scheduler task for this scheduler.
assert!(self.sched_task.is_none());
@ -349,11 +350,10 @@ impl Scheduler {
// returns the still-available scheduler. At this point all
// message-handling will count as a turn of work, and as a result
// return None.
fn interpret_message_queue(mut ~self, stask: Box<GreenTask>,
fn interpret_message_queue(mut self: Box<Scheduler>,
stask: Box<GreenTask>,
effort: EffortLevel)
-> (Box<Scheduler>, Box<GreenTask>, bool)
{
-> (Box<Scheduler>, Box<GreenTask>, bool) {
let msg = if effort == DontTryTooHard {
self.message_queue.casual_pop()
} else {
@ -432,7 +432,7 @@ impl Scheduler {
}
}
fn do_work(mut ~self, stask: Box<GreenTask>)
fn do_work(mut self: Box<Scheduler>, stask: Box<GreenTask>)
-> (Box<Scheduler>, Box<GreenTask>, bool) {
rtdebug!("scheduler calling do work");
match self.find_work() {
@ -517,7 +517,7 @@ impl Scheduler {
// * Task Routing Functions - Make sure tasks send up in the right
// place.
fn process_task(mut ~self,
fn process_task(mut self: Box<Scheduler>,
cur: Box<GreenTask>,
mut next: Box<GreenTask>,
schedule_fn: SchedulingFn)
@ -610,7 +610,7 @@ impl Scheduler {
// cleanup function f, which takes the scheduler and the
// old task as inputs.
pub fn change_task_context(mut ~self,
pub fn change_task_context(mut self: Box<Scheduler>,
mut current_task: Box<GreenTask>,
mut next_task: Box<GreenTask>,
f: |&mut Scheduler, Box<GreenTask>|)
@ -693,7 +693,7 @@ impl Scheduler {
// * Context Swapping Helpers - Here be ugliness!
pub fn resume_task_immediately(~self,
pub fn resume_task_immediately(self: Box<Scheduler>,
cur: Box<GreenTask>,
next: Box<GreenTask>)
-> (Box<Scheduler>, Box<GreenTask>) {
@ -733,7 +733,7 @@ impl Scheduler {
/// This situation is currently prevented, or in other words it is
/// guaranteed that this function will not return before the given closure
/// has returned.
pub fn deschedule_running_task_and_then(mut ~self,
pub fn deschedule_running_task_and_then(mut self: Box<Scheduler>,
cur: Box<GreenTask>,
f: |&mut Scheduler, BlockedTask|) {
// Trickier - we need to get the scheduler task out of self
@ -743,7 +743,7 @@ impl Scheduler {
self.switch_running_tasks_and_then(cur, stask, f)
}
pub fn switch_running_tasks_and_then(~self,
pub fn switch_running_tasks_and_then(self: Box<Scheduler>,
cur: Box<GreenTask>,
next: Box<GreenTask>,
f: |&mut Scheduler, BlockedTask|) {
@ -795,7 +795,9 @@ impl Scheduler {
/// Called by a running task to end execution, after which it will
/// be recycled by the scheduler for reuse in a new task.
pub fn terminate_current_task(mut ~self, cur: Box<GreenTask>) -> ! {
pub fn terminate_current_task(mut self: Box<Scheduler>,
cur: Box<GreenTask>)
-> ! {
// Similar to deschedule running task and then, but cannot go through
// the task-blocking path. The task is already dying.
let stask = self.sched_task.take_unwrap();
@ -807,7 +809,9 @@ impl Scheduler {
fail!("should never return!");
}
pub fn run_task(~self, cur: Box<GreenTask>, next: Box<GreenTask>) {
pub fn run_task(self: Box<Scheduler>,
cur: Box<GreenTask>,
next: Box<GreenTask>) {
let (sched, task) =
self.process_task(cur, next, Scheduler::switch_task);
task.put_with_sched(sched);
@ -823,7 +827,7 @@ impl Scheduler {
/// to introduce some amount of randomness to the scheduler. Currently the
/// randomness is a result of performing a round of work stealing (which
/// may end up stealing from the current scheduler).
pub fn yield_now(mut ~self, cur: Box<GreenTask>) {
pub fn yield_now(mut self: Box<Scheduler>, cur: Box<GreenTask>) {
// Async handles trigger the scheduler by calling yield_now on the local
// task, which eventually gets us to here. See comments in SchedRunner
// for more info on this.
@ -842,7 +846,7 @@ impl Scheduler {
}
}
pub fn maybe_yield(mut ~self, cur: Box<GreenTask>) {
pub fn maybe_yield(mut self: Box<Scheduler>, cur: Box<GreenTask>) {
// It's possible for sched tasks to possibly call this function, and it
// just means that they're likely sending on channels (which
// occasionally call this function). Sched tasks follow different paths

View File

@ -27,7 +27,9 @@ struct SimpleTask {
impl Runtime for SimpleTask {
// Implement the simple tasks of descheduling and rescheduling, but only in
// a simple number of cases.
fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
fn deschedule(mut self: Box<SimpleTask>,
times: uint,
mut cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
assert!(times == 1);
@ -54,7 +56,7 @@ impl Runtime for SimpleTask {
}
Local::put(cur_task);
}
fn reawaken(mut ~self, mut to_wake: Box<Task>) {
fn reawaken(mut self: Box<SimpleTask>, mut to_wake: Box<Task>) {
let me = &mut *self as *mut SimpleTask;
to_wake.put_runtime(self);
unsafe {
@ -69,9 +71,9 @@ impl Runtime for SimpleTask {
// purpose. A "simple task" is just that, a very simple task that can't
// really do a whole lot. The only purpose of the task is to get us off our
// feet and running.
fn yield_now(~self, _cur_task: Box<Task>) { fail!() }
fn maybe_yield(~self, _cur_task: Box<Task>) { fail!() }
fn spawn_sibling(~self,
fn yield_now(self: Box<SimpleTask>, _cur_task: Box<Task>) { fail!() }
fn maybe_yield(self: Box<SimpleTask>, _cur_task: Box<Task>) { fail!() }
fn spawn_sibling(self: Box<SimpleTask>,
_cur_task: Box<Task>,
_opts: TaskOpts,
_f: proc():Send) {
@ -80,7 +82,7 @@ impl Runtime for SimpleTask {
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
fn stack_bounds(&self) -> (uint, uint) { fail!() }
fn can_block(&self) -> bool { true }
fn wrap(~self) -> Box<Any> { fail!() }
fn wrap(self: Box<SimpleTask>) -> Box<Any> { fail!() }
}
pub fn task() -> Box<Task> {

View File

@ -265,7 +265,7 @@ impl GreenTask {
// Runtime glue functions and helpers
pub fn put_with_sched(mut ~self, sched: Box<Scheduler>) {
pub fn put_with_sched(mut self: Box<GreenTask>, sched: Box<Scheduler>) {
assert!(self.sched.is_none());
self.sched = Some(sched);
self.put();
@ -276,18 +276,18 @@ impl GreenTask {
self.task = Some(task);
}
pub fn swap(mut ~self) -> Box<Task> {
pub fn swap(mut self: Box<GreenTask>) -> Box<Task> {
let mut task = self.task.take_unwrap();
task.put_runtime(self);
return task;
}
pub fn put(~self) {
pub fn put(self: Box<GreenTask>) {
assert!(self.sched.is_some());
Local::put(self.swap());
}
fn terminate(mut ~self) -> ! {
fn terminate(mut self: Box<GreenTask>) -> ! {
let sched = self.sched.take_unwrap();
sched.terminate_current_task(self)
}
@ -311,7 +311,7 @@ impl GreenTask {
// *not* a cheap operation to clone a handle. Until the day comes that we
// need to optimize this, a lock should do just fine (it's completely
// uncontended except for when the task is rescheduled).
fn reawaken_remotely(mut ~self) {
fn reawaken_remotely(mut self: Box<GreenTask>) {
unsafe {
let mtx = &mut self.nasty_deschedule_lock as *mut NativeMutex;
let handle = self.handle.get_mut_ref() as *mut SchedHandle;
@ -322,19 +322,21 @@ impl GreenTask {
}
impl Runtime for GreenTask {
fn yield_now(mut ~self, cur_task: Box<Task>) {
fn yield_now(mut self: Box<GreenTask>, cur_task: Box<Task>) {
self.put_task(cur_task);
let sched = self.sched.take_unwrap();
sched.yield_now(self);
}
fn maybe_yield(mut ~self, cur_task: Box<Task>) {
fn maybe_yield(mut self: Box<GreenTask>, cur_task: Box<Task>) {
self.put_task(cur_task);
let sched = self.sched.take_unwrap();
sched.maybe_yield(self);
}
fn deschedule(mut ~self, times: uint, cur_task: Box<Task>,
fn deschedule(mut self: Box<GreenTask>,
times: uint,
cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
self.put_task(cur_task);
let mut sched = self.sched.take_unwrap();
@ -383,7 +385,7 @@ impl Runtime for GreenTask {
}
}
fn reawaken(mut ~self, to_wake: Box<Task>) {
fn reawaken(mut self: Box<GreenTask>, to_wake: Box<Task>) {
self.put_task(to_wake);
assert!(self.sched.is_none());
@ -434,7 +436,7 @@ impl Runtime for GreenTask {
}
}
fn spawn_sibling(mut ~self,
fn spawn_sibling(mut self: Box<GreenTask>,
cur_task: Box<Task>,
opts: TaskOpts,
f: proc():Send) {
@ -471,7 +473,7 @@ impl Runtime for GreenTask {
fn can_block(&self) -> bool { false }
fn wrap(~self) -> Box<Any> { self as Box<Any> }
fn wrap(self: Box<GreenTask>) -> Box<Any> { self as Box<Any> }
}
#[cfg(test)]

View File

@ -10,7 +10,6 @@
use libc::{c_char, c_int};
use libc;
use std::c_str::CString;
use std::mem;
use std::ptr::{null, mut_null};
use std::rt::rtio;
@ -27,8 +26,10 @@ impl GetAddrInfoRequest {
{
assert!(host.is_some() || servname.is_some());
let c_host = host.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
let c_serv = servname.map_or(unsafe { CString::new(null(), true) }, |x| x.to_c_str());
let c_host = host.map(|x| x.to_c_str());
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let c_serv = servname.map(|x| x.to_c_str());
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
libc::addrinfo {
@ -50,9 +51,7 @@ impl GetAddrInfoRequest {
// Make the call
let s = unsafe {
let ch = if c_host.is_null() { null() } else { c_host.as_ptr() };
let cs = if c_serv.is_null() { null() } else { c_serv.as_ptr() };
getaddrinfo(ch, cs, hint_ptr, &mut res)
getaddrinfo(c_host, c_serv, hint_ptr, &mut res)
};
// Error?
@ -104,6 +103,7 @@ fn get_error(_: c_int) -> IoError {
#[cfg(not(windows))]
fn get_error(s: c_int) -> IoError {
use std::c_str::CString;
let err_str = unsafe {
CString::new(gai_strerror(s), false).as_str().unwrap().to_string()

View File

@ -484,7 +484,8 @@ impl TcpListener {
}
impl rtio::RtioTcpListener for TcpListener {
fn listen(~self) -> IoResult<Box<rtio::RtioTcpAcceptor + Send>> {
fn listen(self: Box<TcpListener>)
-> IoResult<Box<rtio::RtioTcpAcceptor + Send>> {
self.native_listen(128).map(|a| {
box a as Box<rtio::RtioTcpAcceptor + Send>
})

View File

@ -229,7 +229,8 @@ impl UnixListener {
}
impl rtio::RtioUnixListener for UnixListener {
fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
fn listen(self: Box<UnixListener>)
-> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
self.native_listen(128).map(|a| {
box a as Box<rtio::RtioUnixAcceptor + Send>
})

View File

@ -588,7 +588,8 @@ impl Drop for UnixListener {
}
impl rtio::RtioUnixListener for UnixListener {
fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
fn listen(self: Box<UnixListener>)
-> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
self.native_listen().map(|a| {
box a as Box<rtio::RtioUnixAcceptor + Send>
})

View File

@ -131,21 +131,21 @@ struct Ops {
}
impl rt::Runtime for Ops {
fn yield_now(~self, mut cur_task: Box<Task>) {
fn yield_now(self: Box<Ops>, mut cur_task: Box<Task>) {
// put the task back in TLS and then invoke the OS thread yield
cur_task.put_runtime(self);
Local::put(cur_task);
Thread::yield_now();
}
fn maybe_yield(~self, mut cur_task: Box<Task>) {
fn maybe_yield(self: Box<Ops>, mut cur_task: Box<Task>) {
// just put the task back in TLS, on OS threads we never need to
// opportunistically yield b/c the OS will do that for us (preemption)
cur_task.put_runtime(self);
Local::put(cur_task);
}
fn wrap(~self) -> Box<Any> {
fn wrap(self: Box<Ops>) -> Box<Any> {
self as Box<Any>
}
@ -192,7 +192,9 @@ impl rt::Runtime for Ops {
// `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.
fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
fn deschedule(mut self: Box<Ops>,
times: uint,
mut cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
let me = &mut *self as *mut Ops;
cur_task.put_runtime(self);
@ -250,7 +252,7 @@ impl rt::Runtime for Ops {
// See the comments on `deschedule` for why the task is forgotten here, and
// why it's valid to do so.
fn reawaken(mut ~self, mut to_wake: Box<Task>) {
fn reawaken(mut self: Box<Ops>, mut to_wake: Box<Task>) {
unsafe {
let me = &mut *self as *mut Ops;
to_wake.put_runtime(self);
@ -261,7 +263,7 @@ impl rt::Runtime for Ops {
}
}
fn spawn_sibling(~self,
fn spawn_sibling(self: Box<Ops>,
mut cur_task: Box<Task>,
opts: TaskOpts,
f: proc():Send) {

View File

@ -233,7 +233,7 @@ use std::io;
use std::mem;
use std::ptr;
use std::slice;
use std::str;
use std::string;
use std::collections::{HashMap, HashSet};
use flate;
@ -772,7 +772,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let mut name_buf = ptr::null();
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
let name = str::raw::from_buf_len(name_buf as *const u8,
let name = string::raw::from_buf_len(name_buf as *const u8,
name_len as uint);
debug!("get_metadata_section: name {}", name);
if read_meta_section_name(os).as_slice() == name.as_slice() {

View File

@ -21,9 +21,9 @@ use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
use std::c_str::ToCStr;
use std::mem;
use std::string;
use std::cell::RefCell;
use std::collections::HashMap;
use std::str::raw::from_c_str;
use libc::{c_uint, c_void, free};
@ -334,9 +334,9 @@ impl TypeNames {
pub fn type_to_string(&self, ty: Type) -> String {
unsafe {
let s = llvm::LLVMTypeToString(ty.to_ref());
let ret = from_c_str(s);
let ret = string::raw::from_buf(s as *const u8);
free(s as *mut c_void);
ret.to_string()
ret
}
}
@ -348,9 +348,9 @@ impl TypeNames {
pub fn val_to_string(&self, val: ValueRef) -> String {
unsafe {
let s = llvm::LLVMValueToString(val);
let ret = from_c_str(s);
let ret = string::raw::from_buf(s as *const u8);
free(s as *mut c_void);
ret.to_string()
ret
}
}
}

View File

@ -53,6 +53,7 @@ use middle::const_eval;
use middle::def;
use middle::lang_items::FnMutTraitLangItem;
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::subst::{VecPerParamSpace};
use middle::ty;
use middle::ty_fold::TypeFolder;
use middle::typeck::rscope::{ExplicitRscope, ImpliedSingleRscope};
@ -299,6 +300,47 @@ pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
TypeAndSubsts { substs: substs, ty: ty }
}
/// Returns the type that this AST path refers to. If the path has no type
/// parameters and the corresponding type has type parameters, fresh type
/// and/or region variables are substituted.
///
/// This is used when checking the constructor in struct literals.
pub fn ast_path_to_ty_relaxed<AC:AstConv,
RS:RegionScope>(
this: &AC,
rscope: &RS,
did: ast::DefId,
path: &ast::Path)
-> TypeAndSubsts {
let tcx = this.tcx();
let ty::Polytype {
generics: generics,
ty: decl_ty
} = this.get_item_ty(did);
let substs = if (generics.has_type_params(TypeSpace) ||
generics.has_region_params(TypeSpace)) &&
path.segments.iter().all(|s| {
s.lifetimes.len() == 0 && s.types.len() == 0
}) {
let type_params = Vec::from_fn(generics.types.len(TypeSpace),
|_| this.ty_infer(path.span));
let region_params =
rscope.anon_regions(path.span, generics.regions.len(TypeSpace))
.unwrap();
Substs::new(VecPerParamSpace::params_from_type(type_params),
VecPerParamSpace::params_from_type(region_params))
} else {
ast_path_substs(this, rscope, &generics, None, path)
};
let ty = decl_ty.subst(tcx, &substs);
TypeAndSubsts {
substs: substs,
ty: ty,
}
}
pub static NO_REGIONS: uint = 1;
pub static NO_TPS: uint = 2;
@ -1051,7 +1093,6 @@ fn determine_explicit_self_category<AC:AstConv,
lifetime);
ty::ByReferenceExplicitSelfCategory(region, mutability)
}
ast::SelfUniq(_) => ty::ByBoxExplicitSelfCategory,
ast::SelfExplicit(ast_type, _) => {
let explicit_type = ast_ty_to_ty(this, rscope, &*ast_type);

View File

@ -1541,6 +1541,13 @@ fn try_overloaded_call(fcx: &FnCtxt,
callee_type: ty::t,
args: &[Gc<ast::Expr>])
-> bool {
// Bail out if the callee is a bare function or a closure. We check those
// manually.
match *structure_of(fcx, callee.span, callee_type) {
ty::ty_bare_fn(_) | ty::ty_closure(_) => return false,
_ => {}
}
// Try `FnOnce`, then `FnMut`, then `Fn`.
for &(maybe_function_trait, method_name) in [
(fcx.tcx().lang_items.fn_once_trait(), token::intern("call_once")),
@ -3409,10 +3416,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
ast::ExprStruct(ref path, ref fields, base_expr) => {
// Resolve the path.
let def = tcx.def_map.borrow().find(&id).map(|i| *i);
match def {
let struct_id = match def {
Some(def::DefVariant(enum_id, variant_id, _)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
variant_id, fields.as_slice());
enum_id
}
Some(def) => {
// Verify that this was actually a struct.
@ -3432,11 +3440,47 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
pprust::path_to_string(path));
}
}
def.def_id()
}
_ => {
tcx.sess.span_bug(path.span,
"structure constructor wasn't resolved")
}
};
// Turn the path into a type and verify that that type unifies with
// the resulting structure type. This is needed to handle type
// parameters correctly.
let actual_structure_type = fcx.expr_ty(&*expr);
if !ty::type_is_error(actual_structure_type) {
let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
fcx.infcx(),
struct_id,
path);
match fcx.mk_subty(false,
infer::Misc(path.span),
actual_structure_type,
type_and_substs.ty) {
Ok(()) => {}
Err(type_error) => {
let type_error_description =
ty::type_err_to_str(tcx, &type_error);
fcx.tcx()
.sess
.span_err(path.span,
format!("structure constructor specifies a \
structure of type `{}`, but this \
structure has type `{}`: {}",
fcx.infcx()
.ty_to_string(type_and_substs.ty),
fcx.infcx()
.ty_to_string(
actual_structure_type),
type_error_description).as_slice());
ty::note_and_explain_type_err(tcx, &type_error);
}
}
}
}
ast::ExprField(ref base, ref field, ref tys) => {

View File

@ -779,7 +779,6 @@ impl Clean<SelfTy> for ast::ExplicitSelf_ {
match *self {
ast::SelfStatic => SelfStatic,
ast::SelfValue(_) => SelfValue,
ast::SelfUniq(_) => SelfOwned,
ast::SelfRegion(lt, mt, _) => {
SelfBorrowed(lt.clean(), mt.clean())
}

View File

@ -491,7 +491,7 @@ impl<'a> fmt::Show for Method<'a> {
match *selfty {
clean::SelfStatic => {},
clean::SelfValue => args.push_str("self"),
clean::SelfOwned => args.push_str("~self"),
clean::SelfOwned => args.push_str("self: Box<Self>"),
clean::SelfBorrowed(Some(ref lt), mtbl) => {
args.push_str(format!("&amp;{} {}self", *lt,
MutableSpace(mtbl)).as_slice());

View File

@ -32,6 +32,7 @@ use std::cell::{RefCell, Cell};
use std::fmt;
use std::slice;
use std::str;
use std::string;
use std::collections::HashMap;
use html::toc::TocBuilder;
@ -222,7 +223,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
"".to_string()
} else {
unsafe {
str::raw::from_buf_len((*text).data, (*text).size as uint)
string::raw::from_buf_len((*text).data, (*text).size as uint)
}
};

View File

@ -102,6 +102,7 @@ pub fn opts() -> Vec<getopts::OptGroup> {
optopt("w", "output-format", "the output type to write",
"[html|json]"),
optopt("o", "output", "where to place the output", "PATH"),
optopt("", "crate-name", "specify the name of this crate", "NAME"),
optmulti("L", "library-path", "directory to add to crate search path",
"DIR"),
optmulti("", "cfg", "pass a --cfg to rustc", ""),
@ -131,7 +132,8 @@ pub fn opts() -> Vec<getopts::OptGroup> {
Markdown file or generated documentation",
"FILES"),
optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")
"URL to send code snippets to", "URL"),
optflag("", "markdown-no-toc", "don't include table of contents")
)
}
@ -220,7 +222,8 @@ pub fn main_args(args: &[String]) -> int {
return test::run(input, cfgs, libs, externs, test_args)
}
(false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")),
&matches, &external_html),
&matches, &external_html,
!matches.opt_present("markdown-no-toc")),
(false, false) => {}
}
@ -321,7 +324,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
let cr = Path::new(cratefile);
info!("starting to run rustc");
let (krate, analysis) = std::task::try(proc() {
let (mut krate, analysis) = std::task::try(proc() {
let cr = cr;
core::run_core(libs.move_iter().collect(),
cfgs,
@ -331,6 +334,11 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
info!("finished with rustc");
analysiskey.replace(Some(analysis));
match matches.opt_str("crate-name") {
Some(name) => krate.name = name,
None => {}
}
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
match krate.module.get_ref().doc_list() {

View File

@ -20,7 +20,7 @@ use externalfiles::ExternalHtml;
use html::escape::Escape;
use html::markdown;
use html::markdown::{MarkdownWithToc, find_testable_code, reset_headers};
use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, reset_headers};
use test::Collector;
/// Separate any lines at the start of the file that begin with `%`.
@ -42,7 +42,7 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
/// Render `input` (e.g. "foo.md") into an HTML file in `output`
/// (e.g. output = "bar" => "bar/foo.html").
pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
external_html: &ExternalHtml) -> int {
external_html: &ExternalHtml, include_toc: bool) -> int {
let input_p = Path::new(input);
output.push(input_p.filestem().unwrap());
output.set_extension("html");
@ -80,6 +80,12 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
reset_headers();
let rendered = if include_toc {
format!("{}", MarkdownWithToc(text))
} else {
format!("{}", Markdown(text))
};
let err = write!(
&mut out,
r#"<!DOCTYPE html>
@ -113,7 +119,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
css = css,
in_header = external_html.in_header,
before_content = external_html.before_content,
text = MarkdownWithToc(text),
text = rendered,
after_content = external_html.after_content,
playground = playground,
);

View File

@ -70,6 +70,7 @@ use core::prelude::*;
use alloc::libc_heap::malloc_raw;
use collections::string::String;
use collections::hash;
use core::fmt;
use core::kinds::marker;
use core::mem;
use core::ptr;
@ -92,23 +93,18 @@ impl Clone for CString {
/// reasons, this is always a deep clone, rather than the usual shallow
/// clone.
fn clone(&self) -> CString {
if self.buf.is_null() {
CString { buf: self.buf, owns_buffer_: self.owns_buffer_ }
} else {
let len = self.len() + 1;
let buf = unsafe { malloc_raw(len) } as *mut libc::c_char;
unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
CString { buf: buf as *const libc::c_char, owns_buffer_: true }
}
let len = self.len() + 1;
let buf = unsafe { malloc_raw(len) } as *mut libc::c_char;
unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
CString { buf: buf as *const libc::c_char, owns_buffer_: true }
}
}
impl PartialEq for CString {
fn eq(&self, other: &CString) -> bool {
// Check if the two strings share the same buffer
if self.buf as uint == other.buf as uint {
true
} else if self.buf.is_null() || other.buf.is_null() {
false
} else {
unsafe {
libc::strcmp(self.buf, other.buf) == 0
@ -135,7 +131,12 @@ impl<S: hash::Writer> hash::Hash<S> for CString {
impl CString {
/// Create a C String from a pointer.
///
///# Failure
///
/// Fails if `buf` is null
pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
assert!(!buf.is_null());
CString { buf: buf, owns_buffer_: owns_buffer }
}
@ -157,10 +158,6 @@ impl CString {
/// let p = foo.to_c_str().as_ptr();
/// ```
///
/// # Failure
///
/// Fails if the CString is null.
///
/// # Example
///
/// ```rust
@ -174,8 +171,6 @@ impl CString {
/// }
/// ```
pub fn as_ptr(&self) -> *const libc::c_char {
if self.buf.is_null() { fail!("CString is null!"); }
self.buf
}
@ -196,44 +191,30 @@ impl CString {
/// // wrong (the CString will be freed, invalidating `p`)
/// let p = foo.to_c_str().as_mut_ptr();
/// ```
///
/// # Failure
///
/// Fails if the CString is null.
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
if self.buf.is_null() { fail!("CString is null!") }
self.buf as *mut _
}
/// Calls a closure with a reference to the underlying `*libc::c_char`.
///
/// # Failure
///
/// Fails if the CString is null.
#[deprecated="use `.as_ptr()`"]
pub fn with_ref<T>(&self, f: |*const libc::c_char| -> T) -> T {
if self.buf.is_null() { fail!("CString is null!"); }
f(self.buf)
}
/// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
///
/// # Failure
///
/// Fails if the CString is null.
#[deprecated="use `.as_mut_ptr()`"]
pub fn with_mut_ref<T>(&mut self, f: |*mut libc::c_char| -> T) -> T {
if self.buf.is_null() { fail!("CString is null!"); }
f(self.buf as *mut libc::c_char)
}
/// Returns true if the CString is a null.
#[deprecated="a CString cannot be null"]
pub fn is_null(&self) -> bool {
self.buf.is_null()
}
/// Returns true if the CString is not null.
#[deprecated="a CString cannot be null"]
pub fn is_not_null(&self) -> bool {
self.buf.is_not_null()
}
@ -245,13 +226,8 @@ impl CString {
/// Converts the CString into a `&[u8]` without copying.
/// Includes the terminating NUL byte.
///
/// # Failure
///
/// Fails if the CString is null.
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
if self.buf.is_null() { fail!("CString is null!"); }
unsafe {
mem::transmute(Slice { data: self.buf, len: self.len() + 1 })
}
@ -259,13 +235,8 @@ impl CString {
/// Converts the CString into a `&[u8]` without copying.
/// Does not include the terminating NUL byte.
///
/// # Failure
///
/// Fails if the CString is null.
#[inline]
pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
if self.buf.is_null() { fail!("CString is null!"); }
unsafe {
mem::transmute(Slice { data: self.buf, len: self.len() })
}
@ -273,10 +244,6 @@ impl CString {
/// Converts the CString into a `&str` without copying.
/// Returns None if the CString is not UTF-8.
///
/// # Failure
///
/// Fails if the CString is null.
#[inline]
pub fn as_str<'a>(&'a self) -> Option<&'a str> {
let buf = self.as_bytes_no_nul();
@ -284,12 +251,7 @@ impl CString {
}
/// Return a CString iterator.
///
/// # Failure
///
/// Fails if the CString is null.
pub fn iter<'a>(&'a self) -> CChars<'a> {
if self.buf.is_null() { fail!("CString is null!"); }
CChars {
ptr: self.buf,
marker: marker::ContravariantLifetime,
@ -325,13 +287,8 @@ impl Drop for CString {
impl Collection for CString {
/// Return the number of bytes in the CString (not including the NUL terminator).
///
/// # Failure
///
/// Fails if the CString is null.
#[inline]
fn len(&self) -> uint {
if self.buf.is_null() { fail!("CString is null!"); }
let mut cur = self.buf;
let mut len = 0;
unsafe {
@ -344,6 +301,12 @@ impl Collection for CString {
}
}
impl fmt::Show for CString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
}
}
/// A generic trait for converting a value to a CString.
pub trait ToCStr {
/// Copy the receiver into a CString.
@ -624,13 +587,6 @@ mod tests {
}
}
#[test]
fn test_is_null() {
let c_str = unsafe { CString::new(ptr::null(), false) };
assert!(c_str.is_null());
assert!(!c_str.is_not_null());
}
#[test]
fn test_unwrap() {
let c_str = "hello".to_c_str();
@ -641,16 +597,8 @@ mod tests {
fn test_as_ptr() {
let c_str = "hello".to_c_str();
let len = unsafe { libc::strlen(c_str.as_ptr()) };
assert!(!c_str.is_null());
assert!(c_str.is_not_null());
assert_eq!(len, 5);
}
#[test]
#[should_fail]
fn test_as_ptr_empty_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.as_ptr();
}
#[test]
fn test_iterator() {
@ -709,20 +657,6 @@ mod tests {
assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
}
#[test]
#[should_fail]
fn test_as_bytes_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.as_bytes();
}
#[test]
#[should_fail]
fn test_as_bytes_no_nul_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.as_bytes_no_nul();
}
#[test]
fn test_as_str() {
let c_str = "hello".to_c_str();
@ -735,23 +669,8 @@ mod tests {
#[test]
#[should_fail]
fn test_as_str_fail() {
fn test_new_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.as_str();
}
#[test]
#[should_fail]
fn test_len_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.len();
}
#[test]
#[should_fail]
fn test_iter_fail() {
let c_str = unsafe { CString::new(ptr::null(), false) };
c_str.iter();
}
#[test]
@ -784,13 +703,6 @@ mod tests {
// force a copy, reading the memory
c_.as_bytes().to_vec();
}
#[test]
fn test_clone_eq_null() {
let x = unsafe { CString::new(ptr::null(), false) };
let y = x.clone();
assert!(x == y);
}
}
#[cfg(test)]

View File

@ -74,15 +74,17 @@ pub mod unwind;
pub trait Runtime {
// Necessary scheduling functions, used for channels and blocking I/O
// (sometimes).
fn yield_now(~self, cur_task: Box<Task>);
fn maybe_yield(~self, cur_task: Box<Task>);
fn deschedule(~self, times: uint, cur_task: Box<Task>,
fn yield_now(self: Box<Self>, cur_task: Box<Task>);
fn maybe_yield(self: Box<Self>, cur_task: Box<Task>);
fn deschedule(self: Box<Self>,
times: uint,
cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>);
fn reawaken(~self, to_wake: Box<Task>);
fn reawaken(self: Box<Self>, to_wake: Box<Task>);
// Miscellaneous calls which are very different depending on what context
// you're in.
fn spawn_sibling(~self,
fn spawn_sibling(self: Box<Self>,
cur_task: Box<Task>,
opts: TaskOpts,
f: proc():Send);
@ -92,7 +94,7 @@ pub trait Runtime {
fn can_block(&self) -> bool;
// FIXME: This is a serious code smell and this should not exist at all.
fn wrap(~self) -> Box<Any>;
fn wrap(self: Box<Self>) -> Box<Any>;
}
/// The default error code of the rust runtime if the main task fails instead

View File

@ -238,7 +238,7 @@ pub trait IoFactory {
}
pub trait RtioTcpListener : RtioSocket {
fn listen(~self) -> IoResult<Box<RtioTcpAcceptor + Send>>;
fn listen(self: Box<Self>) -> IoResult<Box<RtioTcpAcceptor + Send>>;
}
pub trait RtioTcpAcceptor : RtioSocket {
@ -329,7 +329,7 @@ pub trait RtioPipe {
}
pub trait RtioUnixListener {
fn listen(~self) -> IoResult<Box<RtioUnixAcceptor + Send>>;
fn listen(self: Box<Self>) -> IoResult<Box<RtioUnixAcceptor + Send>>;
}
pub trait RtioUnixAcceptor {

View File

@ -203,7 +203,7 @@ impl Task {
/// }).destroy();
/// # }
/// ```
pub fn run(~self, f: ||) -> Box<Task> {
pub fn run(self: Box<Task>, f: ||) -> Box<Task> {
assert!(!self.is_destroyed(), "cannot re-use a destroyed task");
// First, make sure that no one else is in TLS. This does not allow
@ -239,7 +239,7 @@ impl Task {
///
/// The returned task cannot be used for running any more code, but it may
/// be used to extract the runtime as necessary.
pub fn destroy(~self) -> Box<Task> {
pub fn destroy(self: Box<Task>) -> Box<Task> {
if self.is_destroyed() {
self
} else {
@ -252,7 +252,7 @@ impl Task {
/// This function consumes ownership of the task, deallocating it once it's
/// done being processed. It is assumed that TLD and the local heap have
/// already been destroyed and/or annihilated.
fn cleanup(~self, result: Result) -> Box<Task> {
fn cleanup(self: Box<Task>, result: Result) -> Box<Task> {
// The first thing to do when cleaning up is to deallocate our local
// resources, such as TLD and GC data.
//
@ -394,7 +394,9 @@ impl Task {
/// Spawns a sibling to this task. The newly spawned task is configured with
/// the `opts` structure and will run `f` as the body of its code.
pub fn spawn_sibling(mut ~self, opts: TaskOpts, f: proc(): Send) {
pub fn spawn_sibling(mut self: Box<Task>,
opts: TaskOpts,
f: proc(): Send) {
let ops = self.imp.take_unwrap();
ops.spawn_sibling(self, opts, f)
}
@ -402,7 +404,8 @@ impl Task {
/// Deschedules the current task, invoking `f` `amt` times. It is not
/// recommended to use this function directly, but rather communication
/// primitives in `std::comm` should be used.
pub fn deschedule(mut ~self, amt: uint,
pub fn deschedule(mut self: Box<Task>,
amt: uint,
f: |BlockedTask| -> ::core::result::Result<(), BlockedTask>) {
let ops = self.imp.take_unwrap();
ops.deschedule(amt, self, f)
@ -411,7 +414,7 @@ impl Task {
/// Wakes up a previously blocked task, optionally specifying whether the
/// current task can accept a change in scheduling. This function can only
/// be called on tasks that were previously blocked in `deschedule`.
pub fn reawaken(mut ~self) {
pub fn reawaken(mut self: Box<Task>) {
let ops = self.imp.take_unwrap();
ops.reawaken(self);
}
@ -419,14 +422,14 @@ impl Task {
/// Yields control of this task to another task. This function will
/// eventually return, but possibly not immediately. This is used as an
/// opportunity to allow other tasks a chance to run.
pub fn yield_now(mut ~self) {
pub fn yield_now(mut self: Box<Task>) {
let ops = self.imp.take_unwrap();
ops.yield_now(self);
}
/// Similar to `yield_now`, except that this function may immediately return
/// without yielding (depending on what the runtime decides to do).
pub fn maybe_yield(mut ~self) {
pub fn maybe_yield(mut self: Box<Task>) {
let ops = self.imp.take_unwrap();
ops.maybe_yield(self);
}

View File

@ -58,11 +58,11 @@ use libc::{c_int, c_void};
use std::fmt;
use std::mem;
use std::ptr;
use std::string;
use std::rt::local::Local;
use std::rt::rtio;
use std::rt::rtio::{IoResult, IoError};
use std::rt::task::{BlockedTask, Task};
use std::str::raw::from_c_str;
use std::task;
pub use self::async::AsyncWatcher;
@ -154,7 +154,7 @@ pub trait UvHandle<T> {
mem::transmute(uvll::get_data_for_uv_handle(*h))
}
fn install(~self) -> Box<Self> {
fn install(self: Box<Self>) -> Box<Self> {
unsafe {
let myptr = mem::transmute::<&Box<Self>, &*mut u8>(&self);
uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
@ -363,7 +363,7 @@ impl UvError {
let inner = match self { &UvError(a) => a };
let name_str = uvll::uv_err_name(inner);
assert!(name_str.is_not_null());
from_c_str(name_str).to_string()
string::raw::from_buf(name_str as *const u8)
}
}
@ -372,7 +372,7 @@ impl UvError {
let inner = match self { &UvError(a) => a };
let desc_str = uvll::uv_strerror(inner);
assert!(desc_str.is_not_null());
from_c_str(desc_str).to_string()
string::raw::from_buf(desc_str as *const u8)
}
}

View File

@ -389,7 +389,8 @@ impl rtio::RtioSocket for TcpListener {
}
impl rtio::RtioTcpListener for TcpListener {
fn listen(~self) -> Result<Box<rtio::RtioTcpAcceptor + Send>, IoError> {
fn listen(self: Box<TcpListener>)
-> Result<Box<rtio::RtioTcpAcceptor + Send>, IoError> {
// create the acceptor object from ourselves
let mut acceptor = box TcpAcceptor {
listener: self,

View File

@ -248,7 +248,8 @@ impl PipeListener {
}
impl rtio::RtioUnixListener for PipeListener {
fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
fn listen(self: Box<PipeListener>)
-> IoResult<Box<rtio::RtioUnixAcceptor + Send>> {
// create the acceptor object from ourselves
let mut acceptor = box PipeAcceptor {
listener: self,

View File

@ -11,8 +11,8 @@
// ignore-lexer-test FIXME #15679
//! Base64 binary-to-text encoding
use std::str;
use std::fmt;
use std::string;
/// Available encoding character sets
pub enum CharacterSet {
@ -148,7 +148,7 @@ impl<'a> ToBase64 for &'a [u8] {
}
unsafe {
str::raw::from_utf8_owned(v)
string::raw::from_utf8(v)
}
}
}

View File

@ -11,8 +11,8 @@
// ignore-lexer-test FIXME #15679
//! Hex binary-to-text encoding
use std::str;
use std::fmt;
use std::string;
/// A trait for converting a value to hexadecimal encoding
pub trait ToHex {
@ -47,7 +47,7 @@ impl<'a> ToHex for &'a [u8] {
}
unsafe {
str::raw::from_utf8_owned(v)
string::raw::from_utf8(v)
}
}
}

View File

@ -20,7 +20,7 @@ use iter::Iterator;
use mem;
use option::{Option, Some, None};
use slice::{ImmutableVector, MutableVector, Vector};
use str::{OwnedStr, Str, StrAllocating, StrSlice};
use str::{Str, StrAllocating, StrSlice};
use string::String;
use to_string::IntoStr;
use vec::Vec;

View File

@ -47,7 +47,6 @@ use ptr;
use result::{Err, Ok, Result};
use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector};
use str::{Str, StrSlice, StrAllocating};
use str;
use string::String;
use sync::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
use vec::Vec;
@ -56,8 +55,6 @@ use vec::Vec;
use c_str::ToCStr;
#[cfg(unix)]
use libc::c_char;
#[cfg(windows)]
use str::OwnedStr;
/// Get the number of cores available
pub fn num_cpus() -> uint {
@ -137,7 +134,7 @@ pub fn getcwd() -> Path {
fail!();
}
}
Path::new(String::from_utf16(str::truncate_utf16_at_nul(buf))
Path::new(String::from_utf16(::str::truncate_utf16_at_nul(buf))
.expect("GetCurrentDirectoryW returned invalid UTF-16"))
}
@ -415,7 +412,7 @@ pub fn setenv<T: BytesContainer>(n: &str, v: T) {
fn _setenv(n: &str, v: &[u8]) {
let n: Vec<u16> = n.utf16_units().collect();
let n = n.append_one(0);
let v: Vec<u16> = str::from_utf8(v).unwrap().utf16_units().collect();
let v: Vec<u16> = ::str::from_utf8(v).unwrap().utf16_units().collect();
let v = v.append_one(0);
unsafe {
@ -708,8 +705,6 @@ pub fn self_exe_name() -> Option<Path> {
#[cfg(windows)]
fn load_self() -> Option<Vec<u8>> {
use str::OwnedStr;
unsafe {
use os::win32::fill_utf16_buf_and_decode;
fill_utf16_buf_and_decode(|buf, sz| {
@ -1002,7 +997,7 @@ pub fn error_string(errnum: uint) -> String {
fail!("strerror_r failure");
}
str::raw::from_c_str(p as *const c_char).into_string()
::string::raw::from_buf(p as *const u8)
}
}
@ -1049,7 +1044,7 @@ pub fn error_string(errnum: uint) -> String {
return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
}
let msg = String::from_utf16(str::truncate_utf16_at_nul(buf));
let msg = String::from_utf16(::str::truncate_utf16_at_nul(buf));
match msg {
Some(msg) => format!("OS Error {}: {}", errnum, msg),
None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
@ -1206,7 +1201,7 @@ fn real_args() -> Vec<String> {
// Push it onto the list.
let opt_s = slice::raw::buf_as_slice(ptr as *const _, len, |buf| {
String::from_utf16(str::truncate_utf16_at_nul(buf))
String::from_utf16(::str::truncate_utf16_at_nul(buf))
});
opt_s.expect("CommandLineToArgvW returned invalid UTF-16")
});

View File

@ -76,7 +76,7 @@
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
#[doc(no_inline)] pub use ptr::RawPtr;
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice, OwnedStr};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};

View File

@ -955,8 +955,6 @@ pub enum ExplicitSelf_ {
SelfValue(Ident),
/// `&'lt self`, `&'lt mut self`
SelfRegion(Option<Lifetime>, Mutability, Ident),
/// `~self`
SelfUniq(Ident),
/// `self: TYPE`
SelfExplicit(P<Ty>, Ident),
}

View File

@ -340,7 +340,7 @@ pub trait Folder {
fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
match *es {
SelfStatic | SelfValue(_) | SelfUniq(_) => *es,
SelfStatic | SelfValue(_) => *es,
SelfRegion(ref lifetime, m, id) => {
SelfRegion(fold_opt_lifetime(lifetime, self), m, id)
}

View File

@ -31,6 +31,7 @@ pub enum ObsoleteSyntax {
ObsoleteOwnedExpr,
ObsoleteOwnedPattern,
ObsoleteOwnedVector,
ObsoleteOwnedSelf,
ObsoleteManagedType,
ObsoleteManagedExpr,
}
@ -70,6 +71,10 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
"`~[T]` is no longer a type",
"use the `Vec` type instead"
),
ObsoleteOwnedSelf => (
"`~self` is no longer supported",
"write `self: Box<Self>` instead"
),
ObsoleteManagedType => (
"`@` notation for managed pointers",
"use `Gc<T>` in `std::gc` instead"

View File

@ -45,7 +45,7 @@ use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfUniq, SelfValue};
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
@ -3826,10 +3826,11 @@ impl<'a> Parser<'a> {
// We need to make sure it isn't a type
if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
self.bump();
SelfUniq(self.expect_self_ident())
} else {
SelfStatic
drop(self.expect_self_ident());
let last_span = self.last_span;
self.obsolete(last_span, ObsoleteOwnedSelf)
}
SelfStatic
}
token::IDENT(..) if self.is_self_ident() => {
let self_ident = self.expect_self_ident();
@ -3877,7 +3878,10 @@ impl<'a> Parser<'a> {
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
mutbl_self = self.parse_mutability();
self.bump();
SelfUniq(self.expect_self_ident())
drop(self.expect_self_ident());
let last_span = self.last_span;
self.obsolete(last_span, ObsoleteOwnedSelf);
SelfStatic
}
_ => SelfStatic
};
@ -3921,7 +3925,6 @@ impl<'a> Parser<'a> {
}
SelfValue(id) => parse_remaining_arguments!(id),
SelfRegion(_,_,id) => parse_remaining_arguments!(id),
SelfUniq(id) => parse_remaining_arguments!(id),
SelfExplicit(_,id) => parse_remaining_arguments!(id),
};
@ -4042,7 +4045,8 @@ impl<'a> Parser<'a> {
/// Parse a method in a trait impl, starting with `attrs` attributes.
pub fn parse_method(&mut self,
already_parsed_attrs: Option<Vec<Attribute>>) -> Gc<Method> {
already_parsed_attrs: Option<Vec<Attribute>>)
-> Gc<Method> {
let next_attrs = self.parse_outer_attributes();
let attrs = match already_parsed_attrs {
Some(mut a) => { a.push_all_move(next_attrs); a }
@ -4080,6 +4084,11 @@ impl<'a> Parser<'a> {
let visa = self.parse_visibility();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi().unwrap_or(abi::C)
} else if attr::contains_name(attrs.as_slice(),
"rust_call_abi_hack") {
// FIXME(stage0, pcwalton): Remove this awful hack after a
// snapshot, and change to `extern "rust-call" fn`.
abi::RustCall
} else {
abi::Rust
};

View File

@ -1892,9 +1892,6 @@ impl<'a> State<'a> {
ast::SelfValue(_) => {
try!(word(&mut self.s, "self"));
}
ast::SelfUniq(_) => {
try!(word(&mut self.s, "~self"));
}
ast::SelfRegion(ref lt, m, _) => {
try!(word(&mut self.s, "&"));
try!(self.print_opt_lifetime(lt));

View File

@ -216,7 +216,7 @@ pub fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
explicit_self: &ExplicitSelf,
env: E) {
match explicit_self.node {
SelfStatic | SelfValue(_) | SelfUniq(_) => {},
SelfStatic | SelfValue(_) => {},
SelfRegion(ref lifetime, _, _) => {
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
}

@ -1 +1 @@
Subproject commit d66318a4aae089bae5c3c38ee42daaa1bd8fadb7
Subproject commit cd24b5c6633b27df2b84249a65a46a610b734494

View File

@ -658,13 +658,14 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
#if LLVM_VERSION_MINOR >= 5
extern "C" void*
LLVMRustOpenArchive(char *path) {
std::unique_ptr<MemoryBuffer> buf;
std::error_code err = MemoryBuffer::getFile(path, buf);
if (err) {
LLVMRustSetLastError(err.message().c_str());
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path);
if (!buf_or) {
LLVMRustSetLastError(buf_or.getError().message().c_str());
return NULL;
}
Archive *ret = new Archive(buf.release(), err);
std::error_code err;
Archive *ret = new Archive(std::move(buf_or.get()), err);
if (err) {
LLVMRustSetLastError(err.message().c_str());
return NULL;

View File

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
2014-07-21
2014-07-22

View File

@ -0,0 +1,56 @@
// 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.
struct Point<T> {
x: T,
y: T,
}
type PointF = Point<f32>;
struct Pair<T,U> {
x: T,
y: U,
}
type PairF<U> = Pair<f32,U>;
fn main() {
let pt = PointF {
//~^ ERROR expected f32 but found int
x: 1i,
y: 2i,
};
let pt2 = Point::<f32> {
//~^ ERROR expected f32 but found int
x: 3i,
y: 4i,
};
let pair = PairF {
//~^ ERROR expected f32 but found int
x: 5i,
y: 6i,
};
let pair2 = PairF::<int> {
//~^ ERROR expected f32 but found int
x: 7i,
y: 8i,
};
let pt3 = PointF::<int> {
//~^ ERROR wrong number of type arguments
x: 9i,
y: 10i,
};
}

View File

@ -0,0 +1,37 @@
// 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(overloaded_calls)]
use std::ops::FnMut;
fn call_f<F:FnMut<(),()>>(mut f: F) {
f();
}
fn f() {
println!("hello");
}
fn call_g<G:FnMut<(String,String),String>>(mut g: G, x: String, y: String)
-> String {
g(x, y)
}
fn g(x: String, y: String) -> String {
x.append(y.as_slice())
}
fn main() {
call_f(f);
assert_eq!(call_g(g, "foo".to_string(), "bar".to_string()).as_slice(),
"foobar");
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::str;
use std::{str, string};
static A: [u8, ..2] = ['h' as u8, 'i' as u8];
static B: &'static [u8, ..2] = &A;
@ -18,12 +18,12 @@ pub fn main() {
unsafe {
let foo = &A as *const u8;
assert_eq!(str::raw::from_utf8(A), "hi");
assert_eq!(str::raw::from_buf_len(foo, A.len()), "hi".to_string());
assert_eq!(str::raw::from_buf_len(C, B.len()), "hi".to_string());
assert_eq!(string::raw::from_buf_len(foo, A.len()), "hi".to_string());
assert_eq!(string::raw::from_buf_len(C, B.len()), "hi".to_string());
assert!(*C == A[0]);
assert!(*(&B[0] as *const u8) == A[0]);
let bar = str::raw::from_utf8(A).to_c_str();
assert_eq!(str::raw::from_c_str(bar.as_ptr()), "hi".to_string());
assert_eq!(bar.as_str(), "hi".to_c_str().as_str());
}
}