This is a reopening of #8182, although this removes any abuse of the compiler internals. Now it's just a pure syntax extension (hard coded what the attribute names are).
LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rs
LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \
- *.rs */*.rs */*/*.rs))
+ *.rs */*.rs */*/*.rs */*/*/*.rs))
DRIVER_CRATE := $(S)src/driver/driver.rs
All tasks are, by default, _linked_ to each other. That means that the fates
of all tasks are intertwined: if one fails, so do all the others.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task::spawn;
# use std::task;
# fn do_some_work() { loop { task::yield() } }
field (representing a successful result) or an `Err` result (representing
termination with an error).
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# fn some_condition() -> bool { false }
# fn calculate_result() -> int { 0 }
By default, task failure is _bidirectionally linked_, which means that if
either task fails, it kills the other one.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
-# fn sleep_forever() { loop { task::yield() } }
+# use std::comm::oneshot;
+# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }
# do task::try {
do spawn {
do spawn {
internally, with additional logic to wait for the child task to finish
before returning. Hence:
-~~~
+~~~{.xfail-test .linked-failure}
# use std::comm::{stream, Chan, Port};
+# use std::comm::oneshot;
# use std::task::{spawn, try};
# use std::task;
-# fn sleep_forever() { loop { task::yield() } }
+# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }
# do task::try {
let (receiver, sender): (Port<int>, Chan<int>) = stream();
do spawn { // Bidirectionally linked
Supervised task failure propagates across multiple generations even if
an intermediate generation has already exited:
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
-# fn sleep_forever() { loop { task::yield() } }
-# fn wait_for_a_while() { do 1000.times { task::yield() } }
+# use std::comm::oneshot;
+# fn sleep_forever() { loop { let (p, c) = oneshot::<()>(); p.recv(); } }
+# fn wait_for_a_while() { for _ in range(0, 1000u) { task::yield() } }
# do task::try::<int> {
do task::spawn_supervised {
do task::spawn_supervised {
Finally, tasks can be configured to not propagate failure to each
other at all, using `task::spawn_unlinked` for _isolated failure_.
-~~~
+~~~{.xfail-test .linked-failure}
# use std::task;
# fn random() -> uint { 100 }
-# fn sleep_for(i: uint) { do i.times { task::yield() } }
+# fn sleep_for(i: uint) { for _ in range(0, i) { task::yield() } }
# do task::try::<()> {
let (time1, time2) = (random(), random());
do task::spawn_unlinked {
the string in response. The child terminates when it receives `0`.
Here is the function that implements the child task:
-~~~~
+~~~{.xfail-test .linked-failure}
# use extra::comm::DuplexStream;
# use std::uint;
fn stringifier(channel: &DuplexStream<~str, uint>) {
Here is the code for the parent task:
-~~~~
+~~~{.xfail-test .linked-failure}
# use std::task::spawn;
# use std::uint;
# use extra::comm::DuplexStream;
impl Drop for TimeBomb {
fn drop(&self) {
- do self.explosivity.times {
+ for _ in range(0, self.explosivity) {
println("blam!");
}
}
compile_lib_path: getopts::opt_str(matches, "compile-lib-path"),
run_lib_path: getopts::opt_str(matches, "run-lib-path"),
rustc_path: opt_path(matches, "rustc-path"),
- clang_path: getopts::opt_maybe_str(matches, "clang-path").map(|s| Path(*s)),
- llvm_bin_path: getopts::opt_maybe_str(matches, "llvm-bin-path").map(|s| Path(*s)),
+ clang_path: getopts::opt_maybe_str(matches, "clang-path").map_move(|s| Path(s)),
+ llvm_bin_path: getopts::opt_maybe_str(matches, "llvm-bin-path").map_move(|s| Path(s)),
src_base: opt_path(matches, "src-base"),
build_base: opt_path(matches, "build-base"),
aux_base: opt_path(matches, "aux-base"),
} else {
None
},
- logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)),
- save_metrics: getopts::opt_maybe_str(matches, "save-metrics").map(|s| Path(*s)),
+ logfile: getopts::opt_maybe_str(matches, "logfile").map_move(|s| Path(s)),
+ save_metrics: getopts::opt_maybe_str(matches, "save-metrics").map_move(|s| Path(s)),
ratchet_metrics:
- getopts::opt_maybe_str(matches, "ratchet-metrics").map(|s| Path(*s)),
+ getopts::opt_maybe_str(matches, "ratchet-metrics").map_move(|s| Path(s)),
ratchet_noise_percent:
getopts::opt_maybe_str(matches,
- "ratchet-noise-percent").map(|s|
- f64::from_str(*s).unwrap()),
+ "ratchet-noise-percent").map_move(|s|
+ f64::from_str(s).unwrap()),
runtool: getopts::opt_maybe_str(matches, "runtool"),
rustcflags: getopts::opt_maybe_str(matches, "rustcflags"),
jit: getopts::opt_present(matches, "jit"),
round += 1;
}
- let mut expected =
- match props.pp_exact {
- Some(ref file) => {
+ let mut expected = match props.pp_exact {
+ Some(ref file) => {
let filepath = testfile.dir_path().push_rel(file);
io::read_whole_file_str(&filepath).unwrap()
}
}
}
}
+
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_arc_condvar_poison() {
unsafe {
// except according to those terms.
//! Base64 binary-to-text encoding
+use std::str;
/// Available encoding character sets
pub enum CharacterSet {
pub static MIME: Config =
Config {char_set: Standard, pad: true, line_length: Some(76)};
-static STANDARD_CHARS: [char, ..64] = [
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-];
-
-static URLSAFE_CHARS: [char, ..64] = [
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
-];
+static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "abcdefghijklmnopqrstuvwxyz",
+ "0123456789+/");
+
+static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "abcdefghijklmnopqrstuvwxyz",
+ "0123456789-_");
/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
* ~~~
*/
fn to_base64(&self, config: Config) -> ~str {
- let chars = match config.char_set {
+ let bytes = match config.char_set {
Standard => STANDARD_CHARS,
UrlSafe => URLSAFE_CHARS
};
- let mut s = ~"";
+ let mut v: ~[u8] = ~[];
let mut i = 0;
let mut cur_length = 0;
let len = self.len();
match config.line_length {
Some(line_length) =>
if cur_length >= line_length {
- s.push_str("\r\n");
+ v.push('\r' as u8);
+ v.push('\n' as u8);
cur_length = 0;
},
None => ()
(self[i + 2] as u32);
// This 24-bit number gets separated into four 6-bit numbers.
- s.push_char(chars[(n >> 18) & 63]);
- s.push_char(chars[(n >> 12) & 63]);
- s.push_char(chars[(n >> 6 ) & 63]);
- s.push_char(chars[n & 63]);
+ v.push(bytes[(n >> 18) & 63]);
+ v.push(bytes[(n >> 12) & 63]);
+ v.push(bytes[(n >> 6 ) & 63]);
+ v.push(bytes[n & 63]);
cur_length += 4;
i += 3;
match config.line_length {
Some(line_length) =>
if cur_length >= line_length {
- s.push_str("\r\n");
+ v.push('\r' as u8);
+ v.push('\n' as u8);
},
None => ()
}
0 => (),
1 => {
let n = (self[i] as u32) << 16;
- s.push_char(chars[(n >> 18) & 63]);
- s.push_char(chars[(n >> 12) & 63]);
+ v.push(bytes[(n >> 18) & 63]);
+ v.push(bytes[(n >> 12) & 63]);
if config.pad {
- s.push_str("==");
+ v.push('=' as u8);
+ v.push('=' as u8);
}
}
2 => {
let n = (self[i] as u32) << 16 |
(self[i + 1u] as u32) << 8;
- s.push_char(chars[(n >> 18) & 63]);
- s.push_char(chars[(n >> 12) & 63]);
- s.push_char(chars[(n >> 6 ) & 63]);
+ v.push(bytes[(n >> 18) & 63]);
+ v.push(bytes[(n >> 12) & 63]);
+ v.push(bytes[(n >> 6 ) & 63]);
if config.pad {
- s.push_char('=');
+ v.push('=' as u8);
}
}
_ => fail!("Algebra is broken, please alert the math police")
}
- s
- }
-}
-impl<'self> ToBase64 for &'self str {
- /**
- * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
- *
- *
- * # Example
- *
- * ~~~ {.rust}
- * extern mod extra;
- * use extra::base64::{ToBase64, standard};
- *
- * fn main () {
- * let str = "Hello, World".to_base64(standard);
- * printfln!("%s", str);
- * }
- * ~~~
- *
- */
- fn to_base64(&self, config: Config) -> ~str {
- self.as_bytes().to_base64(config)
+ unsafe {
+ str::raw::from_bytes_owned(v)
+ }
}
}
fn from_base64(&self) -> Result<~[u8], ~str>;
}
-impl<'self> FromBase64 for &'self [u8] {
+impl<'self> FromBase64 for &'self str {
/**
- * Convert base64 `u8` vector into u8 byte values.
- * Every 4 encoded characters is converted into 3 octets, modulo padding.
+ * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
+ * to the byte values it encodes.
+ *
+ * You can use the `from_bytes` function in `std::str`
+ * to turn a `[u8]` into a string with characters corresponding to those
+ * values.
*
* # Example
*
+ * This converts a string literal to base64 and back.
+ *
* ~~~ {.rust}
* extern mod extra;
* use extra::base64::{ToBase64, FromBase64, standard};
+ * use std::str;
*
* fn main () {
- * let str = [52,32].to_base64(standard);
- * printfln!("%s", str);
- * let bytes = str.from_base64();
+ * let hello_str = "Hello, World".to_base64(standard);
+ * printfln!("%s", hello_str);
+ * let bytes = hello_str.from_base64();
* printfln!("%?", bytes);
+ * let result_str = str::from_bytes(bytes);
+ * printfln!("%s", result_str);
* }
* ~~~
*/
let mut buf: u32 = 0;
let mut modulus = 0;
- let mut it = self.iter();
- for &byte in it {
- let ch = byte as char;
+ let mut it = self.byte_iter().enumerate();
+ for (idx, byte) in it {
let val = byte as u32;
- match ch {
+ match byte as char {
'A'..'Z' => buf |= val - 0x41,
'a'..'z' => buf |= val - 0x47,
'0'..'9' => buf |= val + 0x04,
'/'|'_' => buf |= 0x3F,
'\r'|'\n' => loop,
'=' => break,
- _ => return Err(~"Invalid Base64 character")
+ _ => return Err(fmt!("Invalid character '%c' at position %u",
+ self.char_at(idx), idx))
}
buf <<= 6;
}
}
- if !it.all(|&byte| {byte as char == '='}) {
- return Err(~"Invalid Base64 character");
+ for (idx, byte) in it {
+ if (byte as char) != '=' {
+ return Err(fmt!("Invalid character '%c' at position %u",
+ self.char_at(idx), idx));
+ }
}
match modulus {
}
}
-impl<'self> FromBase64 for &'self str {
- /**
- * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
- * to the byte values it encodes.
- *
- * You can use the `from_bytes` function in `std::str`
- * to turn a `[u8]` into a string with characters corresponding to those
- * values.
- *
- * # Example
- *
- * This converts a string literal to base64 and back.
- *
- * ~~~ {.rust}
- * extern mod extra;
- * use extra::base64::{ToBase64, FromBase64, standard};
- * use std::str;
- *
- * fn main () {
- * let hello_str = "Hello, World".to_base64(standard);
- * printfln!("%s", hello_str);
- * let bytes = hello_str.from_base64();
- * printfln!("%?", bytes);
- * let result_str = str::from_bytes(bytes);
- * printfln!("%s", result_str);
- * }
- * ~~~
- */
- fn from_base64(&self) -> Result<~[u8], ~str> {
- self.as_bytes().from_base64()
- }
-}
-
#[cfg(test)]
mod test {
use test::BenchHarness;
#[test]
fn test_to_base64_basic() {
- assert_eq!("".to_base64(STANDARD), ~"");
- assert_eq!("f".to_base64(STANDARD), ~"Zg==");
- assert_eq!("fo".to_base64(STANDARD), ~"Zm8=");
- assert_eq!("foo".to_base64(STANDARD), ~"Zm9v");
- assert_eq!("foob".to_base64(STANDARD), ~"Zm9vYg==");
- assert_eq!("fooba".to_base64(STANDARD), ~"Zm9vYmE=");
- assert_eq!("foobar".to_base64(STANDARD), ~"Zm9vYmFy");
+ assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
+ assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
+ assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
+ assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
+ assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
+ assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
+ assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
}
#[test]
fn test_to_base64_line_break() {
assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
.contains("\r\n"));
- assert_eq!("foobar".to_base64(Config {line_length: Some(4), ..STANDARD}),
+ assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
+ ..STANDARD}),
~"Zm9v\r\nYmFy");
}
#[test]
fn test_to_base64_padding() {
- assert_eq!("f".to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
- assert_eq!("fo".to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
+ assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
+ assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
}
#[test]
#[test]
fn test_from_base64_invalid_char() {
assert!("Zm$=".from_base64().is_err())
- assert!("Zg==$".from_base64().is_err());
+ assert!("Zg==$".from_base64().is_err());
}
#[test]
}
#[bench]
- pub fn to_base64(bh: & mut BenchHarness) {
+ pub fn bench_to_base64(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
do bh.iter {
- s.to_base64(STANDARD);
+ s.as_bytes().to_base64(STANDARD);
}
bh.bytes = s.len() as u64;
}
#[bench]
- pub fn from_base64(bh: & mut BenchHarness) {
+ pub fn bench_from_base64(bh: & mut BenchHarness) {
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
- let b = s.to_base64(STANDARD);
+ let b = s.as_bytes().to_base64(STANDARD);
do bh.iter {
b.from_base64();
}
/// Remove the first Node and return it, or None if the list is empty
#[inline]
fn pop_front_node(&mut self) -> Option<~Node<T>> {
- do self.list_head.take().map_consume |mut front_node| {
+ do self.list_head.take().map_move |mut front_node| {
self.length -= 1;
match front_node.next.take() {
Some(node) => self.list_head = link_with_prev(node, Rawlink::none()),
/// Remove the last Node and return it, or None if the list is empty
#[inline]
fn pop_back_node(&mut self) -> Option<~Node<T>> {
- do self.list_tail.resolve().map_consume_default(None) |tail| {
+ do self.list_tail.resolve().map_move_default(None) |tail| {
self.length -= 1;
self.list_tail = tail.prev;
match tail.prev.resolve() {
///
/// O(1)
fn pop_front(&mut self) -> Option<T> {
- self.pop_front_node().map_consume(|~Node{value, _}| value)
+ self.pop_front_node().map_move(|~Node{value, _}| value)
}
/// Add an element last in the list
///
/// O(1)
fn pop_back(&mut self) -> Option<T> {
- self.pop_back_node().map_consume(|~Node{value, _}| value)
+ self.pop_back_node().map_move(|~Node{value, _}| value)
}
}
/// If the list is empty, do nothing.
#[inline]
pub fn rotate_forward(&mut self) {
- do self.pop_back_node().map_consume |tail| {
+ do self.pop_back_node().map_move |tail| {
self.push_front_node(tail)
};
}
/// If the list is empty, do nothing.
#[inline]
pub fn rotate_backward(&mut self) {
- do self.pop_front_node().map_consume |head| {
+ do self.pop_front_node().map_move |head| {
self.push_back_node(head)
};
}
if self.nelem == 0 {
return None;
}
- do self.tail.resolve().map_consume |prev| {
+ do self.tail.resolve().map_move |prev| {
self.nelem -= 1;
self.tail = prev.prev;
&prev.value
if self.nelem == 0 {
return None;
}
- do self.head.resolve().map_consume |next| {
+ do self.head.resolve().map_move |next| {
self.nelem -= 1;
self.head = match next.next {
Some(ref mut node) => Rawlink::some(&mut **node),
if self.nelem == 0 {
return None;
}
- do self.tail.resolve().map_consume |prev| {
+ do self.tail.resolve().map_move |prev| {
self.nelem -= 1;
self.tail = prev.prev;
&mut prev.value
if self.nelem == 0 {
return None
}
- self.head.resolve().map_consume(|head| &mut head.value)
+ self.head.resolve().map_move(|head| &mut head.value)
}
}
pub mod semver;
pub mod fileinput;
pub mod flate;
+pub mod hex;
#[cfg(unicode)]
mod unicode;
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Hex binary-to-text encoding
+use std::str;
+use std::vec;
+
+/// A trait for converting a value to hexadecimal encoding
+pub trait ToHex {
+ /// Converts the value of `self` to a hex value, returning the owned
+ /// string.
+ fn to_hex(&self) -> ~str;
+}
+
+static CHARS: &'static[u8] = bytes!("0123456789abcdef");
+
+impl<'self> ToHex for &'self [u8] {
+ /**
+ * Turn a vector of `u8` bytes into a hexadecimal string.
+ *
+ * # Example
+ *
+ * ~~~ {.rust}
+ * extern mod extra;
+ * use extra::hex::ToHex;
+ *
+ * fn main () {
+ * let str = [52,32].to_hex();
+ * printfln!("%s", str);
+ * }
+ * ~~~
+ */
+ fn to_hex(&self) -> ~str {
+ let mut v = vec::with_capacity(self.len() * 2);
+ for &byte in self.iter() {
+ v.push(CHARS[byte >> 4]);
+ v.push(CHARS[byte & 0xf]);
+ }
+
+ unsafe {
+ str::raw::from_bytes_owned(v)
+ }
+ }
+}
+
+/// A trait for converting hexadecimal encoded values
+pub trait FromHex {
+ /// Converts the value of `self`, interpreted as hexadecimal encoded data,
+ /// into an owned vector of bytes, returning the vector.
+ fn from_hex(&self) -> Result<~[u8], ~str>;
+}
+
+impl<'self> FromHex for &'self str {
+ /**
+ * Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
+ * to the byte values it encodes.
+ *
+ * You can use the `from_bytes` function in `std::str`
+ * to turn a `[u8]` into a string with characters corresponding to those
+ * values.
+ *
+ * # Example
+ *
+ * This converts a string literal to hexadecimal and back.
+ *
+ * ~~~ {.rust}
+ * extern mod extra;
+ * use extra::hex::{FromHex, ToHex};
+ * use std::str;
+ *
+ * fn main () {
+ * let hello_str = "Hello, World".to_hex();
+ * printfln!("%s", hello_str);
+ * let bytes = hello_str.from_hex().unwrap();
+ * printfln!("%?", bytes);
+ * let result_str = str::from_bytes(bytes);
+ * printfln!("%s", result_str);
+ * }
+ * ~~~
+ */
+ fn from_hex(&self) -> Result<~[u8], ~str> {
+ // This may be an overestimate if there is any whitespace
+ let mut b = vec::with_capacity(self.len() / 2);
+ let mut modulus = 0;
+ let mut buf = 0u8;
+
+ for (idx, byte) in self.byte_iter().enumerate() {
+ buf <<= 4;
+
+ match byte as char {
+ 'A'..'F' => buf |= byte - ('A' as u8) + 10,
+ 'a'..'f' => buf |= byte - ('a' as u8) + 10,
+ '0'..'9' => buf |= byte - ('0' as u8),
+ ' '|'\r'|'\n'|'\t' => {
+ buf >>= 4;
+ loop
+ }
+ _ => return Err(fmt!("Invalid character '%c' at position %u",
+ self.char_at(idx), idx))
+ }
+
+ modulus += 1;
+ if modulus == 2 {
+ modulus = 0;
+ b.push(buf);
+ }
+ }
+
+ match modulus {
+ 0 => Ok(b),
+ _ => Err(~"Invalid input length")
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use test::BenchHarness;
+ use hex::*;
+
+ #[test]
+ pub fn test_to_hex() {
+ assert_eq!("foobar".as_bytes().to_hex(), ~"666f6f626172");
+ }
+
+ #[test]
+ pub fn test_from_hex_okay() {
+ assert_eq!("666f6f626172".from_hex().unwrap(),
+ "foobar".as_bytes().to_owned());
+ assert_eq!("666F6F626172".from_hex().unwrap(),
+ "foobar".as_bytes().to_owned());
+ }
+
+ #[test]
+ pub fn test_from_hex_odd_len() {
+ assert!("666".from_hex().is_err());
+ assert!("66 6".from_hex().is_err());
+ }
+
+ #[test]
+ pub fn test_from_hex_invalid_char() {
+ assert!("66y6".from_hex().is_err());
+ }
+
+ #[test]
+ pub fn test_from_hex_ignores_whitespace() {
+ assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(),
+ "foobar".as_bytes().to_owned());
+ }
+
+ #[test]
+ pub fn test_to_hex_all_bytes() {
+ for i in range(0, 256) {
+ assert_eq!([i as u8].to_hex(), fmt!("%02x", i as uint));
+ }
+ }
+
+ #[test]
+ pub fn test_from_hex_all_bytes() {
+ for i in range(0, 256) {
+ assert_eq!(fmt!("%02x", i as uint).from_hex().unwrap(), ~[i as u8]);
+ assert_eq!(fmt!("%02X", i as uint).from_hex().unwrap(), ~[i as u8]);
+ }
+ }
+
+ #[bench]
+ pub fn bench_to_hex(bh: & mut BenchHarness) {
+ let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
+ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
+ do bh.iter {
+ s.as_bytes().to_hex();
+ }
+ bh.bytes = s.len() as u64;
+ }
+
+ #[bench]
+ pub fn bench_from_hex(bh: & mut BenchHarness) {
+ let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
+ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
+ let b = s.as_bytes().to_hex();
+ do bh.iter {
+ b.from_hex();
+ }
+ bh.bytes = b.len() as u64;
+ }
+}
+++ /dev/null
-// Copyright 2012 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.
-
-/*! Composable internal iterators
-
-Internal iterators are functions implementing the protocol used by the `for` loop.
-
-An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
-breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
-tied to specific traits. For example:
-
-~~~ {.rust}
-println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
-~~~
-
-An external iterator object implementing the interface in the `iterator` module can be used as an
-internal iterator by calling the `advance` method. For example:
-
-~~~ {.rust}
-let xs = [0u, 1, 2, 3, 4, 5];
-let ys = [30, 40, 50, 60];
-let mut it = xs.iter().chain(ys.iter());
-for &x: &uint in it {
- println(x.to_str());
-}
-~~~
-
-Internal iterators provide a subset of the functionality of an external iterator. It's not possible
-to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
-much easier to implement.
-
-*/
-
-use std::vec;
-use std::cmp::Ord;
-use std::option::{Option, Some, None};
-use std::num::{One, Zero};
-use std::ops::{Add, Mul};
-
-#[allow(missing_doc)]
-pub trait FromIter<T> {
- /// Build a container with elements from an internal iterator.
- ///
- /// # Example:
- ///
- /// ~~~ {.rust}
- /// let xs = ~[1, 2, 3];
- /// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
- /// assert_eq!(xs, ys);
- /// ~~~
- pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
-}
-
-/**
- * Return true if `predicate` is true for any values yielded by an internal iterator.
- *
- * Example:
- *
- * ~~~ {.rust}
- * let xs = ~[1u, 2, 3, 4, 5];
- * assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
- * assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
- * ~~~
- */
-#[inline]
-pub fn any<T>(predicate: &fn(T) -> bool,
- iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
- do iter |x| {
- predicate(x)
- }
-}
-
-/**
- * Return true if `predicate` is true for all values yielded by an internal iterator.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
- * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
- * ~~~
- */
-#[inline]
-pub fn all<T>(predicate: &fn(T) -> bool,
- iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
- // If we ever break, iter will return false, so this will only return true
- // if predicate returns true for everything.
- iter(|x| predicate(x))
-}
-
-/**
- * Return the first element where `predicate` returns `true`. Return `None` if no element is found.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * let xs = ~[1u, 2, 3, 4, 5, 6];
- * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
- * ~~~
- */
-#[inline]
-pub fn find<T>(predicate: &fn(&T) -> bool,
- iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
- let mut ret = None;
- do iter |x| {
- if predicate(&x) {
- ret = Some(x);
- false
- } else { true }
- };
- ret
-}
-
-/**
- * Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
- * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
- * ~~~
- */
-#[inline]
-pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
- let mut result = None;
- do iter |x| {
- match result {
- Some(ref mut y) => {
- if x > *y {
- *y = x;
- }
- }
- None => result = Some(x)
- }
- true
- };
- result
-}
-
-/**
- * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
- * assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5);
- * ~~~
- */
-#[inline]
-pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
- let mut result = None;
- do iter |x| {
- match result {
- Some(ref mut y) => {
- if x < *y {
- *y = x;
- }
- }
- None => result = Some(x)
- }
- true
- };
- result
-}
-
-/**
- * Reduce an iterator to an accumulated value.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
- * ~~~
- */
-#[inline]
-pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
- let mut result = start;
- do iter |x| {
- f(&mut result, x);
- true
- };
- result
-}
-
-/**
- * Reduce an iterator to an accumulated value.
- *
- * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
- * forces the iterator to yield borrowed pointers.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
- * fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
- * }
- * ~~~
- */
-#[inline]
-pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
- let mut result = start;
- do iter |x| {
- f(&mut result, x);
- true
- };
- result
-}
-
-/**
- * Return the sum of the items yielding by an iterator.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * let xs: ~[int] = ~[1, 2, 3, 4];
- * assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
- * ~~~
- */
-#[inline]
-pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
- fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
-}
-
-/**
- * Return the product of the items yielded by an iterator.
- *
- * # Example:
- *
- * ~~~ {.rust}
- * let xs: ~[int] = ~[1, 2, 3, 4];
- * assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
- * ~~~
- */
-#[inline]
-pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
- fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
-}
-
-impl<T> FromIter<T> for ~[T]{
- #[inline]
- pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
- let mut v = ~[];
- do iter |x| { v.push(x); true };
- v
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use prelude::*;
-
- use int;
- use uint;
-
- #[test]
- fn test_from_iter() {
- let xs = ~[1, 2, 3];
- let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
- assert_eq!(xs, ys);
- }
-
- #[test]
- fn test_any() {
- let xs = ~[1u, 2, 3, 4, 5];
- assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
- assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
- }
-
- #[test]
- fn test_all() {
- assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
- assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
- }
-
- #[test]
- fn test_find() {
- let xs = ~[1u, 2, 3, 4, 5, 6];
- assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
- }
-
- #[test]
- fn test_max() {
- let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
- assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
- }
-
- #[test]
- fn test_min() {
- let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
- assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5);
- }
-
- #[test]
- fn test_fold() {
- assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
- }
-
- #[test]
- fn test_sum() {
- let xs: ~[int] = ~[1, 2, 3, 4];
- assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
- }
-
- #[test]
- fn test_empty_sum() {
- let xs: ~[int] = ~[];
- assert_eq!(do sum |f| { xs.iter().advance(f) }, 0);
- }
-
- #[test]
- fn test_product() {
- let xs: ~[int] = ~[1, 2, 3, 4];
- assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
- }
-
- #[test]
- fn test_empty_product() {
- let xs: ~[int] = ~[];
- assert_eq!(do product |f| { xs.iter().advance(f) }, 1);
- }
-}
pub fn new(v: ~[BigDigit]) -> BigUint {
// omit trailing zeros
- let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1);
+ let new_len = v.rposition(|n| *n != 0).map_move_default(0, |p| p + 1);
if new_len == v.len() { return BigUint { data: v }; }
let mut v = v;
start = 1;
}
return BigUint::parse_bytes(buf.slice(start, buf.len()), radix)
- .map_consume(|bu| BigInt::from_biguint(sign, bu));
+ .map_move(|bu| BigInt::from_biguint(sign, bu));
}
pub fn to_uint(&self) -> uint {
#[test]
fn test_from_str_radix() {
fn check(s: &str, ans: Option<int>) {
- let ans = ans.map(|&n| IntConvertible::from_int::<BigInt>(n));
+ let ans = ans.map_move(|n| IntConvertible::from_int::<BigInt>(n));
assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
}
check("10", Some(10));
let u: ~[int] = deq.iter().transform(|&x| x).collect();
assert_eq!(u, v);
- let mut seq = iterator::Counter::new(0u, 2).take_(256);
+ let mut seq = iterator::count(0u, 2).take_(256);
let deq: RingBuf<uint> = seq.collect();
for (i, &x) in deq.iter().enumerate() {
assert_eq!(2*i, x);
{
let values = replace(&mut self.v, ~[]);
values.consume_iter().enumerate().filter_map(|(i, v)| {
- v.map_consume(|v| (i, v))
+ v.map_move(|v| (i, v))
})
}
}
use sort;
use std::cmp;
+use std::hashmap;
use std::io;
use std::num;
w.write_str(histr);
}
+/// Returns a HashMap with the number of occurences of every element in the
+/// sequence that the iterator exposes.
+pub fn freq_count<T: Iterator<U>, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap<U, uint> {
+ let mut map = hashmap::HashMap::new::<U, uint>();
+ for elem in iter {
+ map.insert_or_update_with(elem, 1, |_, count| *count += 1);
+ }
+ map
+}
+
// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
#[cfg(test)]
// child task must have finished by the time try returns
do m.lock { }
}
+ #[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_mutex_killed_cond() {
// Getting killed during cond wait must not corrupt the mutex while
assert!(!woken);
}
}
+ #[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_mutex_killed_broadcast() {
use std::unstable::finally::Finally;
let inf = ti.unwrap();
let nc = if inf.strings.find_equiv(&("setaf")).is_some()
&& inf.strings.find_equiv(&("setab")).is_some() {
- inf.numbers.find_equiv(&("colors")).map_consume_default(0, |&n| n)
+ inf.numbers.find_equiv(&("colors")).map_move_default(0, |&n| n)
} else { 0 };
return Ok(Terminal {out: out, ti: inf, num_colors: nc});
cap = self.ti.strings.find_equiv(&("op"));
}
}
- let s = do cap.map_consume_default(Err(~"can't find terminfo capability `sgr0`")) |op| {
+ let s = do cap.map_move_default(Err(~"can't find terminfo capability `sgr0`")) |op| {
expand(*op, [], &mut Variables::new())
};
if s.is_ok() {
let run_ignored = getopts::opt_present(&matches, "ignored");
let logfile = getopts::opt_maybe_str(&matches, "logfile");
- let logfile = logfile.map(|s| Path(*s));
+ let logfile = logfile.map_move(|s| Path(s));
let run_benchmarks = getopts::opt_present(&matches, "bench");
let run_tests = ! run_benchmarks ||
getopts::opt_present(&matches, "test");
let ratchet_metrics = getopts::opt_maybe_str(&matches, "ratchet-metrics");
- let ratchet_metrics = ratchet_metrics.map(|s| Path(*s));
+ let ratchet_metrics = ratchet_metrics.map_move(|s| Path(s));
let ratchet_noise_percent = getopts::opt_maybe_str(&matches, "ratchet-noise-percent");
- let ratchet_noise_percent = ratchet_noise_percent.map(|s| f64::from_str(*s).unwrap());
+ let ratchet_noise_percent = ratchet_noise_percent.map_move(|s| f64::from_str(s).unwrap());
let save_metrics = getopts::opt_maybe_str(&matches, "save-metrics");
- let save_metrics = save_metrics.map(|s| Path(*s));
+ let save_metrics = save_metrics.map_move(|s| Path(s));
let test_opts = TestOpts {
filter: filter,
/// Advance the iterator to the next node (in order). If there are no more nodes, return `None`.
#[inline]
fn next(&mut self) -> Option<&'self T> {
- do self.iter.next().map |&(value, _)| { value }
+ do self.iter.next().map_move |(value, _)| { value }
}
}
fn digest_file(path: &Path) -> ~str {
let mut sha = ~Sha1::new();
let s = io::read_whole_file_str(path);
- (*sha).input_str(*s.get_ref());
+ (*sha).input_str(s.unwrap());
(*sha).result_str()
}
let pth = Path("foo.c");
{
let r = io::file_writer(&pth, [io::Create]);
- r.get_ref().write_str("int main() { return 0; }");
+ r.unwrap().write_str("int main() { return 0; }");
}
let cx = Context::new(RWArc::new(Database::new(Path("db.json"))),
fn find_cmd(command_string: &str) -> Option<Command> {
do COMMANDS.iter().find_ |command| {
command.cmd == command_string
- }.map_consume(|x| *x)
+ }.map_move(|x| *x)
}
fn cmd_help(args: &[~str]) -> ValidUsage {
} else if opt_present(matches, "emit-llvm") {
link::output_type_bitcode
} else { link::output_type_exe };
- let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot");
- let sysroot_opt = sysroot_opt.map(|m| @Path(*m));
+ let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot").map_move(|m| @Path(m));
let target_opt = getopts::opt_maybe_str(matches, "target");
let target_feature_opt = getopts::opt_maybe_str(matches, "target-feature");
let save_temps = getopts::opt_present(matches, "save-temps");
filter_item(cx, *a).chain(|x| fld.fold_item(x))
}.collect();
let filtered_view_items = do m.view_items.iter().filter_map |a| {
- filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
+ do filter_view_item(cx, a).map_move |x| {
+ fld.fold_view_item(x)
+ }
}.collect();
ast::_mod {
view_items: filtered_view_items,
) -> ast::foreign_mod {
let filtered_items = nm.items.iter().filter_map(|a| filter_foreign_item(cx, *a)).collect();
let filtered_view_items = do nm.view_items.iter().filter_map |a| {
- filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
+ do filter_view_item(cx, a).map_move |x| {
+ fld.fold_view_item(x)
+ }
}.collect();
ast::foreign_mod {
sort: nm.sort,
filter_stmt(cx, *a).chain(|stmt| fld.fold_stmt(stmt))
}.collect();
let filtered_view_items = do b.view_items.iter().filter_map |a| {
- filter_view_item(cx, a).map(|&x| fld.fold_view_item(x))
+ filter_view_item(cx, a).map(|x| fld.fold_view_item(*x))
}.collect();
ast::Block {
view_items: filtered_view_items,
}
pub fn find_type(&self, s: &str) -> Option<Type> {
- self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
+ self.named_types.find_equiv(&s).map_move(|x| Type::from_ref(*x))
}
// We have a depth count, because we seem to make infinite types.
pub fn find_extern_mod_stmt_cnum(cstore: &CStore,
emod_id: ast::NodeId)
-> Option<ast::CrateNum> {
- cstore.extern_mod_crate_map.find(&emod_id).map_consume(|x| *x)
+ cstore.extern_mod_crate_map.find(&emod_id).map_move(|x| *x)
}
#[deriving(Clone)]
}
fn get_provided_source(d: ebml::Doc, cdata: cmd) -> Option<ast::def_id> {
- do reader::maybe_get_doc(d, tag_item_method_provided_source).map |doc| {
- translate_def_id(cdata, reader::with_doc_data(*doc, parse_def_id))
+ do reader::maybe_get_doc(d, tag_item_method_provided_source).map_move |doc| {
+ translate_def_id(cdata, reader::with_doc_data(doc, parse_def_id))
}
}
}
fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
- reader::maybe_get_doc(item, tag_region_param).map(|doc| {
- let mut decoder = reader::Decoder(*doc);
+ do reader::maybe_get_doc(item, tag_region_param).map_move |doc| {
+ let mut decoder = reader::Decoder(doc);
Decodable::decode(&mut decoder)
- })
+ }
}
fn item_ty_param_count(item: ebml::Doc) -> uint {
tcx: ty::ctxt) -> Option<@ty::TraitRef>
{
let item_doc = lookup_item(id, cdata.data);
- do reader::maybe_get_doc(item_doc, tag_item_trait_ref).map |&tp| {
+ do reader::maybe_get_doc(item_doc, tag_item_trait_ref).map_move |tp| {
@doc_trait_ref(tp, tcx, cdata)
}
}
}
mc::cat_deref(cmt_base, _, _) => {
- opt_loan_path(cmt_base).map(
- |&lp| @LpExtend(lp, cmt.mutbl, LpDeref))
+ do opt_loan_path(cmt_base).map_move |lp| {
+ @LpExtend(lp, cmt.mutbl, LpDeref)
+ }
}
mc::cat_interior(cmt_base, ik) => {
- opt_loan_path(cmt_base).map(
- |&lp| @LpExtend(lp, cmt.mutbl, LpInterior(ik)))
+ do opt_loan_path(cmt_base).map_move |lp| {
+ @LpExtend(lp, cmt.mutbl, LpInterior(ik))
+ }
}
mc::cat_downcast(cmt_base) |
}
pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: &expr, b: &expr) -> Option<bool> {
- compare_lit_exprs(tcx, a, b).map(|&val| val == 0)
+ compare_lit_exprs(tcx, a, b).map_move(|val| val == 0)
}
pub fn lit_eq(a: &lit, b: &lit) -> Option<bool> {
- compare_const_vals(&lit_to_const(a), &lit_to_const(b)).map(|&val| val == 0)
+ compare_const_vals(&lit_to_const(a), &lit_to_const(b)).map_move(|val| val == 0)
}
return; // Didn't match.
}
- let item_index = self.item_refs.find(&value).map(|x| **x);
+ let item_index = self.item_refs.find(&value).map_move(|x| *x);
// prevent borrow checker from considering ^~~~~~~~~~~
// self to be borrowed (annoying)
match expr.node {
expr_path(_) => {
let def = self.tcx.def_map.get_copy(&expr.id);
- moves::moved_variable_node_id_from_def(def).map(
- |rdef| self.variable(*rdef, expr.span)
- )
+ do moves::moved_variable_node_id_from_def(def).map_move |rdef| {
+ self.variable(rdef, expr.span)
+ }
}
_ => None
}
-> Option<Variable> {
match self.tcx.def_map.find(&node_id) {
Some(&def) => {
- moves::moved_variable_node_id_from_def(def).map(
- |rdef| self.variable(*rdef, span)
- )
+ do moves::moved_variable_node_id_from_def(def).map_move |rdef| {
+ self.variable(rdef, span)
+ }
}
None => {
self.tcx.sess.span_bug(
pub fn opt_encl_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
//! Returns the narrowest scope that encloses `id`, if any.
- self.scope_map.find(&id).map(|&x| *x)
+ self.scope_map.find(&id).map_move(|x| *x)
}
pub fn encl_scope(&self, id: ast::NodeId) -> ast::NodeId {
/// the new variance is joined with the old variance.
pub fn add_rp(&mut self, id: ast::NodeId, variance: region_variance) {
assert!(id != 0);
- let old_variance = self.region_paramd_items.find(&id).
- map_consume(|x| *x);
+ let old_variance = self.region_paramd_items.find(&id).map_move(|x| *x);
let joined_variance = match old_variance {
None => variance,
Some(v) => join_variance(v, variance)
// item, it's ok
match def {
def_ty_param(did, _)
- if self.def_map.find(&did.node).map_consume(|x| *x)
+ if self.def_map.find(&did.node).map_move(|x| *x)
== Some(def_typaram_binder(item_id)) => {
// ok
}
static task_local_insn_key: local_data::Key<@~[&'static str]> = &local_data::Key;
pub fn with_insn_ctxt(blk: &fn(&[&'static str])) {
- let opt = local_data::get(task_local_insn_key, |k| k.map(|&k| *k));
+ let opt = local_data::get(task_local_insn_key, |k| k.map_move(|k| *k));
if opt.is_some() {
blk(*opt.unwrap());
}
impl Drop for _InsnCtxt {
fn drop(&self) {
do local_data::modify(task_local_insn_key) |c| {
- do c.map_consume |ctx| {
+ do c.map_move |ctx| {
let mut ctx = (*ctx).clone();
ctx.pop();
@ctx
pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
debug!("new InsnCtxt: %s", s);
do local_data::modify(task_local_insn_key) |c| {
- do c.map_consume |ctx| {
+ do c.map_move |ctx| {
let mut ctx = (*ctx).clone();
ctx.push(s);
@ctx
padding: Option<Type>,
coerce: bool) -> Type {
let size = ty_size(ty) * 8;
- let mut fields = padding.map_default(~[], |p| ~[*p]);
+ let mut fields = padding.map_move_default(~[], |p| ~[p]);
if coerce {
fields = vec::append(fields, coerce_to_int(size));
pub fn node_vtables(bcx: @mut Block, id: ast::NodeId)
-> Option<typeck::vtable_res> {
let raw_vtables = bcx.ccx().maps.vtable_map.find(&id);
- raw_vtables.map(
- |&vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
+ raw_vtables.map_move(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
}
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
pub fn task_llcx() -> ContextRef {
- let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
+ let opt = local_data::get(task_local_llcx_key, |k| k.map_move(|k| *k));
*opt.expect("task-local LLVMContextRef wasn't ever set!")
}
let offset = get_param(decl, first_real_arg + 1);
Ret(bcx, GEP(bcx, ptr, [offset]));
}
+ "offset_inbounds" => {
+ let ptr = get_param(decl, first_real_arg);
+ let offset = get_param(decl, first_real_arg + 1);
+ Ret(bcx, InBoundsGEP(bcx, ptr, [offset]));
+ }
"memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
"memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
"memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
data: Method(MethodData {
llfn: callee_fn.llfn,
llself: val,
- temp_cleanup: temp_cleanups.head_opt().map(|&v| *v),
+ temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
self_ty: node_id_type(bcx, this.id),
self_mode: mentry.self_mode,
})
data: Method(MethodData {
llfn: llfn_val,
llself: llself_val,
- temp_cleanup: temp_cleanups.head_opt().map(|&v| *v),
+ temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
self_ty: node_id_type(bcx, base.id),
self_mode: mentry.self_mode,
})
"visit_tydesc" | "forget" | "frame_address" |
"morestack_addr" => 0,
- "offset" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
+ "offset" | "offset_inbounds" |
+ "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
"memset32" | "memset64" => use_repr,
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
pub fn provided_source(cx: ctxt, id: ast::def_id)
-> Option<ast::def_id> {
- cx.provided_method_sources.find(&id).map(|x| **x)
+ cx.provided_method_sources.find(&id).map_move(|x| *x)
}
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@Method] {
Some(&ast_map::node_item(item, _)) => {
match item.node {
ast::item_struct(struct_def, _) => {
- struct_def.ctor_id.map(|ctor_id|
- ast_util::local_def(*ctor_id))
+ do struct_def.ctor_id.map_move |ctor_id| {
+ ast_util::local_def(ctor_id)
+ }
}
_ => cx.sess.bug("called struct_ctor_id on non-struct")
}
}
pub fn get_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
- do tcx.lang_items.require(TyDescStructLangItem).map |tydesc_lang_item| {
- tcx.intrinsic_defs.find_copy(tydesc_lang_item)
+ do tcx.lang_items.require(TyDescStructLangItem).map_move |tydesc_lang_item| {
+ tcx.intrinsic_defs.find_copy(&tydesc_lang_item)
.expect("Failed to resolve TyDesc")
}
}
pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
- do tcx.lang_items.require(OpaqueStructLangItem).map |opaque_lang_item| {
- tcx.intrinsic_defs.find_copy(opaque_lang_item)
+ do tcx.lang_items.require(OpaqueStructLangItem).map_move |opaque_lang_item| {
+ tcx.intrinsic_defs.find_copy(&opaque_lang_item)
.expect("Failed to resolve Opaque")
}
}
in_binding_rscope(rscope,
RegionParamNames(bound_lifetime_names.clone()));
- let opt_transformed_self_ty = opt_self_info.map(|&self_info| {
+ let opt_transformed_self_ty = do opt_self_info.map_move |self_info| {
transform_self_ty(this, &rb, self_info)
- });
+ };
let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, a, None));
None => {
fcx.infcx().type_error_message_str_with_expected(pat.span,
|expected, actual| {
- expected.map_default(~"", |e| {
+ expected.map_move_default(~"", |e| {
fmt!("mismatched types: expected `%s` but found %s",
- *e, actual)})},
+ e, actual)})},
Some(expected), ~"a structure pattern",
None);
fcx.write_error(pat.id);
_ => {
fcx.infcx().type_error_message_str_with_expected(pat.span,
|expected, actual| {
- expected.map_default(~"", |e| {
+ expected.map_move_default(~"", |e| {
fmt!("mismatched types: expected `%s` but found %s",
- *e, actual)})},
+ e, actual)})},
Some(expected), ~"an enum or structure pattern",
None);
fcx.write_error(pat.id);
_ => ty::terr_mismatch
};
fcx.infcx().type_error_message_str_with_expected(pat.span, |expected, actual| {
- expected.map_default(~"", |e| {
+ expected.map_move_default(~"", |e| {
fmt!("mismatched types: expected `%s` but found %s",
- *e, actual)})}, Some(expected), ~"tuple", Some(&type_error));
+ e, actual)})}, Some(expected), ~"tuple", Some(&type_error));
fcx.write_error(pat.id);
}
}
fcx.infcx().type_error_message_str_with_expected(
pat.span,
|expected, actual| {
- expected.map_default(~"", |e| {
+ expected.map_move_default(~"", |e| {
fmt!("mismatched types: expected `%s` but found %s",
- *e, actual)})},
+ e, actual)})},
Some(expected),
~"a vector pattern",
None);
fcx.infcx().type_error_message_str_with_expected(
span,
|expected, actual| {
- expected.map_default(~"", |e| {
+ expected.map_move_default(~"", |e| {
fmt!("mismatched types: expected `%s` but found %s",
- *e, actual)})},
+ e, actual)})},
Some(expected),
fmt!("%s pattern", match pointer_kind {
Managed => "an @-box",
|br| ty::re_free(ty::FreeRegion {scope_id: body.id,
bound_region: br}));
let opt_self_info =
- opt_self_info.map(
- |si| SelfInfo {self_ty: opt_self_ty.unwrap(), ..*si});
+ opt_self_info.map_move(
+ |si| SelfInfo {self_ty: opt_self_ty.unwrap(), .. si});
(isr, opt_self_info, fn_sig)
};
{
let method_def_id = local_def(method.id);
let method_ty = ty::method(ccx.tcx, method_def_id);
- let opt_self_info = method_ty.transformed_self_ty.map(|&ty| {
+ let opt_self_info = method_ty.transformed_self_ty.map_move(|ty| {
SelfInfo {self_ty: ty,
self_id: method.self_id,
span: method.explicit_self.span}
for p in fields.iter() {
let (id, sp) = *p;
- let orig_sp = field_names.find(&id).map_consume(|x| *x);
+ let orig_sp = field_names.find(&id).map_move(|x| *x);
match orig_sp {
Some(orig_sp) => {
tcx.sess.span_err(sp, fmt!("Duplicate field name %s in record type declaration",
check_bare_fn(ccx, decl, body, it.id, None);
}
ast::item_impl(_, _, _, ref ms) => {
- let rp = ccx.tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
+ let rp = ccx.tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
debug!("item_impl %s with id %d rp %?",
ccx.tcx.sess.str_of(it.ident), it.id, rp);
for m in ms.iter() {
for field in ast_fields.iter() {
let mut expected_field_type = ty::mk_err();
- let pair = class_field_map.find(&field.ident).
- map_consume(|x| *x);
+ let pair = class_field_map.find(&field.ident).map_move(|x| *x);
match pair {
None => {
tcx.sess.span_err(
if class_id.crate == ast::LOCAL_CRATE {
region_parameterized =
tcx.region_paramd_items.find(&class_id.node).
- map_consume(|x| *x);
+ map_move(|x| *x);
match tcx.items.find(&class_id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_struct(_, ref generics),
let raw_type;
if enum_id.crate == ast::LOCAL_CRATE {
region_parameterized =
- tcx.region_paramd_items.find(&enum_id.node).map_consume(|x| *x);
+ tcx.region_paramd_items.find(&enum_id.node).map_move(|x| *x);
match tcx.items.find(&enum_id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_enum(_, ref generics),
mutbl: ast::m_imm
}))
}
+ "offset_inbounds" => {
+ (1,
+ ~[
+ ty::mk_ptr(tcx, ty::mt {
+ ty: param(ccx, 0),
+ mutbl: ast::m_imm
+ }),
+ ty::mk_int()
+ ],
+ ty::mk_ptr(tcx, ty::mt {
+ ty: param(ccx, 0),
+ mutbl: ast::m_imm
+ }))
+ }
"memcpy32" => {
(1,
~[
debug!("replace_bound_regions_in_fn_sig(self_ty=%?, fn_sig=%s, \
all_tys=%?)",
- opt_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)),
+ opt_self_ty.map(|t| ppaux::ty_to_str(tcx, *t)),
ppaux::fn_sig_to_str(tcx, fn_sig),
- all_tys.map(|&t| ppaux::ty_to_str(tcx, t)));
+ all_tys.map(|t| ppaux::ty_to_str(tcx, *t)));
let _i = indenter();
let isr = do create_bound_region_mapping(tcx, isr, all_tys) |br| {
let new_fn_sig = ty::fold_sig(fn_sig, |t| {
replace_bound_regions(tcx, isr, t)
});
- let new_self_ty = opt_self_ty.map(|&t| replace_bound_regions(tcx, isr, t));
+ let new_self_ty = opt_self_ty.map(|t| replace_bound_regions(tcx, isr, *t));
debug!("result of replace_bound_regions_in_fn_sig: \
new_self_ty=%?, \
fn_sig=%s",
- new_self_ty.map(|&t| ppaux::ty_to_str(tcx, t)),
+ new_self_ty.map(|t| ppaux::ty_to_str(tcx, *t)),
ppaux::fn_sig_to_str(tcx, &new_fn_sig));
return (isr, new_self_ty, new_fn_sig);
// ty is the value supplied for the type parameter A...
let mut param_result = ~[];
- do ty::each_bound_trait_and_supertraits(
- tcx, type_param_bounds.trait_bounds) |trait_ref|
- {
+ do ty::each_bound_trait_and_supertraits(tcx, type_param_bounds.trait_bounds) |trait_ref| {
// ...and here trait_ref is each bound that was declared on A,
// expressed in terms of the type parameters.
trait_id: ast::NodeId)
{
let tcx = ccx.tcx;
- let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x);
+ let region_paramd = tcx.region_paramd_items.find(&trait_id).map_move(|x| *x);
match tcx.items.get_copy(&trait_id) {
ast_map::node_item(@ast::item {
node: ast::item_trait(ref generics, _, ref ms),
pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
let tcx = ccx.tcx;
- let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
+ let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
debug!("convert: item %s with id %d rp %?",
tcx.sess.str_of(it.ident), it.id, rp);
match it.node {
Some(&def) => return def,
_ => {}
}
- let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
+ let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
match it.node {
ast::item_trait(ref generics, _, _) => {
let self_ty = ty::mk_self(tcx, def_id);
Some(&tpt) => return tpt,
_ => {}
}
- let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
+ let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
match it.node {
ast::item_static(ref t, _, _) => {
let typ = ccx.to_ty(&empty_rscope, t);
None => { }
}
- let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
+ let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x);
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let tpt = {
err: Option<&ty::type_err>) {
debug!("hi! expected_ty = %?, actual_ty = %s", expected_ty, actual_ty);
- let error_str = err.map_default(~"", |t_err|
- fmt!(" (%s)",
- ty::type_err_to_str(self.tcx, *t_err)));
- let resolved_expected = expected_ty.map(|&e_ty|
- { self.resolve_type_vars_if_possible(e_ty) });
- if !resolved_expected.map_default(false, |&e| { ty::type_is_error(e) }) {
+ let error_str = do err.map_move_default(~"") |t_err| {
+ fmt!(" (%s)", ty::type_err_to_str(self.tcx, t_err))
+ };
+ let resolved_expected = do expected_ty.map_move |e_ty| {
+ self.resolve_type_vars_if_possible(e_ty)
+ };
+ if !resolved_expected.map_move_default(false, |e| { ty::type_is_error(e) }) {
match resolved_expected {
None => self.tcx.sess.span_err(sp,
fmt!("%s%s", mk_msg(None, actual_ty), error_str)),
let sopts = build_session_options(binary, matches, demitter);
let sess = build_session(sopts, demitter);
- let odir = getopts::opt_maybe_str(matches, "out-dir");
- let odir = odir.map(|o| Path(*o));
- let ofile = getopts::opt_maybe_str(matches, "o");
- let ofile = ofile.map(|o| Path(*o));
+ let odir = getopts::opt_maybe_str(matches, "out-dir").map_move(|o| Path(o));
+ let ofile = getopts::opt_maybe_str(matches, "o").map_move(|o| Path(o));
let cfg = build_configuration(sess, binary, &input);
- let pretty = getopts::opt_default(matches, "pretty", "normal").map(
- |a| parse_pretty(sess, *a));
+ let pretty = do getopts::opt_default(matches, "pretty", "normal").map_move |a| {
+ parse_pretty(sess, a)
+ };
match pretty {
Some::<pp_mode>(ppm) => {
pretty_print_input(sess, cfg, &input, ppm);
*/
pub fn monitor(f: ~fn(diagnostic::Emitter)) {
use std::comm::*;
+
+ // XXX: This is a hack for newsched since it doesn't support split stacks.
+ // rustc needs a lot of stack!
+ static STACK_SIZE: uint = 4000000;
+
let (p, ch) = stream();
let ch = SharedChan::new(ch);
let ch_capture = ch.clone();
- match do task::try || {
+ let mut task_builder = task::task();
+ task_builder.supervised();
+ task_builder.opts.stack_size = Some(STACK_SIZE);
+ match do task_builder.try {
let ch = ch_capture.clone();
let ch_capture = ch.clone();
// The 'diagnostics emitter'. Every error, warning, etc. should
let result = result::Ok(config);
let result = do result.chain |config| {
let output_dir = getopts::opt_maybe_str(matches, opt_output_dir());
- let output_dir = output_dir.map(|s| Path(*s));
+ let output_dir = output_dir.map_move(|s| Path(s));
result::Ok(Config {
output_dir: output_dir.unwrap_or_default(config.output_dir.clone()),
.. config
};
let result = do result.chain |config| {
let output_format = getopts::opt_maybe_str(matches, opt_output_format());
- do output_format.map_default(result::Ok(config.clone())) |output_format| {
- do parse_output_format(*output_format).chain |output_format| {
+ do output_format.map_move_default(result::Ok(config.clone())) |output_format| {
+ do parse_output_format(output_format).chain |output_format| {
result::Ok(Config {
output_format: output_format,
.. config.clone()
let result = do result.chain |config| {
let output_style =
getopts::opt_maybe_str(matches, opt_output_style());
- do output_style.map_default(result::Ok(config.clone())) |output_style| {
- do parse_output_style(*output_style).chain |output_style| {
+ do output_style.map_move_default(result::Ok(config.clone())) |output_style| {
+ do parse_output_style(output_style).chain |output_style| {
result::Ok(Config {
output_style: output_style,
.. config.clone()
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
// We expect two pages to have been written
- do 2.times {
+ for _ in range(0, 2u) {
po.recv();
}
}
~"#[link(name = \"core\")]; mod a { }");
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
- do 2.times {
+ for _ in range(0, 2u) {
let (page, markdown) = po.recv();
match page {
doc::CratePage(_) => {
}, _) => {
let bounds = pprust::generics_to_str(generics, extract::interner());
let bounds = if bounds.is_empty() { None } else { Some(bounds) };
- let trait_types = opt_trait_type.map_default(~[], |p| {
+ let trait_types = do opt_trait_type.map_default(~[]) |p| {
~[pprust::path_to_str(&p.path, extract::interner())]
- });
+ };
(bounds,
trait_types,
Some(pprust::ty_to_str(
}
}
}
- result = do blk.expr.map_consume |e| {
+ result = do blk.expr.map_move |e| {
do with_pp(intr) |pp, _| { pprust::print_expr(pp, e); }
};
}
}
}
- #[cfg(not(target_word_size = "32"))]
+ // FIXME: #7220 rusti on 32bit mac doesn't work.
+ // FIXME: #7641 rusti on 32bit linux cross compile doesn't work
+ // FIXME: #7115 re-enable once LLVM has been upgraded
+ #[cfg(thiswillneverbeacfgflag)]
fn run_program(prog: &str) {
let mut r = repl();
for cmd in prog.split_iter('\n') {
"the command '%s' failed", cmd);
}
}
- // FIXME: #7220 rusti on 32bit mac doesn't work
- // FIXME: #7641 rusti on 32bit linux cross compile doesn't work
- #[cfg(target_word_size = "32")]
fn run_program(_: &str) {}
+ #[ignore]
#[test]
fn super_basic() {
run_program("");
}
+ #[ignore]
#[test]
fn regression_5937() {
run_program("use std::hashmap;");
}
+ #[ignore]
#[test]
fn regression_5784() {
run_program("let a = 3;");
}
- #[test]
+ #[test] #[ignore]
fn new_tasks() {
+ // XXX: can't spawn new tasks because the JIT code is cleaned up
+ // after the main function is done.
run_program("
- use std::task::try;
- try( || println(\"Please don't segfault\") );
- do try { println(\"Please?\"); }
+ spawn( || println(\"Please don't segfault\") );
+ do spawn { println(\"Please?\"); }
");
}
+ #[ignore]
#[test]
fn inferred_integers_usable() {
run_program("let a = 2;\n()\n");
");
}
+ #[ignore]
#[test]
fn local_variables_allow_shadowing() {
run_program("
");
}
+ #[ignore]
#[test]
fn string_usable() {
run_program("
");
}
+ #[ignore]
#[test]
fn vectors_usable() {
run_program("
");
}
+ #[ignore]
#[test]
fn structs_usable() {
run_program("
");
}
+ #[ignore]
#[test]
fn mutable_variables_work() {
run_program("
");
}
+ #[ignore]
#[test]
fn functions_saved() {
run_program("
");
}
+ #[ignore]
#[test]
fn modules_saved() {
run_program("
");
}
+ #[ignore]
#[test]
fn multiple_functions() {
run_program("
");
}
+ #[ignore]
#[test]
fn multiple_items_same_name() {
run_program("
");
}
+ #[ignore]
#[test]
fn simultaneous_definition_and_expression() {
run_program("
");
}
+ #[ignore]
#[test]
fn exit_quits() {
let mut r = repl();
}
#[test]
+#[ignore(reason = "test not yet implemented")]
fn test_uninstall() {
let workspace = create_local_package(&PkgId::new("foo", &os::getcwd()));
let _output = command_line_test([~"info", ~"foo"], &workspace);
*(*self) > *(*other)
}
}
+
+#[cfg(not(test))]
+impl<'self, T: TotalOrd> TotalOrd for &'self T {
+ #[inline]
+ fn cmp(&self, other: & &'self T) -> Ordering { (**self).cmp(*other) }
+}
+
+#[cfg(not(test))]
+impl<'self, T: TotalEq> TotalEq for &'self T {
+ #[inline]
+ fn equals(&self, other: & &'self T) -> bool { (**self).equals(*other) }
+}
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
lexical ordering on a type `(int, int)`.
*/
-// used in deriving code in libsyntax
#[inline]
pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
match o1 {
let len_buckets = self.buckets.len();
let bucket = self.buckets[idx].take();
- let value = do bucket.map_consume |bucket| {
+ let value = do bucket.map_move |bucket| {
bucket.value
};
impl<K: Hash + Eq, V: Clone> HashMap<K, V> {
/// Like `find`, but returns a copy of the value.
pub fn find_copy(&self, k: &K) -> Option<V> {
- self.find(k).map_consume(|v| (*v).clone())
+ self.find(k).map_move(|v| (*v).clone())
}
/// Like `get`, but returns a copy of the value.
*/
use cmp;
-use num::{Zero, One};
+use num::{Zero, One, Saturating};
use option::{Option, Some, None};
use ops::{Add, Mul};
use cmp::Ord;
/// ~~~ {.rust}
/// let xs = [2u, 3];
/// let ys = [0u, 1, 0, 1, 2];
- /// let mut it = xs.iter().flat_map_(|&x| Counter::new(0u, 1).take_(x));
+ /// let mut it = xs.iter().flat_map_(|&x| count(0u, 1).take_(x));
/// // Check that `it` has the same elements as `ys`
/// let mut i = 0;
/// for x: uint in it {
/// ~~~ {.rust}
/// use std::iterator::Counter;
///
- /// for i in Counter::new(0, 10) {
+ /// for i in count(0, 10) {
/// printfln!("%d", i);
/// }
/// ~~~
Some((y, y_val))
}
}
- }).map_consume(|(x, _)| x)
+ }).map_move(|(x, _)| x)
}
#[inline]
Some((y, y_val))
}
}
- }).map_consume(|(x, _)| x)
+ }).map_move(|(x, _)| x)
}
}
/// use std::iterator::Counter;
///
/// fn factorial(n: uint) -> uint {
- /// Counter::new(1u, 1).take_while(|&i| i <= n).product()
+ /// count(1u, 1).take_while(|&i| i <= n).product()
/// }
/// assert!(factorial(0) == 1);
/// assert!(factorial(1) == 1);
/// # Example
///
/// ~~~ {.rust}
- /// let a = Counter::new(1,1).take_(1);
+ /// let a = count(1,1).take_(1);
/// let mut cy = a.cycle();
/// assert_eq!(cy.next(), Some(1));
/// assert_eq!(cy.next(), Some(1));
let (a_lower, a_upper) = self.a.size_hint();
let (b_lower, b_upper) = self.b.size_hint();
- let lower = if uint::max_value - a_lower < b_lower {
- uint::max_value
- } else {
- a_lower + b_lower
- };
+ let lower = a_lower.saturating_add(b_lower);
let upper = match (a_upper, b_upper) {
- (Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
- (Some(x), Some(y)) => Some(x + y),
+ (Some(x), Some(y)) => Some(x.saturating_add(y)),
_ => None
};
#[inline]
fn indexable(&self) -> uint {
let (a, b) = (self.a.indexable(), self.b.indexable());
- let total = a + b;
- if total < a || total < b {
- uint::max_value
- } else {
- total
- }
+ a.saturating_add(b)
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
let (lower, upper) = self.iter.size_hint();
- let lower = if lower >= self.n { lower - self.n } else { 0 };
+ let lower = lower.saturating_sub(self.n);
let upper = match upper {
- Some(x) if x >= self.n => Some(x - self.n),
- Some(_) => Some(0),
+ Some(x) => Some(x.saturating_sub(self.n)),
None => None
};
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
#[inline]
fn indexable(&self) -> uint {
- let N = self.iter.indexable();
- if N < self.n {
- 0
- } else {
- N - self.n
- }
+ self.iter.indexable().saturating_sub(self.n)
}
#[inline]
impl<A, T: Iterator<A>> Iterator<A> for Take<T> {
#[inline]
fn next(&mut self) -> Option<A> {
- let next = self.iter.next();
if self.n != 0 {
self.n -= 1;
- next
+ self.iter.next()
} else {
None
}
return Some(x)
}
}
- match self.iter.next().map_consume(|x| (self.f)(x)) {
+ match self.iter.next().map_move(|x| (self.f)(x)) {
None => return self.backiter.chain_mut_ref(|it| it.next()),
next => self.frontiter = next,
}
fn size_hint(&self) -> (uint, Option<uint>) {
let (flo, fhi) = self.frontiter.map_default((0, Some(0)), |it| it.size_hint());
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
+ let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
- ((0, Some(0)), Some(a), Some(b)) => (flo + blo, Some(a + b)),
- _ => (flo + blo, None)
+ ((0, Some(0)), Some(a), Some(b)) => (lo, Some(a.saturating_add(b))),
+ _ => (lo, None)
}
}
}
y => return y
}
}
- match self.iter.next_back().map_consume(|x| (self.f)(x)) {
+ match self.iter.next_back().map_move(|x| (self.f)(x)) {
None => return self.frontiter.chain_mut_ref(|it| it.next_back()),
next => self.backiter = next,
}
step: A
}
-impl<A> Counter<A> {
- /// Creates a new counter with the specified start/step
- #[inline]
- pub fn new(start: A, step: A) -> Counter<A> {
- Counter{state: start, step: step}
- }
+/// Creates a new counter with the specified start/step
+#[inline]
+pub fn count<A>(start: A, step: A) -> Counter<A> {
+ Counter{state: start, step: step}
}
/// A range of numbers from [0, N)
#[test]
fn test_counter_from_iter() {
- let mut it = Counter::new(0, 5).take_(10);
+ let mut it = count(0, 5).take_(10);
let xs: ~[int] = FromIterator::from_iterator(&mut it);
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
}
}
assert_eq!(i, expected.len());
- let ys = Counter::new(30u, 10).take_(4);
+ let ys = count(30u, 10).take_(4);
let mut it = xs.iter().transform(|&x| x).chain_(ys);
let mut i = 0;
for x in it {
#[test]
fn test_filter_map() {
- let mut it = Counter::new(0u, 1u).take_(10)
+ let mut it = count(0u, 1u).take_(10)
.filter_map(|x| if x.is_even() { Some(x*x) } else { None });
assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
}
fn test_iterator_flat_map() {
let xs = [0u, 3, 6];
let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
- let mut it = xs.iter().flat_map_(|&x| Counter::new(x, 1).take_(3));
+ let mut it = xs.iter().flat_map_(|&x| count(x, 1).take_(3));
let mut i = 0;
for x in it {
assert_eq!(x, ys[i]);
#[test]
fn test_cycle() {
let cycle_len = 3;
- let it = Counter::new(0u, 1).take_(cycle_len).cycle();
+ let it = count(0u, 1).take_(cycle_len).cycle();
assert_eq!(it.size_hint(), (uint::max_value, None));
for (i, x) in it.take_(100).enumerate() {
assert_eq!(i % cycle_len, x);
}
- let mut it = Counter::new(0u, 1).take_(0).cycle();
+ let mut it = count(0u, 1).take_(0).cycle();
assert_eq!(it.size_hint(), (0, Some(0)));
assert_eq!(it.next(), None);
}
#[test]
fn test_iterator_size_hint() {
- let c = Counter::new(0, 1);
+ let c = count(0, 1);
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let v2 = &[10, 11, 12];
let vi = v.iter();
set(my_key, @~"parent data");
do task::spawn {
// TLS shouldn't carry over.
- assert!(get(my_key, |k| k.map(|&k| *k)).is_none());
+ assert!(get(my_key, |k| k.map_move(|k| *k)).is_none());
set(my_key, @~"child data");
- assert!(*(get(my_key, |k| k.map(|&k| *k)).unwrap()) ==
+ assert!(*(get(my_key, |k| k.map_move(|k| *k)).unwrap()) ==
~"child data");
// should be cleaned up for us
}
// Must work multiple times
- assert!(*(get(my_key, |k| k.map(|&k| *k)).unwrap()) == ~"parent data");
- assert!(*(get(my_key, |k| k.map(|&k| *k)).unwrap()) == ~"parent data");
- assert!(*(get(my_key, |k| k.map(|&k| *k)).unwrap()) == ~"parent data");
+ assert!(*(get(my_key, |k| k.map_move(|k| *k)).unwrap()) == ~"parent data");
+ assert!(*(get(my_key, |k| k.map_move(|k| *k)).unwrap()) == ~"parent data");
+ assert!(*(get(my_key, |k| k.map_move(|k| *k)).unwrap()) == ~"parent data");
}
#[test]
static my_key: Key<@~str> = &Key;
set(my_key, @~"first data");
set(my_key, @~"next data"); // Shouldn't leak.
- assert!(*(get(my_key, |k| k.map(|&k| *k)).unwrap()) == ~"next data");
+ assert!(*(get(my_key, |k| k.map_move(|k| *k)).unwrap()) == ~"next data");
}
#[test]
use ptr::to_unsafe_ptr;
-#[cfg(not(test))] use cmp::{Eq, Ord};
+#[cfg(not(test))] use cmp::*;
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
pub static RC_IMMORTAL : uint = 0x77777777;
fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
}
+#[cfg(not(test))]
+impl<T: TotalOrd> TotalOrd for @T {
+ #[inline]
+ fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalOrd> TotalOrd for @mut T {
+ #[inline]
+ fn cmp(&self, other: &@mut T) -> Ordering { (**self).cmp(*other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalEq> TotalEq for @T {
+ #[inline]
+ fn equals(&self, other: &@T) -> bool { (**self).equals(*other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalEq> TotalEq for @mut T {
+ #[inline]
+ fn equals(&self, other: &@mut T) -> bool { (**self).equals(*other) }
+}
#[test]
fn test() {
let x = @3;
fn is_zero(&self) -> bool { (**self).is_zero() }
}
+/// Saturating math operations
+pub trait Saturating: Int {
+ /// Saturating addition operator.
+ /// Returns a+b, saturating at the numeric bounds instead of overflowing.
+ #[inline]
+ fn saturating_add(self, v: Self) -> Self {
+ let x = self + v;
+ if v >= Zero::zero() {
+ if x < self {
+ // overflow
+ Bounded::max_value::<Self>()
+ } else { x }
+ } else {
+ if x > self {
+ // underflow
+ Bounded::min_value::<Self>()
+ } else { x }
+ }
+ }
+
+ /// Saturating subtraction operator.
+ /// Returns a-b, saturating at the numeric bounds instead of overflowing.
+ #[inline]
+ fn saturating_sub(self, v: Self) -> Self {
+ let x = self - v;
+ if v >= Zero::zero() {
+ if x > self {
+ // underflow
+ Bounded::min_value::<Self>()
+ } else { x }
+ } else {
+ if x < self {
+ // overflow
+ Bounded::max_value::<Self>()
+ } else { x }
+ }
+ }
+}
+
+impl Saturating for int {}
+impl Saturating for i8 {}
+impl Saturating for i16 {}
+impl Saturating for i32 {}
+impl Saturating for i64 {}
+impl Saturating for uint {}
+impl Saturating for u8 {}
+impl Saturating for u16 {}
+impl Saturating for u32 {}
+impl Saturating for u64 {}
+
/// Helper function for testing numeric operations
#[cfg(test)]
pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
assert_eq!(ten.rem(&two), ten % two);
}
-macro_rules! test_cast_20(
- ($_20:expr) => ({
- let _20 = $_20;
-
- assert_eq!(20u, _20.to_uint());
- assert_eq!(20u8, _20.to_u8());
- assert_eq!(20u16, _20.to_u16());
- assert_eq!(20u32, _20.to_u32());
- assert_eq!(20u64, _20.to_u64());
- assert_eq!(20i, _20.to_int());
- assert_eq!(20i8, _20.to_i8());
- assert_eq!(20i16, _20.to_i16());
- assert_eq!(20i32, _20.to_i32());
- assert_eq!(20i64, _20.to_i64());
- assert_eq!(20f, _20.to_float());
- assert_eq!(20f32, _20.to_f32());
- assert_eq!(20f64, _20.to_f64());
-
- assert_eq!(_20, NumCast::from(20u));
- assert_eq!(_20, NumCast::from(20u8));
- assert_eq!(_20, NumCast::from(20u16));
- assert_eq!(_20, NumCast::from(20u32));
- assert_eq!(_20, NumCast::from(20u64));
- assert_eq!(_20, NumCast::from(20i));
- assert_eq!(_20, NumCast::from(20i8));
- assert_eq!(_20, NumCast::from(20i16));
- assert_eq!(_20, NumCast::from(20i32));
- assert_eq!(_20, NumCast::from(20i64));
- assert_eq!(_20, NumCast::from(20f));
- assert_eq!(_20, NumCast::from(20f32));
- assert_eq!(_20, NumCast::from(20f64));
-
- assert_eq!(_20, cast(20u));
- assert_eq!(_20, cast(20u8));
- assert_eq!(_20, cast(20u16));
- assert_eq!(_20, cast(20u32));
- assert_eq!(_20, cast(20u64));
- assert_eq!(_20, cast(20i));
- assert_eq!(_20, cast(20i8));
- assert_eq!(_20, cast(20i16));
- assert_eq!(_20, cast(20i32));
- assert_eq!(_20, cast(20i64));
- assert_eq!(_20, cast(20f));
- assert_eq!(_20, cast(20f32));
- assert_eq!(_20, cast(20f64));
- })
-)
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ macro_rules! test_cast_20(
+ ($_20:expr) => ({
+ let _20 = $_20;
+
+ assert_eq!(20u, _20.to_uint());
+ assert_eq!(20u8, _20.to_u8());
+ assert_eq!(20u16, _20.to_u16());
+ assert_eq!(20u32, _20.to_u32());
+ assert_eq!(20u64, _20.to_u64());
+ assert_eq!(20i, _20.to_int());
+ assert_eq!(20i8, _20.to_i8());
+ assert_eq!(20i16, _20.to_i16());
+ assert_eq!(20i32, _20.to_i32());
+ assert_eq!(20i64, _20.to_i64());
+ assert_eq!(20f, _20.to_float());
+ assert_eq!(20f32, _20.to_f32());
+ assert_eq!(20f64, _20.to_f64());
+
+ assert_eq!(_20, NumCast::from(20u));
+ assert_eq!(_20, NumCast::from(20u8));
+ assert_eq!(_20, NumCast::from(20u16));
+ assert_eq!(_20, NumCast::from(20u32));
+ assert_eq!(_20, NumCast::from(20u64));
+ assert_eq!(_20, NumCast::from(20i));
+ assert_eq!(_20, NumCast::from(20i8));
+ assert_eq!(_20, NumCast::from(20i16));
+ assert_eq!(_20, NumCast::from(20i32));
+ assert_eq!(_20, NumCast::from(20i64));
+ assert_eq!(_20, NumCast::from(20f));
+ assert_eq!(_20, NumCast::from(20f32));
+ assert_eq!(_20, NumCast::from(20f64));
+
+ assert_eq!(_20, cast(20u));
+ assert_eq!(_20, cast(20u8));
+ assert_eq!(_20, cast(20u16));
+ assert_eq!(_20, cast(20u32));
+ assert_eq!(_20, cast(20u64));
+ assert_eq!(_20, cast(20i));
+ assert_eq!(_20, cast(20i8));
+ assert_eq!(_20, cast(20i16));
+ assert_eq!(_20, cast(20i32));
+ assert_eq!(_20, cast(20i64));
+ assert_eq!(_20, cast(20f));
+ assert_eq!(_20, cast(20f32));
+ assert_eq!(_20, cast(20f64));
+ })
+ )
+
+ #[test] fn test_u8_cast() { test_cast_20!(20u8) }
+ #[test] fn test_u16_cast() { test_cast_20!(20u16) }
+ #[test] fn test_u32_cast() { test_cast_20!(20u32) }
+ #[test] fn test_u64_cast() { test_cast_20!(20u64) }
+ #[test] fn test_uint_cast() { test_cast_20!(20u) }
+ #[test] fn test_i8_cast() { test_cast_20!(20i8) }
+ #[test] fn test_i16_cast() { test_cast_20!(20i16) }
+ #[test] fn test_i32_cast() { test_cast_20!(20i32) }
+ #[test] fn test_i64_cast() { test_cast_20!(20i64) }
+ #[test] fn test_int_cast() { test_cast_20!(20i) }
+ #[test] fn test_f32_cast() { test_cast_20!(20f32) }
+ #[test] fn test_f64_cast() { test_cast_20!(20f64) }
+ #[test] fn test_float_cast() { test_cast_20!(20f) }
+
+ #[test]
+ fn test_saturating_add_uint() {
+ use uint::max_value;
+ assert_eq!(3u.saturating_add(5u), 8u);
+ assert_eq!(3u.saturating_add(max_value-1), max_value);
+ assert_eq!(max_value.saturating_add(max_value), max_value);
+ assert_eq!((max_value-2).saturating_add(1), max_value-1);
+ }
+
+ #[test]
+ fn test_saturating_sub_uint() {
+ use uint::max_value;
+ assert_eq!(5u.saturating_sub(3u), 2u);
+ assert_eq!(3u.saturating_sub(5u), 0u);
+ assert_eq!(0u.saturating_sub(1u), 0u);
+ assert_eq!((max_value-1).saturating_sub(max_value), 0);
+ }
-#[test] fn test_u8_cast() { test_cast_20!(20u8) }
-#[test] fn test_u16_cast() { test_cast_20!(20u16) }
-#[test] fn test_u32_cast() { test_cast_20!(20u32) }
-#[test] fn test_u64_cast() { test_cast_20!(20u64) }
-#[test] fn test_uint_cast() { test_cast_20!(20u) }
-#[test] fn test_i8_cast() { test_cast_20!(20i8) }
-#[test] fn test_i16_cast() { test_cast_20!(20i16) }
-#[test] fn test_i32_cast() { test_cast_20!(20i32) }
-#[test] fn test_i64_cast() { test_cast_20!(20i64) }
-#[test] fn test_int_cast() { test_cast_20!(20i) }
-#[test] fn test_f32_cast() { test_cast_20!(20f32) }
-#[test] fn test_f64_cast() { test_cast_20!(20f64) }
-#[test] fn test_float_cast() { test_cast_20!(20f) }
+ #[test]
+ fn test_saturating_add_int() {
+ use int::{min_value,max_value};
+ assert_eq!(3i.saturating_add(5i), 8i);
+ assert_eq!(3i.saturating_add(max_value-1), max_value);
+ assert_eq!(max_value.saturating_add(max_value), max_value);
+ assert_eq!((max_value-2).saturating_add(1), max_value-1);
+ assert_eq!(3i.saturating_add(-5i), -2i);
+ assert_eq!(min_value.saturating_add(-1i), min_value);
+ assert_eq!((-2i).saturating_add(-max_value), min_value);
+ }
+
+ #[test]
+ fn test_saturating_sub_int() {
+ use int::{min_value,max_value};
+ assert_eq!(3i.saturating_sub(5i), -2i);
+ assert_eq!(min_value.saturating_sub(1i), min_value);
+ assert_eq!((-2i).saturating_sub(max_value), min_value);
+ assert_eq!(3i.saturating_sub(-5i), 8i);
+ assert_eq!(3i.saturating_sub(-(max_value-1)), max_value);
+ assert_eq!(max_value.saturating_sub(-max_value), max_value);
+ assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
+ }
+}
match *self { Some(ref mut x) => Some(f(x)), None => None }
}
+ /// Applies a function to the contained value or returns a default
+ #[inline]
+ pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
+ match *self { None => def, Some(ref t) => f(t) }
+ }
+
/// Maps a `Some` value from one type to another by a mutable reference,
/// or returns a default value.
#[inline]
/// As `map`, but consumes the option and gives `f` ownership to avoid
/// copying.
#[inline]
- pub fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
- match self { None => None, Some(v) => Some(f(v)) }
- }
-
- /// Applies a function to the contained value or returns a default
- #[inline]
- pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
- match *self { None => def, Some(ref t) => f(t) }
+ pub fn map_move<U>(self, f: &fn(T) -> U) -> Option<U> {
+ match self { Some(x) => Some(f(x)), None => None }
}
/// As `map_default`, but consumes the option and gives `f`
/// ownership to avoid copying.
#[inline]
- pub fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
- match self { None => def, Some(v) => f(v) }
+ pub fn map_move_default<U>(self, def: U, f: &fn(T) -> U) -> U {
+ match self { None => def, Some(t) => f(t) }
}
/// Take the value out of the option, leaving a `None` in its place.
util::replace(self, None)
}
- /// As `map_consume`, but swaps a None into the original option rather
- /// than consuming it by-value.
- #[inline]
- pub fn take_map<U>(&mut self, blk: &fn(T) -> U) -> Option<U> {
- self.take().map_consume(blk)
- }
-
- /// As `map_consume_default`, but swaps a None into the original option
- /// rather than consuming it by-value.
- #[inline]
- pub fn take_map_default<U> (&mut self, def: U, blk: &fn(T) -> U) -> U {
- self.take().map_consume_default(def, blk)
- }
-
/// Apply a function to the contained value or do nothing.
/// Returns true if the contained value was mutated.
pub fn mutate(&mut self, f: &fn(T) -> T) -> bool {
}
}
- do load_self().map |pth| {
- Path(*pth).dir_path()
- }
+ load_self().map_move(|path| Path(path).dir_path())
}
//! Operations on unique pointer types
-#[cfg(not(test))] use cmp::{Eq, Ord};
+#[cfg(not(test))] use cmp::*;
#[cfg(not(test))]
impl<T:Eq> Eq for ~T {
#[inline]
fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
}
+
+#[cfg(not(test))]
+impl<T: TotalOrd> TotalOrd for ~T {
+ #[inline]
+ fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalEq> TotalEq for ~T {
+ #[inline]
+ fn equals(&self, other: &~T) -> bool { (**self).equals(*other) }
+}
pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
pub use hash::Hash;
pub use iter::Times;
+pub use iterator::Extendable;
pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
pub use iterator::{ClonableIterator, OrdIterator};
pub use num::{Num, NumCast};
pub use ptr::RawPtr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
pub use str::{Str, StrVector, StrSlice, OwnedStr, NullTerminatedStr};
-pub use from_str::{FromStr};
+pub use from_str::FromStr;
pub use to_bytes::IterBytes;
pub use to_str::{ToStr, ToStrConsume};
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
fn is_not_null(&self) -> bool;
unsafe fn to_option(&self) -> Option<&T>;
fn offset(&self, count: int) -> Self;
+ unsafe fn offset_inbounds(self, count: int) -> Self;
}
/// Extension methods for immutable pointers
/// Calculates the offset from a pointer.
#[inline]
fn offset(&self, count: int) -> *T { offset(*self, count) }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end.
+ #[inline]
+ #[cfg(stage0)]
+ unsafe fn offset_inbounds(self, count: int) -> *T {
+ intrinsics::offset(self, count)
+ }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end.
+ #[inline]
+ #[cfg(not(stage0))]
+ unsafe fn offset_inbounds(self, count: int) -> *T {
+ intrinsics::offset_inbounds(self, count)
+ }
}
/// Extension methods for mutable pointers
/// Calculates the offset from a mutable pointer.
#[inline]
fn offset(&self, count: int) -> *mut T { mut_offset(*self, count) }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end. An arithmetic overflow is also
+ /// undefined behaviour.
+ ///
+ /// This method should be preferred over `offset` when the guarantee can be
+ /// satisfied, to enable better optimization.
+ #[inline]
+ #[cfg(stage0)]
+ unsafe fn offset_inbounds(self, count: int) -> *mut T {
+ intrinsics::offset(self as *T, count) as *mut T
+ }
+
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end. An arithmetic overflow is also
+ /// undefined behaviour.
+ ///
+ /// This method should be preferred over `offset` when the guarantee can be
+ /// satisfied, to enable better optimization.
+ #[inline]
+ #[cfg(not(stage0))]
+ unsafe fn offset_inbounds(self, count: int) -> *mut T {
+ intrinsics::offset_inbounds(self as *T, count) as *mut T
+ }
}
// Equality for pointers
}
}
+ /// Call a method based on a previous result
+ ///
+ /// If `self` is `Ok` then the value is extracted and passed to `op`
+ /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is
+ /// `Err` then it is immediately returned. This function can be used to
+ /// compose the results of two functions.
+ ///
+ /// Example:
+ ///
+ /// let res = do read_file(file).map_move |buf| {
+ /// parse_bytes(buf)
+ /// }
+ #[inline]
+ pub fn map_move<U>(self, op: &fn(T) -> U) -> Result<U,E> {
+ match self {
+ Ok(t) => Ok(op(t)),
+ Err(e) => Err(e)
+ }
+ }
+
+ /// Call a method based on a previous result
+ ///
+ /// If `self` is `Err` then the value is extracted and passed to `op`
+ /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is
+ /// `Ok` then it is immediately returned. This function can be used to pass
+ /// through a successful result while handling an error.
+ #[inline]
+ pub fn map_err_move<F>(self, op: &fn(E) -> F) -> Result<T,F> {
+ match self {
+ Ok(t) => Ok(t),
+ Err(e) => Err(op(e))
+ }
+ }
+
/// Call a method based on a previous result
///
/// If `self` is `Ok` then the value is extracted and passed to `op`
#[cfg(test)]
mod tests {
use super::*;
+
use either;
+ use str::OwnedStr;
pub fn op1() -> Result<int, ~str> { Ok(666) }
#[test]
pub fn test_impl_map() {
- assert_eq!(Ok::<~str, ~str>(~"a").map(|_x| ~"b"), Ok(~"b"));
- assert_eq!(Err::<~str, ~str>(~"a").map(|_x| ~"b"), Err(~"a"));
+ assert_eq!(Ok::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Ok(~"ba"));
+ assert_eq!(Err::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Err(~"a"));
}
#[test]
pub fn test_impl_map_err() {
- assert_eq!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b"), Ok(~"a"));
- assert_eq!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b"), Err(~"b"));
+ assert_eq!(Ok::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Ok(~"a"));
+ assert_eq!(Err::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Err(~"ba"));
+ }
+
+ #[test]
+ pub fn test_impl_map_move() {
+ assert_eq!(Ok::<~str, ~str>(~"a").map_move(|x| x + "b"), Ok(~"ab"));
+ assert_eq!(Err::<~str, ~str>(~"a").map_move(|x| x + "b"), Err(~"a"));
+ }
+
+ #[test]
+ pub fn test_impl_map_err_move() {
+ assert_eq!(Ok::<~str, ~str>(~"a").map_err_move(|x| x + "b"), Ok(~"a"));
+ assert_eq!(Err::<~str, ~str>(~"a").map_err_move(|x| x + "b"), Err(~"ab"));
}
#[test]
// Port is blocked. Wake it up.
let recvr = BlockedTask::cast_from_uint(task_as_state);
if do_resched {
- do recvr.wake().map_consume |woken_task| {
+ do recvr.wake().map_move |woken_task| {
Scheduler::run_task(woken_task);
};
} else {
// The port is blocked waiting for a message we will never send. Wake it.
assert!((*this.packet()).payload.is_none());
let recvr = BlockedTask::cast_from_uint(task_as_state);
- do recvr.wake().map_consume |woken_task| {
+ do recvr.wake().map_move |woken_task| {
Scheduler::run_task(woken_task);
};
}
//! Runtime environment settings
+use from_str::FromStr;
use libc::{size_t, c_char, c_int};
+use option::{Some, None};
+use os;
+
+// OLD RT stuff
pub struct Environment {
/// The number of threads to use by default
extern {
fn rust_get_rt_env() -> &Environment;
}
+
+// NEW RT stuff
+
+// Note that these are all accessed without any synchronization.
+// They are expected to be initialized once then left alone.
+
+static mut MIN_STACK: uint = 2000000;
+
+pub fn init() {
+ unsafe {
+ match os::getenv("RUST_MIN_STACK") {
+ Some(s) => match FromStr::from_str(s) {
+ Some(i) => MIN_STACK = i,
+ None => ()
+ },
+ None => ()
+ }
+ }
+}
+
+pub fn min_stack() -> uint {
+ unsafe { MIN_STACK }
+}
|| {
// Prefer to check tombstones that were there first,
// being "more fair" at the expense of tail-recursion.
- others.take().map_consume_default(true, |f| f()) && {
+ others.take().map_move_default(true, |f| f()) && {
let mut inner = this.take().unwrap();
(!inner.any_child_failed) &&
- inner.child_tombstones.take_map_default(true, |f| f())
+ inner.child_tombstones.take().map_move_default(true, |f| f())
}
}
}
let others = Cell::new(other_tombstones); // :(
|| {
// Prefer fairness to tail-recursion, as in above case.
- others.take().map_consume_default(true, |f| f()) &&
+ others.take().map_move_default(true, |f| f()) &&
f.take()()
}
}
{ use util; util::ignore(group); }
// Step 1. Decide if we need to collect child failures synchronously.
- do self.on_exit.take_map |on_exit| {
+ do self.on_exit.take().map_move |on_exit| {
if success {
// We succeeded, but our children might not. Need to wait for them.
let mut inner = self.kill_handle.take_unwrap().unwrap();
success = false;
} else {
// Lockless access to tombstones protected by unwrap barrier.
- success = inner.child_tombstones.take_map_default(true, |f| f());
+ success = inner.child_tombstones.take().map_move_default(true, |f| f());
}
}
on_exit(success);
// Step 2. Possibly alert possibly-watching parent to failure status.
// Note that as soon as parent_handle goes out of scope, the parent
// can successfully unwrap its handle and collect our reported status.
- do self.watching_parent.take_map |mut parent_handle| {
+ do self.watching_parent.take().map_move |mut parent_handle| {
if success {
// Our handle might be None if we had an exit callback, and
// already unwrapped it. But 'success' being true means no
// child failed, so there's nothing to do (see below case).
- do self.kill_handle.take_map |own_handle| {
+ do self.kill_handle.take().map_move |own_handle| {
own_handle.reparent_children_to(&mut parent_handle);
};
} else {
// Test cases don't care about the spare killed flag.
fn make_kill_handle() -> KillHandle { let (h,_) = KillHandle::new(); h }
+ #[ignore(reason = "linked failure")]
#[test]
fn no_tombstone_success() {
do run_in_newsched_task {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_and_get_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_already_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_unkillably_and_get_killed() {
do with_test_task |mut task| {
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_on_pipe() {
// Tests the "killable" path of casting to/from uint.
}
}
+ #[ignore(reason = "linked failure")]
#[test]
fn block_unkillably_on_pipe() {
// Tests the "indestructible" path of casting to/from uint.
#[cfg(test)]
mod test {
+ use option::None;
use unstable::run_in_bare_thread;
use rt::test::*;
use super::*;
do run_in_bare_thread {
local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched();
- let task = ~Task::new_root(&mut sched.stack_pool, || {});
+ let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task);
let task: ~Task = Local::take();
cleanup_task(task);
do run_in_bare_thread {
local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched();
- let task = ~Task::new_root(&mut sched.stack_pool, || {});
+ let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task);
let task: ~Task = Local::take();
cleanup_task(task);
- let task = ~Task::new_root(&mut sched.stack_pool, || {});
+ let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task);
let task: ~Task = Local::take();
cleanup_task(task);
do run_in_bare_thread {
local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched();
- let task = ~Task::new_root(&mut sched.stack_pool, || {});
+ let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task);
unsafe {
do run_in_bare_thread {
local_ptr::init_tls_key();
let mut sched = ~new_test_uv_sched();
- let task = ~Task::new_root(&mut sched.stack_pool, || {});
+ let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
Local::put(task);
let res = do Local::borrow::<Task,bool> |_task| {
// Need to propagate the unsafety to `start`.
unsafe {
args::init(argc, argv);
+ env::init();
logging::init(crate_map);
rust_update_gc_metadata(crate_map);
}
// In the case where we do not use a main_thread scheduler we
// run the main task in one of our threads.
- let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
- main.take());
+ let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, main.take());
main_task.death.on_exit = Some(on_exit.take());
let main_task_cell = Cell::new(main_task);
let sched_cell = Cell::new(sched);
let thread = do Thread::start {
let mut sched = sched_cell.take();
- let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool) || {
+ let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool, None) || {
rtdebug!("boostraping a non-primary scheduler");
};
sched.bootstrap(bootstrap_task);
let mut main_sched = main_sched.unwrap();
let home = Sched(main_sched.make_handle());
- let mut main_task = ~Task::new_root_homed(&mut main_sched.stack_pool,
+ let mut main_task = ~Task::new_root_homed(&mut main_sched.stack_pool, None,
home, main.take());
main_task.death.on_exit = Some(on_exit.take());
rtdebug!("boostrapping main_task");
/// As enqueue_task, but with the possibility for the blocked task to
/// already have been killed.
pub fn enqueue_blocked_task(&mut self, blocked_task: BlockedTask) {
- do blocked_task.wake().map_consume |task| {
+ do blocked_task.wake().map_move |task| {
self.enqueue_task(task);
};
}
sched.enqueue_blocked_task(last_task);
}
};
- opt.map_consume(Local::put);
+ opt.map_move(Local::put);
}
// The primary function for changing contexts. In the current
let mut sched = ~new_test_uv_sched();
let sched_handle = sched.make_handle();
- let mut task = ~do Task::new_root_homed(&mut sched.stack_pool,
+ let mut task = ~do Task::new_root_homed(&mut sched.stack_pool, None,
Sched(sched_handle)) {
unsafe { *task_ran_ptr = true };
assert!(Task::on_appropriate_sched());
// 3) task not homed, sched requeues
// 4) task not home, send home
- let task1 = ~do Task::new_root_homed(&mut special_sched.stack_pool,
+ let task1 = ~do Task::new_root_homed(&mut special_sched.stack_pool, None,
Sched(t1_handle)) || {
rtassert!(Task::on_appropriate_sched());
};
rtdebug!("task1 id: **%u**", borrow::to_uint(task1));
- let task2 = ~do Task::new_root(&mut normal_sched.stack_pool) {
+ let task2 = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtassert!(Task::on_appropriate_sched());
};
- let task3 = ~do Task::new_root(&mut normal_sched.stack_pool) {
+ let task3 = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtassert!(Task::on_appropriate_sched());
};
- let task4 = ~do Task::new_root_homed(&mut special_sched.stack_pool,
+ let task4 = ~do Task::new_root_homed(&mut special_sched.stack_pool, None,
Sched(t4_handle)) {
rtassert!(Task::on_appropriate_sched());
};
let port = Cell::new(port);
let chan = Cell::new(chan);
- let normal_task = ~do Task::new_root(&mut normal_sched.stack_pool) {
+ let normal_task = ~do Task::new_root(&mut normal_sched.stack_pool, None) {
rtdebug!("*about to submit task2*");
Scheduler::run_task(task2.take());
rtdebug!("*about to submit task4*");
rtdebug!("normal task: %u", borrow::to_uint(normal_task));
- let special_task = ~do Task::new_root(&mut special_sched.stack_pool) {
+ let special_task = ~do Task::new_root(&mut special_sched.stack_pool, None) {
rtdebug!("*about to submit task1*");
Scheduler::run_task(task1.take());
rtdebug!("*about to submit task3*");
use ptr;
use prelude::*;
use option::{Option, Some, None};
+use rt::env;
use rt::kill::Death;
use rt::local::Local;
use rt::logging::StdErrLogger;
// A helper to build a new task using the dynamically found
// scheduler and task. Only works in GreenTask context.
- pub fn build_homed_child(f: ~fn(), home: SchedHome) -> ~Task {
+ pub fn build_homed_child(stack_size: Option<uint>, f: ~fn(), home: SchedHome) -> ~Task {
let f = Cell::new(f);
let home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap();
let new_task = ~running_task.new_child_homed(&mut sched.stack_pool,
+ stack_size,
home.take(),
f.take());
running_task.sched = Some(sched);
}
}
- pub fn build_child(f: ~fn()) -> ~Task {
- Task::build_homed_child(f, AnySched)
+ pub fn build_child(stack_size: Option<uint>, f: ~fn()) -> ~Task {
+ Task::build_homed_child(stack_size, f, AnySched)
}
- pub fn build_homed_root(f: ~fn(), home: SchedHome) -> ~Task {
+ pub fn build_homed_root(stack_size: Option<uint>, f: ~fn(), home: SchedHome) -> ~Task {
let f = Cell::new(f);
let home = Cell::new(home);
do Local::borrow::<Task, ~Task> |running_task| {
let mut sched = running_task.sched.take_unwrap();
let new_task = ~Task::new_root_homed(&mut sched.stack_pool,
- home.take(),
- f.take());
+ stack_size,
+ home.take(),
+ f.take());
running_task.sched = Some(sched);
new_task
}
}
- pub fn build_root(f: ~fn()) -> ~Task {
- Task::build_homed_root(f, AnySched)
+ pub fn build_root(stack_size: Option<uint>, f: ~fn()) -> ~Task {
+ Task::build_homed_root(stack_size, f, AnySched)
}
pub fn new_sched_task() -> Task {
}
pub fn new_root(stack_pool: &mut StackPool,
+ stack_size: Option<uint>,
start: ~fn()) -> Task {
- Task::new_root_homed(stack_pool, AnySched, start)
+ Task::new_root_homed(stack_pool, stack_size, AnySched, start)
}
pub fn new_child(&mut self,
stack_pool: &mut StackPool,
+ stack_size: Option<uint>,
start: ~fn()) -> Task {
- self.new_child_homed(stack_pool, AnySched, start)
+ self.new_child_homed(stack_pool, stack_size, AnySched, start)
}
pub fn new_root_homed(stack_pool: &mut StackPool,
+ stack_size: Option<uint>,
home: SchedHome,
start: ~fn()) -> Task {
Task {
death: Death::new(),
destroyed: false,
name: None,
- coroutine: Some(Coroutine::new(stack_pool, start)),
+ coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None,
task_type: GreenTask(Some(~home))
}
pub fn new_child_homed(&mut self,
stack_pool: &mut StackPool,
+ stack_size: Option<uint>,
home: SchedHome,
start: ~fn()) -> Task {
Task {
death: self.death.new_child(),
destroyed: false,
name: None,
- coroutine: Some(Coroutine::new(stack_pool, start)),
+ coroutine: Some(Coroutine::new(stack_pool, stack_size, start)),
sched: None,
task_type: GreenTask(Some(~home))
}
impl Coroutine {
- pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine {
- static MIN_STACK_SIZE: uint = 3000000; // XXX: Too much stack
-
+ pub fn new(stack_pool: &mut StackPool, stack_size: Option<uint>, start: ~fn()) -> Coroutine {
+ let stack_size = match stack_size {
+ Some(size) => size,
+ None => env::min_stack()
+ };
let start = Coroutine::build_start_wrapper(start);
- let mut stack = stack_pool.take_segment(MIN_STACK_SIZE);
+ let mut stack = stack_pool.take_segment(stack_size);
let initial_context = Context::new(start, &mut stack);
Coroutine {
current_stack_segment: stack,
do run_in_newsched_task() {
static key: local_data::Key<@~str> = &local_data::Key;
local_data::set(key, @~"data");
- assert!(*local_data::get(key, |k| k.map(|&k| *k)).unwrap() == ~"data");
+ assert!(*local_data::get(key, |k| k.map_move(|k| *k)).unwrap() == ~"data");
static key2: local_data::Key<@~str> = &local_data::Key;
local_data::set(key2, @~"data");
- assert!(*local_data::get(key2, |k| k.map(|&k| *k)).unwrap() == ~"data");
+ assert!(*local_data::get(key2, |k| k.map_move(|k| *k)).unwrap() == ~"data");
}
}
exit_handle.take().send(Shutdown);
rtassert!(exit_status);
};
- let mut task = ~Task::new_root(&mut sched.stack_pool, f);
+ let mut task = ~Task::new_root(&mut sched.stack_pool, None, f);
task.death.on_exit = Some(on_exit);
sched.bootstrap(task);
rtassert!(exit_status);
};
- let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
- f.take());
+ let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, None, f.take());
main_task.death.on_exit = Some(on_exit);
let mut threads = ~[];
while !scheds.is_empty() {
let mut sched = scheds.pop();
- let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool) || {
+ let bootstrap_task = ~do Task::new_root(&mut sched.stack_pool, None) || {
rtdebug!("bootstrapping non-primary scheduler");
};
let bootstrap_task_cell = Cell::new(bootstrap_task);
/// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) {
- Scheduler::run_task(Task::build_child(f));
+ Scheduler::run_task(Task::build_child(None, f));
}
/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) {
- Scheduler::run_task_later(Task::build_child(f));
+ Scheduler::run_task_later(Task::build_child(None, f));
}
pub fn spawntask_random(f: ~fn()) {
let chan = Cell::new(chan);
let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
- let mut new_task = Task::build_root(f);
+ let mut new_task = Task::build_root(None, f);
new_task.death.on_exit = Some(on_exit);
Scheduler::run_task(new_task);
pub fn with_test_task(blk: ~fn(~Task) -> ~Task) {
do run_in_bare_thread {
let mut sched = ~new_test_uv_sched();
- let task = blk(~Task::new_root(&mut sched.stack_pool, ||{}));
+ let task = blk(~Task::new_root(&mut sched.stack_pool, None, ||{}));
cleanup_task(task);
}
}
} else {
self.matches_index_iter(needle)
.next()
- .map_consume(|(start, _end)| start)
+ .map_move(|(start, _end)| start)
}
}
fn test_add() {
#[allow(unnecessary_allocation)];
macro_rules! t (
- ($s1:expr, $s2:expr, $e:expr) => {
- assert_eq!($s1 + $s2, $e);
- assert_eq!($s1.to_owned() + $s2, $e);
- assert_eq!($s1.to_managed() + $s2, $e);
- }
+ ($s1:expr, $s2:expr, $e:expr) => { {
+ let s1 = $s1;
+ let s2 = $s2;
+ let e = $e;
+ assert_eq!(s1 + s2, e.to_owned());
+ assert_eq!(s1.to_owned() + s2, e.to_owned());
+ assert_eq!(s1.to_managed() + s2, e.to_owned());
+ } }
);
- t!("foo", "bar", ~"foobar");
- t!("foo", @"bar", ~"foobar");
- t!("foo", ~"bar", ~"foobar");
- t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam");
- t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam");
- t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam");
+ t!("foo", "bar", "foobar");
+ t!("foo", @"bar", "foobar");
+ t!("foo", ~"bar", "foobar");
+ t!("ศไทย中", "华Việt Nam", "ศไทย中华Việt Nam");
+ t!("ศไทย中", @"华Việt Nam", "ศไทย中华Việt Nam");
+ t!("ศไทย中", ~"华Việt Nam", "ศไทย中华Việt Nam");
}
#[test]
indestructible: bool,
notify_chan: Option<Chan<TaskResult>>,
name: Option<~str>,
- sched: SchedOpts
+ sched: SchedOpts,
+ stack_size: Option<uint>
}
/**
indestructible: self.opts.indestructible,
notify_chan: notify_chan,
name: name,
- sched: self.opts.sched
+ sched: self.opts.sched,
+ stack_size: self.opts.stack_size
},
gen_body: gen_body,
can_not_copy: None,
indestructible: x.opts.indestructible,
notify_chan: notify_chan,
name: name,
- sched: x.opts.sched
+ sched: x.opts.sched,
+ stack_size: x.opts.stack_size
};
let f = match gen_body {
Some(gen) => {
name: None,
sched: SchedOpts {
mode: DefaultScheduler,
- }
+ },
+ stack_size: None
}
}
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_kill_unkillable_task() {
use rt::test::*;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_kill_rekillable_task() {
use rt::test::*;
#[cfg(test)]
fn block_forever() { let (po, _ch) = stream::<()>(); po.recv(); }
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port
use rt::test::run_in_newsched_task;
po.recv();
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails
use rt::test::run_in_newsched_task;
do spawn_unlinked { fail!(); }
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails
use rt::test::run_in_newsched_task;
do 16.times { task::yield(); }
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_unlinked_sup_fail_down() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_fail_down() { // parent fails; child fails
use rt::test::run_in_newsched_task;
assert!(result.is_err());
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_unsup_default_opts() { // parent fails; child fails
use rt::test::run_in_newsched_task;
// A couple bonus linked failure tests - testing for failure propagation even
// when the middle task exits successfully early before kill signals are sent.
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_grandchild() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_secondborn() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_failure_propagate_nephew_or_niece() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_linked_sup_propagate_sibling() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test]
#[ignore(cfg(windows))]
#[should_fail]
po.recv();
}
+#[ignore(reason = "linked failure")]
#[test]
#[ignore(cfg(windows))]
#[should_fail]
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_spawn_watched() {
use rt::test::run_in_newsched_task;
}
}
+#[ignore(reason = "linked failure")]
#[test] #[ignore(cfg(windows))]
fn test_indestructible() {
use rt::test::run_in_newsched_task;
OldTask(ptr) => rt::rust_task_kill_other(ptr),
NewTask(handle) => {
let mut handle = handle;
- do handle.kill().map_consume |killed_task| {
+ do handle.kill().map_move |killed_task| {
let killed_task = Cell::new(killed_task);
do Local::borrow::<Scheduler, ()> |sched| {
sched.enqueue_task(killed_task.take());
// Child task runs this code.
// If child data is 'None', the enlist is vacuously successful.
- let enlist_success = do child_data.take().map_consume_default(true) |child_data| {
+ let enlist_success = do child_data.take().map_move_default(true) |child_data| {
let child_data = Cell::new(child_data); // :(
do Local::borrow::<Task, bool> |me| {
let (child_tg, ancestors, is_main) = child_data.take();
let mut task = unsafe {
if opts.sched.mode != SingleThreaded {
if opts.watched {
- Task::build_child(child_wrapper)
+ Task::build_child(opts.stack_size, child_wrapper)
} else {
- Task::build_root(child_wrapper)
+ Task::build_root(opts.stack_size, child_wrapper)
}
} else {
// Creating a 1:1 task:thread ...
// Pin the new task to the new scheduler
let new_task = if opts.watched {
- Task::build_homed_child(child_wrapper, Sched(new_sched_handle))
+ Task::build_homed_child(opts.stack_size, child_wrapper, Sched(new_sched_handle))
} else {
- Task::build_homed_root(child_wrapper, Sched(new_sched_handle))
+ Task::build_homed_root(opts.stack_size, child_wrapper, Sched(new_sched_handle))
};
// Create a task that will later be used to join with the new scheduler
// thread when it is ready to terminate
let (thread_port, thread_chan) = oneshot();
let thread_port_cell = Cell::new(thread_port);
- let join_task = do Task::build_child() {
+ let join_task = do Task::build_child(None) {
rtdebug!("running join task");
let thread_port = thread_port_cell.take();
let thread: Thread = thread_port.recv();
let mut orig_sched_handle = orig_sched_handle_cell.take();
let join_task = join_task_cell.take();
- let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool) || {
- rtdebug!("bootstrapping a 1:1 scheduler");
+ let bootstrap_task = ~do Task::new_root(&mut new_sched.stack_pool, None) || {
+ rtdebug!("boostrapping a 1:1 scheduler");
};
new_sched.bootstrap(bootstrap_task);
// Even if the below code fails to kick the child off, we must
// send Something on the notify channel.
- let notifier = notify_chan.map_consume(|c| AutoNotify(c));
+ let notifier = notify_chan.map_move(|c| AutoNotify(c));
if enlist_many(OldTask(child), &child_arc, &mut ancestors) {
let group = @@mut Taskgroup(child_arc, ancestors, is_main, notifier);
/// Get the address of the `__morestack` stack growth function.
pub fn morestack_addr() -> *();
- /// Adjust a pointer by an offset.
+ /// Calculates the offset from a pointer.
///
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
pub fn offset<T>(dst: *T, offset: int) -> *T;
+ /// Calculates the offset from a pointer. The offset *must* be in-bounds of
+ /// the object, or one-byte-past-the-end. An arithmetic overflow is also
+ /// undefined behaviour.
+ ///
+ /// This intrinsic should be preferred over `offset` when the guarantee can
+ /// be satisfied, to enable better optimization.
+ #[cfg(not(stage0))]
+ pub fn offset_inbounds<T>(dst: *T, offset: int) -> *T;
+
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);
use os;
unsafe {
- let use_old_rt = os::getenv("RUST_NEWRT").is_none();
+ let use_old_rt = os::getenv("RUST_OLDRT").is_some();
if use_old_rt {
return rust_start(main as *c_void, argc as c_int, argv,
crate_map as *c_void) as int;
fn iter(self) -> VecIterator<'self, T> {
unsafe {
let p = vec::raw::to_ptr(self);
- VecIterator{ptr: p,
- end: (p as uint + self.len() *
- sys::nonzero_size_of::<T>()) as *T,
- lifetime: cast::transmute(p)}
+ if sys::size_of::<T>() == 0 {
+ VecIterator{ptr: p,
+ end: (p as uint + self.len()) as *T,
+ lifetime: cast::transmute(p)}
+ } else {
+ VecIterator{ptr: p,
+ end: p.offset_inbounds(self.len() as int),
+ lifetime: cast::transmute(p)}
+ }
}
}
fn mut_iter(self) -> VecMutIterator<'self, T> {
unsafe {
let p = vec::raw::to_mut_ptr(self);
- VecMutIterator{ptr: p,
- end: (p as uint + self.len() *
- sys::nonzero_size_of::<T>()) as *mut T,
- lifetime: cast::transmute(p)}
+ if sys::size_of::<T>() == 0 {
+ VecMutIterator{ptr: p,
+ end: (p as uint + self.len()) as *mut T,
+ lifetime: cast::transmute(p)}
+ } else {
+ VecMutIterator{ptr: p,
+ end: p.offset_inbounds(self.len() as int),
+ lifetime: cast::transmute(p)}
+ }
}
}
// same pointer.
cast::transmute(self.ptr as uint + 1)
} else {
- self.ptr.offset(1)
+ self.ptr.offset_inbounds(1)
};
Some(cast::transmute(old))
// See above for why 'ptr.offset' isn't used
cast::transmute(self.end as uint - 1)
} else {
- self.end.offset(-1)
+ self.end.offset_inbounds(-1)
};
Some(cast::transmute(self.end))
}
// fetch the SCTable from TLS, create one if it doesn't yet exist.
pub fn get_sctable() -> @mut SCTable {
static sctable_key: local_data::Key<@@mut SCTable> = &local_data::Key;
- match local_data::get(sctable_key, |k| k.map(|&k| *k)) {
+ match local_data::get(sctable_key, |k| k.map_move(|k| *k)) {
None => {
let new_table = @@mut new_sctable_internal();
local_data::set(sctable_key,new_table);
}
pub fn name_str_pair(&self) -> Option<(@str, @str)> {
- self.value_str().map_consume(|s| (self.name(), s))
+ self.value_str().map_move(|s| (self.name(), s))
}
}
let stderr = io::stderr();
if stderr.get_type() == io::Screen {
- let t = match local_data::get(tls_terminal, |v| v.map_consume(|&k|k)) {
+ let t = match local_data::get(tls_terminal, |v| v.map_move(|k| *k)) {
None => {
let t = term::Terminal::new(stderr);
let tls = @match t {
ConsMapChain(ref map,_) => map
};
// strip one layer of indirection off the pointer.
- map.find(key).map(|r| {**r})
+ map.find(key).map_move(|r| {*r})
}
// insert the binding into the top-level map
fn expr_if(&self, span: span,
cond: @ast::expr, then: @ast::expr, els: Option<@ast::expr>) -> @ast::expr {
- let els = els.map(|x| self.expr_block(self.block_expr(*x)));
+ let els = els.map_move(|x| self.expr_block(self.block_expr(x)));
self.expr(span, ast::expr_if(cond, self.block_expr(then), els))
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use ast;
use ast::{MetaItem, item, expr};
use codemap::span;
use ext::base::ExtCtxt;
}
-pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> @expr {
+pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> ast::Path {
let cnst = match cnst {
Less => "Less",
Equal => "Equal",
Greater => "Greater"
};
- cx.expr_path(
- cx.path_global(span,
- ~[cx.ident_of("std"),
- cx.ident_of("cmp"),
- cx.ident_of(cnst)]))
+ cx.path_global(span,
+ ~[cx.ident_of("std"),
+ cx.ident_of("cmp"),
+ cx.ident_of(cnst)])
}
pub fn cs_cmp(cx: @ExtCtxt, span: span,
substr: &Substructure) -> @expr {
+ let test_id = cx.ident_of("__test");
+ let equals_path = ordering_const(cx, span, Equal);
+ /*
+ Builds:
+
+ let __test = self_field1.cmp(&other_field2);
+ if other == ::std::cmp::Equal {
+ let __test = self_field2.cmp(&other_field2);
+ if __test == ::std::cmp::Equal {
+ ...
+ } else {
+ __test
+ }
+ } else {
+ __test
+ }
+
+ FIXME #6449: These `if`s could/should be `match`es.
+ */
cs_same_method_fold(
- // foldr (possibly) nests the matches in lexical_ordering better
+ // foldr nests the if-elses correctly, leaving the first field
+ // as the outermost one, and the last as the innermost.
false,
|cx, span, old, new| {
- cx.expr_call_global(span,
- ~[cx.ident_of("std"),
- cx.ident_of("cmp"),
- cx.ident_of("lexical_ordering")],
- ~[old, new])
+ // let __test = new;
+ // if __test == ::std::cmp::Equal {
+ // old
+ // } else {
+ // __test
+ // }
+
+ let assign = cx.stmt_let(span, false, test_id, new);
+
+ let cond = cx.expr_binary(span, ast::eq,
+ cx.expr_ident(span, test_id),
+ cx.expr_path(equals_path.clone()));
+ let if_ = cx.expr_if(span,
+ cond,
+ old, Some(cx.expr_ident(span, test_id)));
+ cx.expr_block(cx.block(span, ~[assign], Some(if_)))
},
- ordering_const(cx, span, Equal),
+ cx.expr_path(equals_path.clone()),
|cx, span, list, _| {
match list {
// an earlier nonmatching variant is Less than a
- // later one
+ // later one.
[(self_var, _, _),
- (other_var, _, _)] => ordering_const(cx, span,
- self_var.cmp(&other_var)),
+ (other_var, _, _)] => cx.expr_path(ordering_const(cx, span,
+ self_var.cmp(&other_var))),
_ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`")
}
},
fn noop_fold_arm(a: &arm, fld: @ast_fold) -> arm {
arm {
pats: a.pats.map(|x| fld.fold_pat(*x)),
- guard: a.guard.map(|x| fld.fold_expr(*x)),
+ guard: a.guard.map_move(|x| fld.fold_expr(x)),
body: fld.fold_block(&a.body),
}
}
pat_ident(
binding_mode,
fld.fold_path(pth),
- sub.map(|x| fld.fold_pat(*x))
+ sub.map_move(|x| fld.fold_pat(x))
)
}
pat_lit(e) => pat_lit(fld.fold_expr(e)),
pat_vec(ref before, ref slice, ref after) => {
pat_vec(
before.map(|x| fld.fold_pat(*x)),
- slice.map(|x| fld.fold_pat(*x)),
+ slice.map_move(|x| fld.fold_pat(x)),
after.map(|x| fld.fold_pat(*x))
)
}
expr_if(
fld.fold_expr(cond),
fld.fold_block(tr),
- fl.map(|x| fld.fold_expr(*x))
+ fl.map_move(|x| fld.fold_expr(x))
)
}
expr_while(cond, ref body) => {
expr_loop(ref body, opt_ident) => {
expr_loop(
fld.fold_block(body),
- opt_ident.map(|x| fld.fold_ident(*x))
+ opt_ident.map_move(|x| fld.fold_ident(x))
)
}
expr_match(expr, ref arms) => {
expr_path(ref pth) => expr_path(fld.fold_path(pth)),
expr_self => expr_self,
expr_break(ref opt_ident) => {
- expr_break(opt_ident.map(|x| fld.fold_ident(*x)))
+ expr_break(opt_ident.map_move(|x| fld.fold_ident(x)))
}
expr_again(ref opt_ident) => {
- expr_again(opt_ident.map(|x| fld.fold_ident(*x)))
+ expr_again(opt_ident.map_move(|x| fld.fold_ident(x)))
}
expr_ret(ref e) => {
- expr_ret(e.map(|x| fld.fold_expr(*x)))
+ expr_ret(e.map_move(|x| fld.fold_expr(x)))
}
expr_log(lv, e) => {
expr_log(
expr_struct(
fld.fold_path(path),
fields.map(|x| fold_field(*x)),
- maybe_expr.map(|x| fld.fold_expr(*x))
+ maybe_expr.map_move(|x| fld.fold_expr(x))
)
},
expr_paren(ex) => expr_paren(fld.fold_expr(ex))
fold_variant_arg(/*bad*/ (*x).clone())
})
}
- struct_variant_kind(struct_def) => {
+ struct_variant_kind(ref struct_def) => {
kind = struct_variant_kind(@ast::struct_def {
fields: struct_def.fields.iter()
.transform(|f| fld.fold_struct_field(*f)).collect(),
is_mutbl: l.is_mutbl,
ty: fld.fold_ty(&l.ty),
pat: fld.fold_pat(l.pat),
- init: l.init.map(|e| fld.fold_expr(*e)),
+ init: l.init.map_move(|e| fld.fold_expr(e)),
id: fld.new_id(l.id),
span: fld.new_span(l.span),
}
// If the path might have bounds on it, they should be parsed before
// the parameters, e.g. module::TraitName:B1+B2<T>
- before_tps.map_consume(|callback| callback());
+ before_tps.map_move(|callback| callback());
// Parse the (obsolete) trailing region parameter, if any, which will
// be written "foo/&x"
pub fn get_ident_interner() -> @ident_interner {
static key: local_data::Key<@@::parse::token::ident_interner> =
&local_data::Key;
- match local_data::get(key, |k| k.map(|&k| *k)) {
+ match local_data::get(key, |k| k.map_move(|k| *k)) {
Some(interner) => *interner,
None => {
let interner = mk_fresh_ident_interner();
{
let mut set = f();
do timed(&mut self.random_ints) {
- do num_keys.times {
+ for _ in range(0, num_keys) {
set.insert((rng.next() as uint) % rand_cap);
}
}
{
let mut set = f();
do timed(&mut self.random_strings) {
- do num_keys.times {
+ for _ in range(0, num_keys) {
let s = uint::to_str(rng.next() as uint);
set.insert(s);
}
let symbols = [" ", "░", "▒", "▓", "█", "█"];
let mut pixels = [0f32, ..256*256];
let n2d = ~Noise2DContext::new();
- do 100.times {
+ for _ in range(0, 100u) {
for y in range(0, 256) {
for x in range(0, 256) {
let v = n2d.get(
let mut creatures_met = 0;
// set up meetings...
- do nn.times {
+ for _ in range(0, nn) {
let fst_creature: CreatureInfo = from_creatures.recv();
let snd_creature: CreatureInfo = from_creatures.recv();
+// xfail-test reading from os::args()[1] - bogus!
+
use std::from_str::FromStr;
use std::os;
use std::vec::MutableVector;
+// xfail-test reading from os::args()[1] - bogus!
+
use std::cast::transmute;
use std::from_str::FromStr;
use std::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t};
let chars_left = n % LINE_LEN;
let mut buf = [0, ..LINE_LEN + 1];
- do lines.times {
+ for _ in range(0, lines) {
for i in range(0u, LINE_LEN) {
buf[i] = self.nextc();
}
fn unpack(&self, frame: i32) -> ~str {
let mut key = **self;
let mut result = ~[];
- do (frame as uint).times {
+ for _ in range(0, frame) {
result.push(unpack_symbol((key as u8) & 3));
key >>= 2;
}
let mut code = Code(0);
// Pull first frame.
- do (frame as uint).times {
+ for _ in range(0, frame) {
code = code.push_char(input[0]);
input = next_char(input);
}
+// xfail-test reading from os::args()[1] - bogus!
+
use std::cast::transmute;
use std::from_str::FromStr;
use std::libc::{STDOUT_FILENO, c_int, fdopen, fputc};
+// xfail-test reading from os::args()[1] - bogus!
+
use std::from_str::FromStr;
use std::os;
fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) {
let mut d = [ 0.0, ..3 ];
- do (steps as uint).times {
+ for _ in range(0, steps) {
for i in range(0u, N_BODIES) {
for j in range(i + 1, N_BODIES) {
d[0] = bodies[i].x[0] - bodies[j].x[0];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test reading from os::args()[1] - bogus!
+
use std::from_str::FromStr;
use std::os;
use std::vec;
let mut u = vec::from_elem(n, 1f64);
let mut v = u.clone();
let mut tmp = u.clone();
- do 8.times {
+ for _ in range(0, 8u) {
mult_AtAv(u, v, tmp);
mult_AtAv(v, u, tmp);
}
}
fn run(repeat: int, depth: int) {
- do (repeat as uint).times {
+ for _ in range(0, repeat) {
info!("starting %.4f", precise_time_s());
do task::try {
recurse_or_fail(depth, None)
let (po, ch) = stream();
let ch = SharedChan::new(ch);
- do num_tasks.times {
+ for _ in range(0, num_tasks) {
let ch = ch.clone();
- do task::spawn { // linked
+ let mut t = task::task();
+ t.linked();
+ t.unwatched();
+ do t.spawn { // linked
ch.send(());
let (p, _c) = stream::<()>();
p.recv(); // block forever
}
}
error!("Grandchild group getting started");
- do num_tasks.times {
+ for _ in range(0, num_tasks) {
// Make sure all above children are fully spawned; i.e., enlisted in
// their ancestor groups.
po.recv();
// except according to those terms.
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+// xfail-test broken in newrt?
// compile-flags:-Z extra-debug-info
// debugger:break zzz
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:explicit failure
// Testing that runtime failure doesn't cause callbacks to abort abnormally.
// Instead the failure will be delivered after the callbacks return.
// except according to those terms.
+// xfail-test linked failure
// error-pattern:1 == 2
extern mod extra;
// except according to those terms.
+// xfail-test linked failure
// error-pattern:fail
use std::comm;
// except according to those terms.
+// xfail-test linked failure
// error-pattern:fail
use std::comm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:1 == 2
use std::comm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// error-pattern:explicit
extern mod extra;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// error-pattern:goodfail
use std::comm;
+++ /dev/null
-// Copyright 2012 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.
-
-// xfail-test FIXME #7307
-// xfail-fast
-
-extern mod extra;
-use extra::oldmap::*;
-
-class cat : map<int, bool> {
- priv {
- // Yes, you can have negative meows
- let mut meows : int;
- fn meow() {
- self.meows += 1;
- error!("Meow %d", self.meows);
- if self.meows % 5 == 0 {
- self.how_hungry += 1;
- }
- }
- }
-
- let mut how_hungry : int;
- let name : str;
-
- new(in_x : int, in_y : int, in_name: str)
- { self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }
-
- fn speak() { self.meow(); }
-
- fn eat() -> bool {
- if self.how_hungry > 0 {
- error!("OM NOM NOM");
- self.how_hungry -= 2;
- return true;
- }
- else {
- error!("Not hungry!");
- return false;
- }
- }
-
- fn size() -> uint { self.meows as uint }
- fn insert(+k: int, +v: bool) -> bool {
- if v { self.meows += k; } else { self.meows -= k; };
- true
- }
- fn contains_key(&&k: int) -> bool { k <= self.meows }
- fn get(&&k:int) -> bool { k <= self.meows }
- fn [](&&k:int) -> bool { k <= self.meows }
- fn find(&&k:int) -> Option<bool> { Some(self.get(k)) }
- fn remove(&&k:int) -> Option<bool> { self.meows -= k; Some(true) }
- fn each(f: &fn(&&int, &&bool) -> bool) {
- let mut n = num::abs(self.meows);
- while n > 0 {
- if !f(n, true) { break; }
- n -= 1;
- }
- }
- fn each_key(&&f: &fn(&&int) -> bool) {
- for self.each |k, _v| { if !f(k) { break; } again;};
- }
- fn each_value(&&f: &fn(&&bool) -> bool) {
- for self.each |_k, v| { if !f(v) { break; } again;};
- }
- fn clear() { }
-}
-
-pub fn main() {
- let nyan : cat = cat(0, 2, "nyan");
- for _ in range(1u, 5u) { nyan.speak(); }
- // cat returns true if uint input is greater than
- // the number of meows so far
- assert!((nyan.get(1)));
- assert!((!nyan.get(10)));
-}
+++ /dev/null
-// Copyright 2012 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.
-
-// xfail-test FIXME #7305
-
-extern mod extra;
-use extra::oldmap::*;
-use vec::*;
-use dvec::{dvec, extensions};
-
-enum furniture { chair, couch, bed }
-enum body_part { finger, toe, nose, ear }
-
-trait noisy {
- fn speak() -> int;
-}
-
-trait scratchy {
- fn scratch() -> Option<furniture>;
-}
-
-trait bitey {
- fn bite() -> body_part;
-}
-
-fn vec_includes<T>(xs: ~[T], x: T) -> bool {
- for each(xs) |y| { if y == x { return true; }}
- return false;
-}
-
-// vtables other than the 1st one don't seem to work
-class cat : noisy, scratchy, bitey {
- priv {
- let meows : @mut uint;
- let scratched : dvec<furniture>;
- let bite_counts : hashmap<body_part, uint>;
-
- fn meow() -> uint {
- info!("Meow: %u", *self.meows);
- *self.meows += 1u;
- if *self.meows % 5u == 0u {
- *self.how_hungry += 1;
- }
- *self.meows
- }
- }
-
- let how_hungry : @mut int;
- let name : str;
-
- new(in_x : uint, in_y : int, in_name: str)
- { self.meows = @mut in_x; self.how_hungry = @mut in_y;
- self.name = in_name; self.scratched = dvec();
- let hsher: hashfn<body_part> = |p| int::hash(p as int);
- let eqer : eqfn<body_part> = |p, q| p == q;
- let t : hashmap<body_part, uint> =
- hashmap::<body_part, uint>(hsher, eqer);
- self.bite_counts = t;
- do iter(~[finger, toe, nose, ear]) |p| {
- self.bite_counts.insert(p, 0u);
- };
- }
-
- fn speak() -> int { self.meow() as int }
- fn meow_count() -> uint { *self.meows }
- fn scratch() -> Option<furniture> {
- let all = ~[chair, couch, bed];
- log(error, self.scratched);
- let mut rslt = None;
- for each(all) |thing| { if !self.scratched.contains(thing) {
- self.scratched.push(thing);
- return Some(thing); }}
- rslt
- }
- fn bite() -> body_part {
- error!("In bite()");
- let all = ~[toe, nose, ear];
- let mut min = finger;
- do iter(all) |next| {
- info!("min = %?", min);
- if self.bite_counts.get(next) < self.bite_counts.get(min) {
- min = next;
- }};
- self.bite_counts.insert(min, self.bite_counts.get(min) + 1u);
- info!("Bit %?", min);
- min
- }
-}
-
-fn annoy_neighbors<T:noisy>(critter: T) {
- for i in range(0u, 10u) {
- let what = critter.speak();
- info!("%u %d", i, what);
- }
-}
-
-fn bite_everything<T:bitey>(critter: T) -> bool {
- let mut left : ~[body_part] = ~[finger, toe, nose, ear];
- while left.len() > 0u {
- let part = critter.bite();
- info!("%? %?", left, part);
- if vec_includes(left, part) {
- left = vec::filter(left, |p| p != part );
- }
- else {
- return false;
- }
- }
- true
-}
-
-fn scratched_something<T:scratchy>(critter: T) -> bool {
- option::is_some(critter.scratch())
-}
-
-pub fn main() {
- let nyan : cat = cat(0u, 2, "nyan");
- annoy_neighbors(nyan as noisy);
- assert_eq!(nyan.meow_count(), 10u);
- assert!((bite_everything(nyan as bitey)));
- assert!((scratched_something(nyan as scratchy)));
-}
sum(y)
}
-/* FIXME #7304
-fn sum_const(y: &const [int]) -> int {
- sum(y)
-}
-*/
-
pub fn main() {}
-/* FIXME #7302
-fn foo(v: &const [uint]) -> ~[uint] {
- v.to_owned()
-}
-*/
-
fn bar(v: &mut [uint]) -> ~[uint] {
v.to_owned()
}
pub fn main() {
let mut the_vec = ~[1u, 2, 3, 100];
-// assert_eq!(the_vec.clone(), foo(the_vec));
assert_eq!(the_vec.clone(), bar(the_vec));
assert_eq!(the_vec.clone(), bip(the_vec));
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that the derived impls for the comparison traits shortcircuit
+// where possible, by having a type that fails when compared as the
+// second element, so this passes iff the instances shortcircuit.
+
+pub struct FailCmp;
+impl Eq for FailCmp {
+ fn eq(&self, _: &FailCmp) -> bool { fail!("eq") }
+}
+
+impl Ord for FailCmp {
+ fn lt(&self, _: &FailCmp) -> bool { fail!("lt") }
+}
+
+impl TotalEq for FailCmp {
+ fn equals(&self, _: &FailCmp) -> bool { fail!("equals") }
+}
+
+impl TotalOrd for FailCmp {
+ fn cmp(&self, _: &FailCmp) -> Ordering { fail!("cmp") }
+}
+
+#[deriving(Eq,Ord,TotalEq,TotalOrd)]
+struct ShortCircuit {
+ x: int,
+ y: FailCmp
+}
+
+fn main() {
+ let a = ShortCircuit { x: 1, y: FailCmp };
+ let b = ShortCircuit { x: 2, y: FailCmp };
+
+ assert!(a != b);
+ assert!(a < b);
+ assert!(!a.equals(&b));
+ assert_eq!(a.cmp(&b), ::std::cmp::Less);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-fast
// xfail-win32 #7999
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32 leaks
extern mod extra;
fn get(self) -> int;
}
-// FIXME #7302: Note: impl on a slice
+// Note: impl on a slice; we're checking that the pointers below
+// correctly get borrowed to `&`. (similar to impling for `int`, with
+// `&self` instead of `self`.)
impl<'self> get for &'self int {
fn get(self) -> int {
return *self;
info!("y=%d", y);
assert_eq!(y, 6);
- let x = ~6;
- let y = x.get();
- info!("y=%d", y);
- assert_eq!(y, 6);
-
let x = &6;
let y = x.get();
info!("y=%d", y);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
extern mod extra;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// A port of task-killjoin to use a class with a dtor to manage
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// xfail-test linked failure
// xfail-win32
// Create a task that is supervised by another task, join the supervised task