mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 14:01:51 +00:00
commit
578e680477
@ -2230,7 +2230,7 @@ Some examples of call expressions:
|
||||
# fn add(x: int, y: int) -> int { 0 }
|
||||
|
||||
let x: int = add(1, 2);
|
||||
let pi = FromStr::from_str::<f32>("3.14");
|
||||
let pi: Option<f32> = FromStr::from_str("3.14");
|
||||
~~~~
|
||||
|
||||
### Lambda expressions
|
||||
|
@ -420,6 +420,7 @@ mod test {
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_add_bytes_to_bits_tuple_overflow2() {
|
||||
add_bytes_to_bits_tuple::<u64>((Bounded::max_value::<u64>() - 1, 0), 0x8000000000000000);
|
||||
let value: u64 = Bounded::max_value();
|
||||
add_bytes_to_bits_tuple::<u64>((value - 1, 0), 0x8000000000000000);
|
||||
}
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
let mut m = DList::new::<~int>();
|
||||
let mut m: DList<~int> = DList::new();
|
||||
assert_eq!(m.pop_front(), None);
|
||||
assert_eq!(m.pop_back(), None);
|
||||
assert_eq!(m.pop_front(), None);
|
||||
@ -768,7 +768,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_rotate() {
|
||||
let mut n = DList::new::<int>();
|
||||
let mut n: DList<int> = DList::new();
|
||||
n.rotate_backward(); check_links(&n);
|
||||
assert_eq!(n.len(), 0);
|
||||
n.rotate_forward(); check_links(&n);
|
||||
@ -1033,7 +1033,7 @@ mod tests {
|
||||
|
||||
#[cfg(test)]
|
||||
fn fuzz_test(sz: int) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
let mut v = ~[];
|
||||
for i in range(0, sz) {
|
||||
check_links(&m);
|
||||
@ -1078,7 +1078,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
do b.iter {
|
||||
m.push_front(0);
|
||||
}
|
||||
@ -1086,7 +1086,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
do b.iter {
|
||||
m.push_back(0);
|
||||
}
|
||||
@ -1094,7 +1094,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_push_back_pop_back(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
do b.iter {
|
||||
m.push_back(0);
|
||||
m.pop_back();
|
||||
@ -1103,7 +1103,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_push_front_pop_front(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
do b.iter {
|
||||
m.push_front(0);
|
||||
m.pop_front();
|
||||
@ -1112,7 +1112,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_rotate_forward(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
m.push_front(0);
|
||||
m.push_front(1);
|
||||
do b.iter {
|
||||
@ -1122,7 +1122,7 @@ mod tests {
|
||||
|
||||
#[bench]
|
||||
fn bench_rotate_backward(b: &mut test::BenchHarness) {
|
||||
let mut m = DList::new::<int>();
|
||||
let mut m: DList<int> = DList::new();
|
||||
m.push_front(0);
|
||||
m.push_front(1);
|
||||
do b.iter {
|
||||
|
@ -25,13 +25,13 @@ pub mod rustrt {
|
||||
|
||||
#[link_name = "rustrt"]
|
||||
extern {
|
||||
pub fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
|
||||
pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
|
||||
src_buf_len: size_t,
|
||||
pout_len: *mut size_t,
|
||||
flags: c_int)
|
||||
-> *c_void;
|
||||
|
||||
pub fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
|
||||
pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void,
|
||||
src_buf_len: size_t,
|
||||
pout_len: *mut size_t,
|
||||
flags: c_int)
|
||||
|
@ -359,7 +359,7 @@ impl Integer for BigUint {
|
||||
|
||||
fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
|
||||
let mut m = a;
|
||||
let mut d = Zero::zero::<BigUint>();
|
||||
let mut d: BigUint = Zero::zero();
|
||||
let mut n = 1;
|
||||
while m >= b {
|
||||
let (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
|
||||
@ -411,8 +411,9 @@ impl Integer for BigUint {
|
||||
if shift == 0 {
|
||||
return (BigUint::new(d), One::one(), (*b).clone());
|
||||
}
|
||||
let one: BigUint = One::one();
|
||||
return (BigUint::from_slice(d).shl_unit(shift),
|
||||
One::one::<BigUint>().shl_unit(shift),
|
||||
one.shl_unit(shift),
|
||||
b.shl_unit(shift));
|
||||
}
|
||||
}
|
||||
@ -1168,8 +1169,8 @@ mod biguint_tests {
|
||||
#[test]
|
||||
fn test_shl() {
|
||||
fn check(s: &str, shift: uint, ans: &str) {
|
||||
let bu = (FromStrRadix::from_str_radix::<BigUint>(s, 16).unwrap() << shift)
|
||||
.to_str_radix(16);
|
||||
let opt_biguint: Option<BigUint> = FromStrRadix::from_str_radix(s, 16);
|
||||
let bu = (opt_biguint.unwrap() << shift).to_str_radix(16);
|
||||
assert_eq!(bu.as_slice(), ans);
|
||||
}
|
||||
|
||||
@ -1206,8 +1207,9 @@ mod biguint_tests {
|
||||
#[test]
|
||||
fn test_shr() {
|
||||
fn check(s: &str, shift: uint, ans: &str) {
|
||||
let bu = (FromStrRadix::from_str_radix::<BigUint>(s, 16).unwrap() >> shift)
|
||||
.to_str_radix(16);
|
||||
let opt_biguint: Option<BigUint> =
|
||||
FromStrRadix::from_str_radix(s, 16);
|
||||
let bu = (opt_biguint.unwrap() >> shift).to_str_radix(16);
|
||||
assert_eq!(bu.as_slice(), ans);
|
||||
}
|
||||
|
||||
@ -1445,11 +1447,18 @@ mod biguint_tests {
|
||||
|
||||
#[test]
|
||||
fn test_is_even() {
|
||||
assert!(FromStr::from_str::<BigUint>("1").unwrap().is_odd());
|
||||
assert!(FromStr::from_str::<BigUint>("2").unwrap().is_even());
|
||||
assert!(FromStr::from_str::<BigUint>("1000").unwrap().is_even());
|
||||
assert!(FromStr::from_str::<BigUint>("1000000000000000000000").unwrap().is_even());
|
||||
assert!(FromStr::from_str::<BigUint>("1000000000000000000001").unwrap().is_odd());
|
||||
let one: Option<BigUint> = FromStr::from_str("1");
|
||||
let two: Option<BigUint> = FromStr::from_str("2");
|
||||
let thousand: Option<BigUint> = FromStr::from_str("1000");
|
||||
let big: Option<BigUint> =
|
||||
FromStr::from_str("1000000000000000000000");
|
||||
let bigger: Option<BigUint> =
|
||||
FromStr::from_str("1000000000000000000001");
|
||||
assert!(one.unwrap().is_odd());
|
||||
assert!(two.unwrap().is_even());
|
||||
assert!(thousand.unwrap().is_even());
|
||||
assert!(big.unwrap().is_even());
|
||||
assert!(bigger.unwrap().is_odd());
|
||||
assert!((BigUint::from_uint(1) << 64).is_even());
|
||||
assert!(((BigUint::from_uint(1) << 64) + BigUint::from_uint(1)).is_odd());
|
||||
}
|
||||
@ -1534,15 +1543,19 @@ mod biguint_tests {
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(FromStrRadix::from_str_radix::<BigUint>("Z", 10), None);
|
||||
assert_eq!(FromStrRadix::from_str_radix::<BigUint>("_", 2), None);
|
||||
assert_eq!(FromStrRadix::from_str_radix::<BigUint>("-1", 10), None);
|
||||
let zed: Option<BigUint> = FromStrRadix::from_str_radix("Z", 10);
|
||||
assert_eq!(zed, None);
|
||||
let blank: Option<BigUint> = FromStrRadix::from_str_radix("_", 2);
|
||||
assert_eq!(blank, None);
|
||||
let minus_one: Option<BigUint> = FromStrRadix::from_str_radix("-1",
|
||||
10);
|
||||
assert_eq!(minus_one, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_factor() {
|
||||
fn factor(n: uint) -> BigUint {
|
||||
let mut f= One::one::<BigUint>();
|
||||
let mut f: BigUint = One::one();
|
||||
for i in range(2, n + 1) {
|
||||
// FIXME(#6102): Assignment operator for BigInt causes ICE
|
||||
// f *= BigUint::from_uint(i);
|
||||
@ -1939,17 +1952,24 @@ mod bigint_tests {
|
||||
|
||||
#[test]
|
||||
fn test_abs_sub() {
|
||||
assert_eq!((-One::one::<BigInt>()).abs_sub(&One::one()), Zero::zero());
|
||||
assert_eq!(One::one::<BigInt>().abs_sub(&One::one()), Zero::zero());
|
||||
assert_eq!(One::one::<BigInt>().abs_sub(&Zero::zero()), One::one());
|
||||
assert_eq!(One::one::<BigInt>().abs_sub(&-One::one::<BigInt>()),
|
||||
IntConvertible::from_int(2));
|
||||
let zero: BigInt = Zero::zero();
|
||||
let one: BigInt = One::one();
|
||||
assert_eq!((-one).abs_sub(&one), zero);
|
||||
let one: BigInt = One::one();
|
||||
let zero: BigInt = Zero::zero();
|
||||
assert_eq!(one.abs_sub(&one), zero);
|
||||
let one: BigInt = One::one();
|
||||
let zero: BigInt = Zero::zero();
|
||||
assert_eq!(one.abs_sub(&zero), one);
|
||||
let one: BigInt = One::one();
|
||||
assert_eq!(one.abs_sub(&-one), IntConvertible::from_int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_str_radix() {
|
||||
fn check(n: int, ans: &str) {
|
||||
assert!(ans == IntConvertible::from_int::<BigInt>(n).to_str_radix(10));
|
||||
let n: BigInt = IntConvertible::from_int(n);
|
||||
assert!(ans == n.to_str_radix(10));
|
||||
}
|
||||
check(10, "10");
|
||||
check(1, "1");
|
||||
@ -1962,7 +1982,10 @@ mod bigint_tests {
|
||||
#[test]
|
||||
fn test_from_str_radix() {
|
||||
fn check(s: &str, ans: Option<int>) {
|
||||
let ans = ans.map_move(|n| IntConvertible::from_int::<BigInt>(n));
|
||||
let ans = ans.map_move(|n| {
|
||||
let x: BigInt = IntConvertible::from_int(n);
|
||||
x
|
||||
});
|
||||
assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
|
||||
}
|
||||
check("10", Some(10));
|
||||
@ -1980,7 +2003,8 @@ mod bigint_tests {
|
||||
BigInt::new(Minus, ~[1, 1, 1]));
|
||||
assert!(-BigInt::new(Minus, ~[1, 1, 1]) ==
|
||||
BigInt::new(Plus, ~[1, 1, 1]));
|
||||
assert_eq!(-Zero::zero::<BigInt>(), Zero::zero::<BigInt>());
|
||||
let zero: BigInt = Zero::zero();
|
||||
assert_eq!(-zero, zero);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1992,7 +2016,7 @@ mod bench {
|
||||
use extra::test::BenchHarness;
|
||||
|
||||
fn factorial(n: uint) -> BigUint {
|
||||
let mut f = One::one::<BigUint>();
|
||||
let mut f: BigUint = One::one();
|
||||
for i in iterator::range_inclusive(1, n) {
|
||||
f = f * BigUint::from_uint(i);
|
||||
}
|
||||
@ -2000,8 +2024,8 @@ mod bench {
|
||||
}
|
||||
|
||||
fn fib(n: uint) -> BigUint {
|
||||
let mut f0 = Zero::zero::<BigUint>();
|
||||
let mut f1 = One::one::<BigUint>();
|
||||
let mut f0: BigUint = Zero::zero();
|
||||
let mut f1: BigUint = One::one();
|
||||
for _ in range(0, n) {
|
||||
let f2 = f0 + f1;
|
||||
f0 = util::replace(&mut f1, f2);
|
||||
|
@ -269,9 +269,13 @@ impl<T: FromStr + Clone + Integer + Ord>
|
||||
/// Parses `numer/denom`.
|
||||
fn from_str(s: &str) -> Option<Ratio<T>> {
|
||||
let split: ~[&str] = s.splitn_iter('/', 1).collect();
|
||||
if split.len() < 2 { return None; }
|
||||
do FromStr::from_str::<T>(split[0]).chain |a| {
|
||||
do FromStr::from_str::<T>(split[1]).chain |b| {
|
||||
if split.len() < 2 {
|
||||
return None
|
||||
}
|
||||
let a_option: Option<T> = FromStr::from_str(split[0]);
|
||||
do a_option.chain |a| {
|
||||
let b_option: Option<T> = FromStr::from_str(split[1]);
|
||||
do b_option.chain |b| {
|
||||
Some(Ratio::new(a.clone(), b.clone()))
|
||||
}
|
||||
}
|
||||
@ -282,10 +286,15 @@ impl<T: FromStrRadix + Clone + Integer + Ord>
|
||||
/// Parses `numer/denom` where the numbers are in base `radix`.
|
||||
fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
|
||||
let split: ~[&str] = s.splitn_iter('/', 1).collect();
|
||||
if split.len() < 2 { None }
|
||||
else {
|
||||
do FromStrRadix::from_str_radix::<T>(split[0], radix).chain |a| {
|
||||
do FromStrRadix::from_str_radix::<T>(split[1], radix).chain |b| {
|
||||
if split.len() < 2 {
|
||||
None
|
||||
} else {
|
||||
let a_option: Option<T> = FromStrRadix::from_str_radix(split[0],
|
||||
radix);
|
||||
do a_option.chain |a| {
|
||||
let b_option: Option<T> =
|
||||
FromStrRadix::from_str_radix(split[1], radix);
|
||||
do b_option.chain |b| {
|
||||
Some(Ratio::new(a.clone(), b.clone()))
|
||||
}
|
||||
}
|
||||
@ -496,7 +505,8 @@ mod test {
|
||||
#[test]
|
||||
fn test_from_str_fail() {
|
||||
fn test(s: &str) {
|
||||
assert_eq!(FromStr::from_str::<Rational>(s), None);
|
||||
let rational: Option<Rational> = FromStr::from_str(s);
|
||||
assert_eq!(rational, None);
|
||||
}
|
||||
|
||||
let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"];
|
||||
@ -536,7 +546,8 @@ mod test {
|
||||
#[test]
|
||||
fn test_from_str_radix_fail() {
|
||||
fn test(s: &str) {
|
||||
assert_eq!(FromStrRadix::from_str_radix::<Rational>(s, 3), None);
|
||||
let radix: Option<Rational> = FromStrRadix::from_str_radix(s, 3);
|
||||
assert_eq!(radix, None);
|
||||
}
|
||||
|
||||
let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"];
|
||||
|
@ -338,27 +338,36 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_empty_pop() { let mut heap = PriorityQueue::new::<int>(); heap.pop(); }
|
||||
fn test_empty_pop() {
|
||||
let mut heap: PriorityQueue<int> = PriorityQueue::new();
|
||||
heap.pop();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_maybe_pop() {
|
||||
let mut heap = PriorityQueue::new::<int>();
|
||||
let mut heap: PriorityQueue<int> = PriorityQueue::new();
|
||||
assert!(heap.maybe_pop().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_empty_top() { let empty = PriorityQueue::new::<int>(); empty.top(); }
|
||||
fn test_empty_top() {
|
||||
let empty: PriorityQueue<int> = PriorityQueue::new();
|
||||
empty.top();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_maybe_top() {
|
||||
let empty = PriorityQueue::new::<int>();
|
||||
let empty: PriorityQueue<int> = PriorityQueue::new();
|
||||
assert!(empty.maybe_top().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_empty_replace() { let mut heap = PriorityQueue::new(); heap.replace(5); }
|
||||
fn test_empty_replace() {
|
||||
let mut heap: PriorityQueue<int> = PriorityQueue::new();
|
||||
heap.replace(5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_iter() {
|
||||
|
@ -483,7 +483,7 @@ mod tests {
|
||||
#[bench]
|
||||
fn bench_new(b: &mut test::BenchHarness) {
|
||||
do b.iter {
|
||||
let _ = RingBuf::new::<u64>();
|
||||
let _: RingBuf<u64> = RingBuf::new();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ pub fn write_boxplot(w: @io::Writer, s: &Summary, width_hint: uint) {
|
||||
/// Returns a HashMap with the number of occurrences 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>();
|
||||
let mut map: hashmap::HashMap<U,uint> = hashmap::HashMap::new();
|
||||
for elem in iter {
|
||||
map.insert_or_update_with(elem, 1, |_, count| *count += 1);
|
||||
}
|
||||
|
@ -879,7 +879,8 @@ mod test_treemap {
|
||||
|
||||
#[test]
|
||||
fn find_empty() {
|
||||
let m = TreeMap::new::<int, int>(); assert!(m.find(&5) == None);
|
||||
let m: TreeMap<int,int> = TreeMap::new();
|
||||
assert!(m.find(&5) == None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1006,7 +1007,7 @@ mod test_treemap {
|
||||
|
||||
#[test]
|
||||
fn test_rand_int() {
|
||||
let mut map = TreeMap::new::<int, int>();
|
||||
let mut map: TreeMap<int,int> = TreeMap::new();
|
||||
let mut ctrl = ~[];
|
||||
|
||||
check_equal(ctrl, &map);
|
||||
|
@ -17,6 +17,7 @@ use syntax::attr;
|
||||
use syntax::codemap::dummy_sp;
|
||||
use syntax::codemap;
|
||||
use syntax::fold;
|
||||
use syntax::opt_vec;
|
||||
|
||||
static STD_VERSION: &'static str = "0.8-pre";
|
||||
|
||||
@ -90,12 +91,18 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
|
||||
let prelude_path = ast::Path {
|
||||
span: dummy_sp(),
|
||||
global: false,
|
||||
idents: ~[
|
||||
sess.ident_of("std"),
|
||||
sess.ident_of("prelude")
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: sess.ident_of("std"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: sess.ident_of("prelude"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
],
|
||||
rp: None,
|
||||
types: ~[]
|
||||
};
|
||||
|
||||
let vp = @spanned(ast::view_path_glob(prelude_path, n2));
|
||||
|
@ -16,14 +16,15 @@ use front::config;
|
||||
|
||||
use std::vec;
|
||||
use syntax::ast_util::*;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::{dummy_sp, span, ExpnInfo, NameAndSpan};
|
||||
use syntax::codemap;
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::fold;
|
||||
use syntax::opt_vec;
|
||||
use syntax::print::pprust;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
type node_id_gen = @fn() -> ast::NodeId;
|
||||
|
||||
@ -383,19 +384,27 @@ fn nospan<T>(t: T) -> codemap::spanned<T> {
|
||||
}
|
||||
|
||||
fn path_node(ids: ~[ast::ident]) -> ast::Path {
|
||||
ast::Path { span: dummy_sp(),
|
||||
global: false,
|
||||
idents: ids,
|
||||
rp: None,
|
||||
types: ~[] }
|
||||
ast::Path {
|
||||
span: dummy_sp(),
|
||||
global: false,
|
||||
segments: ids.move_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn path_node_global(ids: ~[ast::ident]) -> ast::Path {
|
||||
ast::Path { span: dummy_sp(),
|
||||
global: true,
|
||||
idents: ids,
|
||||
rp: None,
|
||||
types: ~[] }
|
||||
ast::Path {
|
||||
span: dummy_sp(),
|
||||
global: true,
|
||||
segments: ids.move_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
|
@ -182,6 +182,12 @@ pub static tag_misc_info_crate_items: uint = 0x80;
|
||||
pub static tag_item_method_provided_source: uint = 0x81;
|
||||
pub static tag_item_impl_vtables: uint = 0x82;
|
||||
|
||||
pub static tag_impls: uint = 0x83;
|
||||
pub static tag_impls_impl: uint = 0x84;
|
||||
|
||||
pub static tag_items_data_item_inherent_impl: uint = 0x85;
|
||||
pub static tag_items_data_item_extension_impl: uint = 0x86;
|
||||
|
||||
pub struct LinkMeta {
|
||||
name: @str,
|
||||
vers: @str,
|
||||
|
@ -49,16 +49,34 @@ pub fn each_lang_item(cstore: @mut cstore::CStore,
|
||||
decoder::each_lang_item(crate_data, f)
|
||||
}
|
||||
|
||||
/// Iterates over all the paths in the given crate.
|
||||
pub fn each_path(cstore: @mut cstore::CStore,
|
||||
cnum: ast::CrateNum,
|
||||
f: &fn(&str, decoder::def_like, ast::visibility) -> bool)
|
||||
-> bool {
|
||||
/// Iterates over each child of the given item.
|
||||
pub fn each_child_of_item(cstore: @mut cstore::CStore,
|
||||
def_id: ast::def_id,
|
||||
callback: &fn(decoder::def_like, ast::ident)) {
|
||||
let crate_data = cstore::get_crate_data(cstore, def_id.crate);
|
||||
let get_crate_data: decoder::GetCrateDataCb = |cnum| {
|
||||
cstore::get_crate_data(cstore, cnum)
|
||||
};
|
||||
decoder::each_child_of_item(cstore.intr,
|
||||
crate_data,
|
||||
def_id.node,
|
||||
get_crate_data,
|
||||
callback)
|
||||
}
|
||||
|
||||
/// Iterates over each top-level crate item.
|
||||
pub fn each_top_level_item_of_crate(cstore: @mut cstore::CStore,
|
||||
cnum: ast::CrateNum,
|
||||
callback: &fn(decoder::def_like,
|
||||
ast::ident)) {
|
||||
let crate_data = cstore::get_crate_data(cstore, cnum);
|
||||
let get_crate_data: decoder::GetCrateDataCb = |cnum| {
|
||||
cstore::get_crate_data(cstore, cnum)
|
||||
};
|
||||
decoder::each_path(cstore.intr, crate_data, get_crate_data, f)
|
||||
decoder::each_top_level_item_of_crate(cstore.intr,
|
||||
crate_data,
|
||||
get_crate_data,
|
||||
callback)
|
||||
}
|
||||
|
||||
pub fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path {
|
||||
@ -246,3 +264,36 @@ pub fn get_link_args_for_crate(cstore: @mut cstore::CStore,
|
||||
let cdata = cstore::get_crate_data(cstore, crate_num);
|
||||
decoder::get_link_args_for_crate(cdata)
|
||||
}
|
||||
|
||||
pub fn each_impl(cstore: @mut cstore::CStore,
|
||||
crate_num: ast::CrateNum,
|
||||
callback: &fn(ast::def_id)) {
|
||||
let cdata = cstore::get_crate_data(cstore, crate_num);
|
||||
decoder::each_impl(cdata, callback)
|
||||
}
|
||||
|
||||
pub fn each_implementation_for_type(cstore: @mut cstore::CStore,
|
||||
def_id: ast::def_id,
|
||||
callback: &fn(ast::def_id)) {
|
||||
let cdata = cstore::get_crate_data(cstore, def_id.crate);
|
||||
decoder::each_implementation_for_type(cdata, def_id.node, callback)
|
||||
}
|
||||
|
||||
pub fn each_implementation_for_trait(cstore: @mut cstore::CStore,
|
||||
def_id: ast::def_id,
|
||||
callback: &fn(ast::def_id)) {
|
||||
let cdata = cstore::get_crate_data(cstore, def_id.crate);
|
||||
decoder::each_implementation_for_trait(cdata, def_id.node, callback)
|
||||
}
|
||||
|
||||
/// If the given def ID describes a method belonging to a trait (either a
|
||||
/// default method or an implementation of a trait method), returns the ID of
|
||||
/// the trait that the method belongs to. Otherwise, returns `None`.
|
||||
pub fn get_trait_of_method(cstore: @mut cstore::CStore,
|
||||
def_id: ast::def_id,
|
||||
tcx: ty::ctxt)
|
||||
-> Option<ast::def_id> {
|
||||
let cdata = cstore::get_crate_data(cstore, def_id.crate);
|
||||
decoder::get_trait_of_method(cdata, def_id.node, tcx)
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ use metadata::decoder;
|
||||
use metadata::tydecode::{parse_ty_data, parse_def_id,
|
||||
parse_type_param_def_data,
|
||||
parse_bare_fn_ty_data, parse_trait_ref_data};
|
||||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use middle::astencode::vtable_decoder_helpers;
|
||||
@ -39,7 +40,7 @@ use syntax::ast_map;
|
||||
use syntax::attr;
|
||||
use syntax::parse::token::{ident_interner, special_idents};
|
||||
use syntax::print::pprust;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
use syntax::parse::token;
|
||||
|
||||
@ -335,15 +336,19 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::CrateNum)
|
||||
let purity = if fam == UnsafeStaticMethod { ast::unsafe_fn } else
|
||||
{ ast::impure_fn };
|
||||
// def_static_method carries an optional field of its enclosing
|
||||
// *trait*, but not an inclosing Impl (if this is an inherent
|
||||
// static method). So we need to detect whether this is in
|
||||
// a trait or not, which we do through the mildly hacky
|
||||
// way of checking whether there is a trait_method_sort.
|
||||
let trait_did_opt = if reader::maybe_get_doc(
|
||||
// trait or enclosing impl (if this is an inherent static method).
|
||||
// So we need to detect whether this is in a trait or not, which
|
||||
// we do through the mildly hacky way of checking whether there is
|
||||
// a trait_method_sort.
|
||||
let provenance = if reader::maybe_get_doc(
|
||||
item, tag_item_trait_method_sort).is_some() {
|
||||
Some(item_reqd_and_translated_parent_item(cnum, item))
|
||||
} else { None };
|
||||
dl_def(ast::def_static_method(did, trait_did_opt, purity))
|
||||
ast::FromTrait(item_reqd_and_translated_parent_item(cnum,
|
||||
item))
|
||||
} else {
|
||||
ast::FromImpl(item_reqd_and_translated_parent_item(cnum,
|
||||
item))
|
||||
};
|
||||
dl_def(ast::def_static_method(did, provenance, purity))
|
||||
}
|
||||
Type | ForeignType => dl_def(ast::def_ty(did)),
|
||||
Mod => dl_def(ast::def_mod(did)),
|
||||
@ -698,33 +703,164 @@ impl<'self> EachItemContext<'self> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over all the paths in the given crate.
|
||||
pub fn each_path(intr: @ident_interner,
|
||||
cdata: cmd,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
f: &fn(&str, def_like, ast::visibility) -> bool)
|
||||
-> bool {
|
||||
// FIXME #4572: This function needs to be nuked, as it's impossible to
|
||||
// make fast. It's the source of most of the performance problems when
|
||||
// compiling small crates.
|
||||
fn each_child_of_item_or_crate(intr: @ident_interner,
|
||||
cdata: cmd,
|
||||
item_doc: ebml::Doc,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
callback: &fn(def_like, ast::ident)) {
|
||||
// Iterate over all children.
|
||||
let _ = do reader::tagged_docs(item_doc, tag_mod_child) |child_info_doc| {
|
||||
let child_def_id = reader::with_doc_data(child_info_doc,
|
||||
parse_def_id);
|
||||
let child_def_id = translate_def_id(cdata, child_def_id);
|
||||
|
||||
// This item may be in yet another crate if it was the child of a
|
||||
// reexport.
|
||||
let other_crates_items = if child_def_id.crate == cdata.cnum {
|
||||
reader::get_doc(reader::Doc(cdata.data), tag_items)
|
||||
} else {
|
||||
let crate_data = get_crate_data(child_def_id.crate);
|
||||
reader::get_doc(reader::Doc(crate_data.data), tag_items)
|
||||
};
|
||||
|
||||
// Get the item.
|
||||
match maybe_find_item(child_def_id.node, other_crates_items) {
|
||||
None => {}
|
||||
Some(child_item_doc) => {
|
||||
// Hand off the item to the callback.
|
||||
let child_name = item_name(intr, child_item_doc);
|
||||
let def_like = item_to_def_like(child_item_doc,
|
||||
child_def_id,
|
||||
cdata.cnum);
|
||||
callback(def_like, child_name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
// As a special case, iterate over all static methods of
|
||||
// associated implementations too. This is a bit of a botch.
|
||||
// --pcwalton
|
||||
let _ = do reader::tagged_docs(item_doc,
|
||||
tag_items_data_item_inherent_impl)
|
||||
|inherent_impl_def_id_doc| {
|
||||
let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc,
|
||||
cdata);
|
||||
let items = reader::get_doc(reader::Doc(cdata.data), tag_items);
|
||||
match maybe_find_item(inherent_impl_def_id.node, items) {
|
||||
None => {}
|
||||
Some(inherent_impl_doc) => {
|
||||
let _ = do reader::tagged_docs(inherent_impl_doc,
|
||||
tag_item_impl_method)
|
||||
|impl_method_def_id_doc| {
|
||||
let impl_method_def_id =
|
||||
reader::with_doc_data(impl_method_def_id_doc,
|
||||
parse_def_id);
|
||||
let impl_method_def_id =
|
||||
translate_def_id(cdata, impl_method_def_id);
|
||||
match maybe_find_item(impl_method_def_id.node, items) {
|
||||
None => {}
|
||||
Some(impl_method_doc) => {
|
||||
match item_family(impl_method_doc) {
|
||||
StaticMethod | UnsafeStaticMethod => {
|
||||
// Hand off the static method
|
||||
// to the callback.
|
||||
let static_method_name =
|
||||
item_name(intr, impl_method_doc);
|
||||
let static_method_def_like =
|
||||
item_to_def_like(impl_method_doc,
|
||||
impl_method_def_id,
|
||||
cdata.cnum);
|
||||
callback(static_method_def_like,
|
||||
static_method_name);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
// Iterate over all reexports.
|
||||
let _ = do each_reexport(item_doc) |reexport_doc| {
|
||||
let def_id_doc = reader::get_doc(reexport_doc,
|
||||
tag_items_data_item_reexport_def_id);
|
||||
let child_def_id = reader::with_doc_data(def_id_doc,
|
||||
parse_def_id);
|
||||
let child_def_id = translate_def_id(cdata, child_def_id);
|
||||
|
||||
let name_doc = reader::get_doc(reexport_doc,
|
||||
tag_items_data_item_reexport_name);
|
||||
let name = name_doc.as_str_slice();
|
||||
|
||||
// This reexport may be in yet another crate.
|
||||
let other_crates_items = if child_def_id.crate == cdata.cnum {
|
||||
reader::get_doc(reader::Doc(cdata.data), tag_items)
|
||||
} else {
|
||||
let crate_data = get_crate_data(child_def_id.crate);
|
||||
reader::get_doc(reader::Doc(crate_data.data), tag_items)
|
||||
};
|
||||
|
||||
// Get the item.
|
||||
match maybe_find_item(child_def_id.node, other_crates_items) {
|
||||
None => {}
|
||||
Some(child_item_doc) => {
|
||||
// Hand off the item to the callback.
|
||||
let def_like = item_to_def_like(child_item_doc,
|
||||
child_def_id,
|
||||
cdata.cnum);
|
||||
callback(def_like, token::str_to_ident(name));
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
/// Iterates over each child of the given item.
|
||||
pub fn each_child_of_item(intr: @ident_interner,
|
||||
cdata: cmd,
|
||||
id: ast::NodeId,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
callback: &fn(def_like, ast::ident)) {
|
||||
// Find the item.
|
||||
let root_doc = reader::Doc(cdata.data);
|
||||
let items = reader::get_doc(root_doc, tag_items);
|
||||
let item_doc = match maybe_find_item(id, items) {
|
||||
None => return,
|
||||
Some(item_doc) => item_doc,
|
||||
};
|
||||
|
||||
each_child_of_item_or_crate(intr,
|
||||
cdata,
|
||||
item_doc,
|
||||
get_crate_data,
|
||||
callback)
|
||||
}
|
||||
|
||||
/// Iterates over all the top-level crate items.
|
||||
pub fn each_top_level_item_of_crate(intr: @ident_interner,
|
||||
cdata: cmd,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
callback: &fn(def_like, ast::ident)) {
|
||||
let root_doc = reader::Doc(cdata.data);
|
||||
let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
|
||||
let crate_items_doc = reader::get_doc(misc_info_doc,
|
||||
tag_misc_info_crate_items);
|
||||
|
||||
let mut path_builder = ~"";
|
||||
|
||||
let mut context = EachItemContext {
|
||||
intr: intr,
|
||||
cdata: cdata,
|
||||
get_crate_data: get_crate_data,
|
||||
path_builder: &mut path_builder,
|
||||
callback: f,
|
||||
};
|
||||
|
||||
// Iterate over all top-level crate items.
|
||||
context.each_child_of_module_or_crate(crate_items_doc)
|
||||
each_child_of_item_or_crate(intr,
|
||||
cdata,
|
||||
crate_items_doc,
|
||||
get_crate_data,
|
||||
callback)
|
||||
}
|
||||
|
||||
pub fn get_item_path(cdata: cmd, id: ast::NodeId) -> ast_map::path {
|
||||
@ -804,12 +940,9 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
|
||||
fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
|
||||
fn get_mutability(ch: u8) -> ast::mutability {
|
||||
match ch as char {
|
||||
'i' => { ast::m_imm }
|
||||
'm' => { ast::m_mutbl }
|
||||
'c' => { ast::m_const }
|
||||
_ => {
|
||||
fail!("unknown mutability character: `%c`", ch as char)
|
||||
}
|
||||
'i' => ast::m_imm,
|
||||
'm' => ast::m_mutbl,
|
||||
_ => fail!("unknown mutability character: `%c`", ch as char),
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,8 +1009,15 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
|
||||
{
|
||||
let method_doc = lookup_item(id, cdata.data);
|
||||
let def_id = item_def_id(method_doc, cdata);
|
||||
|
||||
let container_id = item_reqd_and_translated_parent_item(cdata.cnum,
|
||||
method_doc);
|
||||
let container_doc = lookup_item(container_id.node, cdata.data);
|
||||
let container = match item_family(container_doc) {
|
||||
Trait => TraitContainer(container_id),
|
||||
_ => ImplContainer(container_id),
|
||||
};
|
||||
|
||||
let name = item_name(intr, method_doc);
|
||||
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
|
||||
tag_item_method_tps);
|
||||
@ -898,7 +1038,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
|
||||
explicit_self,
|
||||
vis,
|
||||
def_id,
|
||||
container_id,
|
||||
container,
|
||||
provided_source
|
||||
)
|
||||
}
|
||||
@ -1267,21 +1407,6 @@ pub fn get_crate_vers(data: @~[u8]) -> @str {
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_crate_items(intr: @ident_interner, cdata: cmd,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
proc: &fn(path: &str, ast::def_id)) {
|
||||
do each_path(intr, cdata, get_crate_data) |path_string, def_like, _| {
|
||||
match def_like {
|
||||
dl_impl(*) | dl_field => {}
|
||||
dl_def(def) => {
|
||||
proc(path_string,
|
||||
ast_util::def_id_of_def(def))
|
||||
}
|
||||
}
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
pub fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8],
|
||||
out: @io::Writer) {
|
||||
let hash = get_crate_hash(bytes);
|
||||
@ -1315,3 +1440,59 @@ pub fn get_link_args_for_crate(cdata: cmd) -> ~[~str] {
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
pub fn each_impl(cdata: cmd, callback: &fn(ast::def_id)) {
|
||||
let impls_doc = reader::get_doc(reader::Doc(cdata.data), tag_impls);
|
||||
let _ = do reader::tagged_docs(impls_doc, tag_impls_impl) |impl_doc| {
|
||||
callback(item_def_id(impl_doc, cdata));
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
pub fn each_implementation_for_type(cdata: cmd,
|
||||
id: ast::NodeId,
|
||||
callback: &fn(ast::def_id)) {
|
||||
let item_doc = lookup_item(id, cdata.data);
|
||||
do reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl)
|
||||
|impl_doc| {
|
||||
let implementation_def_id = item_def_id(impl_doc, cdata);
|
||||
callback(implementation_def_id);
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
pub fn each_implementation_for_trait(cdata: cmd,
|
||||
id: ast::NodeId,
|
||||
callback: &fn(ast::def_id)) {
|
||||
let item_doc = lookup_item(id, cdata.data);
|
||||
|
||||
let _ = do reader::tagged_docs(item_doc,
|
||||
tag_items_data_item_extension_impl)
|
||||
|impl_doc| {
|
||||
let implementation_def_id = item_def_id(impl_doc, cdata);
|
||||
callback(implementation_def_id);
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_trait_of_method(cdata: cmd, id: ast::NodeId, tcx: ty::ctxt)
|
||||
-> Option<ast::def_id> {
|
||||
let item_doc = lookup_item(id, cdata.data);
|
||||
let parent_item_id = match item_parent_item(item_doc) {
|
||||
None => return None,
|
||||
Some(item_id) => item_id,
|
||||
};
|
||||
let parent_item_id = translate_def_id(cdata, parent_item_id);
|
||||
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data);
|
||||
match item_family(parent_item_doc) {
|
||||
Trait => Some(item_def_id(parent_item_doc, cdata)),
|
||||
Impl => {
|
||||
do reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref).map
|
||||
|_| {
|
||||
item_trait_ref(parent_item_doc, tcx, cdata).def_id
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ use syntax::attr::AttrMetaMethods;
|
||||
use syntax::diagnostic::span_handler;
|
||||
use syntax::parse::token::special_idents;
|
||||
use syntax::ast_util;
|
||||
use syntax::visit::Visitor;
|
||||
use syntax::visit;
|
||||
use syntax::parse::token;
|
||||
use syntax;
|
||||
@ -72,6 +73,7 @@ struct Stats {
|
||||
dep_bytes: uint,
|
||||
lang_item_bytes: uint,
|
||||
link_args_bytes: uint,
|
||||
impl_bytes: uint,
|
||||
misc_bytes: uint,
|
||||
item_bytes: uint,
|
||||
index_bytes: uint,
|
||||
@ -511,8 +513,12 @@ fn encode_reexports(ecx: &EncodeContext,
|
||||
Some(ref exports) => {
|
||||
debug!("(encoding info for module) found reexports for %d", id);
|
||||
for exp in exports.iter() {
|
||||
debug!("(encoding info for module) reexport '%s' for %d",
|
||||
exp.name, id);
|
||||
debug!("(encoding info for module) reexport '%s' (%d/%d) for \
|
||||
%d",
|
||||
exp.name,
|
||||
exp.def_id.crate,
|
||||
exp.def_id.node,
|
||||
id);
|
||||
ebml_w.start_tag(tag_items_data_item_reexport);
|
||||
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
|
||||
ebml_w.wr_str(def_to_str(exp.def_id));
|
||||
@ -635,15 +641,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
|
||||
fn encode_mutability(ebml_w: &writer::Encoder,
|
||||
m: ast::mutability) {
|
||||
match m {
|
||||
m_imm => {
|
||||
ebml_w.writer.write(&[ 'i' as u8 ]);
|
||||
}
|
||||
m_mutbl => {
|
||||
ebml_w.writer.write(&[ 'm' as u8 ]);
|
||||
}
|
||||
m_const => {
|
||||
ebml_w.writer.write(&[ 'c' as u8 ]);
|
||||
}
|
||||
m_imm => ebml_w.writer.write(&[ 'i' as u8 ]),
|
||||
m_mutbl => ebml_w.writer.write(&[ 'm' as u8 ]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -804,6 +803,38 @@ fn should_inline(attrs: &[Attribute]) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Encodes the inherent implementations of a structure, enumeration, or trait.
|
||||
fn encode_inherent_implementations(ecx: &EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
def_id: def_id) {
|
||||
match ecx.tcx.inherent_impls.find(&def_id) {
|
||||
None => {}
|
||||
Some(&implementations) => {
|
||||
for implementation in implementations.iter() {
|
||||
ebml_w.start_tag(tag_items_data_item_inherent_impl);
|
||||
encode_def_id(ebml_w, implementation.did);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encodes the implementations of a trait defined in this crate.
|
||||
fn encode_extension_implementations(ecx: &EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
trait_def_id: def_id) {
|
||||
match ecx.tcx.trait_impls.find(&trait_def_id) {
|
||||
None => {}
|
||||
Some(&implementations) => {
|
||||
for implementation in implementations.iter() {
|
||||
ebml_w.start_tag(tag_items_data_item_extension_impl);
|
||||
encode_def_id(ebml_w, implementation.did);
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_info_for_item(ecx: &EncodeContext,
|
||||
ebml_w: &mut writer::Encoder,
|
||||
item: @item,
|
||||
@ -907,6 +938,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
|
||||
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
||||
encode_region_param(ecx, ebml_w, item);
|
||||
|
||||
// Encode inherent implementations for this enumeration.
|
||||
encode_inherent_implementations(ecx, ebml_w, def_id);
|
||||
|
||||
ebml_w.end_tag();
|
||||
|
||||
encode_enum_variant_info(ecx,
|
||||
@ -959,6 +994,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
// Encode inherent implementations for this structure.
|
||||
encode_inherent_implementations(ecx, ebml_w, def_id);
|
||||
|
||||
/* Each class has its own index -- encode it */
|
||||
let bkts = create_index(idx);
|
||||
encode_index(ebml_w, bkts, write_i64);
|
||||
@ -995,7 +1033,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
encode_name(ecx, ebml_w, item.ident);
|
||||
encode_attributes(ebml_w, item.attrs);
|
||||
match ty.node {
|
||||
ast::ty_path(ref path, ref bounds, _) if path.idents.len() == 1 => {
|
||||
ast::ty_path(ref path, ref bounds, _) if path.segments
|
||||
.len() == 1 => {
|
||||
assert!(bounds.is_none());
|
||||
encode_impl_type_basename(ecx, ebml_w,
|
||||
ast_util::path_to_ident(path));
|
||||
@ -1073,6 +1112,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
|
||||
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
|
||||
}
|
||||
|
||||
// Encode the implementations of this trait.
|
||||
encode_extension_implementations(ecx, ebml_w, def_id);
|
||||
|
||||
ebml_w.end_tag();
|
||||
|
||||
// Now output the method info for each method.
|
||||
@ -1134,6 +1177,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
// Encode inherent implementations for this trait.
|
||||
encode_inherent_implementations(ecx, ebml_w, def_id);
|
||||
}
|
||||
item_mac(*) => fail!("item macros unimplemented")
|
||||
}
|
||||
@ -1227,7 +1273,10 @@ struct EncodeVisitor {
|
||||
}
|
||||
|
||||
impl visit::Visitor<()> for EncodeVisitor {
|
||||
fn visit_expr(&mut self, ex:@expr, _:()) { my_visit_expr(ex); }
|
||||
fn visit_expr(&mut self, ex:@expr, _:()) {
|
||||
visit::walk_expr(self, ex, ());
|
||||
my_visit_expr(ex);
|
||||
}
|
||||
fn visit_item(&mut self, i:@item, _:()) {
|
||||
visit::walk_item(self, i, ());
|
||||
my_visit_item(i,
|
||||
@ -1516,6 +1565,60 @@ fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
struct ImplVisitor<'self> {
|
||||
ecx: &'self EncodeContext<'self>,
|
||||
ebml_w: &'self mut writer::Encoder,
|
||||
}
|
||||
|
||||
impl<'self> Visitor<()> for ImplVisitor<'self> {
|
||||
fn visit_item(&mut self, item: @item, _: ()) {
|
||||
match item.node {
|
||||
item_impl(_, Some(ref trait_ref), _, _) => {
|
||||
let def_map = self.ecx.tcx.def_map;
|
||||
let trait_def = def_map.get_copy(&trait_ref.ref_id);
|
||||
let def_id = ast_util::def_id_of_def(trait_def);
|
||||
|
||||
// Load eagerly if this is an implementation of the Drop trait
|
||||
// or if the trait is not defined in this crate.
|
||||
if def_id == self.ecx.tcx.lang_items.drop_trait().unwrap() ||
|
||||
def_id.crate != LOCAL_CRATE {
|
||||
self.ebml_w.start_tag(tag_impls_impl);
|
||||
encode_def_id(self.ebml_w, local_def(item.id));
|
||||
self.ebml_w.end_tag();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_item(self, item, ());
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes implementations that are eagerly loaded.
|
||||
///
|
||||
/// None of this is necessary in theory; we can load all implementations
|
||||
/// lazily. However, in two cases the optimizations to lazily load
|
||||
/// implementations are not yet implemented. These two cases, which require us
|
||||
/// to load implementations eagerly, are:
|
||||
///
|
||||
/// * Destructors (implementations of the Drop trait).
|
||||
///
|
||||
/// * Implementations of traits not defined in this crate.
|
||||
fn encode_impls(ecx: &EncodeContext,
|
||||
crate: &Crate,
|
||||
ebml_w: &mut writer::Encoder) {
|
||||
ebml_w.start_tag(tag_impls);
|
||||
|
||||
{
|
||||
let mut visitor = ImplVisitor {
|
||||
ecx: ecx,
|
||||
ebml_w: ebml_w,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, crate, ());
|
||||
}
|
||||
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_misc_info(ecx: &EncodeContext,
|
||||
crate: &Crate,
|
||||
ebml_w: &mut writer::Encoder) {
|
||||
@ -1580,6 +1683,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
||||
dep_bytes: 0,
|
||||
lang_item_bytes: 0,
|
||||
link_args_bytes: 0,
|
||||
impl_bytes: 0,
|
||||
misc_bytes: 0,
|
||||
item_bytes: 0,
|
||||
index_bytes: 0,
|
||||
@ -1638,6 +1742,11 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
||||
encode_link_args(&ecx, &mut ebml_w);
|
||||
ecx.stats.link_args_bytes = *wr.pos - i;
|
||||
|
||||
// Encode the def IDs of impls, for coherence checking.
|
||||
i = *wr.pos;
|
||||
encode_impls(&ecx, crate, &mut ebml_w);
|
||||
ecx.stats.impl_bytes = *wr.pos - i;
|
||||
|
||||
// Encode miscellaneous info.
|
||||
i = *wr.pos;
|
||||
encode_misc_info(&ecx, crate, &mut ebml_w);
|
||||
@ -1670,6 +1779,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
|
||||
printfln!(" dep bytes: %u", ecx.stats.dep_bytes);
|
||||
printfln!(" lang item bytes: %u", ecx.stats.lang_item_bytes);
|
||||
printfln!(" link args bytes: %u", ecx.stats.link_args_bytes);
|
||||
printfln!(" impl bytes: %u", ecx.stats.impl_bytes);
|
||||
printfln!(" misc bytes: %u", ecx.stats.misc_bytes);
|
||||
printfln!(" item bytes: %u", ecx.stats.item_bytes);
|
||||
printfln!(" index bytes: %u", ecx.stats.index_bytes);
|
||||
|
@ -138,12 +138,20 @@ fn parse_path(st: &mut PState) -> @ast::Path {
|
||||
':' => { next(st); next(st); }
|
||||
c => {
|
||||
if c == '(' {
|
||||
return @ast::Path { span: dummy_sp(),
|
||||
global: false,
|
||||
idents: idents,
|
||||
rp: None,
|
||||
types: ~[] };
|
||||
} else { idents.push(parse_ident_(st, is_last)); }
|
||||
return @ast::Path {
|
||||
span: dummy_sp(),
|
||||
global: false,
|
||||
segments: idents.move_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
} else {
|
||||
idents.push(parse_ident_(st, is_last));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -417,7 +425,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
||||
fn parse_mutability(st: &mut PState) -> ast::mutability {
|
||||
match peek(st) {
|
||||
'm' => { next(st); ast::m_mutbl }
|
||||
'?' => { next(st); ast::m_const }
|
||||
_ => { ast::m_imm }
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ fn enc_mutability(w: @io::Writer, mt: ast::mutability) {
|
||||
match mt {
|
||||
m_imm => (),
|
||||
m_mutbl => w.write_char('m'),
|
||||
m_const => w.write_char('?')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,9 +374,16 @@ impl tr for ast::def {
|
||||
fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def {
|
||||
match *self {
|
||||
ast::def_fn(did, p) => ast::def_fn(did.tr(xcx), p),
|
||||
ast::def_static_method(did, did2_opt, p) => {
|
||||
ast::def_static_method(did, wrapped_did2, p) => {
|
||||
ast::def_static_method(did.tr(xcx),
|
||||
did2_opt.map(|did2| did2.tr(xcx)),
|
||||
match wrapped_did2 {
|
||||
ast::FromTrait(did2) => {
|
||||
ast::FromTrait(did2.tr(xcx))
|
||||
}
|
||||
ast::FromImpl(did2) => {
|
||||
ast::FromImpl(did2.tr(xcx))
|
||||
}
|
||||
},
|
||||
p)
|
||||
}
|
||||
ast::def_method(did0, did1) => {
|
||||
|
@ -23,12 +23,12 @@ use mc = middle::mem_categorization;
|
||||
use middle::borrowck::*;
|
||||
use middle::moves;
|
||||
use middle::ty;
|
||||
use syntax::ast::{m_mutbl, m_imm, m_const};
|
||||
use syntax::ast::{m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util;
|
||||
use syntax::codemap::span;
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
use syntax::visit;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
#[deriving(Clone)]
|
||||
@ -86,6 +86,44 @@ enum MoveError {
|
||||
}
|
||||
|
||||
impl<'self> CheckLoanCtxt<'self> {
|
||||
fn check_by_move_capture(&self,
|
||||
closure_id: ast::NodeId,
|
||||
cap_var: &moves::CaptureVar,
|
||||
move_path: @LoanPath) {
|
||||
let move_err = self.analyze_move_out_from(closure_id, move_path);
|
||||
match move_err {
|
||||
MoveOk => {}
|
||||
MoveWhileBorrowed(loan_path, loan_span) => {
|
||||
self.bccx.span_err(
|
||||
cap_var.span,
|
||||
fmt!("cannot move `%s` into closure \
|
||||
because it is borrowed",
|
||||
self.bccx.loan_path_to_str(move_path)));
|
||||
self.bccx.span_note(
|
||||
loan_span,
|
||||
fmt!("borrow of `%s` occurs here",
|
||||
self.bccx.loan_path_to_str(loan_path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_captured_variables(&self, closure_id: ast::NodeId, span: span) {
|
||||
let cap_vars = self.bccx.capture_map.get(&closure_id);
|
||||
for cap_var in cap_vars.iter() {
|
||||
let var_id = ast_util::def_id_of_def(cap_var.def).node;
|
||||
let var_path = @LpVar(var_id);
|
||||
self.check_if_path_is_moved(closure_id, span,
|
||||
MovedInCapture, var_path);
|
||||
match cap_var.mode {
|
||||
moves::CapRef | moves::CapCopy => {}
|
||||
moves::CapMove => {
|
||||
self.check_by_move_capture(closure_id, cap_var, var_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx }
|
||||
|
||||
pub fn each_issued_loan(&self,
|
||||
@ -220,9 +258,9 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
|
||||
// Restrictions that would cause the new loan to be illegal:
|
||||
let illegal_if = match loan2.mutbl {
|
||||
m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM,
|
||||
m_imm => RESTR_ALIAS | RESTR_FREEZE,
|
||||
m_const => RESTR_ALIAS,
|
||||
MutableMutability => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM,
|
||||
ImmutableMutability => RESTR_ALIAS | RESTR_FREEZE,
|
||||
ConstMutability => RESTR_ALIAS,
|
||||
};
|
||||
debug!("illegal_if=%?", illegal_if);
|
||||
|
||||
@ -231,7 +269,7 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
if restr.loan_path != loan2.loan_path { loop; }
|
||||
|
||||
match (new_loan.mutbl, old_loan.mutbl) {
|
||||
(m_mutbl, m_mutbl) => {
|
||||
(MutableMutability, MutableMutability) => {
|
||||
self.bccx.span_err(
|
||||
new_loan.span,
|
||||
fmt!("cannot borrow `%s` as mutable \
|
||||
@ -450,7 +488,6 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
mc::cat_deref(_, _, mc::unsafe_ptr(*)) |
|
||||
mc::cat_static_item(*) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(_)) |
|
||||
mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
|
||||
mc::cat_deref(_, _, mc::region_ptr(m_imm, _)) => {
|
||||
// Aliasability is independent of base cmt
|
||||
match cmt.freely_aliasable() {
|
||||
@ -582,7 +619,6 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
// Otherwise stop iterating
|
||||
LpExtend(_, mc::McDeclared, _) |
|
||||
LpExtend(_, mc::McImmutable, _) |
|
||||
LpExtend(_, mc::McReadOnly, _) |
|
||||
LpVar(_) => {
|
||||
return true;
|
||||
}
|
||||
@ -590,8 +626,11 @@ impl<'self> CheckLoanCtxt<'self> {
|
||||
|
||||
// Check for a non-const loan of `loan_path`
|
||||
let cont = do this.each_in_scope_loan(expr.id) |loan| {
|
||||
if loan.loan_path == loan_path && loan.mutbl != m_const {
|
||||
this.report_illegal_mutation(expr, full_loan_path, loan);
|
||||
if loan.loan_path == loan_path &&
|
||||
loan.mutbl != ConstMutability {
|
||||
this.report_illegal_mutation(expr,
|
||||
full_loan_path,
|
||||
loan);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
@ -825,3 +864,4 @@ fn check_loans_in_block<'a>(vt: &mut CheckLoanVisitor,
|
||||
visit::walk_block(vt, blk, this);
|
||||
this.check_for_conflicting_loans(blk.id);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
use middle::borrowck::*;
|
||||
use mc = middle::mem_categorization;
|
||||
use middle::ty;
|
||||
use syntax::ast::{m_const, m_imm, m_mutbl};
|
||||
use syntax::ast::{m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::span;
|
||||
use util::ppaux::{note_and_explain_region};
|
||||
@ -26,7 +26,7 @@ pub fn guarantee_lifetime(bccx: @BorrowckCtxt,
|
||||
span: span,
|
||||
cmt: mc::cmt,
|
||||
loan_region: ty::Region,
|
||||
loan_mutbl: ast::mutability) {
|
||||
loan_mutbl: LoanMutability) {
|
||||
debug!("guarantee_lifetime(cmt=%s, loan_region=%s)",
|
||||
cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
|
||||
let ctxt = GuaranteeLifetimeContext {bccx: bccx,
|
||||
@ -54,7 +54,7 @@ struct GuaranteeLifetimeContext {
|
||||
|
||||
span: span,
|
||||
loan_region: ty::Region,
|
||||
loan_mutbl: ast::mutability,
|
||||
loan_mutbl: LoanMutability,
|
||||
cmt_original: mc::cmt
|
||||
}
|
||||
|
||||
@ -235,11 +235,11 @@ impl GuaranteeLifetimeContext {
|
||||
// we need to dynamically mark it to prevent incompatible
|
||||
// borrows from happening later.
|
||||
let opt_dyna = match ptr_mutbl {
|
||||
m_imm | m_const => None,
|
||||
m_imm => None,
|
||||
m_mutbl => {
|
||||
match self.loan_mutbl {
|
||||
m_mutbl => Some(DynaMut),
|
||||
m_imm | m_const => Some(DynaImm)
|
||||
MutableMutability => Some(DynaMut),
|
||||
ImmutableMutability | ConstMutability => Some(DynaImm)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -26,7 +26,6 @@ use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::{Repr};
|
||||
|
||||
use syntax::ast::{m_const, m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::id_range;
|
||||
use syntax::codemap::span;
|
||||
@ -237,7 +236,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor,
|
||||
// make sure that the thing we are pointing out stays valid
|
||||
// for the lifetime `scope_r` of the resulting ptr:
|
||||
let scope_r = ty_region(tcx, ex.span, ty::expr_ty(tcx, ex));
|
||||
this.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r);
|
||||
this.guarantee_valid(ex.id,
|
||||
ex.span,
|
||||
base_cmt,
|
||||
LoanMutability::from_ast_mutability(mutbl),
|
||||
scope_r);
|
||||
visit::walk_expr(v, ex, this);
|
||||
}
|
||||
|
||||
@ -278,7 +281,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor,
|
||||
// adjustments).
|
||||
let scope_r = ty::re_scope(ex.id);
|
||||
let arg_cmt = this.bccx.cat_expr(arg);
|
||||
this.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r);
|
||||
this.guarantee_valid(arg.id,
|
||||
arg.span,
|
||||
arg_cmt,
|
||||
ImmutableMutability,
|
||||
scope_r);
|
||||
visit::walk_expr(v, ex, this);
|
||||
}
|
||||
|
||||
@ -357,18 +364,22 @@ impl GatherLoanCtxt {
|
||||
|
||||
match *autoref {
|
||||
ty::AutoPtr(r, m) => {
|
||||
let loan_mutability =
|
||||
LoanMutability::from_ast_mutability(m);
|
||||
self.guarantee_valid(expr.id,
|
||||
expr.span,
|
||||
cmt,
|
||||
m,
|
||||
loan_mutability,
|
||||
r)
|
||||
}
|
||||
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
|
||||
let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1);
|
||||
let loan_mutability =
|
||||
LoanMutability::from_ast_mutability(m);
|
||||
self.guarantee_valid(expr.id,
|
||||
expr.span,
|
||||
cmt_index,
|
||||
m,
|
||||
loan_mutability,
|
||||
r)
|
||||
}
|
||||
ty::AutoBorrowFn(r) => {
|
||||
@ -376,15 +387,17 @@ impl GatherLoanCtxt {
|
||||
self.guarantee_valid(expr.id,
|
||||
expr.span,
|
||||
cmt_deref,
|
||||
m_imm,
|
||||
ImmutableMutability,
|
||||
r)
|
||||
}
|
||||
ty::AutoBorrowObj(r, m) => {
|
||||
let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0);
|
||||
let loan_mutability =
|
||||
LoanMutability::from_ast_mutability(m);
|
||||
self.guarantee_valid(expr.id,
|
||||
expr.span,
|
||||
cmt_deref,
|
||||
m,
|
||||
loan_mutability,
|
||||
r)
|
||||
}
|
||||
ty::AutoUnsafe(_) => {}
|
||||
@ -402,7 +415,7 @@ impl GatherLoanCtxt {
|
||||
borrow_id: ast::NodeId,
|
||||
borrow_span: span,
|
||||
cmt: mc::cmt,
|
||||
req_mutbl: ast::mutability,
|
||||
req_mutbl: LoanMutability,
|
||||
loan_region: ty::Region) {
|
||||
debug!("guarantee_valid(borrow_id=%?, cmt=%s, \
|
||||
req_mutbl=%?, loan_region=%?)",
|
||||
@ -473,7 +486,7 @@ impl GatherLoanCtxt {
|
||||
let kill_scope = self.compute_kill_scope(loan_scope, loan_path);
|
||||
debug!("kill_scope = %?", kill_scope);
|
||||
|
||||
if req_mutbl == m_mutbl {
|
||||
if req_mutbl == MutableMutability {
|
||||
self.mark_loan_path_as_mutated(loan_path);
|
||||
}
|
||||
|
||||
@ -516,7 +529,7 @@ impl GatherLoanCtxt {
|
||||
// index: all_loans.len(),
|
||||
// loan_path: loan_path,
|
||||
// cmt: cmt,
|
||||
// mutbl: m_const,
|
||||
// mutbl: ConstMutability,
|
||||
// gen_scope: borrow_id,
|
||||
// kill_scope: kill_scope,
|
||||
// span: borrow_span,
|
||||
@ -527,29 +540,20 @@ impl GatherLoanCtxt {
|
||||
fn check_mutability(bccx: @BorrowckCtxt,
|
||||
borrow_span: span,
|
||||
cmt: mc::cmt,
|
||||
req_mutbl: ast::mutability) {
|
||||
req_mutbl: LoanMutability) {
|
||||
//! Implements the M-* rules in doc.rs.
|
||||
|
||||
match req_mutbl {
|
||||
m_const => {
|
||||
ConstMutability => {
|
||||
// Data of any mutability can be lent as const.
|
||||
}
|
||||
|
||||
m_imm => {
|
||||
match cmt.mutbl {
|
||||
mc::McImmutable | mc::McDeclared | mc::McInherited => {
|
||||
// both imm and mut data can be lent as imm;
|
||||
// for mutable data, this is a freeze
|
||||
}
|
||||
mc::McReadOnly => {
|
||||
bccx.report(BckError {span: borrow_span,
|
||||
cmt: cmt,
|
||||
code: err_mutbl(req_mutbl)});
|
||||
}
|
||||
}
|
||||
ImmutableMutability => {
|
||||
// both imm and mut data can be lent as imm;
|
||||
// for mutable data, this is a freeze
|
||||
}
|
||||
|
||||
m_mutbl => {
|
||||
MutableMutability => {
|
||||
// Only mutable data can be lent as mutable.
|
||||
if !cmt.mutbl.is_mutable() {
|
||||
bccx.report(BckError {span: borrow_span,
|
||||
@ -561,12 +565,14 @@ impl GatherLoanCtxt {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restriction_set(&self, req_mutbl: ast::mutability)
|
||||
pub fn restriction_set(&self, req_mutbl: LoanMutability)
|
||||
-> RestrictionSet {
|
||||
match req_mutbl {
|
||||
m_const => RESTR_EMPTY,
|
||||
m_imm => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM,
|
||||
m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE
|
||||
ConstMutability => RESTR_EMPTY,
|
||||
ImmutableMutability => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM,
|
||||
MutableMutability => {
|
||||
RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,8 +588,8 @@ impl GatherLoanCtxt {
|
||||
self.mark_loan_path_as_mutated(base);
|
||||
}
|
||||
LpExtend(_, mc::McDeclared, _) |
|
||||
LpExtend(_, mc::McImmutable, _) |
|
||||
LpExtend(_, mc::McReadOnly, _) => {
|
||||
LpExtend(_, mc::McImmutable, _) => {
|
||||
// Nothing to do.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -701,8 +707,13 @@ impl GatherLoanCtxt {
|
||||
}
|
||||
}
|
||||
};
|
||||
self.guarantee_valid(pat.id, pat.span,
|
||||
cmt_discr, mutbl, scope_r);
|
||||
let loan_mutability =
|
||||
LoanMutability::from_ast_mutability(mutbl);
|
||||
self.guarantee_valid(pat.id,
|
||||
pat.span,
|
||||
cmt_discr,
|
||||
loan_mutability,
|
||||
scope_r);
|
||||
}
|
||||
ast::bind_infer => {
|
||||
// No borrows here, but there may be moves
|
||||
@ -725,6 +736,8 @@ impl GatherLoanCtxt {
|
||||
self.vec_slice_info(slice_pat, slice_ty);
|
||||
let mcx = self.bccx.mc_ctxt();
|
||||
let cmt_index = mcx.cat_index(slice_pat, cmt, 0);
|
||||
let slice_loan_mutability =
|
||||
LoanMutability::from_ast_mutability(slice_mutbl);
|
||||
|
||||
// Note: We declare here that the borrow occurs upon
|
||||
// entering the `[...]` pattern. This implies that
|
||||
@ -743,8 +756,11 @@ impl GatherLoanCtxt {
|
||||
// trans do the right thing, and it would only work
|
||||
// for `~` vectors. It seems simpler to just require
|
||||
// that people call `vec.pop()` or `vec.unshift()`.
|
||||
self.guarantee_valid(pat.id, pat.span,
|
||||
cmt_index, slice_mutbl, slice_r);
|
||||
self.guarantee_valid(pat.id,
|
||||
pat.span,
|
||||
cmt_index,
|
||||
slice_loan_mutability,
|
||||
slice_r);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
@ -15,7 +15,7 @@ use std::vec;
|
||||
use middle::borrowck::*;
|
||||
use mc = middle::mem_categorization;
|
||||
use middle::ty;
|
||||
use syntax::ast::{m_const, m_imm, m_mutbl};
|
||||
use syntax::ast::{m_imm, m_mutbl};
|
||||
use syntax::codemap::span;
|
||||
|
||||
pub enum RestrictionResult {
|
||||
@ -121,13 +121,6 @@ impl RestrictionsContext {
|
||||
Safe
|
||||
}
|
||||
|
||||
mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(m_const)) => {
|
||||
// R-Deref-Freeze-Borrowed
|
||||
self.check_no_mutability_control(cmt, restrictions);
|
||||
Safe
|
||||
}
|
||||
|
||||
mc::cat_deref(cmt_base, _, pk @ mc::gc_ptr(m_mutbl)) => {
|
||||
// R-Deref-Managed-Borrowed
|
||||
//
|
||||
|
@ -241,12 +241,39 @@ pub enum PartialTotal {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Loans and loan paths
|
||||
|
||||
#[deriving(Clone, Eq)]
|
||||
pub enum LoanMutability {
|
||||
ImmutableMutability,
|
||||
ConstMutability,
|
||||
MutableMutability,
|
||||
}
|
||||
|
||||
impl LoanMutability {
|
||||
pub fn from_ast_mutability(ast_mutability: ast::mutability)
|
||||
-> LoanMutability {
|
||||
match ast_mutability {
|
||||
ast::m_imm => ImmutableMutability,
|
||||
ast::m_mutbl => MutableMutability,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToStr for LoanMutability {
|
||||
fn to_str(&self) -> ~str {
|
||||
match *self {
|
||||
ImmutableMutability => ~"immutable",
|
||||
ConstMutability => ~"read-only",
|
||||
MutableMutability => ~"mutable",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Record of a loan that was issued.
|
||||
pub struct Loan {
|
||||
index: uint,
|
||||
loan_path: @LoanPath,
|
||||
cmt: mc::cmt,
|
||||
mutbl: ast::mutability,
|
||||
mutbl: LoanMutability,
|
||||
restrictions: ~[Restriction],
|
||||
gen_scope: ast::NodeId,
|
||||
kill_scope: ast::NodeId,
|
||||
@ -417,7 +444,7 @@ impl ToStr for DynaFreezeKind {
|
||||
// Errors that can occur
|
||||
#[deriving(Eq)]
|
||||
pub enum bckerr_code {
|
||||
err_mutbl(ast::mutability),
|
||||
err_mutbl(LoanMutability),
|
||||
err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope
|
||||
err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
|
||||
err_freeze_aliasable_const
|
||||
@ -794,17 +821,14 @@ impl BorrowckCtxt {
|
||||
mc.cmt_to_str(cmt)
|
||||
}
|
||||
|
||||
pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str {
|
||||
let mc = &mc::mem_categorization_ctxt {tcx: self.tcx,
|
||||
method_map: self.method_map};
|
||||
mc.mut_to_str(mutbl)
|
||||
pub fn mut_to_str(&self, mutbl: LoanMutability) -> ~str {
|
||||
mutbl.to_str()
|
||||
}
|
||||
|
||||
pub fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str {
|
||||
match mutbl {
|
||||
ast::m_imm => "",
|
||||
ast::m_const => "const",
|
||||
ast::m_mutbl => "mut"
|
||||
ast::m_mutbl => "mut",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
|
||||
// to handle on-demand instantiation of functions via
|
||||
// foo::<bar> in a const. Currently that is only done on
|
||||
// a path in trans::callee that only works in block contexts.
|
||||
if pth.types.len() != 0 {
|
||||
if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
|
||||
sess.span_err(
|
||||
e.span, "paths in constants may only refer to \
|
||||
items without type parameters");
|
||||
|
@ -52,7 +52,7 @@ use middle::typeck;
|
||||
use util::ppaux::{ty_to_str, region_ptr_to_str, Repr};
|
||||
use util::common::indenter;
|
||||
|
||||
use syntax::ast::{m_imm, m_const, m_mutbl};
|
||||
use syntax::ast::{m_imm, m_mutbl};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::span;
|
||||
use syntax::print::pprust;
|
||||
@ -113,7 +113,6 @@ pub enum ElementKind {
|
||||
#[deriving(Eq, IterBytes)]
|
||||
pub enum MutabilityCategory {
|
||||
McImmutable, // Immutable.
|
||||
McReadOnly, // Read-only (`const`)
|
||||
McDeclared, // Directly declared as mutable.
|
||||
McInherited // Inherited from the fact that owner is mutable.
|
||||
}
|
||||
@ -297,7 +296,6 @@ impl MutabilityCategory {
|
||||
pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory {
|
||||
match m {
|
||||
m_imm => McImmutable,
|
||||
m_const => McReadOnly,
|
||||
m_mutbl => McDeclared
|
||||
}
|
||||
}
|
||||
@ -305,7 +303,6 @@ impl MutabilityCategory {
|
||||
pub fn inherit(&self) -> MutabilityCategory {
|
||||
match *self {
|
||||
McImmutable => McImmutable,
|
||||
McReadOnly => McReadOnly,
|
||||
McDeclared => McInherited,
|
||||
McInherited => McInherited
|
||||
}
|
||||
@ -313,7 +310,7 @@ impl MutabilityCategory {
|
||||
|
||||
pub fn is_mutable(&self) -> bool {
|
||||
match *self {
|
||||
McImmutable | McReadOnly => false,
|
||||
McImmutable => false,
|
||||
McDeclared | McInherited => true
|
||||
}
|
||||
}
|
||||
@ -321,7 +318,7 @@ impl MutabilityCategory {
|
||||
pub fn is_immutable(&self) -> bool {
|
||||
match *self {
|
||||
McImmutable => true,
|
||||
McReadOnly | McDeclared | McInherited => false
|
||||
McDeclared | McInherited => false
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +326,6 @@ impl MutabilityCategory {
|
||||
match *self {
|
||||
McDeclared | McInherited => "mutable",
|
||||
McImmutable => "immutable",
|
||||
McReadOnly => "const"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -610,7 +606,6 @@ impl mem_categorization_ctxt {
|
||||
-> MutabilityCategory {
|
||||
match interior_m {
|
||||
m_imm => base_m.inherit(),
|
||||
m_const => McReadOnly,
|
||||
m_mutbl => McDeclared
|
||||
}
|
||||
}
|
||||
@ -999,7 +994,6 @@ impl mem_categorization_ctxt {
|
||||
pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str {
|
||||
match mutbl {
|
||||
m_mutbl => ~"mutable",
|
||||
m_const => ~"const",
|
||||
m_imm => ~"immutable"
|
||||
}
|
||||
}
|
||||
@ -1164,7 +1158,6 @@ impl cmt_ {
|
||||
Some(AliasableManaged(m))
|
||||
}
|
||||
|
||||
cat_deref(_, _, region_ptr(m @ m_const, _)) |
|
||||
cat_deref(_, _, region_ptr(m @ m_imm, _)) => {
|
||||
Some(AliasableBorrowed(m))
|
||||
}
|
||||
|
@ -8,9 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// A pass that checks to make sure private fields and methods aren't used
|
||||
// outside their scopes.
|
||||
|
||||
//! A pass that checks to make sure private fields and methods aren't used
|
||||
//! outside their scopes.
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::ty::{ty_struct, ty_enum};
|
||||
@ -226,7 +225,7 @@ impl PrivacyVisitor {
|
||||
|
||||
if method_id.crate == LOCAL_CRATE {
|
||||
let is_private = self.method_is_private(span, method_id.node);
|
||||
let container_id = ty::method(self.tcx, method_id).container_id;
|
||||
let container_id = ty::method(self.tcx, method_id).container_id();
|
||||
if is_private &&
|
||||
(container_id.crate != LOCAL_CRATE ||
|
||||
!self.privileged_items.iter().any(|x| x == &(container_id.node))) {
|
||||
@ -251,7 +250,9 @@ impl PrivacyVisitor {
|
||||
match def {
|
||||
def_static_method(method_id, _, _) => {
|
||||
debug!("found static method def, checking it");
|
||||
self.check_method_common(span, method_id, path.idents.last())
|
||||
self.check_method_common(span,
|
||||
method_id,
|
||||
&path.segments.last().identifier)
|
||||
}
|
||||
def_fn(def_id, _) => {
|
||||
if def_id.crate == LOCAL_CRATE {
|
||||
@ -259,13 +260,19 @@ impl PrivacyVisitor {
|
||||
!self.privileged_items.iter().any(|x| x == &def_id.node) {
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("function `%s` is private",
|
||||
token::ident_to_str(path.idents.last())));
|
||||
token::ident_to_str(
|
||||
&path.segments
|
||||
.last()
|
||||
.identifier)));
|
||||
}
|
||||
} else if csearch::get_item_visibility(self.tcx.sess.cstore,
|
||||
def_id) != public {
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("function `%s` is private",
|
||||
token::ident_to_str(path.idents.last())));
|
||||
token::ident_to_str(
|
||||
&path.segments
|
||||
.last()
|
||||
.identifier)));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -827,7 +827,7 @@ fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
||||
Some(&ast::def_trait(did)) |
|
||||
Some(&ast::def_struct(did)) => {
|
||||
if did.crate == ast::LOCAL_CRATE {
|
||||
if cx.region_is_relevant(&path.rp) {
|
||||
if cx.region_is_relevant(&path.segments.last().lifetime) {
|
||||
cx.add_dep(did.node);
|
||||
}
|
||||
} else {
|
||||
@ -837,7 +837,7 @@ fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
||||
Some(variance) => {
|
||||
debug!("reference to external, rp'd type %s",
|
||||
pprust::ty_to_str(ty, sess.intr()));
|
||||
if cx.region_is_relevant(&path.rp) {
|
||||
if cx.region_is_relevant(&path.segments.last().lifetime) {
|
||||
let rv = cx.add_variance(variance);
|
||||
cx.add_rp(cx.item_id, rv)
|
||||
}
|
||||
@ -860,7 +860,7 @@ fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
||||
ast::ty_path(ref path, _, _) => {
|
||||
// type parameters are---for now, anyway---always invariant
|
||||
do cx.with_ambient_variance(rv_invariant) {
|
||||
for tp in path.types.iter() {
|
||||
for tp in path.segments.iter().flat_map(|s| s.types.iter()) {
|
||||
visitor.visit_ty(tp, cx);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -117,10 +117,13 @@ pub fn trans(bcx: @mut Block, expr: @ast::expr) -> Callee {
|
||||
|
||||
fn trans_def(bcx: @mut Block, def: ast::def, ref_expr: @ast::expr) -> Callee {
|
||||
match def {
|
||||
ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
|
||||
ast::def_fn(did, _) |
|
||||
ast::def_static_method(did, ast::FromImpl(_), _) => {
|
||||
fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
|
||||
}
|
||||
ast::def_static_method(impl_did, Some(trait_did), _) => {
|
||||
ast::def_static_method(impl_did,
|
||||
ast::FromTrait(trait_did),
|
||||
_) => {
|
||||
fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did,
|
||||
trait_did,
|
||||
ref_expr.id))
|
||||
@ -280,6 +283,14 @@ pub fn trans_fn_ref_with_vtables(
|
||||
self_ty: None,
|
||||
tps: /*bad*/ type_params.to_owned() };
|
||||
|
||||
// Load the info for the appropriate trait if necessary.
|
||||
match ty::trait_of_method(tcx, def_id) {
|
||||
None => {}
|
||||
Some(trait_id) => {
|
||||
ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
|
||||
}
|
||||
}
|
||||
|
||||
// We need to do a bunch of special handling for default methods.
|
||||
// We need to modify the def_id and our substs in order to monomorphize
|
||||
// the function.
|
||||
@ -300,7 +311,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// So, what we need to do is find this substitution and
|
||||
// compose it with the one we already have.
|
||||
|
||||
let impl_id = ty::method(tcx, def_id).container_id;
|
||||
let impl_id = ty::method(tcx, def_id).container_id();
|
||||
let method = ty::method(tcx, source_id);
|
||||
let trait_ref = ty::impl_trait_ref(tcx, impl_id)
|
||||
.expect("could not find trait_ref for impl with \
|
||||
|
@ -559,7 +559,9 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
|
||||
v
|
||||
}
|
||||
ast::expr_path(ref pth) => {
|
||||
assert_eq!(pth.types.len(), 0);
|
||||
// Assert that there are no type parameters in this path.
|
||||
assert!(pth.segments.iter().all(|seg| seg.types.is_empty()));
|
||||
|
||||
let tcx = cx.tcx;
|
||||
match tcx.def_map.find(&e.id) {
|
||||
Some(&ast::def_fn(def_id, _purity)) => {
|
||||
|
@ -825,11 +825,13 @@ fn trans_def_datum_unadjusted(bcx: @mut Block,
|
||||
let _icx = push_ctxt("trans_def_datum_unadjusted");
|
||||
|
||||
let fn_data = match def {
|
||||
ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
|
||||
ast::def_fn(did, _) |
|
||||
ast::def_static_method(did, ast::FromImpl(_), _) => {
|
||||
callee::trans_fn_ref(bcx, did, ref_expr.id)
|
||||
}
|
||||
ast::def_static_method(impl_did, Some(trait_did), _) => {
|
||||
meth::trans_static_method_callee(bcx, impl_did,
|
||||
ast::def_static_method(impl_did, ast::FromTrait(trait_did), _) => {
|
||||
meth::trans_static_method_callee(bcx,
|
||||
impl_did,
|
||||
trait_did,
|
||||
ref_expr.id)
|
||||
}
|
||||
|
@ -176,6 +176,10 @@ pub fn trans_method_callee(bcx: @mut Block,
|
||||
}) => {
|
||||
match bcx.fcx.param_substs {
|
||||
Some(substs) => {
|
||||
ty::populate_implementations_for_trait_if_necessary(
|
||||
bcx.tcx(),
|
||||
trait_id);
|
||||
|
||||
let vtbl = find_vtable(bcx.tcx(), substs,
|
||||
p, b);
|
||||
trans_monomorphized_callee(bcx, callee_id, this, mentry,
|
||||
@ -210,6 +214,8 @@ pub fn trans_static_method_callee(bcx: @mut Block,
|
||||
callee_id);
|
||||
let _indenter = indenter();
|
||||
|
||||
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
|
||||
|
||||
// When we translate a static fn defined in a trait like:
|
||||
//
|
||||
// trait<T1...Tn> Trait {
|
||||
@ -575,6 +581,8 @@ fn emit_vtable_methods(bcx: @mut Block,
|
||||
make a vtable for a type impl!")
|
||||
};
|
||||
|
||||
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
|
||||
|
||||
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
||||
do trait_method_def_ids.map |method_def_id| {
|
||||
let ident = ty::method(tcx, *method_def_id).ident;
|
||||
|
@ -60,6 +60,12 @@ pub struct field {
|
||||
mt: mt
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub enum MethodContainer {
|
||||
TraitContainer(ast::def_id),
|
||||
ImplContainer(ast::def_id),
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct Method {
|
||||
ident: ast::ident,
|
||||
@ -69,7 +75,7 @@ pub struct Method {
|
||||
explicit_self: ast::explicit_self_,
|
||||
vis: ast::visibility,
|
||||
def_id: ast::def_id,
|
||||
container_id: ast::def_id,
|
||||
container: MethodContainer,
|
||||
|
||||
// If this method is provided, we need to know where it came from
|
||||
provided_source: Option<ast::def_id>
|
||||
@ -83,7 +89,7 @@ impl Method {
|
||||
explicit_self: ast::explicit_self_,
|
||||
vis: ast::visibility,
|
||||
def_id: ast::def_id,
|
||||
container_id: ast::def_id,
|
||||
container: MethodContainer,
|
||||
provided_source: Option<ast::def_id>)
|
||||
-> Method {
|
||||
// Check the invariants.
|
||||
@ -101,10 +107,17 @@ impl Method {
|
||||
explicit_self: explicit_self,
|
||||
vis: vis,
|
||||
def_id: def_id,
|
||||
container_id: container_id,
|
||||
container: container,
|
||||
provided_source: provided_source
|
||||
}
|
||||
}
|
||||
|
||||
pub fn container_id(&self) -> ast::def_id {
|
||||
match self.container {
|
||||
TraitContainer(id) => id,
|
||||
ImplContainer(id) => id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Impl {
|
||||
@ -324,7 +337,15 @@ struct ctxt_ {
|
||||
used_mut_nodes: @mut HashSet<ast::NodeId>,
|
||||
|
||||
// vtable resolution information for impl declarations
|
||||
impl_vtables: typeck::impl_vtable_map
|
||||
impl_vtables: typeck::impl_vtable_map,
|
||||
|
||||
// The set of external nominal types whose implementations have been read.
|
||||
// This is used for lazy resolution of methods.
|
||||
populated_external_types: @mut HashSet<ast::def_id>,
|
||||
|
||||
// The set of external traits whose implementations have been read. This
|
||||
// is used for lazy resolution of traits.
|
||||
populated_external_traits: @mut HashSet<ast::def_id>,
|
||||
}
|
||||
|
||||
pub enum tbox_flag {
|
||||
@ -938,6 +959,8 @@ pub fn mk_ctxt(s: session::Session,
|
||||
used_unsafe: @mut HashSet::new(),
|
||||
used_mut_nodes: @mut HashSet::new(),
|
||||
impl_vtables: @mut HashMap::new(),
|
||||
populated_external_types: @mut HashSet::new(),
|
||||
populated_external_traits: @mut HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -3612,8 +3635,7 @@ pub fn def_has_ty_params(def: ast::def) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provided_source(cx: ctxt, id: ast::def_id)
|
||||
-> Option<ast::def_id> {
|
||||
pub fn provided_source(cx: ctxt, id: ast::def_id) -> Option<ast::def_id> {
|
||||
cx.provided_method_sources.find(&id).map_move(|x| *x)
|
||||
}
|
||||
|
||||
@ -4553,3 +4575,135 @@ pub fn visitor_object_ty(tcx: ctxt,
|
||||
ast::m_imm,
|
||||
EmptyBuiltinBounds())))
|
||||
}
|
||||
|
||||
/// Records a trait-to-implementation mapping.
|
||||
fn record_trait_implementation(tcx: ctxt,
|
||||
trait_def_id: def_id,
|
||||
implementation: @Impl) {
|
||||
let implementation_list;
|
||||
match tcx.trait_impls.find(&trait_def_id) {
|
||||
None => {
|
||||
implementation_list = @mut ~[];
|
||||
tcx.trait_impls.insert(trait_def_id, implementation_list);
|
||||
}
|
||||
Some(&existing_implementation_list) => {
|
||||
implementation_list = existing_implementation_list
|
||||
}
|
||||
}
|
||||
|
||||
implementation_list.push(implementation);
|
||||
}
|
||||
|
||||
/// Populates the type context with all the implementations for the given type
|
||||
/// if necessary.
|
||||
pub fn populate_implementations_for_type_if_necessary(tcx: ctxt,
|
||||
type_id: ast::def_id) {
|
||||
if type_id.crate == LOCAL_CRATE {
|
||||
return
|
||||
}
|
||||
if tcx.populated_external_types.contains(&type_id) {
|
||||
return
|
||||
}
|
||||
|
||||
do csearch::each_implementation_for_type(tcx.sess.cstore, type_id)
|
||||
|implementation_def_id| {
|
||||
let implementation = @csearch::get_impl(tcx, implementation_def_id);
|
||||
|
||||
// Record the trait->implementation mappings, if applicable.
|
||||
let associated_traits = csearch::get_impl_trait(tcx,
|
||||
implementation.did);
|
||||
for trait_ref in associated_traits.iter() {
|
||||
record_trait_implementation(tcx,
|
||||
trait_ref.def_id,
|
||||
implementation);
|
||||
}
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for method in implementation.methods.iter() {
|
||||
for source in method.provided_source.iter() {
|
||||
tcx.provided_method_sources.insert(method.def_id, *source);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is an inherent implementation, record it.
|
||||
if associated_traits.is_none() {
|
||||
let implementation_list;
|
||||
match tcx.inherent_impls.find(&type_id) {
|
||||
None => {
|
||||
implementation_list = @mut ~[];
|
||||
tcx.inherent_impls.insert(type_id, implementation_list);
|
||||
}
|
||||
Some(&existing_implementation_list) => {
|
||||
implementation_list = existing_implementation_list;
|
||||
}
|
||||
}
|
||||
implementation_list.push(implementation);
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
tcx.impls.insert(implementation_def_id, implementation);
|
||||
}
|
||||
|
||||
tcx.populated_external_types.insert(type_id);
|
||||
}
|
||||
|
||||
/// Populates the type context with all the implementations for the given
|
||||
/// trait if necessary.
|
||||
pub fn populate_implementations_for_trait_if_necessary(
|
||||
tcx: ctxt,
|
||||
trait_id: ast::def_id) {
|
||||
if trait_id.crate == LOCAL_CRATE {
|
||||
return
|
||||
}
|
||||
if tcx.populated_external_traits.contains(&trait_id) {
|
||||
return
|
||||
}
|
||||
|
||||
do csearch::each_implementation_for_trait(tcx.sess.cstore, trait_id)
|
||||
|implementation_def_id| {
|
||||
let implementation = @csearch::get_impl(tcx, implementation_def_id);
|
||||
|
||||
// Record the trait->implementation mapping.
|
||||
record_trait_implementation(tcx, trait_id, implementation);
|
||||
|
||||
// For any methods that use a default implementation, add them to
|
||||
// the map. This is a bit unfortunate.
|
||||
for method in implementation.methods.iter() {
|
||||
for source in method.provided_source.iter() {
|
||||
tcx.provided_method_sources.insert(method.def_id, *source);
|
||||
}
|
||||
}
|
||||
|
||||
// Store the implementation info.
|
||||
tcx.impls.insert(implementation_def_id, implementation);
|
||||
}
|
||||
|
||||
tcx.populated_external_traits.insert(trait_id);
|
||||
}
|
||||
|
||||
/// If the given def ID describes a trait method, returns the ID of the trait
|
||||
/// that the method belongs to. Otherwise, returns `None`.
|
||||
pub fn trait_of_method(tcx: ctxt, def_id: ast::def_id)
|
||||
-> Option<ast::def_id> {
|
||||
match tcx.methods.find(&def_id) {
|
||||
Some(method_descriptor) => {
|
||||
match method_descriptor.container {
|
||||
TraitContainer(id) => return Some(id),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
// If the method was in the local crate, then if we got here we know the
|
||||
// answer is negative.
|
||||
if def_id.crate == LOCAL_CRATE {
|
||||
return None
|
||||
}
|
||||
|
||||
let result = csearch::get_trait_of_method(tcx.cstore, def_id, tcx);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,6 @@ use middle::typeck::rscope::RegionParamNames;
|
||||
use middle::typeck::lookup_def_tcx;
|
||||
|
||||
use std::result;
|
||||
use std::vec;
|
||||
use syntax::abi::AbiSet;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::codemap::span;
|
||||
@ -150,7 +149,8 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
|
||||
// If the type is parameterized by the this region, then replace this
|
||||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
let regions = match (&decl_generics.region_param, &path.rp) {
|
||||
let regions = match (&decl_generics.region_param,
|
||||
&path.segments.last().lifetime) {
|
||||
(&None, &None) => {
|
||||
opt_vec::Empty
|
||||
}
|
||||
@ -169,20 +169,34 @@ fn ast_path_substs<AC:AstConv,RS:region_scope + Clone + 'static>(
|
||||
}
|
||||
(&Some(_), &Some(_)) => {
|
||||
opt_vec::with(
|
||||
ast_region_to_region(this, rscope, path.span, &path.rp))
|
||||
ast_region_to_region(this,
|
||||
rscope,
|
||||
path.span,
|
||||
&path.segments.last().lifetime))
|
||||
}
|
||||
};
|
||||
|
||||
// Convert the type parameters supplied by the user.
|
||||
if !vec::same_length(*decl_generics.type_param_defs, path.types) {
|
||||
let supplied_type_parameter_count =
|
||||
path.segments.iter().flat_map(|s| s.types.iter()).len();
|
||||
if decl_generics.type_param_defs.len() != supplied_type_parameter_count {
|
||||
this.tcx().sess.span_fatal(
|
||||
path.span,
|
||||
fmt!("wrong number of type arguments: expected %u but found %u",
|
||||
decl_generics.type_param_defs.len(), path.types.len()));
|
||||
decl_generics.type_param_defs.len(),
|
||||
supplied_type_parameter_count));
|
||||
}
|
||||
let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, a_t));
|
||||
let tps = path.segments
|
||||
.iter()
|
||||
.flat_map(|s| s.types.iter())
|
||||
.map(|a_t| ast_ty_to_ty(this, rscope, a_t))
|
||||
.collect();
|
||||
|
||||
substs {regions:ty::NonerasedRegions(regions), self_ty:self_ty, tps:tps}
|
||||
substs {
|
||||
regions: ty::NonerasedRegions(regions),
|
||||
self_ty: self_ty,
|
||||
tps: tps
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_path_to_substs_and_ty<AC:AstConv,
|
||||
@ -272,8 +286,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
|
||||
match a_seq_ty.ty.node {
|
||||
ast::ty_vec(ref mt) => {
|
||||
let mut mt = ast_mt_to_mt(this, rscope, mt);
|
||||
if a_seq_ty.mutbl == ast::m_mutbl ||
|
||||
a_seq_ty.mutbl == ast::m_const {
|
||||
if a_seq_ty.mutbl == ast::m_mutbl {
|
||||
mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
|
||||
}
|
||||
return ty::mk_evec(tcx, mt, vst);
|
||||
@ -326,7 +339,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
|
||||
path: &ast::Path,
|
||||
flags: uint) {
|
||||
if (flags & NO_TPS) != 0u {
|
||||
if path.types.len() > 0u {
|
||||
if !path.segments.iter().all(|s| s.types.is_empty()) {
|
||||
tcx.sess.span_err(
|
||||
path.span,
|
||||
"type parameters are not allowed on this type");
|
||||
@ -334,7 +347,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Clone + 'static>(
|
||||
}
|
||||
|
||||
if (flags & NO_REGIONS) != 0u {
|
||||
if path.rp.is_some() {
|
||||
if path.segments.last().lifetime.is_some() {
|
||||
tcx.sess.span_err(
|
||||
path.span,
|
||||
"region parameters are not allowed on this type");
|
||||
|
@ -128,7 +128,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path,
|
||||
Some((enm, var)) => {
|
||||
// Assign the pattern the type of the *enum*, not the variant.
|
||||
let enum_tpt = ty::lookup_item_type(tcx, enm);
|
||||
instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id);
|
||||
instantiate_path(pcx.fcx,
|
||||
path,
|
||||
enum_tpt,
|
||||
v_def,
|
||||
pat.span,
|
||||
pat.id);
|
||||
|
||||
// check that the type of the value being matched is a subtype
|
||||
// of the type of the pattern:
|
||||
@ -185,7 +190,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path,
|
||||
} else {
|
||||
ctor_tpt
|
||||
};
|
||||
instantiate_path(pcx.fcx, path, struct_tpt, pat.span, pat.id);
|
||||
instantiate_path(pcx.fcx,
|
||||
path,
|
||||
struct_tpt,
|
||||
s_def,
|
||||
pat.span,
|
||||
pat.id);
|
||||
|
||||
// Check that the type of the value being matched is a subtype of
|
||||
// the type of the pattern.
|
||||
|
@ -102,7 +102,7 @@ use std::vec;
|
||||
use extra::list::Nil;
|
||||
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
|
||||
use syntax::ast::{sty_uniq, sty_static, NodeId};
|
||||
use syntax::ast::{m_const, m_mutbl, m_imm};
|
||||
use syntax::ast::{m_mutbl, m_imm};
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
|
||||
@ -350,6 +350,10 @@ impl<'self> LookupContext<'self> {
|
||||
let opt_applicable_traits = trait_map.find(&self.expr.id);
|
||||
for applicable_traits in opt_applicable_traits.iter() {
|
||||
for trait_did in applicable_traits.iter() {
|
||||
ty::populate_implementations_for_trait_if_necessary(
|
||||
self.tcx(),
|
||||
*trait_did);
|
||||
|
||||
// Look for explicit implementations.
|
||||
let opt_impl_infos = self.tcx().trait_impls.find(trait_did);
|
||||
for impl_infos in opt_impl_infos.iter() {
|
||||
@ -534,6 +538,10 @@ impl<'self> LookupContext<'self> {
|
||||
|
||||
|
||||
fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
|
||||
// Read the inherent implementation candidates for this type from the
|
||||
// metadata if necessary.
|
||||
ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
|
||||
|
||||
let opt_impl_infos = self.tcx().inherent_impls.find(&did);
|
||||
for impl_infos in opt_impl_infos.iter() {
|
||||
for impl_info in impl_infos.iter() {
|
||||
@ -700,7 +708,7 @@ impl<'self> LookupContext<'self> {
|
||||
ty_evec(mt, vstore_fixed(_)) => {
|
||||
// First try to borrow to a slice
|
||||
let entry = self.search_for_some_kind_of_autorefd_method(
|
||||
AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl],
|
||||
AutoBorrowVec, autoderefs, [m_imm, m_mutbl],
|
||||
|m,r| ty::mk_evec(tcx,
|
||||
ty::mt {ty:mt.ty, mutbl:m},
|
||||
vstore_slice(r)));
|
||||
@ -709,7 +717,7 @@ impl<'self> LookupContext<'self> {
|
||||
|
||||
// Then try to borrow to a slice *and* borrow a pointer.
|
||||
self.search_for_some_kind_of_autorefd_method(
|
||||
AutoBorrowVecRef, autoderefs, [m_const, m_imm, m_mutbl],
|
||||
AutoBorrowVecRef, autoderefs, [m_imm, m_mutbl],
|
||||
|m,r| {
|
||||
let slice_ty = ty::mk_evec(tcx,
|
||||
ty::mt {ty:mt.ty, mutbl:m},
|
||||
@ -744,7 +752,7 @@ impl<'self> LookupContext<'self> {
|
||||
// Coerce ~/@/&Trait instances to &Trait.
|
||||
|
||||
self.search_for_some_kind_of_autorefd_method(
|
||||
AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl],
|
||||
AutoBorrowObj, autoderefs, [m_imm, m_mutbl],
|
||||
|trt_mut, reg| {
|
||||
ty::mk_trait(tcx, trt_did, trt_substs.clone(),
|
||||
RegionTraitStore(reg), trt_mut, b)
|
||||
@ -779,7 +787,7 @@ impl<'self> LookupContext<'self> {
|
||||
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) |
|
||||
ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => {
|
||||
self.search_for_some_kind_of_autorefd_method(
|
||||
AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
|
||||
AutoPtr, autoderefs, [m_imm, m_mutbl],
|
||||
|m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
|
||||
}
|
||||
|
||||
@ -1270,18 +1278,10 @@ impl<'self> LookupContext<'self> {
|
||||
}
|
||||
|
||||
fn mutability_matches(self_mutbl: ast::mutability,
|
||||
candidate_mutbl: ast::mutability) -> bool {
|
||||
candidate_mutbl: ast::mutability)
|
||||
-> bool {
|
||||
//! True if `self_mutbl <: candidate_mutbl`
|
||||
|
||||
match (self_mutbl, candidate_mutbl) {
|
||||
(_, m_const) => true,
|
||||
(m_mutbl, m_mutbl) => true,
|
||||
(m_imm, m_imm) => true,
|
||||
(m_mutbl, m_imm) => false,
|
||||
(m_imm, m_mutbl) => false,
|
||||
(m_const, m_imm) => false,
|
||||
(m_const, m_mutbl) => false,
|
||||
}
|
||||
self_mutbl == candidate_mutbl
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,7 +377,7 @@ impl Visitor<()> for GatherLocalsVisitor {
|
||||
if pat_util::pat_is_binding(self.fcx.ccx.tcx.def_map, p) => {
|
||||
self.assign(p.id, None);
|
||||
debug!("Pattern binding %s is assigned to %s",
|
||||
self.tcx.sess.str_of(path.idents[0]),
|
||||
self.tcx.sess.str_of(path.segments[0].identifier),
|
||||
self.fcx.infcx().ty_to_str(
|
||||
self.fcx.inh.locals.get_copy(&p.id)));
|
||||
}
|
||||
@ -1132,8 +1132,160 @@ pub enum DerefArgs {
|
||||
DoDerefArgs
|
||||
}
|
||||
|
||||
pub fn break_here() {
|
||||
debug!("break here!");
|
||||
// Given the provenance of a static method, returns the generics of the static
|
||||
// method's container.
|
||||
fn generics_of_static_method_container(type_context: ty::ctxt,
|
||||
provenance: ast::MethodProvenance)
|
||||
-> ty::Generics {
|
||||
match provenance {
|
||||
ast::FromTrait(trait_def_id) => {
|
||||
ty::lookup_trait_def(type_context, trait_def_id).generics
|
||||
}
|
||||
ast::FromImpl(impl_def_id) => {
|
||||
ty::lookup_item_type(type_context, impl_def_id).generics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies that type parameters supplied in paths are in the right
|
||||
// locations.
|
||||
fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
|
||||
path: &ast::Path,
|
||||
def: ast::def) {
|
||||
// We only care about checking the case in which the path has two or
|
||||
// more segments.
|
||||
if path.segments.len() < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
// Verify that no lifetimes or type parameters are present anywhere
|
||||
// except the final two elements of the path.
|
||||
for i in range(0, path.segments.len() - 2) {
|
||||
match path.segments[i].lifetime {
|
||||
None => {}
|
||||
Some(lifetime) => {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(lifetime.span,
|
||||
"lifetime parameters may not \
|
||||
appear here")
|
||||
}
|
||||
}
|
||||
|
||||
for typ in path.segments[i].types.iter() {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(typ.span,
|
||||
"type parameters may not appear here")
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no parameters at all, there is nothing more to do; the
|
||||
// rest of typechecking will (attempt to) infer everything.
|
||||
if path.segments
|
||||
.iter()
|
||||
.all(|s| s.lifetime.is_none() && s.types.is_empty()) {
|
||||
return
|
||||
}
|
||||
|
||||
match def {
|
||||
// If this is a static method of a trait or implementation, then
|
||||
// ensure that the segment of the path which names the trait or
|
||||
// implementation (the penultimate segment) is annotated with the
|
||||
// right number of type parameters.
|
||||
ast::def_static_method(_, provenance, _) => {
|
||||
let generics =
|
||||
generics_of_static_method_container(function_context.ccx.tcx,
|
||||
provenance);
|
||||
let name = match provenance {
|
||||
ast::FromTrait(_) => "trait",
|
||||
ast::FromImpl(_) => "impl",
|
||||
};
|
||||
|
||||
let trait_segment = &path.segments[path.segments.len() - 2];
|
||||
|
||||
// Make sure lifetime parameterization agrees with the trait or
|
||||
// implementation type.
|
||||
match (generics.region_param, trait_segment.lifetime) {
|
||||
(Some(_), None) => {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(path.span,
|
||||
fmt!("this %s has a lifetime \
|
||||
parameter but no \
|
||||
lifetime was specified",
|
||||
name))
|
||||
}
|
||||
(None, Some(_)) => {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(path.span,
|
||||
fmt!("this %s has no lifetime \
|
||||
parameter but a lifetime \
|
||||
was specified",
|
||||
name))
|
||||
}
|
||||
(Some(_), Some(_)) | (None, None) => {}
|
||||
}
|
||||
|
||||
// Make sure the number of type parameters supplied on the trait
|
||||
// or implementation segment equals the number of type parameters
|
||||
// on the trait or implementation definition.
|
||||
let trait_type_parameter_count = generics.type_param_defs.len();
|
||||
let supplied_type_parameter_count = trait_segment.types.len();
|
||||
if trait_type_parameter_count != supplied_type_parameter_count {
|
||||
let trait_count_suffix = if trait_type_parameter_count == 1 {
|
||||
""
|
||||
} else {
|
||||
"s"
|
||||
};
|
||||
let supplied_count_suffix =
|
||||
if supplied_type_parameter_count == 1 {
|
||||
""
|
||||
} else {
|
||||
"s"
|
||||
};
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(path.span,
|
||||
fmt!("the %s referenced by this \
|
||||
path has %u type \
|
||||
parameter%s, but %u type \
|
||||
parameter%s were supplied",
|
||||
name,
|
||||
trait_type_parameter_count,
|
||||
trait_count_suffix,
|
||||
supplied_type_parameter_count,
|
||||
supplied_count_suffix))
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Verify that no lifetimes or type parameters are present on
|
||||
// the penultimate segment of the path.
|
||||
let segment = &path.segments[path.segments.len() - 2];
|
||||
match segment.lifetime {
|
||||
None => {}
|
||||
Some(lifetime) => {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(lifetime.span,
|
||||
"lifetime parameters may not
|
||||
appear here")
|
||||
}
|
||||
}
|
||||
for typ in segment.types.iter() {
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_err(typ.span,
|
||||
"type parameters may not appear \
|
||||
here");
|
||||
function_context.tcx()
|
||||
.sess
|
||||
.span_note(typ.span,
|
||||
fmt!("this is a %?", def));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Invariant:
|
||||
@ -2333,8 +2485,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
ast::expr_path(ref pth) => {
|
||||
let defn = lookup_def(fcx, pth.span, id);
|
||||
|
||||
check_type_parameter_positions_in_path(fcx, pth, defn);
|
||||
let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
|
||||
instantiate_path(fcx, pth, tpt, expr.span, expr.id);
|
||||
instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
|
||||
}
|
||||
ast::expr_self => {
|
||||
let definition = lookup_def(fcx, expr.span, id);
|
||||
@ -3141,12 +3294,16 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
|
||||
pub fn instantiate_path(fcx: @mut FnCtxt,
|
||||
pth: &ast::Path,
|
||||
tpt: ty_param_bounds_and_ty,
|
||||
def: ast::def,
|
||||
span: span,
|
||||
node_id: ast::NodeId) {
|
||||
debug!(">>> instantiate_path");
|
||||
|
||||
let ty_param_count = tpt.generics.type_param_defs.len();
|
||||
let ty_substs_len = pth.types.len();
|
||||
let mut ty_substs_len = 0;
|
||||
for segment in pth.segments.iter() {
|
||||
ty_substs_len += segment.types.len()
|
||||
}
|
||||
|
||||
debug!("tpt=%s ty_param_count=%? ty_substs_len=%?",
|
||||
tpt.repr(fcx.tcx()),
|
||||
@ -3155,7 +3312,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
||||
|
||||
// determine the region bound, using the value given by the user
|
||||
// (if any) and otherwise using a fresh region variable
|
||||
let regions = match pth.rp {
|
||||
let regions = match pth.segments.last().lifetime {
|
||||
Some(_) => { // user supplied a lifetime parameter...
|
||||
match tpt.generics.region_param {
|
||||
None => { // ...but the type is not lifetime parameterized!
|
||||
@ -3165,7 +3322,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
||||
}
|
||||
Some(_) => { // ...and the type is lifetime parameterized, ok.
|
||||
opt_vec::with(
|
||||
ast_region_to_region(fcx, fcx, span, &pth.rp))
|
||||
ast_region_to_region(fcx,
|
||||
fcx,
|
||||
span,
|
||||
&pth.segments.last().lifetime))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3174,6 +3334,21 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
||||
}
|
||||
};
|
||||
|
||||
// Special case: If there is a self parameter, omit it from the list of
|
||||
// type parameters.
|
||||
//
|
||||
// Here we calculate the "user type parameter count", which is the number
|
||||
// of type parameters actually manifest in the AST. This will differ from
|
||||
// the internal type parameter count when there are self types involved.
|
||||
let (user_type_parameter_count, self_parameter_index) = match def {
|
||||
ast::def_static_method(_, provenance @ ast::FromTrait(_), _) => {
|
||||
let generics = generics_of_static_method_container(fcx.ccx.tcx,
|
||||
provenance);
|
||||
(ty_param_count - 1, Some(generics.type_param_defs.len()))
|
||||
}
|
||||
_ => (ty_param_count, None),
|
||||
};
|
||||
|
||||
// determine values for type parameters, using the values given by
|
||||
// the user (if any) and otherwise using fresh type variables
|
||||
let tps = if ty_substs_len == 0 {
|
||||
@ -3182,34 +3357,51 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(span, "this item does not take type parameters");
|
||||
fcx.infcx().next_ty_vars(ty_param_count)
|
||||
} else if ty_substs_len > ty_param_count {
|
||||
} else if ty_substs_len > user_type_parameter_count {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(span,
|
||||
fmt!("too many type parameters provided: expected %u, found %u",
|
||||
ty_param_count, ty_substs_len));
|
||||
user_type_parameter_count, ty_substs_len));
|
||||
fcx.infcx().next_ty_vars(ty_param_count)
|
||||
} else if ty_substs_len < ty_param_count {
|
||||
let is_static_method = match fcx.ccx.tcx.def_map.find(&node_id) {
|
||||
Some(&ast::def_static_method(*)) => true,
|
||||
_ => false
|
||||
};
|
||||
} else if ty_substs_len < user_type_parameter_count {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(span,
|
||||
fmt!("not enough type parameters provided: expected %u, found %u",
|
||||
ty_param_count, ty_substs_len));
|
||||
if is_static_method {
|
||||
fcx.ccx.tcx.sess.span_note
|
||||
(span, "Static methods have an extra implicit type parameter -- \
|
||||
did you omit the type parameter for the `Self` type?");
|
||||
}
|
||||
user_type_parameter_count, ty_substs_len));
|
||||
fcx.infcx().next_ty_vars(ty_param_count)
|
||||
} else {
|
||||
pth.types.map(|aty| fcx.to_ty(aty))
|
||||
// Build up the list of type parameters, inserting the self parameter
|
||||
// at the appropriate position.
|
||||
let mut result = ~[];
|
||||
let mut pushed = false;
|
||||
for (i, ast_type) in pth.segments
|
||||
.iter()
|
||||
.flat_map(|segment| segment.types.iter())
|
||||
.enumerate() {
|
||||
match self_parameter_index {
|
||||
Some(index) if index == i => {
|
||||
result.push(fcx.infcx().next_ty_vars(1)[0]);
|
||||
pushed = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result.push(fcx.to_ty(ast_type))
|
||||
}
|
||||
|
||||
// If the self parameter goes at the end, insert it there.
|
||||
if !pushed && self_parameter_index.is_some() {
|
||||
result.push(fcx.infcx().next_ty_vars(1)[0])
|
||||
}
|
||||
|
||||
assert_eq!(result.len(), ty_param_count)
|
||||
result
|
||||
};
|
||||
|
||||
let substs = substs {regions: ty::NonerasedRegions(regions),
|
||||
self_ty: None,
|
||||
tps: tps };
|
||||
let substs = substs {
|
||||
regions: ty::NonerasedRegions(regions),
|
||||
self_ty: None,
|
||||
tps: tps
|
||||
};
|
||||
fcx.write_ty_substs(node_id, tpt.ty, substs);
|
||||
|
||||
debug!("<<<");
|
||||
|
@ -136,6 +136,9 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
|
||||
// ...and here trait_ref is each bound that was declared on A,
|
||||
// expressed in terms of the type parameters.
|
||||
|
||||
ty::populate_implementations_for_trait_if_necessary(tcx,
|
||||
trait_ref.def_id);
|
||||
|
||||
// Substitute the values of the type parameters that may
|
||||
// appear in the bound.
|
||||
let trait_ref = substs.map_default(trait_ref, |substs| {
|
||||
@ -321,6 +324,10 @@ fn search_for_vtable(vcx: &VtableContext,
|
||||
let mut found = ~[];
|
||||
let mut impls_seen = HashSet::new();
|
||||
|
||||
// Load the implementations from external metadata if necessary.
|
||||
ty::populate_implementations_for_trait_if_necessary(tcx,
|
||||
trait_ref.def_id);
|
||||
|
||||
// XXX: this is a bad way to do this, since we do
|
||||
// pointless allocations.
|
||||
let impls = tcx.trait_impls.find(&trait_ref.def_id)
|
||||
|
@ -15,12 +15,11 @@
|
||||
// each trait in the system to its implementations.
|
||||
|
||||
|
||||
use metadata::csearch::{each_path, get_impl_trait};
|
||||
use metadata::csearch::{each_impl, get_impl_trait};
|
||||
use metadata::csearch;
|
||||
use metadata::cstore::iter_crate_data;
|
||||
use metadata::decoder::{dl_def, dl_field, dl_impl};
|
||||
use middle::ty::get;
|
||||
use middle::ty::{lookup_item_type, subst};
|
||||
use middle::ty::{ImplContainer, lookup_item_type, subst};
|
||||
use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
|
||||
use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
|
||||
use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
|
||||
@ -43,13 +42,12 @@ use syntax::ast;
|
||||
use syntax::ast_map::node_item;
|
||||
use syntax::ast_map;
|
||||
use syntax::ast_util::{def_id_of_def, local_def};
|
||||
use syntax::codemap::{span, dummy_sp};
|
||||
use syntax::codemap::span;
|
||||
use syntax::opt_vec;
|
||||
use syntax::visit;
|
||||
use syntax::parse;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::hashmap::HashSet;
|
||||
use std::result::Ok;
|
||||
use std::vec;
|
||||
|
||||
@ -150,19 +148,12 @@ pub fn CoherenceChecker(crate_context: @mut CrateCtxt) -> CoherenceChecker {
|
||||
CoherenceChecker {
|
||||
crate_context: crate_context,
|
||||
inference_context: new_infer_ctxt(crate_context.tcx),
|
||||
|
||||
base_type_def_ids: @mut HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CoherenceChecker {
|
||||
crate_context: @mut CrateCtxt,
|
||||
inference_context: @mut InferCtxt,
|
||||
|
||||
// A mapping from implementations to the corresponding base type
|
||||
// definition ID.
|
||||
|
||||
base_type_def_ids: @mut HashMap<def_id,def_id>,
|
||||
}
|
||||
|
||||
struct CoherenceCheckVisitor { cc: CoherenceChecker }
|
||||
@ -321,9 +312,6 @@ impl CoherenceChecker {
|
||||
if associated_traits.len() == 0 {
|
||||
self.add_inherent_impl(base_type_def_id, implementation);
|
||||
}
|
||||
|
||||
self.base_type_def_ids.insert(local_def(item.id),
|
||||
base_type_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,9 +668,6 @@ impl CoherenceChecker {
|
||||
let tcx = self.crate_context.tcx;
|
||||
let implementation = @csearch::get_impl(tcx, impl_def_id);
|
||||
|
||||
debug!("coherence: adding impl from external crate: %s",
|
||||
ty::item_path_str(tcx, implementation.did));
|
||||
|
||||
// Make sure we don't visit the same implementation multiple times.
|
||||
if !impls_seen.insert(implementation.did) {
|
||||
// Skip this one.
|
||||
@ -690,25 +675,11 @@ impl CoherenceChecker {
|
||||
}
|
||||
// Good. Continue.
|
||||
|
||||
let self_type = lookup_item_type(tcx, implementation.did);
|
||||
let associated_traits = get_impl_trait(tcx,
|
||||
implementation.did);
|
||||
let _ = lookup_item_type(tcx, implementation.did);
|
||||
let associated_traits = get_impl_trait(tcx, implementation.did);
|
||||
|
||||
// Do a sanity check to make sure that inherent methods have base
|
||||
// types.
|
||||
if associated_traits.is_none() {
|
||||
match get_base_type_def_id(self.inference_context,
|
||||
dummy_sp(),
|
||||
self_type.ty) {
|
||||
None => {
|
||||
tcx.sess.bug(fmt!("no base type for external impl with no \
|
||||
trait: %s (type %s)!",
|
||||
tcx.sess.str_of(implementation.ident),
|
||||
ty_to_str(tcx, self_type.ty)));
|
||||
}
|
||||
Some(_) => {} // Nothing to do.
|
||||
}
|
||||
}
|
||||
// Do a sanity check.
|
||||
assert!(associated_traits.is_some());
|
||||
|
||||
// Record all the trait methods.
|
||||
for trait_ref in associated_traits.iter() {
|
||||
@ -723,25 +694,6 @@ impl CoherenceChecker {
|
||||
}
|
||||
}
|
||||
|
||||
// Add the implementation to the mapping from implementation to base
|
||||
// type def ID, if there is a base type for this implementation.
|
||||
match get_base_type_def_id(self.inference_context,
|
||||
dummy_sp(),
|
||||
self_type.ty) {
|
||||
None => {} // Nothing to do.
|
||||
Some(base_type_def_id) => {
|
||||
// inherent methods apply to `impl Type` but not
|
||||
// `impl Trait for Type`:
|
||||
if associated_traits.is_none() {
|
||||
self.add_inherent_impl(base_type_def_id,
|
||||
implementation);
|
||||
}
|
||||
|
||||
self.base_type_def_ids.insert(implementation.did,
|
||||
base_type_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
tcx.impls.insert(implementation.did, implementation);
|
||||
}
|
||||
|
||||
@ -752,15 +704,10 @@ impl CoherenceChecker {
|
||||
|
||||
let crate_store = self.crate_context.tcx.sess.cstore;
|
||||
do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
|
||||
do each_path(crate_store, crate_number) |_, def_like, _| {
|
||||
match def_like {
|
||||
dl_impl(def_id) => {
|
||||
self.add_external_impl(&mut impls_seen, def_id)
|
||||
}
|
||||
dl_def(_) | dl_field => (), // Skip this.
|
||||
}
|
||||
true
|
||||
};
|
||||
do each_impl(crate_store, crate_number) |def_id| {
|
||||
assert_eq!(crate_number, def_id.crate);
|
||||
self.add_external_impl(&mut impls_seen, def_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -892,7 +839,7 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
|
||||
method.explicit_self,
|
||||
method.vis,
|
||||
new_def_id,
|
||||
impl_id,
|
||||
ImplContainer(impl_id),
|
||||
provided_source
|
||||
)
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ are represented as `ty_param()` instances.
|
||||
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::ty::{substs, ty_param_bounds_and_ty};
|
||||
use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
|
||||
use middle::ty::{ty_param_bounds_and_ty};
|
||||
use middle::ty;
|
||||
use middle::subst::Subst;
|
||||
use middle::typeck::astconv::{AstConv, ty_of_arg};
|
||||
@ -388,7 +389,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
||||
// assume public, because this is only invoked on trait methods
|
||||
ast::public,
|
||||
local_def(*m_id),
|
||||
local_def(trait_id),
|
||||
TraitContainer(local_def(trait_id)),
|
||||
None
|
||||
)
|
||||
}
|
||||
@ -744,7 +745,7 @@ pub struct ConvertedMethod {
|
||||
}
|
||||
|
||||
pub fn convert_methods(ccx: &CrateCtxt,
|
||||
container_id: ast::NodeId,
|
||||
container: MethodContainer,
|
||||
ms: &[@ast::method],
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
rcvr_ty_generics: &ty::Generics,
|
||||
@ -758,11 +759,14 @@ pub fn convert_methods(ccx: &CrateCtxt,
|
||||
let m_ty_generics =
|
||||
ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
|
||||
num_rcvr_ty_params);
|
||||
let mty =
|
||||
@ty_of_method(ccx, container_id, *m, rcvr_ty_generics.region_param,
|
||||
untransformed_rcvr_ty,
|
||||
rcvr_ast_generics, rcvr_visibility,
|
||||
&m.generics);
|
||||
let mty = @ty_of_method(ccx,
|
||||
container,
|
||||
*m,
|
||||
rcvr_ty_generics.region_param,
|
||||
untransformed_rcvr_ty,
|
||||
rcvr_ast_generics,
|
||||
rcvr_visibility,
|
||||
&m.generics);
|
||||
let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
|
||||
tcx.tcache.insert(
|
||||
local_def(m.id),
|
||||
@ -785,7 +789,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
|
||||
}).collect();
|
||||
|
||||
fn ty_of_method(ccx: &CrateCtxt,
|
||||
container_id: ast::NodeId,
|
||||
container: MethodContainer,
|
||||
m: &ast::method,
|
||||
rp: Option<ty::region_variance>,
|
||||
untransformed_rcvr_ty: ty::t,
|
||||
@ -817,7 +821,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
|
||||
m.explicit_self.node,
|
||||
method_vis,
|
||||
local_def(m.id),
|
||||
local_def(container_id),
|
||||
container,
|
||||
None
|
||||
)
|
||||
}
|
||||
@ -877,8 +881,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
|
||||
it.vis
|
||||
};
|
||||
|
||||
let cms = convert_methods(ccx, it.id, *ms, selfty,
|
||||
&i_ty_generics, generics,
|
||||
let cms = convert_methods(ccx,
|
||||
ImplContainer(local_def(it.id)),
|
||||
*ms,
|
||||
selfty,
|
||||
&i_ty_generics,
|
||||
generics,
|
||||
parent_visibility);
|
||||
for t in opt_trait_ref.iter() {
|
||||
// Prevent the builtin kind traits from being manually implemented.
|
||||
@ -901,9 +909,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
|
||||
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
|
||||
let (ty_generics, _) = mk_item_substs(ccx, generics, rp,
|
||||
Some(untransformed_rcvr_ty));
|
||||
let _ = convert_methods(ccx, it.id, provided_methods,
|
||||
let _ = convert_methods(ccx,
|
||||
TraitContainer(local_def(it.id)),
|
||||
provided_methods,
|
||||
untransformed_rcvr_ty,
|
||||
&ty_generics, generics,
|
||||
&ty_generics,
|
||||
generics,
|
||||
it.vis);
|
||||
|
||||
// We need to do this *after* converting methods, since
|
||||
|
@ -21,7 +21,7 @@ use middle::typeck::infer::{cres, InferCtxt};
|
||||
use middle::typeck::infer::{TypeTrace, Subtype};
|
||||
use middle::typeck::infer::fold_regions_in_sig;
|
||||
use middle::typeck::isr_alist;
|
||||
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl};
|
||||
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_imm, m_mutbl};
|
||||
use syntax::ast::{unsafe_fn};
|
||||
use syntax::ast::{Onceness, purity};
|
||||
use util::common::{indenter};
|
||||
@ -52,16 +52,6 @@ impl Combine for Glb {
|
||||
match (a.mutbl, b.mutbl) {
|
||||
// If one side or both is mut, then the GLB must use
|
||||
// the precise type from the mut side.
|
||||
(m_mutbl, m_const) => {
|
||||
Sub(**self).tys(a.ty, b.ty).chain(|_t| {
|
||||
Ok(ty::mt {ty: a.ty, mutbl: m_mutbl})
|
||||
})
|
||||
}
|
||||
(m_const, m_mutbl) => {
|
||||
Sub(**self).tys(b.ty, a.ty).chain(|_t| {
|
||||
Ok(ty::mt {ty: b.ty, mutbl: m_mutbl})
|
||||
})
|
||||
}
|
||||
(m_mutbl, m_mutbl) => {
|
||||
eq_tys(self, a.ty, b.ty).then(|| {
|
||||
Ok(ty::mt {ty: a.ty, mutbl: m_mutbl})
|
||||
@ -70,22 +60,12 @@ impl Combine for Glb {
|
||||
|
||||
// If one side or both is immutable, we can use the GLB of
|
||||
// both sides but mutbl must be `m_imm`.
|
||||
(m_imm, m_const) |
|
||||
(m_const, m_imm) |
|
||||
(m_imm, m_imm) => {
|
||||
self.tys(a.ty, b.ty).chain(|t| {
|
||||
Ok(ty::mt {ty: t, mutbl: m_imm})
|
||||
})
|
||||
}
|
||||
|
||||
// If both sides are const, then we can use GLB of both
|
||||
// sides and mutbl of only `m_const`.
|
||||
(m_const, m_const) => {
|
||||
self.tys(a.ty, b.ty).chain(|t| {
|
||||
Ok(ty::mt {ty: t, mutbl: m_const})
|
||||
})
|
||||
}
|
||||
|
||||
// There is no mutual subtype of these combinations.
|
||||
(m_mutbl, m_imm) |
|
||||
(m_imm, m_mutbl) => {
|
||||
|
@ -24,7 +24,7 @@ use middle::typeck::isr_alist;
|
||||
use util::ppaux::mt_to_str;
|
||||
|
||||
use extra::list;
|
||||
use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn};
|
||||
use syntax::ast::{Many, Once, extern_fn, impure_fn};
|
||||
use syntax::ast::{unsafe_fn};
|
||||
use syntax::ast::{Onceness, purity};
|
||||
|
||||
@ -55,14 +55,13 @@ impl Combine for Lub {
|
||||
mt_to_str(tcx, a),
|
||||
mt_to_str(tcx, b));
|
||||
|
||||
let m = if a.mutbl == b.mutbl {
|
||||
a.mutbl
|
||||
} else {
|
||||
m_const
|
||||
};
|
||||
if a.mutbl != b.mutbl {
|
||||
return Err(ty::terr_mutability)
|
||||
}
|
||||
|
||||
let m = a.mutbl;
|
||||
match m {
|
||||
m_imm | m_const => {
|
||||
m_imm => {
|
||||
self.tys(a.ty, b.ty).chain(|t| Ok(ty::mt {ty: t, mutbl: m}) )
|
||||
}
|
||||
|
||||
@ -71,11 +70,7 @@ impl Combine for Lub {
|
||||
eq_tys(self, a.ty, b.ty).then(|| {
|
||||
Ok(ty::mt {ty: a.ty, mutbl: m})
|
||||
})
|
||||
}).chain_err(|_e| {
|
||||
self.tys(a.ty, b.ty).chain(|t| {
|
||||
Ok(ty::mt {ty: t, mutbl: m_const})
|
||||
})
|
||||
})
|
||||
}).chain_err(|e| Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use util::ppaux::bound_region_to_str;
|
||||
|
||||
use extra::list::Nil;
|
||||
use extra::list;
|
||||
use syntax::ast::{Onceness, m_const, purity};
|
||||
use syntax::ast::{Onceness, purity};
|
||||
|
||||
pub struct Sub(CombineFields); // "subtype", "subregion" etc
|
||||
|
||||
@ -67,7 +67,7 @@ impl Combine for Sub {
|
||||
fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
|
||||
debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx));
|
||||
|
||||
if a.mutbl != b.mutbl && b.mutbl != m_const {
|
||||
if a.mutbl != b.mutbl {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ impl Combine for Sub {
|
||||
// (i.e., invariant if mut):
|
||||
eq_tys(self, a.ty, b.ty).then(|| Ok(*a))
|
||||
}
|
||||
m_imm | m_const => {
|
||||
m_imm => {
|
||||
// Otherwise we can be covariant:
|
||||
self.tys(a.ty, b.ty).chain(|_t| Ok(*a) )
|
||||
}
|
||||
|
@ -239,7 +239,6 @@ fn mutability_to_str(m: ast::mutability) -> ~str {
|
||||
match m {
|
||||
ast::m_mutbl => ~"mut ",
|
||||
ast::m_imm => ~"",
|
||||
ast::m_const => ~"const "
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ pub mod raw {
|
||||
use rt::local::Local;
|
||||
use rt::task::Task;
|
||||
|
||||
do Local::borrow::<Task, *()> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
task.heap.realloc(ptr as *libc::c_void, size) as *()
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
//! Unsafe casting functions
|
||||
|
||||
use ptr::RawPtr;
|
||||
use sys;
|
||||
use unstable::intrinsics;
|
||||
|
||||
@ -94,13 +95,13 @@ pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
|
||||
|
||||
/// Coerce an immutable reference to be mutable.
|
||||
#[inline]
|
||||
pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
|
||||
pub unsafe fn transmute_mut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *mut T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
||||
/// Coerce an immutable reference to be mutable.
|
||||
#[inline]
|
||||
pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
|
||||
pub unsafe fn transmute_immut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ fn test_basic() {
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_take_empty() {
|
||||
let value_cell = Cell::new_empty::<~int>();
|
||||
let value_cell: Cell<~int> = Cell::new_empty();
|
||||
value_cell.take();
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#[doc(hidden)];
|
||||
|
||||
use libc::c_void;
|
||||
use ptr::{mut_null};
|
||||
use ptr::null;
|
||||
use unstable::intrinsics::TyDesc;
|
||||
use unstable::raw;
|
||||
|
||||
@ -37,7 +37,7 @@ unsafe fn each_live_alloc(read_next_before: bool,
|
||||
use rt::local_heap;
|
||||
|
||||
let mut box = local_heap::live_allocs();
|
||||
while box != mut_null() {
|
||||
while box != null() {
|
||||
let next_before = (*box).next;
|
||||
let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE;
|
||||
|
||||
|
@ -884,10 +884,17 @@ impl<T> Poly for T {
|
||||
}
|
||||
}
|
||||
|
||||
// n.b. use 'const' to get an implementation for both '*mut' and '*' at the same
|
||||
// time.
|
||||
impl<T> Pointer for *const T {
|
||||
fn fmt(t: &*const T, f: &mut Formatter) {
|
||||
impl<T> Pointer for *T {
|
||||
fn fmt(t: &*T, f: &mut Formatter) {
|
||||
f.flags |= 1 << (parse::FlagAlternate as uint);
|
||||
do ::uint::to_str_bytes(*t as uint, 16) |buf| {
|
||||
f.pad_integral(buf, "0x", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Pointer for *mut T {
|
||||
fn fmt(t: &*mut T, f: &mut Formatter) {
|
||||
f.flags |= 1 << (parse::FlagAlternate as uint);
|
||||
do ::uint::to_str_bytes(*t as uint, 16) |buf| {
|
||||
f.pad_integral(buf, "0x", true);
|
||||
@ -923,8 +930,12 @@ delegate!(float to Float)
|
||||
delegate!(f32 to Float)
|
||||
delegate!(f64 to Float)
|
||||
|
||||
impl<T> Default for *const T {
|
||||
fn fmt(me: &*const T, f: &mut Formatter) { Pointer::fmt(me, f) }
|
||||
impl<T> Default for *T {
|
||||
fn fmt(me: &*T, f: &mut Formatter) { Pointer::fmt(me, f) }
|
||||
}
|
||||
|
||||
impl<T> Default for *mut T {
|
||||
fn fmt(me: &*mut T, f: &mut Formatter) { Pointer::fmt(me, f) }
|
||||
}
|
||||
|
||||
// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
|
||||
|
@ -869,21 +869,21 @@ mod test_map {
|
||||
|
||||
#[test]
|
||||
fn test_find_or_insert() {
|
||||
let mut m = HashMap::new::<int, int>();
|
||||
let mut m: HashMap<int,int> = HashMap::new();
|
||||
assert_eq!(*m.find_or_insert(1, 2), 2);
|
||||
assert_eq!(*m.find_or_insert(1, 3), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_or_insert_with() {
|
||||
let mut m = HashMap::new::<int, int>();
|
||||
let mut m: HashMap<int,int> = HashMap::new();
|
||||
assert_eq!(*m.find_or_insert_with(1, |_| 2), 2);
|
||||
assert_eq!(*m.find_or_insert_with(1, |_| 3), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_or_update_with() {
|
||||
let mut m = HashMap::new::<int, int>();
|
||||
let mut m: HashMap<int,int> = HashMap::new();
|
||||
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2);
|
||||
assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3);
|
||||
}
|
||||
|
@ -660,7 +660,10 @@ pub trait AdditiveIterator<A> {
|
||||
|
||||
impl<A: Add<A, A> + Zero, T: Iterator<A>> AdditiveIterator<A> for T {
|
||||
#[inline]
|
||||
fn sum(&mut self) -> A { self.fold(Zero::zero::<A>(), |s, x| s + x) }
|
||||
fn sum(&mut self) -> A {
|
||||
let zero: A = Zero::zero();
|
||||
self.fold(zero, |s, x| s + x)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for iterators over elements whose elements can be multiplied
|
||||
@ -685,7 +688,10 @@ pub trait MultiplicativeIterator<A> {
|
||||
|
||||
impl<A: Mul<A, A> + One, T: Iterator<A>> MultiplicativeIterator<A> for T {
|
||||
#[inline]
|
||||
fn product(&mut self) -> A { self.fold(One::one::<A>(), |p, x| p * x) }
|
||||
fn product(&mut self) -> A {
|
||||
let one: A = One::one();
|
||||
self.fold(one, |p, x| p * x)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for iterators over elements which can be compared to one another.
|
||||
|
@ -59,7 +59,8 @@ fn newsched_log_str(msg: ~str) {
|
||||
use rt::local::Local;
|
||||
|
||||
unsafe {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let optional_task: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match optional_task {
|
||||
Some(local) => {
|
||||
// Use the available logger
|
||||
(*local).logger.log(Left(msg));
|
||||
|
@ -182,7 +182,7 @@ impl ApproxEq<f32> for f32 {
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &f32) -> bool {
|
||||
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f32, f32>())
|
||||
self.approx_eq_eps(other, &1.0e-6)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -561,11 +561,14 @@ impl Real for f32 {
|
||||
|
||||
/// Converts to degrees, assuming the number is in radians
|
||||
#[inline]
|
||||
fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::<f32>()) }
|
||||
fn to_degrees(&self) -> f32 { *self * (180.0f32 / Real::pi()) }
|
||||
|
||||
/// Converts to radians, assuming the number is in degrees
|
||||
#[inline]
|
||||
fn to_radians(&self) -> f32 { *self * (Real::pi::<f32>() / 180.0) }
|
||||
fn to_radians(&self) -> f32 {
|
||||
let value: f32 = Real::pi();
|
||||
*self * (value / 180.0f32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Bounded for f32 {
|
||||
@ -578,10 +581,10 @@ impl Bounded for f32 {
|
||||
|
||||
impl Primitive for f32 {
|
||||
#[inline]
|
||||
fn bits() -> uint { 32 }
|
||||
fn bits(_: Option<f32>) -> uint { 32 }
|
||||
|
||||
#[inline]
|
||||
fn bytes() -> uint { Primitive::bits::<f32>() / 8 }
|
||||
fn bytes(_: Option<f32>) -> uint { Primitive::bits(Some(0f32)) / 8 }
|
||||
}
|
||||
|
||||
impl Float for f32 {
|
||||
@ -638,25 +641,25 @@ impl Float for f32 {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mantissa_digits() -> uint { 24 }
|
||||
fn mantissa_digits(_: Option<f32>) -> uint { 24 }
|
||||
|
||||
#[inline]
|
||||
fn digits() -> uint { 6 }
|
||||
fn digits(_: Option<f32>) -> uint { 6 }
|
||||
|
||||
#[inline]
|
||||
fn epsilon() -> f32 { 1.19209290e-07 }
|
||||
|
||||
#[inline]
|
||||
fn min_exp() -> int { -125 }
|
||||
fn min_exp(_: Option<f32>) -> int { -125 }
|
||||
|
||||
#[inline]
|
||||
fn max_exp() -> int { 128 }
|
||||
fn max_exp(_: Option<f32>) -> int { 128 }
|
||||
|
||||
#[inline]
|
||||
fn min_10_exp() -> int { -37 }
|
||||
fn min_10_exp(_: Option<f32>) -> int { -37 }
|
||||
|
||||
#[inline]
|
||||
fn max_10_exp() -> int { 38 }
|
||||
fn max_10_exp(_: Option<f32>) -> int { 38 }
|
||||
|
||||
/// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
|
||||
#[inline]
|
||||
@ -949,9 +952,11 @@ mod tests {
|
||||
assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
|
||||
assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
|
||||
assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
|
||||
assert!(3f32.clamp(&Float::NaN::<f32>(), &4f32).is_NaN());
|
||||
assert!(3f32.clamp(&2f32, &Float::NaN::<f32>()).is_NaN());
|
||||
assert!(Float::NaN::<f32>().clamp(&2f32, &4f32).is_NaN());
|
||||
|
||||
let nan: f32 = Float::NaN();
|
||||
assert!(3f32.clamp(&nan, &4f32).is_NaN());
|
||||
assert!(3f32.clamp(&2f32, &nan).is_NaN());
|
||||
assert!(nan.clamp(&2f32, &4f32).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1028,9 +1033,13 @@ mod tests {
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f32.asinh(), 0.0f32);
|
||||
assert_eq!((-0.0f32).asinh(), -0.0f32);
|
||||
assert_eq!(Float::infinity::<f32>().asinh(), Float::infinity::<f32>());
|
||||
assert_eq!(Float::neg_infinity::<f32>().asinh(), Float::neg_infinity::<f32>());
|
||||
assert!(Float::NaN::<f32>().asinh().is_NaN());
|
||||
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let nan: f32 = Float::NaN();
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_NaN());
|
||||
assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
|
||||
assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32);
|
||||
}
|
||||
@ -1039,9 +1048,13 @@ mod tests {
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f32.acosh(), 0.0f32);
|
||||
assert!(0.999f32.acosh().is_NaN());
|
||||
assert_eq!(Float::infinity::<f32>().acosh(), Float::infinity::<f32>());
|
||||
assert!(Float::neg_infinity::<f32>().acosh().is_NaN());
|
||||
assert!(Float::NaN::<f32>().acosh().is_NaN());
|
||||
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let nan: f32 = Float::NaN();
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_NaN());
|
||||
assert!(nan.acosh().is_NaN());
|
||||
assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32);
|
||||
assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32);
|
||||
}
|
||||
@ -1050,34 +1063,61 @@ mod tests {
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f32.atanh(), 0.0f32);
|
||||
assert_eq!((-0.0f32).atanh(), -0.0f32);
|
||||
assert_eq!(1.0f32.atanh(), Float::infinity::<f32>());
|
||||
assert_eq!((-1.0f32).atanh(), Float::neg_infinity::<f32>());
|
||||
|
||||
let inf32: f32 = Float::infinity();
|
||||
let neg_inf32: f32 = Float::neg_infinity();
|
||||
assert_eq!(1.0f32.atanh(), inf32);
|
||||
assert_eq!((-1.0f32).atanh(), neg_inf32);
|
||||
|
||||
assert!(2f64.atanh().atanh().is_NaN());
|
||||
assert!((-2f64).atanh().atanh().is_NaN());
|
||||
assert!(Float::infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::NaN::<f32>().atanh().is_NaN());
|
||||
|
||||
let inf64: f32 = Float::infinity();
|
||||
let neg_inf64: f32 = Float::neg_infinity();
|
||||
let nan32: f32 = Float::NaN();
|
||||
assert!(inf64.atanh().is_NaN());
|
||||
assert!(neg_inf64.atanh().is_NaN());
|
||||
assert!(nan32.atanh().is_NaN());
|
||||
|
||||
assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32);
|
||||
assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_approx_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
|
||||
assert_approx_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
|
||||
assert_approx_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
|
||||
assert_approx_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
|
||||
assert_approx_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
|
||||
assert_approx_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
|
||||
assert_approx_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
|
||||
assert_approx_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
|
||||
assert_approx_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
|
||||
assert_approx_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
|
||||
assert_approx_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
|
||||
assert_approx_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
|
||||
assert_approx_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
|
||||
assert_approx_eq!(Real::ln_2::<f32>(), 2f32.ln());
|
||||
assert_approx_eq!(Real::ln_10::<f32>(), 10f32.ln());
|
||||
let pi: f32 = Real::pi();
|
||||
let two_pi: f32 = Real::two_pi();
|
||||
let frac_pi_2: f32 = Real::frac_pi_2();
|
||||
let frac_pi_3: f32 = Real::frac_pi_3();
|
||||
let frac_pi_4: f32 = Real::frac_pi_4();
|
||||
let frac_pi_6: f32 = Real::frac_pi_6();
|
||||
let frac_pi_8: f32 = Real::frac_pi_8();
|
||||
let frac_1_pi: f32 = Real::frac_1_pi();
|
||||
let frac_2_pi: f32 = Real::frac_2_pi();
|
||||
let frac_2_sqrtpi: f32 = Real::frac_2_sqrtpi();
|
||||
let sqrt2: f32 = Real::sqrt2();
|
||||
let frac_1_sqrt2: f32 = Real::frac_1_sqrt2();
|
||||
let e: f32 = Real::e();
|
||||
let log2_e: f32 = Real::log2_e();
|
||||
let log10_e: f32 = Real::log10_e();
|
||||
let ln_2: f32 = Real::ln_2();
|
||||
let ln_10: f32 = Real::ln_10();
|
||||
|
||||
assert_approx_eq!(two_pi, 2f32 * pi);
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f32);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f32);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f32);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f32);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f32);
|
||||
assert_approx_eq!(frac_1_pi, 1f32 / pi);
|
||||
assert_approx_eq!(frac_2_pi, 2f32 / pi);
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f32 / pi.sqrt());
|
||||
assert_approx_eq!(sqrt2, 2f32.sqrt());
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f32 / 2f32.sqrt());
|
||||
assert_approx_eq!(log2_e, e.log2());
|
||||
assert_approx_eq!(log10_e, e.log10());
|
||||
assert_approx_eq!(ln_2, 2f32.ln());
|
||||
assert_approx_eq!(ln_10, 10f32.ln());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1153,17 +1193,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<f32>(), sys::size_of::<f32>() * 8);
|
||||
assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
|
||||
let none: Option<f32> = None;
|
||||
assert_eq!(Primitive::bits(none), sys::size_of::<f32>() * 8);
|
||||
assert_eq!(Primitive::bytes(none), sys::size_of::<f32>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_normal() {
|
||||
assert!(!Float::NaN::<f32>().is_normal());
|
||||
assert!(!Float::infinity::<f32>().is_normal());
|
||||
assert!(!Float::neg_infinity::<f32>().is_normal());
|
||||
assert!(!Zero::zero::<f32>().is_normal());
|
||||
assert!(!Float::neg_zero::<f32>().is_normal());
|
||||
let nan: f32 = Float::NaN();
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let zero: f32 = Zero::zero();
|
||||
let neg_zero: f32 = Float::neg_zero();
|
||||
assert!(!nan.is_normal());
|
||||
assert!(!inf.is_normal());
|
||||
assert!(!neg_inf.is_normal());
|
||||
assert!(!zero.is_normal());
|
||||
assert!(!neg_zero.is_normal());
|
||||
assert!(1f32.is_normal());
|
||||
assert!(1e-37f32.is_normal());
|
||||
assert!(!1e-38f32.is_normal());
|
||||
@ -1171,11 +1217,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_classify() {
|
||||
assert_eq!(Float::NaN::<f32>().classify(), FPNaN);
|
||||
assert_eq!(Float::infinity::<f32>().classify(), FPInfinite);
|
||||
assert_eq!(Float::neg_infinity::<f32>().classify(), FPInfinite);
|
||||
assert_eq!(Zero::zero::<f32>().classify(), FPZero);
|
||||
assert_eq!(Float::neg_zero::<f32>().classify(), FPZero);
|
||||
let nan: f32 = Float::NaN();
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let zero: f32 = Zero::zero();
|
||||
let neg_zero: f32 = Float::neg_zero();
|
||||
assert_eq!(nan.classify(), FPNaN);
|
||||
assert_eq!(inf.classify(), FPInfinite);
|
||||
assert_eq!(neg_inf.classify(), FPInfinite);
|
||||
assert_eq!(zero.classify(), FPZero);
|
||||
assert_eq!(neg_zero.classify(), FPZero);
|
||||
assert_eq!(1f32.classify(), FPNormal);
|
||||
assert_eq!(1e-37f32.classify(), FPNormal);
|
||||
assert_eq!(1e-38f32.classify(), FPSubnormal);
|
||||
@ -1192,11 +1243,13 @@ mod tests {
|
||||
|
||||
assert_eq!(Float::ldexp(0f32, -123), 0f32);
|
||||
assert_eq!(Float::ldexp(-0f32, -123), -0f32);
|
||||
assert_eq!(Float::ldexp(Float::infinity::<f32>(), -123),
|
||||
Float::infinity::<f32>());
|
||||
assert_eq!(Float::ldexp(Float::neg_infinity::<f32>(), -123),
|
||||
Float::neg_infinity::<f32>());
|
||||
assert!(Float::ldexp(Float::NaN::<f32>(), -123).is_NaN());
|
||||
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let nan: f32 = Float::NaN();
|
||||
assert_eq!(Float::ldexp(inf, -123), inf);
|
||||
assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
|
||||
assert!(Float::ldexp(nan, -123).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1214,10 +1267,12 @@ mod tests {
|
||||
|
||||
assert_eq!(0f32.frexp(), (0f32, 0));
|
||||
assert_eq!((-0f32).frexp(), (-0f32, 0));
|
||||
assert_eq!(match Float::infinity::<f32>().frexp() { (x, _) => x },
|
||||
Float::infinity::<f32>())
|
||||
assert_eq!(match Float::neg_infinity::<f32>().frexp() { (x, _) => x },
|
||||
Float::neg_infinity::<f32>())
|
||||
assert!(match Float::NaN::<f32>().frexp() { (x, _) => x.is_NaN() })
|
||||
|
||||
let inf: f32 = Float::infinity();
|
||||
let neg_inf: f32 = Float::neg_infinity();
|
||||
let nan: f32 = Float::NaN();
|
||||
assert_eq!(match inf.frexp() { (x, _) => x }, inf)
|
||||
assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf)
|
||||
assert!(match nan.frexp() { (x, _) => x.is_NaN() })
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ impl ApproxEq<f64> for f64 {
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &f64) -> bool {
|
||||
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f64, f64>())
|
||||
self.approx_eq_eps(other, &1.0e-6)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -578,11 +578,14 @@ impl Real for f64 {
|
||||
|
||||
/// Converts to degrees, assuming the number is in radians
|
||||
#[inline]
|
||||
fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) }
|
||||
fn to_degrees(&self) -> f64 { *self * (180.0f64 / Real::pi()) }
|
||||
|
||||
/// Converts to radians, assuming the number is in degrees
|
||||
#[inline]
|
||||
fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) }
|
||||
fn to_radians(&self) -> f64 {
|
||||
let value: f64 = Real::pi();
|
||||
*self * (value / 180.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl RealExt for f64 {
|
||||
@ -625,10 +628,10 @@ impl Bounded for f64 {
|
||||
|
||||
impl Primitive for f64 {
|
||||
#[inline]
|
||||
fn bits() -> uint { 64 }
|
||||
fn bits(_: Option<f64>) -> uint { 64 }
|
||||
|
||||
#[inline]
|
||||
fn bytes() -> uint { Primitive::bits::<f64>() / 8 }
|
||||
fn bytes(_: Option<f64>) -> uint { Primitive::bits(Some(0f64)) / 8 }
|
||||
}
|
||||
|
||||
impl Float for f64 {
|
||||
@ -685,25 +688,25 @@ impl Float for f64 {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mantissa_digits() -> uint { 53 }
|
||||
fn mantissa_digits(_: Option<f64>) -> uint { 53 }
|
||||
|
||||
#[inline]
|
||||
fn digits() -> uint { 15 }
|
||||
fn digits(_: Option<f64>) -> uint { 15 }
|
||||
|
||||
#[inline]
|
||||
fn epsilon() -> f64 { 2.2204460492503131e-16 }
|
||||
|
||||
#[inline]
|
||||
fn min_exp() -> int { -1021 }
|
||||
fn min_exp(_: Option<f64>) -> int { -1021 }
|
||||
|
||||
#[inline]
|
||||
fn max_exp() -> int { 1024 }
|
||||
fn max_exp(_: Option<f64>) -> int { 1024 }
|
||||
|
||||
#[inline]
|
||||
fn min_10_exp() -> int { -307 }
|
||||
fn min_10_exp(_: Option<f64>) -> int { -307 }
|
||||
|
||||
#[inline]
|
||||
fn max_10_exp() -> int { 308 }
|
||||
fn max_10_exp(_: Option<f64>) -> int { 308 }
|
||||
|
||||
/// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
|
||||
#[inline]
|
||||
@ -983,16 +986,20 @@ mod tests {
|
||||
fn test_min() {
|
||||
assert_eq!(1f64.min(&2f64), 1f64);
|
||||
assert_eq!(2f64.min(&1f64), 1f64);
|
||||
assert!(1f64.min(&Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().min(&1f64).is_NaN());
|
||||
|
||||
let nan: f64 = Float::NaN();
|
||||
assert!(1f64.min(&nan).is_NaN());
|
||||
assert!(nan.min(&1f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
assert_eq!(1f64.max(&2f64), 2f64);
|
||||
assert_eq!(2f64.max(&1f64), 2f64);
|
||||
assert!(1f64.max(&Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().max(&1f64).is_NaN());
|
||||
|
||||
let nan: f64 = Float::NaN();
|
||||
assert!(1f64.max(&nan).is_NaN());
|
||||
assert!(nan.max(&1f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1000,9 +1007,11 @@ mod tests {
|
||||
assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
|
||||
assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
|
||||
assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
|
||||
assert!(3f64.clamp(&Float::NaN::<f64>(), &4f64).is_NaN());
|
||||
assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
|
||||
assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
|
||||
|
||||
let nan: f64 = Float::NaN();
|
||||
assert!(3f64.clamp(&nan, &4f64).is_NaN());
|
||||
assert!(3f64.clamp(&2f64, &nan).is_NaN());
|
||||
assert!(nan.clamp(&2f64, &4f64).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1079,9 +1088,13 @@ mod tests {
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f64.asinh(), 0.0f64);
|
||||
assert_eq!((-0.0f64).asinh(), -0.0f64);
|
||||
assert_eq!(Float::infinity::<f64>().asinh(), Float::infinity::<f64>());
|
||||
assert_eq!(Float::neg_infinity::<f64>().asinh(), Float::neg_infinity::<f64>());
|
||||
assert!(Float::NaN::<f64>().asinh().is_NaN());
|
||||
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let nan: f64 = Float::NaN();
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_NaN());
|
||||
assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64);
|
||||
assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
|
||||
}
|
||||
@ -1090,9 +1103,13 @@ mod tests {
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f64.acosh(), 0.0f64);
|
||||
assert!(0.999f64.acosh().is_NaN());
|
||||
assert_eq!(Float::infinity::<f64>().acosh(), Float::infinity::<f64>());
|
||||
assert!(Float::neg_infinity::<f64>().acosh().is_NaN());
|
||||
assert!(Float::NaN::<f64>().acosh().is_NaN());
|
||||
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let nan: f64 = Float::NaN();
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_NaN());
|
||||
assert!(nan.acosh().is_NaN());
|
||||
assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64);
|
||||
assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64);
|
||||
}
|
||||
@ -1101,34 +1118,56 @@ mod tests {
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f64.atanh(), 0.0f64);
|
||||
assert_eq!((-0.0f64).atanh(), -0.0f64);
|
||||
assert_eq!(1.0f64.atanh(), Float::infinity::<f64>());
|
||||
assert_eq!((-1.0f64).atanh(), Float::neg_infinity::<f64>());
|
||||
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let nan: f64 = Float::NaN();
|
||||
assert_eq!(1.0f64.atanh(), inf);
|
||||
assert_eq!((-1.0f64).atanh(), neg_inf);
|
||||
assert!(2f64.atanh().atanh().is_NaN());
|
||||
assert!((-2f64).atanh().atanh().is_NaN());
|
||||
assert!(Float::infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::NaN::<f64>().atanh().is_NaN());
|
||||
assert!(inf.atanh().is_NaN());
|
||||
assert!(neg_inf.atanh().is_NaN());
|
||||
assert!(nan.atanh().is_NaN());
|
||||
assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64);
|
||||
assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_approx_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
|
||||
assert_approx_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
|
||||
assert_approx_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
|
||||
assert_approx_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
|
||||
assert_approx_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
|
||||
assert_approx_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
|
||||
assert_approx_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
|
||||
assert_approx_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
|
||||
assert_approx_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
|
||||
assert_approx_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
|
||||
assert_approx_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
|
||||
assert_approx_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
|
||||
assert_approx_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
|
||||
assert_approx_eq!(Real::ln_2::<f64>(), 2f64.ln());
|
||||
assert_approx_eq!(Real::ln_10::<f64>(), 10f64.ln());
|
||||
let pi: f64 = Real::pi();
|
||||
let two_pi: f64 = Real::two_pi();
|
||||
let frac_pi_2: f64 = Real::frac_pi_2();
|
||||
let frac_pi_3: f64 = Real::frac_pi_3();
|
||||
let frac_pi_4: f64 = Real::frac_pi_4();
|
||||
let frac_pi_6: f64 = Real::frac_pi_6();
|
||||
let frac_pi_8: f64 = Real::frac_pi_8();
|
||||
let frac_1_pi: f64 = Real::frac_1_pi();
|
||||
let frac_2_pi: f64 = Real::frac_2_pi();
|
||||
let frac_2_sqrtpi: f64 = Real::frac_2_sqrtpi();
|
||||
let sqrt2: f64 = Real::sqrt2();
|
||||
let frac_1_sqrt2: f64 = Real::frac_1_sqrt2();
|
||||
let e: f64 = Real::e();
|
||||
let log2_e: f64 = Real::log2_e();
|
||||
let log10_e: f64 = Real::log10_e();
|
||||
let ln_2: f64 = Real::ln_2();
|
||||
let ln_10: f64 = Real::ln_10();
|
||||
|
||||
assert_approx_eq!(two_pi, 2.0 * pi);
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f64);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f64);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f64);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f64);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f64);
|
||||
assert_approx_eq!(frac_1_pi, 1f64 / pi);
|
||||
assert_approx_eq!(frac_2_pi, 2f64 / pi);
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f64 / pi.sqrt());
|
||||
assert_approx_eq!(sqrt2, 2f64.sqrt());
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f64 / 2f64.sqrt());
|
||||
assert_approx_eq!(log2_e, e.log2());
|
||||
assert_approx_eq!(log10_e, e.log10());
|
||||
assert_approx_eq!(ln_2, 2f64.ln());
|
||||
assert_approx_eq!(ln_10, 10f64.ln());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1204,17 +1243,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
|
||||
assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
|
||||
let none: Option<f64> = None;
|
||||
assert_eq!(Primitive::bits(none), sys::size_of::<f64>() * 8);
|
||||
assert_eq!(Primitive::bytes(none), sys::size_of::<f64>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_normal() {
|
||||
assert!(!Float::NaN::<f64>().is_normal());
|
||||
assert!(!Float::infinity::<f64>().is_normal());
|
||||
assert!(!Float::neg_infinity::<f64>().is_normal());
|
||||
assert!(!Zero::zero::<f64>().is_normal());
|
||||
assert!(!Float::neg_zero::<f64>().is_normal());
|
||||
let nan: f64 = Float::NaN();
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let zero: f64 = Zero::zero();
|
||||
let neg_zero: f64 = Float::neg_zero();
|
||||
assert!(!nan.is_normal());
|
||||
assert!(!inf.is_normal());
|
||||
assert!(!neg_inf.is_normal());
|
||||
assert!(!zero.is_normal());
|
||||
assert!(!neg_zero.is_normal());
|
||||
assert!(1f64.is_normal());
|
||||
assert!(1e-307f64.is_normal());
|
||||
assert!(!1e-308f64.is_normal());
|
||||
@ -1222,11 +1267,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_classify() {
|
||||
assert_eq!(Float::NaN::<f64>().classify(), FPNaN);
|
||||
assert_eq!(Float::infinity::<f64>().classify(), FPInfinite);
|
||||
assert_eq!(Float::neg_infinity::<f64>().classify(), FPInfinite);
|
||||
assert_eq!(Zero::zero::<f64>().classify(), FPZero);
|
||||
assert_eq!(Float::neg_zero::<f64>().classify(), FPZero);
|
||||
let nan: f64 = Float::NaN();
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let zero: f64 = Zero::zero();
|
||||
let neg_zero: f64 = Float::neg_zero();
|
||||
assert_eq!(nan.classify(), FPNaN);
|
||||
assert_eq!(inf.classify(), FPInfinite);
|
||||
assert_eq!(neg_inf.classify(), FPInfinite);
|
||||
assert_eq!(zero.classify(), FPZero);
|
||||
assert_eq!(neg_zero.classify(), FPZero);
|
||||
assert_eq!(1e-307f64.classify(), FPNormal);
|
||||
assert_eq!(1e-308f64.classify(), FPSubnormal);
|
||||
}
|
||||
@ -1242,11 +1292,13 @@ mod tests {
|
||||
|
||||
assert_eq!(Float::ldexp(0f64, -123), 0f64);
|
||||
assert_eq!(Float::ldexp(-0f64, -123), -0f64);
|
||||
assert_eq!(Float::ldexp(Float::infinity::<f64>(), -123),
|
||||
Float::infinity::<f64>());
|
||||
assert_eq!(Float::ldexp(Float::neg_infinity::<f64>(), -123),
|
||||
Float::neg_infinity::<f64>());
|
||||
assert!(Float::ldexp(Float::NaN::<f64>(), -123).is_NaN());
|
||||
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let nan: f64 = Float::NaN();
|
||||
assert_eq!(Float::ldexp(inf, -123), inf);
|
||||
assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
|
||||
assert!(Float::ldexp(nan, -123).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1264,10 +1316,12 @@ mod tests {
|
||||
|
||||
assert_eq!(0f64.frexp(), (0f64, 0));
|
||||
assert_eq!((-0f64).frexp(), (-0f64, 0));
|
||||
assert_eq!(match Float::infinity::<f64>().frexp() { (x, _) => x },
|
||||
Float::infinity::<f64>())
|
||||
assert_eq!(match Float::neg_infinity::<f64>().frexp() { (x, _) => x },
|
||||
Float::neg_infinity::<f64>())
|
||||
assert!(match Float::NaN::<f64>().frexp() { (x, _) => x.is_NaN() })
|
||||
|
||||
let inf: f64 = Float::infinity();
|
||||
let neg_inf: f64 = Float::neg_infinity();
|
||||
let nan: f64 = Float::NaN();
|
||||
assert_eq!(match inf.frexp() { (x, _) => x }, inf)
|
||||
assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf)
|
||||
assert!(match nan.frexp() { (x, _) => x.is_NaN() })
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ impl ApproxEq<float> for float {
|
||||
|
||||
#[inline]
|
||||
fn approx_eq(&self, other: &float) -> bool {
|
||||
self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<float, float>())
|
||||
self.approx_eq_eps(other, &1.0e-6)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -783,32 +783,56 @@ impl Signed for float {
|
||||
|
||||
impl Bounded for float {
|
||||
#[inline]
|
||||
fn min_value() -> float { Bounded::min_value::<f64>() as float }
|
||||
fn min_value() -> float {
|
||||
let x: f64 = Bounded::min_value();
|
||||
x as float
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_value() -> float { Bounded::max_value::<f64>() as float }
|
||||
fn max_value() -> float {
|
||||
let x: f64 = Bounded::max_value();
|
||||
x as float
|
||||
}
|
||||
}
|
||||
|
||||
impl Primitive for float {
|
||||
#[inline]
|
||||
fn bits() -> uint { Primitive::bits::<f64>() }
|
||||
fn bits(_: Option<float>) -> uint {
|
||||
let bits: uint = Primitive::bits(Some(0f64));
|
||||
bits
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bytes() -> uint { Primitive::bytes::<f64>() }
|
||||
fn bytes(_: Option<float>) -> uint {
|
||||
let bytes: uint = Primitive::bytes(Some(0f64));
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl Float for float {
|
||||
#[inline]
|
||||
fn NaN() -> float { Float::NaN::<f64>() as float }
|
||||
fn NaN() -> float {
|
||||
let value: f64 = Float::NaN();
|
||||
value as float
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn infinity() -> float { Float::infinity::<f64>() as float }
|
||||
fn infinity() -> float {
|
||||
let value: f64 = Float::infinity();
|
||||
value as float
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_infinity() -> float { Float::neg_infinity::<f64>() as float }
|
||||
fn neg_infinity() -> float {
|
||||
let value: f64 = Float::neg_infinity();
|
||||
value as float
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn neg_zero() -> float { Float::neg_zero::<f64>() as float }
|
||||
fn neg_zero() -> float {
|
||||
let value: f64 = Float::neg_zero();
|
||||
value as float
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is NaN
|
||||
#[inline]
|
||||
@ -832,30 +856,46 @@ impl Float for float {
|
||||
fn classify(&self) -> FPCategory { (*self as f64).classify() }
|
||||
|
||||
#[inline]
|
||||
fn mantissa_digits() -> uint { Float::mantissa_digits::<f64>() }
|
||||
fn mantissa_digits(_: Option<float>) -> uint {
|
||||
Float::mantissa_digits(Some(0f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn digits() -> uint { Float::digits::<f64>() }
|
||||
fn digits(_: Option<float>) -> uint {
|
||||
Float::digits(Some(0f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn epsilon() -> float { Float::epsilon::<f64>() as float }
|
||||
fn epsilon() -> float {
|
||||
let value: f64 = Float::epsilon();
|
||||
value as float
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_exp() -> int { Float::min_exp::<f64>() }
|
||||
fn min_exp(_: Option<float>) -> int {
|
||||
Float::min_exp(Some(0f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_exp() -> int { Float::max_exp::<f64>() }
|
||||
fn max_exp(_: Option<float>) -> int {
|
||||
Float::max_exp(Some(0f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_10_exp() -> int { Float::min_10_exp::<f64>() }
|
||||
fn min_10_exp(_: Option<float>) -> int {
|
||||
Float::min_10_exp(Some(0f64))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_10_exp() -> int { Float::max_10_exp::<f64>() }
|
||||
fn max_10_exp(_: Option<float>) -> int {
|
||||
Float::max_10_exp(Some(0f64))
|
||||
}
|
||||
|
||||
/// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
|
||||
#[inline]
|
||||
fn ldexp(x: float, exp: int) -> float {
|
||||
Float::ldexp(x as f64, exp) as float
|
||||
let value: f64 = Float::ldexp(x as f64, exp);
|
||||
value as float
|
||||
}
|
||||
|
||||
///
|
||||
@ -937,9 +977,10 @@ mod tests {
|
||||
assert_eq!(1f.clamp(&2f, &4f), 2f);
|
||||
assert_eq!(8f.clamp(&2f, &4f), 4f);
|
||||
assert_eq!(3f.clamp(&2f, &4f), 3f);
|
||||
assert!(3f.clamp(&Float::NaN::<float>(), &4f).is_NaN());
|
||||
assert!(3f.clamp(&2f, &Float::NaN::<float>()).is_NaN());
|
||||
assert!(Float::NaN::<float>().clamp(&2f, &4f).is_NaN());
|
||||
let nan: float = Float::NaN();
|
||||
assert!(3f.clamp(&nan, &4f).is_NaN());
|
||||
assert!(3f.clamp(&2f, &nan).is_NaN());
|
||||
assert!(nan.clamp(&2f, &4f).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1016,9 +1057,13 @@ mod tests {
|
||||
fn test_asinh() {
|
||||
assert_eq!(0.0f.asinh(), 0.0f);
|
||||
assert_eq!((-0.0f).asinh(), -0.0f);
|
||||
assert_eq!(Float::infinity::<float>().asinh(), Float::infinity::<float>());
|
||||
assert_eq!(Float::neg_infinity::<float>().asinh(), Float::neg_infinity::<float>());
|
||||
assert!(Float::NaN::<float>().asinh().is_NaN());
|
||||
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let nan: float = Float::NaN();
|
||||
assert_eq!(inf.asinh(), inf);
|
||||
assert_eq!(neg_inf.asinh(), neg_inf);
|
||||
assert!(nan.asinh().is_NaN());
|
||||
assert_approx_eq!(2.0f.asinh(), 1.443635475178810342493276740273105f);
|
||||
assert_approx_eq!((-2.0f).asinh(), -1.443635475178810342493276740273105f);
|
||||
}
|
||||
@ -1027,9 +1072,13 @@ mod tests {
|
||||
fn test_acosh() {
|
||||
assert_eq!(1.0f.acosh(), 0.0f);
|
||||
assert!(0.999f.acosh().is_NaN());
|
||||
assert_eq!(Float::infinity::<float>().acosh(), Float::infinity::<float>());
|
||||
assert!(Float::neg_infinity::<float>().acosh().is_NaN());
|
||||
assert!(Float::NaN::<float>().acosh().is_NaN());
|
||||
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let nan: float = Float::NaN();
|
||||
assert_eq!(inf.acosh(), inf);
|
||||
assert!(neg_inf.acosh().is_NaN());
|
||||
assert!(nan.acosh().is_NaN());
|
||||
assert_approx_eq!(2.0f.acosh(), 1.31695789692481670862504634730796844f);
|
||||
assert_approx_eq!(3.0f.acosh(), 1.76274717403908605046521864995958461f);
|
||||
}
|
||||
@ -1038,34 +1087,58 @@ mod tests {
|
||||
fn test_atanh() {
|
||||
assert_eq!(0.0f.atanh(), 0.0f);
|
||||
assert_eq!((-0.0f).atanh(), -0.0f);
|
||||
assert_eq!(1.0f.atanh(), Float::infinity::<float>());
|
||||
assert_eq!((-1.0f).atanh(), Float::neg_infinity::<float>());
|
||||
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let inf64: f64 = Float::infinity();
|
||||
let neg_inf64: f64 = Float::neg_infinity();
|
||||
let nan: float = Float::NaN();
|
||||
assert_eq!(1.0f.atanh(), inf);
|
||||
assert_eq!((-1.0f).atanh(), neg_inf);
|
||||
assert!(2f64.atanh().atanh().is_NaN());
|
||||
assert!((-2f64).atanh().atanh().is_NaN());
|
||||
assert!(Float::infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
|
||||
assert!(Float::NaN::<float>().atanh().is_NaN());
|
||||
assert!(inf64.atanh().is_NaN());
|
||||
assert!(neg_inf64.atanh().is_NaN());
|
||||
assert!(nan.atanh().is_NaN());
|
||||
assert_approx_eq!(0.5f.atanh(), 0.54930614433405484569762261846126285f);
|
||||
assert_approx_eq!((-0.5f).atanh(), -0.54930614433405484569762261846126285f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_approx_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
|
||||
assert_approx_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
|
||||
assert_approx_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
|
||||
assert_approx_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
|
||||
assert_approx_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
|
||||
assert_approx_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
|
||||
assert_approx_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
|
||||
assert_approx_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
|
||||
assert_approx_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
|
||||
assert_approx_eq!(Real::sqrt2::<float>(), 2f.sqrt());
|
||||
assert_approx_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
|
||||
assert_approx_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
|
||||
assert_approx_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
|
||||
assert_approx_eq!(Real::ln_2::<float>(), 2f.ln());
|
||||
assert_approx_eq!(Real::ln_10::<float>(), 10f.ln());
|
||||
let pi: float = Real::pi();
|
||||
let two_pi: float = Real::two_pi();
|
||||
let frac_pi_2: float = Real::frac_pi_2();
|
||||
let frac_pi_3: float = Real::frac_pi_3();
|
||||
let frac_pi_4: float = Real::frac_pi_4();
|
||||
let frac_pi_6: float = Real::frac_pi_6();
|
||||
let frac_pi_8: float = Real::frac_pi_8();
|
||||
let frac_1_pi: float = Real::frac_1_pi();
|
||||
let frac_2_pi: float = Real::frac_2_pi();
|
||||
let frac_2_sqrtpi: float = Real::frac_2_sqrtpi();
|
||||
let sqrt2: float = Real::sqrt2();
|
||||
let frac_1_sqrt2: float = Real::frac_1_sqrt2();
|
||||
let e: float = Real::e();
|
||||
let log2_e: float = Real::log2_e();
|
||||
let log10_e: float = Real::log10_e();
|
||||
let ln_2: float = Real::ln_2();
|
||||
let ln_10: float = Real::ln_10();
|
||||
|
||||
assert_approx_eq!(two_pi, 2f * pi);
|
||||
assert_approx_eq!(frac_pi_2, pi / 2f);
|
||||
assert_approx_eq!(frac_pi_3, pi / 3f);
|
||||
assert_approx_eq!(frac_pi_4, pi / 4f);
|
||||
assert_approx_eq!(frac_pi_6, pi / 6f);
|
||||
assert_approx_eq!(frac_pi_8, pi / 8f);
|
||||
assert_approx_eq!(frac_1_pi, 1f / pi);
|
||||
assert_approx_eq!(frac_2_pi, 2f / pi);
|
||||
assert_approx_eq!(frac_2_sqrtpi, 2f / pi.sqrt());
|
||||
assert_approx_eq!(sqrt2, 2f.sqrt());
|
||||
assert_approx_eq!(frac_1_sqrt2, 1f / 2f.sqrt());
|
||||
assert_approx_eq!(log2_e, e.log2());
|
||||
assert_approx_eq!(log10_e, e.log10());
|
||||
assert_approx_eq!(ln_2, 2f.ln());
|
||||
assert_approx_eq!(ln_10, 10f.ln());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1141,17 +1214,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<float>(), sys::size_of::<float>() * 8);
|
||||
assert_eq!(Primitive::bytes::<float>(), sys::size_of::<float>());
|
||||
let none: Option<float> = None;
|
||||
assert_eq!(Primitive::bits(none), sys::size_of::<float>() * 8);
|
||||
assert_eq!(Primitive::bytes(none), sys::size_of::<float>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_normal() {
|
||||
assert!(!Float::NaN::<float>().is_normal());
|
||||
assert!(!Float::infinity::<float>().is_normal());
|
||||
assert!(!Float::neg_infinity::<float>().is_normal());
|
||||
assert!(!Zero::zero::<float>().is_normal());
|
||||
assert!(!Float::neg_zero::<float>().is_normal());
|
||||
let nan: float = Float::NaN();
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let zero: float = Zero::zero();
|
||||
let neg_zero: float = Float::neg_zero();
|
||||
assert!(!nan.is_normal());
|
||||
assert!(!inf.is_normal());
|
||||
assert!(!neg_inf.is_normal());
|
||||
assert!(!zero.is_normal());
|
||||
assert!(!neg_zero.is_normal());
|
||||
assert!(1f.is_normal());
|
||||
assert!(1e-307f.is_normal());
|
||||
assert!(!1e-308f.is_normal());
|
||||
@ -1159,11 +1238,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_classify() {
|
||||
assert_eq!(Float::NaN::<float>().classify(), FPNaN);
|
||||
assert_eq!(Float::infinity::<float>().classify(), FPInfinite);
|
||||
assert_eq!(Float::neg_infinity::<float>().classify(), FPInfinite);
|
||||
assert_eq!(Zero::zero::<float>().classify(), FPZero);
|
||||
assert_eq!(Float::neg_zero::<float>().classify(), FPZero);
|
||||
let nan: float = Float::NaN();
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let zero: float = Zero::zero();
|
||||
let neg_zero: float = Float::neg_zero();
|
||||
assert_eq!(nan.classify(), FPNaN);
|
||||
assert_eq!(inf.classify(), FPInfinite);
|
||||
assert_eq!(neg_inf.classify(), FPInfinite);
|
||||
assert_eq!(zero.classify(), FPZero);
|
||||
assert_eq!(neg_zero.classify(), FPZero);
|
||||
assert_eq!(1f.classify(), FPNormal);
|
||||
assert_eq!(1e-307f.classify(), FPNormal);
|
||||
assert_eq!(1e-308f.classify(), FPSubnormal);
|
||||
@ -1180,11 +1264,13 @@ mod tests {
|
||||
|
||||
assert_eq!(Float::ldexp(0f, -123), 0f);
|
||||
assert_eq!(Float::ldexp(-0f, -123), -0f);
|
||||
assert_eq!(Float::ldexp(Float::infinity::<float>(), -123),
|
||||
Float::infinity::<float>());
|
||||
assert_eq!(Float::ldexp(Float::neg_infinity::<float>(), -123),
|
||||
Float::neg_infinity::<float>());
|
||||
assert!(Float::ldexp(Float::NaN::<float>(), -123).is_NaN());
|
||||
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let nan: float = Float::NaN();
|
||||
assert_eq!(Float::ldexp(inf, -123), inf);
|
||||
assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
|
||||
assert!(Float::ldexp(nan, -123).is_NaN());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1202,11 +1288,13 @@ mod tests {
|
||||
|
||||
assert_eq!(0f.frexp(), (0f, 0));
|
||||
assert_eq!((-0f).frexp(), (-0f, 0));
|
||||
assert_eq!(match Float::infinity::<float>().frexp() { (x, _) => x },
|
||||
Float::infinity::<float>())
|
||||
assert_eq!(match Float::neg_infinity::<float>().frexp() { (x, _) => x },
|
||||
Float::neg_infinity::<float>())
|
||||
assert!(match Float::NaN::<float>().frexp() { (x, _) => x.is_NaN() })
|
||||
|
||||
let inf: float = Float::infinity();
|
||||
let neg_inf: float = Float::neg_infinity();
|
||||
let nan: float = Float::NaN();
|
||||
assert_eq!(match inf.frexp() { (x, _) => x }, inf);
|
||||
assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
|
||||
assert!(match nan.frexp() { (x, _) => x.is_NaN() })
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -466,10 +466,10 @@ impl Int for $T {}
|
||||
|
||||
impl Primitive for $T {
|
||||
#[inline]
|
||||
fn bits() -> uint { bits }
|
||||
fn bits(_: Option<$T>) -> uint { bits }
|
||||
|
||||
#[inline]
|
||||
fn bytes() -> uint { bits / 8 }
|
||||
fn bytes(_: Option<$T>) -> uint { bits / 8 }
|
||||
}
|
||||
|
||||
// String conversion functions and impl str -> num
|
||||
@ -754,8 +754,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8);
|
||||
assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>());
|
||||
let none: Option<$T> = None;
|
||||
assert_eq!(Primitive::bits(none), sys::size_of::<$T>() * 8);
|
||||
assert_eq!(Primitive::bytes(none), sys::size_of::<$T>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -272,8 +272,8 @@ pub trait Primitive: Num
|
||||
+ Div<Self,Self>
|
||||
+ Rem<Self,Self> {
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn bits() -> uint;
|
||||
fn bytes() -> uint;
|
||||
fn bits(unused_self: Option<Self>) -> uint;
|
||||
fn bytes(unused_self: Option<Self>) -> uint;
|
||||
}
|
||||
|
||||
/// A collection of traits relevant to primitive signed and unsigned integers
|
||||
@ -314,13 +314,13 @@ pub trait Float: Real
|
||||
fn is_normal(&self) -> bool;
|
||||
fn classify(&self) -> FPCategory;
|
||||
|
||||
fn mantissa_digits() -> uint;
|
||||
fn digits() -> uint;
|
||||
fn mantissa_digits(unused_self: Option<Self>) -> uint;
|
||||
fn digits(unused_self: Option<Self>) -> uint;
|
||||
fn epsilon() -> Self;
|
||||
fn min_exp() -> int;
|
||||
fn max_exp() -> int;
|
||||
fn min_10_exp() -> int;
|
||||
fn max_10_exp() -> int;
|
||||
fn min_exp(unused_self: Option<Self>) -> int;
|
||||
fn max_exp(unused_self: Option<Self>) -> int;
|
||||
fn min_10_exp(unused_self: Option<Self>) -> int;
|
||||
fn max_10_exp(unused_self: Option<Self>) -> int;
|
||||
|
||||
fn ldexp(x: Self, exp: int) -> Self;
|
||||
fn frexp(&self) -> (Self, int);
|
||||
@ -484,9 +484,9 @@ impl<T: CheckedAdd+CheckedSub+Zero+Ord+Bounded> Saturating for T {
|
||||
match self.checked_add(&v) {
|
||||
Some(x) => x,
|
||||
None => if v >= Zero::zero() {
|
||||
Bounded::max_value::<T>()
|
||||
Bounded::max_value()
|
||||
} else {
|
||||
Bounded::min_value::<T>()
|
||||
Bounded::min_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,9 +496,9 @@ impl<T: CheckedAdd+CheckedSub+Zero+Ord+Bounded> Saturating for T {
|
||||
match self.checked_sub(&v) {
|
||||
Some(x) => x,
|
||||
None => if v >= Zero::zero() {
|
||||
Bounded::min_value::<T>()
|
||||
Bounded::min_value()
|
||||
} else {
|
||||
Bounded::max_value::<T>()
|
||||
Bounded::max_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,10 +404,10 @@ impl ToStrRadix for $T {
|
||||
|
||||
impl Primitive for $T {
|
||||
#[inline]
|
||||
fn bits() -> uint { bits }
|
||||
fn bits(_: Option<$T>) -> uint { bits }
|
||||
|
||||
#[inline]
|
||||
fn bytes() -> uint { bits / 8 }
|
||||
fn bytes(_: Option<$T>) -> uint { bits / 8 }
|
||||
}
|
||||
|
||||
impl BitCount for $T {
|
||||
@ -532,8 +532,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_primitive() {
|
||||
assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8);
|
||||
assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>());
|
||||
let none: Option<$T> = None;
|
||||
assert_eq!(Primitive::bits(none), sys::size_of::<$T>() * 8);
|
||||
assert_eq!(Primitive::bytes(none), sys::size_of::<$T>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1521,7 +1521,7 @@ impl MemoryMap {
|
||||
let r = unsafe {
|
||||
libc::mmap(addr, len, prot, flags, fd, offset)
|
||||
};
|
||||
if r == libc::MAP_FAILED {
|
||||
if r.equiv(&libc::MAP_FAILED) {
|
||||
Err(match errno() as c_int {
|
||||
libc::EACCES => ErrFdNotAvail,
|
||||
libc::EBADF => ErrInvalidFd,
|
||||
|
@ -12,8 +12,11 @@
|
||||
|
||||
use cast;
|
||||
use clone::Clone;
|
||||
use cmp::Equiv;
|
||||
use iterator::{range, Iterator};
|
||||
use option::{Option, Some, None};
|
||||
#[cfg(stage0)]
|
||||
use sys;
|
||||
use unstable::intrinsics;
|
||||
use util::swap;
|
||||
|
||||
@ -24,18 +27,28 @@ use util::swap;
|
||||
|
||||
/// Calculate the offset from a pointer
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
pub fn offset<T>(ptr: *T, count: int) -> *T {
|
||||
unsafe { intrinsics::offset(ptr, count) }
|
||||
}
|
||||
|
||||
/// Calculate the offset from a const pointer
|
||||
#[inline]
|
||||
pub fn const_offset<T>(ptr: *const T, count: int) -> *const T {
|
||||
unsafe { intrinsics::offset(ptr as *T, count) }
|
||||
(ptr as uint + (count as uint) * sys::size_of::<T>()) as *T
|
||||
}
|
||||
|
||||
/// Calculate the offset from a mut pointer
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
|
||||
(ptr as uint + (count as uint) * sys::size_of::<T>()) as *mut T
|
||||
}
|
||||
|
||||
/// Calculate the offset from a pointer
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
pub fn offset<T>(ptr: *T, count: int) -> *T {
|
||||
unsafe { intrinsics::offset(ptr, count) }
|
||||
}
|
||||
|
||||
/// Calculate the offset from a mut pointer
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
|
||||
unsafe { intrinsics::offset(ptr as *T, count) as *mut T }
|
||||
}
|
||||
@ -73,11 +86,11 @@ pub fn mut_null<T>() -> *mut T { 0 as *mut T }
|
||||
|
||||
/// Returns true if the pointer is equal to the null pointer.
|
||||
#[inline]
|
||||
pub fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
|
||||
pub fn is_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_null() }
|
||||
|
||||
/// Returns true if the pointer is not equal to the null pointer.
|
||||
#[inline]
|
||||
pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
|
||||
pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
|
||||
|
||||
/**
|
||||
* Copies data from one location to another.
|
||||
@ -87,8 +100,10 @@ pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(target_word_size = "32")]
|
||||
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
intrinsics::memmove32(dst, src as *T, count as u32);
|
||||
pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
|
||||
intrinsics::memmove32(dst,
|
||||
cast::transmute_immut_unsafe(src),
|
||||
count as u32);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,8 +114,10 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(target_word_size = "64")]
|
||||
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
intrinsics::memmove64(dst, src as *T, count as u64);
|
||||
pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
|
||||
intrinsics::memmove64(dst,
|
||||
cast::transmute_immut_unsafe(src),
|
||||
count as u64);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,8 +128,12 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(target_word_size = "32")]
|
||||
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
intrinsics::memcpy32(dst, src as *T, count as u32);
|
||||
pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
|
||||
src: P,
|
||||
count: uint) {
|
||||
intrinsics::memcpy32(dst,
|
||||
cast::transmute_immut_unsafe(src),
|
||||
count as u32);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,8 +144,12 @@ pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: u
|
||||
*/
|
||||
#[inline]
|
||||
#[cfg(target_word_size = "64")]
|
||||
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
intrinsics::memcpy64(dst, src as *T, count as u64);
|
||||
pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
|
||||
src: P,
|
||||
count: uint) {
|
||||
intrinsics::memcpy64(dst,
|
||||
cast::transmute_immut_unsafe(src),
|
||||
count as u64);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,12 +241,6 @@ pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
|
||||
thing as *T
|
||||
}
|
||||
|
||||
/// Transform a const region pointer - &const T - to a const unsafe pointer - *const T.
|
||||
#[inline]
|
||||
pub fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
|
||||
thing as *const T
|
||||
}
|
||||
|
||||
/// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T.
|
||||
#[inline]
|
||||
pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
|
||||
@ -269,8 +288,10 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
|
||||
|
||||
#[allow(missing_doc)]
|
||||
pub trait RawPtr<T> {
|
||||
fn null() -> Self;
|
||||
fn is_null(&self) -> bool;
|
||||
fn is_not_null(&self) -> bool;
|
||||
fn to_uint(&self) -> uint;
|
||||
unsafe fn to_option(&self) -> Option<&T>;
|
||||
fn offset(&self, count: int) -> Self;
|
||||
unsafe fn offset_inbounds(self, count: int) -> Self;
|
||||
@ -278,13 +299,21 @@ pub trait RawPtr<T> {
|
||||
|
||||
/// Extension methods for immutable pointers
|
||||
impl<T> RawPtr<T> for *T {
|
||||
/// Returns the null pointer.
|
||||
#[inline]
|
||||
fn null() -> *T { null() }
|
||||
|
||||
/// Returns true if the pointer is equal to the null pointer.
|
||||
#[inline]
|
||||
fn is_null(&self) -> bool { is_null(*self) }
|
||||
fn is_null(&self) -> bool { *self == RawPtr::null() }
|
||||
|
||||
/// Returns true if the pointer is not equal to the null pointer.
|
||||
#[inline]
|
||||
fn is_not_null(&self) -> bool { is_not_null(*self) }
|
||||
fn is_not_null(&self) -> bool { *self != RawPtr::null() }
|
||||
|
||||
/// Returns the address of this pointer.
|
||||
#[inline]
|
||||
fn to_uint(&self) -> uint { *self as uint }
|
||||
|
||||
///
|
||||
/// Returns `None` if the pointer is null, or else returns the value wrapped
|
||||
@ -317,13 +346,21 @@ impl<T> RawPtr<T> for *T {
|
||||
|
||||
/// Extension methods for mutable pointers
|
||||
impl<T> RawPtr<T> for *mut T {
|
||||
/// Returns the null pointer.
|
||||
#[inline]
|
||||
fn null() -> *mut T { mut_null() }
|
||||
|
||||
/// Returns true if the pointer is equal to the null pointer.
|
||||
#[inline]
|
||||
fn is_null(&self) -> bool { is_null(*self) }
|
||||
fn is_null(&self) -> bool { *self == RawPtr::null() }
|
||||
|
||||
/// Returns true if the pointer is not equal to the null pointer.
|
||||
#[inline]
|
||||
fn is_not_null(&self) -> bool { is_not_null(*self) }
|
||||
fn is_not_null(&self) -> bool { *self != RawPtr::null() }
|
||||
|
||||
/// Returns the address of this pointer.
|
||||
#[inline]
|
||||
fn to_uint(&self) -> uint { *self as uint }
|
||||
|
||||
///
|
||||
/// Returns `None` if the pointer is null, or else returns the value wrapped
|
||||
@ -360,13 +397,38 @@ impl<T> RawPtr<T> for *mut T {
|
||||
|
||||
// Equality for pointers
|
||||
#[cfg(not(test))]
|
||||
impl<T> Eq for *const T {
|
||||
impl<T> Eq for *T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*const T) -> bool {
|
||||
fn eq(&self, other: &*T) -> bool {
|
||||
(*self as uint) == (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
|
||||
fn ne(&self, other: &*T) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T> Eq for *mut T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*mut T) -> bool {
|
||||
(*self as uint) == (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
// Equivalence for pointers
|
||||
#[cfg(not(test))]
|
||||
impl<T> Equiv<*mut T> for *T {
|
||||
fn equiv(&self, other: &*mut T) -> bool {
|
||||
self.to_uint() == other.to_uint()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T> Equiv<*T> for *mut T {
|
||||
fn equiv(&self, other: &*T) -> bool {
|
||||
self.to_uint() == other.to_uint()
|
||||
}
|
||||
}
|
||||
|
||||
// Equality for extern "C" fn pointers
|
||||
@ -412,21 +474,41 @@ mod externfnpointers {
|
||||
|
||||
// Comparison for pointers
|
||||
#[cfg(not(test))]
|
||||
impl<T> Ord for *const T {
|
||||
impl<T> Ord for *T {
|
||||
#[inline]
|
||||
fn lt(&self, other: &*const T) -> bool {
|
||||
fn lt(&self, other: &*T) -> bool {
|
||||
(*self as uint) < (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &*const T) -> bool {
|
||||
fn le(&self, other: &*T) -> bool {
|
||||
(*self as uint) <= (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &*const T) -> bool {
|
||||
fn ge(&self, other: &*T) -> bool {
|
||||
(*self as uint) >= (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &*const T) -> bool {
|
||||
fn gt(&self, other: &*T) -> bool {
|
||||
(*self as uint) > (*other as uint)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T> Ord for *mut T {
|
||||
#[inline]
|
||||
fn lt(&self, other: &*mut T) -> bool {
|
||||
(*self as uint) < (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &*mut T) -> bool {
|
||||
(*self as uint) <= (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &*mut T) -> bool {
|
||||
(*self as uint) >= (*other as uint)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &*mut T) -> bool {
|
||||
(*self as uint) > (*other as uint)
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,18 @@
|
||||
use cell::Cell;
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use libc::{c_char, size_t, STDERR_FILENO};
|
||||
use io;
|
||||
use io::{Writer, WriterUtil};
|
||||
use io;
|
||||
use libc::{c_char, size_t, STDERR_FILENO};
|
||||
use option::{Option, None, Some};
|
||||
use uint;
|
||||
use ptr::RawPtr;
|
||||
use rt::env;
|
||||
use rt::local::Local;
|
||||
use rt::task::Task;
|
||||
use str;
|
||||
use str::{OwnedStr, StrSlice};
|
||||
use str;
|
||||
use sys;
|
||||
use uint;
|
||||
use unstable::raw;
|
||||
use vec::ImmutableVector;
|
||||
|
||||
@ -37,7 +38,7 @@ pub struct BorrowRecord {
|
||||
}
|
||||
|
||||
fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> {
|
||||
do Local::borrow::<Task, Option<~[BorrowRecord]>> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
task.borrow_list.take()
|
||||
}
|
||||
}
|
||||
@ -49,7 +50,7 @@ fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
|
||||
};
|
||||
let borrows = f(borrows);
|
||||
let borrows = Cell::new(borrows);
|
||||
do Local::borrow::<Task, ()> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
task.borrow_list = Some(borrows.take());
|
||||
}
|
||||
}
|
||||
@ -93,12 +94,12 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
|
||||
static ENABLE_DEBUG: bool = false;
|
||||
|
||||
#[inline]
|
||||
unsafe fn debug_borrow<T>(tag: &'static str,
|
||||
p: *const T,
|
||||
old_bits: uint,
|
||||
new_bits: uint,
|
||||
filename: *c_char,
|
||||
line: size_t) {
|
||||
unsafe fn debug_borrow<T,P:RawPtr<T>>(tag: &'static str,
|
||||
p: P,
|
||||
old_bits: uint,
|
||||
new_bits: uint,
|
||||
filename: *c_char,
|
||||
line: size_t) {
|
||||
//! A useful debugging function that prints a pointer + tag + newline
|
||||
//! without allocating memory.
|
||||
|
||||
@ -106,15 +107,15 @@ unsafe fn debug_borrow<T>(tag: &'static str,
|
||||
debug_borrow_slow(tag, p, old_bits, new_bits, filename, line);
|
||||
}
|
||||
|
||||
unsafe fn debug_borrow_slow<T>(tag: &'static str,
|
||||
p: *const T,
|
||||
old_bits: uint,
|
||||
new_bits: uint,
|
||||
filename: *c_char,
|
||||
line: size_t) {
|
||||
unsafe fn debug_borrow_slow<T,P:RawPtr<T>>(tag: &'static str,
|
||||
p: P,
|
||||
old_bits: uint,
|
||||
new_bits: uint,
|
||||
filename: *c_char,
|
||||
line: size_t) {
|
||||
let dbg = STDERR_FILENO as io::fd_t;
|
||||
dbg.write_str(tag);
|
||||
dbg.write_hex(p as uint);
|
||||
dbg.write_hex(p.to_uint());
|
||||
dbg.write_str(" ");
|
||||
dbg.write_hex(old_bits);
|
||||
dbg.write_str(" ");
|
||||
|
@ -159,7 +159,7 @@ impl<T> ChanOne<T> {
|
||||
};
|
||||
} else {
|
||||
let recvr = Cell::new(recvr);
|
||||
do Local::borrow::<Scheduler, ()> |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
sched.enqueue_blocked_task(recvr.take());
|
||||
}
|
||||
}
|
||||
@ -199,7 +199,7 @@ impl<T> PortOne<T> {
|
||||
if !this.optimistic_check() {
|
||||
// No data available yet.
|
||||
// Switch to the scheduler to put the ~Task into the Packet state.
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
this.block_on(sched, task);
|
||||
}
|
||||
@ -221,7 +221,7 @@ impl<T> SelectInner for PortOne<T> {
|
||||
// The optimistic check is never necessary for correctness. For testing
|
||||
// purposes, making it randomly return false simulates a racing sender.
|
||||
use rand::{Rand};
|
||||
let actually_check = do Local::borrow::<Scheduler, bool> |sched| {
|
||||
let actually_check = do Local::borrow |sched: &mut Scheduler| {
|
||||
Rand::rand(&mut sched.rng)
|
||||
};
|
||||
if actually_check {
|
||||
|
@ -24,7 +24,7 @@ pub fn open<P: PathLike>(path: &P,
|
||||
access: FileAccess
|
||||
) -> Option<FileStream> {
|
||||
let open_result = unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*io).fs_open(path, mode, access)
|
||||
};
|
||||
match open_result {
|
||||
@ -43,7 +43,7 @@ pub fn open<P: PathLike>(path: &P,
|
||||
/// by `path`.
|
||||
pub fn unlink<P: PathLike>(path: &P) {
|
||||
let unlink_result = unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*io).fs_unlink(path)
|
||||
};
|
||||
match unlink_result {
|
||||
|
@ -359,7 +359,7 @@ impl FromStr for SocketAddr {
|
||||
mod test {
|
||||
use super::*;
|
||||
use from_str::FromStr;
|
||||
use option::{Some, None};
|
||||
use option::{Option, Some, None};
|
||||
|
||||
#[test]
|
||||
fn test_from_str_ipv4() {
|
||||
@ -368,13 +368,17 @@ mod test {
|
||||
assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
|
||||
|
||||
// out of range
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("256.0.0.1"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
|
||||
assert_eq!(None, none);
|
||||
// too short
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("255.0.0");
|
||||
assert_eq!(None, none);
|
||||
// too long
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0.1.2"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
|
||||
assert_eq!(None, none);
|
||||
// no number between dots
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0..1"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("255.0..1");
|
||||
assert_eq!(None, none);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -389,15 +393,20 @@ mod test {
|
||||
FromStr::from_str("2a02:6b8::11:11"));
|
||||
|
||||
// too long group
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("::00000"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("::00000");
|
||||
assert_eq!(None, none);
|
||||
// too short
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
|
||||
assert_eq!(None, none);
|
||||
// too long
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7:8:9"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
|
||||
assert_eq!(None, none);
|
||||
// triple colon
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:::6:7:8"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
|
||||
assert_eq!(None, none);
|
||||
// two double colons
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2::6::8"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
|
||||
assert_eq!(None, none);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -412,11 +421,15 @@ mod test {
|
||||
FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
|
||||
|
||||
// colon after v4
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("::127.0.0.1:"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
|
||||
assert_eq!(None, none);
|
||||
// not enought groups
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:127.0.0.1"));
|
||||
let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
|
||||
assert_eq!(None, none);
|
||||
// too many groups
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:6:7:127.0.0.1"));
|
||||
let none: Option<IpAddr> =
|
||||
FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
|
||||
assert_eq!(None, none);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -429,13 +442,17 @@ mod test {
|
||||
FromStr::from_str("[::127.0.0.1]:22"));
|
||||
|
||||
// without port
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1"));
|
||||
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
|
||||
assert_eq!(None, none);
|
||||
// without port
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:"));
|
||||
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
|
||||
assert_eq!(None, none);
|
||||
// wrong brackets around v4
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("[127.0.0.1]:22"));
|
||||
let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
|
||||
assert_eq!(None, none);
|
||||
// port out of range
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:123456"));
|
||||
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
|
||||
assert_eq!(None, none);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -29,7 +29,7 @@ impl TcpStream {
|
||||
pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
|
||||
let stream = unsafe {
|
||||
rtdebug!("borrowing io to connect");
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
rtdebug!("about to connect");
|
||||
(*io).tcp_connect(addr)
|
||||
};
|
||||
@ -100,7 +100,7 @@ pub struct TcpListener(~RtioTcpListenerObject);
|
||||
impl TcpListener {
|
||||
pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
|
||||
let listener = unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*io).tcp_bind(addr)
|
||||
};
|
||||
match listener {
|
||||
|
@ -20,7 +20,10 @@ pub struct UdpSocket(~RtioUdpSocketObject);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(addr: SocketAddr) -> Option<UdpSocket> {
|
||||
let socket = unsafe { (*Local::unsafe_borrow::<IoFactoryObject>()).udp_bind(addr) };
|
||||
let socket = unsafe {
|
||||
let factory: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*factory).udp_bind(addr)
|
||||
};
|
||||
match socket {
|
||||
Ok(s) => Some(UdpSocket(s)),
|
||||
Err(ioerr) => {
|
||||
|
@ -22,7 +22,7 @@ impl Timer {
|
||||
pub fn new() -> Option<Timer> {
|
||||
let timer = unsafe {
|
||||
rtdebug!("Timer::init: borrowing io to init timer");
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
rtdebug!("about to init timer");
|
||||
(*io).timer_init()
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ use cell::Cell;
|
||||
pub trait Local {
|
||||
fn put(value: ~Self);
|
||||
fn take() -> ~Self;
|
||||
fn exists() -> bool;
|
||||
fn exists(unused_value: Option<Self>) -> bool;
|
||||
fn borrow<T>(f: &fn(&mut Self) -> T) -> T;
|
||||
unsafe fn unsafe_take() -> ~Self;
|
||||
unsafe fn unsafe_borrow() -> *mut Self;
|
||||
@ -31,7 +31,7 @@ impl Local for Task {
|
||||
fn put(value: ~Task) { unsafe { local_ptr::put(value) } }
|
||||
#[inline]
|
||||
fn take() -> ~Task { unsafe { local_ptr::take() } }
|
||||
fn exists() -> bool { local_ptr::exists() }
|
||||
fn exists(_: Option<Task>) -> bool { local_ptr::exists() }
|
||||
fn borrow<T>(f: &fn(&mut Task) -> T) -> T {
|
||||
let mut res: Option<T> = None;
|
||||
let res_ptr: *mut Option<T> = &mut res;
|
||||
@ -59,7 +59,7 @@ impl Local for Task {
|
||||
impl Local for Scheduler {
|
||||
fn put(value: ~Scheduler) {
|
||||
let value = Cell::new(value);
|
||||
do Local::borrow::<Task,()> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
let task = task;
|
||||
task.sched = Some(value.take());
|
||||
};
|
||||
@ -68,12 +68,12 @@ impl Local for Scheduler {
|
||||
fn take() -> ~Scheduler {
|
||||
unsafe {
|
||||
// XXX: Unsafe for speed
|
||||
let task = Local::unsafe_borrow::<Task>();
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
(*task).sched.take_unwrap()
|
||||
}
|
||||
}
|
||||
fn exists() -> bool {
|
||||
do Local::borrow::<Task,bool> |task| {
|
||||
fn exists(_: Option<Scheduler>) -> bool {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
match task.sched {
|
||||
Some(ref _task) => true,
|
||||
None => false
|
||||
@ -81,7 +81,7 @@ impl Local for Scheduler {
|
||||
}
|
||||
}
|
||||
fn borrow<T>(f: &fn(&mut Scheduler) -> T) -> T {
|
||||
do Local::borrow::<Task, T> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
match task.sched {
|
||||
Some(~ref mut task) => {
|
||||
f(task)
|
||||
@ -94,7 +94,8 @@ impl Local for Scheduler {
|
||||
}
|
||||
unsafe fn unsafe_take() -> ~Scheduler { rtabort!("unimpl") }
|
||||
unsafe fn unsafe_borrow() -> *mut Scheduler {
|
||||
match (*Local::unsafe_borrow::<Task>()).sched {
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
match (*task).sched {
|
||||
Some(~ref mut sched) => {
|
||||
let s: *mut Scheduler = &mut *sched;
|
||||
return s;
|
||||
@ -105,7 +106,8 @@ impl Local for Scheduler {
|
||||
}
|
||||
}
|
||||
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task_opt: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task_opt {
|
||||
Some(task) => {
|
||||
match (*task).sched {
|
||||
Some(~ref mut sched) => {
|
||||
@ -124,15 +126,17 @@ impl Local for Scheduler {
|
||||
impl Local for IoFactoryObject {
|
||||
fn put(_value: ~IoFactoryObject) { rtabort!("unimpl") }
|
||||
fn take() -> ~IoFactoryObject { rtabort!("unimpl") }
|
||||
fn exists() -> bool { rtabort!("unimpl") }
|
||||
fn exists(_: Option<IoFactoryObject>) -> bool { rtabort!("unimpl") }
|
||||
fn borrow<T>(_f: &fn(&mut IoFactoryObject) -> T) -> T { rtabort!("unimpl") }
|
||||
unsafe fn unsafe_take() -> ~IoFactoryObject { rtabort!("unimpl") }
|
||||
unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
|
||||
let sched = Local::unsafe_borrow::<Scheduler>();
|
||||
let sched: *mut Scheduler = Local::unsafe_borrow();
|
||||
let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
|
||||
return io;
|
||||
}
|
||||
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { rtabort!("unimpl") }
|
||||
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> {
|
||||
rtabort!("unimpl")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -198,7 +202,7 @@ mod test {
|
||||
let task = ~Task::new_root(&mut sched.stack_pool, None, || {});
|
||||
Local::put(task);
|
||||
|
||||
let res = do Local::borrow::<Task,bool> |_task| {
|
||||
let res = do Local::borrow |_task: &mut Task| {
|
||||
true
|
||||
};
|
||||
assert!(res)
|
||||
|
@ -13,7 +13,7 @@
|
||||
use libc;
|
||||
use libc::{c_void, uintptr_t, size_t};
|
||||
use ops::Drop;
|
||||
use option::{Some, None};
|
||||
use option::{Option, None, Some};
|
||||
use rt::local::Local;
|
||||
use rt::task::Task;
|
||||
use unstable::raw;
|
||||
@ -89,7 +89,8 @@ impl Drop for LocalHeap {
|
||||
// A little compatibility function
|
||||
pub unsafe fn local_free(ptr: *libc::c_char) {
|
||||
// XXX: Unsafe borrow for speed. Lame.
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task_ptr {
|
||||
Some(task) => {
|
||||
(*task).heap.free(ptr as *libc::c_void);
|
||||
}
|
||||
@ -98,7 +99,7 @@ pub unsafe fn local_free(ptr: *libc::c_char) {
|
||||
}
|
||||
|
||||
pub fn live_allocs() -> *raw::Box<()> {
|
||||
let region = do Local::borrow::<Task, *BoxedRegion> |task| {
|
||||
let region = do Local::borrow |task: &mut Task| {
|
||||
task.heap.boxed_region
|
||||
};
|
||||
|
||||
|
@ -64,7 +64,7 @@ use cell::Cell;
|
||||
use clone::Clone;
|
||||
use container::Container;
|
||||
use iterator::{Iterator, range};
|
||||
use option::{Some, None};
|
||||
use option::{Option, None, Some};
|
||||
use ptr::RawPtr;
|
||||
use rt::local::Local;
|
||||
use rt::sched::{Scheduler, Shutdown};
|
||||
@ -408,7 +408,8 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
|
||||
|
||||
pub fn in_sched_context() -> bool {
|
||||
unsafe {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task_ptr {
|
||||
Some(task) => {
|
||||
match (*task).task_type {
|
||||
SchedTask => true,
|
||||
@ -422,7 +423,8 @@ pub fn in_sched_context() -> bool {
|
||||
|
||||
pub fn in_green_task_context() -> bool {
|
||||
unsafe {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task {
|
||||
Some(task) => {
|
||||
match (*task).task_type {
|
||||
GreenTask(_) => true,
|
||||
|
@ -169,13 +169,13 @@ impl Scheduler {
|
||||
// successfully run the input task. Start by running the
|
||||
// scheduler. Grab it out of TLS - performing the scheduler
|
||||
// action will have given it away.
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
|
||||
rtdebug!("starting scheduler %u", sched.sched_id());
|
||||
sched.run();
|
||||
|
||||
// Close the idle callback.
|
||||
let mut sched = Local::take::<Scheduler>();
|
||||
let mut sched: ~Scheduler = Local::take();
|
||||
sched.idle_callback.get_mut_ref().close();
|
||||
// Make one go through the loop to run the close callback.
|
||||
sched.run();
|
||||
@ -185,7 +185,7 @@ impl Scheduler {
|
||||
// cleaning up the memory it uses. As we didn't actually call
|
||||
// task.run() on the scheduler task we never get through all
|
||||
// the cleanup code it runs.
|
||||
let mut stask = Local::take::<Task>();
|
||||
let mut stask: ~Task = Local::take();
|
||||
|
||||
rtdebug!("stopping scheduler %u", stask.sched.get_ref().sched_id());
|
||||
|
||||
@ -212,7 +212,7 @@ impl Scheduler {
|
||||
// Our scheduler must be in the task before the event loop
|
||||
// is started.
|
||||
let self_sched = Cell::new(self_sched);
|
||||
do Local::borrow::<Task,()> |stask| {
|
||||
do Local::borrow |stask: &mut Task| {
|
||||
stask.sched = Some(self_sched.take());
|
||||
};
|
||||
|
||||
@ -234,7 +234,7 @@ impl Scheduler {
|
||||
// already have a scheduler stored in our local task, so we
|
||||
// start off by taking it. This is the only path through the
|
||||
// scheduler where we get the scheduler this way.
|
||||
let mut sched = Local::take::<Scheduler>();
|
||||
let mut sched: ~Scheduler = Local::take();
|
||||
|
||||
// Assume that we need to continue idling unless we reach the
|
||||
// end of this function without performing an action.
|
||||
@ -522,7 +522,7 @@ impl Scheduler {
|
||||
// The current task is grabbed from TLS, not taken as an input.
|
||||
// Doing an unsafe_take to avoid writing back a null pointer -
|
||||
// We're going to call `put` later to do that.
|
||||
let current_task: ~Task = unsafe { Local::unsafe_take::<Task>() };
|
||||
let current_task: ~Task = unsafe { Local::unsafe_take() };
|
||||
|
||||
// Check that the task is not in an atomically() section (e.g.,
|
||||
// holding a pthread mutex, which could deadlock the scheduler).
|
||||
@ -554,7 +554,8 @@ impl Scheduler {
|
||||
|
||||
let current_task: &mut Task = match sched.cleanup_job {
|
||||
Some(CleanupJob { task: ref task, _ }) => {
|
||||
transmute_mut_region(*transmute_mut_unsafe(task))
|
||||
let task_ptr: *~Task = task;
|
||||
transmute_mut_region(*transmute_mut_unsafe(task_ptr))
|
||||
}
|
||||
None => {
|
||||
rtabort!("no cleanup job");
|
||||
@ -580,7 +581,7 @@ impl Scheduler {
|
||||
// run the cleanup job, as expected by the previously called
|
||||
// swap_contexts function.
|
||||
unsafe {
|
||||
let task = Local::unsafe_borrow::<Task>();
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
(*task).sched.get_mut_ref().run_cleanup_job();
|
||||
|
||||
// Must happen after running the cleanup job (of course).
|
||||
@ -685,13 +686,13 @@ impl Scheduler {
|
||||
}
|
||||
|
||||
pub fn run_task(task: ~Task) {
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
sched.process_task(task, Scheduler::switch_task).map_move(Local::put);
|
||||
}
|
||||
|
||||
pub fn run_task_later(next_task: ~Task) {
|
||||
let next_task = Cell::new(next_task);
|
||||
do Local::borrow::<Scheduler,()> |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
sched.enqueue_task(next_task.take());
|
||||
};
|
||||
}
|
||||
@ -1023,12 +1024,12 @@ mod test {
|
||||
// exit before emptying the work queue
|
||||
do run_in_newsched_task {
|
||||
do spawntask {
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
let task = Cell::new(task);
|
||||
do sched.event_loop.callback_ms(10) {
|
||||
rtdebug!("in callback");
|
||||
let mut sched = Local::take::<Scheduler>();
|
||||
let mut sched: ~Scheduler = Local::take();
|
||||
sched.enqueue_blocked_task(task.take());
|
||||
Local::put(sched);
|
||||
}
|
||||
|
@ -26,3 +26,4 @@ pub trait SelectInner {
|
||||
pub trait SelectPortInner<T> {
|
||||
fn recv_ready(self) -> Option<T>;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ impl 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| {
|
||||
do Local::borrow |running_task: &mut Task| {
|
||||
let mut sched = running_task.sched.take_unwrap();
|
||||
let new_task = ~running_task.new_child_homed(&mut sched.stack_pool,
|
||||
stack_size,
|
||||
@ -111,7 +111,7 @@ impl 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| {
|
||||
do Local::borrow |running_task: &mut Task| {
|
||||
let mut sched = running_task.sched.take_unwrap();
|
||||
let new_task = ~Task::new_root_homed(&mut sched.stack_pool,
|
||||
stack_size,
|
||||
@ -305,7 +305,7 @@ impl Task {
|
||||
// Grab both the scheduler and the task from TLS and check if the
|
||||
// task is executing on an appropriate scheduler.
|
||||
pub fn on_appropriate_sched() -> bool {
|
||||
do Local::borrow::<Task,bool> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
let sched_id = task.sched.get_ref().sched_id();
|
||||
let sched_run_anything = task.sched.get_ref().run_anything;
|
||||
match task.task_type {
|
||||
@ -369,7 +369,7 @@ impl Coroutine {
|
||||
unsafe {
|
||||
|
||||
// Again - might work while safe, or it might not.
|
||||
do Local::borrow::<Scheduler,()> |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
sched.run_cleanup_job();
|
||||
}
|
||||
|
||||
@ -378,7 +378,7 @@ impl Coroutine {
|
||||
// simply unsafe_borrow it to get this reference. We
|
||||
// need to still have the task in TLS though, so we
|
||||
// need to unsafe_borrow.
|
||||
let task = Local::unsafe_borrow::<Task>();
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
|
||||
do (*task).run {
|
||||
// N.B. Removing `start` from the start wrapper
|
||||
@ -397,7 +397,7 @@ impl Coroutine {
|
||||
}
|
||||
|
||||
// We remove the sched from the Task in TLS right now.
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
// ... allowing us to give it away when performing a
|
||||
// scheduling operation.
|
||||
sched.terminate_current_task()
|
||||
|
@ -51,7 +51,7 @@ impl<T> Tube<T> {
|
||||
// There's a waiting task. Wake it up
|
||||
rtdebug!("waking blocked tube");
|
||||
let task = (*state).blocked_task.take_unwrap();
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
sched.resume_blocked_task_immediately(task);
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@ impl<T> Tube<T> {
|
||||
rtdebug!("blocking on tube recv");
|
||||
assert!(self.p.refcount() > 1); // There better be somebody to wake us up
|
||||
assert!((*state).blocked_task.is_none());
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |_, task| {
|
||||
(*state).blocked_task = Some(task);
|
||||
}
|
||||
@ -102,7 +102,7 @@ mod test {
|
||||
let mut tube: Tube<int> = Tube::new();
|
||||
let tube_clone = tube.clone();
|
||||
let tube_clone_cell = Cell::new(tube_clone);
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
let mut tube_clone = tube_clone_cell.take();
|
||||
tube_clone.send(1);
|
||||
@ -119,7 +119,7 @@ mod test {
|
||||
let mut tube: Tube<int> = Tube::new();
|
||||
let tube_clone = tube.clone();
|
||||
let tube_clone = Cell::new(tube_clone);
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
let tube_clone = Cell::new(tube_clone.take());
|
||||
do sched.event_loop.callback {
|
||||
@ -143,7 +143,7 @@ mod test {
|
||||
let mut tube: Tube<int> = Tube::new();
|
||||
let tube_clone = tube.clone();
|
||||
let tube_clone = Cell::new(tube_clone);
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
callback_send(tube_clone.take(), 0);
|
||||
|
||||
@ -151,7 +151,7 @@ mod test {
|
||||
if i == 100 { return; }
|
||||
|
||||
let tube = Cell::new(Cell::new(tube));
|
||||
do Local::borrow::<Scheduler, ()> |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
let tube = tube.take();
|
||||
do sched.event_loop.callback {
|
||||
let mut tube = tube.take();
|
||||
|
@ -57,7 +57,7 @@ trait HomingIO {
|
||||
let old_home = Cell::new_empty();
|
||||
let old_home_ptr = &old_home;
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
// get the old home first
|
||||
do task.wake().map_move |mut task| {
|
||||
@ -72,7 +72,7 @@ trait HomingIO {
|
||||
|
||||
// unhome home
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |scheduler, task| {
|
||||
do task.wake().map_move |mut task| {
|
||||
task.give_home(old_home.take());
|
||||
@ -92,7 +92,7 @@ trait HomingIO {
|
||||
// go home
|
||||
let old_home = Cell::new_empty();
|
||||
let old_home_ptr = &old_home;
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
// get the old home first
|
||||
do task.wake().map_move |mut task| {
|
||||
@ -102,11 +102,11 @@ trait HomingIO {
|
||||
}
|
||||
|
||||
// do IO
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
let a = io_sched(self, scheduler);
|
||||
|
||||
// unhome home
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |scheduler, task| {
|
||||
do task.wake().map_move |mut task| {
|
||||
task.give_home(old_home.take());
|
||||
@ -122,7 +122,7 @@ trait HomingIO {
|
||||
|
||||
// get a handle for the current scheduler
|
||||
macro_rules! get_handle_to_current_scheduler(
|
||||
() => (do Local::borrow::<Scheduler, SchedHandle> |sched| { sched.make_handle() })
|
||||
() => (do Local::borrow |sched: &mut Scheduler| { sched.make_handle() })
|
||||
)
|
||||
|
||||
enum SocketNameKind {
|
||||
@ -375,7 +375,7 @@ mod test_remote {
|
||||
let mut tube = Tube::new();
|
||||
let tube_clone = tube.clone();
|
||||
let remote_cell = Cell::new_empty();
|
||||
do Local::borrow::<Scheduler, ()>() |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
let tube_clone = tube_clone.clone();
|
||||
let tube_clone_cell = Cell::new(tube_clone);
|
||||
let remote = do sched.event_loop.remote_callback {
|
||||
@ -416,7 +416,7 @@ impl IoFactory for UvIoFactory {
|
||||
|
||||
// Block this task and take ownership, switch to scheduler context
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
|
||||
let mut tcp = TcpWatcher::new(self.uv_loop());
|
||||
@ -434,7 +434,7 @@ impl IoFactory for UvIoFactory {
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
|
||||
// Context switch
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
Some(_) => {
|
||||
@ -442,7 +442,7 @@ impl IoFactory for UvIoFactory {
|
||||
do stream.close {
|
||||
let res = Err(uv_error_to_io_error(status.unwrap()));
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -464,11 +464,11 @@ impl IoFactory for UvIoFactory {
|
||||
}
|
||||
Err(uverr) => {
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do watcher.as_stream().close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -487,11 +487,11 @@ impl IoFactory for UvIoFactory {
|
||||
}
|
||||
Err(uverr) => {
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do watcher.close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -539,7 +539,7 @@ impl IoFactory for UvIoFactory {
|
||||
IoError>> = &result_cell;
|
||||
let path_cell = Cell::new(path);
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
let path = path_cell.take();
|
||||
@ -553,12 +553,12 @@ impl IoFactory for UvIoFactory {
|
||||
loop_, fd, true, home) as ~RtioFileStream;
|
||||
let res = Ok(fs);
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
} else {
|
||||
let res = Err(uv_error_to_io_error(err.unwrap()));
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
};
|
||||
@ -573,7 +573,7 @@ impl IoFactory for UvIoFactory {
|
||||
let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
|
||||
let path_cell = Cell::new(path);
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
let path = path_cell.take();
|
||||
@ -583,7 +583,7 @@ impl IoFactory for UvIoFactory {
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
};
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
@ -625,7 +625,7 @@ impl Drop for UvTcpListener {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.watcher().as_stream().close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -717,7 +717,7 @@ impl Drop for UvTcpStream {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.watcher.as_stream().close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -765,7 +765,7 @@ impl RtioTcpStream for UvTcpStream {
|
||||
|
||||
unsafe { (*result_cell_ptr).put_back(result); }
|
||||
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -793,7 +793,7 @@ impl RtioTcpStream for UvTcpStream {
|
||||
|
||||
unsafe { (*result_cell_ptr).put_back(result); }
|
||||
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -876,7 +876,7 @@ impl Drop for UvUdpSocket {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.watcher.close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -917,7 +917,7 @@ impl RtioUdpSocket for UvUdpSocket {
|
||||
|
||||
unsafe { (*result_cell_ptr).put_back(result); }
|
||||
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -944,7 +944,7 @@ impl RtioUdpSocket for UvUdpSocket {
|
||||
|
||||
unsafe { (*result_cell_ptr).put_back(result); }
|
||||
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -1094,7 +1094,7 @@ impl Drop for UvTimer {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.watcher.close {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -1110,7 +1110,7 @@ impl RtioTimer for UvTimer {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.watcher.start(msecs, 0) |_, status| {
|
||||
assert!(status.is_none());
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
}
|
||||
}
|
||||
@ -1154,7 +1154,7 @@ impl UvFileStream {
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
};
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
@ -1175,7 +1175,7 @@ impl UvFileStream {
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
};
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
@ -1208,7 +1208,7 @@ impl Drop for UvFileStream {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.fd.close(&self.loop_) |_,_| {
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
@ -1254,7 +1254,7 @@ impl RtioFileStream for UvFileStream {
|
||||
fn test_simple_io_no_connect() {
|
||||
do run_in_newsched_task {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let addr = next_test_ip4();
|
||||
let maybe_chan = (*io).tcp_connect(addr);
|
||||
assert!(maybe_chan.is_err());
|
||||
@ -1266,7 +1266,7 @@ fn test_simple_io_no_connect() {
|
||||
fn test_simple_udp_io_bind_only() {
|
||||
do run_in_newsched_task {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let addr = next_test_ip4();
|
||||
let maybe_socket = (*io).udp_bind(addr);
|
||||
assert!(maybe_socket.is_ok());
|
||||
@ -1303,7 +1303,9 @@ fn test_simple_homed_udp_io_bind_then_move_task_then_home_and_close() {
|
||||
};
|
||||
|
||||
let test_function: ~fn() = || {
|
||||
let io = unsafe { Local::unsafe_borrow::<IoFactoryObject>() };
|
||||
let io: *mut IoFactoryObject = unsafe {
|
||||
Local::unsafe_borrow()
|
||||
};
|
||||
let addr = next_test_ip4();
|
||||
let maybe_socket = unsafe { (*io).udp_bind(addr) };
|
||||
// this socket is bound to this event loop
|
||||
@ -1311,7 +1313,7 @@ fn test_simple_homed_udp_io_bind_then_move_task_then_home_and_close() {
|
||||
|
||||
// block self on sched1
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
// unblock task
|
||||
do task.wake().map_move |task| {
|
||||
@ -1377,7 +1379,9 @@ fn test_simple_homed_udp_io_bind_then_move_handle_then_home_and_close() {
|
||||
let chan = Cell::new(chan);
|
||||
|
||||
let body1: ~fn() = || {
|
||||
let io = unsafe { Local::unsafe_borrow::<IoFactoryObject>() };
|
||||
let io: *mut IoFactoryObject = unsafe {
|
||||
Local::unsafe_borrow()
|
||||
};
|
||||
let addr = next_test_ip4();
|
||||
let socket = unsafe { (*io).udp_bind(addr) };
|
||||
assert!(socket.is_ok());
|
||||
@ -1430,7 +1434,7 @@ fn test_simple_tcp_server_and_client() {
|
||||
// Start the server first so it's listening when we connect
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut listener = (*io).tcp_bind(addr).unwrap();
|
||||
let mut stream = listener.accept().unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
@ -1445,7 +1449,7 @@ fn test_simple_tcp_server_and_client() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut stream = (*io).tcp_connect(addr).unwrap();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
}
|
||||
@ -1489,7 +1493,9 @@ fn test_simple_tcp_server_and_client_on_diff_threads() {
|
||||
};
|
||||
|
||||
let server_fn: ~fn() = || {
|
||||
let io = unsafe { Local::unsafe_borrow::<IoFactoryObject>() };
|
||||
let io: *mut IoFactoryObject = unsafe {
|
||||
Local::unsafe_borrow()
|
||||
};
|
||||
let mut listener = unsafe { (*io).tcp_bind(server_addr).unwrap() };
|
||||
let mut stream = listener.accept().unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
@ -1501,7 +1507,9 @@ fn test_simple_tcp_server_and_client_on_diff_threads() {
|
||||
};
|
||||
|
||||
let client_fn: ~fn() = || {
|
||||
let io = unsafe { Local::unsafe_borrow::<IoFactoryObject>() };
|
||||
let io: *mut IoFactoryObject = unsafe {
|
||||
Local::unsafe_borrow()
|
||||
};
|
||||
let mut stream = unsafe { (*io).tcp_connect(client_addr) };
|
||||
while stream.is_err() {
|
||||
stream = unsafe { (*io).tcp_connect(client_addr) };
|
||||
@ -1540,7 +1548,7 @@ fn test_simple_udp_server_and_client() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut server_socket = (*io).udp_bind(server_addr).unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
let (nread,src) = server_socket.recvfrom(buf).unwrap();
|
||||
@ -1555,7 +1563,7 @@ fn test_simple_udp_server_and_client() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut client_socket = (*io).udp_bind(client_addr).unwrap();
|
||||
client_socket.sendto([0, 1, 2, 3, 4, 5, 6, 7], server_addr);
|
||||
}
|
||||
@ -1569,7 +1577,7 @@ fn test_read_and_block() {
|
||||
let addr = next_test_ip4();
|
||||
|
||||
do spawntask {
|
||||
let io = unsafe { Local::unsafe_borrow::<IoFactoryObject>() };
|
||||
let io: *mut IoFactoryObject = unsafe { Local::unsafe_borrow() };
|
||||
let mut listener = unsafe { (*io).tcp_bind(addr).unwrap() };
|
||||
let mut stream = listener.accept().unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
@ -1588,7 +1596,7 @@ fn test_read_and_block() {
|
||||
reads += 1;
|
||||
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler = Local::take::<Scheduler>();
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
// Yield to the other task in hopes that it
|
||||
// will trigger a read callback while we are
|
||||
// not ready for it
|
||||
@ -1605,7 +1613,7 @@ fn test_read_and_block() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut stream = (*io).tcp_connect(addr).unwrap();
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
@ -1625,7 +1633,7 @@ fn test_read_read_read() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut listener = (*io).tcp_bind(addr).unwrap();
|
||||
let mut stream = listener.accept().unwrap();
|
||||
let buf = [1, .. 2048];
|
||||
@ -1639,7 +1647,7 @@ fn test_read_read_read() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut stream = (*io).tcp_connect(addr).unwrap();
|
||||
let mut buf = [0, .. 2048];
|
||||
let mut total_bytes_read = 0;
|
||||
@ -1665,7 +1673,7 @@ fn test_udp_twice() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut client = (*io).udp_bind(client_addr).unwrap();
|
||||
assert!(client.sendto([1], server_addr).is_ok());
|
||||
assert!(client.sendto([2], server_addr).is_ok());
|
||||
@ -1674,7 +1682,7 @@ fn test_udp_twice() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut server = (*io).udp_bind(server_addr).unwrap();
|
||||
let mut buf1 = [0];
|
||||
let mut buf2 = [0];
|
||||
@ -1702,7 +1710,7 @@ fn test_udp_many_read() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut server_out = (*io).udp_bind(server_out_addr).unwrap();
|
||||
let mut server_in = (*io).udp_bind(server_in_addr).unwrap();
|
||||
let msg = [1, .. 2048];
|
||||
@ -1725,7 +1733,7 @@ fn test_udp_many_read() {
|
||||
|
||||
do spawntask {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let mut client_out = (*io).udp_bind(client_out_addr).unwrap();
|
||||
let mut client_in = (*io).udp_bind(client_in_addr).unwrap();
|
||||
let mut total_bytes_recv = 0;
|
||||
@ -1754,7 +1762,7 @@ fn test_udp_many_read() {
|
||||
fn test_timer_sleep_simple() {
|
||||
do run_in_newsched_task {
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let timer = (*io).timer_init();
|
||||
do timer.map_move |mut t| { t.sleep(1) };
|
||||
}
|
||||
@ -1768,7 +1776,7 @@ fn file_test_uvio_full_simple_impl() {
|
||||
use path::Path;
|
||||
use rt::io::{Open, Create, ReadWrite, Read};
|
||||
unsafe {
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
let write_val = "hello uvio!";
|
||||
let path = "./tmp/file_test_uvio_full.txt";
|
||||
{
|
||||
@ -1802,7 +1810,7 @@ fn uvio_naive_print(input: &str) {
|
||||
use str::StrSlice;
|
||||
unsafe {
|
||||
use libc::{STDOUT_FILENO};
|
||||
let io = Local::unsafe_borrow::<IoFactoryObject>();
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
{
|
||||
let mut fd = (*io).fs_from_raw_fd(STDOUT_FILENO, false);
|
||||
let write_buf = input.as_bytes();
|
||||
|
@ -60,7 +60,7 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
|
||||
|
||||
do (|| {
|
||||
let c = Cell::new(c.take());
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
let task_handles = task.make_selectable(ports.len());
|
||||
|
||||
|
@ -143,7 +143,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
if in_green_task_context() {
|
||||
// XXX: Logging doesn't work here - the check to call the log
|
||||
// function never passes - so calling the log function directly.
|
||||
do Local::borrow::<Task, ()> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
let msg = match task.name {
|
||||
Some(ref name) =>
|
||||
fmt!("task '%s' failed at '%s', %s:%i",
|
||||
@ -160,7 +160,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
msg, file, line as int);
|
||||
}
|
||||
|
||||
let task = Local::unsafe_borrow::<Task>();
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
if (*task).unwinder.unwinding {
|
||||
rtabort!("unwinding again");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ impl Handle {
|
||||
pub fn new() -> Handle {
|
||||
use rt::local::Local;
|
||||
unsafe {
|
||||
let task = Local::unsafe_borrow::<Task>();
|
||||
let task: *mut Task = Local::unsafe_borrow();
|
||||
NewHandle(&mut (*task).storage)
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
|
||||
use rt::task::Task;
|
||||
|
||||
if in_green_task_context() {
|
||||
do Local::borrow::<Task, U> |task| {
|
||||
do Local::borrow |task: &mut Task| {
|
||||
match task.name {
|
||||
Some(ref name) => blk(Some(name.as_slice())),
|
||||
None => blk(None)
|
||||
@ -545,7 +545,7 @@ pub fn deschedule() {
|
||||
|
||||
// FIXME #6842: What does yield really mean in newsched?
|
||||
// FIXME(#7544): Optimize this, since we know we won't block.
|
||||
let sched = Local::take::<Scheduler>();
|
||||
let sched: ~Scheduler = Local::take();
|
||||
do sched.deschedule_running_task_and_then |sched, task| {
|
||||
sched.enqueue_blocked_task(task);
|
||||
}
|
||||
@ -556,7 +556,7 @@ pub fn failing() -> bool {
|
||||
|
||||
use rt::task::Task;
|
||||
|
||||
do Local::borrow::<Task, bool> |local| {
|
||||
do Local::borrow |local: &mut Task| {
|
||||
local.unwinder.unwinding
|
||||
}
|
||||
}
|
||||
@ -582,7 +582,7 @@ pub fn unkillable<U>(f: &fn() -> U) -> U {
|
||||
unsafe {
|
||||
if in_green_task_context() {
|
||||
// The inhibits/allows might fail and need to borrow the task.
|
||||
let t = Local::unsafe_borrow::<Task>();
|
||||
let t: *mut Task = Local::unsafe_borrow();
|
||||
do (|| {
|
||||
(*t).death.inhibit_kill((*t).unwinder.unwinding);
|
||||
f()
|
||||
@ -616,7 +616,7 @@ pub fn rekillable<U>(f: &fn() -> U) -> U {
|
||||
|
||||
unsafe {
|
||||
if in_green_task_context() {
|
||||
let t = Local::unsafe_borrow::<Task>();
|
||||
let t: *mut Task = Local::unsafe_borrow();
|
||||
do (|| {
|
||||
(*t).death.allow_kill((*t).unwinder.unwinding);
|
||||
f()
|
||||
@ -1032,7 +1032,7 @@ fn test_try_fail() {
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_sched_id() -> int {
|
||||
do Local::borrow::<::rt::sched::Scheduler, int> |sched| {
|
||||
do Local::borrow |sched: &mut ::rt::sched::Scheduler| {
|
||||
sched.sched_id() as int
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ impl RuntimeGlue {
|
||||
fn kill_task(mut handle: KillHandle) {
|
||||
do handle.kill().map_move |killed_task| {
|
||||
let killed_task = Cell::new(killed_task);
|
||||
do Local::borrow::<Scheduler, ()> |sched| {
|
||||
do Local::borrow |sched: &mut Scheduler| {
|
||||
sched.enqueue_task(killed_task.take());
|
||||
}
|
||||
};
|
||||
@ -460,7 +460,7 @@ impl RuntimeGlue {
|
||||
unsafe {
|
||||
// Can't use safe borrow, because the taskgroup destructor needs to
|
||||
// access the scheduler again to send kill signals to other tasks.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
let me: *mut Task = Local::unsafe_borrow();
|
||||
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
|
||||
}
|
||||
}
|
||||
@ -470,7 +470,7 @@ impl RuntimeGlue {
|
||||
unsafe {
|
||||
// Can't use safe borrow, because creating new hashmaps for the
|
||||
// tasksets requires an rng, which needs to borrow the sched.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
let me: *mut Task = Local::unsafe_borrow();
|
||||
blk(match (*me).taskgroup {
|
||||
None => {
|
||||
// First task in its (unlinked/unsupervised) taskgroup.
|
||||
@ -574,7 +574,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
|
||||
// If child data is 'None', the enlist is vacuously successful.
|
||||
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| {
|
||||
do Local::borrow |me: &mut Task| {
|
||||
let (child_tg, ancestors) = child_data.take();
|
||||
let mut ancestors = ancestors;
|
||||
let handle = me.death.kill_handle.get_ref();
|
||||
@ -608,7 +608,7 @@ pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
|
||||
} else {
|
||||
unsafe {
|
||||
// Creating a 1:1 task:thread ...
|
||||
let sched = Local::unsafe_borrow::<Scheduler>();
|
||||
let sched: *mut Scheduler = Local::unsafe_borrow();
|
||||
let sched_handle = (*sched).make_handle();
|
||||
|
||||
// Since this is a 1:1 scheduler we create a queue not in
|
||||
|
@ -343,7 +343,14 @@ impl<A:IterBytes> IterBytes for ~A {
|
||||
|
||||
// NB: raw-pointer IterBytes does _not_ dereference
|
||||
// to the target; it just gives you the pointer-bytes.
|
||||
impl<A> IterBytes for *const A {
|
||||
impl<A> IterBytes for *A {
|
||||
#[inline]
|
||||
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
||||
(*self as uint).iter_bytes(lsb0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> IterBytes for *mut A {
|
||||
#[inline]
|
||||
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
|
||||
(*self as uint).iter_bytes(lsb0, f)
|
||||
|
@ -176,7 +176,7 @@ macro_rules! tuple_impls {
|
||||
impl<$($T:Zero),+> Zero for ($($T,)+) {
|
||||
#[inline]
|
||||
fn zero() -> ($($T,)+) {
|
||||
($(Zero::zero::<$T>(),)+)
|
||||
($({ let x: $T = Zero::zero(); x},)+)
|
||||
}
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
|
@ -538,7 +538,8 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn option_empty() {
|
||||
assert!(AtomicOption::empty::<()>().is_empty(SeqCst));
|
||||
let mut option: AtomicOption<()> = AtomicOption::empty();
|
||||
assert!(option.is_empty(SeqCst));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -13,7 +13,7 @@
|
||||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use libc::{c_char, c_void, size_t, uintptr_t};
|
||||
use option::{Some, None};
|
||||
use option::{Option, None, Some};
|
||||
use sys;
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
@ -37,7 +37,8 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
|
||||
#[lang="malloc"]
|
||||
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
// XXX: Unsafe borrow for speed. Lame.
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task {
|
||||
Some(task) => {
|
||||
(*task).heap.alloc(td as *c_void, size as uint) as *c_char
|
||||
}
|
||||
|
@ -279,7 +279,8 @@ pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
|
||||
use rt::task::{Task, GreenTask, SchedTask};
|
||||
use rt::local::Local;
|
||||
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
let task_opt: Option<*mut Task> = Local::try_unsafe_borrow();
|
||||
match task_opt {
|
||||
Some(t) => {
|
||||
match (*t).task_type {
|
||||
GreenTask(_) => {
|
||||
|
@ -54,8 +54,10 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
let t: *mut T = &mut tmp;
|
||||
|
||||
// Perform the swap, `&mut` pointers never alias
|
||||
ptr::copy_nonoverlapping_memory(t, x, 1);
|
||||
ptr::copy_nonoverlapping_memory(x, y, 1);
|
||||
let x_raw: *mut T = x;
|
||||
let y_raw: *mut T = y;
|
||||
ptr::copy_nonoverlapping_memory(t, x_raw, 1);
|
||||
ptr::copy_nonoverlapping_memory(x, y_raw, 1);
|
||||
ptr::copy_nonoverlapping_memory(y, t, 1);
|
||||
|
||||
// y and t now point to the same thing, but we need to completely forget `tmp`
|
||||
|
@ -1122,14 +1122,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||
* foreign interop.
|
||||
*/
|
||||
#[inline]
|
||||
fn as_imm_buf<U>(&self,
|
||||
/* NB---this CANNOT be const, see below */
|
||||
f: &fn(*T, uint) -> U) -> U {
|
||||
// NB---Do not change the type of s to `&const [T]`. This is
|
||||
// unsound. The reason is that we are going to create immutable pointers
|
||||
// into `s` and pass them to `f()`, but in fact they are potentially
|
||||
// pointing at *mutable memory*. Use `as_mut_buf` instead!
|
||||
|
||||
fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U {
|
||||
let s = self.repr();
|
||||
f(s.data, s.len / sys::nonzero_size_of::<T>())
|
||||
}
|
||||
|
@ -109,12 +109,21 @@ pub struct Path {
|
||||
/// A `::foo` path, is relative to the crate root rather than current
|
||||
/// module (like paths in an import).
|
||||
global: bool,
|
||||
/// The segments in the path (the things separated by ::)
|
||||
idents: ~[ident],
|
||||
/// "Region parameter", currently only one lifetime is allowed in a path.
|
||||
rp: Option<Lifetime>,
|
||||
/// These are the type parameters, ie, the `a, b` in `foo::bar::<a, b>`
|
||||
types: ~[Ty],
|
||||
/// The segments in the path: the things separated by `::`.
|
||||
segments: ~[PathSegment],
|
||||
}
|
||||
|
||||
/// A segment of a path: an identifier, an optional lifetime, and a set of
|
||||
/// types.
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub struct PathSegment {
|
||||
/// The identifier portion of this path segment.
|
||||
identifier: ident,
|
||||
/// The lifetime parameter for this path segment. Currently only one
|
||||
/// lifetime parameter is allowed.
|
||||
lifetime: Option<Lifetime>,
|
||||
/// The type parameters for this path segment, if present.
|
||||
types: OptVec<Ty>,
|
||||
}
|
||||
|
||||
pub type CrateNum = int;
|
||||
@ -165,12 +174,16 @@ impl Generics {
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum MethodProvenance {
|
||||
FromTrait(def_id),
|
||||
FromImpl(def_id),
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum def {
|
||||
def_fn(def_id, purity),
|
||||
def_static_method(/* method */ def_id,
|
||||
/* trait */ Option<def_id>,
|
||||
purity),
|
||||
def_static_method(/* method */ def_id, MethodProvenance, purity),
|
||||
def_self(NodeId),
|
||||
def_self_ty(/* trait id */ NodeId),
|
||||
def_mod(def_id),
|
||||
@ -298,7 +311,10 @@ pub enum pat_ {
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum mutability { m_mutbl, m_imm, m_const, }
|
||||
pub enum mutability {
|
||||
m_mutbl,
|
||||
m_imm,
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum Sigil {
|
||||
@ -704,7 +720,7 @@ impl ToStr for float_ty {
|
||||
}
|
||||
|
||||
// NB Eq method appears below.
|
||||
#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)]
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub struct Ty {
|
||||
id: NodeId,
|
||||
node: ty_,
|
||||
|
@ -28,8 +28,8 @@ pub fn path_name_i(idents: &[ident]) -> ~str {
|
||||
idents.map(|i| token::interner_get(i.name)).connect("::")
|
||||
}
|
||||
|
||||
pub fn path_to_ident(p: &Path) -> ident {
|
||||
*p.idents.last()
|
||||
pub fn path_to_ident(path: &Path) -> ident {
|
||||
path.segments.last().identifier
|
||||
}
|
||||
|
||||
pub fn local_def(id: NodeId) -> def_id {
|
||||
@ -217,12 +217,18 @@ pub fn default_block(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ident_to_path(s: span, i: ident) -> Path {
|
||||
ast::Path { span: s,
|
||||
global: false,
|
||||
idents: ~[i],
|
||||
rp: None,
|
||||
types: ~[] }
|
||||
pub fn ident_to_path(s: span, identifier: ident) -> Path {
|
||||
ast::Path {
|
||||
span: s,
|
||||
global: false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ident_to_pat(id: NodeId, s: span, i: ident) -> @pat {
|
||||
@ -420,7 +426,7 @@ impl IdVisitor {
|
||||
impl Visitor<()> for IdVisitor {
|
||||
fn visit_mod(&mut self,
|
||||
module: &_mod,
|
||||
_span: span,
|
||||
_: span,
|
||||
node_id: NodeId,
|
||||
env: ()) {
|
||||
(self.visit_callback)(node_id);
|
||||
|
@ -329,20 +329,6 @@ pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> @str {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expr_to_ident(cx: @ExtCtxt,
|
||||
expr: @ast::expr,
|
||||
err_msg: &str) -> ast::ident {
|
||||
match expr.node {
|
||||
ast::expr_path(ref p) => {
|
||||
if p.types.len() > 0u || p.idents.len() != 1u {
|
||||
cx.span_fatal(expr.span, err_msg);
|
||||
}
|
||||
return p.idents[0];
|
||||
}
|
||||
_ => cx.span_fatal(expr.span, err_msg)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree],
|
||||
name: &str) {
|
||||
if tts.len() != 0 {
|
||||
@ -353,15 +339,15 @@ pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree],
|
||||
pub fn get_single_str_from_tts(cx: @ExtCtxt,
|
||||
sp: span,
|
||||
tts: &[ast::token_tree],
|
||||
name: &str) -> @str {
|
||||
name: &str)
|
||||
-> @str {
|
||||
if tts.len() != 1 {
|
||||
cx.span_fatal(sp, fmt!("%s takes 1 argument.", name));
|
||||
}
|
||||
|
||||
match tts[0] {
|
||||
ast::tt_tok(_, token::LIT_STR(ident)) => cx.str_of(ident),
|
||||
_ =>
|
||||
cx.span_fatal(sp, fmt!("%s requires a string.", name))
|
||||
_ => cx.span_fatal(sp, fmt!("%s requires a string.", name)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,13 @@ pub trait AstBuilder {
|
||||
// statements
|
||||
fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt;
|
||||
fn stmt_let(&self, sp: span, mutbl: bool, ident: ast::ident, ex: @ast::expr) -> @ast::stmt;
|
||||
fn stmt_let_typed(&self,
|
||||
sp: span,
|
||||
mutbl: bool,
|
||||
ident: ast::ident,
|
||||
typ: ast::Ty,
|
||||
ex: @ast::expr)
|
||||
-> @ast::stmt;
|
||||
|
||||
// blocks
|
||||
fn block(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@ast::expr>) -> ast::Block;
|
||||
@ -233,18 +240,31 @@ impl AstBuilder for @ExtCtxt {
|
||||
fn path_global(&self, span: span, strs: ~[ast::ident]) -> ast::Path {
|
||||
self.path_all(span, true, strs, None, ~[])
|
||||
}
|
||||
fn path_all(&self, sp: span,
|
||||
fn path_all(&self,
|
||||
sp: span,
|
||||
global: bool,
|
||||
idents: ~[ast::ident],
|
||||
mut idents: ~[ast::ident],
|
||||
rp: Option<ast::Lifetime>,
|
||||
types: ~[ast::Ty])
|
||||
-> ast::Path {
|
||||
-> ast::Path {
|
||||
let last_identifier = idents.pop();
|
||||
let mut segments: ~[ast::PathSegment] = idents.move_iter()
|
||||
.map(|ident| {
|
||||
ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
}).collect();
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: last_identifier,
|
||||
lifetime: rp,
|
||||
types: opt_vec::from(types),
|
||||
});
|
||||
ast::Path {
|
||||
span: sp,
|
||||
global: global,
|
||||
idents: idents,
|
||||
rp: rp,
|
||||
types: types
|
||||
segments: segments,
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,6 +407,26 @@ impl AstBuilder for @ExtCtxt {
|
||||
@respan(sp, ast::stmt_decl(@decl, self.next_id()))
|
||||
}
|
||||
|
||||
fn stmt_let_typed(&self,
|
||||
sp: span,
|
||||
mutbl: bool,
|
||||
ident: ast::ident,
|
||||
typ: ast::Ty,
|
||||
ex: @ast::expr)
|
||||
-> @ast::stmt {
|
||||
let pat = self.pat_ident(sp, ident);
|
||||
let local = @ast::Local {
|
||||
is_mutbl: mutbl,
|
||||
ty: typ,
|
||||
pat: pat,
|
||||
init: Some(ex),
|
||||
id: self.next_id(),
|
||||
span: sp,
|
||||
};
|
||||
let decl = respan(sp, ast::decl_local(local));
|
||||
@respan(sp, ast::stmt_decl(@decl, self.next_id()))
|
||||
}
|
||||
|
||||
fn block(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@expr>) -> ast::Block {
|
||||
self.block_all(span, ~[], stmts, expr)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use ast;
|
||||
use codemap::span;
|
||||
use ext::base::*;
|
||||
use ext::base;
|
||||
use opt_vec;
|
||||
use parse::token;
|
||||
use parse::token::{str_to_ident};
|
||||
|
||||
@ -39,9 +40,13 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
|
||||
ast::Path {
|
||||
span: sp,
|
||||
global: false,
|
||||
idents: ~[res],
|
||||
rp: None,
|
||||
types: ~[],
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: res,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
span: sp,
|
||||
|
@ -76,24 +76,33 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
|
||||
|
||||
let variant_count = cx.expr_uint(span, variants.len());
|
||||
|
||||
// need to specify the uint-ness of the random number
|
||||
let uint_ty = cx.ty_ident(span, cx.ident_of("uint"));
|
||||
let r_ty = cx.ty_ident(span, cx.ident_of("R"));
|
||||
let rand_name = cx.path_all(span,
|
||||
true,
|
||||
rand_ident.clone(),
|
||||
None,
|
||||
~[ uint_ty, r_ty ]);
|
||||
~[]);
|
||||
let rand_name = cx.expr_path(rand_name);
|
||||
|
||||
// ::std::rand::Rand::rand::<uint>(rng)
|
||||
// ::std::rand::Rand::rand(rng)
|
||||
let rv_call = cx.expr_call(span,
|
||||
rand_name,
|
||||
~[ rng[0].duplicate(cx) ]);
|
||||
|
||||
// need to specify the uint-ness of the random number
|
||||
let uint_ty = cx.ty_ident(span, cx.ident_of("uint"));
|
||||
let value_ident = cx.ident_of("__value");
|
||||
let let_statement = cx.stmt_let_typed(span,
|
||||
false,
|
||||
value_ident,
|
||||
uint_ty,
|
||||
rv_call);
|
||||
|
||||
// rand() % variants.len()
|
||||
let rand_variant = cx.expr_binary(span, ast::rem,
|
||||
rv_call, variant_count);
|
||||
let value_ref = cx.expr_ident(span, value_ident);
|
||||
let rand_variant = cx.expr_binary(span,
|
||||
ast::rem,
|
||||
value_ref,
|
||||
variant_count);
|
||||
|
||||
let mut arms = do variants.iter().enumerate().map |(i, id_sum)| {
|
||||
let i_expr = cx.expr_uint(span, i);
|
||||
@ -111,7 +120,10 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
|
||||
// _ => {} at the end. Should never occur
|
||||
arms.push(cx.arm_unreachable(span));
|
||||
|
||||
cx.expr_match(span, rand_variant, arms)
|
||||
let match_expr = cx.expr_match(span, rand_variant, arms);
|
||||
|
||||
let block = cx.block(span, ~[ let_statement ], Some(match_expr));
|
||||
cx.expr_block(block)
|
||||
}
|
||||
_ => cx.bug("Non-static method in `deriving(Rand)`")
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ use codemap;
|
||||
use codemap::{span, spanned, ExpnInfo, NameAndSpan};
|
||||
use ext::base::*;
|
||||
use fold::*;
|
||||
use opt_vec;
|
||||
use parse;
|
||||
use parse::{parse_item_from_source_str};
|
||||
use parse::token;
|
||||
@ -42,13 +43,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
||||
match (*mac).node {
|
||||
// Token-tree macros:
|
||||
mac_invoc_tt(ref pth, ref tts) => {
|
||||
if (pth.idents.len() > 1u) {
|
||||
if (pth.segments.len() > 1u) {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("expected macro name without module \
|
||||
separators"));
|
||||
}
|
||||
let extname = &pth.idents[0];
|
||||
let extname = &pth.segments[0].identifier;
|
||||
let extnamestr = ident_to_str(extname);
|
||||
// leaving explicit deref here to highlight unbox op:
|
||||
match (*extsbox).find(&extname.name) {
|
||||
@ -143,9 +144,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
|
||||
ast::Path {
|
||||
span: span,
|
||||
global: false,
|
||||
idents: ~[ident],
|
||||
rp: None,
|
||||
types: ~[]
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: ident,
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +373,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
|
||||
_ => cx.span_bug(it.span, "invalid item macro invocation")
|
||||
};
|
||||
|
||||
let extname = &pth.idents[0];
|
||||
let extname = &pth.segments[0].identifier;
|
||||
let extnamestr = ident_to_str(extname);
|
||||
let expanded = match (*extsbox).find(&extname.name) {
|
||||
None => cx.span_fatal(pth.span,
|
||||
@ -459,13 +464,13 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
|
||||
}
|
||||
_ => return orig(s, sp, fld)
|
||||
};
|
||||
if (pth.idents.len() > 1u) {
|
||||
if (pth.segments.len() > 1u) {
|
||||
cx.span_fatal(
|
||||
pth.span,
|
||||
fmt!("expected macro name without module \
|
||||
separators"));
|
||||
}
|
||||
let extname = &pth.idents[0];
|
||||
let extname = &pth.segments[0].identifier;
|
||||
let extnamestr = ident_to_str(extname);
|
||||
let (fully_expanded, sp) = match (*extsbox).find(&extname.name) {
|
||||
None =>
|
||||
@ -534,10 +539,14 @@ impl Visitor<()> for NewNameFinderContext {
|
||||
// a path of length one:
|
||||
&ast::Path {
|
||||
global: false,
|
||||
idents: [id],
|
||||
span: _,
|
||||
rp: _,
|
||||
types: _
|
||||
segments: [
|
||||
ast::PathSegment {
|
||||
identifier: id,
|
||||
lifetime: _,
|
||||
types: _
|
||||
}
|
||||
]
|
||||
} => self.ident_accumulator.push(id),
|
||||
// I believe these must be enums...
|
||||
_ => ()
|
||||
|
@ -16,8 +16,8 @@ use codemap::{BytePos, mk_sp};
|
||||
use codemap;
|
||||
use parse::lexer::*; //resolve bug?
|
||||
use parse::ParseSess;
|
||||
use parse::parser::Parser;
|
||||
use parse::attr::parser_attr;
|
||||
use parse::parser::{LifetimeAndTypesWithoutColons, Parser};
|
||||
use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str};
|
||||
use parse::token;
|
||||
|
||||
@ -430,7 +430,9 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
|
||||
_ => p.fatal(~"expected ident, found "
|
||||
+ token::to_str(get_ident_interner(), p.token))
|
||||
},
|
||||
"path" => token::nt_path(~p.parse_path_with_tps(false)),
|
||||
"path" => {
|
||||
token::nt_path(~p.parse_path(LifetimeAndTypesWithoutColons).path)
|
||||
}
|
||||
"attr" => token::nt_attr(@p.parse_attribute(false)),
|
||||
"tt" => {
|
||||
*p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
|
||||
|
@ -765,9 +765,11 @@ fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path {
|
||||
ast::Path {
|
||||
span: fld.new_span(p.span),
|
||||
global: p.global,
|
||||
idents: p.idents.map(|x| fld.fold_ident(*x)),
|
||||
rp: p.rp,
|
||||
types: p.types.map(|x| fld.fold_ty(x)),
|
||||
segments: p.segments.map(|segment| ast::PathSegment {
|
||||
identifier: fld.fold_ident(segment.identifier),
|
||||
lifetime: segment.lifetime,
|
||||
types: segment.types.map(|typ| fld.fold_ty(typ)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,11 @@ pub fn visit_ty<E:Clone>(t: &Ty, (e, v): (E, vt<E>)) {
|
||||
}
|
||||
|
||||
pub fn visit_path<E:Clone>(p: &Path, (e, v): (E, vt<E>)) {
|
||||
for tp in p.types.iter() { (v.visit_ty)(tp, (e.clone(), v)); }
|
||||
for segment in p.segments.iter() {
|
||||
for typ in segment.types.iter() {
|
||||
(v.visit_ty)(typ, (e.clone(), v))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_pat<E:Clone>(p: &pat, (e, v): (E, vt<E>)) {
|
||||
|
@ -361,27 +361,47 @@ mod test {
|
||||
span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
|
||||
}
|
||||
|
||||
#[test] fn path_exprs_1 () {
|
||||
#[test] fn path_exprs_1() {
|
||||
assert_eq!(string_to_expr(@"a"),
|
||||
@ast::expr{id:1,
|
||||
node:ast::expr_path(ast::Path {span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[str_to_ident("a")],
|
||||
rp:None,
|
||||
types:~[]}),
|
||||
span:sp(0,1)})
|
||||
@ast::expr{
|
||||
id: 1,
|
||||
node: ast::expr_path(ast::Path {
|
||||
span: sp(0, 1),
|
||||
global: false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}),
|
||||
span: sp(0, 1)
|
||||
})
|
||||
}
|
||||
|
||||
#[test] fn path_exprs_2 () {
|
||||
assert_eq!(string_to_expr(@"::a::b"),
|
||||
@ast::expr{id:1,
|
||||
node:ast::expr_path(
|
||||
ast::Path {span:sp(0,6),
|
||||
global:true,
|
||||
idents:strs_to_idents(~["a","b"]),
|
||||
rp:None,
|
||||
types:~[]}),
|
||||
span:sp(0,6)})
|
||||
@ast::expr {
|
||||
id:1,
|
||||
node: ast::expr_path(ast::Path {
|
||||
span: sp(0, 6),
|
||||
global: true,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("a"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
]
|
||||
}),
|
||||
span: sp(0, 6)
|
||||
})
|
||||
}
|
||||
|
||||
#[should_fail]
|
||||
@ -420,32 +440,43 @@ mod test {
|
||||
|
||||
#[test] fn ret_expr() {
|
||||
assert_eq!(string_to_expr(@"return d"),
|
||||
@ast::expr{id:2,
|
||||
node:ast::expr_ret(
|
||||
Some(@ast::expr{id:1,
|
||||
node:ast::expr_path(
|
||||
ast::Path{span:sp(7,8),
|
||||
global:false,
|
||||
idents:~[str_to_ident("d")],
|
||||
rp:None,
|
||||
types:~[]
|
||||
}),
|
||||
span:sp(7,8)})),
|
||||
span:sp(0,8)})
|
||||
@ast::expr{
|
||||
id:2,
|
||||
node:ast::expr_ret(Some(@ast::expr{
|
||||
id:1,
|
||||
node:ast::expr_path(ast::Path{
|
||||
span: sp(7, 8),
|
||||
global: false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("d"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}),
|
||||
span:sp(7,8)
|
||||
})),
|
||||
span:sp(0,8)
|
||||
})
|
||||
}
|
||||
|
||||
#[test] fn parse_stmt_1 () {
|
||||
assert_eq!(string_to_stmt(@"b;"),
|
||||
@spanned{
|
||||
node: ast::stmt_expr(@ast::expr{
|
||||
node: ast::stmt_expr(@ast::expr {
|
||||
id: 1,
|
||||
node: ast::expr_path(
|
||||
ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[str_to_ident("b")],
|
||||
rp:None,
|
||||
types: ~[]}),
|
||||
node: ast::expr_path(ast::Path {
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}),
|
||||
span: sp(0,1)},
|
||||
2), // fixme
|
||||
span: sp(0,1)})
|
||||
@ -460,49 +491,24 @@ mod test {
|
||||
let parser = string_to_parser(@"b");
|
||||
assert_eq!(parser.parse_pat(),
|
||||
@ast::pat{id:1, // fixme
|
||||
node: ast::pat_ident(ast::bind_infer,
|
||||
ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[str_to_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
),
|
||||
node: ast::pat_ident(
|
||||
ast::bind_infer,
|
||||
ast::Path {
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier: str_to_ident("b"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
},
|
||||
None /* no idea */),
|
||||
span: sp(0,1)});
|
||||
parser_done(parser);
|
||||
}
|
||||
|
||||
#[test] fn parse_arg () {
|
||||
let parser = string_to_parser(@"b : int");
|
||||
assert_eq!(parser.parse_arg_general(true),
|
||||
ast::arg{
|
||||
is_mutbl: false,
|
||||
ty: ast::Ty{id:3, // fixme
|
||||
node: ast::ty_path(ast::Path{
|
||||
span:sp(4,4), // this is bizarre...
|
||||
// check this in the original parser?
|
||||
global:false,
|
||||
idents:~[str_to_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None, 2),
|
||||
span:sp(4,7)},
|
||||
pat: @ast::pat{id:1,
|
||||
node: ast::pat_ident(ast::bind_infer,
|
||||
ast::Path{
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
idents:~[str_to_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
),
|
||||
span: sp(0,1)},
|
||||
id: 4 // fixme
|
||||
})
|
||||
}
|
||||
|
||||
// check the contents of the tt manually:
|
||||
#[test] fn parse_fundecl () {
|
||||
// this test depends on the intern order of "fn" and "int", and on the
|
||||
@ -519,23 +525,37 @@ mod test {
|
||||
node: ast::ty_path(ast::Path{
|
||||
span:sp(10,13),
|
||||
global:false,
|
||||
idents:~[str_to_ident("int")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None, 2),
|
||||
span:sp(10,13)},
|
||||
pat: @ast::pat{id:1, // fixme
|
||||
node: ast::pat_ident(
|
||||
ast::bind_infer,
|
||||
ast::Path{
|
||||
span:sp(6,7),
|
||||
global:false,
|
||||
idents:~[str_to_ident("b")],
|
||||
rp: None,
|
||||
types: ~[]},
|
||||
None // no idea
|
||||
),
|
||||
span: sp(6,7)},
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident("int"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
}, None, 2),
|
||||
span:sp(10,13)
|
||||
},
|
||||
pat: @ast::pat {
|
||||
id:1, // fixme
|
||||
node: ast::pat_ident(
|
||||
ast::bind_infer,
|
||||
ast::Path {
|
||||
span:sp(6,7),
|
||||
global:false,
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident("b"),
|
||||
lifetime: None,
|
||||
types: opt_vec::Empty,
|
||||
}
|
||||
],
|
||||
},
|
||||
None // no idea
|
||||
),
|
||||
span: sp(6,7)
|
||||
},
|
||||
id: 4 // fixme
|
||||
}],
|
||||
output: ast::Ty{id:5, // fixme
|
||||
@ -558,9 +578,18 @@ mod test {
|
||||
ast::Path{
|
||||
span:sp(17,18),
|
||||
global:false,
|
||||
idents:~[str_to_ident("b")],
|
||||
rp:None,
|
||||
types: ~[]}),
|
||||
segments: ~[
|
||||
ast::PathSegment {
|
||||
identifier:
|
||||
str_to_ident(
|
||||
"b"),
|
||||
lifetime:
|
||||
None,
|
||||
types:
|
||||
opt_vec::Empty
|
||||
}
|
||||
],
|
||||
}),
|
||||
span: sp(17,18)},
|
||||
7), // fixme
|
||||
span: sp(17,18)}],
|
||||
|
@ -53,7 +53,6 @@ pub enum ObsoleteSyntax {
|
||||
ObsoleteMode,
|
||||
ObsoleteImplicitSelf,
|
||||
ObsoleteLifetimeNotation,
|
||||
ObsoleteConstManagedPointer,
|
||||
ObsoletePurity,
|
||||
ObsoleteStaticMethod,
|
||||
ObsoleteConstItem,
|
||||
@ -65,6 +64,7 @@ pub enum ObsoleteSyntax {
|
||||
ObsoleteUnsafeExternFn,
|
||||
ObsoletePrivVisibility,
|
||||
ObsoleteTraitFuncVisibility,
|
||||
ObsoleteConstPointer,
|
||||
}
|
||||
|
||||
impl to_bytes::IterBytes for ObsoleteSyntax {
|
||||
@ -201,10 +201,6 @@ impl ParserObsoleteMethods for Parser {
|
||||
"instead of `&foo/bar`, write `&'foo bar`; instead of \
|
||||
`bar/&foo`, write `&bar<'foo>"
|
||||
),
|
||||
ObsoleteConstManagedPointer => (
|
||||
"const `@` pointer",
|
||||
"instead of `@const Foo`, write `@Foo`"
|
||||
),
|
||||
ObsoletePurity => (
|
||||
"pure function",
|
||||
"remove `pure`"
|
||||
@ -255,6 +251,11 @@ impl ParserObsoleteMethods for Parser {
|
||||
"visibility not necessary",
|
||||
"trait functions inherit the visibility of the trait itself"
|
||||
),
|
||||
ObsoleteConstPointer => (
|
||||
"const pointer",
|
||||
"instead of `&const Foo` or `@const Foo`, write `&Foo` or \
|
||||
`@Foo`"
|
||||
),
|
||||
};
|
||||
|
||||
self.report(sp, kind, kind_str, desc);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user