auto merge of #15949 : alexcrichton/rust/rollup, r=alexcrichton
This commit is contained in:
commit
4461f03a36
@ -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>;
|
||||
}
|
||||
~~~
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
})
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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, ()>
|
||||
}
|
||||
|
@ -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>;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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)]
|
||||
|
@ -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()
|
||||
|
@ -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>
|
||||
})
|
||||
|
@ -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>
|
||||
})
|
||||
|
@ -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>
|
||||
})
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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!("&{} {}self", *lt,
|
||||
MutableSpace(mtbl)).as_slice());
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
});
|
||||
|
@ -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};
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
}
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit d66318a4aae089bae5c3c38ee42daaa1bd8fadb7
|
||||
Subproject commit cd24b5c6633b27df2b84249a65a46a610b734494
|
@ -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;
|
||||
|
@ -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
|
||||
|
56
src/test/compile-fail/structure-constructor-type-mismatch.rs
Normal file
56
src/test/compile-fail/structure-constructor-type-mismatch.rs
Normal 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,
|
||||
};
|
||||
}
|
||||
|
37
src/test/run-pass/bare-fn-implements-fn-mut.rs
Normal file
37
src/test/run-pass/bare-fn-implements-fn-mut.rs
Normal 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");
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user